@titan-design/react-ui 0.11.0 → 0.12.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.
Files changed (152) hide show
  1. package/dist/bodymap.js +173 -343
  2. package/dist/bodymap.js.map +1 -1
  3. package/dist/bodymap.mjs +173 -343
  4. package/dist/bodymap.mjs.map +1 -1
  5. package/dist/index.d.mts +27 -22
  6. package/dist/index.d.ts +27 -22
  7. package/dist/index.js +366 -561
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +360 -553
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/pages.js +242 -407
  12. package/dist/pages.js.map +1 -1
  13. package/dist/pages.mjs +242 -407
  14. package/dist/pages.mjs.map +1 -1
  15. package/dist/theme/index.d.mts +250 -1157
  16. package/dist/theme/index.d.ts +250 -1157
  17. package/dist/theme/index.js +234 -408
  18. package/dist/theme/index.js.map +1 -1
  19. package/dist/theme/index.mjs +227 -399
  20. package/dist/theme/index.mjs.map +1 -1
  21. package/dist/theme/tokens-css.js +141 -140
  22. package/dist/theme/tokens-css.js.map +1 -1
  23. package/dist/theme/tokens-css.mjs +141 -140
  24. package/dist/theme/tokens-css.mjs.map +1 -1
  25. package/dist/theme/tokens.d.mts +904 -0
  26. package/dist/theme/tokens.d.ts +904 -0
  27. package/dist/theme/tokens.js +856 -0
  28. package/dist/theme/tokens.js.map +1 -0
  29. package/dist/theme/tokens.mjs +833 -0
  30. package/dist/theme/tokens.mjs.map +1 -0
  31. package/package.json +7 -1
  32. package/src/arch/Architecture.stories.tsx +9 -9
  33. package/src/components/custom/DateTime/DateTime.stories.tsx +1 -1
  34. package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +3 -3
  35. package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
  36. package/src/components/custom/Fatigue/GhostSpark.stories.tsx +3 -3
  37. package/src/components/custom/Fatigue/LiveFatigueCard.tsx +1 -1
  38. package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +2 -2
  39. package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
  40. package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +4 -4
  41. package/src/components/custom/Fatigue/VelocityHero.stories.tsx +3 -3
  42. package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
  43. package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -12
  44. package/src/components/custom/Sidebar/Sidebar.tsx +4 -4
  45. package/src/components/custom/Table/Table.tsx +2 -2
  46. package/src/components/custom/Workout/ActiveWorkoutPage.tsx +3 -3
  47. package/src/components/custom/Workout/BaseBadge.test.tsx +6 -1
  48. package/src/components/custom/Workout/BaseBadge.tsx +1 -1
  49. package/src/components/custom/Workout/BodyMap.tsx +2 -2
  50. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +2 -2
  51. package/src/components/custom/Workout/DeviationBar.test.tsx +2 -1
  52. package/src/components/custom/Workout/DeviationBar.tsx +3 -2
  53. package/src/components/custom/Workout/ExerciseCard.test.tsx +3 -3
  54. package/src/components/custom/Workout/ExerciseCard.tsx +2 -2
  55. package/src/components/custom/Workout/ExerciseDetailPage.tsx +4 -4
  56. package/src/components/custom/Workout/InputBar.tsx +2 -2
  57. package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +1 -1
  58. package/src/components/custom/Workout/LiveAuraFrame.test.tsx +1 -1
  59. package/src/components/custom/Workout/LiveAuraFrame.tsx +3 -3
  60. package/src/components/custom/Workout/MesoCard.tsx +3 -1
  61. package/src/components/custom/Workout/MuscleGroupChip.tsx +4 -3
  62. package/src/components/custom/Workout/PrHistoryModal.tsx +2 -2
  63. package/src/components/custom/Workout/ProgramPlanningPage.tsx +1 -1
  64. package/src/components/custom/Workout/README.md +1 -1
  65. package/src/components/custom/Workout/ReadinessCheck.tsx +2 -2
  66. package/src/components/custom/Workout/RestTimer.tsx +2 -2
  67. package/src/components/custom/Workout/S3SetTypes.stories.tsx +3 -3
  68. package/src/components/custom/Workout/SessionHeader.stories.tsx +2 -2
  69. package/src/components/custom/Workout/SessionHeader.tsx +1 -1
  70. package/src/components/custom/Workout/SessionRail.stories.tsx +2 -2
  71. package/src/components/custom/Workout/SessionRail.tsx +13 -5
  72. package/src/components/custom/Workout/SetBar.tsx +3 -3
  73. package/src/components/custom/Workout/SetRow.test.tsx +6 -3
  74. package/src/components/custom/Workout/StatusDot.tsx +5 -4
  75. package/src/components/custom/Workout/StrengthTrendChart.tsx +1 -1
  76. package/src/components/custom/Workout/TrainingStatusPage.tsx +2 -2
  77. package/src/components/custom/Workout/VelocityStrip.test.tsx +5 -2
  78. package/src/components/custom/Workout/VelocityStrip.tsx +4 -4
  79. package/src/components/custom/Workout/VolumeLandmarkBar.tsx +3 -3
  80. package/src/components/custom/Workout/WeightBadge.test.tsx +6 -1
  81. package/src/components/custom/Workout/WeightBadge.tsx +2 -1
  82. package/src/components/custom/Workout/WorkoutCard.tsx +3 -1
  83. package/src/components/custom/Workout/WorkoutPill.tsx +5 -2
  84. package/src/components/custom/Workout/ZoneTrack.tsx +4 -4
  85. package/src/components/custom/Workout/setHeadingKit.tsx +14 -8
  86. package/src/components/custom/Workout/velocity-story-kit.tsx +2 -2
  87. package/src/components/custom/charts/SetBarChart.tsx +3 -3
  88. package/src/components/custom/stepper/Stepper.stories.tsx +1 -1
  89. package/src/components/custom/stepper/Stepper.tsx +3 -3
  90. package/src/components/shell/DeviceMenu.tsx +2 -2
  91. package/src/components/shell/README.md +1 -1
  92. package/src/components/shell/SessionRailSpecimen.stories.tsx +1 -1
  93. package/src/components/shell/SideNav.tsx +1 -1
  94. package/src/components/shell/TopBar.tsx +1 -1
  95. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +1 -1
  96. package/src/components/ui/autocomplete/Autocomplete.tsx +1 -1
  97. package/src/components/ui/avatar/Avatar.tsx +2 -2
  98. package/src/components/ui/badge/Badge.tsx +2 -2
  99. package/src/components/ui/card/Card.tsx +3 -3
  100. package/src/components/ui/checkbox/Checkbox.tsx +1 -1
  101. package/src/components/ui/collapse/Collapse.tsx +1 -1
  102. package/src/components/ui/data-row/DataRow.stories.tsx +1 -1
  103. package/src/components/ui/drawer/Drawer.tsx +3 -3
  104. package/src/components/ui/form-field/FormField.tsx +1 -1
  105. package/src/components/ui/help-tip/HelpTip.tsx +1 -1
  106. package/src/components/ui/menu/Menu.tsx +2 -2
  107. package/src/components/ui/pill/Pill.tsx +2 -2
  108. package/src/components/ui/popover/Popover.stories.tsx +2 -2
  109. package/src/components/ui/popover/Popover.tsx +1 -1
  110. package/src/components/ui/progress/Progress.tsx +3 -3
  111. package/src/components/ui/radio/Radio.stories.tsx +1 -1
  112. package/src/components/ui/radio/Radio.tsx +4 -4
  113. package/src/components/ui/select/Select.tsx +3 -3
  114. package/src/components/ui/surface/Surface.stories.tsx +3 -3
  115. package/src/components/ui/surface/Surface.test.tsx +32 -19
  116. package/src/components/ui/surface/Surface.tsx +3 -3
  117. package/src/components/ui/surface/SurfaceContext.ts +19 -29
  118. package/src/components/ui/surface/surface.contract.test.ts +58 -45
  119. package/src/components/ui/switch/Switch.tsx +1 -1
  120. package/src/components/ui/tabs/Tabs.tsx +2 -2
  121. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +5 -5
  122. package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +1 -1
  123. package/src/components/ui/toolbar-button/ToolbarButton.tsx +36 -22
  124. package/src/stories/PresetShowcase.stories.tsx +21 -21
  125. package/src/theme/ColorPalettes.stories.tsx +41 -38
  126. package/src/theme/ColorPrimitives.stories.tsx +89 -41
  127. package/src/theme/Depth.stories.tsx +312 -0
  128. package/src/theme/DepthCalibration.stories.tsx +655 -0
  129. package/src/theme/ThemeProvider.tsx +1 -1
  130. package/src/theme/barrel.ts +7 -14
  131. package/src/theme/color-stories.coverage.test.ts +15 -20
  132. package/src/theme/color-story-kit.tsx +1 -1
  133. package/src/theme/color-utils.ts +197 -0
  134. package/src/theme/config.ts +0 -8
  135. package/src/theme/depth-calibration.test.tsx +97 -0
  136. package/src/theme/elevation.test.ts +62 -1
  137. package/src/theme/elevation.ts +34 -8
  138. package/src/theme/global.css +47 -53
  139. package/src/theme/grey-ramp.test.ts +166 -0
  140. package/src/theme/materials.test.ts +106 -0
  141. package/src/theme/materials.ts +211 -0
  142. package/src/theme/presets/audiobook.ts +4 -4
  143. package/src/theme/presets/types.ts +3 -3
  144. package/src/theme/semantic-contrast.test.ts +83 -0
  145. package/src/theme/token-export-guard.test.ts +104 -0
  146. package/src/theme/tokens/primitives.ts +63 -116
  147. package/src/theme/tokens/semantic.ts +130 -82
  148. package/src/utils/colors.ts +1 -1
  149. package/tailwind.config.js +2 -5
  150. package/src/theme/bar-paper.ts +0 -59
  151. package/src/theme/shadows.stories.tsx +0 -523
  152. package/src/theme/shadows.ts +0 -439
