@fayz-ai/ui 0.9.0 → 0.10.1
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/README.md +2 -2
- package/dist/analytics/AnalyticsCard.d.ts +10 -0
- package/dist/analytics/AnalyticsCard.d.ts.map +1 -0
- package/dist/analytics/AnalyticsControls.d.ts +18 -0
- package/dist/analytics/AnalyticsControls.d.ts.map +1 -0
- package/dist/analytics/AnalyticsGrid.d.ts +16 -0
- package/dist/analytics/AnalyticsGrid.d.ts.map +1 -0
- package/dist/analytics/context.d.ts +58 -0
- package/dist/analytics/context.d.ts.map +1 -0
- package/dist/analytics/derive.d.ts +81 -0
- package/dist/analytics/derive.d.ts.map +1 -0
- package/dist/analytics/index.d.ts +13 -0
- package/dist/analytics/index.d.ts.map +1 -0
- package/dist/analytics/range.d.ts +22 -0
- package/dist/analytics/range.d.ts.map +1 -0
- package/dist/{chunk-PVIB724L.js → chunk-22EVFMS3.js} +5 -3
- package/dist/chunk-22EVFMS3.js.map +1 -0
- package/dist/{chunk-G6OKZ7WL.js → chunk-6V5MGYXH.js} +13 -9
- package/dist/chunk-6V5MGYXH.js.map +1 -0
- package/dist/{chunk-KV3MHB6N.js → chunk-H63TOSQ7.js} +196 -53
- package/dist/chunk-H63TOSQ7.js.map +1 -0
- package/dist/{chunk-OUPJDGKE.js → chunk-I6CPKAOD.js} +134 -37
- package/dist/chunk-I6CPKAOD.js.map +1 -0
- package/dist/{chunk-YRVE4FOD.js → chunk-OKZ6WQB3.js} +3 -3
- package/dist/chunk-OKZ6WQB3.js.map +1 -0
- package/dist/{chunk-S5KNM4D2.js → chunk-SEIY2F5F.js} +235 -107
- package/dist/chunk-SEIY2F5F.js.map +1 -0
- package/dist/{chunk-75EFDLST.js → chunk-VAKWUUVC.js} +157 -6
- package/dist/chunk-VAKWUUVC.js.map +1 -0
- package/dist/dashboard/OnboardingWidget.d.ts +2 -14
- package/dist/dashboard/OnboardingWidget.d.ts.map +1 -1
- package/dist/dashboard/SidebarOnboarding.d.ts +28 -0
- package/dist/dashboard/SidebarOnboarding.d.ts.map +1 -0
- package/dist/dashboard/index.d.ts +2 -0
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +4 -4
- package/dist/dashboard/types.d.ts +18 -0
- package/dist/dashboard/types.d.ts.map +1 -1
- package/dist/dashboard/useOnboardingProgress.d.ts +28 -0
- package/dist/dashboard/useOnboardingProgress.d.ts.map +1 -0
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +960 -14
- package/dist/index.js.map +1 -1
- package/dist/layout/AppShell.d.ts +14 -1
- package/dist/layout/AppShell.d.ts.map +1 -1
- package/dist/layout/ModulePage.d.ts +11 -2
- package/dist/layout/ModulePage.d.ts.map +1 -1
- package/dist/layout/Sidebar.d.ts +8 -1
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/index.js +4 -4
- package/dist/lib/cn.d.ts.map +1 -0
- package/dist/preset.d.ts +3 -0
- package/dist/preset.d.ts.map +1 -0
- package/dist/primitives/data-table.d.ts +19 -4
- package/dist/primitives/data-table.d.ts.map +1 -1
- package/dist/primitives/date-picker.d.ts +4 -2
- package/dist/primitives/date-picker.d.ts.map +1 -1
- package/dist/primitives/filter-chip.d.ts +26 -0
- package/dist/primitives/filter-chip.d.ts.map +1 -0
- package/dist/primitives/header-tabs.d.ts +32 -0
- package/dist/primitives/header-tabs.d.ts.map +1 -0
- package/dist/primitives/hint.d.ts +25 -0
- package/dist/primitives/hint.d.ts.map +1 -0
- package/dist/primitives/index.d.ts +7 -0
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/index.js +4 -4
- package/dist/primitives/list-view.d.ts +14 -1
- package/dist/primitives/list-view.d.ts.map +1 -1
- package/dist/primitives/page-header.d.ts +23 -0
- package/dist/primitives/page-header.d.ts.map +1 -0
- package/dist/primitives/stat-tiles.d.ts +30 -0
- package/dist/primitives/stat-tiles.d.ts.map +1 -0
- package/dist/primitives/switch.d.ts +11 -0
- package/dist/primitives/switch.d.ts.map +1 -0
- package/dist/stores/index.d.ts +1 -0
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/page-header.store.d.ts +69 -0
- package/dist/stores/page-header.store.d.ts.map +1 -0
- package/package.json +6 -15
- package/dist/chunk-75EFDLST.js.map +0 -1
- package/dist/chunk-G6OKZ7WL.js.map +0 -1
- package/dist/chunk-KV3MHB6N.js.map +0 -1
- package/dist/chunk-OUPJDGKE.js.map +0 -1
- package/dist/chunk-PVIB724L.js.map +0 -1
- package/dist/chunk-S5KNM4D2.js.map +0 -1
- package/dist/chunk-YRVE4FOD.js.map +0 -1
- package/dist/utils/cn.d.ts.map +0 -1
- package/src/dashboard/ChartWidget.tsx +0 -50
- package/src/dashboard/ChartWidgetInner.tsx +0 -83
- package/src/dashboard/DashboardCanvas.tsx +0 -210
- package/src/dashboard/DashboardCustomizeMenu.tsx +0 -53
- package/src/dashboard/DashboardGrid.tsx +0 -35
- package/src/dashboard/DashboardRange.tsx +0 -62
- package/src/dashboard/GoldCard.tsx +0 -38
- package/src/dashboard/KpiCard.tsx +0 -238
- package/src/dashboard/OnboardingWidget.tsx +0 -140
- package/src/dashboard/TableWidget.tsx +0 -51
- package/src/dashboard/define.ts +0 -53
- package/src/dashboard/icon.ts +0 -13
- package/src/dashboard/index.ts +0 -38
- package/src/dashboard/layout.ts +0 -50
- package/src/dashboard/preferences.ts +0 -71
- package/src/dashboard/types.ts +0 -41
- package/src/icons.ts +0 -66
- package/src/index.ts +0 -238
- package/src/layout/AppShell.tsx +0 -987
- package/src/layout/ContentSplit.tsx +0 -153
- package/src/layout/ModulePage.tsx +0 -466
- package/src/layout/PageTransition.tsx +0 -57
- package/src/layout/SaveBar.tsx +0 -247
- package/src/layout/Sidebar.tsx +0 -535
- package/src/layout/Topbar.tsx +0 -462
- package/src/layout/index.ts +0 -39
- package/src/layout/useCrossModuleBack.ts +0 -30
- package/src/primitives/Avatar.tsx +0 -48
- package/src/primitives/SearchCombobox.tsx +0 -216
- package/src/primitives/badge.tsx +0 -68
- package/src/primitives/breadcrumb.tsx +0 -43
- package/src/primitives/button.tsx +0 -60
- package/src/primitives/card.tsx +0 -79
- package/src/primitives/checkbox.tsx +0 -53
- package/src/primitives/confirm-dialog.tsx +0 -125
- package/src/primitives/currency-input.tsx +0 -121
- package/src/primitives/data-table.tsx +0 -160
- package/src/primitives/date-picker.tsx +0 -225
- package/src/primitives/dropdown.tsx +0 -196
- package/src/primitives/index.ts +0 -87
- package/src/primitives/input.tsx +0 -50
- package/src/primitives/list-view.tsx +0 -252
- package/src/primitives/markdown-editor.tsx +0 -75
- package/src/primitives/markdown.tsx +0 -169
- package/src/primitives/modal.tsx +0 -156
- package/src/primitives/phone-link.tsx +0 -138
- package/src/primitives/popover.tsx +0 -30
- package/src/primitives/search-select.tsx +0 -314
- package/src/primitives/segmented-control.tsx +0 -66
- package/src/primitives/select.tsx +0 -157
- package/src/primitives/separator.tsx +0 -29
- package/src/primitives/sheet.tsx +0 -181
- package/src/primitives/skeleton.tsx +0 -46
- package/src/primitives/tabs.tsx +0 -53
- package/src/primitives/time-picker.tsx +0 -148
- package/src/primitives/toast.tsx +0 -46
- package/src/primitives/tooltip.tsx +0 -28
- package/src/stores/index.ts +0 -10
- package/src/stores/layout.store.ts +0 -31
- package/src/stores/theme.store.ts +0 -457
- package/src/tailwind.ts +0 -43
- package/src/theme/index.ts +0 -94
- package/src/theme/preset.ts +0 -209
- package/src/theme/presets.ts +0 -106
- package/src/utils/cn.ts +0 -6
- /package/dist/{utils → lib}/cn.d.ts +0 -0
- /package/{src → dist}/styles.css +0 -0
|
@@ -1,457 +0,0 @@
|
|
|
1
|
-
import { create, type StoreApi, type UseBoundStore } from 'zustand'
|
|
2
|
-
|
|
3
|
-
// ---------------------------------------------------------------------------
|
|
4
|
-
// Theme token types
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
|
|
7
|
-
export interface SemanticColors {
|
|
8
|
-
primary: string
|
|
9
|
-
primaryForeground: string
|
|
10
|
-
secondary: string
|
|
11
|
-
secondaryForeground: string
|
|
12
|
-
accent: string
|
|
13
|
-
accentForeground: string
|
|
14
|
-
background: string
|
|
15
|
-
foreground: string
|
|
16
|
-
card: string
|
|
17
|
-
cardForeground: string
|
|
18
|
-
muted: string
|
|
19
|
-
mutedForeground: string
|
|
20
|
-
border: string
|
|
21
|
-
input: string
|
|
22
|
-
ring: string
|
|
23
|
-
popover: string
|
|
24
|
-
popoverForeground: string
|
|
25
|
-
destructive: string
|
|
26
|
-
destructiveForeground: string
|
|
27
|
-
success: string
|
|
28
|
-
successForeground: string
|
|
29
|
-
warning: string
|
|
30
|
-
warningForeground: string
|
|
31
|
-
// Layout surface colors
|
|
32
|
-
sidebar: string
|
|
33
|
-
sidebarForeground: string
|
|
34
|
-
sidebarBorder: string
|
|
35
|
-
sidebarAccent: string
|
|
36
|
-
sidebarAccentForeground: string
|
|
37
|
-
sidebarMuted: string
|
|
38
|
-
content: string
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface UIPerceptionTokens {
|
|
42
|
-
buttonRadius: string
|
|
43
|
-
cardRadius: string
|
|
44
|
-
inputRadius: string
|
|
45
|
-
modalRadius: string
|
|
46
|
-
fontFamily: string
|
|
47
|
-
fontFamilyMono: string
|
|
48
|
-
shadowSm: string
|
|
49
|
-
shadowMd: string
|
|
50
|
-
shadowLg: string
|
|
51
|
-
shadowButton?: string
|
|
52
|
-
shadowButtonPrimary?: string
|
|
53
|
-
shadowButtonInset?: string
|
|
54
|
-
surfaceBackdropFilter?: string
|
|
55
|
-
modalBackground?: string
|
|
56
|
-
modalBorder?: string
|
|
57
|
-
modalOverlayBackground?: string
|
|
58
|
-
modalOverlayBackdropFilter?: string
|
|
59
|
-
modalShadow?: string
|
|
60
|
-
glassEdgeGradient?: string
|
|
61
|
-
glassPrimaryEdgeGradient?: string
|
|
62
|
-
glassInnerHighlight?: string
|
|
63
|
-
fieldBackground?: string
|
|
64
|
-
fieldBorder?: string
|
|
65
|
-
fieldShadow?: string
|
|
66
|
-
buttonBackground?: string
|
|
67
|
-
buttonBackgroundHover?: string
|
|
68
|
-
buttonBorder?: string
|
|
69
|
-
buttonPrimaryBackground?: string
|
|
70
|
-
buttonPrimaryBackgroundHover?: string
|
|
71
|
-
buttonPrimaryBorder?: string
|
|
72
|
-
buttonBackdropFilter?: string
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface ThemeTokens {
|
|
76
|
-
name: string
|
|
77
|
-
colors: SemanticColors
|
|
78
|
-
perception: UIPerceptionTokens
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export interface CreateThemeOptions {
|
|
82
|
-
name?: string
|
|
83
|
-
colors?: Partial<SemanticColors>
|
|
84
|
-
/** Dark mode color overrides — applied instead of `colors` when in dark mode */
|
|
85
|
-
darkColors?: Partial<SemanticColors>
|
|
86
|
-
perception?: Partial<UIPerceptionTokens>
|
|
87
|
-
/** Shorthand: single HSL value that auto-derives primary, ring, and accent */
|
|
88
|
-
brand?: string
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// ---------------------------------------------------------------------------
|
|
92
|
-
// Built-in themes
|
|
93
|
-
// ---------------------------------------------------------------------------
|
|
94
|
-
|
|
95
|
-
export const lightTheme: ThemeTokens = {
|
|
96
|
-
name: 'light',
|
|
97
|
-
colors: {
|
|
98
|
-
primary: '0 0% 18.8%',
|
|
99
|
-
primaryForeground: '0 0% 100%',
|
|
100
|
-
secondary: '0 0% 96.9%',
|
|
101
|
-
secondaryForeground: '0 0% 18.8%',
|
|
102
|
-
accent: '0 0% 94.5%',
|
|
103
|
-
accentForeground: '0 0% 18.8%',
|
|
104
|
-
background: '0 0% 94.5%',
|
|
105
|
-
foreground: '0 0% 18.8%',
|
|
106
|
-
card: '0 0% 100%',
|
|
107
|
-
cardForeground: '0 0% 18.8%',
|
|
108
|
-
muted: '0 0% 96.9%',
|
|
109
|
-
mutedForeground: '0 0% 38%',
|
|
110
|
-
border: '0 0% 89%',
|
|
111
|
-
input: '0 0% 54.1%',
|
|
112
|
-
ring: '214 100% 41.4%',
|
|
113
|
-
popover: '0 0% 100%',
|
|
114
|
-
popoverForeground: '0 0% 18.8%',
|
|
115
|
-
destructive: '354 92% 41%',
|
|
116
|
-
destructiveForeground: '0 0% 100%',
|
|
117
|
-
success: '167 95% 25.1%',
|
|
118
|
-
successForeground: '0 0% 100%',
|
|
119
|
-
warning: '43 100% 50%',
|
|
120
|
-
warningForeground: '0 0% 18.8%',
|
|
121
|
-
sidebar: '0 0% 92.2%',
|
|
122
|
-
sidebarForeground: '0 0% 18.8%',
|
|
123
|
-
sidebarBorder: '0 0% 86.3%',
|
|
124
|
-
sidebarAccent: '0 0% 100%',
|
|
125
|
-
sidebarAccentForeground: '0 0% 18.8%',
|
|
126
|
-
sidebarMuted: '0 0% 38%',
|
|
127
|
-
content: '0 0% 94.5%',
|
|
128
|
-
},
|
|
129
|
-
perception: {
|
|
130
|
-
buttonRadius: '0.5rem',
|
|
131
|
-
cardRadius: '0.5rem',
|
|
132
|
-
inputRadius: '0.5rem',
|
|
133
|
-
modalRadius: '1rem',
|
|
134
|
-
fontFamily: 'Inter, ui-sans-serif, system-ui, -apple-system, sans-serif',
|
|
135
|
-
fontFamilyMono: 'JetBrains Mono, ui-monospace, SFMono-Regular, monospace',
|
|
136
|
-
shadowSm: '0 1px 0 rgba(0, 0, 0, 0.05), 0 1px 3px 0 rgba(26, 26, 26, 0.06), 0 1px 2px -1px rgba(26, 26, 26, 0.06)',
|
|
137
|
-
shadowMd: '0 1px 1px -1px rgba(26, 26, 26, 0.07), 0 4px 8px -2px rgba(26, 26, 26, 0.10)',
|
|
138
|
-
shadowLg: '0 4px 12px -2px rgba(26, 26, 26, 0.15), 0 1px 3px rgba(26, 26, 26, 0.08)',
|
|
139
|
-
shadowButton:
|
|
140
|
-
'inset 0 -1px 0 rgba(0,0,0,0.10), inset 0 1px 0 rgba(255,255,255,0.50), 0 1px 0 rgba(0,0,0,0.05)',
|
|
141
|
-
shadowButtonPrimary:
|
|
142
|
-
'inset 0 -1px 0 rgba(0,0,0,0.20), inset 0 1px 0 rgba(255,255,255,0.20), 0 1px 1.5px rgba(0,0,0,0.20)',
|
|
143
|
-
shadowButtonInset:
|
|
144
|
-
'inset 0 2px 1px -1px rgba(0,0,0,0.20), inset 0 0 0 1px rgba(0,0,0,0.05)',
|
|
145
|
-
surfaceBackdropFilter: 'none',
|
|
146
|
-
buttonBackground: 'hsl(var(--card))',
|
|
147
|
-
buttonBackgroundHover: 'hsl(var(--muted))',
|
|
148
|
-
buttonBorder: 'hsl(var(--border))',
|
|
149
|
-
buttonPrimaryBackground: 'hsl(var(--primary))',
|
|
150
|
-
buttonPrimaryBackgroundHover: 'hsl(var(--primary) / 0.9)',
|
|
151
|
-
buttonPrimaryBorder: 'hsl(var(--primary))',
|
|
152
|
-
buttonBackdropFilter: 'none',
|
|
153
|
-
},
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export const darkTheme: ThemeTokens = {
|
|
157
|
-
name: 'dark',
|
|
158
|
-
colors: {
|
|
159
|
-
primary: '0 0% 100%',
|
|
160
|
-
primaryForeground: '0 0% 10.2%',
|
|
161
|
-
secondary: '0 0% 18.8%',
|
|
162
|
-
secondaryForeground: '0 0% 89%',
|
|
163
|
-
accent: '0 0% 22.7%',
|
|
164
|
-
accentForeground: '0 0% 100%',
|
|
165
|
-
background: '0 0% 10.2%',
|
|
166
|
-
foreground: '0 0% 89%',
|
|
167
|
-
card: '0 0% 14.9%',
|
|
168
|
-
cardForeground: '0 0% 89%',
|
|
169
|
-
muted: '0 0% 18.8%',
|
|
170
|
-
mutedForeground: '0 0% 64.7%',
|
|
171
|
-
border: '0 0% 22.7%',
|
|
172
|
-
input: '0 0% 32.2%',
|
|
173
|
-
ring: '217 100% 68.4%',
|
|
174
|
-
popover: '0 0% 18.8%',
|
|
175
|
-
popoverForeground: '0 0% 89%',
|
|
176
|
-
destructive: '7 100% 44.9%',
|
|
177
|
-
destructiveForeground: '0 0% 100%',
|
|
178
|
-
success: '156 71% 42.5%',
|
|
179
|
-
successForeground: '0 0% 0%',
|
|
180
|
-
warning: '41 100% 65.1%',
|
|
181
|
-
warningForeground: '0 0% 10.2%',
|
|
182
|
-
sidebar: '0 0% 10.2%',
|
|
183
|
-
sidebarForeground: '0 0% 89%',
|
|
184
|
-
sidebarBorder: '0 0% 16.5%',
|
|
185
|
-
sidebarAccent: '0 0% 18.8%',
|
|
186
|
-
sidebarAccentForeground: '0 0% 100%',
|
|
187
|
-
sidebarMuted: '0 0% 64.7%',
|
|
188
|
-
content: '0 0% 10.2%',
|
|
189
|
-
},
|
|
190
|
-
perception: {
|
|
191
|
-
buttonRadius: '0.5rem',
|
|
192
|
-
cardRadius: '0.5rem',
|
|
193
|
-
inputRadius: '0.5rem',
|
|
194
|
-
modalRadius: '1rem',
|
|
195
|
-
fontFamily: 'Inter, ui-sans-serif, system-ui, -apple-system, sans-serif',
|
|
196
|
-
fontFamilyMono: 'JetBrains Mono, ui-monospace, SFMono-Regular, monospace',
|
|
197
|
-
shadowSm: '0 1px 0 rgba(0, 0, 0, 0.4), 0 1px 3px 0 rgba(0, 0, 0, 0.35), 0 1px 2px -1px rgba(0, 0, 0, 0.35)',
|
|
198
|
-
shadowMd: '0 1px 1px -1px rgba(0, 0, 0, 0.5), 0 4px 8px -2px rgba(0, 0, 0, 0.6)',
|
|
199
|
-
shadowLg: '0 4px 12px -2px rgba(0, 0, 0, 0.6), 0 1px 3px rgba(0, 0, 0, 0.4)',
|
|
200
|
-
shadowButton:
|
|
201
|
-
'inset 0 -1px 0 rgba(0,0,0,0.40), inset 0 1px 0 rgba(255,255,255,0.08), 0 1px 0 rgba(0,0,0,0.30)',
|
|
202
|
-
shadowButtonPrimary:
|
|
203
|
-
'inset 0 -1px 0 rgba(0,0,0,0.20), inset 0 1px 0 rgba(255,255,255,0.40), 0 1px 1.5px rgba(0,0,0,0.40)',
|
|
204
|
-
shadowButtonInset:
|
|
205
|
-
'inset 0 2px 1px -1px rgba(0,0,0,0.50), inset 0 0 0 1px rgba(0,0,0,0.20)',
|
|
206
|
-
surfaceBackdropFilter: 'none',
|
|
207
|
-
buttonBackground: 'hsl(var(--card))',
|
|
208
|
-
buttonBackgroundHover: 'hsl(var(--muted))',
|
|
209
|
-
buttonBorder: 'hsl(var(--border))',
|
|
210
|
-
buttonPrimaryBackground: 'hsl(var(--primary))',
|
|
211
|
-
buttonPrimaryBackgroundHover: 'hsl(var(--primary) / 0.9)',
|
|
212
|
-
buttonPrimaryBorder: 'hsl(var(--primary))',
|
|
213
|
-
buttonBackdropFilter: 'none',
|
|
214
|
-
},
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// ---------------------------------------------------------------------------
|
|
218
|
-
// CSS variable maps
|
|
219
|
-
// ---------------------------------------------------------------------------
|
|
220
|
-
|
|
221
|
-
const colorVarMap: Record<string, string> = {
|
|
222
|
-
primary: '--primary',
|
|
223
|
-
primaryForeground: '--primary-foreground',
|
|
224
|
-
secondary: '--secondary',
|
|
225
|
-
secondaryForeground: '--secondary-foreground',
|
|
226
|
-
accent: '--accent',
|
|
227
|
-
accentForeground: '--accent-foreground',
|
|
228
|
-
background: '--background',
|
|
229
|
-
foreground: '--foreground',
|
|
230
|
-
card: '--card',
|
|
231
|
-
cardForeground: '--card-foreground',
|
|
232
|
-
muted: '--muted',
|
|
233
|
-
mutedForeground: '--muted-foreground',
|
|
234
|
-
border: '--border',
|
|
235
|
-
input: '--input',
|
|
236
|
-
ring: '--ring',
|
|
237
|
-
popover: '--popover',
|
|
238
|
-
popoverForeground: '--popover-foreground',
|
|
239
|
-
destructive: '--destructive',
|
|
240
|
-
destructiveForeground: '--destructive-foreground',
|
|
241
|
-
success: '--success',
|
|
242
|
-
successForeground: '--success-foreground',
|
|
243
|
-
warning: '--warning',
|
|
244
|
-
warningForeground: '--warning-foreground',
|
|
245
|
-
sidebar: '--sidebar',
|
|
246
|
-
sidebarForeground: '--sidebar-foreground',
|
|
247
|
-
sidebarBorder: '--sidebar-border',
|
|
248
|
-
sidebarAccent: '--sidebar-accent',
|
|
249
|
-
sidebarAccentForeground: '--sidebar-accent-foreground',
|
|
250
|
-
sidebarMuted: '--sidebar-muted',
|
|
251
|
-
content: '--content',
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const perceptionVarMap: Record<string, string> = {
|
|
255
|
-
buttonRadius: '--button-radius',
|
|
256
|
-
cardRadius: '--card-radius',
|
|
257
|
-
inputRadius: '--input-radius',
|
|
258
|
-
modalRadius: '--modal-radius',
|
|
259
|
-
fontFamily: '--font-family',
|
|
260
|
-
fontFamilyMono: '--font-family-mono',
|
|
261
|
-
shadowSm: '--shadow-sm',
|
|
262
|
-
shadowMd: '--shadow-md',
|
|
263
|
-
shadowLg: '--shadow-lg',
|
|
264
|
-
shadowButton: '--shadow-button',
|
|
265
|
-
shadowButtonPrimary: '--shadow-button-primary',
|
|
266
|
-
shadowButtonInset: '--shadow-button-inset',
|
|
267
|
-
surfaceBackdropFilter: '--surface-backdrop-filter',
|
|
268
|
-
modalBackground: '--modal-bg',
|
|
269
|
-
modalBorder: '--modal-border',
|
|
270
|
-
modalOverlayBackground: '--modal-overlay-bg',
|
|
271
|
-
modalOverlayBackdropFilter: '--modal-overlay-backdrop-filter',
|
|
272
|
-
modalShadow: '--modal-shadow',
|
|
273
|
-
glassEdgeGradient: '--glass-edge-gradient',
|
|
274
|
-
glassPrimaryEdgeGradient: '--glass-primary-edge-gradient',
|
|
275
|
-
glassInnerHighlight: '--glass-inner-highlight',
|
|
276
|
-
fieldBackground: '--field-bg',
|
|
277
|
-
fieldBorder: '--field-border',
|
|
278
|
-
fieldShadow: '--field-shadow',
|
|
279
|
-
buttonBackground: '--button-bg',
|
|
280
|
-
buttonBackgroundHover: '--button-hover-bg',
|
|
281
|
-
buttonBorder: '--button-border',
|
|
282
|
-
buttonPrimaryBackground: '--button-primary-bg',
|
|
283
|
-
buttonPrimaryBackgroundHover: '--button-primary-hover-bg',
|
|
284
|
-
buttonPrimaryBorder: '--button-primary-border',
|
|
285
|
-
buttonBackdropFilter: '--button-backdrop-filter',
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function applyTheme(theme: ThemeTokens, element?: HTMLElement): void {
|
|
289
|
-
const target = element ?? document.documentElement
|
|
290
|
-
|
|
291
|
-
for (const [key, cssVar] of Object.entries(colorVarMap)) {
|
|
292
|
-
const value = theme.colors[key as keyof typeof theme.colors]
|
|
293
|
-
if (value) {
|
|
294
|
-
target.style.setProperty(cssVar, value)
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
for (const [key, cssVar] of Object.entries(perceptionVarMap)) {
|
|
299
|
-
const value = theme.perception[key as keyof typeof theme.perception]
|
|
300
|
-
if (value) {
|
|
301
|
-
target.style.setProperty(cssVar, value)
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// ---------------------------------------------------------------------------
|
|
307
|
-
// Store
|
|
308
|
-
// ---------------------------------------------------------------------------
|
|
309
|
-
|
|
310
|
-
type ThemeMode = 'light' | 'dark' | 'system'
|
|
311
|
-
|
|
312
|
-
const STORAGE_KEY = 'fayz-ui:theme-mode'
|
|
313
|
-
|
|
314
|
-
interface ThemeState {
|
|
315
|
-
mode: ThemeMode
|
|
316
|
-
resolvedMode: 'light' | 'dark'
|
|
317
|
-
/** Only the user's partial overrides — NOT a full theme */
|
|
318
|
-
overrides: CreateThemeOptions | null
|
|
319
|
-
setMode: (mode: ThemeMode) => void
|
|
320
|
-
setOverrides: (overrides: CreateThemeOptions | null) => void
|
|
321
|
-
initialize: () => void
|
|
322
|
-
// Keep old API name working
|
|
323
|
-
setCustomTheme: (theme: ThemeTokens | null) => void
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
function getSystemPreference(): 'light' | 'dark' {
|
|
327
|
-
if (typeof window === 'undefined') return 'light'
|
|
328
|
-
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
function getSavedMode(): ThemeMode {
|
|
332
|
-
if (typeof window === 'undefined') return 'light'
|
|
333
|
-
const saved = localStorage.getItem(STORAGE_KEY)
|
|
334
|
-
if (saved === 'light' || saved === 'dark' || saved === 'system') return saved
|
|
335
|
-
return 'light'
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function resolveMode(mode: ThemeMode): 'light' | 'dark' {
|
|
339
|
-
return mode === 'system' ? getSystemPreference() : mode
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/** Merge base theme (light or dark) with user's partial overrides */
|
|
343
|
-
function buildTheme(base: ThemeTokens, overrides: CreateThemeOptions | null): ThemeTokens {
|
|
344
|
-
if (!overrides) return base
|
|
345
|
-
|
|
346
|
-
const isDark = base.name === 'dark'
|
|
347
|
-
const colors = { ...base.colors }
|
|
348
|
-
|
|
349
|
-
// Brand shorthand: derive primary, ring, accent from single HSL
|
|
350
|
-
if (overrides.brand) {
|
|
351
|
-
colors.primary = overrides.brand
|
|
352
|
-
colors.primaryForeground = '0 0% 100%'
|
|
353
|
-
colors.ring = overrides.brand
|
|
354
|
-
const parts = overrides.brand.split(' ')
|
|
355
|
-
if (parts.length >= 3) {
|
|
356
|
-
const hue = (parseFloat(parts[0]) - 50 + 360) % 360
|
|
357
|
-
colors.accent = `${hue} ${parts[1]} ${parts[2]}`
|
|
358
|
-
colors.accentForeground = '0 0% 100%'
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Apply explicit color overrides.
|
|
363
|
-
const colorOverrides = isDark && overrides.darkColors
|
|
364
|
-
? overrides.darkColors
|
|
365
|
-
: overrides.colors
|
|
366
|
-
|
|
367
|
-
if (colorOverrides) {
|
|
368
|
-
for (const [key, value] of Object.entries(colorOverrides)) {
|
|
369
|
-
if (value !== undefined) {
|
|
370
|
-
(colors as any)[key] = value
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
return {
|
|
376
|
-
name: overrides.name ?? base.name,
|
|
377
|
-
colors,
|
|
378
|
-
perception: {
|
|
379
|
-
...base.perception,
|
|
380
|
-
...(overrides.perception ?? {}),
|
|
381
|
-
},
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
const STORE_KEY = '__fayz_ui_theme_store__'
|
|
386
|
-
|
|
387
|
-
function createThemeStore(): UseBoundStore<StoreApi<ThemeState>> {
|
|
388
|
-
// Window-level singleton to survive linked-package dual-module loading
|
|
389
|
-
if (typeof window !== 'undefined' && (window as any)[STORE_KEY]) {
|
|
390
|
-
return (window as any)[STORE_KEY]
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
const store = create<ThemeState>((set, get) => ({
|
|
394
|
-
mode: getSavedMode(),
|
|
395
|
-
resolvedMode: 'light',
|
|
396
|
-
overrides: null,
|
|
397
|
-
|
|
398
|
-
setMode: (mode) => {
|
|
399
|
-
const resolved = resolveMode(mode)
|
|
400
|
-
set({ mode, resolvedMode: resolved })
|
|
401
|
-
|
|
402
|
-
if (typeof window !== 'undefined') {
|
|
403
|
-
localStorage.setItem(STORAGE_KEY, mode)
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
const { overrides } = get()
|
|
407
|
-
const baseTheme = resolved === 'dark' ? darkTheme : lightTheme
|
|
408
|
-
const theme = buildTheme(baseTheme, overrides)
|
|
409
|
-
|
|
410
|
-
if (typeof document !== 'undefined') {
|
|
411
|
-
document.documentElement.classList.add('theme-transitioning')
|
|
412
|
-
applyTheme(theme)
|
|
413
|
-
document.documentElement.classList.toggle('dark', resolved === 'dark')
|
|
414
|
-
setTimeout(() => {
|
|
415
|
-
document.documentElement.classList.remove('theme-transitioning')
|
|
416
|
-
}, 450)
|
|
417
|
-
} else {
|
|
418
|
-
applyTheme(theme)
|
|
419
|
-
}
|
|
420
|
-
},
|
|
421
|
-
|
|
422
|
-
setOverrides: (overrides) => {
|
|
423
|
-
set({ overrides })
|
|
424
|
-
const { resolvedMode } = get()
|
|
425
|
-
const baseTheme = resolvedMode === 'dark' ? darkTheme : lightTheme
|
|
426
|
-
const theme = buildTheme(baseTheme, overrides)
|
|
427
|
-
applyTheme(theme)
|
|
428
|
-
},
|
|
429
|
-
|
|
430
|
-
// Legacy compat
|
|
431
|
-
setCustomTheme: (_theme) => {
|
|
432
|
-
// Ignore — callers should use setOverrides now
|
|
433
|
-
},
|
|
434
|
-
|
|
435
|
-
initialize: () => {
|
|
436
|
-
const { mode, setMode } = get()
|
|
437
|
-
setMode(mode)
|
|
438
|
-
|
|
439
|
-
if (typeof window !== 'undefined') {
|
|
440
|
-
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
|
441
|
-
const current = get()
|
|
442
|
-
if (current.mode === 'system') {
|
|
443
|
-
current.setMode('system')
|
|
444
|
-
}
|
|
445
|
-
})
|
|
446
|
-
}
|
|
447
|
-
},
|
|
448
|
-
}))
|
|
449
|
-
|
|
450
|
-
if (typeof window !== 'undefined') {
|
|
451
|
-
(window as any)[STORE_KEY] = store
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
return store
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
export const useThemeStore = createThemeStore()
|
package/src/tailwind.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import type { Config } from 'tailwindcss'
|
|
2
|
-
import { fayzUiPreset } from './theme/preset'
|
|
3
|
-
|
|
4
|
-
export interface FayzTailwindOptions {
|
|
5
|
-
/** Extra app-specific content globs, appended after the SDK globs. */
|
|
6
|
-
content?: string[]
|
|
7
|
-
/** SDK source location relative to the app root (default ../../fayz-sdk). */
|
|
8
|
-
sdkDir?: string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// SDK packages whose source ships Tailwind class names the app renders.
|
|
12
|
-
const SDK_PACKAGES = ['ui', 'saas', 'storefront', 'portal'] as const
|
|
13
|
-
const GLOB = '/src/**/*.{ts,tsx}'
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Shared Tailwind config for Fayz dogfood apps. Applies the Fayz UI preset and
|
|
17
|
-
* scans the SDK shell/UI/plugin source for class names — from node_modules (the
|
|
18
|
-
* Fayz editor sandbox / published) and a sibling `../../fayz-sdk` checkout (local
|
|
19
|
-
* dev). Whichever exists is scanned; missing globs are ignored. Apps no longer
|
|
20
|
-
* hand-maintain content globs or the relative-vs-npm preset import.
|
|
21
|
-
*
|
|
22
|
-
* import { fayzTailwind } from '@fayz-ai/ui/tailwind'
|
|
23
|
-
* export default fayzTailwind()
|
|
24
|
-
*/
|
|
25
|
-
export function fayzTailwind(opts: FayzTailwindOptions = {}): Config {
|
|
26
|
-
const sdk = opts.sdkDir ?? '../../fayz-sdk'
|
|
27
|
-
return {
|
|
28
|
-
presets: [fayzUiPreset as Config],
|
|
29
|
-
darkMode: 'class',
|
|
30
|
-
content: [
|
|
31
|
-
'./index.html',
|
|
32
|
-
'./src/**/*.{ts,tsx}',
|
|
33
|
-
// Published / sandbox: SDK installed in node_modules (packages ship src/).
|
|
34
|
-
...SDK_PACKAGES.map((p) => `./node_modules/@fayz-ai/${p}${GLOB}`),
|
|
35
|
-
'./node_modules/@fayz-ai/plugin-*/src/**/*.{ts,tsx}',
|
|
36
|
-
// Local dev: SDK as a sibling checkout (matches nothing in production).
|
|
37
|
-
...SDK_PACKAGES.map((p) => `${sdk}/packages/${p}${GLOB}`),
|
|
38
|
-
`${sdk}/plugins/*/src/**/*.{ts,tsx}`,
|
|
39
|
-
...(opts.content ?? []),
|
|
40
|
-
],
|
|
41
|
-
plugins: [],
|
|
42
|
-
}
|
|
43
|
-
}
|
package/src/theme/index.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import { useThemeStore, type CreateThemeOptions, type ThemeTokens, lightTheme, darkTheme } from '../stores/theme.store'
|
|
3
|
-
|
|
4
|
-
// ---------------------------------------------------------------------------
|
|
5
|
-
// ThemeProvider
|
|
6
|
-
// ---------------------------------------------------------------------------
|
|
7
|
-
|
|
8
|
-
export interface ThemeProviderProps {
|
|
9
|
-
children: React.ReactNode
|
|
10
|
-
/** Initial theme overrides to apply on mount */
|
|
11
|
-
overrides?: CreateThemeOptions | null
|
|
12
|
-
/** Default mode. Defaults to 'light'. */
|
|
13
|
-
defaultMode?: 'light' | 'dark' | 'system'
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function ThemeProvider({ children, overrides, defaultMode }: ThemeProviderProps) {
|
|
17
|
-
const initialize = useThemeStore((s) => s.initialize)
|
|
18
|
-
const setMode = useThemeStore((s) => s.setMode)
|
|
19
|
-
const setOverrides = useThemeStore((s) => s.setOverrides)
|
|
20
|
-
|
|
21
|
-
React.useEffect(() => {
|
|
22
|
-
if (defaultMode) {
|
|
23
|
-
setMode(defaultMode)
|
|
24
|
-
}
|
|
25
|
-
if (overrides !== undefined) {
|
|
26
|
-
setOverrides(overrides)
|
|
27
|
-
}
|
|
28
|
-
initialize()
|
|
29
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
30
|
-
}, [])
|
|
31
|
-
|
|
32
|
-
return children as React.ReactElement
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ---------------------------------------------------------------------------
|
|
36
|
-
// useTheme
|
|
37
|
-
// ---------------------------------------------------------------------------
|
|
38
|
-
|
|
39
|
-
export function useTheme() {
|
|
40
|
-
const mode = useThemeStore((s) => s.mode)
|
|
41
|
-
const resolvedMode = useThemeStore((s) => s.resolvedMode)
|
|
42
|
-
const overrides = useThemeStore((s) => s.overrides)
|
|
43
|
-
const setMode = useThemeStore((s) => s.setMode)
|
|
44
|
-
const setOverrides = useThemeStore((s) => s.setOverrides)
|
|
45
|
-
|
|
46
|
-
return {
|
|
47
|
-
mode,
|
|
48
|
-
resolvedMode,
|
|
49
|
-
isDark: resolvedMode === 'dark',
|
|
50
|
-
overrides,
|
|
51
|
-
setMode,
|
|
52
|
-
setOverrides,
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// ---------------------------------------------------------------------------
|
|
57
|
-
// createTheme — build a ThemeTokens object from partial overrides
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
|
-
|
|
60
|
-
export function createTheme(overrides: CreateThemeOptions): ThemeTokens {
|
|
61
|
-
const colors = { ...lightTheme.colors, ...overrides.colors }
|
|
62
|
-
|
|
63
|
-
// Brand shorthand: auto-derive primary, ring, accent from single HSL.
|
|
64
|
-
// Explicit `colors.*` overrides win — the shorthand is a default, not a
|
|
65
|
-
// mandate, so an app can pin any one of these without dropping the rest.
|
|
66
|
-
if (overrides.brand) {
|
|
67
|
-
const given = overrides.colors ?? {}
|
|
68
|
-
if (given.primary == null) colors.primary = overrides.brand
|
|
69
|
-
if (given.primaryForeground == null) colors.primaryForeground = '0 0% 100%'
|
|
70
|
-
if (given.ring == null) colors.ring = overrides.brand
|
|
71
|
-
const parts = overrides.brand.split(' ')
|
|
72
|
-
if (parts.length >= 3) {
|
|
73
|
-
const hue = (parseFloat(parts[0]) - 50 + 360) % 360
|
|
74
|
-
if (given.accent == null) colors.accent = `${hue} ${parts[1]} ${parts[2]}`
|
|
75
|
-
if (given.accentForeground == null) colors.accentForeground = '0 0% 100%'
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
name: overrides.name ?? lightTheme.name,
|
|
81
|
-
colors,
|
|
82
|
-
perception: {
|
|
83
|
-
...lightTheme.perception,
|
|
84
|
-
...overrides.perception,
|
|
85
|
-
},
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Re-export types for convenience
|
|
90
|
-
export type { CreateThemeOptions, ThemeTokens }
|
|
91
|
-
export { lightTheme, darkTheme }
|
|
92
|
-
export { fayzUiPreset } from './preset'
|
|
93
|
-
export { createFayzTheme, fayzThemePresets } from './presets'
|
|
94
|
-
export type { FayzThemePresetId } from './presets'
|