diff --git a/.gitignore b/.gitignore index 2254f27..a48636c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ node_modules /lib .vercel +coverage \ No newline at end of file diff --git a/README.md b/README.md index ff91af2..2f9e9e1 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,29 @@ Described below is the pattern used for accessing `theme` context to create your ``` +## Actions + +### use:theme + +```svelte + + +
+

Hello, World!

+
+ + +``` + ## Contributing Refer to the [contributing guidelines](CONTRIBUTING.md). diff --git a/components/ThemeWrapper.svelte b/components/ThemeWrapper.svelte index a687b97..e6db7c3 100644 --- a/components/ThemeWrapper.svelte +++ b/components/ThemeWrapper.svelte @@ -15,7 +15,7 @@ import { onMount, afterUpdate, setContext } from 'svelte' import { presets } from './presets' import toggle from '../support/toggle' - import { createCSS } from '../support/css' + import { createCSSTemplate } from '../support/css' import { currentThemeName, currentThemeObject, @@ -63,12 +63,13 @@ themesStore.set(themes) const [fallback] = Object.keys(themes) - if (!Object.keys(themes).includes($currentThemeName)) + if (!Object.keys(themes).includes($currentThemeName)) { currentThemeName.set(fallback) + } $: currentThemeObject.set(themes[$currentThemeName]) // create CSS - const style = createCSS(prefix, base, themes) + const style = createCSSTemplate(prefix, base, themes) setContext(CONTEXT_KEY, { current: currentThemeName, diff --git a/components/index.js b/components/index.js index 52f6d79..71b9101 100644 --- a/components/index.js +++ b/components/index.js @@ -1,2 +1,3 @@ export { default as ThemeWrapper } from './ThemeWrapper.svelte' export { default as ThemeToggle } from './ThemeToggle.svelte' +export { presets } from './presets.js' diff --git a/components/use.js b/components/use.js new file mode 100644 index 0000000..765e850 --- /dev/null +++ b/components/use.js @@ -0,0 +1,31 @@ +import { createCSSVariableCollection } from '../support/css' + +/** + * + * @param {HTMLElement} node + * @param {Object.} theme + * @returns + */ +export async function theme(node, theme) { + /** + * + * @param {string} name + * @param {string} value + * @returns {void} + */ + function setProperty(name, value) { + if (!node.style && node.document?.documentElement) { + node.document.documentElement.style.setProperty(name, value) + return + } + node.style.setProperty(name, value) + return + } + + const variables = createCSSVariableCollection(theme) + for (let [name, value] of variables) { + setProperty(name, value) + } + + return {} +} diff --git a/docs/src/App.svelte b/docs/src/App.svelte index 38e9a7d..9e63ca3 100644 --- a/docs/src/App.svelte +++ b/docs/src/App.svelte @@ -33,13 +33,13 @@ - + - + diff --git a/package.json b/package.json index a98157a..b09a6be 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "svelte-themer", "type": "module", - "version": "0.5.2", + "version": "0.5.3-next.1", "homepage": "https://svelte-themer.vercel.app", "license": "MIT", "repository": { @@ -16,7 +16,8 @@ }, "./package.json": "./package.json", "./components": "./components/index.js", - "./store": "./support/store.js" + "./store": "./support/store.js", + "./use": "./components/use.js" }, "files": [ "components", diff --git a/support/css.js b/support/css.js index 607cad3..bc4ce10 100644 --- a/support/css.js +++ b/support/css.js @@ -53,14 +53,30 @@ export function createCSSVariableOverride({ return `${initialVariableName}: var(${themeVariableName});` } +/** + * + * @param {object} config + * @param {Object} options + * @param {string} options.prefix + * @returns {[CSSVariableName, ]} + */ +export function createCSSVariableCollection(config, { prefix } = {}) { + const variablePrefix = prefix ? `--${prefix}` : '-' + const processedConfig = processConfig(config) + const variables = Object.entries(processedConfig).map(([prop, value]) => { + return [createCSSVariableName({ variablePrefix, prop }), value] + }) + return variables +} + /** * Create CSS template - * @name setCSS + * @name createCSSTemplate * @param {string} prefix - CSS variable prefix * @param {Object[]} themes - themes array * @returns {string} CSS template */ -export function createCSS(prefix, base = {}) { +export function createCSSTemplate(prefix, base = {}) { const variablePrefix = prefix ? `--${prefix}` : '-' const themes = get(themesStore) @@ -125,7 +141,7 @@ export function createCSS(prefix, base = {}) { :root { ${rootCSSVariables .map(vars => createCSSVariableStatement(...vars)) - .join('\n\t')} + .join('')} } ${themeCSSContent.join('')} diff --git a/test/support.js b/test/support.js new file mode 100644 index 0000000..310a611 --- /dev/null +++ b/test/support.js @@ -0,0 +1,11 @@ +export function render(Component, props = {}) { + const host = document.createElement('div') + host.setAttribute('id', 'host') + document.body.appendChild(host) + const instance = new Component({ target: host, props }) + return instance +} + +export function getByTestId(id) { + return document.querySelector(`[data-testid="${id}"]`) +} diff --git a/test/use.test.js b/test/use.test.js new file mode 100644 index 0000000..8d7aabe --- /dev/null +++ b/test/use.test.js @@ -0,0 +1,24 @@ +import { describe, expect, it } from 'vitest' +import UseComponent from './use.test.svelte' +import { render as _render, getByTestId } from './support.js' + +function render(props = {}) { + return _render(UseComponent, props) +} + +describe('Theme Action', () => { + it('should render', () => { + const instance = render() + expect(instance).toBeTruthy() + }) + + it('should create inline styles', () => { + const myTheme = { + text: 'red', + } + const instance = render({ myTheme }) + const container = getByTestId('container') + expect(container.style).toBeTruthy() + expect(container.style.getPropertyValue('--text')).toBe('red') + }) +}) diff --git a/test/use.test.svelte b/test/use.test.svelte new file mode 100644 index 0000000..6bec619 --- /dev/null +++ b/test/use.test.svelte @@ -0,0 +1,16 @@ + + +
+

Hello, World!

+
+ + diff --git a/types/index.d.ts b/types/index.d.ts index 88baaab..a413acb 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,2 +1,3 @@ export { default as ThemeWrapper } from "./ThemeWrapper.svelte"; export { default as ThemeToggle } from "./ThemeToggle.svelte"; +export { default as presets } from "./presets.js";