@lobehub/ui 6.0.0-beta.8 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +3 -3
  2. package/es/Accordion/style.d.mts +1 -1
  3. package/es/CodeDiff/DiffPanel.mjs +2 -2
  4. package/es/CodeDiff/DiffPanel.mjs.map +1 -1
  5. package/es/DatePicker/DatePicker.d.mts +5 -3
  6. package/es/DatePicker/DatePicker.mjs +7 -5
  7. package/es/DatePicker/DatePicker.mjs.map +1 -1
  8. package/es/DatePicker/DateRangePicker.d.mts +1 -1
  9. package/es/DatePicker/DayjsDatePicker.d.mts +12 -0
  10. package/es/DatePicker/DayjsDatePicker.mjs +19 -0
  11. package/es/DatePicker/DayjsDatePicker.mjs.map +1 -0
  12. package/es/DatePicker/DayjsDateRangePicker.d.mts +7 -0
  13. package/es/DatePicker/DayjsDateRangePicker.mjs +8 -0
  14. package/es/DatePicker/DayjsDateRangePicker.mjs.map +1 -0
  15. package/es/DatePicker/RangePicker.mjs +7 -1
  16. package/es/DatePicker/RangePicker.mjs.map +1 -1
  17. package/es/DatePicker/SinglePicker.mjs +3 -1
  18. package/es/DatePicker/SinglePicker.mjs.map +1 -1
  19. package/es/DatePicker/dateGenerateConfig.mjs +52 -0
  20. package/es/DatePicker/dateGenerateConfig.mjs.map +1 -0
  21. package/es/DatePicker/index.d.mts +4 -2
  22. package/es/DatePicker/index.mjs +3 -1
  23. package/es/DatePicker/legacyDate.mjs +58 -0
  24. package/es/DatePicker/legacyDate.mjs.map +1 -0
  25. package/es/DatePicker/type.d.mts +60 -34
  26. package/es/DatePicker/usePresetActive.mjs +1 -0
  27. package/es/DatePicker/usePresetActive.mjs.map +1 -1
  28. package/es/Drawer/style.mjs.map +1 -1
  29. package/es/FloatingPanel/style.mjs +3 -2
  30. package/es/FloatingPanel/style.mjs.map +1 -1
  31. package/es/Form/Form.mjs +6 -2
  32. package/es/Form/Form.mjs.map +1 -1
  33. package/es/Form/style.mjs +3 -3
  34. package/es/Form/style.mjs.map +1 -1
  35. package/es/Form/type.d.mts +7 -0
  36. package/es/Popover/style.mjs +1 -1
  37. package/es/Popover/style.mjs.map +1 -1
  38. package/es/ProTable/hooks/useFetchData.mjs +1 -1
  39. package/es/ProTable/hooks/useFetchData.mjs.map +1 -1
  40. package/es/ProTable/parts/FieldControl.mjs +32 -15
  41. package/es/ProTable/parts/FieldControl.mjs.map +1 -1
  42. package/es/ProTable/style.mjs +9 -0
  43. package/es/ProTable/style.mjs.map +1 -1
  44. package/es/ProTable/type.d.mts +5 -2
  45. package/es/Switch/Switch.mjs +8 -1
  46. package/es/Switch/Switch.mjs.map +1 -1
  47. package/es/Switch/atoms.d.mts +7 -1
  48. package/es/Switch/atoms.mjs +20 -4
  49. package/es/Switch/atoms.mjs.map +1 -1
  50. package/es/Switch/style.mjs +33 -2
  51. package/es/Switch/style.mjs.map +1 -1
  52. package/es/Table/Table.mjs +14 -5
  53. package/es/Table/Table.mjs.map +1 -1
  54. package/es/Table/render/FixedFrost.mjs +11 -2
  55. package/es/Table/render/FixedFrost.mjs.map +1 -1
  56. package/es/Table/style.mjs +4 -0
  57. package/es/Table/style.mjs.map +1 -1
  58. package/es/Tabs/style.d.mts +1 -1
  59. package/es/Text/style.d.mts +3 -3
  60. package/es/Toast/dodge.mjs +0 -1
  61. package/es/Toast/dodge.mjs.map +1 -1
  62. package/es/Toast/dodge.stylex.mjs +1 -4
  63. package/es/Toast/dodge.stylex.mjs.map +1 -1
  64. package/es/Toast/style.mjs +1 -1
  65. package/es/Toast/style.mjs.map +1 -1
  66. package/es/Tooltip/style.mjs +2 -2
  67. package/es/Tooltip/style.mjs.map +1 -1
  68. package/es/color/index.d.mts +2 -1
  69. package/es/color/index.mjs +2 -1
  70. package/es/color/status/error.mjs +67 -0
  71. package/es/color/status/error.mjs.map +1 -0
  72. package/es/color/status/index.d.mts +11 -0
  73. package/es/color/status/index.mjs +15 -0
  74. package/es/color/status/index.mjs.map +1 -0
  75. package/es/color/status/info.mjs +67 -0
  76. package/es/color/status/info.mjs.map +1 -0
  77. package/es/color/status/success.mjs +67 -0
  78. package/es/color/status/success.mjs.map +1 -0
  79. package/es/color/status/warning.mjs +67 -0
  80. package/es/color/status/warning.mjs.map +1 -0
  81. package/es/index.d.mts +6 -3
  82. package/es/index.mjs +5 -2
  83. package/es/style.css +114 -23
  84. package/es/styles/index.d.mts +3 -2
  85. package/es/styles/index.mjs +3 -2
  86. package/es/styles/stylex/cssVar.stylex.mjs +3 -0
  87. package/es/styles/stylex/cssVar.stylex.mjs.map +1 -1
  88. package/es/styles/theme/createLobeToken.d.mts +9 -5
  89. package/es/styles/theme/createLobeToken.mjs +3 -2
  90. package/es/styles/theme/createLobeToken.mjs.map +1 -1
  91. package/es/styles/theme/customPalette.d.mts +6 -0
  92. package/es/styles/theme/customPalette.mjs +28 -0
  93. package/es/styles/theme/customPalette.mjs.map +1 -0
  94. package/es/styles/theme/customPrimary.mjs +52 -17
  95. package/es/styles/theme/customPrimary.mjs.map +1 -1
  96. package/es/styles/theme/scope.d.mts +4 -2
  97. package/es/styles/theme/scope.mjs +53 -20
  98. package/es/styles/theme/scope.mjs.map +1 -1
  99. package/es/styles/theme/themeCss.d.mts +1 -0
  100. package/es/styles/theme/themeCss.mjs +16 -1
  101. package/es/styles/theme/themeCss.mjs.map +1 -1
  102. package/es/styles/theme/token/legacy.mjs +12 -12
  103. package/es/styles/theme/token/legacy.mjs.map +1 -1
  104. package/es/styles/theme/token/neutral.mjs +12 -4
  105. package/es/styles/theme/token/neutral.mjs.map +1 -1
  106. package/es/styles/theme/token/neutralText.mjs +91 -0
  107. package/es/styles/theme/token/neutralText.mjs.map +1 -0
  108. package/es/styles/theme/token/palette.mjs +16 -41
  109. package/es/styles/theme/token/palette.mjs.map +1 -1
  110. package/es/styles/theme/token/static.mjs +3 -0
  111. package/es/styles/theme/token/static.mjs.map +1 -1
  112. package/es/theme.css +293 -290
  113. package/package.json +1 -1
@@ -4,9 +4,10 @@ import { LobePrimaryColor } from "./customPrimary.mjs";
4
4
  export interface CreateLobeTokenParams {
5
5
  appearance: 'light' | 'dark';
6
6
  neutralColor?: NeutralColors;
7
+ palette?: string;
7
8
  primaryColor?: LobePrimaryColor;
8
9
  }