@@ -1,439 +0,0 @@
1
- /**
2
- * Neumorphic Shadow Utilities
3
- *
4
- * Neumorphism creates soft, extruded UI using dual opposing shadows.
5
- * - Light source assumed from top-left
6
- * - Raised elements: dark shadow bottom-right, light highlight top-left
7
- * - Pressed elements: inverted with `inset` shadows
8
- */
9
-
10
- import { Platform, type ViewStyle } from 'react-native'
11
-
12
- // ============================================================================
13
- // Color Math Utilities
14
- // ============================================================================
15
-
16
- /**
17
- * Parse a hex color to RGB values (0-255).
18
- * Supports both #RGB and #RRGGBB formats.
19
- */
20
- export function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
21
- const cleaned = hex.replace('#', '')
22
-
23
- let r: number, g: number, b: number
24
-
25
- if (cleaned.length === 3) {
26
- r = parseInt(cleaned[0] + cleaned[0], 16)
27
- g = parseInt(cleaned[1] + cleaned[1], 16)
28
- b = parseInt(cleaned[2] + cleaned[2], 16)
29
- } else if (cleaned.length === 6) {
30
- r = parseInt(cleaned.slice(0, 2), 16)
31
- g = parseInt(cleaned.slice(2, 4), 16)
32
- b = parseInt(cleaned.slice(4, 6), 16)
33
- } else {
34
- return null
35
- }
36
-
37
- return { r, g, b }
38
- }
39
-
40
- /**
41
- * Convert RGB (0-255) to HSV (h: 0-360, s: 0-1, v: 0-1).
42
- */
43
- export function rgbToHsv(r: number, g: number, b: number): { h: number; s: number; v: number } {
44
- const rNorm = r / 255
45
- const gNorm = g / 255
46
- const bNorm = b / 255
47
-
48
- const max = Math.max(rNorm, gNorm, bNorm)
49
- const min = Math.min(rNorm, gNorm, bNorm)
50
- const delta = max - min
51
-
52
- // Value
53
- const v = max
54
-
55
- // Saturation
56
- const s = max === 0 ? 0 : delta / max
57
-
58
- // Hue
59
- let h = 0
60
- if (delta !== 0) {
61
- if (max === rNorm) {
62
- h = 60 * (((gNorm - bNorm) / delta) % 6)
63
- } else if (max === gNorm) {
64
- h = 60 * ((bNorm - rNorm) / delta + 2)
65
- } else {
66
- h = 60 * ((rNorm - gNorm) / delta + 4)
67
- }
68
- }
69
- if (h < 0) h += 360
70
-
71
- return { h, s, v }
72
- }
73
-
74
- /**
75
- * Convert HSV (h: 0-360, s: 0-1, v: 0-1) to RGB (0-255).
76
- */
77
- export function hsvToRgb(h: number, s: number, v: number): { r: number; g: number; b: number } {
78
- const c = v * s
79
- const x = c * (1 - Math.abs((h / 60) % 2 - 1))
80
- const m = v - c
81
-
82
- let rPrime: number, gPrime: number, bPrime: number
83
-
84
- if (h >= 0 && h < 60) {
85
- rPrime = c; gPrime = x; bPrime = 0
86
- } else if (h >= 60 && h < 120) {
87
- rPrime = x; gPrime = c; bPrime = 0
88
- } else if (h >= 120 && h < 180) {
89
- rPrime = 0; gPrime = c; bPrime = x
90
- } else if (h >= 180 && h < 240) {
91
- rPrime = 0; gPrime = x; bPrime = c
92
- } else if (h >= 240 && h < 300) {
93
- rPrime = x; gPrime = 0; bPrime = c
94
- } else {
95
- rPrime = c; gPrime = 0; bPrime = x
96
- }
97
-
98
- return {
99
- r: Math.round((rPrime + m) * 255),
100
- g: Math.round((gPrime + m) * 255),
101
- b: Math.round((bPrime + m) * 255),
102
- }
103
- }
104
-
105
- /**
106
- * Convert RGB values to hex string.
107
- */
108
- export function rgbToHex(r: number, g: number, b: number): string {
109
- const toHex = (n: number) => {
110
- const clamped = Math.max(0, Math.min(255, Math.round(n)))
111
- return clamped.toString(16).padStart(2, '0')
112
- }
113
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`
114
- }
115
-
116
- /**
117
- * Lighten a color by increasing its HSV Value component.
118
- *
119
- * @param hex - The hex color to lighten
120
- * @param amount - Amount to increase V by (0-1)
121
- */
122
- export function lighten(hex: string, amount: number = 0.1): string {
123
- const rgb = hexToRgb(hex)
124
- if (!rgb) return hex
125
-
126
- const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b)
127
- const newV = Math.min(1, hsv.v + amount)
128
-
129
- const newRgb = hsvToRgb(hsv.h, hsv.s, newV)
130
- return rgbToHex(newRgb.r, newRgb.g, newRgb.b)
131
- }
132
-
133
- /**
134
- * Darken a color by decreasing its HSV Value component.
135
- *
136
- * @param hex - The hex color to darken
137
- * @param amount - Amount to decrease V by (0-1)
138
- */
139
- export function darken(hex: string, amount: number = 0.1): string {
140
- const rgb = hexToRgb(hex)
141
- if (!rgb) return hex
142
-
143
- const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b)
144
- const newV = Math.max(0, hsv.v - amount)
145
-
146
- const newRgb = hsvToRgb(hsv.h, hsv.s, newV)
147
- return rgbToHex(newRgb.r, newRgb.g, newRgb.b)
148
- }
149
-
150
- /**
151
- * Get hover colors for a button based on its background color.
152
- * Automatically adapts intensity based on the color's luminance.
153
- *
154
- * @param bgColor - The button's background color (hex)
155
- * @param intensity - How strong the hover effect should be ('subtle' | 'medium' | 'strong')
156
- */
157
- export function getHoverColors(
158
- bgColor: string,
159
- intensity: 'subtle' | 'medium' | 'strong' = 'medium'
160
- ): { raised: string; pressed: string } {
161
- const amounts = {
162
- subtle: 0.01,
163
- medium: 0.02,
164
- strong: 0.03,
165
- }
166
-
167
- const amount = amounts[intensity]
168
-
169
- return {
170
- raised: lighten(bgColor, amount), // Raised hover: lighten (lifting up)
171
- pressed: darken(bgColor, amount), // Pressed hover: darken (pressing down)
172
- }
173
- }
174
-
175
- /**
176
- * Check if a color is considered "dark" (for choosing text color).
177
- * Uses HSV Value component for simplicity.
178
- */
179
- export function isDark(hex: string): boolean {
180
- const rgb = hexToRgb(hex)
181
- if (!rgb) return true
182
- const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b)
183
- return hsv.v < 0.6
184
- }
185
-
186
- /**
187
- * Shadow configuration for different surface colors.
188
- * Each surface needs calibrated light/dark shadow colors.
189
- *
190
- * - dark: soft shadow for depth (bottom-right)
191
- * - light: sharp rim highlight (top-left) - higher opacity for crisp edge
192
- * - darker: deeper shadow for pressed/inset states
193
- */
194
- export const shadowColors = {
195
- // For charcoal surfaces (~#2C2C2C to #3C3C3C)
196
- charcoal: {
197
- dark: 'rgba(0, 0, 0, 0.5)',
198
- light: 'rgba(255, 255, 255, 0.12)', // brighter for crisp rim light
199
- darker: 'rgba(0, 0, 0, 0.6)',
200
- },
201
- // For neutral dark surfaces (~#1F2937)
202
- neutralDark: {
203
- dark: 'rgba(0, 0, 0, 0.4)',
204
- light: 'rgba(255, 255, 255, 0.08)',
205
- darker: 'rgba(0, 0, 0, 0.5)',
206
- },
207
- // For light surfaces (white/light gray backgrounds)
208
- neutralLight: {
209
- dark: 'rgba(0, 0, 0, 0.15)', // Visible dark shadow for depth on light backgrounds
210
- light: 'rgba(255, 255, 255, 1)', // Bright highlight for raised effect (visible on light gray)
211
- darker: 'rgba(0, 0, 0, 0.2)', // Deeper shadow for pressed states
212
- },
213
- }
214
-
215
- export type ShadowIntensity = 'subtle' | 'medium' | 'strong'
216
- export type ShadowSurface = keyof typeof shadowColors
217
-
218
- interface ShadowConfig {
219
- offset: number
220
- blur: number
221
- }
222
-
223
- const intensityConfig: Record<ShadowIntensity, ShadowConfig> = {
224
- subtle: { offset: 1, blur: 2 }, // very light, barely visible
225
- medium: { offset: 2, blur: 4 }, // noticeable but restrained
226
- strong: { offset: 2, blur: 5 }, // slightly deeper blur, same offset as medium
227
- }
228
-
229
- /**
230
- * Creates a raised (elevated) neumorphic shadow.
231
- * Element appears to float above the surface.
232
- *
233
- * Uses a soft dark shadow (bottom-right) and a sharp rim light (top-left).
234
- */
235
- export function createRaisedShadow(
236
- surface: ShadowSurface = 'charcoal',
237
- intensity: ShadowIntensity = 'medium'
238
- ): ViewStyle {
239
- const colors = shadowColors[surface]
240
- const { offset, blur } = intensityConfig[intensity]
241
-
242
- // Rim light is sharper: same offset as shadow, but minimal blur for crisp edge
243
- const rimBlur = 1 // Very tight blur for crisp rim
244
-
245
- return Platform.select({
246
- web: {
247
- boxShadow: `${offset}px ${offset}px ${blur}px ${colors.dark}, -${offset}px -${offset}px ${rimBlur}px ${colors.light}`,
248
- } as any,
249
- default: {
250
- // React Native shadow approximation (limited compared to web)
251
- shadowColor: '#000',
252
- shadowOffset: { width: offset, height: offset },
253
- shadowOpacity: 0.3,
254
- shadowRadius: blur / 2,
255
- elevation: offset,
256
- },
257
- }) as ViewStyle
258
- }
259
-
260
- /**
261
- * Creates a pressed (inset) neumorphic shadow.
262
- * Element appears pushed into the surface.
263
- *
264
- * Uses a soft dark inset shadow (top-left) and a thin sharp rim light (bottom-right).
265
- */
266
- export function createPressedShadow(
267
- surface: ShadowSurface = 'charcoal',
268
- intensity: ShadowIntensity = 'medium'
269
- ): ViewStyle {
270
- const colors = shadowColors[surface]
271
- const { offset, blur } = intensityConfig[intensity]
272
-
273
- // Rim light is always thin and subtle for pressed states
274
- const rimOffset = 1 // Fixed thin rim
275
- const rimBlur = 1 // Very tight blur for crisp edge
276
-
277
- return Platform.select({
278
- web: {
279
- boxShadow: `inset ${offset}px ${offset}px ${blur}px ${colors.darker}, inset -${rimOffset}px -${rimOffset}px ${rimBlur}px ${colors.light}`,
280
- } as any,
281
- default: {
282
- // React Native doesn't support inset shadows, approximate with darker bg
283
- shadowOpacity: 0,
284
- elevation: 0,
285
- },
286
- }) as ViewStyle
287
- }
288
-
289
- /**
290
- * Creates a flat (no shadow) style for hover states.
291
- */
292
- export function createFlatShadow(): ViewStyle {
293
- return Platform.select({
294
- web: {
295
- boxShadow: 'none',
296
- } as any,
297
- default: {
298
- shadowOpacity: 0,
299
- elevation: 0,
300
- },
301
- }) as ViewStyle
302
- }
303
-
304
- /**
305
- * Creates a hover shadow for raised elements.
306
- * Reduces shadow depth but keeps a subtle rim light to maintain visual boundary.
307
- */
308
- export function createRaisedHoverShadow(
309
- surface: ShadowSurface = 'charcoal',
310
- intensity: ShadowIntensity = 'medium'
311
- ): ViewStyle {
312
- const colors = shadowColors[surface]
313
- const { offset, blur } = intensityConfig[intensity]
314
-
315
- // Reduce shadow depth by half for hover, keep minimal rim light
316
- const hoverOffset = Math.max(1, Math.round(offset / 2))
317
- const hoverBlur = Math.max(1, Math.round(blur / 2))
318
- const rimBlur = 1
319
-
320
- return Platform.select({
321
- web: {
322
- // Keep same offsets as normal state for rim to prevent "shrinking" effect
323
- boxShadow: `${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${colors.dark}, -${offset}px -${offset}px ${rimBlur}px ${colors.light}`,
324
- } as any,
325
- default: {
326
- shadowColor: '#000',
327
- shadowOffset: { width: hoverOffset, height: hoverOffset },
328
- shadowOpacity: 0.2,
329
- shadowRadius: hoverBlur / 2,
330
- elevation: hoverOffset,
331
- },
332
- }) as ViewStyle
333
- }
334
-
335
- /**
336
- * Creates a hover shadow for pressed elements.
337
- * Reduces shadow depth but keeps a subtle rim light to maintain visual boundary.
338
- */
339
- export function createPressedHoverShadow(
340
- surface: ShadowSurface = 'charcoal',
341
- intensity: ShadowIntensity = 'medium'
342
- ): ViewStyle {
343
- const colors = shadowColors[surface]
344
- const { offset, blur } = intensityConfig[intensity]
345
-
346
- // Reduce shadow depth by half for hover, keep minimal rim light
347
- const hoverOffset = Math.max(1, Math.round(offset / 2))
348
- const hoverBlur = Math.max(1, Math.round(blur / 2))
349
- const rimBlur = 1
350
-
351
- return Platform.select({
352
- web: {
353
- // Keep rim offset at 1px (same as pressed normal) to prevent "shrinking" effect
354
- boxShadow: `inset ${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${colors.darker}, inset -1px -1px ${rimBlur}px ${colors.light}`,
355
- } as any,
356
- default: {
357
- shadowOpacity: 0,
358
- elevation: 0,
359
- },
360
- }) as ViewStyle
361
- }
362
-
363
- /**
364
- * Pre-built shadow presets for common use cases.
365
- */
366
- export const neumorphicShadows = {
367
- // Charcoal surface shadows (for dark toolbars, cards)
368
- charcoal: {
369
- raised: {
370
- subtle: createRaisedShadow('charcoal', 'subtle'),
371
- medium: createRaisedShadow('charcoal', 'medium'),
372
- strong: createRaisedShadow('charcoal', 'strong'),
373
- },
374
- raisedHover: {
375
- subtle: createRaisedHoverShadow('charcoal', 'subtle'),
376
- medium: createRaisedHoverShadow('charcoal', 'medium'),
377
- strong: createRaisedHoverShadow('charcoal', 'strong'),
378
- },
379
- pressed: {
380
- subtle: createPressedShadow('charcoal', 'subtle'),
381
- medium: createPressedShadow('charcoal', 'medium'),
382
- strong: createPressedShadow('charcoal', 'strong'),
383
- },
384
- pressedHover: {
385
- subtle: createPressedHoverShadow('charcoal', 'subtle'),
386
- medium: createPressedHoverShadow('charcoal', 'medium'),
387
- strong: createPressedHoverShadow('charcoal', 'strong'),
388
- },
389
- flat: createFlatShadow(),
390
- },
391
- // Neutral dark surface shadows
392
- neutralDark: {
393
- raised: {
394
- subtle: createRaisedShadow('neutralDark', 'subtle'),
395
- medium: createRaisedShadow('neutralDark', 'medium'),
396
- strong: createRaisedShadow('neutralDark', 'strong'),
397
- },
398
- raisedHover: {
399
- subtle: createRaisedHoverShadow('neutralDark', 'subtle'),
400
- medium: createRaisedHoverShadow('neutralDark', 'medium'),
401
- strong: createRaisedHoverShadow('neutralDark', 'strong'),
402
- },
403
- pressed: {
404
- subtle: createPressedShadow('neutralDark', 'subtle'),
405
- medium: createPressedShadow('neutralDark', 'medium'),
406
- strong: createPressedShadow('neutralDark', 'strong'),
407
- },
408
- pressedHover: {
409
- subtle: createPressedHoverShadow('neutralDark', 'subtle'),
410
- medium: createPressedHoverShadow('neutralDark', 'medium'),
411
- strong: createPressedHoverShadow('neutralDark', 'strong'),
412
- },
413
- flat: createFlatShadow(),
414
- },
415
- // Neutral light surface shadows
416
- neutralLight: {
417
- raised: {
418
- subtle: createRaisedShadow('neutralLight', 'subtle'),
419
- medium: createRaisedShadow('neutralLight', 'medium'),
420
- strong: createRaisedShadow('neutralLight', 'strong'),
421
- },
422
- raisedHover: {
423
- subtle: createRaisedHoverShadow('neutralLight', 'subtle'),
424
- medium: createRaisedHoverShadow('neutralLight', 'medium'),
425
- strong: createRaisedHoverShadow('neutralLight', 'strong'),
426
- },
427
- pressed: {
428
- subtle: createPressedShadow('neutralLight', 'subtle'),
429
- medium: createPressedShadow('neutralLight', 'medium'),
430
- strong: createPressedShadow('neutralLight', 'strong'),
431
- },
432
- pressedHover: {
433
- subtle: createPressedHoverShadow('neutralLight', 'subtle'),
434
- medium: createPressedHoverShadow('neutralLight', 'medium'),
435
- strong: createPressedHoverShadow('neutralLight', 'strong'),
436
- },
437
- flat: createFlatShadow(),
438
- },
439
- }