Skip to content

Commit 800ad7a

Browse files
committed
feat(components): add two params for dynamicStyles, wrap processStringStyle for context styles, change CSSStyleSheet watchEffect
1 parent cf89de5 commit 800ad7a

File tree

4 files changed

+44
-16
lines changed

4 files changed

+44
-16
lines changed

packages/components/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ export * from './src/custom';
22
export * from './src/components';
33
// export * from './src/hooks';
44
export * from './src/utils';
5+
export * from './src/hooks/useBreakpoint';
6+
export * from './src/hooks/useNameSpace';
57
export { themeColors, locales, grayColors, statuses } from './src/common';
68

79
export { useForm } from '@lun/core';

packages/components/src/components/config/config.context.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ export const GlobalContextConfig = reactive({
1414
const original = openShadowComponents.reduce((result, name) => {
1515
result[name] = [];
1616
return result;
17-
}, {} as Record<'common' | OpenShadowComponentKey, ((vm: ComponentInternalInstance) => string)[]>);
18-
const commonStyles = [] as ((vm: ComponentInternalInstance) => string)[];
17+
}, {} as Record<'common' | OpenShadowComponentKey, ((vm: ComponentInternalInstance, compName: OpenShadowComponentKey, context: any) => string)[]>);
18+
const commonStyles = [] as ((
19+
vm: ComponentInternalInstance,
20+
compName: OpenShadowComponentKey,
21+
context: any,
22+
) => string)[];
1923
return new Proxy(original, {
2024
get(target, p, receiver) {
2125
if (p === 'common') return commonStyles;

packages/components/src/hooks/useStyles.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,60 @@
1-
import { copyCSSStyleSheetsIfNeed, isFunction, isSupportCSSStyleSheet, toArrayIfNotNil } from '@lun/utils';
1+
import { copyCSSStyleSheetsIfNeed, runIfFn, isSupportCSSStyleSheet, toArrayIfNotNil } from '@lun/utils';
22
import type { OpenShadowComponentKey } from 'config';
33
import { GlobalStaticConfig, componentsWithTeleport, useContextConfig } from 'config';
44
import { computed, getCurrentInstance, h, watchEffect } from 'vue';
55
import { onCEMount } from './shadowDom';
66
import { error } from '../utils/console';
7+
import { processStringStyle } from 'utils';
78

89
export function useContextStyles(name: OpenShadowComponentKey) {
910
const vm = getCurrentInstance()!;
1011
if (__DEV__ && !vm) {
1112
error('useContextStyles must be called inside setup()');
1213
return;
1314
}
14-
const dynamicStyles = useContextConfig('dynamicStyles');
15-
const styles = toArrayIfNotNil(dynamicStyles[name]).concat(() => (vm.props.innerStyle as string) || '');
15+
const context = useContextConfig();
16+
const { dynamicStyles } = context;
17+
const styles = toArrayIfNotNil(dynamicStyles[name]).concat(
18+
() => (vm.props.innerStyle as string) || '',
19+
);
1620
if (name === 'teleport-holder') {
1721
styles.push(...componentsWithTeleport.flatMap((name) => dynamicStyles[name]));
1822
}
19-
let sheets: CSSStyleSheet[] = [];
23+
const sheets: (CSSStyleSheet & { _clone?: CSSStyleSheet; _css: () => string })[] = [];
2024
const textStyles: (() => string)[] = [];
2125
const adopt = isSupportCSSStyleSheet() && GlobalStaticConfig.preferCSSStyleSheet;
2226
styles.forEach((s) => {
2327
if (!s) return;
24-
const css = !isFunction(s) ? () => String(s) : s;
28+
const css = () => processStringStyle(runIfFn(s, vm, name, context), true);
2529
if (adopt) {
26-
const sheet = new CSSStyleSheet();
27-
watchEffect(() => {
28-
const result = css(vm);
29-
result && sheet.replaceSync(String(result));
30-
});
30+
const sheet = new CSSStyleSheet() as CSSStyleSheet & { _clone?: CSSStyleSheet; _css: () => string };
31+
sheet._css = css;
3132
sheets.push(sheet);
3233
} else {
33-
textStyles.push(() => css(vm));
34+
textStyles.push(css);
3435
}
3536
});
37+
watchEffect(() => {
38+
sheets.forEach((s) => {
39+
s.replaceSync(s._css());
40+
if (s._clone) {
41+
s._clone.replaceSync(s._css());
42+
}
43+
});
44+
});
3645
onCEMount(({ shadowRoot }) => {
3746
if (sheets.length) {
47+
// TODO 或许不用管clone,或许可以通过vm.CE去获取window的CSSStyleSheet,这样就不用克隆了
3848
// copyCSSStyleSheetsIfNeed is for doc-pip component. when custom-element is moved to another document, it will throw an error: Sharing constructed stylesheets in multiple documents is not allowed
3949
// so we must check if the stylesheets are shared between documents, if so, we must clone them
40-
shadowRoot.adoptedStyleSheets.push(...copyCSSStyleSheetsIfNeed(sheets, shadowRoot));
50+
const cloned = copyCSSStyleSheetsIfNeed(sheets, shadowRoot);
51+
// attach cloned sheet to original sheet, so that it can be updated in watchEffect
52+
cloned.forEach((s, i) => {
53+
if (s !== sheets[i]) {
54+
sheets[i]._clone = s;
55+
}
56+
});
57+
shadowRoot.adoptedStyleSheets.push(...cloned);
4158
}
4259
});
4360
return computed(() => textStyles.map((i) => h('style', { type: 'text/css' }, i())));

packages/components/src/utils/style.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,20 @@ import { isString, isSupportCSSStyleSheet, supportCSSLayer } from '@lun/utils';
22
import { GlobalStaticConfig } from 'config';
33
import { mergeProps } from 'vue';
44

5-
export function processStringStyle(style: string) {
5+
export function processStringStyle<B extends boolean>(
6+
style: string,
7+
noSheet?: B,
8+
): B extends true ? string : string | CSSStyleSheet {
9+
style = String(style || '');
610
const { wrapCSSLayer, preferCSSStyleSheet, stylePreprocessor } = GlobalStaticConfig;
711
if (supportCSSLayer && wrapCSSLayer) {
812
style = `@layer ${isString(wrapCSSLayer) ? wrapCSSLayer : 'lun'} {${style}}`;
913
}
1014
style = stylePreprocessor(style);
11-
if (isSupportCSSStyleSheet() && preferCSSStyleSheet) {
15+
if (isSupportCSSStyleSheet() && preferCSSStyleSheet && !noSheet) {
1216
const sheet = new CSSStyleSheet();
1317
sheet.replaceSync(style);
18+
// @ts-ignore
1419
return sheet;
1520
} else return style;
1621
}

0 commit comments

Comments
 (0)