@titan-design/react-ui 0.2.5 → 0.2.7
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/chunk-3VLOBS6O.mjs +846 -0
- package/dist/chunk-3VLOBS6O.mjs.map +1 -0
- package/dist/{chunk-UXVRPOME.mjs → chunk-5SSKGS6E.mjs} +3 -783
- package/dist/chunk-5SSKGS6E.mjs.map +1 -0
- package/dist/index.d.mts +1005 -4
- package/dist/index.d.ts +1005 -4
- package/dist/index.js +6043 -213
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5901 -177
- package/dist/index.mjs.map +1 -1
- package/dist/theme/index.d.mts +57 -1
- package/dist/theme/index.d.ts +57 -1
- package/dist/theme/index.js +63 -0
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +2 -1
- package/dist/theme/tokens-css.d.mts +18 -0
- package/dist/theme/tokens-css.d.ts +18 -0
- package/dist/theme/tokens-css.js +289 -0
- package/dist/theme/tokens-css.js.map +1 -0
- package/dist/theme/tokens-css.mjs +24 -0
- package/dist/theme/tokens-css.mjs.map +1 -0
- package/docs/WEB_SETUP.md +217 -0
- package/package.json +17 -5
- package/src/components/custom/DateTime/DateTime.stories.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.stories.tsx +45 -0
- package/src/components/custom/Gauge/Gauge.test.tsx +71 -0
- package/src/components/custom/Gauge/Gauge.tsx +167 -0
- package/src/components/custom/Gauge/index.ts +2 -0
- package/src/components/custom/Scatter/Scatter.stories.tsx +85 -0
- package/src/components/custom/Scatter/Scatter.test.tsx +96 -0
- package/src/components/custom/Scatter/Scatter.tsx +260 -0
- package/src/components/custom/Scatter/index.ts +2 -0
- package/src/components/custom/Sidebar/Sidebar.tsx +1 -1
- package/src/components/custom/Treemap/Treemap.stories.tsx +60 -0
- package/src/components/custom/Treemap/Treemap.test.tsx +67 -0
- package/src/components/custom/Treemap/Treemap.tsx +192 -0
- package/src/components/custom/Treemap/index.ts +2 -0
- package/src/components/custom/Workout/BaseBadge.stories.tsx +75 -0
- package/src/components/custom/Workout/BaseBadge.test.tsx +102 -0
- package/src/components/custom/Workout/BaseBadge.tsx +113 -0
- package/src/components/custom/Workout/BodyMap.stories.tsx +121 -0
- package/src/components/custom/Workout/BodyMap.test.tsx +124 -0
- package/src/components/custom/Workout/BodyMap.tsx +348 -0
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +171 -0
- package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +225 -0
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +478 -0
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +125 -0
- package/src/components/custom/Workout/CapacityBandChart.test.tsx +193 -0
- package/src/components/custom/Workout/CapacityBandChart.tsx +493 -0
- package/src/components/custom/Workout/DeviationBar.stories.tsx +58 -0
- package/src/components/custom/Workout/DeviationBar.test.tsx +86 -0
- package/src/components/custom/Workout/DeviationBar.tsx +78 -0
- package/src/components/custom/Workout/ExerciseCard.stories.tsx +186 -0
- package/src/components/custom/Workout/ExerciseCard.test.tsx +319 -0
- package/src/components/custom/Workout/ExerciseCard.tsx +429 -0
- package/src/components/custom/Workout/InputBar.stories.tsx +75 -0
- package/src/components/custom/Workout/InputBar.test.tsx +116 -0
- package/src/components/custom/Workout/InputBar.tsx +163 -0
- package/src/components/custom/Workout/IntensityBar.stories.tsx +60 -0
- package/src/components/custom/Workout/IntensityBar.test.tsx +113 -0
- package/src/components/custom/Workout/IntensityBar.tsx +166 -0
- package/src/components/custom/Workout/MesoCard.stories.tsx +152 -0
- package/src/components/custom/Workout/MesoCard.test.tsx +170 -0
- package/src/components/custom/Workout/MesoCard.tsx +235 -0
- package/src/components/custom/Workout/MesoProgressBar.stories.tsx +85 -0
- package/src/components/custom/Workout/MesoProgressBar.test.tsx +141 -0
- package/src/components/custom/Workout/MesoProgressBar.tsx +161 -0
- package/src/components/custom/Workout/MesoStatusCard.stories.tsx +126 -0
- package/src/components/custom/Workout/MesoStatusCard.test.tsx +209 -0
- package/src/components/custom/Workout/MesoStatusCard.tsx +456 -0
- package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +118 -0
- package/src/components/custom/Workout/MuscleGroupChip.test.tsx +91 -0
- package/src/components/custom/Workout/MuscleGroupChip.tsx +92 -0
- package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +94 -0
- package/src/components/custom/Workout/PlaceholderStrip.test.tsx +83 -0
- package/src/components/custom/Workout/PlaceholderStrip.tsx +91 -0
- package/src/components/custom/Workout/PrBadge.stories.tsx +105 -0
- package/src/components/custom/Workout/PrBadge.test.tsx +111 -0
- package/src/components/custom/Workout/PrBadge.tsx +103 -0
- package/src/components/custom/Workout/PrHistoryModal.stories.tsx +116 -0
- package/src/components/custom/Workout/PrHistoryModal.test.tsx +161 -0
- package/src/components/custom/Workout/PrHistoryModal.tsx +244 -0
- package/src/components/custom/Workout/ReadinessCheck.stories.tsx +126 -0
- package/src/components/custom/Workout/ReadinessCheck.test.tsx +181 -0
- package/src/components/custom/Workout/ReadinessCheck.tsx +266 -0
- package/src/components/custom/Workout/RestTimer.tsx +8 -6
- package/src/components/custom/Workout/SetRow.stories.tsx +165 -0
- package/src/components/custom/Workout/SetRow.test.tsx +222 -0
- package/src/components/custom/Workout/SetRow.tsx +253 -0
- package/src/components/custom/Workout/Sparkline.stories.tsx +125 -0
- package/src/components/custom/Workout/Sparkline.test.tsx +113 -0
- package/src/components/custom/Workout/Sparkline.tsx +188 -0
- package/src/components/custom/Workout/StatusDot.stories.tsx +150 -0
- package/src/components/custom/Workout/StatusDot.test.tsx +165 -0
- package/src/components/custom/Workout/StatusDot.tsx +159 -0
- package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +130 -0
- package/src/components/custom/Workout/StrengthTrendChart.test.tsx +217 -0
- package/src/components/custom/Workout/StrengthTrendChart.tsx +628 -0
- package/src/components/custom/Workout/SupersetWrapper.tsx +1 -2
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +66 -0
- package/src/components/custom/Workout/TempoDisplay.test.tsx +90 -0
- package/src/components/custom/Workout/TempoDisplay.tsx +207 -0
- package/src/components/custom/Workout/VelocityStrip.stories.tsx +125 -0
- package/src/components/custom/Workout/VelocityStrip.test.tsx +234 -0
- package/src/components/custom/Workout/VelocityStrip.tsx +287 -0
- package/src/components/custom/Workout/WeekRow.stories.tsx +121 -0
- package/src/components/custom/Workout/WeekRow.test.tsx +117 -0
- package/src/components/custom/Workout/WeekRow.tsx +140 -0
- package/src/components/custom/Workout/WeightBadge.stories.tsx +87 -0
- package/src/components/custom/Workout/WeightBadge.test.tsx +164 -0
- package/src/components/custom/Workout/WeightBadge.tsx +113 -0
- package/src/components/custom/Workout/WorkoutCard.stories.tsx +135 -0
- package/src/components/custom/Workout/WorkoutCard.test.tsx +172 -0
- package/src/components/custom/Workout/WorkoutCard.tsx +226 -0
- package/src/components/custom/Workout/WorkoutPill.stories.tsx +63 -0
- package/src/components/custom/Workout/WorkoutPill.test.tsx +153 -0
- package/src/components/custom/Workout/WorkoutPill.tsx +177 -0
- package/src/components/custom/Workout/index.ts +113 -0
- package/src/components/custom/Workout/muscleTaxonomy.ts +252 -0
- package/src/components/custom/index.ts +3 -0
- package/src/components/custom/stepper/Stepper.stories.tsx +1 -1
- package/src/components/custom/stepper/Stepper.tsx +2 -2
- package/src/components/ui/autocomplete/Autocomplete.stories.tsx +1 -1
- package/src/components/ui/autocomplete/Autocomplete.tsx +1 -1
- package/src/components/ui/card/Card.tsx +1 -1
- package/src/components/ui/checkbox/Checkbox.tsx +1 -1
- package/src/components/ui/collapse/Collapse.tsx +1 -1
- package/src/components/ui/data-row/DataRow.stories.tsx +1 -1
- package/src/components/ui/drawer/Drawer.tsx +3 -3
- package/src/components/ui/form-field/FormField.tsx +1 -1
- package/src/components/ui/help-tip/HelpTip.tsx +1 -1
- package/src/components/ui/menu/Menu.tsx +2 -2
- package/src/components/ui/pill/Pill.tsx +1 -1
- package/src/components/ui/popover/Popover.stories.tsx +2 -2
- package/src/components/ui/popover/Popover.tsx +1 -1
- package/src/components/ui/radio/Radio.stories.tsx +1 -1
- package/src/components/ui/section/Section.stories.tsx +4 -4
- package/src/components/ui/select/Select.tsx +1 -1
- package/src/components/ui/stack/Stack.stories.tsx +4 -4
- package/src/components/ui/tabs/Tabs.tsx +2 -2
- package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +1 -1
- package/src/components/ui/toolbar-button/ToolbarButton.tsx +1 -1
- package/src/examples/react-hook-form/ControlledFields.tsx +171 -0
- package/src/examples/react-hook-form/ReactHookForm.stories.tsx +51 -0
- package/src/examples/react-hook-form/ReactHookForm.test.tsx +61 -0
- package/src/examples/react-hook-form/RhfContactForm.tsx +99 -0
- package/src/stories/PresetShowcase.stories.tsx +15 -15
- package/src/theme/index.ts +2 -1
- package/src/theme/manifest/css-property-manifest.example.json +79 -0
- package/src/theme/manifest/css-property-manifest.schema.json +93 -0
- package/src/theme/manifest/css-property-manifest.test.ts +81 -0
- package/src/theme/manifest/css-property-manifest.types.ts +49 -0
- package/src/theme/manifest/css-property-manifest.validate.ts +84 -0
- package/src/theme/manifest/index.ts +11 -0
- package/src/theme/tokens-css.test.ts +28 -0
- package/src/theme/tokens-css.ts +34 -0
- package/src/theme/workout-tokens.ts +61 -0
- package/dist/chunk-UXVRPOME.mjs.map +0 -1
|
@@ -0,0 +1,846 @@
|
|
|
1
|
+
import { semanticColorsLight, semanticColorsDark } from './chunk-5SSKGS6E.mjs';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
|
|
4
|
+
function hexToRgb(hex) {
|
|
5
|
+
const cleaned = hex.replace("#", "");
|
|
6
|
+
let r, g, b;
|
|
7
|
+
if (cleaned.length === 3) {
|
|
8
|
+
r = parseInt(cleaned[0] + cleaned[0], 16);
|
|
9
|
+
g = parseInt(cleaned[1] + cleaned[1], 16);
|
|
10
|
+
b = parseInt(cleaned[2] + cleaned[2], 16);
|
|
11
|
+
} else if (cleaned.length === 6) {
|
|
12
|
+
r = parseInt(cleaned.slice(0, 2), 16);
|
|
13
|
+
g = parseInt(cleaned.slice(2, 4), 16);
|
|
14
|
+
b = parseInt(cleaned.slice(4, 6), 16);
|
|
15
|
+
} else {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return { r, g, b };
|
|
19
|
+
}
|
|
20
|
+
function rgbToHsv(r, g, b) {
|
|
21
|
+
const rNorm = r / 255;
|
|
22
|
+
const gNorm = g / 255;
|
|
23
|
+
const bNorm = b / 255;
|
|
24
|
+
const max = Math.max(rNorm, gNorm, bNorm);
|
|
25
|
+
const min = Math.min(rNorm, gNorm, bNorm);
|
|
26
|
+
const delta = max - min;
|
|
27
|
+
const v = max;
|
|
28
|
+
const s = max === 0 ? 0 : delta / max;
|
|
29
|
+
let h = 0;
|
|
30
|
+
if (delta !== 0) {
|
|
31
|
+
if (max === rNorm) {
|
|
32
|
+
h = 60 * ((gNorm - bNorm) / delta % 6);
|
|
33
|
+
} else if (max === gNorm) {
|
|
34
|
+
h = 60 * ((bNorm - rNorm) / delta + 2);
|
|
35
|
+
} else {
|
|
36
|
+
h = 60 * ((rNorm - gNorm) / delta + 4);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (h < 0) h += 360;
|
|
40
|
+
return { h, s, v };
|
|
41
|
+
}
|
|
42
|
+
function hsvToRgb(h, s, v) {
|
|
43
|
+
const c = v * s;
|
|
44
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
45
|
+
const m = v - c;
|
|
46
|
+
let rPrime, gPrime, bPrime;
|
|
47
|
+
if (h >= 0 && h < 60) {
|
|
48
|
+
rPrime = c;
|
|
49
|
+
gPrime = x;
|
|
50
|
+
bPrime = 0;
|
|
51
|
+
} else if (h >= 60 && h < 120) {
|
|
52
|
+
rPrime = x;
|
|
53
|
+
gPrime = c;
|
|
54
|
+
bPrime = 0;
|
|
55
|
+
} else if (h >= 120 && h < 180) {
|
|
56
|
+
rPrime = 0;
|
|
57
|
+
gPrime = c;
|
|
58
|
+
bPrime = x;
|
|
59
|
+
} else if (h >= 180 && h < 240) {
|
|
60
|
+
rPrime = 0;
|
|
61
|
+
gPrime = x;
|
|
62
|
+
bPrime = c;
|
|
63
|
+
} else if (h >= 240 && h < 300) {
|
|
64
|
+
rPrime = x;
|
|
65
|
+
gPrime = 0;
|
|
66
|
+
bPrime = c;
|
|
67
|
+
} else {
|
|
68
|
+
rPrime = c;
|
|
69
|
+
gPrime = 0;
|
|
70
|
+
bPrime = x;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
r: Math.round((rPrime + m) * 255),
|
|
74
|
+
g: Math.round((gPrime + m) * 255),
|
|
75
|
+
b: Math.round((bPrime + m) * 255)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function rgbToHex(r, g, b) {
|
|
79
|
+
const toHex = (n) => {
|
|
80
|
+
const clamped = Math.max(0, Math.min(255, Math.round(n)));
|
|
81
|
+
return clamped.toString(16).padStart(2, "0");
|
|
82
|
+
};
|
|
83
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
84
|
+
}
|
|
85
|
+
function lighten(hex, amount = 0.1) {
|
|
86
|
+
const rgb = hexToRgb(hex);
|
|
87
|
+
if (!rgb) return hex;
|
|
88
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
89
|
+
const newV = Math.min(1, hsv.v + amount);
|
|
90
|
+
const newRgb = hsvToRgb(hsv.h, hsv.s, newV);
|
|
91
|
+
return rgbToHex(newRgb.r, newRgb.g, newRgb.b);
|
|
92
|
+
}
|
|
93
|
+
function darken(hex, amount = 0.1) {
|
|
94
|
+
const rgb = hexToRgb(hex);
|
|
95
|
+
if (!rgb) return hex;
|
|
96
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
97
|
+
const newV = Math.max(0, hsv.v - amount);
|
|
98
|
+
const newRgb = hsvToRgb(hsv.h, hsv.s, newV);
|
|
99
|
+
return rgbToHex(newRgb.r, newRgb.g, newRgb.b);
|
|
100
|
+
}
|
|
101
|
+
function getHoverColors(bgColor, intensity = "medium") {
|
|
102
|
+
const amounts = {
|
|
103
|
+
subtle: 0.01,
|
|
104
|
+
medium: 0.02,
|
|
105
|
+
strong: 0.03
|
|
106
|
+
};
|
|
107
|
+
const amount = amounts[intensity];
|
|
108
|
+
return {
|
|
109
|
+
raised: lighten(bgColor, amount),
|
|
110
|
+
// Raised hover: lighten (lifting up)
|
|
111
|
+
pressed: darken(bgColor, amount)
|
|
112
|
+
// Pressed hover: darken (pressing down)
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function isDark(hex) {
|
|
116
|
+
const rgb = hexToRgb(hex);
|
|
117
|
+
if (!rgb) return true;
|
|
118
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
119
|
+
return hsv.v < 0.6;
|
|
120
|
+
}
|
|
121
|
+
var shadowColors = {
|
|
122
|
+
// For charcoal surfaces (~#2C2C2C to #3C3C3C)
|
|
123
|
+
charcoal: {
|
|
124
|
+
dark: "rgba(0, 0, 0, 0.5)",
|
|
125
|
+
light: "rgba(255, 255, 255, 0.12)",
|
|
126
|
+
// brighter for crisp rim light
|
|
127
|
+
darker: "rgba(0, 0, 0, 0.6)"
|
|
128
|
+
},
|
|
129
|
+
// For neutral dark surfaces (~#1F2937)
|
|
130
|
+
neutralDark: {
|
|
131
|
+
dark: "rgba(0, 0, 0, 0.4)",
|
|
132
|
+
light: "rgba(255, 255, 255, 0.08)",
|
|
133
|
+
darker: "rgba(0, 0, 0, 0.5)"
|
|
134
|
+
},
|
|
135
|
+
// For light surfaces (white/light gray backgrounds)
|
|
136
|
+
neutralLight: {
|
|
137
|
+
dark: "rgba(0, 0, 0, 0.15)",
|
|
138
|
+
// Visible dark shadow for depth on light backgrounds
|
|
139
|
+
light: "rgba(255, 255, 255, 1)",
|
|
140
|
+
// Bright highlight for raised effect (visible on light gray)
|
|
141
|
+
darker: "rgba(0, 0, 0, 0.2)"
|
|
142
|
+
// Deeper shadow for pressed states
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
var intensityConfig = {
|
|
146
|
+
subtle: { offset: 1, blur: 2 },
|
|
147
|
+
// very light, barely visible
|
|
148
|
+
medium: { offset: 2, blur: 4 },
|
|
149
|
+
// noticeable but restrained
|
|
150
|
+
strong: { offset: 2, blur: 5 }
|
|
151
|
+
// slightly deeper blur, same offset as medium
|
|
152
|
+
};
|
|
153
|
+
function createRaisedShadow(surface = "charcoal", intensity = "medium") {
|
|
154
|
+
const colors = shadowColors[surface];
|
|
155
|
+
const { offset, blur } = intensityConfig[intensity];
|
|
156
|
+
const rimBlur = 1;
|
|
157
|
+
return Platform.select({
|
|
158
|
+
web: {
|
|
159
|
+
boxShadow: `${offset}px ${offset}px ${blur}px ${colors.dark}, -${offset}px -${offset}px ${rimBlur}px ${colors.light}`
|
|
160
|
+
},
|
|
161
|
+
default: {
|
|
162
|
+
// React Native shadow approximation (limited compared to web)
|
|
163
|
+
shadowColor: "#000",
|
|
164
|
+
shadowOffset: { width: offset, height: offset },
|
|
165
|
+
shadowOpacity: 0.3,
|
|
166
|
+
shadowRadius: blur / 2,
|
|
167
|
+
elevation: offset
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function createPressedShadow(surface = "charcoal", intensity = "medium") {
|
|
172
|
+
const colors = shadowColors[surface];
|
|
173
|
+
const { offset, blur } = intensityConfig[intensity];
|
|
174
|
+
const rimOffset = 1;
|
|
175
|
+
const rimBlur = 1;
|
|
176
|
+
return Platform.select({
|
|
177
|
+
web: {
|
|
178
|
+
boxShadow: `inset ${offset}px ${offset}px ${blur}px ${colors.darker}, inset -${rimOffset}px -${rimOffset}px ${rimBlur}px ${colors.light}`
|
|
179
|
+
},
|
|
180
|
+
default: {
|
|
181
|
+
// React Native doesn't support inset shadows, approximate with darker bg
|
|
182
|
+
shadowOpacity: 0,
|
|
183
|
+
elevation: 0
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function createFlatShadow() {
|
|
188
|
+
return Platform.select({
|
|
189
|
+
web: {
|
|
190
|
+
boxShadow: "none"
|
|
191
|
+
},
|
|
192
|
+
default: {
|
|
193
|
+
shadowOpacity: 0,
|
|
194
|
+
elevation: 0
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
function createRaisedHoverShadow(surface = "charcoal", intensity = "medium") {
|
|
199
|
+
const colors = shadowColors[surface];
|
|
200
|
+
const { offset, blur } = intensityConfig[intensity];
|
|
201
|
+
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
202
|
+
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
203
|
+
const rimBlur = 1;
|
|
204
|
+
return Platform.select({
|
|
205
|
+
web: {
|
|
206
|
+
// Keep same offsets as normal state for rim to prevent "shrinking" effect
|
|
207
|
+
boxShadow: `${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${colors.dark}, -${offset}px -${offset}px ${rimBlur}px ${colors.light}`
|
|
208
|
+
},
|
|
209
|
+
default: {
|
|
210
|
+
shadowColor: "#000",
|
|
211
|
+
shadowOffset: { width: hoverOffset, height: hoverOffset },
|
|
212
|
+
shadowOpacity: 0.2,
|
|
213
|
+
shadowRadius: hoverBlur / 2,
|
|
214
|
+
elevation: hoverOffset
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function createPressedHoverShadow(surface = "charcoal", intensity = "medium") {
|
|
219
|
+
const colors = shadowColors[surface];
|
|
220
|
+
const { offset, blur } = intensityConfig[intensity];
|
|
221
|
+
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
222
|
+
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
223
|
+
const rimBlur = 1;
|
|
224
|
+
return Platform.select({
|
|
225
|
+
web: {
|
|
226
|
+
// Keep rim offset at 1px (same as pressed normal) to prevent "shrinking" effect
|
|
227
|
+
boxShadow: `inset ${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${colors.darker}, inset -1px -1px ${rimBlur}px ${colors.light}`
|
|
228
|
+
},
|
|
229
|
+
default: {
|
|
230
|
+
shadowOpacity: 0,
|
|
231
|
+
elevation: 0
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
var neumorphicShadows = {
|
|
236
|
+
// Charcoal surface shadows (for dark toolbars, cards)
|
|
237
|
+
charcoal: {
|
|
238
|
+
raised: {
|
|
239
|
+
subtle: createRaisedShadow("charcoal", "subtle"),
|
|
240
|
+
medium: createRaisedShadow("charcoal", "medium"),
|
|
241
|
+
strong: createRaisedShadow("charcoal", "strong")
|
|
242
|
+
},
|
|
243
|
+
raisedHover: {
|
|
244
|
+
subtle: createRaisedHoverShadow("charcoal", "subtle"),
|
|
245
|
+
medium: createRaisedHoverShadow("charcoal", "medium"),
|
|
246
|
+
strong: createRaisedHoverShadow("charcoal", "strong")
|
|
247
|
+
},
|
|
248
|
+
pressed: {
|
|
249
|
+
subtle: createPressedShadow("charcoal", "subtle"),
|
|
250
|
+
medium: createPressedShadow("charcoal", "medium"),
|
|
251
|
+
strong: createPressedShadow("charcoal", "strong")
|
|
252
|
+
},
|
|
253
|
+
pressedHover: {
|
|
254
|
+
subtle: createPressedHoverShadow("charcoal", "subtle"),
|
|
255
|
+
medium: createPressedHoverShadow("charcoal", "medium"),
|
|
256
|
+
strong: createPressedHoverShadow("charcoal", "strong")
|
|
257
|
+
},
|
|
258
|
+
flat: createFlatShadow()
|
|
259
|
+
},
|
|
260
|
+
// Neutral dark surface shadows
|
|
261
|
+
neutralDark: {
|
|
262
|
+
raised: {
|
|
263
|
+
subtle: createRaisedShadow("neutralDark", "subtle"),
|
|
264
|
+
medium: createRaisedShadow("neutralDark", "medium"),
|
|
265
|
+
strong: createRaisedShadow("neutralDark", "strong")
|
|
266
|
+
},
|
|
267
|
+
raisedHover: {
|
|
268
|
+
subtle: createRaisedHoverShadow("neutralDark", "subtle"),
|
|
269
|
+
medium: createRaisedHoverShadow("neutralDark", "medium"),
|
|
270
|
+
strong: createRaisedHoverShadow("neutralDark", "strong")
|
|
271
|
+
},
|
|
272
|
+
pressed: {
|
|
273
|
+
subtle: createPressedShadow("neutralDark", "subtle"),
|
|
274
|
+
medium: createPressedShadow("neutralDark", "medium"),
|
|
275
|
+
strong: createPressedShadow("neutralDark", "strong")
|
|
276
|
+
},
|
|
277
|
+
pressedHover: {
|
|
278
|
+
subtle: createPressedHoverShadow("neutralDark", "subtle"),
|
|
279
|
+
medium: createPressedHoverShadow("neutralDark", "medium"),
|
|
280
|
+
strong: createPressedHoverShadow("neutralDark", "strong")
|
|
281
|
+
},
|
|
282
|
+
flat: createFlatShadow()
|
|
283
|
+
},
|
|
284
|
+
// Neutral light surface shadows
|
|
285
|
+
neutralLight: {
|
|
286
|
+
raised: {
|
|
287
|
+
subtle: createRaisedShadow("neutralLight", "subtle"),
|
|
288
|
+
medium: createRaisedShadow("neutralLight", "medium"),
|
|
289
|
+
strong: createRaisedShadow("neutralLight", "strong")
|
|
290
|
+
},
|
|
291
|
+
raisedHover: {
|
|
292
|
+
subtle: createRaisedHoverShadow("neutralLight", "subtle"),
|
|
293
|
+
medium: createRaisedHoverShadow("neutralLight", "medium"),
|
|
294
|
+
strong: createRaisedHoverShadow("neutralLight", "strong")
|
|
295
|
+
},
|
|
296
|
+
pressed: {
|
|
297
|
+
subtle: createPressedShadow("neutralLight", "subtle"),
|
|
298
|
+
medium: createPressedShadow("neutralLight", "medium"),
|
|
299
|
+
strong: createPressedShadow("neutralLight", "strong")
|
|
300
|
+
},
|
|
301
|
+
pressedHover: {
|
|
302
|
+
subtle: createPressedHoverShadow("neutralLight", "subtle"),
|
|
303
|
+
medium: createPressedHoverShadow("neutralLight", "medium"),
|
|
304
|
+
strong: createPressedHoverShadow("neutralLight", "strong")
|
|
305
|
+
},
|
|
306
|
+
flat: createFlatShadow()
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
var elevationSystem = {
|
|
310
|
+
// Deep inset (recessed input fields, deeply pressed buttons)
|
|
311
|
+
[-2]: {
|
|
312
|
+
name: "deep-inset",
|
|
313
|
+
colorAdjustment: 0,
|
|
314
|
+
shadowIntensity: "strong",
|
|
315
|
+
shadowStyle: "pressed",
|
|
316
|
+
description: "Deeply recessed elements (e.g., input fields, deeply pressed buttons)"
|
|
317
|
+
},
|
|
318
|
+
// Shallow inset (pressed buttons, sunken panels)
|
|
319
|
+
[-1]: {
|
|
320
|
+
name: "inset",
|
|
321
|
+
colorAdjustment: 0,
|
|
322
|
+
shadowIntensity: "medium",
|
|
323
|
+
shadowStyle: "pressed",
|
|
324
|
+
description: "Shallow inset elements (e.g., pressed buttons, sunken panels within cards)"
|
|
325
|
+
},
|
|
326
|
+
// Base level (page background, default surface)
|
|
327
|
+
[0]: {
|
|
328
|
+
name: "base",
|
|
329
|
+
colorAdjustment: 0,
|
|
330
|
+
shadowIntensity: "subtle",
|
|
331
|
+
shadowStyle: "raised",
|
|
332
|
+
description: "Base surface level (page background, default containers)"
|
|
333
|
+
},
|
|
334
|
+
// Level 1: Subtle elevation (outline cards, subtle containers)
|
|
335
|
+
[1]: {
|
|
336
|
+
name: "subtle",
|
|
337
|
+
colorAdjustment: 0.01,
|
|
338
|
+
shadowIntensity: "subtle",
|
|
339
|
+
shadowStyle: "raised",
|
|
340
|
+
description: "Subtle elevation (outline cards, subtle containers)"
|
|
341
|
+
},
|
|
342
|
+
// Level 2: Standard elevation (default cards, buttons)
|
|
343
|
+
[2]: {
|
|
344
|
+
name: "standard",
|
|
345
|
+
colorAdjustment: 0.02,
|
|
346
|
+
shadowIntensity: "medium",
|
|
347
|
+
shadowStyle: "raised",
|
|
348
|
+
description: "Standard elevation (default cards, raised buttons)"
|
|
349
|
+
},
|
|
350
|
+
// Level 3: Prominent elevation (important cards, modals)
|
|
351
|
+
[3]: {
|
|
352
|
+
name: "prominent",
|
|
353
|
+
colorAdjustment: 0.04,
|
|
354
|
+
shadowIntensity: "strong",
|
|
355
|
+
shadowStyle: "raised",
|
|
356
|
+
description: "Prominent elevation (important cards, modals, dropdowns)"
|
|
357
|
+
},
|
|
358
|
+
// Level 4: High elevation (overlays, popovers)
|
|
359
|
+
[4]: {
|
|
360
|
+
name: "high",
|
|
361
|
+
colorAdjustment: 0.06,
|
|
362
|
+
shadowIntensity: "strong",
|
|
363
|
+
shadowStyle: "raised",
|
|
364
|
+
description: "High elevation (overlays, popovers, tooltips)"
|
|
365
|
+
},
|
|
366
|
+
// Level 5: Floating (toasts, floating action buttons)
|
|
367
|
+
[5]: {
|
|
368
|
+
name: "floating",
|
|
369
|
+
colorAdjustment: 0.08,
|
|
370
|
+
shadowIntensity: "strong",
|
|
371
|
+
shadowStyle: "raised",
|
|
372
|
+
description: "Floating elevation (toasts, floating action buttons, highest z-index)"
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
function calculateRimLightColor(baseColor, level) {
|
|
376
|
+
const rgb = hexToRgb(baseColor);
|
|
377
|
+
if (!rgb) {
|
|
378
|
+
return "rgba(255, 255, 255, 0.5)";
|
|
379
|
+
}
|
|
380
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
381
|
+
const isLight = hsv.v > 0.6;
|
|
382
|
+
const isSaturated = hsv.s > 0.3;
|
|
383
|
+
const absLevel = Math.abs(level);
|
|
384
|
+
const opacityBoost = Math.max(0, (absLevel - 1) * 0.05);
|
|
385
|
+
if (isSaturated) {
|
|
386
|
+
const rimLightValue = 0.95;
|
|
387
|
+
const rimLightRgb = hsvToRgb(hsv.h, hsv.s * 0.3, rimLightValue);
|
|
388
|
+
const baseOpacity = isLight ? 0.9 : 0.5;
|
|
389
|
+
const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
|
|
390
|
+
return `rgba(${rimLightRgb.r}, ${rimLightRgb.g}, ${rimLightRgb.b}, ${finalOpacity.toFixed(2)})`;
|
|
391
|
+
} else {
|
|
392
|
+
const baseOpacity = isLight ? 0.9 : 0.12;
|
|
393
|
+
const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
|
|
394
|
+
return `rgba(255, 255, 255, ${finalOpacity.toFixed(2)})`;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function calculateDarkShadowColors(surfaceColor) {
|
|
398
|
+
const rgb = hexToRgb(surfaceColor);
|
|
399
|
+
if (!rgb) {
|
|
400
|
+
return {
|
|
401
|
+
dark: "rgba(0, 0, 0, 0.3)",
|
|
402
|
+
darker: "rgba(0, 0, 0, 0.4)"
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
406
|
+
const isLight = hsv.v > 0.6;
|
|
407
|
+
const isSaturated = hsv.s > 0.3;
|
|
408
|
+
if (isSaturated) {
|
|
409
|
+
const darkShadowValue = 0.15;
|
|
410
|
+
const darkShadowRgb = hsvToRgb(hsv.h, hsv.s, darkShadowValue);
|
|
411
|
+
if (isLight) {
|
|
412
|
+
return {
|
|
413
|
+
dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.3)`,
|
|
414
|
+
darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.4)`
|
|
415
|
+
};
|
|
416
|
+
} else {
|
|
417
|
+
return {
|
|
418
|
+
dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.5)`,
|
|
419
|
+
darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.6)`
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
} else {
|
|
423
|
+
if (isLight) {
|
|
424
|
+
return {
|
|
425
|
+
dark: "rgba(0, 0, 0, 0.2)",
|
|
426
|
+
darker: "rgba(0, 0, 0, 0.3)"
|
|
427
|
+
};
|
|
428
|
+
} else {
|
|
429
|
+
return {
|
|
430
|
+
dark: "rgba(0, 0, 0, 0.5)",
|
|
431
|
+
darker: "rgba(0, 0, 0, 0.6)"
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
function getRimLightConfig() {
|
|
437
|
+
return {
|
|
438
|
+
offset: 1,
|
|
439
|
+
// Fixed 1px for crisp rim
|
|
440
|
+
blur: 1
|
|
441
|
+
// Tight blur for crisp edge
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
function getElevationConfig(level) {
|
|
445
|
+
return elevationSystem[level];
|
|
446
|
+
}
|
|
447
|
+
var elevationSurfaceCache = /* @__PURE__ */ new Map();
|
|
448
|
+
var MAX_CACHE_SIZE = 100;
|
|
449
|
+
function getCacheKey(baseColor, level, theme) {
|
|
450
|
+
return `${baseColor}-${level}-${theme}`;
|
|
451
|
+
}
|
|
452
|
+
function calculateElevationSurface(baseColor, level, theme) {
|
|
453
|
+
const config = elevationSystem[level];
|
|
454
|
+
if (config.colorAdjustment === 0) {
|
|
455
|
+
return baseColor;
|
|
456
|
+
}
|
|
457
|
+
if (level < 0) {
|
|
458
|
+
return baseColor;
|
|
459
|
+
}
|
|
460
|
+
return lighten(baseColor, config.colorAdjustment);
|
|
461
|
+
}
|
|
462
|
+
function getElevationSurface(baseColor, level, theme) {
|
|
463
|
+
const cacheKey = getCacheKey(baseColor, level, theme);
|
|
464
|
+
if (elevationSurfaceCache.has(cacheKey)) {
|
|
465
|
+
return elevationSurfaceCache.get(cacheKey);
|
|
466
|
+
}
|
|
467
|
+
const result = calculateElevationSurface(baseColor, level);
|
|
468
|
+
if (elevationSurfaceCache.size >= MAX_CACHE_SIZE) {
|
|
469
|
+
const firstKey = elevationSurfaceCache.keys().next().value;
|
|
470
|
+
elevationSurfaceCache.delete(firstKey);
|
|
471
|
+
}
|
|
472
|
+
elevationSurfaceCache.set(cacheKey, result);
|
|
473
|
+
return result;
|
|
474
|
+
}
|
|
475
|
+
var elevationShadowCache = /* @__PURE__ */ new Map();
|
|
476
|
+
var MAX_SHADOW_CACHE_SIZE = 50;
|
|
477
|
+
function getShadowCacheKey(baseColor, level, theme, isHovered) {
|
|
478
|
+
return `${baseColor}-${level}-${theme}-${isHovered}`;
|
|
479
|
+
}
|
|
480
|
+
function calculateElevationShadow(baseColor, level, theme, isHovered = false) {
|
|
481
|
+
const config = elevationSystem[level];
|
|
482
|
+
if (level === 0) {
|
|
483
|
+
return {};
|
|
484
|
+
}
|
|
485
|
+
const elevatedSurfaceColor = calculateElevationSurface(baseColor, level);
|
|
486
|
+
const rimLightColor = calculateRimLightColor(baseColor, level);
|
|
487
|
+
const darkShadowColors = calculateDarkShadowColors(elevatedSurfaceColor);
|
|
488
|
+
const intensityConfig2 = {
|
|
489
|
+
subtle: { offset: 1, blur: 2 },
|
|
490
|
+
medium: { offset: 2, blur: 4 },
|
|
491
|
+
strong: { offset: 2, blur: 5 }
|
|
492
|
+
};
|
|
493
|
+
const { offset, blur } = intensityConfig2[config.shadowIntensity];
|
|
494
|
+
const rimConfig = getRimLightConfig();
|
|
495
|
+
if (config.shadowStyle === "pressed") {
|
|
496
|
+
if (isHovered) {
|
|
497
|
+
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
498
|
+
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
499
|
+
return Platform.select({
|
|
500
|
+
web: {
|
|
501
|
+
boxShadow: `inset ${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
502
|
+
},
|
|
503
|
+
default: {
|
|
504
|
+
shadowOpacity: 0,
|
|
505
|
+
elevation: 0
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
return Platform.select({
|
|
510
|
+
web: {
|
|
511
|
+
boxShadow: `inset ${offset}px ${offset}px ${blur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
512
|
+
},
|
|
513
|
+
default: {
|
|
514
|
+
shadowOpacity: 0,
|
|
515
|
+
elevation: 0
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
} else {
|
|
519
|
+
if (isHovered) {
|
|
520
|
+
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
521
|
+
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
522
|
+
return Platform.select({
|
|
523
|
+
web: {
|
|
524
|
+
boxShadow: `${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
525
|
+
},
|
|
526
|
+
default: {
|
|
527
|
+
shadowColor: "#000",
|
|
528
|
+
shadowOffset: { width: hoverOffset, height: hoverOffset },
|
|
529
|
+
shadowOpacity: 0.2,
|
|
530
|
+
shadowRadius: hoverBlur / 2,
|
|
531
|
+
elevation: hoverOffset
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
return Platform.select({
|
|
536
|
+
web: {
|
|
537
|
+
boxShadow: `${offset}px ${offset}px ${blur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
538
|
+
},
|
|
539
|
+
default: {
|
|
540
|
+
shadowColor: "#000",
|
|
541
|
+
shadowOffset: { width: offset, height: offset },
|
|
542
|
+
shadowOpacity: 0.3,
|
|
543
|
+
shadowRadius: blur / 2,
|
|
544
|
+
elevation: offset
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
function getElevationShadow(baseColor, level, theme, isHovered = false) {
|
|
550
|
+
const cacheKey = getShadowCacheKey(baseColor, level, theme, isHovered);
|
|
551
|
+
if (elevationShadowCache.has(cacheKey)) {
|
|
552
|
+
return elevationShadowCache.get(cacheKey);
|
|
553
|
+
}
|
|
554
|
+
const result = calculateElevationShadow(baseColor, level, theme, isHovered);
|
|
555
|
+
if (elevationShadowCache.size >= MAX_SHADOW_CACHE_SIZE) {
|
|
556
|
+
const firstKey = elevationShadowCache.keys().next().value;
|
|
557
|
+
elevationShadowCache.delete(firstKey);
|
|
558
|
+
}
|
|
559
|
+
elevationShadowCache.set(cacheKey, result);
|
|
560
|
+
return result;
|
|
561
|
+
}
|
|
562
|
+
function getBaseSurfaceColor(theme) {
|
|
563
|
+
return theme === "light" ? semanticColorsLight["surface-raised"] : semanticColorsDark["surface-elevated"];
|
|
564
|
+
}
|
|
565
|
+
var componentElevationRanges = {
|
|
566
|
+
button: {
|
|
567
|
+
allowed: [2],
|
|
568
|
+
default: 2,
|
|
569
|
+
hover: 3
|
|
570
|
+
},
|
|
571
|
+
card: {
|
|
572
|
+
allowed: [1, 2, 3],
|
|
573
|
+
default: 2,
|
|
574
|
+
hover: 3
|
|
575
|
+
},
|
|
576
|
+
input: {
|
|
577
|
+
allowed: [-2, -1, 0],
|
|
578
|
+
default: -1
|
|
579
|
+
},
|
|
580
|
+
overlay: {
|
|
581
|
+
allowed: [4, 5],
|
|
582
|
+
default: 4
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
function getValidatedElevation(component, requested) {
|
|
586
|
+
const range = componentElevationRanges[component];
|
|
587
|
+
if (range.allowed.includes(requested)) {
|
|
588
|
+
return requested;
|
|
589
|
+
}
|
|
590
|
+
const sorted = [...range.allowed].sort((a, b) => a - b);
|
|
591
|
+
if (requested < sorted[0]) return sorted[0];
|
|
592
|
+
if (requested > sorted[sorted.length - 1]) return sorted[sorted.length - 1];
|
|
593
|
+
return sorted.reduce(
|
|
594
|
+
(prev, curr) => Math.abs(curr - requested) < Math.abs(prev - requested) ? curr : prev
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
var glowConfig = {
|
|
598
|
+
subtle: { blur: 12, spread: 0, opacity: 0.25 },
|
|
599
|
+
medium: { blur: 20, spread: 2, opacity: 0.4 },
|
|
600
|
+
strong: { blur: 30, spread: 4, opacity: 0.55 }
|
|
601
|
+
};
|
|
602
|
+
function getGlowShadow(color, intensity = "medium") {
|
|
603
|
+
const config = glowConfig[intensity];
|
|
604
|
+
const rgb = hexToRgb(color);
|
|
605
|
+
if (!rgb) return {};
|
|
606
|
+
return Platform.select({
|
|
607
|
+
web: {
|
|
608
|
+
boxShadow: `0 0 ${config.blur}px ${config.spread}px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${config.opacity})`
|
|
609
|
+
},
|
|
610
|
+
default: {
|
|
611
|
+
shadowColor: color,
|
|
612
|
+
shadowOffset: { width: 0, height: 0 },
|
|
613
|
+
shadowOpacity: config.opacity,
|
|
614
|
+
shadowRadius: config.blur / 2,
|
|
615
|
+
elevation: 0
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// src/theme/manifest/css-property-manifest.validate.ts
|
|
621
|
+
var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
622
|
+
var isVariantAxes = (value) => isPlainObject(value) && Object.keys(value).length > 0 && Object.values(value).every((axisValue) => typeof axisValue === "string");
|
|
623
|
+
function collectVariantOverrideErrors(override, path) {
|
|
624
|
+
if (!isPlainObject(override)) return [`${path} must be an object`];
|
|
625
|
+
const errors = [];
|
|
626
|
+
if (!isVariantAxes(override.variant))
|
|
627
|
+
errors.push(`${path}.variant must be a non-empty string-keyed object`);
|
|
628
|
+
if (override.token !== void 0 && override.token !== null && typeof override.token !== "string") {
|
|
629
|
+
errors.push(`${path}.token must be a string or null`);
|
|
630
|
+
}
|
|
631
|
+
if (typeof override.resolvedValue !== "string" || override.resolvedValue.length === 0) {
|
|
632
|
+
errors.push(`${path}.resolvedValue must be a non-empty string`);
|
|
633
|
+
}
|
|
634
|
+
return errors;
|
|
635
|
+
}
|
|
636
|
+
function collectPropertyErrors(entry, path) {
|
|
637
|
+
if (!isPlainObject(entry)) return [`${path} must be an object`];
|
|
638
|
+
const errors = [];
|
|
639
|
+
if (typeof entry.property !== "string" || entry.property.length === 0) {
|
|
640
|
+
errors.push(`${path}.property must be a non-empty string`);
|
|
641
|
+
}
|
|
642
|
+
if (entry.token !== null && typeof entry.token !== "string") {
|
|
643
|
+
errors.push(`${path}.token must be a string or null`);
|
|
644
|
+
}
|
|
645
|
+
if (typeof entry.resolvedValue !== "string" || entry.resolvedValue.length === 0) {
|
|
646
|
+
errors.push(`${path}.resolvedValue must be a non-empty string`);
|
|
647
|
+
}
|
|
648
|
+
if (entry.variantOverrides !== void 0) {
|
|
649
|
+
if (!Array.isArray(entry.variantOverrides)) {
|
|
650
|
+
errors.push(`${path}.variantOverrides must be an array`);
|
|
651
|
+
} else {
|
|
652
|
+
entry.variantOverrides.forEach(
|
|
653
|
+
(override, i) => errors.push(...collectVariantOverrideErrors(override, `${path}.variantOverrides[${i}]`))
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return errors;
|
|
658
|
+
}
|
|
659
|
+
function validateCssPropertyManifest(candidate) {
|
|
660
|
+
if (!isPlainObject(candidate)) return { valid: false, errors: ["manifest must be an object"] };
|
|
661
|
+
const errors = [];
|
|
662
|
+
if (typeof candidate.component !== "string" || candidate.component.length === 0) {
|
|
663
|
+
errors.push("component must be a non-empty string");
|
|
664
|
+
}
|
|
665
|
+
if (candidate.baseVariant !== void 0 && !isVariantAxes(candidate.baseVariant)) {
|
|
666
|
+
errors.push("baseVariant must be a non-empty string-keyed object");
|
|
667
|
+
}
|
|
668
|
+
if (!Array.isArray(candidate.properties) || candidate.properties.length === 0) {
|
|
669
|
+
errors.push("properties must be a non-empty array");
|
|
670
|
+
} else {
|
|
671
|
+
candidate.properties.forEach(
|
|
672
|
+
(entry, i) => errors.push(...collectPropertyErrors(entry, `properties[${i}]`))
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
return { valid: errors.length === 0, errors };
|
|
676
|
+
}
|
|
677
|
+
function isCssPropertyManifest(candidate) {
|
|
678
|
+
return validateCssPropertyManifest(candidate).valid;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// src/theme/presets/apply.ts
|
|
682
|
+
function colorKeyToVar(key) {
|
|
683
|
+
return `--color-${key}`;
|
|
684
|
+
}
|
|
685
|
+
function applyColorOverrides(colors, root) {
|
|
686
|
+
for (const [key, value] of Object.entries(colors)) {
|
|
687
|
+
if (value !== void 0) {
|
|
688
|
+
root.style.setProperty(colorKeyToVar(key), value);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
function applyFontOverrides(fonts, root) {
|
|
693
|
+
const fontVarMap = {
|
|
694
|
+
sans: "--font-family-sans",
|
|
695
|
+
body: "--font-family-body",
|
|
696
|
+
heading: "--font-family-heading",
|
|
697
|
+
mono: "--font-family-mono"
|
|
698
|
+
};
|
|
699
|
+
for (const [key, value] of Object.entries(fonts)) {
|
|
700
|
+
if (value !== void 0 && fontVarMap[key]) {
|
|
701
|
+
root.style.setProperty(fontVarMap[key], value);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
function injectFontImport(url) {
|
|
706
|
+
if (typeof document === "undefined") return;
|
|
707
|
+
const existing = document.querySelector(`link[href="${url}"]`);
|
|
708
|
+
if (existing) return;
|
|
709
|
+
const link = document.createElement("link");
|
|
710
|
+
link.rel = "stylesheet";
|
|
711
|
+
link.href = url;
|
|
712
|
+
document.head.appendChild(link);
|
|
713
|
+
}
|
|
714
|
+
function applyThemePreset(preset) {
|
|
715
|
+
if (typeof document === "undefined") {
|
|
716
|
+
return () => {
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
const root = document.documentElement;
|
|
720
|
+
const removals = [];
|
|
721
|
+
if (preset.fontImport) {
|
|
722
|
+
injectFontImport(preset.fontImport);
|
|
723
|
+
}
|
|
724
|
+
const isLight = root.classList.contains("light");
|
|
725
|
+
const modeColors = isLight ? preset.colors?.light : preset.colors?.dark;
|
|
726
|
+
if (modeColors) {
|
|
727
|
+
const previousValues = {};
|
|
728
|
+
for (const key of Object.keys(modeColors)) {
|
|
729
|
+
previousValues[colorKeyToVar(key)] = root.style.getPropertyValue(colorKeyToVar(key)) || null;
|
|
730
|
+
}
|
|
731
|
+
applyColorOverrides(modeColors, root);
|
|
732
|
+
removals.push(() => {
|
|
733
|
+
for (const [varName, prev] of Object.entries(previousValues)) {
|
|
734
|
+
if (prev === null) {
|
|
735
|
+
root.style.removeProperty(varName);
|
|
736
|
+
} else {
|
|
737
|
+
root.style.setProperty(varName, prev);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
if (preset.fonts) {
|
|
743
|
+
applyFontOverrides(preset.fonts, root);
|
|
744
|
+
}
|
|
745
|
+
if (preset.rootClasses) {
|
|
746
|
+
for (const cls of preset.rootClasses) {
|
|
747
|
+
root.classList.add(cls);
|
|
748
|
+
}
|
|
749
|
+
removals.push(() => {
|
|
750
|
+
for (const cls of preset.rootClasses) {
|
|
751
|
+
root.classList.remove(cls);
|
|
752
|
+
}
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
return () => {
|
|
756
|
+
for (const remove of removals) {
|
|
757
|
+
remove();
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// src/theme/presets/default.ts
|
|
763
|
+
var defaultPreset = {
|
|
764
|
+
name: "default",
|
|
765
|
+
description: "Titan Design System default theme \u2014 orange accent, steel secondary"
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
// src/theme/presets/audiobook.ts
|
|
769
|
+
var audiobookPreset = {
|
|
770
|
+
name: "audiobook",
|
|
771
|
+
description: "Warm copper/patina theme with editorial typography",
|
|
772
|
+
fontImport: "https://fonts.googleapis.com/css2?family=Newsreader:ital,wght@0,400;0,600;0,700;1,400&family=Outfit:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap",
|
|
773
|
+
fonts: {
|
|
774
|
+
sans: "'Outfit', 'Avenir', 'Avenir Next', system-ui, sans-serif",
|
|
775
|
+
body: "'Outfit', 'Avenir', 'Avenir Next', system-ui, sans-serif",
|
|
776
|
+
heading: "'Newsreader', 'Libre Baskerville', Georgia, serif",
|
|
777
|
+
mono: "'JetBrains Mono', 'SF Mono', 'Fira Code', monospace"
|
|
778
|
+
},
|
|
779
|
+
colors: {
|
|
780
|
+
dark: {
|
|
781
|
+
// Brand: Copper accent
|
|
782
|
+
"brand-primary": "#d4782a",
|
|
783
|
+
"brand-primary-light": "#e8944a",
|
|
784
|
+
"brand-primary-dark": "#9a4a15",
|
|
785
|
+
"brand-primary-subtle": "rgba(212, 120, 42, 0.12)",
|
|
786
|
+
"brand-primary-hover": "#e8944a",
|
|
787
|
+
"brand-primary-active": "#f5b070",
|
|
788
|
+
// Brand secondary: Patina/verdigris
|
|
789
|
+
"brand-secondary": "#3a9b8a",
|
|
790
|
+
"brand-secondary-light": "#55baa7",
|
|
791
|
+
"brand-secondary-dark": "#1f5c52",
|
|
792
|
+
"brand-secondary-subtle": "rgba(58, 155, 138, 0.12)",
|
|
793
|
+
"brand-secondary-hover": "#55baa7",
|
|
794
|
+
"brand-secondary-active": "#7ed4c4",
|
|
795
|
+
"on-brand-primary": "#FFFFFF",
|
|
796
|
+
"on-brand-secondary": "#FFFFFF",
|
|
797
|
+
// Status colors (audiobook's warmer status palette)
|
|
798
|
+
"status-success": "#5fb870",
|
|
799
|
+
"status-error": "#d85c4a",
|
|
800
|
+
"status-warning": "#d4a43a",
|
|
801
|
+
"status-info": "#5a8fd4",
|
|
802
|
+
// Text: warm off-whites
|
|
803
|
+
"text-primary": "#f4f3f1",
|
|
804
|
+
"text-secondary": "#b5b3af",
|
|
805
|
+
"text-tertiary": "#7a7875",
|
|
806
|
+
// Surfaces: warm charcoals (not pure gray)
|
|
807
|
+
"surface-base": "#101114",
|
|
808
|
+
"surface-elevated": "#15171c",
|
|
809
|
+
"surface-raised": "#1a1d24",
|
|
810
|
+
"surface-overlay": "#15171c",
|
|
811
|
+
"surface-input": "#15171c",
|
|
812
|
+
// Backgrounds
|
|
813
|
+
"background-base": "#0a0b0d",
|
|
814
|
+
"background-default": "#101114",
|
|
815
|
+
"background-subtle": "#1a1d24",
|
|
816
|
+
// Borders
|
|
817
|
+
"border-default": "rgba(255, 255, 255, 0.06)",
|
|
818
|
+
"border-subtle": "rgba(255, 255, 255, 0.03)",
|
|
819
|
+
"border-strong": "#2d323d",
|
|
820
|
+
"border-focus": "#d4782a",
|
|
821
|
+
"border-input": "#2d323d",
|
|
822
|
+
"border-input-hover": "#454c5c",
|
|
823
|
+
"border-input-focus": "#d4782a",
|
|
824
|
+
"border-input-error": "#d85c4a",
|
|
825
|
+
// Interactive
|
|
826
|
+
"interactive-hover": "rgba(255, 255, 255, 0.04)",
|
|
827
|
+
"interactive-focus": "rgba(255, 255, 255, 0.12)",
|
|
828
|
+
"interactive-active": "rgba(255, 255, 255, 0.16)",
|
|
829
|
+
"interactive-selected": "rgba(255, 255, 255, 0.08)",
|
|
830
|
+
"divider": "rgba(255, 255, 255, 0.06)",
|
|
831
|
+
// Glow RGB values for shadow utilities
|
|
832
|
+
"brand-primary-rgb": "212, 120, 42",
|
|
833
|
+
"brand-secondary-rgb": "58, 155, 138",
|
|
834
|
+
"status-success-rgb": "95, 184, 112",
|
|
835
|
+
"status-error-rgb": "216, 92, 74",
|
|
836
|
+
"status-warning-rgb": "212, 164, 58",
|
|
837
|
+
"status-info-rgb": "90, 143, 212",
|
|
838
|
+
"background-base-rgb": "10, 11, 13"
|
|
839
|
+
}
|
|
840
|
+
},
|
|
841
|
+
rootClasses: ["atmosphere-warm", "grain"]
|
|
842
|
+
};
|
|
843
|
+
|
|
844
|
+
export { applyThemePreset, audiobookPreset, componentElevationRanges, createFlatShadow, createPressedHoverShadow, createPressedShadow, createRaisedHoverShadow, createRaisedShadow, darken, defaultPreset, elevationSystem, getBaseSurfaceColor, getElevationConfig, getElevationShadow, getElevationSurface, getGlowShadow, getHoverColors, getValidatedElevation, hexToRgb, hsvToRgb, isCssPropertyManifest, isDark, lighten, neumorphicShadows, rgbToHex, rgbToHsv, shadowColors, validateCssPropertyManifest };
|
|
845
|
+
//# sourceMappingURL=chunk-3VLOBS6O.mjs.map
|
|
846
|
+
//# sourceMappingURL=chunk-3VLOBS6O.mjs.map
|