Theming API: Refactor on $dt method and inline styles for css variables

pull/5677/head
mertsincan 2024-04-15 10:17:29 +01:00
parent ddeaab525a
commit 51110b585a
12 changed files with 129 additions and 67 deletions

View File

@ -1 +1,18 @@
export default {};
export default {
_loadedStyleNames: new Set(),
getLoadedStyleNames() {
return this._loadedStyleNames;
},
isStyleNameLoaded(name) {
return this._loadedStyleNames.has(name);
},
setLoadedStyleName(name) {
this._loadedStyleNames.add(name);
},
deleteLoadedStyleName(name) {
this._loadedStyleNames.delete(name);
},
clearLoadedStyleNames() {
this._loadedStyleNames.clear();
}
};

View File

@ -1,11 +1,8 @@
import Theme from 'primevue/themes';
import Theme, { dt } from 'primevue/themes';
import { useStyle } from 'primevue/usestyle';
import { ObjectUtils } from 'primevue/utils';
/**
* @todo padding-right: ${$dt('scrollbar.width')};
*/
const css = `
const css = ({ dt }) => `
.p-hidden-accessible {
border: 0;
clip: rect(0 0 0 0);
@ -24,7 +21,7 @@ const css = `
.p-overflow-hidden {
overflow: hidden;
padding-right: var(--p-scrollbar-width);
padding-right: ${dt('scrollbar.width')};
}
`;
@ -38,7 +35,9 @@ export default {
classes,
inlineStyles,
loadStyle(options = {}) {
return this.css ? useStyle(ObjectUtils.minifyCSS(this.css), { name: this.name, ...options }) : {};
const css = ObjectUtils.getItemValue(this.css, { dt });
return css ? useStyle(ObjectUtils.minifyCSS(css), { name: this.name, ...options }) : {};
},
loadTheme(theme, options = {}) {
return theme ? useStyle(ObjectUtils.minifyCSS(theme), { name: this.name, ...options }) : {};

View File

@ -1,4 +1,5 @@
<script>
import Base from 'primevue/base';
import BaseStyle from 'primevue/base/style';
import Theme, { ThemeService } from 'primevue/themes';
import { DomHandler, ObjectUtils, UniqueComponentId } from 'primevue/utils';
@ -35,8 +36,8 @@ export default {
immediate: true,
handler(newValue) {
if (!newValue) {
BaseComponentStyle.loadStyle(this.$styleOptions);
this.$options.style && this.$style.loadStyle(this.$styleOptions);
this._loadCoreStyles();
this._themeChangeListener(this._loadCoreStyles); // update styles with theme settings
} else {
// load theme
this._loadThemeStyles();
@ -107,11 +108,28 @@ export default {
return ObjectUtils.isFunction(fn) ? fn(...args) : mergeProps(...args);
},
_loadStyles() {
const _load = () => {
// @todo
if (!Base.isStyleNameLoaded('base')) {
BaseStyle.loadStyle(this.$styleOptions);
this._loadGlobalStyles();
this._loadThemeStyles();
ThemeService.on('theme:change', this._loadThemeStyles);
Base.setLoadedStyleName('base');
}
this._loadThemeStyles();
};
_load();
this._themeChangeListener(_load);
},
_loadCoreStyles() {
if (!Base.isStyleNameLoaded(this.$style?.name) && this.$style?.name) {
BaseComponentStyle.loadStyle(this.$styleOptions);
this.$options.style && this.$style.loadStyle(this.$styleOptions);
Base.setLoadedStyleName(this.$style.name);
}
},
_loadGlobalStyles() {
/*
@ -167,6 +185,10 @@ export default {
this.scopedStyleEl = scopedStyle.el;
},
_themeChangeListener(callback = () => {}) {
Base.clearLoadedStyleNames();
ThemeService.on('theme:change', callback);
},
_getHostInstance(instance) {
return instance ? (this.$options.hostName ? (instance.$.type.name === this.$options.hostName ? instance : this._getHostInstance(instance.$parentInstance)) : instance.$parentInstance) : undefined;
},

View File

@ -1,3 +1,4 @@
import Base from 'primevue/base';
import BaseStyle from 'primevue/base/style';
import Theme, { ThemeService } from 'primevue/themes';
import { ObjectUtils, UniqueComponentId } from 'primevue/utils';
@ -76,14 +77,21 @@ const BaseDirective = {
},
_loadStyles: (el, binding, vnode) => {
const config = BaseDirective._getConfig(binding, vnode);
const useStyleOptions = { nonce: config?.csp?.nonce };
BaseStyle.loadStyle({ nonce: config?.csp?.nonce });
!el.$instance?.isUnstyled() && el.$instance?.$style?.loadStyle({ nonce: config?.csp?.nonce });
BaseDirective._loadCoreStyles(el.$instance, useStyleOptions);
BaseDirective._loadThemeStyles(el.$instance, useStyleOptions);
BaseDirective._loadScopedThemeStyles(el.$instance, useStyleOptions);
BaseDirective._loadThemeStyles(el.$instance, { nonce: config?.csp?.nonce });
ThemeService.on('theme:change', () => BaseDirective._loadThemeStyles(el.$instance, { nonce: config?.csp?.nonce }));
BaseDirective._themeChangeListener(() => BaseDirective._loadThemeStyles(el.$instance, useStyleOptions));
},
_loadCoreStyles(instance = {}, useStyleOptions) {
if (!Base.isStyleNameLoaded(instance.$style?.name) && instance.$style?.name) {
BaseStyle.loadStyle(useStyleOptions);
instance.isUnstyled() && instance.$style?.loadStyle(useStyleOptions);
BaseDirective._loadScopedThemeStyles(el.$instance, { nonce: config?.csp?.nonce });
Base.setLoadedStyleName(instance.$style.name);
}
},
_loadThemeStyles: (instance = {}, useStyleOptions) => {
if (instance?.isUnstyled()) return;
@ -128,6 +136,10 @@ const BaseDirective = {
instance.scopedStyleEl = scopedStyle.el;
}
},
_themeChangeListener(callback = () => {}) {
Base.clearLoadedStyleNames();
ThemeService.on('theme:change', callback);
},
_hook: (directiveName, hookName, el, binding, vnode, prevVnode) => {
const name = `on${ObjectUtils.toCapitalCase(hookName)}`;
const config = BaseDirective._getConfig(binding, vnode);

View File

@ -63,7 +63,7 @@ import ConfirmationEventBus from 'primevue/confirmationeventbus';
import FocusTrap from 'primevue/focustrap';
import OverlayEventBus from 'primevue/overlayeventbus';
import Portal from 'primevue/portal';
import { $dtp } from 'primevue/themes';
import { $dt } from 'primevue/themes';
import { ConnectedOverlayScrollHandler, DomHandler, ZIndexUtils } from 'primevue/utils';
import BaseConfirmPopup from './BaseConfirmPopup.vue';
@ -204,7 +204,7 @@ export default {
arrowLeft = targetOffset.left - containerOffset.left;
}
this.container.style.setProperty($dtp('overlay.arrow.left').name, `${arrowLeft}px`);
this.container.style.setProperty($dt('overlay.arrow.left').name, `${arrowLeft}px`);
if (containerOffset.top < targetOffset.top) {
this.container.setAttribute('data-p-confirm-popup-flipped', 'true');

View File

@ -37,15 +37,21 @@ export default {
},
valueColor: {
type: String,
default: $dt('knob.value.background')
default: () => {
return $dt('knob.value.background').variable;
}
},
rangeColor: {
type: String,
default: $dt('knob.range.background')
default: () => {
return $dt('knob.range.background').variable;
}
},
textColor: {
type: String,
default: $dt('knob.text.color')
default: () => {
return $dt('knob.text.color').variable;
}
},
strokeWidth: {
type: Number,

View File

@ -18,7 +18,7 @@ import FocusTrap from 'primevue/focustrap';
import OverlayEventBus from 'primevue/overlayeventbus';
import Portal from 'primevue/portal';
import Ripple from 'primevue/ripple';
import { $dtp } from 'primevue/themes';
import { $dt } from 'primevue/themes';
import { ConnectedOverlayScrollHandler, DomHandler, UniqueComponentId, ZIndexUtils } from 'primevue/utils';
import BaseOverlayPanel from './BaseOverlayPanel.vue';
@ -155,7 +155,7 @@ export default {
arrowLeft = targetOffset.left - containerOffset.left;
}
this.container.style.setProperty($dtp('overlay.arrow.left').name, `${arrowLeft}px`);
this.container.style.setProperty($dt('overlay.arrow.left').name, `${arrowLeft}px`);
if (containerOffset.top < targetOffset.top) {
this.container.setAttribute('data-p-overlaypanel-flipped', 'true');

View File

@ -67,7 +67,7 @@
import Button from 'primevue/button';
import PlusIcon from 'primevue/icons/plus';
import Ripple from 'primevue/ripple';
import { $dt, $dtp } from 'primevue/themes';
import { $dt } from 'primevue/themes';
import Tooltip from 'primevue/tooltip';
import { DomHandler, UniqueComponentId } from 'primevue/utils';
import BaseSpeedDial from './BaseSpeedDial.vue';
@ -108,8 +108,8 @@ export default {
const wDiff = Math.abs(button.offsetWidth - firstItem.offsetWidth);
const hDiff = Math.abs(button.offsetHeight - firstItem.offsetHeight);
this.list.style.setProperty($dtp('item.diff.x').name, `${wDiff / 2}px`);
this.list.style.setProperty($dtp('item.diff.y').name, `${hDiff / 2}px`);
this.list.style.setProperty($dt('item.diff.x').name, `${wDiff / 2}px`);
this.list.style.setProperty($dt('item.diff.y').name, `${hDiff / 2}px`);
}
}

View File

@ -1,14 +1,25 @@
import Theme, { SharedUtils } from 'primevue/themes';
import { SharedUtils } from 'primevue/themes';
import Theme from 'primevue/themes/config';
const types = ['value', 'variable'];
export const $dt = (tokenPath, param1, param2) => {
export const $dt = (tokenPath) => {
const theme = Theme.getTheme();
return types.includes(param1) ? dt(theme, tokenPath, undefined, param1) : dt(theme, tokenPath, param1, param2);
const variable = dtwt(theme, tokenPath, undefined, 'variable');
const name = variable.match(/--[\w-]+/g)?.[0];
const value = dtwt(theme, tokenPath, undefined, 'value');
return {
name,
variable,
value
};
};
export const dt = (theme = {}, tokenPath, fallback, type = 'variable') => {
export const dt = (...args) => {
return dtwt(Theme.getTheme(), ...args);
};
export const dtwt = (theme = {}, tokenPath, fallback, type = 'variable') => {
if (tokenPath) {
const VARIABLE = Theme.defaults.variable;
const { prefix, transform } = theme?.options || {};
@ -21,17 +32,3 @@ export const dt = (theme = {}, tokenPath, fallback, type = 'variable') => {
return '';
};
export const $dtp = (tokenPath) => {
const theme = Theme.getTheme();
const variable = dt(theme, tokenPath, undefined, 'variable');
const name = variable.match(/--[\w-]+/g)?.[0];
const value = dt(theme, tokenPath, undefined, 'value');
return {
variable,
name,
value
};
};

View File

@ -1,4 +1,4 @@
import { SharedUtils, dt, toVariables } from 'primevue/themes';
import { SharedUtils, dtwt, toVariables } from 'primevue/themes';
export default {
regex: {
@ -62,7 +62,7 @@ export default {
semantic_css = `${semantic_light_css}${semantic_dark_css}`;
}
global_css = SharedUtils.object.getItemValue(base?.global?.css, { ...params, dt: (tokenPath, fallback, type) => dt(theme, tokenPath, fallback, type) });
global_css = SharedUtils.object.getItemValue(base?.global?.css, { ...params, dt: (...args) => dtwt(theme, ...args) });
global_css = this._transformCSS(name, global_css, undefined, 'style', options, set, defaults);
return {
@ -93,7 +93,7 @@ export default {
getBaseC({ name = '', theme = {}, params, set, defaults }) {
const { base, options } = theme;
const { css } = base?.components?.[name] || {};
const computed_css = SharedUtils.object.getItemValue(css, { ...params, dt: (tokenPath, fallback, type) => dt(theme, tokenPath, fallback, type) });
const computed_css = SharedUtils.object.getItemValue(css, { ...params, dt: (...args) => dtwt(theme, ...args) });
return this._transformCSS(name, computed_css, undefined, 'style', options, set, defaults);
},
@ -108,7 +108,7 @@ export default {
const dName = name.replace('-directive', '');
const { base, options } = theme;
const { css } = base?.directives?.[dName] || {};
const computed_css = SharedUtils.object.getItemValue(css, { ...params, dt: (tokenPath, fallback, type) => dt(theme, tokenPath, fallback, type) });
const computed_css = SharedUtils.object.getItemValue(css, { ...params, dt: (...args) => dtwt(theme, ...args) });
return this._transformCSS(dName, computed_css, undefined, 'style', options, set, defaults);
},
@ -173,10 +173,10 @@ export default {
if (colorScheme) {
const path = this.paths.find((p) => p.scheme === colorScheme) || this.paths.find((p) => p.scheme === 'none');
return path?.computed(colorScheme, tokenPathMap['paths']);
return path?.computed(colorScheme, tokenPathMap['binding']);
}
return this.paths.map((p) => p.computed(p.scheme, tokenPathMap));
return this.paths.map((p) => p.computed(p.scheme, tokenPathMap[p.scheme]));
}
};
tokens[currentKey].paths.push({
@ -187,8 +187,8 @@ export default {
const regex = /{([^}]*)}/g;
let computedValue = value;
tokenPathMap['path'] = this.path;
tokenPathMap['paths'] ||= {};
tokenPathMap['name'] = this.path;
tokenPathMap['binding'] ||= {};
if (SharedUtils.object.test(regex, value)) {
const val = value.trim();
@ -204,12 +204,12 @@ export default {
computedValue = SharedUtils.object.test(calculationRegex, _val.replace(cleanedVarRegex, '0')) ? `calc(${_val})` : _val;
}
SharedUtils.object.isEmpty(tokenPathMap['paths']) && delete tokenPathMap['paths'];
SharedUtils.object.isEmpty(tokenPathMap['binding']) && delete tokenPathMap['binding'];
return {
colorScheme,
tokenPath: this.path,
tokenPathMap,
path: this.path,
paths: tokenPathMap,
value: computedValue.includes('undefined') ? undefined : computedValue
};
}
@ -228,8 +228,17 @@ export default {
const token = normalizePath(path);
const colorScheme = path.includes('colorScheme.light') ? 'light' : path.includes('colorScheme.dark') ? 'dark' : undefined;
const computedValues = [tokens[token]?.computed(colorScheme)].flat().filter((computed) => computed);
return [tokens[token]?.computed(colorScheme)].flat();
return computedValues.length === 1
? computedValues[0].value
: computedValues.reduce((acc = {}, computed) => {
const { colorScheme: cs, ...rest } = computed;
acc[cs] = rest;
return acc;
}, undefined);
},
_toVariables(theme, options) {
return toVariables(theme, { prefix: options?.prefix });

View File

@ -1,4 +1,4 @@
import { $dt, $dtp } from 'primevue/themes';
import { $dt } from 'primevue/themes';
export default {
innerWidth(el) {
@ -328,7 +328,7 @@ export default {
element.style.top = top + 'px';
element.style.left = left + 'px';
element.style.transformOrigin = origin;
gutter && (element.style.marginTop = origin === 'bottom' ? $dt('{anchor.gutter} * -1') : $dt('anchor.gutter'));
gutter && (element.style.marginTop = origin === 'bottom' ? $dt('{anchor.gutter} * -1').variable : $dt('anchor.gutter').variable);
}
},
@ -367,7 +367,7 @@ export default {
element.style.top = top + 'px';
element.style.left = left + 'px';
element.style.transformOrigin = origin;
gutter && (element.style.marginTop = origin === 'bottom' ? $dt('{anchor.gutter} * -1') : $dt('anchor.gutter'));
gutter && (element.style.marginTop = origin === 'bottom' ? $dt('{anchor.gutter} * -1').variable : $dt('anchor.gutter').variable);
}
},
@ -851,12 +851,12 @@ export default {
},
blockBodyScroll(className = 'p-overflow-hidden') {
document.body.style.setProperty($dtp('scrollbar.width').name, this.calculateBodyScrollbarWidth() + 'px');
document.body.style.setProperty($dt('scrollbar.width').name, this.calculateBodyScrollbarWidth() + 'px');
this.addClass(document.body, className);
},
unblockBodyScroll(className = 'p-overflow-hidden') {
document.body.style.removeProperty($dtp('scrollbar.width').name);
document.body.style.removeProperty($dt('scrollbar.width').name);
this.removeClass(document.body, className);
}
};

View File

@ -33,7 +33,7 @@ export default {
var(--p-blue-500)
// With JS
$dt('blue.500', 'value')
$dt('blue.500').value
`
}
};