From 6273826b4141380d7cd4eb40442ce87040fcfabb Mon Sep 17 00:00:00 2001 From: Mert Sincan Date: Tue, 14 May 2024 09:35:40 +0100 Subject: [PATCH] Theming API: Refactor on methods --- components/lib/base/style/BaseStyle.js | 16 +++---- .../lib/basecomponent/BaseComponent.vue | 23 +++++---- components/lib/basedirective/BaseDirective.js | 17 ++++--- components/lib/themes/config/index.js | 20 +++----- components/lib/themes/helpers/toVariables.js | 36 ++++++++------ components/lib/themes/utils/themeUtils.js | 48 ++++++++++++++----- modules/nuxt-primevue/module.js | 7 ++- modules/nuxt-primevue/register.js | 18 +------ 8 files changed, 100 insertions(+), 85 deletions(-) diff --git a/components/lib/base/style/BaseStyle.js b/components/lib/base/style/BaseStyle.js index 590979d73..1bc77df75 100644 --- a/components/lib/base/style/BaseStyle.js +++ b/components/lib/base/style/BaseStyle.js @@ -168,17 +168,17 @@ export default { loadTheme(options = {}) { return this.load(this.theme, options, (computedStyle) => Theme.transformCSS(options.name || this.name, computedStyle)); }, - getCommonThemeCSS(params) { - return Theme.getCommonCSS(this.name, params); + getCommonTheme(params) { + return Theme.getCommon(this.name, params); }, - getComponentThemeCSS(params) { - return Theme.getComponentCSS(this.name, params); + getComponentTheme(params) { + return Theme.getComponent(this.name, params); }, - getDirectiveThemeCSS(params) { - return Theme.getDirectiveCSS(this.name, params); + getDirectiveTheme(params) { + return Theme.getDirective(this.name, params); }, - getPresetThemeCSS(preset, selector, params) { - return Theme.getPresetCSS(this.name, preset, selector, params); + getPresetTheme(preset, selector, params) { + return Theme.getCustomPreset(this.name, preset, selector, params); }, getLayerOrderThemeCSS() { return Theme.getLayerOrderCSS(this.name); diff --git a/components/lib/basecomponent/BaseComponent.vue b/components/lib/basecomponent/BaseComponent.vue index a31fedd9c..556400d8f 100644 --- a/components/lib/basecomponent/BaseComponent.vue +++ b/components/lib/basecomponent/BaseComponent.vue @@ -54,6 +54,7 @@ export default { } }, scopedStyleEl: undefined, + rootEl: undefined, beforeCreate() { const _usept = this.pt?.['_usept']; const originalValue = _usept ? this.pt?.originalValue?.[this.$.type.name] : undefined; @@ -76,9 +77,13 @@ export default { }, mounted() { // @todo - improve performance - const rootElement = DomHandler.findSingle(this.$el, `[data-pc-name="${ObjectUtils.toFlatCase(this.$.type.name)}"]`); + this.rootEl = DomHandler.findSingle(this.$el, `[data-pc-name="${ObjectUtils.toFlatCase(this.$.type.name)}"]`); + + if (this.rootEl) { + this.rootEl.setAttribute(this.$attrSelector, ''); + this.rootEl.$pc = { name: this.$.type.name, ...this.$params }; + } - rootElement?.setAttribute(this.$attrSelector, ''); this._hook('onMounted'); }, beforeUpdate() { @@ -151,10 +156,10 @@ export default { // common if (!Theme.isStyleNameLoaded('common')) { - const { primitive, semantic } = this.$style?.getCommonThemeCSS?.() || {}; + const { primitive, semantic } = this.$style?.getCommonTheme?.() || {}; - BaseStyle.load(primitive, { name: 'primitive-variables', ...this.$styleOptions }); - BaseStyle.load(semantic, { name: 'semantic-variables', ...this.$styleOptions }); + BaseStyle.load(primitive?.css, { name: 'primitive-variables', ...this.$styleOptions }); + BaseStyle.load(semantic?.css, { name: 'semantic-variables', ...this.$styleOptions }); BaseStyle.loadTheme({ name: 'global-style', ...this.$styleOptions }); Theme.setLoadedStyleName('common'); @@ -162,9 +167,9 @@ export default { // component if (!Theme.isStyleNameLoaded(this.$style?.name) && this.$style?.name) { - const { variables } = this.$style?.getComponentThemeCSS?.() || {}; + const { css } = this.$style?.getComponentTheme?.() || {}; - this.$style?.load(variables, { name: `${this.$style.name}-variables`, ...this.$styleOptions }); + this.$style?.load(css, { name: `${this.$style.name}-variables`, ...this.$styleOptions }); this.$style?.loadTheme({ name: `${this.$style.name}-style`, ...this.$styleOptions }); Theme.setLoadedStyleName(this.$style.name); @@ -180,8 +185,8 @@ export default { } }, _loadScopedThemeStyles(preset) { - const { variables } = this.$style?.getPresetThemeCSS?.(preset, `[${this.$attrSelector}]`) || {}; - const scopedStyle = this.$style?.load(variables, { name: `${this.$attrSelector}-${this.$style.name}`, ...this.$styleOptions }); + const { css } = this.$style?.getPresetTheme?.(preset, `[${this.$attrSelector}]`) || {}; + const scopedStyle = this.$style?.load(css, { name: `${this.$attrSelector}-${this.$style.name}`, ...this.$styleOptions }); this.scopedStyleEl = scopedStyle.el; }, diff --git a/components/lib/basedirective/BaseDirective.js b/components/lib/basedirective/BaseDirective.js index f80f07885..4c7af6257 100644 --- a/components/lib/basedirective/BaseDirective.js +++ b/components/lib/basedirective/BaseDirective.js @@ -99,10 +99,10 @@ const BaseDirective = { // common if (!Theme.isStyleNameLoaded('common')) { - const { primitive, semantic } = instance.$style?.getCommonThemeCSS?.() || {}; + const { primitive, semantic } = instance.$style?.getCommonTheme?.() || {}; - BaseStyle.load(primitive, { name: 'primitive-variables', ...useStyleOptions }); - BaseStyle.load(semantic, { name: 'semantic-variables', ...useStyleOptions }); + BaseStyle.load(primitive?.css, { name: 'primitive-variables', ...useStyleOptions }); + BaseStyle.load(semantic?.css, { name: 'semantic-variables', ...useStyleOptions }); BaseStyle.loadTheme({ name: 'global-style', ...useStyleOptions }); Theme.setLoadedStyleName('common'); @@ -110,9 +110,9 @@ const BaseDirective = { // directive if (!Theme.isStyleNameLoaded(instance.$style?.name) && instance.$style?.name) { - const { variables } = instance.$style?.getDirectiveThemeCSS?.() || {}; + const { css } = instance.$style?.getDirectiveTheme?.() || {}; - instance.$style?.load(variables, { name: `${instance.$style.name}-variables`, ...useStyleOptions }); + instance.$style?.load(css, { name: `${instance.$style.name}-variables`, ...useStyleOptions }); instance.$style?.loadTheme({ name: `${instance.$style.name}-style`, ...useStyleOptions }); Theme.setLoadedStyleName(instance.$style.name); @@ -131,8 +131,8 @@ const BaseDirective = { const preset = instance.preset(); if (preset && instance.$attrSelector) { - const { variables } = instance.$style?.getPresetThemeCSS?.(preset, `[${instance.$attrSelector}]`) || {}; - const scopedStyle = instance.$style?.load(variables, { name: `${instance.$attrSelector}-${instance.$style.name}`, ...useStyleOptions }); + const { css } = instance.$style?.getPresetTheme?.(preset, `[${instance.$attrSelector}]`) || {}; + const scopedStyle = instance.$style?.load(css, { name: `${instance.$attrSelector}-${instance.$style.name}`, ...useStyleOptions }); instance.scopedStyleEl = scopedStyle.el; } @@ -192,6 +192,9 @@ const BaseDirective = { el.$instance[hook]?.(el, binding, vnode, prevVnode); // handle hook in directive implementation el[`$${name}`] = el.$instance; // expose all options with $ BaseDirective._hook(name, hook, el, binding, vnode, prevVnode); // handle hooks during directive uses (global and self-definition) + + el.$pd ||= {}; + el.$pd[name] = { ...el.$pd?.[name], name, instance: el.$instance }; }; const handleWatch = (el) => { diff --git a/components/lib/themes/config/index.js b/components/lib/themes/config/index.js index 002fee782..0b06eab71 100644 --- a/components/lib/themes/config/index.js +++ b/components/lib/themes/config/index.js @@ -97,29 +97,23 @@ export default { getTokenValue(tokenPath) { return ThemeUtils.getTokenValue(this.tokens, tokenPath, this.defaults); }, - getCommonCSS(name = '', params) { + getCommon(name = '', params) { return ThemeUtils.getCommon({ name, theme: this.theme, params, defaults: this.defaults, set: { layerNames: this.setLayerNames.bind(this) } }); }, - getComponentCSS(name = '', params) { + getComponent(name = '', params) { const options = { name, theme: this.theme, params, defaults: this.defaults, set: { layerNames: this.setLayerNames.bind(this) } }; - return { - variables: ThemeUtils.getPresetC(options) - }; + return ThemeUtils.getPresetC(options); }, - getDirectiveCSS(name = '', params) { + getDirective(name = '', params) { const options = { name, theme: this.theme, params, defaults: this.defaults, set: { layerNames: this.setLayerNames.bind(this) } }; - return { - variables: ThemeUtils.getPresetD(options) - }; + return ThemeUtils.getPresetD(options); }, - getPresetCSS(name = '', preset, selector, params) { + getCustomPreset(name = '', preset, selector, params) { const options = { name, preset, options: this.options, selector, params, defaults: this.defaults, set: { layerNames: this.setLayerNames.bind(this) } }; - return { - variables: ThemeUtils.getPreset(options) - }; + return ThemeUtils.getPreset(options); }, getLayerOrderCSS(name = '') { return ThemeUtils.getLayerOrder(name, this.options, { names: this.getLayerNames() }, this.defaults); diff --git a/components/lib/themes/helpers/toVariables.js b/components/lib/themes/helpers/toVariables.js index 268ce3490..7d98c42be 100644 --- a/components/lib/themes/helpers/toVariables.js +++ b/components/lib/themes/helpers/toVariables.js @@ -5,27 +5,33 @@ export default function (theme, options = {}) { const { prefix = VARIABLE.prefix, selector = VARIABLE.selector, excludedKeyRegex = VARIABLE.excludedKeyRegex } = options; const _toVariables = (_theme, _prefix = '') => { - return Object.entries(_theme).reduce((acc, [key, value]) => { - const px = SharedUtils.object.test(excludedKeyRegex, key) ? SharedUtils.object.toNormalizeVariable(_prefix) : SharedUtils.object.toNormalizeVariable(_prefix, SharedUtils.object.toKebabCase(key)); - const v = SharedUtils.object.toValue(value); + return Object.entries(_theme).reduce( + (acc, [key, value]) => { + const px = SharedUtils.object.test(excludedKeyRegex, key) ? SharedUtils.object.toNormalizeVariable(_prefix) : SharedUtils.object.toNormalizeVariable(_prefix, SharedUtils.object.toKebabCase(key)); + const v = SharedUtils.object.toValue(value); - if (SharedUtils.object.isObject(v)) { - const variables = _toVariables(v, px); + if (SharedUtils.object.isObject(v)) { + const { variables, tokens } = _toVariables(v, px); - SharedUtils.object.merge(acc, variables); - } else { - SharedUtils.object.setProperty(acc, SharedUtils.object.getVariableName(px), SharedUtils.object.getVariableValue(v, px, prefix, [excludedKeyRegex])); - } + SharedUtils.object.merge(acc['tokens'], tokens); + SharedUtils.object.merge(acc['variables'], variables); + } else { + acc['tokens'].push((prefix ? px.replace(`${prefix}-`, '') : px).replaceAll('-', '.')); + SharedUtils.object.setProperty(acc['variables'], SharedUtils.object.getVariableName(px), SharedUtils.object.getVariableValue(v, px, prefix, [excludedKeyRegex])); + } - return acc; - }, []); + return acc; + }, + { variables: [], tokens: [] } + ); }; - const value = _toVariables(theme, prefix); + const { variables, tokens } = _toVariables(theme, prefix); return { - value, - declarations: value.join(''), - css: SharedUtils.object.getRule(selector, value.join('')) + value: variables, + tokens, + declarations: variables.join(''), + css: SharedUtils.object.getRule(selector, variables.join('')) }; } diff --git a/components/lib/themes/utils/themeUtils.js b/components/lib/themes/utils/themeUtils.js index 483516d12..2b97ca379 100644 --- a/components/lib/themes/utils/themeUtils.js +++ b/components/lib/themes/utils/themeUtils.js @@ -46,42 +46,63 @@ export default { }, getCommon({ name = '', theme = {}, params, set, defaults }) { const { preset, options } = theme; - let primitive_css, semantic_css; + let primitive_css, primitive_tokens, semantic_css, semantic_tokens; if (SharedUtils.object.isNotEmpty(preset)) { const { primitive, semantic } = preset; const { colorScheme, ...sRest } = semantic || {}; const { dark, ...csRest } = colorScheme || {}; - const prim_css = SharedUtils.object.isNotEmpty(primitive) ? this._toVariables({ primitive }, options).declarations : ''; - const sRest_css = SharedUtils.object.isNotEmpty(sRest) ? this._toVariables({ semantic: sRest }, options).declarations : ''; - const csRest_css = SharedUtils.object.isNotEmpty(csRest) ? this._toVariables({ light: csRest }, options).declarations : ''; - const dark_css = SharedUtils.object.isNotEmpty(dark) ? this._toVariables({ dark }, options).declarations : ''; + const prim_var = SharedUtils.object.isNotEmpty(primitive) ? this._toVariables({ primitive }, options) : {}; + const sRest_var = SharedUtils.object.isNotEmpty(sRest) ? this._toVariables({ semantic: sRest }, options) : {}; + const csRest_var = SharedUtils.object.isNotEmpty(csRest) ? this._toVariables({ light: csRest }, options) : {}; + const dark_var = SharedUtils.object.isNotEmpty(dark) ? this._toVariables({ dark }, options) : {}; + + const [prim_css, prim_tokens] = [prim_var.declarations ?? '', prim_var.tokens]; + const [sRest_css, sRest_tokens] = [sRest_var.declarations ?? '', sRest_var.tokens || []]; + const [csRest_css, csRest_tokens] = [csRest_var.declarations ?? '', csRest_var.tokens || []]; + const [dark_css, dark_tokens] = [dark_var.declarations ?? '', dark_var.tokens || []]; primitive_css = this.transformCSS(name, prim_css, 'light', 'variable', options, set, defaults); + primitive_tokens = prim_tokens; const semantic_light_css = this.transformCSS(name, `${sRest_css}${csRest_css}color-scheme:light`, 'light', 'variable', options, set, defaults); const semantic_dark_css = this.transformCSS(name, `${dark_css}color-scheme:dark`, 'dark', 'variable', options, set, defaults); semantic_css = `${semantic_light_css}${semantic_dark_css}`; + semantic_tokens = [...new Set([...sRest_tokens, ...csRest_tokens, ...dark_tokens])]; } return { - primitive: primitive_css, - semantic: semantic_css + primitive: { + css: primitive_css, + tokens: primitive_tokens + }, + semantic: { + css: semantic_css, + tokens: semantic_tokens + } }; }, getPreset({ name = '', preset = {}, options, params, set, defaults, selector }) { const _name = name.replace('-directive', ''); const { colorScheme, ...vRest } = preset; const { dark, ...csRest } = colorScheme || {}; - const vRest_css = SharedUtils.object.isNotEmpty(vRest) ? this._toVariables({ [_name]: vRest }, options).declarations : ''; - const csRest_css = SharedUtils.object.isNotEmpty(csRest) ? this._toVariables({ [_name]: csRest }, options).declarations : ''; - const dark_css = SharedUtils.object.isNotEmpty(dark) ? this._toVariables({ [_name]: dark }, options).declarations : ''; + const vRest_var = SharedUtils.object.isNotEmpty(vRest) ? this._toVariables({ [_name]: vRest }, options) : {}; + const csRest_var = SharedUtils.object.isNotEmpty(csRest) ? this._toVariables({ [_name]: csRest }, options) : {}; + const dark_var = SharedUtils.object.isNotEmpty(dark) ? this._toVariables({ [_name]: dark }, options) : {}; + + const [vRest_css, vRest_tokens] = [vRest_var.declarations ?? '', vRest_var.tokens || []]; + const [csRest_css, csRest_tokens] = [csRest_var.declarations ?? '', csRest_var.tokens || []]; + const [dark_css, dark_tokens] = [dark_var.declarations ?? '', dark_var.tokens || []]; + const tokens = [...new Set([...vRest_tokens, ...csRest_tokens, ...dark_tokens])]; const light_variable_css = this.transformCSS(_name, `${vRest_css}${csRest_css}`, 'light', 'variable', options, set, defaults, selector); const dark_variable_css = this.transformCSS(_name, dark_css, 'dark', 'variable', options, set, defaults, selector); - return `${light_variable_css}${dark_variable_css}`; + return { + css: `${light_variable_css}${dark_variable_css}`, + tokens + }; }, getPresetC({ name = '', theme = {}, params, set, defaults }) { const { preset, options } = theme; @@ -111,7 +132,8 @@ export default { return ''; }, getCommonStyleSheet({ name = '', theme = {}, params, props = {}, set, defaults }) { - const common_css = this.getCommon({ name, theme, params, set, defaults }); + const { primitive, semantic } = this.getCommon({ name, theme, params, set, defaults }); + const common_css = `${primitive.css}${semantic.css}`; const _props = Object.entries(props) .reduce((acc, [k, v]) => acc.push(`${k}="${v}"`) && acc, []) .join(' '); @@ -130,7 +152,7 @@ export default { .join(''); }, getStyleSheet({ name = '', theme = {}, params, props = {}, set, defaults }) { - const presetC_css = this.getPresetC({ name, theme, params, set, defaults }); + const presetC_css = this.getPresetC({ name, theme, params, set, defaults })?.css; const _props = Object.entries(props) .reduce((acc, [k, v]) => acc.push(`${k}="${v}"`) && acc, []) .join(' '); diff --git a/modules/nuxt-primevue/module.js b/modules/nuxt-primevue/module.js index d0f3c4e74..913f99087 100644 --- a/modules/nuxt-primevue/module.js +++ b/modules/nuxt-primevue/module.js @@ -15,7 +15,6 @@ export default defineNuxtModule({ layerOrder: 'tailwind-base, primevue, tailwind-utilities', importPT: undefined, importTheme: undefined, - unstyled: undefined, options: {}, components: { prefix: '', @@ -40,8 +39,8 @@ export default defineNuxtModule({ setup(moduleOptions, nuxt) { const resolver = createResolver(import.meta.url); const registered = register(moduleOptions); - const { importPT, importTheme, options, unstyled } = moduleOptions; - const hasTheme = importTheme && unstyled !== true && !options.unstyled; + const { importPT, importTheme, options } = moduleOptions; + const hasTheme = importTheme && !options.unstyled; nuxt.options.runtimeConfig.public.primevue = { ...moduleOptions, @@ -103,7 +102,7 @@ export default defineNuxtPlugin(({ vueApp }) => { const pt = ${importPT ? `{ pt: ${importPT.as} }` : `{}`}; const theme = ${hasTheme ? `{ theme: ${importTheme.as} }` : `{}`}; - usePrimeVue && vueApp.use(${unstyled === true ? 'PrimeVueUnstyled' : unstyled === false ? 'PrimeVueStyled' : 'PrimeVue'}, { ...options, ...pt, ...theme }); + usePrimeVue && vueApp.use(PrimeVue, { ...options, ...pt, ...theme }); ${registered.services.map((service) => `vueApp.use(${service.as});`).join('\n')} ${registered.directives.map((directive) => `vueApp.directive('${directive.name}', ${directive.as});`).join('\n')} }); diff --git a/modules/nuxt-primevue/register.js b/modules/nuxt-primevue/register.js index f604a81a0..51112dcfe 100644 --- a/modules/nuxt-primevue/register.js +++ b/modules/nuxt-primevue/register.js @@ -20,21 +20,7 @@ function registerItems(items = [], options = {}, params) { function registerConfig(resolvePath, moduleOptions) { const configs = []; - if (moduleOptions.unstyled === true) { - configs.push({ - name: 'PrimeVueUnstyled', - as: 'PrimeVueUnstyled', - from: resolvePath({ name: 'PrimeVueUnstyled', as: 'PrimeVueUnstyled', from: `primevue/unstyled`, type: 'config' }) - }); - } else if (moduleOptions.unstyled === false) { - configs.push({ - name: 'PrimeVueStyled', - as: 'PrimeVueStyled', - from: resolvePath({ name: 'PrimeVueStyled', as: 'PrimeVueStyled', from: `primevue/styled`, type: 'config' }) - }); - } else { - configs.push({ name: 'PrimeVue', as: 'PrimeVue', from: resolvePath({ name: 'PrimeVue', as: 'PrimeVue', from: `primevue/config`, type: 'config' }) }); - } + configs.push({ name: 'PrimeVue', as: 'PrimeVue', from: resolvePath({ name: 'PrimeVue', as: 'PrimeVue', from: `primevue/config`, type: 'config' }) }); return configs; } @@ -115,7 +101,7 @@ function registerStyles(resolvePath, registered, moduleOptions) { } ]; - if (!moduleOptions.unstyled) { + if (!moduleOptions?.options?.unstyled) { if (Utils.object.isNotEmpty(registered?.components)) { styles.push({ name: 'BaseComponentStyle',