@sigx/lynx-daisyui 0.4.3 → 0.4.4
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.
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/styles/components/alert.css +1 -1
- package/dist/styles/components/badge.css +1 -1
- package/dist/styles/components/button.css +1 -1
- package/dist/styles/components/card.css +1 -1
- package/dist/styles/components/checkbox.css +1 -1
- package/dist/styles/components/input.css +1 -1
- package/dist/styles/components/modal.css +1 -1
- package/dist/styles/components/select.css +2 -2
- package/dist/styles/components/skeleton.css +1 -1
- package/dist/styles/components/textarea.css +1 -1
- package/dist/styles/components/toggle.css +4 -4
- package/dist/styles/index.css +5 -0
- package/dist/styles/themes/builtins.generated.css +140 -0
- package/dist/styles/themes/shapes.css +6 -12
- package/dist/styles/themes/tokens.css +35 -29
- package/dist/theme/ThemeProvider.d.ts +2 -2
- package/dist/theme/ThemeProvider.js +102 -29
- package/dist/theme/registry.d.ts +33 -6
- package/dist/theme/registry.js +22 -0
- package/package.json +9 -9
package/dist/index.d.ts
CHANGED
|
@@ -54,8 +54,8 @@ export { NavDrawer } from './navigation/NavDrawer.js';
|
|
|
54
54
|
export type { NavDrawerProps, NavDrawerSide, } from './navigation/NavDrawer.js';
|
|
55
55
|
export { SwiperIndicator } from './navigation/SwiperIndicator.js';
|
|
56
56
|
export type { SwiperIndicatorProps, SwiperIndicatorVariant, SwiperIndicatorSize, } from './navigation/SwiperIndicator.js';
|
|
57
|
-
export { ThemeProvider, useTheme, listThemes, registerTheme, extendTheme, pickThemeFor, pairOf, variantOf, colorsOf, radiusOf, } from './theme/ThemeProvider.js';
|
|
58
|
-
export type { DaisyTheme, ThemeController, ThemeProviderProps, Theme, ThemePalette, ThemeRadius, ThemeVariant, } from './theme/ThemeProvider.js';
|
|
57
|
+
export { ThemeProvider, useTheme, listThemes, registerTheme, extendTheme, pickThemeFor, pairOf, variantOf, colorsOf, radiusOf, sizesOf, } from './theme/ThemeProvider.js';
|
|
58
|
+
export type { DaisyTheme, ThemeController, ThemeProviderProps, Theme, ThemePalette, ThemeRadius, ThemeSizes, ThemeVariant, } from './theme/ThemeProvider.js';
|
|
59
59
|
export { StatusBarSync } from './theme/StatusBarSync.js';
|
|
60
60
|
export type { StatusBarSyncProps } from './theme/StatusBarSync.js';
|
|
61
61
|
export { themeController } from './theme/theme-state.js';
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ export { NavHeader } from './navigation/NavHeader.js';
|
|
|
32
32
|
export { NavDrawer } from './navigation/NavDrawer.js';
|
|
33
33
|
export { SwiperIndicator } from './navigation/SwiperIndicator.js';
|
|
34
34
|
// Theme
|
|
35
|
-
export { ThemeProvider, useTheme, listThemes, registerTheme, extendTheme, pickThemeFor, pairOf, variantOf, colorsOf, radiusOf, } from './theme/ThemeProvider.js';
|
|
35
|
+
export { ThemeProvider, useTheme, listThemes, registerTheme, extendTheme, pickThemeFor, pairOf, variantOf, colorsOf, radiusOf, sizesOf, } from './theme/ThemeProvider.js';
|
|
36
36
|
export { StatusBarSync } from './theme/StatusBarSync.js';
|
|
37
37
|
// Headless theme handle (issue #113): import and call from anywhere — stores,
|
|
38
38
|
// services, effects, app-boot — with no `<ThemeProvider>` ancestor required.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
height: var(--size-md);
|
|
5
5
|
padding-left: var(--padding-btn-md);
|
|
6
6
|
padding-right: var(--padding-btn-md);
|
|
7
|
-
border-radius: var(--
|
|
7
|
+
border-radius: var(--radius-field);
|
|
8
8
|
font-size: var(--font-md);
|
|
9
9
|
background-color: var(--color-base-100);
|
|
10
10
|
color: var(--color-base-content);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
height: var(--size-md);
|
|
8
8
|
padding-left: var(--padding-btn-md);
|
|
9
9
|
padding-right: var(--padding-btn-md);
|
|
10
|
-
border-radius: var(--
|
|
10
|
+
border-radius: var(--radius-field);
|
|
11
11
|
font-size: var(--font-md);
|
|
12
12
|
background-color: var(--color-base-100);
|
|
13
13
|
color: var(--color-base-content);
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
background-color: var(--color-base-100);
|
|
39
39
|
border-width: var(--border-btn);
|
|
40
40
|
border-color: var(--color-base-300);
|
|
41
|
-
border-radius: var(--
|
|
41
|
+
border-radius: var(--radius-field);
|
|
42
42
|
overflow: hidden;
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
padding: 12px;
|
|
5
5
|
padding-left: var(--padding-btn-md);
|
|
6
6
|
padding-right: var(--padding-btn-md);
|
|
7
|
-
border-radius: var(--
|
|
7
|
+
border-radius: var(--radius-field);
|
|
8
8
|
font-size: var(--font-md);
|
|
9
9
|
background-color: var(--color-base-100);
|
|
10
10
|
color: var(--color-base-content);
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
/* Size variants — track dimensions */
|
|
11
|
-
.toggle-xs { width: var(--toggle-width-xs); height: var(--toggle-height-xs); border-radius: var(--
|
|
12
|
-
.toggle-sm { width: var(--toggle-width-sm); height: var(--toggle-height-sm); border-radius: var(--
|
|
13
|
-
.toggle-md { width: var(--toggle-width-md); height: var(--toggle-height-md); border-radius: var(--
|
|
14
|
-
.toggle-lg { width: var(--toggle-width-lg); height: var(--toggle-height-lg); border-radius: var(--
|
|
11
|
+
.toggle-xs { width: var(--toggle-width-xs); height: var(--toggle-height-xs); border-radius: var(--radius-selector); }
|
|
12
|
+
.toggle-sm { width: var(--toggle-width-sm); height: var(--toggle-height-sm); border-radius: var(--radius-selector); }
|
|
13
|
+
.toggle-md { width: var(--toggle-width-md); height: var(--toggle-height-md); border-radius: var(--radius-selector); }
|
|
14
|
+
.toggle-lg { width: var(--toggle-width-lg); height: var(--toggle-height-lg); border-radius: var(--radius-selector); }
|
|
15
15
|
|
|
16
16
|
/* Thumb */
|
|
17
17
|
.toggle-thumb {
|
package/dist/styles/index.css
CHANGED
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
/* Structural design tokens (.daisy) + composable shape modifiers */
|
|
9
9
|
@import './themes/tokens.css';
|
|
10
10
|
@import './themes/shapes.css';
|
|
11
|
+
/* Per-theme color tokens for the built-in themes — generated from the theme
|
|
12
|
+
* registry at build time (scripts/gen-theme-css.mjs). Declared as CSS rules so
|
|
13
|
+
* `var(--color-*)` resolves on the first paint; the runtime `setProperty` path
|
|
14
|
+
* can't set inheritable custom properties before descendants have painted. */
|
|
15
|
+
@import './themes/builtins.generated.css';
|
|
11
16
|
|
|
12
17
|
/* Base reset */
|
|
13
18
|
@import './base.css';
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/* AUTO-GENERATED from src/theme/registry.ts — do not edit.
|
|
2
|
+
* Regenerated by scripts/gen-theme-css.mjs on every build. */
|
|
3
|
+
|
|
4
|
+
.daisy-light {
|
|
5
|
+
--color-primary: #491dff;
|
|
6
|
+
--color-primary-content: #d3dbff;
|
|
7
|
+
--color-secondary: #ff20cc;
|
|
8
|
+
--color-secondary-content: #fff8fc;
|
|
9
|
+
--color-accent: #00cfbd;
|
|
10
|
+
--color-accent-content: #00100d;
|
|
11
|
+
--color-neutral: #2b3440;
|
|
12
|
+
--color-neutral-content: #d7dde4;
|
|
13
|
+
--color-base-100: #ffffff;
|
|
14
|
+
--color-base-200: #f2f2f2;
|
|
15
|
+
--color-base-300: #e5e6e6;
|
|
16
|
+
--color-base-content: #1f2937;
|
|
17
|
+
--color-info: #00b4fa;
|
|
18
|
+
--color-info-content: #000000;
|
|
19
|
+
--color-success: #00a96e;
|
|
20
|
+
--color-success-content: #000000;
|
|
21
|
+
--color-warning: #ffc100;
|
|
22
|
+
--color-warning-content: #000000;
|
|
23
|
+
--color-error: #ff676a;
|
|
24
|
+
--color-error-content: #000000;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.daisy-cupcake {
|
|
28
|
+
--color-primary: #65c3c8;
|
|
29
|
+
--color-primary-content: #052124;
|
|
30
|
+
--color-secondary: #ef9fbc;
|
|
31
|
+
--color-secondary-content: #2d0a16;
|
|
32
|
+
--color-accent: #eeaf3a;
|
|
33
|
+
--color-accent-content: #2d1c00;
|
|
34
|
+
--color-neutral: #291334;
|
|
35
|
+
--color-neutral-content: #f5f1f8;
|
|
36
|
+
--color-base-100: #faf7f5;
|
|
37
|
+
--color-base-200: #efeae6;
|
|
38
|
+
--color-base-300: #e7e2df;
|
|
39
|
+
--color-base-content: #291334;
|
|
40
|
+
--color-info: #00b4fa;
|
|
41
|
+
--color-info-content: #000000;
|
|
42
|
+
--color-success: #00a96e;
|
|
43
|
+
--color-success-content: #000000;
|
|
44
|
+
--color-warning: #ffc100;
|
|
45
|
+
--color-warning-content: #000000;
|
|
46
|
+
--color-error: #ff676a;
|
|
47
|
+
--color-error-content: #000000;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.daisy-emerald {
|
|
51
|
+
--color-primary: #66cc8a;
|
|
52
|
+
--color-primary-content: #06200f;
|
|
53
|
+
--color-secondary: #377cfb;
|
|
54
|
+
--color-secondary-content: #02112d;
|
|
55
|
+
--color-accent: #f68067;
|
|
56
|
+
--color-accent-content: #2d0a02;
|
|
57
|
+
--color-neutral: #333c4d;
|
|
58
|
+
--color-neutral-content: #e9eaed;
|
|
59
|
+
--color-base-100: #ffffff;
|
|
60
|
+
--color-base-200: #f3f4f6;
|
|
61
|
+
--color-base-300: #e5e7eb;
|
|
62
|
+
--color-base-content: #333c4d;
|
|
63
|
+
--color-info: #1c92f2;
|
|
64
|
+
--color-info-content: #000a14;
|
|
65
|
+
--color-success: #00a96e;
|
|
66
|
+
--color-success-content: #000a05;
|
|
67
|
+
--color-warning: #ff9900;
|
|
68
|
+
--color-warning-content: #261600;
|
|
69
|
+
--color-error: #ff5724;
|
|
70
|
+
--color-error-content: #000000;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.daisy-dark {
|
|
74
|
+
--color-primary: #7582ff;
|
|
75
|
+
--color-primary-content: #050617;
|
|
76
|
+
--color-secondary: #ff71cf;
|
|
77
|
+
--color-secondary-content: #190211;
|
|
78
|
+
--color-accent: #00e7d0;
|
|
79
|
+
--color-accent-content: #001210;
|
|
80
|
+
--color-neutral: #2a323c;
|
|
81
|
+
--color-neutral-content: #a6adbb;
|
|
82
|
+
--color-base-100: #1d232a;
|
|
83
|
+
--color-base-200: #191e24;
|
|
84
|
+
--color-base-300: #343b46;
|
|
85
|
+
--color-base-content: #a6adbb;
|
|
86
|
+
--color-info: #00b4fa;
|
|
87
|
+
--color-info-content: #000000;
|
|
88
|
+
--color-success: #00a96e;
|
|
89
|
+
--color-success-content: #000000;
|
|
90
|
+
--color-warning: #ffc100;
|
|
91
|
+
--color-warning-content: #000000;
|
|
92
|
+
--color-error: #ff676a;
|
|
93
|
+
--color-error-content: #000000;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.daisy-synthwave {
|
|
97
|
+
--color-primary: #e779c1;
|
|
98
|
+
--color-primary-content: #2a0a1f;
|
|
99
|
+
--color-secondary: #58c7f3;
|
|
100
|
+
--color-secondary-content: #02141d;
|
|
101
|
+
--color-accent: #f3cc30;
|
|
102
|
+
--color-accent-content: #2a1f00;
|
|
103
|
+
--color-neutral: #20134e;
|
|
104
|
+
--color-neutral-content: #e3e0f5;
|
|
105
|
+
--color-base-100: #2d1b69;
|
|
106
|
+
--color-base-200: #261159;
|
|
107
|
+
--color-base-300: #1f0f4a;
|
|
108
|
+
--color-base-content: #f9f7fd;
|
|
109
|
+
--color-info: #53c0f3;
|
|
110
|
+
--color-info-content: #02151e;
|
|
111
|
+
--color-success: #71ead2;
|
|
112
|
+
--color-success-content: #002721;
|
|
113
|
+
--color-warning: #f3cc30;
|
|
114
|
+
--color-warning-content: #2a1f00;
|
|
115
|
+
--color-error: #e24056;
|
|
116
|
+
--color-error-content: #ffffff;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.daisy-dracula {
|
|
120
|
+
--color-primary: #ff79c6;
|
|
121
|
+
--color-primary-content: #2d0414;
|
|
122
|
+
--color-secondary: #bd93f9;
|
|
123
|
+
--color-secondary-content: #160226;
|
|
124
|
+
--color-accent: #50fa7b;
|
|
125
|
+
--color-accent-content: #002a0e;
|
|
126
|
+
--color-neutral: #414558;
|
|
127
|
+
--color-neutral-content: #f8f8f2;
|
|
128
|
+
--color-base-100: #282a36;
|
|
129
|
+
--color-base-200: #21222c;
|
|
130
|
+
--color-base-300: #181920;
|
|
131
|
+
--color-base-content: #f8f8f2;
|
|
132
|
+
--color-info: #8be9fd;
|
|
133
|
+
--color-info-content: #002a31;
|
|
134
|
+
--color-success: #50fa7b;
|
|
135
|
+
--color-success-content: #002a0e;
|
|
136
|
+
--color-warning: #f1fa8c;
|
|
137
|
+
--color-warning-content: #2a2900;
|
|
138
|
+
--color-error: #ff5555;
|
|
139
|
+
--color-error-content: #2a0000;
|
|
140
|
+
}
|
|
@@ -3,19 +3,13 @@
|
|
|
3
3
|
<ThemeProvider class="daisy-rounded"> → host class="daisy daisy-rounded" */
|
|
4
4
|
|
|
5
5
|
.daisy-flat {
|
|
6
|
-
--
|
|
7
|
-
--
|
|
8
|
-
--
|
|
9
|
-
--rounded-tab: 0px;
|
|
10
|
-
--rounded-selector: 0px;
|
|
11
|
-
--rounded-toggle: 0px;
|
|
6
|
+
--radius-selector: 0px;
|
|
7
|
+
--radius-field: 0px;
|
|
8
|
+
--radius-box: 0px;
|
|
12
9
|
}
|
|
13
10
|
|
|
14
11
|
.daisy-rounded {
|
|
15
|
-
--
|
|
16
|
-
--
|
|
17
|
-
--
|
|
18
|
-
--rounded-tab: 9999px;
|
|
19
|
-
--rounded-selector: 9999px;
|
|
20
|
-
--rounded-toggle: 9999px;
|
|
12
|
+
--radius-selector: 9999px;
|
|
13
|
+
--radius-field: 9999px;
|
|
14
|
+
--radius-box: 24px;
|
|
21
15
|
}
|
|
@@ -8,15 +8,20 @@
|
|
|
8
8
|
* may still override roundness via its `radius` field. */
|
|
9
9
|
|
|
10
10
|
.daisy {
|
|
11
|
-
/* ── Roundness ── */
|
|
12
|
-
--
|
|
13
|
-
--
|
|
14
|
-
--
|
|
15
|
-
--rounded-tab: 8px;
|
|
16
|
-
--rounded-selector: 8px;
|
|
17
|
-
--rounded-toggle: 9999px;
|
|
11
|
+
/* ── Roundness (DaisyUI v5 contract) ── */
|
|
12
|
+
--radius-selector: 8px;
|
|
13
|
+
--radius-field: 8px;
|
|
14
|
+
--radius-box: 16px;
|
|
18
15
|
|
|
19
|
-
/* ──
|
|
16
|
+
/* ── Base size units (DaisyUI v5 contract) ──
|
|
17
|
+
* A theme's `sizes` ({ field, selector }) overrides these; <ThemeProvider>
|
|
18
|
+
* re-derives the component dimensions below from them in JS. We deliberately
|
|
19
|
+
* do NOT use `calc(var() * n)` in CSS — it's unproven in Lynx's runtime CSS
|
|
20
|
+
* engine. Defaults below are base 4px × the per-token multiples shown. */
|
|
21
|
+
--size-selector: 4px;
|
|
22
|
+
--size-field: 4px;
|
|
23
|
+
|
|
24
|
+
/* ── Field sizing scale (button / input / select) — field × 6/8/12/16 ── */
|
|
20
25
|
--size-xs: 24px;
|
|
21
26
|
--size-sm: 32px;
|
|
22
27
|
--size-md: 48px;
|
|
@@ -41,27 +46,28 @@
|
|
|
41
46
|
--border-btn: 1px;
|
|
42
47
|
--border-card: 1px;
|
|
43
48
|
|
|
44
|
-
/* ──
|
|
45
|
-
|
|
46
|
-
--checkbox-
|
|
47
|
-
--checkbox-
|
|
48
|
-
--checkbox-
|
|
49
|
-
--
|
|
50
|
-
--toggle-width-
|
|
51
|
-
--toggle-width-
|
|
52
|
-
--toggle-width-
|
|
53
|
-
--toggle-
|
|
54
|
-
--toggle-height-
|
|
55
|
-
--toggle-height-
|
|
56
|
-
--toggle-height-
|
|
57
|
-
--toggle-
|
|
58
|
-
--toggle-thumb-
|
|
59
|
-
--toggle-thumb-
|
|
60
|
-
--toggle-thumb-
|
|
61
|
-
--
|
|
62
|
-
--badge-
|
|
63
|
-
--badge-
|
|
64
|
-
--badge-
|
|
49
|
+
/* ── Selector-driven sizes (checkbox / toggle / badge) — selector × the
|
|
50
|
+
* multiples shown; <ThemeProvider> re-derives these from `sizes.selector`. ── */
|
|
51
|
+
--checkbox-xs: 16px; /* ×4 */
|
|
52
|
+
--checkbox-sm: 20px; /* ×5 */
|
|
53
|
+
--checkbox-md: 24px; /* ×6 */
|
|
54
|
+
--checkbox-lg: 32px; /* ×8 */
|
|
55
|
+
--toggle-width-xs: 32px; /* ×8 */
|
|
56
|
+
--toggle-width-sm: 40px; /* ×10 */
|
|
57
|
+
--toggle-width-md: 48px; /* ×12 */
|
|
58
|
+
--toggle-width-lg: 56px; /* ×14 */
|
|
59
|
+
--toggle-height-xs: 24px; /* ×6 */
|
|
60
|
+
--toggle-height-sm: 24px; /* ×6 */
|
|
61
|
+
--toggle-height-md: 28px; /* ×7 */
|
|
62
|
+
--toggle-height-lg: 32px; /* ×8 */
|
|
63
|
+
--toggle-thumb-xs: 16px; /* ×4 */
|
|
64
|
+
--toggle-thumb-sm: 16px; /* ×4 */
|
|
65
|
+
--toggle-thumb-md: 20px; /* ×5 */
|
|
66
|
+
--toggle-thumb-lg: 24px; /* ×6 */
|
|
67
|
+
--badge-xs: 16px; /* ×4 */
|
|
68
|
+
--badge-sm: 20px; /* ×5 */
|
|
69
|
+
--badge-md: 24px; /* ×6 */
|
|
70
|
+
--badge-lg: 32px; /* ×8 */
|
|
65
71
|
--step-indicator: 32px;
|
|
66
72
|
--progress-height: 8px;
|
|
67
73
|
--modal-max-width: 400px;
|
|
@@ -138,5 +138,5 @@ Define.Prop<'initial', DaisyTheme, false>
|
|
|
138
138
|
export declare const ThemeProvider: import("@sigx/runtime-core").ComponentFactory<ThemeProviderProps, void, {
|
|
139
139
|
default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
|
|
140
140
|
}>;
|
|
141
|
-
export { listThemes, registerTheme, extendTheme, pickThemeFor, pairOf, variantOf, colorsOf, radiusOf, } from './registry.js';
|
|
142
|
-
export type { Theme, ThemePalette, ThemeRadius, ThemeVariant } from './registry.js';
|
|
141
|
+
export { listThemes, registerTheme, extendTheme, pickThemeFor, pairOf, variantOf, colorsOf, radiusOf, sizesOf, } from './registry.js';
|
|
142
|
+
export type { Theme, ThemePalette, ThemeRadius, ThemeSizes, ThemeVariant, } from './registry.js';
|
|
@@ -38,8 +38,74 @@ import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
|
38
38
|
import { component, defineInjectable, defineProvide, effect, onMounted, onUnmounted, signal, untrack, } from '@sigx/lynx';
|
|
39
39
|
import { useIconColorResolver } from '@sigx/lynx-icons';
|
|
40
40
|
import { useSystemColorScheme } from '@sigx/lynx-appearance';
|
|
41
|
-
import { colorsOf, pickThemeFor, radiusOf } from './registry.js';
|
|
41
|
+
import { colorsOf, isBuiltInTheme, pickThemeFor, radiusOf, sizesOf, variantOf, } from './registry.js';
|
|
42
42
|
import { globalThemeState, makeThemeController, themeController, } from './theme-state.js';
|
|
43
|
+
// DaisyUI v5 expresses control dimensions as multiples of two base units
|
|
44
|
+
// (`--size-field`, `--size-selector`). Lynx's runtime CSS engine is unproven
|
|
45
|
+
// for `calc(var() * n)`, so when a theme overrides a base unit we do the
|
|
46
|
+
// multiplication here and emit literal px. Bases must be px (engine-safe, like
|
|
47
|
+
// colors); a non-px base sets only the base var and leaves the `.daisy`
|
|
48
|
+
// defaults in place. Multiples mirror the defaults in `styles/themes/tokens.css`.
|
|
49
|
+
const FIELD_STEPS = { xs: 6, sm: 8, md: 12, lg: 16 };
|
|
50
|
+
const SELECTOR_STEPS = {
|
|
51
|
+
'checkbox-xs': 4, 'checkbox-sm': 5, 'checkbox-md': 6, 'checkbox-lg': 8,
|
|
52
|
+
'toggle-width-xs': 8, 'toggle-width-sm': 10, 'toggle-width-md': 12, 'toggle-width-lg': 14,
|
|
53
|
+
'toggle-height-xs': 6, 'toggle-height-sm': 6, 'toggle-height-md': 7, 'toggle-height-lg': 8,
|
|
54
|
+
'toggle-thumb-xs': 4, 'toggle-thumb-sm': 4, 'toggle-thumb-md': 5, 'toggle-thumb-lg': 6,
|
|
55
|
+
'badge-xs': 4, 'badge-sm': 5, 'badge-md': 6, 'badge-lg': 8,
|
|
56
|
+
};
|
|
57
|
+
const pxValue = (v) => {
|
|
58
|
+
const m = /^\s*(\d+(?:\.\d+)?)px\s*$/.exec(v);
|
|
59
|
+
return m ? Number(m[1]) : undefined;
|
|
60
|
+
};
|
|
61
|
+
/** Emit a theme's `sizes` overrides as literal-px CSS custom properties. */
|
|
62
|
+
function applySizeVars(style, sizes) {
|
|
63
|
+
if (sizes.field) {
|
|
64
|
+
style['--size-field'] = sizes.field;
|
|
65
|
+
const base = pxValue(sizes.field);
|
|
66
|
+
if (base !== undefined) {
|
|
67
|
+
for (const k in FIELD_STEPS)
|
|
68
|
+
style[`--size-${k}`] = `${base * FIELD_STEPS[k]}px`;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (sizes.selector) {
|
|
72
|
+
style['--size-selector'] = sizes.selector;
|
|
73
|
+
const base = pxValue(sizes.selector);
|
|
74
|
+
if (base !== undefined) {
|
|
75
|
+
for (const k in SELECTOR_STEPS)
|
|
76
|
+
style[`--${k}`] = `${base * SELECTOR_STEPS[k]}px`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The full custom-property set for a theme — colors plus any radius/size
|
|
82
|
+
* overrides. Applied at runtime via the Lynx `setProperty` API (see
|
|
83
|
+
* `<ThemeProvider>`), NOT the inline `style` attribute: Lynx does not honor
|
|
84
|
+
* custom properties declared inline in this toolchain, but `setProperty`
|
|
85
|
+
* registers real, inheritable ones — the documented way to theme via CSS
|
|
86
|
+
* variables (https://lynxjs.org/guide/styling/custom-theming).
|
|
87
|
+
*/
|
|
88
|
+
function buildThemeVars(name) {
|
|
89
|
+
const palette = colorsOf(name) ?? colorsOf('daisy-light');
|
|
90
|
+
const radius = radiusOf(name);
|
|
91
|
+
const sizes = sizesOf(name);
|
|
92
|
+
const vars = {};
|
|
93
|
+
for (const key in palette)
|
|
94
|
+
vars[`--color-${key}`] = palette[key];
|
|
95
|
+
if (radius) {
|
|
96
|
+
if (radius.selector)
|
|
97
|
+
vars['--radius-selector'] = radius.selector;
|
|
98
|
+
if (radius.field)
|
|
99
|
+
vars['--radius-field'] = radius.field;
|
|
100
|
+
if (radius.box)
|
|
101
|
+
vars['--radius-box'] = radius.box;
|
|
102
|
+
}
|
|
103
|
+
if (sizes)
|
|
104
|
+
applySizeVars(vars, sizes);
|
|
105
|
+
return vars;
|
|
106
|
+
}
|
|
107
|
+
/** Unique host id per provider instance so `getElementById` targets its own subtree. */
|
|
108
|
+
let themeIdSeq = 0;
|
|
43
109
|
/**
|
|
44
110
|
* Access the active daisyui theme controller. Resolves to the nearest
|
|
45
111
|
* `<ThemeProvider>`'s controller (a content sub-scope), or — at the app root
|
|
@@ -82,6 +148,9 @@ export const ThemeProvider = component(({ props, slots }) => {
|
|
|
82
148
|
const depth = useThemeDepth();
|
|
83
149
|
const isRoot = depth === 0;
|
|
84
150
|
defineProvide(useThemeDepth, () => depth + 1);
|
|
151
|
+
// Stable id for the host view so the runtime `setProperty` call (below) can
|
|
152
|
+
// target it. Unique per instance so nested providers theme their own subtree.
|
|
153
|
+
const hostId = `daisy-theme-${++themeIdSeq}`;
|
|
85
154
|
const state = isRoot
|
|
86
155
|
? globalThemeState
|
|
87
156
|
: signal(props.initial
|
|
@@ -135,6 +204,7 @@ export const ThemeProvider = component(({ props, slots }) => {
|
|
|
135
204
|
// Created on mount (the native publisher may populate the scheme between
|
|
136
205
|
// setup and mount) and torn down on unmount.
|
|
137
206
|
let follow;
|
|
207
|
+
let applyVars;
|
|
138
208
|
onMounted(() => {
|
|
139
209
|
follow = effect(() => {
|
|
140
210
|
const following = state.following;
|
|
@@ -149,22 +219,42 @@ export const ThemeProvider = component(({ props, slots }) => {
|
|
|
149
219
|
state.name = next;
|
|
150
220
|
});
|
|
151
221
|
});
|
|
222
|
+
// Built-in themes are themed by their generated CSS class (applied on
|
|
223
|
+
// the host below), which resolves on the very first frame. This
|
|
224
|
+
// `setProperty` path additionally serves runtime-registered themes
|
|
225
|
+
// (`registerTheme`, no shipped CSS class) — applied once they're
|
|
226
|
+
// selected post-mount, where it lands reliably. Reading `state.name`
|
|
227
|
+
// (via buildThemeVars) tracks it, so this re-runs on every theme change.
|
|
228
|
+
applyVars = effect(() => {
|
|
229
|
+
const vars = buildThemeVars(state.name);
|
|
230
|
+
if (typeof lynx !== 'undefined') {
|
|
231
|
+
lynx.getElementById(hostId)?.setProperty(vars);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
152
234
|
});
|
|
153
235
|
onUnmounted(() => {
|
|
154
236
|
follow?.stop();
|
|
155
237
|
follow = undefined;
|
|
238
|
+
applyVars?.stop();
|
|
239
|
+
applyVars = undefined;
|
|
156
240
|
});
|
|
157
241
|
return () => {
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
// `
|
|
242
|
+
// Theme COLORS and any radius/size overrides are applied as real,
|
|
243
|
+
// inheritable CSS custom properties via the Lynx `setProperty` runtime
|
|
244
|
+
// API (see the `applyVars` effect above) — Lynx does NOT honor custom
|
|
245
|
+
// properties declared through the inline `style` attribute in this
|
|
246
|
+
// toolchain. The root background/text are painted here from palette
|
|
247
|
+
// literals (real properties, not custom props) so the surface is themed
|
|
248
|
+
// on first paint; descendants resolve `var(--color-*)` once setProperty
|
|
249
|
+
// has run. The `daisy` base class supplies structural token defaults.
|
|
166
250
|
const palette = colorsOf(state.name) ?? colorsOf('daisy-light');
|
|
167
|
-
|
|
251
|
+
// Built-ins ship a generated CSS class, so `state.name` alone paints on
|
|
252
|
+
// the first frame. A runtime-registered theme has no class — fall back
|
|
253
|
+
// to its variant's built-in class for the first frame; the `setProperty`
|
|
254
|
+
// effect above then swaps in its exact palette post-mount.
|
|
255
|
+
const themeClass = isBuiltInTheme(state.name)
|
|
256
|
+
? state.name
|
|
257
|
+
: `${pickThemeFor(variantOf(state.name) ?? 'light')} ${state.name}`;
|
|
168
258
|
const style = {
|
|
169
259
|
flexGrow: 1,
|
|
170
260
|
flexShrink: 1,
|
|
@@ -175,27 +265,10 @@ export const ThemeProvider = component(({ props, slots }) => {
|
|
|
175
265
|
backgroundColor: palette['base-100'],
|
|
176
266
|
color: palette['base-content'],
|
|
177
267
|
};
|
|
178
|
-
for (const key in palette) {
|
|
179
|
-
style[`--color-${key}`] = palette[key];
|
|
180
|
-
}
|
|
181
|
-
if (radius) {
|
|
182
|
-
if (radius.box)
|
|
183
|
-
style['--rounded-box'] = radius.box;
|
|
184
|
-
if (radius.btn)
|
|
185
|
-
style['--rounded-btn'] = radius.btn;
|
|
186
|
-
if (radius.badge)
|
|
187
|
-
style['--rounded-badge'] = radius.badge;
|
|
188
|
-
if (radius.tab)
|
|
189
|
-
style['--rounded-tab'] = radius.tab;
|
|
190
|
-
if (radius.selector)
|
|
191
|
-
style['--rounded-selector'] = radius.selector;
|
|
192
|
-
if (radius.toggle)
|
|
193
|
-
style['--rounded-toggle'] = radius.toggle;
|
|
194
|
-
}
|
|
195
268
|
if (props.style)
|
|
196
269
|
Object.assign(style, props.style);
|
|
197
|
-
return (_jsx("view", { class: `daisy${props.class ? ' ' + props.class : ''}`, style: style, children: slots.default?.() }));
|
|
270
|
+
return (_jsx("view", { id: hostId, class: `daisy ${themeClass}${props.class ? ' ' + props.class : ''}`, style: style, children: slots.default?.() }));
|
|
198
271
|
};
|
|
199
272
|
});
|
|
200
273
|
// Re-export registry helpers so consumers only need `@sigx/lynx-daisyui`.
|
|
201
|
-
export { listThemes, registerTheme, extendTheme, pickThemeFor, pairOf, variantOf, colorsOf, radiusOf, } from './registry.js';
|
|
274
|
+
export { listThemes, registerTheme, extendTheme, pickThemeFor, pairOf, variantOf, colorsOf, radiusOf, sizesOf, } from './registry.js';
|
package/dist/theme/registry.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*
|
|
18
18
|
* Structural tokens (radius, sizing, component dimensions) are theme-agnostic
|
|
19
19
|
* and ship once in the bundled `.daisy` base class (`styles/themes/tokens.css`);
|
|
20
|
-
* a theme may override roundness via `radius`.
|
|
20
|
+
* a theme may override roundness via `radius` and base size units via `sizes`.
|
|
21
21
|
*
|
|
22
22
|
* Colors are engine-safe strings — hex or `rgb()`. Lynx's CSS engine does not
|
|
23
23
|
* parse `oklch()`, so convert before registering.
|
|
@@ -26,14 +26,29 @@ import type { DaisyColor } from '../shared/styles.js';
|
|
|
26
26
|
export type ThemeVariant = 'light' | 'dark';
|
|
27
27
|
/** Full daisy color palette — every semantic token, no holes. */
|
|
28
28
|
export type ThemePalette = Record<DaisyColor, string>;
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* Roundness token overrides (DaisyUI v5 contract). Emitted as
|
|
31
|
+
* `--radius-selector` / `--radius-field` / `--radius-box`. Defaults live in
|
|
32
|
+
* the bundled `.daisy` base.
|
|
33
|
+
*/
|
|
30
34
|
export interface ThemeRadius {
|
|
35
|
+
/** Small selectable controls — checkbox, toggle, badge. */
|
|
36
|
+
selector?: string;
|
|
37
|
+
/** Fields — button, input, select, textarea. */
|
|
38
|
+
field?: string;
|
|
39
|
+
/** Boxes — card, modal, alert. */
|
|
31
40
|
box?: string;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Base size-unit overrides (DaisyUI v5 contract). Emitted as
|
|
44
|
+
* `--size-selector` / `--size-field`; component dimensions are integer
|
|
45
|
+
* multiples of these. Defaults live in the bundled `.daisy` base.
|
|
46
|
+
*/
|
|
47
|
+
export interface ThemeSizes {
|
|
48
|
+
/** Base unit for selector controls (checkbox, toggle, badge). */
|
|
35
49
|
selector?: string;
|
|
36
|
-
|
|
50
|
+
/** Base unit for fields (button, input, select). */
|
|
51
|
+
field?: string;
|
|
37
52
|
}
|
|
38
53
|
export interface Theme {
|
|
39
54
|
/** Unique id — also the value of `theme.name`. */
|
|
@@ -49,7 +64,16 @@ export interface Theme {
|
|
|
49
64
|
pair?: string;
|
|
50
65
|
/** Optional roundness overrides; unspecified tokens fall back to `.daisy`. */
|
|
51
66
|
radius?: ThemeRadius;
|
|
67
|
+
/** Optional base size-unit overrides; unspecified tokens fall back to `.daisy`. */
|
|
68
|
+
sizes?: ThemeSizes;
|
|
52
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Whether `name` is a built-in theme that ships a CSS class — i.e. it paints
|
|
72
|
+
* correctly on the first frame. Runtime-registered themes return `false`;
|
|
73
|
+
* `<ThemeProvider>` falls back to their variant's built-in class for first
|
|
74
|
+
* paint and swaps in the exact palette via `setProperty`.
|
|
75
|
+
*/
|
|
76
|
+
export declare function isBuiltInTheme(name: string | undefined): boolean;
|
|
53
77
|
/**
|
|
54
78
|
* All registered themes in insertion order. Returns a shallow copy so callers
|
|
55
79
|
* can't mutate the internal registry — re-registration goes through
|
|
@@ -80,6 +104,7 @@ export declare function extendTheme(base: string, patch: {
|
|
|
80
104
|
pair?: string;
|
|
81
105
|
colors?: Partial<ThemePalette>;
|
|
82
106
|
radius?: ThemeRadius;
|
|
107
|
+
sizes?: ThemeSizes;
|
|
83
108
|
}): Theme;
|
|
84
109
|
/** The variant of a registered theme, or `undefined` if not registered. */
|
|
85
110
|
export declare function variantOf(name: string | undefined): ThemeVariant | undefined;
|
|
@@ -87,6 +112,8 @@ export declare function variantOf(name: string | undefined): ThemeVariant | unde
|
|
|
87
112
|
export declare function colorsOf(name: string | undefined): ThemePalette | undefined;
|
|
88
113
|
/** The roundness overrides of a registered theme, if any. */
|
|
89
114
|
export declare function radiusOf(name: string | undefined): ThemeRadius | undefined;
|
|
115
|
+
/** The base size-unit overrides of a registered theme, if any. */
|
|
116
|
+
export declare function sizesOf(name: string | undefined): ThemeSizes | undefined;
|
|
90
117
|
/**
|
|
91
118
|
* Pick a default theme for a given system color scheme — the first registered
|
|
92
119
|
* theme of that variant (`daisy-light` / `daisy-dark` under the seeded
|
package/dist/theme/registry.js
CHANGED
|
@@ -89,6 +89,23 @@ const registry = [
|
|
|
89
89
|
},
|
|
90
90
|
},
|
|
91
91
|
];
|
|
92
|
+
/**
|
|
93
|
+
* Names of the themes seeded at module load — the built-ins that ship a
|
|
94
|
+
* generated CSS class (`scripts/gen-theme-css.mjs`). Captured before any
|
|
95
|
+
* runtime `registerTheme()`, so it distinguishes "has a first-paint CSS class"
|
|
96
|
+
* from runtime-registered themes (which only have their palette as data and
|
|
97
|
+
* apply via `setProperty` post-mount).
|
|
98
|
+
*/
|
|
99
|
+
const BUILTIN_NAMES = new Set(registry.map((t) => t.name));
|
|
100
|
+
/**
|
|
101
|
+
* Whether `name` is a built-in theme that ships a CSS class — i.e. it paints
|
|
102
|
+
* correctly on the first frame. Runtime-registered themes return `false`;
|
|
103
|
+
* `<ThemeProvider>` falls back to their variant's built-in class for first
|
|
104
|
+
* paint and swaps in the exact palette via `setProperty`.
|
|
105
|
+
*/
|
|
106
|
+
export function isBuiltInTheme(name) {
|
|
107
|
+
return name != null && BUILTIN_NAMES.has(name);
|
|
108
|
+
}
|
|
92
109
|
/**
|
|
93
110
|
* Resolve a `theme.name` to its registered `Theme`. Supports multi-class names
|
|
94
111
|
* like `'daisy-light daisy-rounded'` by matching the first registered id found.
|
|
@@ -147,6 +164,7 @@ export function extendTheme(base, patch) {
|
|
|
147
164
|
pair: patch.pair ?? src.pair,
|
|
148
165
|
colors: { ...src.colors, ...patch.colors },
|
|
149
166
|
radius: patch.radius ?? src.radius,
|
|
167
|
+
sizes: patch.sizes ?? src.sizes,
|
|
150
168
|
};
|
|
151
169
|
}
|
|
152
170
|
/** The variant of a registered theme, or `undefined` if not registered. */
|
|
@@ -161,6 +179,10 @@ export function colorsOf(name) {
|
|
|
161
179
|
export function radiusOf(name) {
|
|
162
180
|
return findTheme(name)?.radius;
|
|
163
181
|
}
|
|
182
|
+
/** The base size-unit overrides of a registered theme, if any. */
|
|
183
|
+
export function sizesOf(name) {
|
|
184
|
+
return findTheme(name)?.sizes;
|
|
185
|
+
}
|
|
164
186
|
/**
|
|
165
187
|
* Pick a default theme for a given system color scheme — the first registered
|
|
166
188
|
* theme of that variant (`daisy-light` / `daisy-dark` under the seeded
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigx/lynx-daisyui",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "DaisyUI integration for sigx-lynx",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
"LICENSE"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@sigx/lynx": "^0.4.
|
|
41
|
-
"@sigx/lynx-
|
|
42
|
-
"@sigx/lynx-
|
|
43
|
-
"@sigx/lynx-
|
|
44
|
-
"@sigx/lynx-motion": "^0.4.
|
|
40
|
+
"@sigx/lynx": "^0.4.4",
|
|
41
|
+
"@sigx/lynx-appearance": "^0.4.4",
|
|
42
|
+
"@sigx/lynx-gestures": "^0.4.4",
|
|
43
|
+
"@sigx/lynx-icons": "^0.4.4",
|
|
44
|
+
"@sigx/lynx-motion": "^0.4.4"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"tailwindcss": "^3.0.0 || ^4.0.0",
|
|
48
|
-
"@sigx/lynx-navigation": "^0.4.
|
|
48
|
+
"@sigx/lynx-navigation": "^0.4.4"
|
|
49
49
|
},
|
|
50
50
|
"peerDependenciesMeta": {
|
|
51
51
|
"@sigx/lynx-navigation": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@typescript/native-preview": "7.0.0-dev.20260521.1",
|
|
57
57
|
"tailwindcss": "^4.0.0",
|
|
58
58
|
"typescript": "^6.0.3",
|
|
59
|
-
"@sigx/lynx-navigation": "^0.4.
|
|
59
|
+
"@sigx/lynx-navigation": "^0.4.4"
|
|
60
60
|
},
|
|
61
61
|
"publishConfig": {
|
|
62
62
|
"access": "public"
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"author": "Andreas Ekdahl",
|
|
73
73
|
"license": "MIT",
|
|
74
74
|
"scripts": {
|
|
75
|
-
"build": "node ../../scripts/clean.mjs dist && tsgo && node ../../scripts/copy-assets.mjs src/styles dist/styles",
|
|
75
|
+
"build": "node ../../scripts/clean.mjs dist && tsgo && node ../../scripts/copy-assets.mjs src/styles dist/styles && node scripts/gen-theme-css.mjs",
|
|
76
76
|
"dev": "tsgo --watch",
|
|
77
77
|
"clean": "node ../../scripts/clean.mjs dist .turbo"
|
|
78
78
|
}
|