9
- export declare const createLobeTokenGroups: ({ appearance, neutralColor, primaryColor }: CreateLobeTokenParams) => {
10
+ export declare const createLobeTokenGroups: ({ appearance, neutralColor, palette: paletteName, primaryColor }: CreateLobeTokenParams) => {
10
11
  neutral: {
11
12
  colorBgContainerDisabled: string;
12
13
  colorBgContainerSecondary: string;
@@ -29,6 +30,10 @@ export declare const createLobeTokenGroups: ({ appearance, neutralColor, primary
29
30
  controlItemBgActiveDisabled: string;
30
31
  controlItemBgHover: string;
31
32
  controlTmpOutline: string;
33
+ colorText: string;
34
+ colorTextQuaternary: string;
35
+ colorTextSecondary: string;
36
+ colorTextTertiary: string;
32
37
  colorBgContainer: string;
33
38
  colorBgElevated: string;
34
39
  colorBgLayout: string;
@@ -40,10 +45,6 @@ export declare const createLobeTokenGroups: ({ appearance, neutralColor, primary
40
45
  colorFillQuaternary: string;
41
46
  colorFillSecondary: string;
42
47
  colorFillTertiary: string;
43
- colorText: string;
44
- colorTextQuaternary: string;
45
- colorTextSecondary: string;
46
- colorTextTertiary: string;
47
48
  };
48
49
  palette: {
49
50
  colorErrorAffix: string;
@@ -1291,6 +1292,9 @@ export declare const createLobeTokenGroups: ({ appearance, neutralColor, primary
1291
1292
  motionEaseOutBack: string;
1292
1293
  motionEaseOutCirc: string;
1293
1294
  motionEaseOutQuint: string;
1295
+ motionSpringBouncy: string;
1296
+ motionSpringSmooth: string;
1297
+ motionSpringSnappy: string;
1294
1298
  motionUnit: number;
1295
1299
  opacityImage: number;
1296
1300
  opacityLoading: number;
@@ -1,10 +1,11 @@
1
+ import { resolveStatusScales } from "./customPalette.mjs";
1
2
  import { createNeutralToken } from "./token/neutral.mjs";
2
3
  import { createPaletteToken } from "./token/palette.mjs";
3
4
  import { createPrimaryToken } from "./token/primary.mjs";
4
5
  import { staticToken } from "./token/static.mjs";
5
6
  //#region src/styles/theme/createLobeToken.ts
6
- const createLobeTokenGroups = ({ appearance, neutralColor, primaryColor }) => {
7
- const palette = createPaletteToken(appearance);
7
+ const createLobeTokenGroups = ({ appearance, neutralColor, palette: paletteName, primaryColor }) => {
8
+ const palette = createPaletteToken(appearance, resolveStatusScales(paletteName));
8
9
  return {
9
10
  neutral: createNeutralToken(appearance, neutralColor, palette),
10
11
  palette,
@@ -1 +1 @@
1
- {"version":3,"file":"createLobeToken.mjs","names":[],"sources":["../../../src/styles/theme/createLobeToken.ts"],"sourcesContent":["import type { NeutralColors } from '../customTheme';\nimport type { LobePrimaryColor } from './customPrimary';\nimport { createNeutralToken } from './token/neutral';\nimport { createPaletteToken } from './token/palette';\nimport { createPrimaryToken } from './token/primary';\nimport { staticToken } from './token/static';\n\nexport interface CreateLobeTokenParams {\n appearance: 'light' | 'dark';\n neutralColor?: NeutralColors;\n primaryColor?: LobePrimaryColor;\n}\n\nexport const createLobeTokenGroups = ({\n appearance,\n neutralColor,\n primaryColor,\n}: CreateLobeTokenParams) => {\n const palette = createPaletteToken(appearance);\n\n return {\n neutral: createNeutralToken(appearance, neutralColor, palette),\n palette,\n primary: createPrimaryToken(appearance, primaryColor),\n static: staticToken,\n };\n};\n\nexport type LobeTokenGroups = ReturnType<typeof createLobeTokenGroups>;\n\nexport type LobeToken = LobeTokenGroups['static'] &\n LobeTokenGroups['palette'] &\n LobeTokenGroups['primary'] &\n LobeTokenGroups['neutral'];\n\nexport const createLobeToken = (params: CreateLobeTokenParams): LobeToken => {\n const groups = createLobeTokenGroups(params);\n\n return { ...groups.static, ...groups.palette, ...groups.primary, ...groups.neutral };\n};\n"],"mappings":";;;;;AAaA,MAAa,yBAAyB,EACpC,YACA,cACA,mBAC2B;CAC3B,MAAM,UAAU,mBAAmB,UAAU;CAE7C,OAAO;EACL,SAAS,mBAAmB,YAAY,cAAc,OAAO;EAC7D;EACA,SAAS,mBAAmB,YAAY,YAAY;EACpD,QAAQ;CACV;AACF;AASA,MAAa,mBAAmB,WAA6C;CAC3E,MAAM,SAAS,sBAAsB,MAAM;CAE3C,OAAO;EAAE,GAAG,OAAO;EAAQ,GAAG,OAAO;EAAS,GAAG,OAAO;EAAS,GAAG,OAAO;CAAQ;AACrF"}
1
+ {"version":3,"file":"createLobeToken.mjs","names":[],"sources":["../../../src/styles/theme/createLobeToken.ts"],"sourcesContent":["import type { NeutralColors } from '../customTheme';\nimport { resolveStatusScales } from './customPalette';\nimport type { LobePrimaryColor } from './customPrimary';\nimport { createNeutralToken } from './token/neutral';\nimport { createPaletteToken } from './token/palette';\nimport { createPrimaryToken } from './token/primary';\nimport { staticToken } from './token/static';\n\nexport interface CreateLobeTokenParams {\n appearance: 'light' | 'dark';\n neutralColor?: NeutralColors;\n palette?: string;\n primaryColor?: LobePrimaryColor;\n}\n\nexport const createLobeTokenGroups = ({\n appearance,\n neutralColor,\n palette: paletteName,\n primaryColor,\n}: CreateLobeTokenParams) => {\n const palette = createPaletteToken(appearance, resolveStatusScales(paletteName));\n\n return {\n neutral: createNeutralToken(appearance, neutralColor, palette),\n palette,\n primary: createPrimaryToken(appearance, primaryColor),\n static: staticToken,\n };\n};\n\nexport type LobeTokenGroups = ReturnType<typeof createLobeTokenGroups>;\n\nexport type LobeToken = LobeTokenGroups['static'] &\n LobeTokenGroups['palette'] &\n LobeTokenGroups['primary'] &\n LobeTokenGroups['neutral'];\n\nexport const createLobeToken = (params: CreateLobeTokenParams): LobeToken => {\n const groups = createLobeTokenGroups(params);\n\n return { ...groups.static, ...groups.palette, ...groups.primary, ...groups.neutral };\n};\n"],"mappings":";;;;;;AAeA,MAAa,yBAAyB,EACpC,YACA,cACA,SAAS,aACT,mBAC2B;CAC3B,MAAM,UAAU,mBAAmB,YAAY,oBAAoB,WAAW,CAAC;CAE/E,OAAO;EACL,SAAS,mBAAmB,YAAY,cAAc,OAAO;EAC7D;EACA,SAAS,mBAAmB,YAAY,YAAY;EACpD,QAAQ;CACV;AACF;AASA,MAAa,mBAAmB,WAA6C;CAC3E,MAAM,SAAS,sBAAsB,MAAM;CAE3C,OAAO;EAAE,GAAG,OAAO;EAAQ,GAAG,OAAO;EAAS,GAAG,OAAO;EAAS,GAAG,OAAO;CAAQ;AACrF"}
@@ -0,0 +1,6 @@
1
+ import { StatusColorScales } from "../../color/status/index.mjs";
2
+ //#region src/styles/theme/customPalette.d.ts
3
+ export type LobeStatusPalette = Partial<StatusColorScales>;
4
+ export declare const registerLobePalette: (name: string, palette: LobeStatusPalette) => void;
5
+ //#endregion
6
+ //# sourceMappingURL=customPalette.d.mts.map
@@ -0,0 +1,28 @@
1
+ import { statusColorScales } from "../../color/status/index.mjs";
2
+ //#region src/styles/theme/customPalette.ts
3
+ const NAME = /^[\w-]+$/;
4
+ const registry = /* @__PURE__ */ new Map();
5
+ const listeners = /* @__PURE__ */ new Set();
6
+ let revision = 0;
7
+ const registerLobePalette = (name, palette) => {
8
+ if (!NAME.test(name)) throw new Error(`Invalid palette name "${name}": use letters, digits, _ or -`);
9
+ registry.set(name, palette);
10
+ revision++;
11
+ for (const listener of listeners) listener();
12
+ };
13
+ const getPaletteRevision = () => revision;
14
+ const subscribePalettes = (listener) => {
15
+ listeners.add(listener);
16
+ return () => {
17
+ listeners.delete(listener);
18
+ };
19
+ };
20
+ const isRegisteredPalette = (name) => !!name && registry.has(name);
21
+ const resolveStatusScales = (name) => isRegisteredPalette(name) ? {
22
+ ...statusColorScales,
23
+ ...registry.get(name)
24
+ } : statusColorScales;
25
+ //#endregion
26
+ export { getPaletteRevision, isRegisteredPalette, registerLobePalette, resolveStatusScales, subscribePalettes };
27
+
28
+ //# sourceMappingURL=customPalette.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customPalette.mjs","names":[],"sources":["../../../src/styles/theme/customPalette.ts"],"sourcesContent":["import { type StatusColorScales, statusColorScales } from '@/color/status';\n\nexport type LobeStatusPalette = Partial<StatusColorScales>;\n\nconst NAME = /^[\\w-]+$/;\n\nconst registry = new Map<string, LobeStatusPalette>();\nconst listeners = new Set<() => void>();\nlet revision = 0;\n\nexport const registerLobePalette = (name: string, palette: LobeStatusPalette) => {\n if (!NAME.test(name))\n throw new Error(`Invalid palette name \"${name}\": use letters, digits, _ or -`);\n registry.set(name, palette);\n revision++;\n for (const listener of listeners) listener();\n};\n\nexport const getPaletteRevision = () => revision;\n\nexport const subscribePalettes = (listener: () => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\n\nexport const isRegisteredPalette = (name?: string): name is string => !!name && registry.has(name);\n\nexport const resolveStatusScales = (name?: string): StatusColorScales =>\n isRegisteredPalette(name) ? { ...statusColorScales, ...registry.get(name) } : statusColorScales;\n"],"mappings":";;AAIA,MAAM,OAAO;AAEb,MAAM,2BAAW,IAAI,IAA+B;AACpD,MAAM,4BAAY,IAAI,IAAgB;AACtC,IAAI,WAAW;AAEf,MAAa,uBAAuB,MAAc,YAA+B;CAC/E,IAAI,CAAC,KAAK,KAAK,IAAI,GACjB,MAAM,IAAI,MAAM,yBAAyB,KAAK,+BAA+B;CAC/E,SAAS,IAAI,MAAM,OAAO;CAC1B;CACA,KAAK,MAAM,YAAY,WAAW,SAAS;AAC7C;AAEA,MAAa,2BAA2B;AAExC,MAAa,qBAAqB,aAAyB;CACzD,UAAU,IAAI,QAAQ;CACtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,MAAa,uBAAuB,SAAkC,CAAC,CAAC,QAAQ,SAAS,IAAI,IAAI;AAEjG,MAAa,uBAAuB,SAClC,oBAAoB,IAAI,IAAI;CAAE,GAAG;CAAmB,GAAG,SAAS,IAAI,IAAI;AAAE,IAAI"}
@@ -1,3 +1,4 @@
1
+ import gray from "../../color/colors/gray.mjs";
1
2
  import { colorScales } from "../../color/colors/index.mjs";
2
3
  import { primaryColors } from "../customTheme.mjs";
3
4
  import chroma from "chroma-js";
@@ -5,12 +6,26 @@ import chroma from "chroma-js";
5
6
  const HEX = /^#[\da-f]{6}$/i;
6
7
  const isCustomPrimaryColor = (value) => !!value && HEX.test(value);
7
8
  const ANCHOR = 9;
8
- const ANCHORED_STEPS = /* @__PURE__ */ new Set([
9
- 7,
10
- 8,
11
- 10
12
- ]);
9
+ const SHIFT_WEIGHT = [
10
+ 0,
11
+ 0,
12
+ 0,
13
+ 0,
14
+ 0,
15
+ .25,
16
+ .5,
17
+ .75,
18
+ 1,
19
+ 1,
20
+ 1,
21
+ .5,
22
+ 0
23
+ ];
24
+ const MIN_STEP_GAP = .015;
25
+ const LIGHTNESS_WEIGHT = 100;
13
26
  const MAX_CHROMA_RATIO = 2;
27
+ const DARK_SURFACE = gray.dark[1];
28
+ const MIN_DARK_CONTRAST = 4.5;
14
29
  const oklch = (color) => {
15
30
  const [l, c, h] = chroma(color).oklch();
16
31
  return {
@@ -23,17 +38,35 @@ const hueDistance = (a, b) => {
23
38
  const d = Math.abs(a - b) % 360;
24
39
  return d > 180 ? 360 - d : d;
25
40
  };
26
- const nearestPreset = (hue) => Object.keys(primaryColors).reduce((best, name) => hueDistance(oklch(primaryColors[name]).h, hue) < hueDistance(oklch(primaryColors[best]).h, hue) ? name : best);
41
+ const presetDistance = (name, target) => {
42
+ const preset = oklch(primaryColors[name]);
43
+ return hueDistance(preset.h, target.h) + LIGHTNESS_WEIGHT * Math.abs(preset.l - target.l);
44
+ };
45
+ const nearestPreset = (target) => Object.keys(primaryColors).reduce((best, name) => presetDistance(name, target) < presetDistance(best, target) ? name : best);
27
46
  const clamp = (value) => Math.min(1, Math.max(0, value));
28
- const retintSolid = (steps, target, hex) => {
47
+ const readableOnDark = (hex) => {
48
+ const { c, h, l } = oklch(hex);
49
+ let lightness = l;
50
+ let color = hex;
51
+ while (chroma.contrast(color, DARK_SURFACE) < MIN_DARK_CONTRAST && lightness < 1) {
52
+ lightness = Math.min(1, lightness + .005);
53
+ color = chroma.oklch(lightness, c, h).hex();
54
+ }
55
+ return color;
56
+ };
57
+ const orderLightness = (lightness, direction) => {
58
+ const ordered = [...lightness];
59
+ for (let i = 10; i < ordered.length; i++) ordered[i] = direction > 0 ? Math.max(ordered[i], ordered[i - 1] + MIN_STEP_GAP) : Math.min(ordered[i], ordered[i - 1] - MIN_STEP_GAP);
60
+ for (let i = 8; i >= 0; i--) ordered[i] = direction > 0 ? Math.min(ordered[i], ordered[i + 1] - MIN_STEP_GAP) : Math.max(ordered[i], ordered[i + 1] + MIN_STEP_GAP);
61
+ return ordered.map(clamp);
62
+ };
63
+ const retintSolid = (steps, target, hex, direction) => {
29
64
  const anchor = oklch(steps[ANCHOR]);
30
65
  const ratio = anchor.c > 0 ? Math.min(target.c / anchor.c, MAX_CHROMA_RATIO) : 0;
31
- return steps.map((step, i) => {
32
- if (i === ANCHOR) return hex;
33
- const { c, l } = oklch(step);
34
- const lightness = ANCHORED_STEPS.has(i) ? clamp(target.l + l - anchor.l) : l;
35
- return chroma.oklch(lightness, c * ratio, target.h).hex();
36
- });
66
+ const shift = target.l - anchor.l;
67
+ const source = steps.map(oklch);
68
+ const lightness = orderLightness(source.map(({ l }, i) => i === ANCHOR ? target.l : l + SHIFT_WEIGHT[i] * shift), direction);
69
+ return source.map(({ c }, i) => i === ANCHOR ? hex : chroma.oklch(lightness[i], c * ratio, target.h).hex());
37
70
  };
38
71
  const retintAlpha = (steps, solid, target) => {
39
72
  const anchor = oklch(solid[ANCHOR]);
@@ -50,11 +83,13 @@ const generatePrimaryScale = (color) => {
50
83
  const cached = cache.get(hex);
51
84
  if (cached) return cached;
52
85
  const target = oklch(hex);
53
- const preset = colorScales[nearestPreset(target.h)];
86
+ const preset = colorScales[nearestPreset(target)];
87
+ const darkHex = readableOnDark(hex);
88
+ const darkTarget = oklch(darkHex);
54
89
  const scale = {
55
- dark: retintSolid(preset.dark, target, hex),
56
- darkA: retintAlpha(preset.darkA, preset.dark, target),
57
- light: retintSolid(preset.light, target, hex),
90
+ dark: retintSolid(preset.dark, darkTarget, darkHex, 1),
91
+ darkA: retintAlpha(preset.darkA, preset.dark, darkTarget),
92
+ light: retintSolid(preset.light, target, hex, -1),
58
93
  lightA: retintAlpha(preset.lightA, preset.light, target)
59
94
  };
60
95
  cache.set(hex, scale);
@@ -1 +1 @@
1
- {"version":3,"file":"customPrimary.mjs","names":[],"sources":["../../../src/styles/theme/customPrimary.ts"],"sourcesContent":["import chroma from 'chroma-js';\n\nimport { colorScales } from '@/color/colors';\nimport type { ColorScaleItem } from '@/color/types';\n\nimport { type PrimaryColors, primaryColors } from '../customTheme';\n\nexport type CustomPrimaryColor = `#${string}`;\nexport type LobePrimaryColor = PrimaryColors | CustomPrimaryColor;\n\nconst HEX = /^#[\\da-f]{6}$/i;\n\nexport const isCustomPrimaryColor = (value?: string): value is CustomPrimaryColor =>\n !!value && HEX.test(value);\n\nconst ANCHOR = 9;\nconst ANCHORED_STEPS = new Set([7, 8, 10]);\nconst MAX_CHROMA_RATIO = 2;\n\nconst oklch = (color: string) => {\n const [l, c, h] = chroma(color).oklch();\n return { c, h: Number.isNaN(h) ? 0 : h, l };\n};\n\nconst hueDistance = (a: number, b: number) => {\n const d = Math.abs(a - b) % 360;\n return d > 180 ? 360 - d : d;\n};\n\nconst nearestPreset = (hue: number) =>\n (Object.keys(primaryColors) as PrimaryColors[]).reduce((best, name) =>\n hueDistance(oklch(primaryColors[name]).h, hue) < hueDistance(oklch(primaryColors[best]).h, hue)\n ? name\n : best,\n );\n\nconst clamp = (value: number) => Math.min(1, Math.max(0, value));\n\ntype Steps = ColorScaleItem['light'];\n\nconst retintSolid = (steps: Steps, target: ReturnType<typeof oklch>, hex: string): Steps => {\n const anchor = oklch(steps[ANCHOR]);\n const ratio = anchor.c > 0 ? Math.min(target.c / anchor.c, MAX_CHROMA_RATIO) : 0;\n\n return steps.map((step, i) => {\n if (i === ANCHOR) return hex;\n const { c, l } = oklch(step);\n const lightness = ANCHORED_STEPS.has(i) ? clamp(target.l + l - anchor.l) : l;\n return chroma.oklch(lightness, c * ratio, target.h).hex();\n }) as Steps;\n};\n\nconst retintAlpha = (steps: Steps, solid: Steps, target: ReturnType<typeof oklch>): Steps => {\n const anchor = oklch(solid[ANCHOR]);\n const ratio = anchor.c > 0 ? Math.min(target.c / anchor.c, MAX_CHROMA_RATIO) : 0;\n\n return steps.map((step) => {\n const color = chroma(step);\n const { c, l } = oklch(step);\n return chroma\n .oklch(l, c * ratio, target.h)\n .alpha(color.alpha())\n .css();\n }) as Steps;\n};\n\nconst cache = new Map<string, ColorScaleItem>();\n\nexport const generatePrimaryScale = (color: CustomPrimaryColor): ColorScaleItem => {\n const hex = color.toLowerCase();\n const cached = cache.get(hex);\n if (cached) return cached;\n\n const target = oklch(hex);\n const preset = colorScales[nearestPreset(target.h)];\n const scale: ColorScaleItem = {\n dark: retintSolid(preset.dark, target, hex),\n darkA: retintAlpha(preset.darkA, preset.dark, target),\n light: retintSolid(preset.light, target, hex),\n lightA: retintAlpha(preset.lightA, preset.light, target),\n };\n\n cache.set(hex, scale);\n return scale;\n};\n"],"mappings":";;;;AAUA,MAAM,MAAM;AAEZ,MAAa,wBAAwB,UACnC,CAAC,CAAC,SAAS,IAAI,KAAK,KAAK;AAE3B,MAAM,SAAS;AACf,MAAM,iCAAiB,IAAI,IAAI;CAAC;CAAG;CAAG;AAAE,CAAC;AACzC,MAAM,mBAAmB;AAEzB,MAAM,SAAS,UAAkB;CAC/B,MAAM,CAAC,GAAG,GAAG,KAAK,OAAO,KAAK,CAAC,CAAC,MAAM;CACtC,OAAO;EAAE;EAAG,GAAG,OAAO,MAAM,CAAC,IAAI,IAAI;EAAG;CAAE;AAC5C;AAEA,MAAM,eAAe,GAAW,MAAc;CAC5C,MAAM,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI;CAC5B,OAAO,IAAI,MAAM,MAAM,IAAI;AAC7B;AAEA,MAAM,iBAAiB,QACpB,OAAO,KAAK,aAAa,CAAC,CAAqB,QAAQ,MAAM,SAC5D,YAAY,MAAM,cAAc,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,YAAY,MAAM,cAAc,KAAK,CAAC,CAAC,GAAG,GAAG,IAC1F,OACA,IACN;AAEF,MAAM,SAAS,UAAkB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC;AAI/D,MAAM,eAAe,OAAc,QAAkC,QAAuB;CAC1F,MAAM,SAAS,MAAM,MAAM,OAAO;CAClC,MAAM,QAAQ,OAAO,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,OAAO,GAAG,gBAAgB,IAAI;CAE/E,OAAO,MAAM,KAAK,MAAM,MAAM;EAC5B,IAAI,MAAM,QAAQ,OAAO;EACzB,MAAM,EAAE,GAAG,MAAM,MAAM,IAAI;EAC3B,MAAM,YAAY,eAAe,IAAI,CAAC,IAAI,MAAM,OAAO,IAAI,IAAI,OAAO,CAAC,IAAI;EAC3E,OAAO,OAAO,MAAM,WAAW,IAAI,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI;CAC1D,CAAC;AACH;AAEA,MAAM,eAAe,OAAc,OAAc,WAA4C;CAC3F,MAAM,SAAS,MAAM,MAAM,OAAO;CAClC,MAAM,QAAQ,OAAO,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,OAAO,GAAG,gBAAgB,IAAI;CAE/E,OAAO,MAAM,KAAK,SAAS;EACzB,MAAM,QAAQ,OAAO,IAAI;EACzB,MAAM,EAAE,GAAG,MAAM,MAAM,IAAI;EAC3B,OAAO,OACJ,MAAM,GAAG,IAAI,OAAO,OAAO,CAAC,CAAC,CAC7B,MAAM,MAAM,MAAM,CAAC,CAAC,CACpB,IAAI;CACT,CAAC;AACH;AAEA,MAAM,wBAAQ,IAAI,IAA4B;AAE9C,MAAa,wBAAwB,UAA8C;CACjF,MAAM,MAAM,MAAM,YAAY;CAC9B,MAAM,SAAS,MAAM,IAAI,GAAG;CAC5B,IAAI,QAAQ,OAAO;CAEnB,MAAM,SAAS,MAAM,GAAG;CACxB,MAAM,SAAS,YAAY,cAAc,OAAO,CAAC;CACjD,MAAM,QAAwB;EAC5B,MAAM,YAAY,OAAO,MAAM,QAAQ,GAAG;EAC1C,OAAO,YAAY,OAAO,OAAO,OAAO,MAAM,MAAM;EACpD,OAAO,YAAY,OAAO,OAAO,QAAQ,GAAG;EAC5C,QAAQ,YAAY,OAAO,QAAQ,OAAO,OAAO,MAAM;CACzD;CAEA,MAAM,IAAI,KAAK,KAAK;CACpB,OAAO;AACT"}
1
+ {"version":3,"file":"customPrimary.mjs","names":[],"sources":["../../../src/styles/theme/customPrimary.ts"],"sourcesContent":["import chroma from 'chroma-js';\n\nimport { colorScales, gray } from '@/color/colors';\nimport type { ColorScaleItem } from '@/color/types';\n\nimport { type PrimaryColors, primaryColors } from '../customTheme';\n\nexport type CustomPrimaryColor = `#${string}`;\nexport type LobePrimaryColor = PrimaryColors | CustomPrimaryColor;\n\nconst HEX = /^#[\\da-f]{6}$/i;\n\nexport const isCustomPrimaryColor = (value?: string): value is CustomPrimaryColor =>\n !!value && HEX.test(value);\n\nconst ANCHOR = 9;\nconst SHIFT_WEIGHT = [0, 0, 0, 0, 0, 0.25, 0.5, 0.75, 1, 1, 1, 0.5, 0];\nconst MIN_STEP_GAP = 0.015;\nconst LIGHTNESS_WEIGHT = 100;\nconst MAX_CHROMA_RATIO = 2;\nconst DARK_SURFACE = gray.dark[1];\nconst MIN_DARK_CONTRAST = 4.5;\n\nconst oklch = (color: string) => {\n const [l, c, h] = chroma(color).oklch();\n return { c, h: Number.isNaN(h) ? 0 : h, l };\n};\n\nconst hueDistance = (a: number, b: number) => {\n const d = Math.abs(a - b) % 360;\n return d > 180 ? 360 - d : d;\n};\n\nconst presetDistance = (name: PrimaryColors, target: ReturnType<typeof oklch>) => {\n const preset = oklch(primaryColors[name]);\n return hueDistance(preset.h, target.h) + LIGHTNESS_WEIGHT * Math.abs(preset.l - target.l);\n};\n\nconst nearestPreset = (target: ReturnType<typeof oklch>) =>\n (Object.keys(primaryColors) as PrimaryColors[]).reduce((best, name) =>\n presetDistance(name, target) < presetDistance(best, target) ? name : best,\n );\n\nconst clamp = (value: number) => Math.min(1, Math.max(0, value));\n\nconst readableOnDark = (hex: string) => {\n const { c, h, l } = oklch(hex);\n let lightness = l;\n let color = hex;\n while (chroma.contrast(color, DARK_SURFACE) < MIN_DARK_CONTRAST && lightness < 1) {\n lightness = Math.min(1, lightness + 0.005);\n color = chroma.oklch(lightness, c, h).hex();\n }\n return color;\n};\n\nconst orderLightness = (lightness: number[], direction: 1 | -1) => {\n const ordered = [...lightness];\n for (let i = ANCHOR + 1; i < ordered.length; i++)\n ordered[i] =\n direction > 0\n ? Math.max(ordered[i], ordered[i - 1] + MIN_STEP_GAP)\n : Math.min(ordered[i], ordered[i - 1] - MIN_STEP_GAP);\n for (let i = ANCHOR - 1; i >= 0; i--)\n ordered[i] =\n direction > 0\n ? Math.min(ordered[i], ordered[i + 1] - MIN_STEP_GAP)\n : Math.max(ordered[i], ordered[i + 1] + MIN_STEP_GAP);\n return ordered.map(clamp);\n};\n\ntype Steps = ColorScaleItem['light'];\n\nconst retintSolid = (\n steps: Steps,\n target: ReturnType<typeof oklch>,\n hex: string,\n direction: 1 | -1,\n): Steps => {\n const anchor = oklch(steps[ANCHOR]);\n const ratio = anchor.c > 0 ? Math.min(target.c / anchor.c, MAX_CHROMA_RATIO) : 0;\n const shift = target.l - anchor.l;\n const source = steps.map(oklch);\n const lightness = orderLightness(\n source.map(({ l }, i) => (i === ANCHOR ? target.l : l + SHIFT_WEIGHT[i] * shift)),\n direction,\n );\n\n return source.map(({ c }, i) =>\n i === ANCHOR ? hex : chroma.oklch(lightness[i], c * ratio, target.h).hex(),\n ) as Steps;\n};\n\nconst retintAlpha = (steps: Steps, solid: Steps, target: ReturnType<typeof oklch>): Steps => {\n const anchor = oklch(solid[ANCHOR]);\n const ratio = anchor.c > 0 ? Math.min(target.c / anchor.c, MAX_CHROMA_RATIO) : 0;\n\n return steps.map((step) => {\n const color = chroma(step);\n const { c, l } = oklch(step);\n return chroma\n .oklch(l, c * ratio, target.h)\n .alpha(color.alpha())\n .css();\n }) as Steps;\n};\n\nconst cache = new Map<string, ColorScaleItem>();\n\nexport const generatePrimaryScale = (color: CustomPrimaryColor): ColorScaleItem => {\n const hex = color.toLowerCase();\n const cached = cache.get(hex);\n if (cached) return cached;\n\n const target = oklch(hex);\n const preset = colorScales[nearestPreset(target)];\n const darkHex = readableOnDark(hex);\n const darkTarget = oklch(darkHex);\n const scale: ColorScaleItem = {\n dark: retintSolid(preset.dark, darkTarget, darkHex, 1),\n darkA: retintAlpha(preset.darkA, preset.dark, darkTarget),\n light: retintSolid(preset.light, target, hex, -1),\n lightA: retintAlpha(preset.lightA, preset.light, target),\n };\n\n cache.set(hex, scale);\n return scale;\n};\n"],"mappings":"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"}
@@ -7,6 +7,7 @@ export type LobeAppearance = 'light' | 'dark';
7
7
  export interface LobeThemeState {
8
8
  appearance: LobeAppearance;
9
9
  neutralColor?: NeutralColors;
10
+ palette?: string;
10
11
  primaryColor?: LobePrimaryColor;
11
12
  }
12
13
  export declare const setLobeTheme: (state: Partial<LobeThemeState>, root?: HTMLElement) => void;
@@ -15,7 +16,7 @@ export interface ThemeScopeProps extends Partial<LobeThemeState> {
15
16
  className?: string;
16
17
  style?: CSSProperties;
17
18
  }
18
- export declare const ThemeScope: ({ appearance, children, className, neutralColor, primaryColor, style }: ThemeScopeProps) => import("react").JSX.Element;
19
+ export declare const ThemeScope: ({ appearance, children, className, neutralColor, palette, primaryColor, style }: ThemeScopeProps) => import("react").JSX.Element;
19
20
  export declare const useThemeMode: () => {
20
21
  appearance: LobeAppearance;
21
22
  isDarkMode: boolean;
@@ -41,9 +42,10 @@ export interface LobeThemeScriptProps {
41
42
  appearance?: LobeAppearance | 'system';
42
43
  neutralColor?: NeutralColors;
43
44
  nonce?: string;
45
+ palette?: string;
44
46
  primaryColor?: LobePrimaryColor;
45
47
  }
46
- export declare const LobeThemeScript: ({ appearance, neutralColor, nonce, primaryColor }: LobeThemeScriptProps) => import("react").JSX.Element;
48
+ export declare const LobeThemeScript: ({ appearance, neutralColor, nonce, palette, primaryColor }: LobeThemeScriptProps) => import("react").JSX.Element;
47
49
  //#endregion
48
50
  export {};
49
51
  //# sourceMappingURL=scope.d.mts.map
@@ -1,18 +1,21 @@
1
1
  "use client";
2
+ import { getPaletteRevision, isRegisteredPalette, subscribePalettes } from "./customPalette.mjs";
2
3
  import { isCustomPrimaryColor } from "./customPrimary.mjs";
3
4
  import { staticToken } from "./token/static.mjs";
4
5
  import { createLobeToken } from "./createLobeToken.mjs";
5
- import { getCustomPrimaryCss } from "./themeCss.mjs";
6
+ import { getCustomPaletteCss, getCustomPrimaryCss } from "./themeCss.mjs";
6
7
  import { createContext, use, useMemo, useSyncExternalStore } from "react";
7
8
  import { jsx, jsxs } from "react/jsx-runtime";
8
9
  //#region src/styles/theme/scope.tsx
9
10
  const ATTRIBUTES = [
10
11
  "data-theme",
11
12
  "data-primary-color",
12
- "data-neutral-color"
13
+ "data-neutral-color",
14
+ "data-palette"
13
15
  ];
14
- const toAttributes = ({ appearance, neutralColor, primaryColor }) => ({
16
+ const toAttributes = ({ appearance, neutralColor, palette, primaryColor }) => ({
15
17
  "data-neutral-color": neutralColor,
18
+ "data-palette": palette,
16
19
  "data-primary-color": primaryColor,
17
20
  "data-theme": appearance
18
21
  });
@@ -26,6 +29,18 @@ const ensureCustomPrimaryStyle = (color, doc) => {
26
29
  style.textContent = getCustomPrimaryCss(color);
27
30
  doc.head.append(style);
28
31
  };
32
+ const paletteStyleId = (name) => `lobe-palette-${name}`;
33
+ const ensurePaletteStyle = (name, doc) => {
34
+ const id = paletteStyleId(name);
35
+ let style = doc.getElementById(id);
36
+ if (!style) {
37
+ style = doc.createElement("style");
38
+ style.id = id;
39
+ doc.head.append(style);
40
+ }
41
+ const css = getCustomPaletteCss(name);
42
+ if (style.textContent !== css) style.textContent = css;
43
+ };
29
44
  const setLobeTheme = (state, root = document.documentElement) => {
30
45
  const next = {
31
46
  ...readThemeState(root),
@@ -33,15 +48,18 @@ const setLobeTheme = (state, root = document.documentElement) => {
33
48
  };
34
49
  next.primaryColor = normalizePrimary(next.primaryColor);
35
50
  if (isCustomPrimaryColor(next.primaryColor)) ensureCustomPrimaryStyle(next.primaryColor, root.ownerDocument);
51
+ if (isRegisteredPalette(next.palette)) ensurePaletteStyle(next.palette, root.ownerDocument);
36
52
  for (const [name, value] of Object.entries(toAttributes(next))) if (value) root.setAttribute(name, value);
37
53
  else root.removeAttribute(name);
38
54
  };
39
55
  const readThemeState = (el) => ({
40
56
  appearance: el.dataset.theme === "dark" ? "dark" : "light",
41
57
  neutralColor: el.dataset.neutralColor || void 0,
58
+ palette: el.dataset.palette || void 0,
42
59
  primaryColor: el.dataset.primaryColor || void 0
43
60
  });
44
- const stateKey = (state) => `${state.appearance}|${state.primaryColor ?? ""}|${state.neutralColor ?? ""}`;
61
+ const stateKey = (state) => `${state.appearance}|${state.primaryColor ?? ""}|${state.neutralColor ?? ""}|${state.palette ?? ""}`;
62
+ const usePaletteRevision = () => useSyncExternalStore(subscribePalettes, getPaletteRevision, getPaletteRevision);
45
63
  const SERVER_STATE = { appearance: "light" };
46
64
  let rootSnapshot = SERVER_STATE;
47
65
  const getRootSnapshot = () => {
@@ -63,31 +81,43 @@ const useThemeState = () => {
63
81
  const root = useSyncExternalStore(subscribeRoot, getRootSnapshot, () => SERVER_STATE);
64
82
  return scoped ?? root;
65
83
  };
66
- const ThemeScope = ({ appearance, children, className, neutralColor, primaryColor, style }) => {
84
+ const ThemeScope = ({ appearance, children, className, neutralColor, palette, primaryColor, style }) => {
67
85
  const parent = useThemeState();
68
86
  const state = useMemo(() => ({
69
87
  appearance: appearance ?? parent.appearance,
70
88
  neutralColor: neutralColor ?? parent.neutralColor,
89
+ palette: palette ?? parent.palette,
71
90
  primaryColor: normalizePrimary(primaryColor) ?? parent.primaryColor
72
91
  }), [
73
92
  appearance,
74
93
  neutralColor,
94
+ palette,
75
95
  primaryColor,
76
96
  parent
77
97
  ]);
78
98
  const customPrimary = isCustomPrimaryColor(state.primaryColor) ? state.primaryColor : void 0;
99
+ const paletteRevision = usePaletteRevision();
100
+ const customPalette = isRegisteredPalette(state.palette) ? state.palette : void 0;
79
101
  return /* @__PURE__ */ jsxs(ThemeScopeContext, {
80
102
  value: state,
81
- children: [customPrimary && /* @__PURE__ */ jsx("style", {
82
- href: customPrimaryStyleId(customPrimary),
83
- precedence: "lobe-theme",
84
- children: getCustomPrimaryCss(customPrimary)
85
- }), /* @__PURE__ */ jsx("div", {
86
- className,
87
- style,
88
- ...toAttributes(state),
89
- children
90
- })]
103
+ children: [
104
+ customPrimary && /* @__PURE__ */ jsx("style", {
105
+ href: customPrimaryStyleId(customPrimary),
106
+ precedence: "lobe-theme",
107
+ children: getCustomPrimaryCss(customPrimary)
108
+ }),
109
+ customPalette && /* @__PURE__ */ jsx("style", {
110
+ href: `${paletteStyleId(customPalette)}-${paletteRevision}`,
111
+ precedence: "lobe-theme",
112
+ children: getCustomPaletteCss(customPalette)
113
+ }),
114
+ /* @__PURE__ */ jsx("div", {
115
+ className,
116
+ style,
117
+ ...toAttributes(state),
118
+ children
119
+ })
120
+ ]
91
121
  });
92
122
  };
93
123
  const useThemeMode = () => {
@@ -100,7 +130,7 @@ const useThemeMode = () => {
100
130
  const themeCache = /* @__PURE__ */ new Map();
101
131
  const useTheme = () => {
102
132
  const state = useThemeState();
103
- const key = stateKey(state);
133
+ const key = `${stateKey(state)}@${usePaletteRevision()}`;
104
134
  let theme = themeCache.get(key);
105
135
  if (!theme) {
106
136
  theme = {
@@ -151,14 +181,17 @@ const subscribeResponsive = (onChange) => {
151
181
  };
152
182
  };
153
183
  const useResponsive = () => useSyncExternalStore(subscribeResponsive, getResponsiveSnapshot, () => SERVER_RESPONSIVE);
154
- const LobeThemeScript = ({ appearance, neutralColor, nonce, primaryColor }) => {
184
+ const LobeThemeScript = ({ appearance, neutralColor, nonce, palette, primaryColor }) => {
155
185
  const primary = normalizePrimary(primaryColor);
156
- const custom = isCustomPrimaryColor(primary) ? [customPrimaryStyleId(primary), getCustomPrimaryCss(primary)] : [null, null];
157
- const script = `(function(a,p,n,i,c){var d=document.documentElement;if(a==='system')a=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';if(a)d.setAttribute('data-theme',a);else if(!d.hasAttribute('data-theme'))d.setAttribute('data-theme','light');if(p)d.setAttribute('data-primary-color',p);if(n)d.setAttribute('data-neutral-color',n);if(c&&!document.getElementById(i)){var s=document.createElement('style');s.id=i;s.textContent=c;document.head.appendChild(s);}}).apply(null,${JSON.stringify([
186
+ const styles = [];
187
+ if (isCustomPrimaryColor(primary)) styles.push([customPrimaryStyleId(primary), getCustomPrimaryCss(primary)]);
188
+ if (isRegisteredPalette(palette)) styles.push([paletteStyleId(palette), getCustomPaletteCss(palette)]);
189
+ const script = `(function(a,p,n,q,t){var d=document.documentElement;if(a==='system')a=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';if(a)d.setAttribute('data-theme',a);else if(!d.hasAttribute('data-theme'))d.setAttribute('data-theme','light');if(p)d.setAttribute('data-primary-color',p);if(n)d.setAttribute('data-neutral-color',n);if(q)d.setAttribute('data-palette',q);t.forEach(function(x){if(document.getElementById(x[0]))return;var s=document.createElement('style');s.id=x[0];s.textContent=x[1];document.head.appendChild(s);});}).apply(null,${JSON.stringify([
158
190
  appearance ?? null,
159
191
  primary ?? null,
160
192
  neutralColor ?? null,
161
- ...custom
193
+ palette ?? null,
194
+ styles
162
195
  ])})`;
163
196
  return /* @__PURE__ */ jsx("script", {
164
197
  suppressHydrationWarning: true,
@@ -1 +1 @@
1
- {"version":3,"file":"scope.mjs","names":[],"sources":["../../../src/styles/theme/scope.tsx"],"sourcesContent":["'use client';\n\nimport {\n createContext,\n type CSSProperties,\n type ReactNode,\n use,\n useMemo,\n useSyncExternalStore,\n} from 'react';\n\nimport type { NeutralColors } from '../customTheme';\nimport { createLobeToken, type LobeToken } from './createLobeToken';\nimport {\n type CustomPrimaryColor,\n isCustomPrimaryColor,\n type LobePrimaryColor,\n} from './customPrimary';\nimport { getCustomPrimaryCss } from './themeCss';\nimport { staticToken } from './token/static';\n\nexport type LobeAppearance = 'light' | 'dark';\n\nexport interface LobeThemeState {\n appearance: LobeAppearance;\n neutralColor?: NeutralColors;\n primaryColor?: LobePrimaryColor;\n}\n\nconst ATTRIBUTES = ['data-theme', 'data-primary-color', 'data-neutral-color'];\n\nconst toAttributes = ({ appearance, neutralColor, primaryColor }: LobeThemeState) => ({\n 'data-neutral-color': neutralColor,\n 'data-primary-color': primaryColor,\n 'data-theme': appearance,\n});\n\nconst normalizePrimary = (color?: LobePrimaryColor) =>\n isCustomPrimaryColor(color) ? (color.toLowerCase() as CustomPrimaryColor) : color;\n\nconst customPrimaryStyleId = (color: CustomPrimaryColor) => `lobe-primary-${color.slice(1)}`;\n\nconst ensureCustomPrimaryStyle = (color: CustomPrimaryColor, doc: Document) => {\n const id = customPrimaryStyleId(color);\n if (doc.getElementById(id)) return;\n const style = doc.createElement('style');\n style.id = id;\n style.textContent = getCustomPrimaryCss(color);\n doc.head.append(style);\n};\n\nexport const setLobeTheme = (\n state: Partial<LobeThemeState>,\n root: HTMLElement = document.documentElement,\n) => {\n const next = { ...readThemeState(root), ...state };\n next.primaryColor = normalizePrimary(next.primaryColor);\n if (isCustomPrimaryColor(next.primaryColor))\n ensureCustomPrimaryStyle(next.primaryColor, root.ownerDocument);\n for (const [name, value] of Object.entries(toAttributes(next))) {\n if (value) root.setAttribute(name, value);\n else root.removeAttribute(name);\n }\n};\n\nconst readThemeState = (el: HTMLElement): LobeThemeState => ({\n appearance: el.dataset.theme === 'dark' ? 'dark' : 'light',\n neutralColor: (el.dataset.neutralColor as NeutralColors) || undefined,\n primaryColor: (el.dataset.primaryColor as LobePrimaryColor) || undefined,\n});\n\nconst stateKey = (state: LobeThemeState) =>\n `${state.appearance}|${state.primaryColor ?? ''}|${state.neutralColor ?? ''}`;\n\nconst SERVER_STATE: LobeThemeState = { appearance: 'light' };\nlet rootSnapshot: LobeThemeState = SERVER_STATE;\n\nconst getRootSnapshot = () => {\n const next = readThemeState(document.documentElement);\n if (stateKey(next) !== stateKey(rootSnapshot)) rootSnapshot = next;\n return rootSnapshot;\n};\n\nconst subscribeRoot = (onChange: () => void) => {\n const observer = new MutationObserver(onChange);\n observer.observe(document.documentElement, { attributeFilter: ATTRIBUTES, attributes: true });\n return () => observer.disconnect();\n};\n\nconst ThemeScopeContext = createContext<LobeThemeState | null>(null);\n\nconst useThemeState = () => {\n const scoped = use(ThemeScopeContext);\n const root = useSyncExternalStore(subscribeRoot, getRootSnapshot, () => SERVER_STATE);\n return scoped ?? root;\n};\n\nexport interface ThemeScopeProps extends Partial<LobeThemeState> {\n children?: ReactNode;\n className?: string;\n style?: CSSProperties;\n}\n\nexport const ThemeScope = ({\n appearance,\n children,\n className,\n neutralColor,\n primaryColor,\n style,\n}: ThemeScopeProps) => {\n const parent = useThemeState();\n const state = useMemo<LobeThemeState>(\n () => ({\n appearance: appearance ?? parent.appearance,\n neutralColor: neutralColor ?? parent.neutralColor,\n primaryColor: normalizePrimary(primaryColor) ?? parent.primaryColor,\n }),\n [appearance, neutralColor, primaryColor, parent],\n );\n const customPrimary = isCustomPrimaryColor(state.primaryColor) ? state.primaryColor : undefined;\n\n return (\n <ThemeScopeContext value={state}>\n {customPrimary && (\n <style href={customPrimaryStyleId(customPrimary)} precedence=\"lobe-theme\">\n {getCustomPrimaryCss(customPrimary)}\n </style>\n )}\n <div className={className} style={style} {...toAttributes(state)}>\n {children}\n </div>\n </ThemeScopeContext>\n );\n};\n\nexport const useThemeMode = () => {\n const { appearance } = useThemeState();\n return useMemo(() => ({ appearance, isDarkMode: appearance === 'dark' }), [appearance]);\n};\n\nexport type LobeTheme = LobeToken & { appearance: LobeAppearance; isDarkMode: boolean };\n\nconst themeCache = new Map<string, LobeTheme>();\n\nexport const useTheme = (): LobeTheme => {\n const state = useThemeState();\n const key = stateKey(state);\n let theme = themeCache.get(key);\n if (!theme) {\n theme = {\n ...createLobeToken(state),\n appearance: state.appearance,\n isDarkMode: state.appearance === 'dark',\n };\n themeCache.set(key, theme);\n }\n return theme;\n};\n\nconst breakpointQueries = {\n lg: `(min-width: ${staticToken.screenLG}px)`,\n md: `(min-width: ${staticToken.screenMD}px)`,\n sm: `(min-width: ${staticToken.screenSM}px)`,\n xl: `(min-width: ${staticToken.screenXL}px)`,\n xs: `(max-width: ${staticToken.screenXSMax}px)`,\n xxl: `(min-width: ${staticToken.screenXXL}px)`,\n xxxl: `(min-width: ${staticToken.screenXXXL}px)`,\n};\n\ntype Breakpoint = keyof typeof breakpointQueries;\nexport type ResponsiveState = Record<\n Breakpoint | 'mobile' | 'tablet' | 'laptop' | 'desktop',\n boolean\n>;\n\nconst toResponsive = (matches: Record<Breakpoint, boolean>): ResponsiveState => ({\n ...matches,\n desktop: matches.xxl,\n laptop: matches.lg,\n mobile: matches.xs,\n tablet: matches.md,\n});\n\nconst SERVER_RESPONSIVE = toResponsive({\n lg: false,\n md: false,\n sm: false,\n xl: false,\n xs: false,\n xxl: false,\n xxxl: false,\n});\nlet responsiveSnapshot = SERVER_RESPONSIVE;\n\nconst getResponsiveSnapshot = () => {\n const matches = Object.fromEntries(\n Object.entries(breakpointQueries).map(([key, query]) => [key, matchMedia(query).matches]),\n ) as Record<Breakpoint, boolean>;\n const changed = (Object.keys(matches) as Breakpoint[]).some(\n (key) => matches[key] !== responsiveSnapshot[key],\n );\n if (changed) responsiveSnapshot = toResponsive(matches);\n return responsiveSnapshot;\n};\n\nconst subscribeResponsive = (onChange: () => void) => {\n const lists = Object.values(breakpointQueries).map((query) => matchMedia(query));\n for (const list of lists) list.addEventListener('change', onChange);\n return () => {\n for (const list of lists) list.removeEventListener('change', onChange);\n };\n};\n\nexport const useResponsive = () =>\n useSyncExternalStore(subscribeResponsive, getResponsiveSnapshot, () => SERVER_RESPONSIVE);\n\nexport interface LobeThemeScriptProps {\n appearance?: LobeAppearance | 'system';\n neutralColor?: NeutralColors;\n nonce?: string;\n primaryColor?: LobePrimaryColor;\n}\n\nexport const LobeThemeScript = ({\n appearance,\n neutralColor,\n nonce,\n primaryColor,\n}: LobeThemeScriptProps) => {\n const primary = normalizePrimary(primaryColor);\n const custom = isCustomPrimaryColor(primary)\n ? [customPrimaryStyleId(primary), getCustomPrimaryCss(primary)]\n : [null, null];\n const args = JSON.stringify([\n appearance ?? null,\n primary ?? null,\n neutralColor ?? null,\n ...custom,\n ]);\n const script = `(function(a,p,n,i,c){var d=document.documentElement;if(a==='system')a=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';if(a)d.setAttribute('data-theme',a);else if(!d.hasAttribute('data-theme'))d.setAttribute('data-theme','light');if(p)d.setAttribute('data-primary-color',p);if(n)d.setAttribute('data-neutral-color',n);if(c&&!document.getElementById(i)){var s=document.createElement('style');s.id=i;s.textContent=c;document.head.appendChild(s);}}).apply(null,${args})`;\n\n return (\n <script suppressHydrationWarning dangerouslySetInnerHTML={{ __html: script }} nonce={nonce} />\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"scope.mjs","names":[],"sources":["../../../src/styles/theme/scope.tsx"],"sourcesContent":["'use client';\n\nimport {\n createContext,\n type CSSProperties,\n type ReactNode,\n use,\n useMemo,\n useSyncExternalStore,\n} from 'react';\n\nimport type { NeutralColors } from '../customTheme';\nimport { createLobeToken, type LobeToken } from './createLobeToken';\nimport { getPaletteRevision, isRegisteredPalette, subscribePalettes } from './customPalette';\nimport {\n type CustomPrimaryColor,\n isCustomPrimaryColor,\n type LobePrimaryColor,\n} from './customPrimary';\nimport { getCustomPaletteCss, getCustomPrimaryCss } from './themeCss';\nimport { staticToken } from './token/static';\n\nexport type LobeAppearance = 'light' | 'dark';\n\nexport interface LobeThemeState {\n appearance: LobeAppearance;\n neutralColor?: NeutralColors;\n palette?: string;\n primaryColor?: LobePrimaryColor;\n}\n\nconst ATTRIBUTES = ['data-theme', 'data-primary-color', 'data-neutral-color', 'data-palette'];\n\nconst toAttributes = ({ appearance, neutralColor, palette, primaryColor }: LobeThemeState) => ({\n 'data-neutral-color': neutralColor,\n 'data-palette': palette,\n 'data-primary-color': primaryColor,\n 'data-theme': appearance,\n});\n\nconst normalizePrimary = (color?: LobePrimaryColor) =>\n isCustomPrimaryColor(color) ? (color.toLowerCase() as CustomPrimaryColor) : color;\n\nconst customPrimaryStyleId = (color: CustomPrimaryColor) => `lobe-primary-${color.slice(1)}`;\n\nconst ensureCustomPrimaryStyle = (color: CustomPrimaryColor, doc: Document) => {\n const id = customPrimaryStyleId(color);\n if (doc.getElementById(id)) return;\n const style = doc.createElement('style');\n style.id = id;\n style.textContent = getCustomPrimaryCss(color);\n doc.head.append(style);\n};\n\nconst paletteStyleId = (name: string) => `lobe-palette-${name}`;\n\nconst ensurePaletteStyle = (name: string, doc: Document) => {\n const id = paletteStyleId(name);\n let style = doc.getElementById(id);\n if (!style) {\n style = doc.createElement('style');\n style.id = id;\n doc.head.append(style);\n }\n const css = getCustomPaletteCss(name);\n if (style.textContent !== css) style.textContent = css;\n};\n\nexport const setLobeTheme = (\n state: Partial<LobeThemeState>,\n root: HTMLElement = document.documentElement,\n) => {\n const next = { ...readThemeState(root), ...state };\n next.primaryColor = normalizePrimary(next.primaryColor);\n if (isCustomPrimaryColor(next.primaryColor))\n ensureCustomPrimaryStyle(next.primaryColor, root.ownerDocument);\n if (isRegisteredPalette(next.palette)) ensurePaletteStyle(next.palette, root.ownerDocument);\n for (const [name, value] of Object.entries(toAttributes(next))) {\n if (value) root.setAttribute(name, value);\n else root.removeAttribute(name);\n }\n};\n\nconst readThemeState = (el: HTMLElement): LobeThemeState => ({\n appearance: el.dataset.theme === 'dark' ? 'dark' : 'light',\n neutralColor: (el.dataset.neutralColor as NeutralColors) || undefined,\n palette: el.dataset.palette || undefined,\n primaryColor: (el.dataset.primaryColor as LobePrimaryColor) || undefined,\n});\n\nconst stateKey = (state: LobeThemeState) =>\n `${state.appearance}|${state.primaryColor ?? ''}|${state.neutralColor ?? ''}|${state.palette ?? ''}`;\n\nconst usePaletteRevision = () =>\n useSyncExternalStore(subscribePalettes, getPaletteRevision, getPaletteRevision);\n\nconst SERVER_STATE: LobeThemeState = { appearance: 'light' };\nlet rootSnapshot: LobeThemeState = SERVER_STATE;\n\nconst getRootSnapshot = () => {\n const next = readThemeState(document.documentElement);\n if (stateKey(next) !== stateKey(rootSnapshot)) rootSnapshot = next;\n return rootSnapshot;\n};\n\nconst subscribeRoot = (onChange: () => void) => {\n const observer = new MutationObserver(onChange);\n observer.observe(document.documentElement, { attributeFilter: ATTRIBUTES, attributes: true });\n return () => observer.disconnect();\n};\n\nconst ThemeScopeContext = createContext<LobeThemeState | null>(null);\n\nconst useThemeState = () => {\n const scoped = use(ThemeScopeContext);\n const root = useSyncExternalStore(subscribeRoot, getRootSnapshot, () => SERVER_STATE);\n return scoped ?? root;\n};\n\nexport interface ThemeScopeProps extends Partial<LobeThemeState> {\n children?: ReactNode;\n className?: string;\n style?: CSSProperties;\n}\n\nexport const ThemeScope = ({\n appearance,\n children,\n className,\n neutralColor,\n palette,\n primaryColor,\n style,\n}: ThemeScopeProps) => {\n const parent = useThemeState();\n const state = useMemo<LobeThemeState>(\n () => ({\n appearance: appearance ?? parent.appearance,\n neutralColor: neutralColor ?? parent.neutralColor,\n palette: palette ?? parent.palette,\n primaryColor: normalizePrimary(primaryColor) ?? parent.primaryColor,\n }),\n [appearance, neutralColor, palette, primaryColor, parent],\n );\n const customPrimary = isCustomPrimaryColor(state.primaryColor) ? state.primaryColor : undefined;\n const paletteRevision = usePaletteRevision();\n const customPalette = isRegisteredPalette(state.palette) ? state.palette : undefined;\n\n return (\n <ThemeScopeContext value={state}>\n {customPrimary && (\n <style href={customPrimaryStyleId(customPrimary)} precedence=\"lobe-theme\">\n {getCustomPrimaryCss(customPrimary)}\n </style>\n )}\n {customPalette && (\n <style href={`${paletteStyleId(customPalette)}-${paletteRevision}`} precedence=\"lobe-theme\">\n {getCustomPaletteCss(customPalette)}\n </style>\n )}\n <div className={className} style={style} {...toAttributes(state)}>\n {children}\n </div>\n </ThemeScopeContext>\n );\n};\n\nexport const useThemeMode = () => {\n const { appearance } = useThemeState();\n return useMemo(() => ({ appearance, isDarkMode: appearance === 'dark' }), [appearance]);\n};\n\nexport type LobeTheme = LobeToken & { appearance: LobeAppearance; isDarkMode: boolean };\n\nconst themeCache = new Map<string, LobeTheme>();\n\nexport const useTheme = (): LobeTheme => {\n const state = useThemeState();\n const key = `${stateKey(state)}@${usePaletteRevision()}`;\n let theme = themeCache.get(key);\n if (!theme) {\n theme = {\n ...createLobeToken(state),\n appearance: state.appearance,\n isDarkMode: state.appearance === 'dark',\n };\n themeCache.set(key, theme);\n }\n return theme;\n};\n\nconst breakpointQueries = {\n lg: `(min-width: ${staticToken.screenLG}px)`,\n md: `(min-width: ${staticToken.screenMD}px)`,\n sm: `(min-width: ${staticToken.screenSM}px)`,\n xl: `(min-width: ${staticToken.screenXL}px)`,\n xs: `(max-width: ${staticToken.screenXSMax}px)`,\n xxl: `(min-width: ${staticToken.screenXXL}px)`,\n xxxl: `(min-width: ${staticToken.screenXXXL}px)`,\n};\n\ntype Breakpoint = keyof typeof breakpointQueries;\nexport type ResponsiveState = Record<\n Breakpoint | 'mobile' | 'tablet' | 'laptop' | 'desktop',\n boolean\n>;\n\nconst toResponsive = (matches: Record<Breakpoint, boolean>): ResponsiveState => ({\n ...matches,\n desktop: matches.xxl,\n laptop: matches.lg,\n mobile: matches.xs,\n tablet: matches.md,\n});\n\nconst SERVER_RESPONSIVE = toResponsive({\n lg: false,\n md: false,\n sm: false,\n xl: false,\n xs: false,\n xxl: false,\n xxxl: false,\n});\nlet responsiveSnapshot = SERVER_RESPONSIVE;\n\nconst getResponsiveSnapshot = () => {\n const matches = Object.fromEntries(\n Object.entries(breakpointQueries).map(([key, query]) => [key, matchMedia(query).matches]),\n ) as Record<Breakpoint, boolean>;\n const changed = (Object.keys(matches) as Breakpoint[]).some(\n (key) => matches[key] !== responsiveSnapshot[key],\n );\n if (changed) responsiveSnapshot = toResponsive(matches);\n return responsiveSnapshot;\n};\n\nconst subscribeResponsive = (onChange: () => void) => {\n const lists = Object.values(breakpointQueries).map((query) => matchMedia(query));\n for (const list of lists) list.addEventListener('change', onChange);\n return () => {\n for (const list of lists) list.removeEventListener('change', onChange);\n };\n};\n\nexport const useResponsive = () =>\n useSyncExternalStore(subscribeResponsive, getResponsiveSnapshot, () => SERVER_RESPONSIVE);\n\nexport interface LobeThemeScriptProps {\n appearance?: LobeAppearance | 'system';\n neutralColor?: NeutralColors;\n nonce?: string;\n palette?: string;\n primaryColor?: LobePrimaryColor;\n}\n\nexport const LobeThemeScript = ({\n appearance,\n neutralColor,\n nonce,\n palette,\n primaryColor,\n}: LobeThemeScriptProps) => {\n const primary = normalizePrimary(primaryColor);\n const styles: [string, string][] = [];\n if (isCustomPrimaryColor(primary))\n styles.push([customPrimaryStyleId(primary), getCustomPrimaryCss(primary)]);\n if (isRegisteredPalette(palette))\n styles.push([paletteStyleId(palette), getCustomPaletteCss(palette)]);\n const args = JSON.stringify([\n appearance ?? null,\n primary ?? null,\n neutralColor ?? null,\n palette ?? null,\n styles,\n ]);\n const script = `(function(a,p,n,q,t){var d=document.documentElement;if(a==='system')a=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';if(a)d.setAttribute('data-theme',a);else if(!d.hasAttribute('data-theme'))d.setAttribute('data-theme','light');if(p)d.setAttribute('data-primary-color',p);if(n)d.setAttribute('data-neutral-color',n);if(q)d.setAttribute('data-palette',q);t.forEach(function(x){if(document.getElementById(x[0]))return;var s=document.createElement('style');s.id=x[0];s.textContent=x[1];document.head.appendChild(s);});}).apply(null,${args})`;\n\n return (\n <script suppressHydrationWarning dangerouslySetInnerHTML={{ __html: script }} nonce={nonce} />\n );\n};\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { CustomPrimaryColor } from "./customPrimary.mjs";
2
2
  //#region src/styles/theme/themeCss.d.ts
3
3
  export declare const getCustomPrimaryCss: (color: CustomPrimaryColor) => string;
4
+ export declare const getCustomPaletteCss: (name: string) => string;
4
5
  export declare const getThemeCss: () => string;
5
6
  export declare const getGlobalCss: () => string;
6
7
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { isRegisteredPalette } from "./customPalette.mjs";
1
2
  import { neutralColors, primaryColors } from "../customTheme.mjs";
2
3
  import { createLobeTokenGroups } from "./createLobeToken.mjs";
3
4
  import { toCssVarName, toCssVariables } from "../css.mjs";
@@ -56,6 +57,20 @@ const getCustomPrimaryCss = (color) => {
56
57
  primaryColor: hex
57
58
  }).primary))).join("\n\n");
58
59
  };
60
+ const getCustomPaletteCss = (name) => {
61
+ if (!isRegisteredPalette(name)) return "";
62
+ return ["light", "dark"].map((appearance) => {
63
+ const { neutral, palette } = createLobeTokenGroups({
64
+ appearance,
65
+ palette: name
66
+ });
67
+ return rule(`[data-palette='${name}']${appearanceSelector(appearance)}`, toCssVariables({
68
+ ...palette,
69
+ colorErrorOutline: neutral.colorErrorOutline,
70
+ colorWarningOutline: neutral.colorWarningOutline
71
+ }));
72
+ }).join("\n\n");
73
+ };
59
74
  const essentialCss = `@layer lobe-ui {
60
75
  .lobe-brand-loading path {
61
76
  fill: currentcolor;
@@ -335,6 +350,6 @@ const getThemeCss = () => cached ??= [
335
350
  ].join("\n\n");
336
351
  const getGlobalCss = () => `${layerOrder}\n\n${globalCss}`;
337
352
  //#endregion
338
- export { getCustomPrimaryCss, getGlobalCss, getThemeCss };
353
+ export { getCustomPaletteCss, getCustomPrimaryCss, getGlobalCss, getThemeCss };
339
354
 
340
355
  //# sourceMappingURL=themeCss.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"themeCss.mjs","names":[],"sources":["../../../src/styles/theme/themeCss.ts"],"sourcesContent":["import { toCssVariables, toCssVarName } from '../css';\nimport { neutralColors, primaryColors } from '../customTheme';\nimport { createLobeTokenGroups } from './createLobeToken';\nimport type { CustomPrimaryColor } from './customPrimary';\nimport type { LobeAppearance } from './scope';\n\nconst v = (key: string) => `var(${toCssVarName(key)})`;\n\nconst ring: Record<LobeAppearance, string> = {\n dark: '0 0 0 1px rgb(255 255 255 / 18%)',\n light: '0 0 0 1px rgb(0 0 0 / 5%)',\n};\n\n/* `initial` makes a light scope nested in a dark one fall back to each variant's own fill\n instead of inheriting the dark table surface. */\nconst surface: Record<LobeAppearance, Record<string, string>> = {\n dark: {\n '--lobe-fill-border': v('colorFillSecondary'),\n '--lobe-fill-border-strong': v('colorFill'),\n '--lobe-table-cell-bg': 'transparent',\n '--lobe-table-surface': v('colorFillQuaternary'),\n },\n light: {\n '--lobe-fill-border': v('colorFill'),\n '--lobe-fill-border-strong': `color-mix(in srgb, ${v('colorFill')}, ${v('colorText')} 15%)`,\n '--lobe-table-cell-bg': 'initial',\n '--lobe-table-surface': 'initial',\n },\n};\n\nconst rule = (selector: string, declarations: Record<string, number | string>) =>\n `${selector} {\\n${Object.entries(declarations)\n .map(([name, value]) => ` ${name}: ${value};`)\n .join('\\n')}\\n}`;\n\nconst appearanceRule = (selector: string, appearance: LobeAppearance) => {\n const { neutral, palette, primary, static: base } = createLobeTokenGroups({ appearance });\n const token =\n appearance === 'light'\n ? { ...base, ...palette, ...primary, ...neutral }\n : { ...palette, ...primary, ...neutral };\n\n return rule(selector, {\n ...toCssVariables(token),\n '--lobe-ring': ring[appearance],\n ...surface[appearance],\n 'color-scheme': appearance,\n });\n};\n\nconst appearanceSelector = (appearance: LobeAppearance) =>\n appearance === 'dark' ? \"[data-theme='dark']\" : \":not([data-theme='dark'])\";\n\nconst colorRules = (appearance: LobeAppearance) => [\n ...(Object.keys(primaryColors) as (keyof typeof primaryColors)[]).map((primaryColor) =>\n rule(\n `[data-primary-color='${primaryColor}']${appearanceSelector(appearance)}`,\n toCssVariables(createLobeTokenGroups({ appearance, primaryColor }).primary),\n ),\n ),\n ...(Object.keys(neutralColors) as (keyof typeof neutralColors)[]).map((neutralColor) =>\n rule(\n `[data-neutral-color='${neutralColor}']${appearanceSelector(appearance)}`,\n toCssVariables(createLobeTokenGroups({ appearance, neutralColor }).neutral),\n ),\n ),\n];\n\nexport const getCustomPrimaryCss = (color: CustomPrimaryColor) => {\n const hex = color.toLowerCase();\n return (['light', 'dark'] as const)\n .map((appearance) =>\n rule(\n `[data-primary-color='${hex}']${appearanceSelector(appearance)}`,\n toCssVariables(\n createLobeTokenGroups({ appearance, primaryColor: hex as CustomPrimaryColor }).primary,\n ),\n ),\n )\n .join('\\n\\n');\n};\n\nconst essentialCss = `@layer lobe-ui {\n .lobe-brand-loading path {\n fill: currentcolor;\n fill-opacity: 0;\n stroke: currentcolor;\n stroke-dasharray: 1000;\n stroke-dashoffset: 1000;\n stroke-width: 0.25em;\n\n animation:\n draw 2s cubic-bezier(0.4, 0, 0.2, 1) infinite,\n fill 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;\n }\n}\n\n@layer lobe-popup {\n .lobe-context-trigger[data-popup-open],\n .lobe-dropdown-menu-trigger[data-popup-open] {\n background: ${v('colorFillTertiary')};\n }\n}\n\n@layer lobe-base {\n :where(body, body [data-theme]) {\n color: ${v('colorText')};\n font-family: ${v('fontFamily')};\n font-size: ${v('fontSize')};\n line-height: ${v('lineHeight')};\n }\n\n :where(body) :where(a) {\n cursor: pointer;\n\n color: ${v('colorLink')};\n text-decoration: none;\n\n background-color: transparent;\n outline: none;\n\n transition: color ${v('motionDurationSlow')};\n }\n\n :where(body) :where(a):hover {\n color: ${v('colorLinkHover')};\n }\n\n :where(body) :where(a):active {\n color: ${v('colorLinkActive')};\n }\n\n :where(body) :where(a):focus-visible {\n outline: ${v('lineWidthFocus')} solid ${v('colorPrimaryBorder')};\n outline-offset: 1px;\n }\n\n :where(body) :where(a)[disabled] {\n cursor: not-allowed;\n color: ${v('colorTextDisabled')};\n }\n\n :where(.lobe-flex) {\n --lobe-flex: 0 1 auto;\n --lobe-flex-direction: column;\n --lobe-flex-wrap: nowrap;\n --lobe-flex-justify: flex-start;\n --lobe-flex-align: stretch;\n --lobe-flex-width: auto;\n --lobe-flex-height: auto;\n --lobe-flex-padding: 0;\n --lobe-flex-padding-inline: var(--lobe-flex-padding);\n --lobe-flex-padding-block: var(--lobe-flex-padding);\n --lobe-flex-gap: 0;\n\n display: flex;\n flex: var(--lobe-flex);\n flex-flow: var(--lobe-flex-direction) var(--lobe-flex-wrap);\n gap: var(--lobe-flex-gap);\n align-items: var(--lobe-flex-align);\n justify-content: var(--lobe-flex-justify);\n\n width: var(--lobe-flex-width);\n height: var(--lobe-flex-height);\n padding: var(--lobe-flex-padding);\n padding-block: var(--lobe-flex-padding-block);\n padding-inline: var(--lobe-flex-padding-inline);\n }\n\n .lobe-flex-hidden {\n display: none;\n }\n}\n\n@keyframes draw {\n 0% {\n stroke-dashoffset: 1000;\n }\n\n 100% {\n stroke-dashoffset: 0;\n }\n}\n\n@keyframes fill {\n 30% {\n fill-opacity: 0.05;\n }\n\n 100% {\n fill-opacity: 1;\n }\n}`;\n\nconst globalCss = `@layer lobe-base {\n :root {\n --font-settings: 'cv01', 'tnum', 'kern';\n --font-variations: 'opsz' auto, tabular-nums;\n\n font-synthesis: style;\n text-autospace: normal;\n }\n\n html {\n overscroll-behavior: none;\n }\n\n body {\n overflow: hidden auto;\n\n min-height: 100vh;\n margin: 0;\n padding: 0;\n\n font-feature-settings: var(--font-settings);\n font-variation-settings: var(--font-variations);\n font-optical-sizing: auto;\n font-kerning: normal;\n font-variant-ligatures: common-ligatures contextual;\n font-variant-numeric: tabular-nums;\n font-size-adjust: from-font;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-wrap: pretty;\n text-size-adjust: 100%;\n text-rendering: optimizelegibility;\n overflow-wrap: anywhere;\n vertical-align: baseline;\n\n background-color: ${v('colorBgLayout')};\n\n font-synthesis: style;\n\n -webkit-overflow-scrolling: touch;\n -webkit-tap-highlight-color: transparent;\n }\n\n html,\n body {\n width: 100%;\n height: 100%;\n }\n\n [tabindex='-1']:focus {\n outline: none;\n }\n\n [hidden] {\n display: none !important;\n }\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n margin-block: 0 0.5em;\n font-weight: 500;\n }\n\n p,\n ol,\n ul,\n dl,\n pre {\n margin-block: 0 1em;\n }\n\n ol ol,\n ul ul,\n ol ul,\n ul ol {\n margin-block-end: 0;\n }\n\n dd {\n margin-block-end: 0.5em;\n margin-inline-start: 0;\n }\n\n blockquote,\n figure {\n margin-block: 0 1em;\n margin-inline: 0;\n }\n\n img {\n border-style: none;\n vertical-align: middle;\n }\n\n table {\n border-collapse: collapse;\n }\n\n input,\n button,\n select,\n optgroup,\n textarea {\n margin: 0;\n\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n color: inherit;\n }\n\n textarea {\n resize: vertical;\n overflow: auto;\n }\n\n fieldset {\n min-width: 0;\n margin: 0;\n padding: 0;\n border: 0;\n }\n\n code,\n kbd,\n samp,\n pre {\n font-family: ${v('fontFamilyCode')} !important;\n font-feature-settings:\n 'liga' 0,\n 'calt' 0;\n font-variant-ligatures: none;\n\n span {\n font-family: ${v('fontFamilyCode')} !important;\n }\n }\n\n ::selection {\n color: #000;\n background: ${v('yellow9')};\n\n -webkit-text-fill-color: unset !important;\n }\n\n * {\n scrollbar-color: ${v('colorFill')} transparent;\n scrollbar-width: thin;\n box-sizing: border-box;\n vertical-align: baseline;\n }\n}`;\n\nconst layerOrder = '@layer lobe-base, lobe-popup, lobe-ui;';\n\nlet cached: string | undefined;\n\nexport const getThemeCss = () =>\n (cached ??= [\n layerOrder,\n appearanceRule(\":root, [data-theme='light']\", 'light'),\n appearanceRule(\"[data-theme='dark']\", 'dark'),\n ...colorRules('light'),\n ...colorRules('dark'),\n essentialCss,\n ].join('\\n\\n'));\n\nexport const getGlobalCss = () => `${layerOrder}\\n\\n${globalCss}`;\n"],"mappings":"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"}
1
+ {"version":3,"file":"themeCss.mjs","names":[],"sources":["../../../src/styles/theme/themeCss.ts"],"sourcesContent":["import { toCssVariables, toCssVarName } from '../css';\nimport { neutralColors, primaryColors } from '../customTheme';\nimport { createLobeTokenGroups } from './createLobeToken';\nimport { isRegisteredPalette } from './customPalette';\nimport type { CustomPrimaryColor } from './customPrimary';\nimport type { LobeAppearance } from './scope';\n\nconst v = (key: string) => `var(${toCssVarName(key)})`;\n\nconst ring: Record<LobeAppearance, string> = {\n dark: '0 0 0 1px rgb(255 255 255 / 18%)',\n light: '0 0 0 1px rgb(0 0 0 / 5%)',\n};\n\n/* `initial` makes a light scope nested in a dark one fall back to each variant's own fill\n instead of inheriting the dark table surface. */\nconst surface: Record<LobeAppearance, Record<string, string>> = {\n dark: {\n '--lobe-fill-border': v('colorFillSecondary'),\n '--lobe-fill-border-strong': v('colorFill'),\n '--lobe-table-cell-bg': 'transparent',\n '--lobe-table-surface': v('colorFillQuaternary'),\n },\n light: {\n '--lobe-fill-border': v('colorFill'),\n '--lobe-fill-border-strong': `color-mix(in srgb, ${v('colorFill')}, ${v('colorText')} 15%)`,\n '--lobe-table-cell-bg': 'initial',\n '--lobe-table-surface': 'initial',\n },\n};\n\nconst rule = (selector: string, declarations: Record<string, number | string>) =>\n `${selector} {\\n${Object.entries(declarations)\n .map(([name, value]) => ` ${name}: ${value};`)\n .join('\\n')}\\n}`;\n\nconst appearanceRule = (selector: string, appearance: LobeAppearance) => {\n const { neutral, palette, primary, static: base } = createLobeTokenGroups({ appearance });\n const token =\n appearance === 'light'\n ? { ...base, ...palette, ...primary, ...neutral }\n : { ...palette, ...primary, ...neutral };\n\n return rule(selector, {\n ...toCssVariables(token),\n '--lobe-ring': ring[appearance],\n ...surface[appearance],\n 'color-scheme': appearance,\n });\n};\n\nconst appearanceSelector = (appearance: LobeAppearance) =>\n appearance === 'dark' ? \"[data-theme='dark']\" : \":not([data-theme='dark'])\";\n\nconst colorRules = (appearance: LobeAppearance) => [\n ...(Object.keys(primaryColors) as (keyof typeof primaryColors)[]).map((primaryColor) =>\n rule(\n `[data-primary-color='${primaryColor}']${appearanceSelector(appearance)}`,\n toCssVariables(createLobeTokenGroups({ appearance, primaryColor }).primary),\n ),\n ),\n ...(Object.keys(neutralColors) as (keyof typeof neutralColors)[]).map((neutralColor) =>\n rule(\n `[data-neutral-color='${neutralColor}']${appearanceSelector(appearance)}`,\n toCssVariables(createLobeTokenGroups({ appearance, neutralColor }).neutral),\n ),\n ),\n];\n\nexport const getCustomPrimaryCss = (color: CustomPrimaryColor) => {\n const hex = color.toLowerCase();\n return (['light', 'dark'] as const)\n .map((appearance) =>\n rule(\n `[data-primary-color='${hex}']${appearanceSelector(appearance)}`,\n toCssVariables(\n createLobeTokenGroups({ appearance, primaryColor: hex as CustomPrimaryColor }).primary,\n ),\n ),\n )\n .join('\\n\\n');\n};\n\nexport const getCustomPaletteCss = (name: string) => {\n if (!isRegisteredPalette(name)) return '';\n return (['light', 'dark'] as const)\n .map((appearance) => {\n const { neutral, palette } = createLobeTokenGroups({ appearance, palette: name });\n return rule(\n `[data-palette='${name}']${appearanceSelector(appearance)}`,\n toCssVariables({\n ...palette,\n colorErrorOutline: neutral.colorErrorOutline,\n colorWarningOutline: neutral.colorWarningOutline,\n }),\n );\n })\n .join('\\n\\n');\n};\n\nconst essentialCss = `@layer lobe-ui {\n .lobe-brand-loading path {\n fill: currentcolor;\n fill-opacity: 0;\n stroke: currentcolor;\n stroke-dasharray: 1000;\n stroke-dashoffset: 1000;\n stroke-width: 0.25em;\n\n animation:\n draw 2s cubic-bezier(0.4, 0, 0.2, 1) infinite,\n fill 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;\n }\n}\n\n@layer lobe-popup {\n .lobe-context-trigger[data-popup-open],\n .lobe-dropdown-menu-trigger[data-popup-open] {\n background: ${v('colorFillTertiary')};\n }\n}\n\n@layer lobe-base {\n :where(body, body [data-theme]) {\n color: ${v('colorText')};\n font-family: ${v('fontFamily')};\n font-size: ${v('fontSize')};\n line-height: ${v('lineHeight')};\n }\n\n :where(body) :where(a) {\n cursor: pointer;\n\n color: ${v('colorLink')};\n text-decoration: none;\n\n background-color: transparent;\n outline: none;\n\n transition: color ${v('motionDurationSlow')};\n }\n\n :where(body) :where(a):hover {\n color: ${v('colorLinkHover')};\n }\n\n :where(body) :where(a):active {\n color: ${v('colorLinkActive')};\n }\n\n :where(body) :where(a):focus-visible {\n outline: ${v('lineWidthFocus')} solid ${v('colorPrimaryBorder')};\n outline-offset: 1px;\n }\n\n :where(body) :where(a)[disabled] {\n cursor: not-allowed;\n color: ${v('colorTextDisabled')};\n }\n\n :where(.lobe-flex) {\n --lobe-flex: 0 1 auto;\n --lobe-flex-direction: column;\n --lobe-flex-wrap: nowrap;\n --lobe-flex-justify: flex-start;\n --lobe-flex-align: stretch;\n --lobe-flex-width: auto;\n --lobe-flex-height: auto;\n --lobe-flex-padding: 0;\n --lobe-flex-padding-inline: var(--lobe-flex-padding);\n --lobe-flex-padding-block: var(--lobe-flex-padding);\n --lobe-flex-gap: 0;\n\n display: flex;\n flex: var(--lobe-flex);\n flex-flow: var(--lobe-flex-direction) var(--lobe-flex-wrap);\n gap: var(--lobe-flex-gap);\n align-items: var(--lobe-flex-align);\n justify-content: var(--lobe-flex-justify);\n\n width: var(--lobe-flex-width);\n height: var(--lobe-flex-height);\n padding: var(--lobe-flex-padding);\n padding-block: var(--lobe-flex-padding-block);\n padding-inline: var(--lobe-flex-padding-inline);\n }\n\n .lobe-flex-hidden {\n display: none;\n }\n}\n\n@keyframes draw {\n 0% {\n stroke-dashoffset: 1000;\n }\n\n 100% {\n stroke-dashoffset: 0;\n }\n}\n\n@keyframes fill {\n 30% {\n fill-opacity: 0.05;\n }\n\n 100% {\n fill-opacity: 1;\n }\n}`;\n\nconst globalCss = `@layer lobe-base {\n :root {\n --font-settings: 'cv01', 'tnum', 'kern';\n --font-variations: 'opsz' auto, tabular-nums;\n\n font-synthesis: style;\n text-autospace: normal;\n }\n\n html {\n overscroll-behavior: none;\n }\n\n body {\n overflow: hidden auto;\n\n min-height: 100vh;\n margin: 0;\n padding: 0;\n\n font-feature-settings: var(--font-settings);\n font-variation-settings: var(--font-variations);\n font-optical-sizing: auto;\n font-kerning: normal;\n font-variant-ligatures: common-ligatures contextual;\n font-variant-numeric: tabular-nums;\n font-size-adjust: from-font;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-wrap: pretty;\n text-size-adjust: 100%;\n text-rendering: optimizelegibility;\n overflow-wrap: anywhere;\n vertical-align: baseline;\n\n background-color: ${v('colorBgLayout')};\n\n font-synthesis: style;\n\n -webkit-overflow-scrolling: touch;\n -webkit-tap-highlight-color: transparent;\n }\n\n html,\n body {\n width: 100%;\n height: 100%;\n }\n\n [tabindex='-1']:focus {\n outline: none;\n }\n\n [hidden] {\n display: none !important;\n }\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n margin-block: 0 0.5em;\n font-weight: 500;\n }\n\n p,\n ol,\n ul,\n dl,\n pre {\n margin-block: 0 1em;\n }\n\n ol ol,\n ul ul,\n ol ul,\n ul ol {\n margin-block-end: 0;\n }\n\n dd {\n margin-block-end: 0.5em;\n margin-inline-start: 0;\n }\n\n blockquote,\n figure {\n margin-block: 0 1em;\n margin-inline: 0;\n }\n\n img {\n border-style: none;\n vertical-align: middle;\n }\n\n table {\n border-collapse: collapse;\n }\n\n input,\n button,\n select,\n optgroup,\n textarea {\n margin: 0;\n\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n color: inherit;\n }\n\n textarea {\n resize: vertical;\n overflow: auto;\n }\n\n fieldset {\n min-width: 0;\n margin: 0;\n padding: 0;\n border: 0;\n }\n\n code,\n kbd,\n samp,\n pre {\n font-family: ${v('fontFamilyCode')} !important;\n font-feature-settings:\n 'liga' 0,\n 'calt' 0;\n font-variant-ligatures: none;\n\n span {\n font-family: ${v('fontFamilyCode')} !important;\n }\n }\n\n ::selection {\n color: #000;\n background: ${v('yellow9')};\n\n -webkit-text-fill-color: unset !important;\n }\n\n * {\n scrollbar-color: ${v('colorFill')} transparent;\n scrollbar-width: thin;\n box-sizing: border-box;\n vertical-align: baseline;\n }\n}`;\n\nconst layerOrder = '@layer lobe-base, lobe-popup, lobe-ui;';\n\nlet cached: string | undefined;\n\nexport const getThemeCss = () =>\n (cached ??= [\n layerOrder,\n appearanceRule(\":root, [data-theme='light']\", 'light'),\n appearanceRule(\"[data-theme='dark']\", 'dark'),\n ...colorRules('light'),\n ...colorRules('dark'),\n essentialCss,\n ].join('\\n\\n'));\n\nexport const getGlobalCss = () => `${layerOrder}\\n\\n${globalCss}`;\n"],"mappings":"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"}