@titan-design/react-ui 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MesoStatusCard-CQk71hSi.d.mts +77 -0
- package/dist/MesoStatusCard-CQk71hSi.d.ts +77 -0
- package/dist/bodymap.d.mts +246 -3
- package/dist/bodymap.d.ts +246 -3
- package/dist/bodymap.js +441 -97
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +1958 -66
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +71 -738
- package/dist/index.d.ts +71 -738
- package/dist/index.js +888 -1583
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4515 -2348
- package/dist/index.mjs.map +1 -1
- package/dist/pages-D7Jlssvp.d.ts +791 -0
- package/dist/pages-MO0JCySL.d.mts +791 -0
- package/dist/pages.d.mts +4 -0
- package/dist/pages.d.ts +4 -0
- package/dist/pages.js +6646 -0
- package/dist/pages.js.map +1 -0
- package/dist/pages.mjs +6626 -0
- package/dist/pages.mjs.map +1 -0
- package/dist/theme/index.d.mts +28 -2
- package/dist/theme/index.d.ts +28 -2
- package/dist/theme/index.js +37 -0
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +1880 -2
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.mjs +573 -1
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/package.json +9 -7
- package/src/components/custom/Workout/ActiveWorkoutPage.tsx +10 -15
- package/src/components/custom/Workout/BaseBadge.stories.tsx +3 -3
- package/src/components/custom/Workout/BaseBadge.test.tsx +1 -1
- package/src/components/custom/Workout/BaseBadge.tsx +1 -1
- package/src/components/custom/Workout/BodyMap.tsx +7 -8
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +25 -28
- package/src/components/custom/Workout/CapacityBandChart.tsx +2 -3
- package/src/components/custom/Workout/ExerciseCard.tsx +17 -28
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +38 -31
- package/src/components/custom/Workout/InputBar.tsx +10 -11
- package/src/components/custom/Workout/IntensityBar.test.tsx +112 -60
- package/src/components/custom/Workout/IntensityBar.tsx +109 -58
- package/src/components/custom/Workout/MesoCard.tsx +2 -6
- package/src/components/custom/Workout/MesoStatusCard.tsx +17 -15
- package/src/components/custom/Workout/MuscleGroupChip.tsx +2 -4
- package/src/components/custom/Workout/PlaceholderStrip.tsx +5 -10
- package/src/components/custom/Workout/PrBadge.tsx +3 -3
- package/src/components/custom/Workout/PrHistoryModal.tsx +14 -16
- package/src/components/custom/Workout/ProgramPlanningPage.tsx +8 -12
- package/src/components/custom/Workout/README.md +50 -0
- package/src/components/custom/Workout/ReadinessCheck.tsx +13 -11
- package/src/components/custom/Workout/RestTimer.test.tsx +41 -10
- package/src/components/custom/Workout/RestTimer.tsx +55 -49
- package/src/components/custom/Workout/SetRow.tsx +20 -8
- package/src/components/custom/Workout/StrengthTrendChart.tsx +15 -17
- package/src/components/custom/Workout/TempoBar.stories.tsx +95 -0
- package/src/components/custom/Workout/TempoBar.test.tsx +103 -0
- package/src/components/custom/Workout/TempoBar.tsx +215 -0
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +69 -2
- package/src/components/custom/Workout/TempoDisplay.test.tsx +35 -0
- package/src/components/custom/Workout/TempoDisplay.tsx +104 -1
- package/src/components/custom/Workout/TrainingStatusPage.tsx +8 -17
- package/src/components/custom/Workout/VelocityStrip.test.tsx +89 -2
- package/src/components/custom/Workout/VelocityStrip.tsx +210 -43
- package/src/components/custom/Workout/WeekRow.test.tsx +2 -2
- package/src/components/custom/Workout/WeekRow.tsx +2 -1
- package/src/components/custom/Workout/WeightBadge.test.tsx +2 -2
- package/src/components/custom/Workout/WeightBadge.tsx +2 -2
- package/src/components/custom/Workout/WorkoutCard.tsx +3 -8
- package/src/components/custom/Workout/icons.tsx +68 -0
- package/src/components/custom/Workout/index.ts +47 -47
- package/src/index.ts +3 -2
- package/src/pages.ts +61 -0
- package/src/test/nativewind-stub.ts +13 -0
- package/src/test/stories-smoke.test.tsx +50 -0
- package/src/theme/ThemeProvider.test.tsx +24 -0
- package/src/theme/ThemeProvider.tsx +50 -0
- package/src/theme/barrel.ts +53 -0
- package/src/theme/index.ts +8 -41
- package/src/theme/native-theming-guard.test.ts +117 -0
- package/src/theme/resolve-color.ts +19 -0
- package/dist/bodymap-BhG55xHM.d.mts +0 -318
- package/dist/bodymap-BhG55xHM.d.ts +0 -318
- package/dist/chunk-7XPB4NAO.mjs +0 -1013
- package/dist/chunk-7XPB4NAO.mjs.map +0 -1
- package/dist/chunk-P7TSQUN6.mjs +0 -846
- package/dist/chunk-P7TSQUN6.mjs.map +0 -1
- package/dist/chunk-TOD2WQBG.mjs +0 -1048
- package/dist/chunk-TOD2WQBG.mjs.map +0 -1
package/dist/bodymap.mjs
CHANGED
|
@@ -1,9 +1,409 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import '
|
|
3
|
-
import './chunk-7XPB4NAO.mjs';
|
|
4
|
-
import { useMemo, useState, useEffect } from 'react';
|
|
5
|
-
import { Animated, Easing, View, Text, Pressable, ScrollView } from 'react-native';
|
|
1
|
+
import { useMemo, useState, useEffect, Fragment as Fragment$1, useSyncExternalStore } from 'react';
|
|
2
|
+
import { Platform, Animated, Easing, View, Text, Pressable, ScrollView } from 'react-native';
|
|
6
3
|
import BodyHighlighter from 'react-native-body-highlighter';
|
|
4
|
+
import { clsx } from 'clsx';
|
|
5
|
+
import { twMerge } from 'tailwind-merge';
|
|
6
|
+
import { Fragment, jsx as jsx$1, jsxs as jsxs$1 } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
// src/components/custom/Workout/BodyMap.tsx
|
|
9
|
+
function cn(...inputs) {
|
|
10
|
+
return twMerge(clsx(inputs));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/theme/tokens/primitives.ts
|
|
14
|
+
var primitiveColors = {
|
|
15
|
+
// Blue scale (primary brand)
|
|
16
|
+
blue: {
|
|
17
|
+
400: "#60A5FA",
|
|
18
|
+
600: "#5048E5",
|
|
19
|
+
// Primary main
|
|
20
|
+
700: "#3832A0"},
|
|
21
|
+
// Teal scale (success)
|
|
22
|
+
teal: {
|
|
23
|
+
50: "#F0FDFA",
|
|
24
|
+
400: "#43C6B7",
|
|
25
|
+
// Success light
|
|
26
|
+
500: "#14B8A6",
|
|
27
|
+
700: "#0E8074"},
|
|
28
|
+
// Red scale (error)
|
|
29
|
+
red: {
|
|
30
|
+
50: "#FEF2F2",
|
|
31
|
+
400: "#DA6868",
|
|
32
|
+
// Error light
|
|
33
|
+
500: "#EF4444",
|
|
34
|
+
600: "#D14343",
|
|
35
|
+
// Error main
|
|
36
|
+
700: "#922E2E"},
|
|
37
|
+
// Amber scale (warning)
|
|
38
|
+
amber: {
|
|
39
|
+
50: "#FFFBEB",
|
|
40
|
+
400: "#FFBF4C",
|
|
41
|
+
// Warning light
|
|
42
|
+
500: "#FFB020",
|
|
43
|
+
// Warning main
|
|
44
|
+
600: "#B27B16"},
|
|
45
|
+
// Sky/Blue scale (info)
|
|
46
|
+
sky: {
|
|
47
|
+
50: "#F0F9FF",
|
|
48
|
+
400: "#64B6F7",
|
|
49
|
+
// Info light
|
|
50
|
+
500: "#2196F3",
|
|
51
|
+
700: "#0B79D0"},
|
|
52
|
+
// Neutral/Gray scale
|
|
53
|
+
neutral: {
|
|
54
|
+
50: "#FAFAFA",
|
|
55
|
+
100: "#F3F4F6",
|
|
56
|
+
300: "#D1D5DB",
|
|
57
|
+
400: "#9CA3AF",
|
|
58
|
+
500: "#6B7280",
|
|
59
|
+
600: "#4B5563",
|
|
60
|
+
900: "#111827"},
|
|
61
|
+
// Orange scale (accent/brand color)
|
|
62
|
+
accent: {
|
|
63
|
+
200: "#FF9630",
|
|
64
|
+
300: "#FF8500",
|
|
65
|
+
400: "#FF7900",
|
|
66
|
+
500: "#F56C00",
|
|
67
|
+
600: "#E06D10",
|
|
68
|
+
700: "#D0620C"},
|
|
69
|
+
// Charcoal scale (dark backgrounds)
|
|
70
|
+
charcoal: {
|
|
71
|
+
300: "#2C2C2C",
|
|
72
|
+
400: "#1F1F1F",
|
|
73
|
+
500: "#1C1C1C",
|
|
74
|
+
600: "#191919",
|
|
75
|
+
700: "#161616",
|
|
76
|
+
900: "#101010"
|
|
77
|
+
},
|
|
78
|
+
// Steel scale (cool accent)
|
|
79
|
+
steel: {
|
|
80
|
+
300: "#678498",
|
|
81
|
+
400: "#557488",
|
|
82
|
+
500: "#406D87",
|
|
83
|
+
600: "#39617A",
|
|
84
|
+
700: "#32556D"},
|
|
85
|
+
// Pure colors
|
|
86
|
+
white: "#FFFFFF"};
|
|
87
|
+
var discreteRainbow = [
|
|
88
|
+
"#E8ECFB",
|
|
89
|
+
"#D9CCE3",
|
|
90
|
+
"#D1BBD7",
|
|
91
|
+
"#CAACCB",
|
|
92
|
+
"#BA8DB4",
|
|
93
|
+
"#AE76A3",
|
|
94
|
+
"#AA6F9E",
|
|
95
|
+
"#994F88",
|
|
96
|
+
"#882E72",
|
|
97
|
+
"#1965B0",
|
|
98
|
+
"#437DBF",
|
|
99
|
+
"#5289C7",
|
|
100
|
+
"#6195CF",
|
|
101
|
+
"#7BAFDE",
|
|
102
|
+
"#4EB265",
|
|
103
|
+
"#90C987",
|
|
104
|
+
"#CAE0AB",
|
|
105
|
+
"#F7F056",
|
|
106
|
+
"#F7CB45",
|
|
107
|
+
"#F6C141",
|
|
108
|
+
"#F4A736",
|
|
109
|
+
"#F1932D",
|
|
110
|
+
"#EE8026",
|
|
111
|
+
"#E8601C",
|
|
112
|
+
"#E65518",
|
|
113
|
+
"#DC050C",
|
|
114
|
+
"#A5170E",
|
|
115
|
+
"#72190E",
|
|
116
|
+
"#42150A"
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
// src/theme/tokens/semantic.ts
|
|
120
|
+
var semanticColorsLight = {
|
|
121
|
+
// Brand colors (brand-*)
|
|
122
|
+
"brand-primary": primitiveColors.accent[400],
|
|
123
|
+
// #FF7900
|
|
124
|
+
"brand-primary-light": primitiveColors.accent[200],
|
|
125
|
+
// #FF9630
|
|
126
|
+
"brand-primary-dark": primitiveColors.accent[700],
|
|
127
|
+
// #D0620C
|
|
128
|
+
"brand-primary-subtle": "rgba(255, 121, 0, 0.08)",
|
|
129
|
+
"brand-primary-hover": primitiveColors.accent[500],
|
|
130
|
+
"brand-primary-active": primitiveColors.accent[600],
|
|
131
|
+
"brand-secondary": primitiveColors.steel[500],
|
|
132
|
+
// #406D87
|
|
133
|
+
"brand-secondary-light": primitiveColors.steel[300],
|
|
134
|
+
// #678498
|
|
135
|
+
"brand-secondary-dark": primitiveColors.steel[700],
|
|
136
|
+
// #32556D
|
|
137
|
+
"brand-secondary-subtle": "rgba(64, 109, 135, 0.08)",
|
|
138
|
+
"brand-secondary-hover": primitiveColors.steel[600],
|
|
139
|
+
"brand-secondary-active": primitiveColors.steel[700],
|
|
140
|
+
// Text on brand backgrounds (on-*)
|
|
141
|
+
"on-brand-primary": primitiveColors.white,
|
|
142
|
+
"on-brand-secondary": primitiveColors.white,
|
|
143
|
+
// Status colors (status-*)
|
|
144
|
+
"status-success": primitiveColors.teal[500],
|
|
145
|
+
// #14B8A6
|
|
146
|
+
"status-success-light": primitiveColors.teal[400],
|
|
147
|
+
// #43C6B7
|
|
148
|
+
"status-success-dark": primitiveColors.teal[700],
|
|
149
|
+
// #0E8074
|
|
150
|
+
"status-success-subtle": primitiveColors.teal[50],
|
|
151
|
+
"status-error": primitiveColors.red[600],
|
|
152
|
+
// #D14343
|
|
153
|
+
"status-error-light": primitiveColors.red[400],
|
|
154
|
+
// #DA6868
|
|
155
|
+
"status-error-dark": primitiveColors.red[700],
|
|
156
|
+
// #922E2E
|
|
157
|
+
"status-error-subtle": primitiveColors.red[50],
|
|
158
|
+
"status-warning": primitiveColors.amber[500],
|
|
159
|
+
// #FFB020
|
|
160
|
+
"status-warning-light": primitiveColors.amber[400],
|
|
161
|
+
// #FFBF4C
|
|
162
|
+
"status-warning-dark": primitiveColors.amber[600],
|
|
163
|
+
// #B27B16
|
|
164
|
+
"status-warning-subtle": primitiveColors.amber[50],
|
|
165
|
+
"status-info": primitiveColors.sky[500],
|
|
166
|
+
// #2196F3
|
|
167
|
+
"status-info-light": primitiveColors.sky[400],
|
|
168
|
+
// #64B6F7
|
|
169
|
+
"status-info-dark": primitiveColors.sky[700],
|
|
170
|
+
// #0B79D0
|
|
171
|
+
"status-info-subtle": primitiveColors.sky[50],
|
|
172
|
+
// Text on status backgrounds (on-status-*)
|
|
173
|
+
"on-status-success": primitiveColors.white,
|
|
174
|
+
"on-status-error": primitiveColors.white,
|
|
175
|
+
"on-status-warning": primitiveColors.white,
|
|
176
|
+
"on-status-info": primitiveColors.white,
|
|
177
|
+
// Result/outcome indicators (result-*)
|
|
178
|
+
"result-improve": "#4caf50",
|
|
179
|
+
// Green - positive outcome
|
|
180
|
+
"result-improve-light": "rgba(76, 175, 80, 0.12)",
|
|
181
|
+
"result-improve-dark": "#248a24",
|
|
182
|
+
"result-degrade": "#ef5350",
|
|
183
|
+
// Red - negative outcome
|
|
184
|
+
"result-degrade-light": "rgba(239, 83, 80, 0.12)",
|
|
185
|
+
"result-degrade-dark": "#b30000",
|
|
186
|
+
"result-inconclusive": "#9E9A97",
|
|
187
|
+
// Gray - no clear result
|
|
188
|
+
"result-inconclusive-light": "rgba(158, 154, 151, 0.12)",
|
|
189
|
+
"result-neutral": primitiveColors.neutral[500],
|
|
190
|
+
// Neutral baseline
|
|
191
|
+
// Text on result backgrounds (on-result-*)
|
|
192
|
+
"on-result-improve": primitiveColors.white,
|
|
193
|
+
"on-result-degrade": primitiveColors.white,
|
|
194
|
+
"on-result-inconclusive": primitiveColors.white,
|
|
195
|
+
// Data visualization colors (data-*)
|
|
196
|
+
// First 10 colors from discrete rainbow optimized for charts
|
|
197
|
+
"data-1": discreteRainbow[9],
|
|
198
|
+
// #1965B0 - Blue
|
|
199
|
+
"data-2": discreteRainbow[14],
|
|
200
|
+
// #4EB265 - Green
|
|
201
|
+
"data-3": discreteRainbow[17],
|
|
202
|
+
// #F7F056 - Yellow
|
|
203
|
+
"data-4": discreteRainbow[25],
|
|
204
|
+
// #DC050C - Red
|
|
205
|
+
"data-5": discreteRainbow[8],
|
|
206
|
+
// #882E72 - Purple
|
|
207
|
+
"data-6": discreteRainbow[20],
|
|
208
|
+
// #F4A736 - Orange
|
|
209
|
+
"data-7": discreteRainbow[13],
|
|
210
|
+
// #7BAFDE - Light Blue
|
|
211
|
+
"data-8": discreteRainbow[15],
|
|
212
|
+
// #90C987 - Light Green
|
|
213
|
+
"data-9": discreteRainbow[3],
|
|
214
|
+
// #CAACCB - Lavender
|
|
215
|
+
"data-10": discreteRainbow[22],
|
|
216
|
+
// #EE8026 - Dark Orange
|
|
217
|
+
// Text colors (text-*)
|
|
218
|
+
"text-primary": "#121828",
|
|
219
|
+
"text-secondary": "#65748B",
|
|
220
|
+
"text-tertiary": primitiveColors.neutral[400],
|
|
221
|
+
"text-disabled": "rgba(55, 65, 81, 0.48)",
|
|
222
|
+
"text-inverse": primitiveColors.white,
|
|
223
|
+
"text-link": primitiveColors.blue[600],
|
|
224
|
+
"text-link-hover": primitiveColors.blue[700],
|
|
225
|
+
// Surface colors (surface-*) - for elevated containers
|
|
226
|
+
"surface-base": primitiveColors.white,
|
|
227
|
+
"surface-elevated": primitiveColors.neutral[50],
|
|
228
|
+
// #FAFAFA - slightly off-white for elevated cards
|
|
229
|
+
"surface-raised": primitiveColors.neutral[100],
|
|
230
|
+
// #F3F4F6 - light gray for raised cards
|
|
231
|
+
"surface-overlay": primitiveColors.white,
|
|
232
|
+
"surface-input": primitiveColors.neutral[50],
|
|
233
|
+
// Input field background (filled variant)
|
|
234
|
+
// Background colors (background-*)
|
|
235
|
+
"background-base": "#EBEBEB",
|
|
236
|
+
"background-default": primitiveColors.white,
|
|
237
|
+
"background-subtle": primitiveColors.neutral[50],
|
|
238
|
+
// Border colors (border-*)
|
|
239
|
+
"border-default": "#E8E9EB",
|
|
240
|
+
"border-subtle": primitiveColors.neutral[100],
|
|
241
|
+
"border-strong": primitiveColors.neutral[300],
|
|
242
|
+
"border-focus": primitiveColors.blue[600],
|
|
243
|
+
"border-input": primitiveColors.neutral[300],
|
|
244
|
+
// Input field border
|
|
245
|
+
"border-input-hover": primitiveColors.neutral[400],
|
|
246
|
+
// Input field border on hover
|
|
247
|
+
"border-input-focus": primitiveColors.blue[600],
|
|
248
|
+
// Input field border on focus
|
|
249
|
+
"border-input-error": primitiveColors.red[600],
|
|
250
|
+
// Input field border on error
|
|
251
|
+
// Interactive states (interactive-*)
|
|
252
|
+
"interactive-hover": "rgba(55, 65, 81, 0.04)",
|
|
253
|
+
"interactive-focus": "rgba(55, 65, 81, 0.12)",
|
|
254
|
+
"interactive-active": "rgba(55, 65, 81, 0.16)",
|
|
255
|
+
"interactive-selected": "rgba(55, 65, 81, 0.08)",
|
|
256
|
+
"interactive-disabled": "rgba(55, 65, 81, 0.12)",
|
|
257
|
+
"interactive-disabled-text": "rgba(55, 65, 81, 0.26)",
|
|
258
|
+
// Divider
|
|
259
|
+
"divider": "#E8E9EB",
|
|
260
|
+
// Avatar default
|
|
261
|
+
"avatar-background": primitiveColors.neutral[500],
|
|
262
|
+
"avatar-text": primitiveColors.white
|
|
263
|
+
};
|
|
264
|
+
var semanticColorsDark = {
|
|
265
|
+
// Brand colors stay the same in dark mode
|
|
266
|
+
"brand-primary": primitiveColors.accent[400],
|
|
267
|
+
"brand-primary-light": primitiveColors.accent[200],
|
|
268
|
+
"brand-primary-dark": primitiveColors.accent[700],
|
|
269
|
+
"brand-primary-subtle": "rgba(255, 121, 0, 0.12)",
|
|
270
|
+
"brand-primary-hover": primitiveColors.accent[300],
|
|
271
|
+
"brand-primary-active": primitiveColors.accent[200],
|
|
272
|
+
"brand-secondary": primitiveColors.steel[500],
|
|
273
|
+
"brand-secondary-light": primitiveColors.steel[300],
|
|
274
|
+
"brand-secondary-dark": primitiveColors.steel[700],
|
|
275
|
+
"brand-secondary-subtle": "rgba(64, 109, 135, 0.12)",
|
|
276
|
+
"brand-secondary-hover": primitiveColors.steel[400],
|
|
277
|
+
"brand-secondary-active": primitiveColors.steel[300],
|
|
278
|
+
// Text on brand backgrounds
|
|
279
|
+
"on-brand-primary": primitiveColors.white,
|
|
280
|
+
"on-brand-secondary": primitiveColors.white,
|
|
281
|
+
// Status colors
|
|
282
|
+
"status-success": primitiveColors.teal[500],
|
|
283
|
+
"status-success-light": primitiveColors.teal[400],
|
|
284
|
+
"status-success-dark": primitiveColors.teal[700],
|
|
285
|
+
"status-success-subtle": "rgba(20, 184, 166, 0.12)",
|
|
286
|
+
"status-error": primitiveColors.red[600],
|
|
287
|
+
"status-error-light": primitiveColors.red[400],
|
|
288
|
+
"status-error-dark": primitiveColors.red[700],
|
|
289
|
+
"status-error-subtle": "rgba(209, 67, 67, 0.12)",
|
|
290
|
+
"status-warning": primitiveColors.amber[500],
|
|
291
|
+
"status-warning-light": primitiveColors.amber[400],
|
|
292
|
+
"status-warning-dark": primitiveColors.amber[600],
|
|
293
|
+
"status-warning-subtle": "rgba(255, 176, 32, 0.12)",
|
|
294
|
+
"status-info": primitiveColors.sky[500],
|
|
295
|
+
"status-info-light": primitiveColors.sky[400],
|
|
296
|
+
"status-info-dark": primitiveColors.sky[700],
|
|
297
|
+
"status-info-subtle": "rgba(33, 150, 243, 0.12)",
|
|
298
|
+
// Text on status backgrounds
|
|
299
|
+
"on-status-success": primitiveColors.white,
|
|
300
|
+
"on-status-error": primitiveColors.white,
|
|
301
|
+
"on-status-warning": primitiveColors.white,
|
|
302
|
+
"on-status-info": primitiveColors.white,
|
|
303
|
+
// Result/outcome indicators (result-*)
|
|
304
|
+
"result-improve": "#4caf50",
|
|
305
|
+
"result-improve-light": "rgba(76, 175, 80, 0.16)",
|
|
306
|
+
"result-improve-dark": "#248a24",
|
|
307
|
+
"result-degrade": "#ef5350",
|
|
308
|
+
"result-degrade-light": "rgba(239, 83, 80, 0.16)",
|
|
309
|
+
"result-degrade-dark": "#b30000",
|
|
310
|
+
"result-inconclusive": "#9E9A97",
|
|
311
|
+
"result-inconclusive-light": "rgba(158, 154, 151, 0.16)",
|
|
312
|
+
"result-neutral": primitiveColors.neutral[400],
|
|
313
|
+
// Text on result backgrounds
|
|
314
|
+
"on-result-improve": primitiveColors.white,
|
|
315
|
+
"on-result-degrade": primitiveColors.white,
|
|
316
|
+
"on-result-inconclusive": primitiveColors.white,
|
|
317
|
+
// Data visualization colors (same in dark mode for consistency)
|
|
318
|
+
"data-1": discreteRainbow[9],
|
|
319
|
+
"data-2": discreteRainbow[14],
|
|
320
|
+
"data-3": discreteRainbow[17],
|
|
321
|
+
"data-4": discreteRainbow[25],
|
|
322
|
+
"data-5": discreteRainbow[8],
|
|
323
|
+
"data-6": discreteRainbow[20],
|
|
324
|
+
"data-7": discreteRainbow[13],
|
|
325
|
+
"data-8": discreteRainbow[15],
|
|
326
|
+
"data-9": discreteRainbow[3],
|
|
327
|
+
"data-10": discreteRainbow[22],
|
|
328
|
+
// Text colors - inverted for dark mode
|
|
329
|
+
"text-primary": primitiveColors.neutral[100],
|
|
330
|
+
"text-secondary": primitiveColors.neutral[400],
|
|
331
|
+
"text-tertiary": primitiveColors.neutral[500],
|
|
332
|
+
"text-disabled": "rgba(255, 255, 255, 0.38)",
|
|
333
|
+
"text-inverse": primitiveColors.neutral[900],
|
|
334
|
+
"text-link": "#828DF8",
|
|
335
|
+
"text-link-hover": primitiveColors.blue[400],
|
|
336
|
+
// Surface colors - dark backgrounds
|
|
337
|
+
"surface-base": primitiveColors.charcoal[700],
|
|
338
|
+
// #161616 - main surface
|
|
339
|
+
"surface-elevated": primitiveColors.charcoal[600],
|
|
340
|
+
// #191919 - elevated surface
|
|
341
|
+
"surface-raised": primitiveColors.charcoal[500],
|
|
342
|
+
// #1C1C1C - raised surface
|
|
343
|
+
"surface-overlay": primitiveColors.charcoal[600],
|
|
344
|
+
// #191919 - overlay surface
|
|
345
|
+
"surface-input": primitiveColors.charcoal[600],
|
|
346
|
+
// #191919 - input surface
|
|
347
|
+
// Background colors
|
|
348
|
+
"background-base": primitiveColors.charcoal[900],
|
|
349
|
+
// #101010 - darkest charcoal
|
|
350
|
+
"background-default": primitiveColors.charcoal[700],
|
|
351
|
+
// #161616 - main background
|
|
352
|
+
"background-subtle": primitiveColors.charcoal[500],
|
|
353
|
+
// #1C1C1C - subtle background
|
|
354
|
+
// Border colors
|
|
355
|
+
"border-default": primitiveColors.charcoal[400],
|
|
356
|
+
// #1F1F1F - default border
|
|
357
|
+
"border-subtle": primitiveColors.charcoal[500],
|
|
358
|
+
// #1C1C1C - subtle border
|
|
359
|
+
"border-strong": primitiveColors.charcoal[300],
|
|
360
|
+
// #2C2C2C - strong border
|
|
361
|
+
"border-focus": "#828DF8",
|
|
362
|
+
"border-input": primitiveColors.neutral[600],
|
|
363
|
+
"border-input-hover": primitiveColors.neutral[500],
|
|
364
|
+
"border-input-focus": "#828DF8",
|
|
365
|
+
"border-input-error": primitiveColors.red[500],
|
|
366
|
+
// Interactive states
|
|
367
|
+
"interactive-hover": "rgba(255, 255, 255, 0.04)",
|
|
368
|
+
"interactive-focus": "rgba(255, 255, 255, 0.12)",
|
|
369
|
+
"interactive-active": "rgba(255, 255, 255, 0.16)",
|
|
370
|
+
"interactive-selected": "rgba(255, 255, 255, 0.08)",
|
|
371
|
+
"interactive-disabled": "rgba(255, 255, 255, 0.12)",
|
|
372
|
+
"interactive-disabled-text": "rgba(255, 255, 255, 0.26)",
|
|
373
|
+
// Divider
|
|
374
|
+
"divider": primitiveColors.charcoal[400],
|
|
375
|
+
// #1F1F1F - divider color
|
|
376
|
+
// Avatar default
|
|
377
|
+
"avatar-background": primitiveColors.neutral[600],
|
|
378
|
+
"avatar-text": primitiveColors.white
|
|
379
|
+
};
|
|
380
|
+
function getSemanticColors(mode) {
|
|
381
|
+
return mode === "dark" ? semanticColorsDark : semanticColorsLight;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// src/theme/resolve-color.ts
|
|
385
|
+
function resolveColor(token, mode = "dark") {
|
|
386
|
+
return Platform.OS === "web" ? `var(--color-${token})` : getSemanticColors(mode)[token];
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// src/theme/workout-tokens.ts
|
|
390
|
+
var WORKOUT_TOKENS = {
|
|
391
|
+
// BodyMap volume heatmap scale (drive dynamic SVG fills, so inline values).
|
|
392
|
+
// Maps weekly-volume status against MEV/MAV/MRV landmarks to a fill color.
|
|
393
|
+
heatmap: {
|
|
394
|
+
none: "#E0E0E0",
|
|
395
|
+
// gray — no training data
|
|
396
|
+
under: "#4A90D9",
|
|
397
|
+
// cool blue — below MEV
|
|
398
|
+
maintenance: "#F5C842",
|
|
399
|
+
// warm yellow — MEV to MAV
|
|
400
|
+
productive: "#4CAF50",
|
|
401
|
+
// green — MAV to MRV
|
|
402
|
+
approaching: "#FFA502",
|
|
403
|
+
// orange — near MRV
|
|
404
|
+
over: "#FF6B35"
|
|
405
|
+
// red-orange — over MRV
|
|
406
|
+
}};
|
|
7
407
|
|
|
8
408
|
// src/components/custom/Workout/muscleTaxonomy.ts
|
|
9
409
|
var MuscleGroup = /* @__PURE__ */ ((MuscleGroup5) => {
|
|
@@ -188,14 +588,29 @@ var SLUG_TO_PRIMARY_MUSCLE = {
|
|
|
188
588
|
abs: "abs" /* ABS */,
|
|
189
589
|
obliques: "obliques" /* OBLIQUES */
|
|
190
590
|
};
|
|
591
|
+
function wrapJsx(fn) {
|
|
592
|
+
return function(type, props, ...rest) {
|
|
593
|
+
if (props && typeof props.className === "string" && props.className) {
|
|
594
|
+
const cn2 = props.className;
|
|
595
|
+
const cssStyle = { $$css: true, [cn2]: cn2 };
|
|
596
|
+
const existing = props.style;
|
|
597
|
+
props = {
|
|
598
|
+
...props,
|
|
599
|
+
style: existing ? [cssStyle, existing] : cssStyle
|
|
600
|
+
};
|
|
601
|
+
delete props.className;
|
|
602
|
+
}
|
|
603
|
+
return fn(type, props, ...rest);
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
var jsx = wrapJsx(jsx$1);
|
|
607
|
+
var jsxs = wrapJsx(jsxs$1);
|
|
191
608
|
|
|
192
609
|
// src/components/custom/Workout/BodyMap.tsx
|
|
193
610
|
var Body = BodyHighlighter.default ?? BodyHighlighter;
|
|
194
611
|
var OUTLINE_FILL = "rgba(255,255,255,0.08)";
|
|
195
612
|
var OUTLINE_BORDER = "rgba(255,255,255,0.12)";
|
|
196
613
|
var BODY_SCALE = 0.8;
|
|
197
|
-
var TEXT_PRIMARY = "var(--color-text-primary)";
|
|
198
|
-
var TEXT_SECONDARY = "var(--color-text-secondary)";
|
|
199
614
|
function buildSlugParts(data) {
|
|
200
615
|
const bySlug = /* @__PURE__ */ new Map();
|
|
201
616
|
for (const d of data) {
|
|
@@ -319,10 +734,10 @@ function BodyMap({
|
|
|
319
734
|
legend.length === 0 ? /* @__PURE__ */ jsx(
|
|
320
735
|
Text,
|
|
321
736
|
{
|
|
737
|
+
className: "text-text-secondary",
|
|
322
738
|
style: {
|
|
323
739
|
marginTop: 8,
|
|
324
740
|
fontSize: 12,
|
|
325
|
-
color: TEXT_SECONDARY,
|
|
326
741
|
textAlign: "center",
|
|
327
742
|
fontFamily: "Inter, sans-serif"
|
|
328
743
|
},
|
|
@@ -371,7 +786,7 @@ function ViewToggle({ view, onViewChange }) {
|
|
|
371
786
|
borderRadius: 9999,
|
|
372
787
|
backgroundColor: active ? "rgba(255,121,0,0.16)" : "transparent",
|
|
373
788
|
borderWidth: 1,
|
|
374
|
-
borderColor: active ? "#FF7900" : "
|
|
789
|
+
borderColor: active ? "#FF7900" : resolveColor("border-strong")
|
|
375
790
|
},
|
|
376
791
|
testID: `body-map-toggle-${side}`,
|
|
377
792
|
children: /* @__PURE__ */ jsx(
|
|
@@ -381,7 +796,7 @@ function ViewToggle({ view, onViewChange }) {
|
|
|
381
796
|
fontSize: 12,
|
|
382
797
|
fontFamily: "Inter, sans-serif",
|
|
383
798
|
fontWeight: active ? "700" : "500",
|
|
384
|
-
color: active ? "#FF7900" :
|
|
799
|
+
color: active ? "#FF7900" : resolveColor("text-secondary"),
|
|
385
800
|
textTransform: "capitalize"
|
|
386
801
|
},
|
|
387
802
|
children: side
|
|
@@ -404,6 +819,7 @@ function MuscleButton({ entry, highlighted, onMusclePress }) {
|
|
|
404
819
|
accessibilityRole: "button",
|
|
405
820
|
accessibilityLabel: label,
|
|
406
821
|
"aria-pressed": highlighted,
|
|
822
|
+
className: "bg-surface-raised",
|
|
407
823
|
style: {
|
|
408
824
|
flexDirection: "row",
|
|
409
825
|
alignItems: "center",
|
|
@@ -412,8 +828,7 @@ function MuscleButton({ entry, highlighted, onMusclePress }) {
|
|
|
412
828
|
paddingVertical: 3,
|
|
413
829
|
borderRadius: 9999,
|
|
414
830
|
borderWidth: 1,
|
|
415
|
-
borderColor: highlighted ? "#FF7900" : "
|
|
416
|
-
backgroundColor: "var(--color-surface-raised)"
|
|
831
|
+
borderColor: highlighted ? "#FF7900" : resolveColor("border-default")
|
|
417
832
|
},
|
|
418
833
|
testID: `body-map-muscle-${entry.key}`,
|
|
419
834
|
children: [
|
|
@@ -428,11 +843,11 @@ function MuscleButton({ entry, highlighted, onMusclePress }) {
|
|
|
428
843
|
/* @__PURE__ */ jsx(
|
|
429
844
|
Text,
|
|
430
845
|
{
|
|
846
|
+
className: "text-text-primary",
|
|
431
847
|
style: {
|
|
432
848
|
fontSize: 11,
|
|
433
849
|
fontFamily: "Inter, sans-serif",
|
|
434
|
-
fontWeight: "500"
|
|
435
|
-
color: TEXT_PRIMARY
|
|
850
|
+
fontWeight: "500"
|
|
436
851
|
},
|
|
437
852
|
accessibilityElementsHidden: true,
|
|
438
853
|
children: entry.name
|
|
@@ -442,14 +857,279 @@ function MuscleButton({ entry, highlighted, onMusclePress }) {
|
|
|
442
857
|
}
|
|
443
858
|
);
|
|
444
859
|
}
|
|
445
|
-
var
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
860
|
+
var sizeStyles = {
|
|
861
|
+
xs: "w-1 h-1",
|
|
862
|
+
sm: "w-1.5 h-1.5",
|
|
863
|
+
md: "w-2 h-2",
|
|
864
|
+
lg: "w-2.5 h-2.5"
|
|
865
|
+
};
|
|
866
|
+
var colorStyles = {
|
|
867
|
+
default: "bg-text-tertiary",
|
|
868
|
+
primary: "bg-brand-primary",
|
|
869
|
+
success: "bg-status-success",
|
|
870
|
+
error: "bg-status-error",
|
|
871
|
+
warning: "bg-status-warning",
|
|
872
|
+
info: "bg-status-info"
|
|
873
|
+
};
|
|
874
|
+
function Indicator({
|
|
875
|
+
size = "sm",
|
|
876
|
+
color = "default",
|
|
877
|
+
customColor,
|
|
878
|
+
glow = false,
|
|
879
|
+
ring = false,
|
|
880
|
+
className,
|
|
881
|
+
style,
|
|
882
|
+
...props
|
|
883
|
+
}) {
|
|
884
|
+
const dynamicStyle = {
|
|
885
|
+
...typeof style === "object" ? style : {},
|
|
886
|
+
...customColor ? { backgroundColor: customColor } : {},
|
|
887
|
+
...glow && !customColor ? {} : {},
|
|
888
|
+
...glow && customColor ? { boxShadow: `0 0 6px ${customColor}` } : {}
|
|
889
|
+
};
|
|
890
|
+
return /* @__PURE__ */ jsx(
|
|
891
|
+
View,
|
|
892
|
+
{
|
|
893
|
+
className: cn(
|
|
894
|
+
"rounded-full shrink-0",
|
|
895
|
+
sizeStyles[size],
|
|
896
|
+
!customColor && colorStyles[color],
|
|
897
|
+
ring && "border-2 border-background-base",
|
|
898
|
+
glow && !customColor && color === "success" && "shadow-[0_0_6px_rgba(20,184,166,0.6)]",
|
|
899
|
+
glow && !customColor && color === "error" && "shadow-[0_0_6px_rgba(239,68,68,0.6)]",
|
|
900
|
+
glow && !customColor && color === "warning" && "shadow-[0_0_6px_rgba(245,158,11,0.6)]",
|
|
901
|
+
glow && !customColor && color === "primary" && "shadow-[0_0_6px_rgba(255,121,0,0.6)]",
|
|
902
|
+
className
|
|
903
|
+
),
|
|
904
|
+
style: Object.keys(dynamicStyle).length > 0 ? dynamicStyle : style,
|
|
905
|
+
...props
|
|
906
|
+
}
|
|
907
|
+
);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// src/components/ui/badge/Badge.tsx
|
|
911
|
+
var variantColorStyles = {
|
|
912
|
+
solid: {
|
|
913
|
+
default: "bg-border-strong text-text-inverse",
|
|
914
|
+
primary: "bg-brand-primary text-text-inverse",
|
|
915
|
+
secondary: "bg-brand-secondary text-text-inverse",
|
|
916
|
+
success: "bg-status-success text-text-inverse",
|
|
917
|
+
error: "bg-status-error text-text-inverse",
|
|
918
|
+
warning: "bg-status-warning text-text-inverse",
|
|
919
|
+
info: "bg-status-info text-text-inverse"
|
|
920
|
+
},
|
|
921
|
+
subtle: {
|
|
922
|
+
default: "bg-surface-raised text-text-secondary",
|
|
923
|
+
primary: "bg-brand-primary-subtle text-brand-primary",
|
|
924
|
+
secondary: "bg-brand-secondary-subtle text-brand-secondary",
|
|
925
|
+
success: "bg-status-success-subtle text-status-success",
|
|
926
|
+
error: "bg-status-error-subtle text-status-error",
|
|
927
|
+
warning: "bg-status-warning-subtle text-status-warning",
|
|
928
|
+
info: "bg-status-info-subtle text-status-info"
|
|
929
|
+
},
|
|
930
|
+
outline: {
|
|
931
|
+
default: "border border-border-strong text-text-secondary",
|
|
932
|
+
primary: "border border-brand-primary text-brand-primary",
|
|
933
|
+
secondary: "border border-brand-secondary text-brand-secondary",
|
|
934
|
+
success: "border border-status-success text-status-success",
|
|
935
|
+
error: "border border-status-error text-status-error",
|
|
936
|
+
warning: "border border-status-warning text-status-warning",
|
|
937
|
+
info: "border border-status-info text-status-info"
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
var sizeStyles2 = {
|
|
941
|
+
sm: "px-1.5 py-0.5 text-xs",
|
|
942
|
+
md: "px-2 py-0.5 text-xs",
|
|
943
|
+
lg: "px-2.5 py-1 text-sm"
|
|
944
|
+
};
|
|
945
|
+
function Badge({
|
|
946
|
+
variant = "subtle",
|
|
947
|
+
color = "default",
|
|
948
|
+
size = "md",
|
|
949
|
+
dot,
|
|
950
|
+
dotColor,
|
|
951
|
+
className,
|
|
952
|
+
children,
|
|
953
|
+
...props
|
|
954
|
+
}) {
|
|
955
|
+
return /* @__PURE__ */ jsxs(
|
|
956
|
+
View,
|
|
957
|
+
{
|
|
958
|
+
className: cn(
|
|
959
|
+
"inline-flex items-center justify-center rounded-full font-medium",
|
|
960
|
+
variantColorStyles[variant][color],
|
|
961
|
+
sizeStyles2[size],
|
|
962
|
+
className
|
|
963
|
+
),
|
|
964
|
+
...props,
|
|
965
|
+
children: [
|
|
966
|
+
dot && /* @__PURE__ */ jsx(
|
|
967
|
+
Indicator,
|
|
968
|
+
{
|
|
969
|
+
size: "xs",
|
|
970
|
+
color: dotColor ?? (color === "default" || color === "secondary" ? "default" : color),
|
|
971
|
+
className: "mr-0.5"
|
|
972
|
+
}
|
|
973
|
+
),
|
|
974
|
+
typeof children === "string" ? /* @__PURE__ */ jsx(Text, { className: "text-inherit font-medium", children }) : children
|
|
975
|
+
]
|
|
976
|
+
}
|
|
977
|
+
);
|
|
978
|
+
}
|
|
449
979
|
var BRAND_PRIMARY = "#FF7900";
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
980
|
+
function normalizeData(data, height) {
|
|
981
|
+
if (data.length === 0) return [];
|
|
982
|
+
const min = Math.min(...data);
|
|
983
|
+
const max = Math.max(...data);
|
|
984
|
+
const range = max - min || 1;
|
|
985
|
+
return data.map((v) => height - (v - min) / range * height);
|
|
986
|
+
}
|
|
987
|
+
function normalizeValue(value, data, height) {
|
|
988
|
+
const min = Math.min(...data);
|
|
989
|
+
const max = Math.max(...data);
|
|
990
|
+
const range = max - min || 1;
|
|
991
|
+
return height - (value - min) / range * height;
|
|
992
|
+
}
|
|
993
|
+
function Sparkline({
|
|
994
|
+
data,
|
|
995
|
+
width = 80,
|
|
996
|
+
height = 30,
|
|
997
|
+
color,
|
|
998
|
+
showDots = false,
|
|
999
|
+
referenceLines,
|
|
1000
|
+
highlightLast = false,
|
|
1001
|
+
className,
|
|
1002
|
+
...props
|
|
1003
|
+
}) {
|
|
1004
|
+
if (data.length === 0) {
|
|
1005
|
+
return /* @__PURE__ */ jsx(
|
|
1006
|
+
View,
|
|
1007
|
+
{
|
|
1008
|
+
style: { width, height },
|
|
1009
|
+
className,
|
|
1010
|
+
testID: "sparkline-empty",
|
|
1011
|
+
accessibilityLabel: "Sparkline chart, no data",
|
|
1012
|
+
...props
|
|
1013
|
+
}
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
const resolvedColor = color ?? BRAND_PRIMARY;
|
|
1017
|
+
const normalized = normalizeData(data, height);
|
|
1018
|
+
const stepX = data.length > 1 ? width / (data.length - 1) : 0;
|
|
1019
|
+
const dotSize = 3;
|
|
1020
|
+
const highlightSize = 6;
|
|
1021
|
+
return /* @__PURE__ */ jsxs(
|
|
1022
|
+
View,
|
|
1023
|
+
{
|
|
1024
|
+
style: { width, height, position: "relative" },
|
|
1025
|
+
className: cn(className),
|
|
1026
|
+
accessibilityRole: "image",
|
|
1027
|
+
accessibilityLabel: `Sparkline chart with ${data.length} data points`,
|
|
1028
|
+
testID: "sparkline",
|
|
1029
|
+
...props,
|
|
1030
|
+
children: [
|
|
1031
|
+
referenceLines?.map((line, i) => {
|
|
1032
|
+
const y = normalizeValue(line.value, data, height);
|
|
1033
|
+
return /* @__PURE__ */ jsx(
|
|
1034
|
+
View,
|
|
1035
|
+
{
|
|
1036
|
+
style: [
|
|
1037
|
+
{
|
|
1038
|
+
position: "absolute",
|
|
1039
|
+
top: y,
|
|
1040
|
+
left: 0,
|
|
1041
|
+
right: 0,
|
|
1042
|
+
opacity: 0.6
|
|
1043
|
+
},
|
|
1044
|
+
line.dashed ? {
|
|
1045
|
+
height: 0,
|
|
1046
|
+
borderStyle: "dashed",
|
|
1047
|
+
borderTopWidth: 1,
|
|
1048
|
+
borderTopColor: line.color
|
|
1049
|
+
} : {
|
|
1050
|
+
height: 1,
|
|
1051
|
+
backgroundColor: line.color
|
|
1052
|
+
}
|
|
1053
|
+
],
|
|
1054
|
+
accessibilityElementsHidden: true,
|
|
1055
|
+
testID: `sparkline-reference-${i}`,
|
|
1056
|
+
children: line.label && /* @__PURE__ */ jsx(
|
|
1057
|
+
Text,
|
|
1058
|
+
{
|
|
1059
|
+
style: {
|
|
1060
|
+
position: "absolute",
|
|
1061
|
+
right: 0,
|
|
1062
|
+
top: -10,
|
|
1063
|
+
fontSize: 7,
|
|
1064
|
+
color: line.color,
|
|
1065
|
+
opacity: 1
|
|
1066
|
+
},
|
|
1067
|
+
testID: `sparkline-reference-label-${i}`,
|
|
1068
|
+
children: line.label
|
|
1069
|
+
}
|
|
1070
|
+
)
|
|
1071
|
+
},
|
|
1072
|
+
`ref-${i}`
|
|
1073
|
+
);
|
|
1074
|
+
}),
|
|
1075
|
+
normalized.map((y, i) => {
|
|
1076
|
+
if (i === 0) return null;
|
|
1077
|
+
const prevY = normalized[i - 1];
|
|
1078
|
+
const x1 = (i - 1) * stepX;
|
|
1079
|
+
const x2 = i * stepX;
|
|
1080
|
+
const dx = x2 - x1;
|
|
1081
|
+
const dy = y - prevY;
|
|
1082
|
+
const length = Math.sqrt(dx * dx + dy * dy);
|
|
1083
|
+
const angle = Math.atan2(dy, dx) * (180 / Math.PI);
|
|
1084
|
+
return /* @__PURE__ */ jsx(
|
|
1085
|
+
View,
|
|
1086
|
+
{
|
|
1087
|
+
style: {
|
|
1088
|
+
position: "absolute",
|
|
1089
|
+
left: x1,
|
|
1090
|
+
top: prevY,
|
|
1091
|
+
width: length,
|
|
1092
|
+
height: 1.5,
|
|
1093
|
+
backgroundColor: resolvedColor,
|
|
1094
|
+
transformOrigin: "0 0",
|
|
1095
|
+
transform: [{ rotate: `${angle}deg` }]
|
|
1096
|
+
},
|
|
1097
|
+
accessibilityElementsHidden: true,
|
|
1098
|
+
testID: `sparkline-segment-${i}`
|
|
1099
|
+
},
|
|
1100
|
+
`line-${i}`
|
|
1101
|
+
);
|
|
1102
|
+
}),
|
|
1103
|
+
(showDots || highlightLast) && normalized.map((y, i) => {
|
|
1104
|
+
const isLast = i === data.length - 1;
|
|
1105
|
+
const shouldShow = showDots || highlightLast && isLast;
|
|
1106
|
+
if (!shouldShow) return null;
|
|
1107
|
+
const size = highlightLast && isLast ? highlightSize : dotSize;
|
|
1108
|
+
return /* @__PURE__ */ jsx(
|
|
1109
|
+
View,
|
|
1110
|
+
{
|
|
1111
|
+
style: {
|
|
1112
|
+
position: "absolute",
|
|
1113
|
+
left: i * stepX - size / 2,
|
|
1114
|
+
top: y - size / 2,
|
|
1115
|
+
width: size,
|
|
1116
|
+
height: size,
|
|
1117
|
+
borderRadius: size / 2,
|
|
1118
|
+
backgroundColor: resolvedColor
|
|
1119
|
+
},
|
|
1120
|
+
accessibilityElementsHidden: true,
|
|
1121
|
+
testID: `sparkline-dot-${i}`
|
|
1122
|
+
},
|
|
1123
|
+
`dot-${i}`
|
|
1124
|
+
);
|
|
1125
|
+
})
|
|
1126
|
+
]
|
|
1127
|
+
}
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// src/components/custom/Workout/BodyMapDetailPanel.tsx
|
|
1132
|
+
var BRAND_PRIMARY2 = "#FF7900";
|
|
453
1133
|
var VOLUME_GRADIENT = "linear-gradient(90deg, #2196F3 0%, #14B8A6 50%, #D14343 100%)";
|
|
454
1134
|
var SLIDE_OFFSET = 400;
|
|
455
1135
|
var BACKDROP_OPACITY = 0.4;
|
|
@@ -549,8 +1229,8 @@ function BodyMapDetailPanel({
|
|
|
549
1229
|
accessibilityRole: "dialog",
|
|
550
1230
|
accessibilityLabel: dialogLabel,
|
|
551
1231
|
"aria-label": dialogLabel,
|
|
1232
|
+
className: "bg-surface-elevated",
|
|
552
1233
|
style: {
|
|
553
|
-
backgroundColor: SURFACE_ELEVATED,
|
|
554
1234
|
borderTopLeftRadius: 16,
|
|
555
1235
|
borderTopRightRadius: 16,
|
|
556
1236
|
maxHeight: "88%",
|
|
@@ -571,7 +1251,8 @@ function BodyMapDetailPanel({
|
|
|
571
1251
|
children: /* @__PURE__ */ jsx(
|
|
572
1252
|
View,
|
|
573
1253
|
{
|
|
574
|
-
|
|
1254
|
+
className: "bg-border-strong",
|
|
1255
|
+
style: { width: 40, height: 4, borderRadius: 2 },
|
|
575
1256
|
accessibilityElementsHidden: true
|
|
576
1257
|
}
|
|
577
1258
|
)
|
|
@@ -596,11 +1277,11 @@ function BodyMapDetailPanel({
|
|
|
596
1277
|
Text,
|
|
597
1278
|
{
|
|
598
1279
|
accessibilityRole: "header",
|
|
1280
|
+
className: "text-text-primary",
|
|
599
1281
|
style: {
|
|
600
1282
|
fontSize: 16,
|
|
601
1283
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
602
|
-
fontWeight: "700"
|
|
603
|
-
color: TEXT_PRIMARY2
|
|
1284
|
+
fontWeight: "700"
|
|
604
1285
|
},
|
|
605
1286
|
testID: "body-map-detail-panel-title",
|
|
606
1287
|
children: displayName
|
|
@@ -626,7 +1307,7 @@ function BodyMapDetailPanel({
|
|
|
626
1307
|
hitSlop: 8,
|
|
627
1308
|
style: { padding: 4, margin: -4 },
|
|
628
1309
|
testID: "body-map-detail-panel-close",
|
|
629
|
-
children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 22, lineHeight: 22
|
|
1310
|
+
children: /* @__PURE__ */ jsx(Text, { className: "text-text-secondary", style: { fontSize: 22, lineHeight: 22 }, children: "\xD7" })
|
|
630
1311
|
}
|
|
631
1312
|
)
|
|
632
1313
|
]
|
|
@@ -635,7 +1316,8 @@ function BodyMapDetailPanel({
|
|
|
635
1316
|
lastTrained != null && /* @__PURE__ */ jsx(
|
|
636
1317
|
Text,
|
|
637
1318
|
{
|
|
638
|
-
|
|
1319
|
+
className: "text-text-secondary",
|
|
1320
|
+
style: { fontSize: 12, fontFamily: "Inter, sans-serif" },
|
|
639
1321
|
testID: "body-map-detail-panel-last-trained",
|
|
640
1322
|
children: `Last trained ${lastTrained}`
|
|
641
1323
|
}
|
|
@@ -648,8 +1330,8 @@ function BodyMapDetailPanel({
|
|
|
648
1330
|
style: { marginBottom: 6 },
|
|
649
1331
|
accessibilityElementsHidden: true,
|
|
650
1332
|
children: [
|
|
651
|
-
/* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600"
|
|
652
|
-
/* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600"
|
|
1333
|
+
/* @__PURE__ */ jsx(Text, { className: "text-text-tertiary", style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" }, children: `MEV ${landmarks.mev}` }),
|
|
1334
|
+
/* @__PURE__ */ jsx(Text, { className: "text-text-tertiary", style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" }, children: `MRV ${landmarks.mrv}` })
|
|
653
1335
|
]
|
|
654
1336
|
}
|
|
655
1337
|
),
|
|
@@ -675,6 +1357,7 @@ function BodyMapDetailPanel({
|
|
|
675
1357
|
/* @__PURE__ */ jsx(
|
|
676
1358
|
View,
|
|
677
1359
|
{
|
|
1360
|
+
className: "border-text-primary bg-surface-elevated",
|
|
678
1361
|
style: {
|
|
679
1362
|
position: "absolute",
|
|
680
1363
|
left: `${markerLeft}%`,
|
|
@@ -683,8 +1366,6 @@ function BodyMapDetailPanel({
|
|
|
683
1366
|
height: 14,
|
|
684
1367
|
borderRadius: 7,
|
|
685
1368
|
borderWidth: 2,
|
|
686
|
-
borderColor: TEXT_PRIMARY2,
|
|
687
|
-
backgroundColor: SURFACE_ELEVATED,
|
|
688
1369
|
boxShadow: "0 0 4px rgba(0,0,0,0.5)"
|
|
689
1370
|
},
|
|
690
1371
|
accessibilityElementsHidden: true,
|
|
@@ -699,11 +1380,11 @@ function BodyMapDetailPanel({
|
|
|
699
1380
|
/* @__PURE__ */ jsx(
|
|
700
1381
|
Text,
|
|
701
1382
|
{
|
|
1383
|
+
className: "text-text-primary",
|
|
702
1384
|
style: {
|
|
703
1385
|
fontSize: 24,
|
|
704
1386
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
705
|
-
fontWeight: "700"
|
|
706
|
-
color: TEXT_PRIMARY2
|
|
1387
|
+
fontWeight: "700"
|
|
707
1388
|
},
|
|
708
1389
|
testID: "body-map-detail-panel-set-count",
|
|
709
1390
|
children: weeklySets
|
|
@@ -712,7 +1393,8 @@ function BodyMapDetailPanel({
|
|
|
712
1393
|
/* @__PURE__ */ jsx(
|
|
713
1394
|
Text,
|
|
714
1395
|
{
|
|
715
|
-
|
|
1396
|
+
className: "text-text-secondary",
|
|
1397
|
+
style: { fontSize: 12, fontFamily: "Inter, sans-serif" },
|
|
716
1398
|
testID: "body-map-detail-panel-mrv-suffix",
|
|
717
1399
|
children: `/ ${landmarks.mrv} MRV`
|
|
718
1400
|
}
|
|
@@ -722,11 +1404,11 @@ function BodyMapDetailPanel({
|
|
|
722
1404
|
/* @__PURE__ */ jsx(
|
|
723
1405
|
Text,
|
|
724
1406
|
{
|
|
1407
|
+
className: "text-text-tertiary",
|
|
725
1408
|
style: {
|
|
726
1409
|
fontSize: 10,
|
|
727
1410
|
fontFamily: "Inter, sans-serif",
|
|
728
1411
|
fontWeight: "600",
|
|
729
|
-
color: TEXT_TERTIARY,
|
|
730
1412
|
marginBottom: 6
|
|
731
1413
|
},
|
|
732
1414
|
accessibilityElementsHidden: true,
|
|
@@ -739,11 +1421,11 @@ function BodyMapDetailPanel({
|
|
|
739
1421
|
/* @__PURE__ */ jsx(
|
|
740
1422
|
Text,
|
|
741
1423
|
{
|
|
1424
|
+
className: "text-text-tertiary",
|
|
742
1425
|
style: {
|
|
743
1426
|
fontSize: 10,
|
|
744
1427
|
fontFamily: "Inter, sans-serif",
|
|
745
1428
|
fontWeight: "600",
|
|
746
|
-
color: TEXT_TERTIARY,
|
|
747
1429
|
marginBottom: 8
|
|
748
1430
|
},
|
|
749
1431
|
children: "CONTRIBUTING EXERCISES"
|
|
@@ -752,23 +1434,22 @@ function BodyMapDetailPanel({
|
|
|
752
1434
|
contributingExercises.map((exercise, index) => /* @__PURE__ */ jsxs(
|
|
753
1435
|
View,
|
|
754
1436
|
{
|
|
755
|
-
className: "flex-row items-center justify-between",
|
|
1437
|
+
className: "flex-row items-center justify-between bg-surface-raised border-border",
|
|
756
1438
|
style: {
|
|
757
1439
|
gap: 10,
|
|
758
1440
|
paddingVertical: 8,
|
|
759
1441
|
paddingHorizontal: 12,
|
|
760
1442
|
marginBottom: 6,
|
|
761
1443
|
borderRadius: 8,
|
|
762
|
-
|
|
763
|
-
borderWidth: 1,
|
|
764
|
-
borderColor: BORDER_DEFAULT
|
|
1444
|
+
borderWidth: 1
|
|
765
1445
|
},
|
|
766
1446
|
testID: `body-map-detail-panel-contributing-${index}`,
|
|
767
1447
|
children: [
|
|
768
1448
|
/* @__PURE__ */ jsx(
|
|
769
1449
|
Text,
|
|
770
1450
|
{
|
|
771
|
-
|
|
1451
|
+
className: "text-text-primary",
|
|
1452
|
+
style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600" },
|
|
772
1453
|
testID: `body-map-detail-panel-contributing-${index}-name`,
|
|
773
1454
|
children: exercise.name
|
|
774
1455
|
}
|
|
@@ -776,7 +1457,8 @@ function BodyMapDetailPanel({
|
|
|
776
1457
|
/* @__PURE__ */ jsx(
|
|
777
1458
|
Text,
|
|
778
1459
|
{
|
|
779
|
-
|
|
1460
|
+
className: "text-text-secondary",
|
|
1461
|
+
style: { fontSize: 12, fontFamily: "Inter, sans-serif" },
|
|
780
1462
|
testID: `body-map-detail-panel-contributing-${index}-detail`,
|
|
781
1463
|
children: `${exercise.sets} sets \xB7 ${Math.round(exercise.contributionWeight * 100)}%`
|
|
782
1464
|
}
|
|
@@ -790,11 +1472,11 @@ function BodyMapDetailPanel({
|
|
|
790
1472
|
/* @__PURE__ */ jsx(
|
|
791
1473
|
Text,
|
|
792
1474
|
{
|
|
1475
|
+
className: "text-text-tertiary",
|
|
793
1476
|
style: {
|
|
794
1477
|
fontSize: 10,
|
|
795
1478
|
fontFamily: "Inter, sans-serif",
|
|
796
1479
|
fontWeight: "600",
|
|
797
|
-
color: TEXT_TERTIARY,
|
|
798
1480
|
marginBottom: 8
|
|
799
1481
|
},
|
|
800
1482
|
children: "UPCOMING"
|
|
@@ -810,7 +1492,8 @@ function BodyMapDetailPanel({
|
|
|
810
1492
|
/* @__PURE__ */ jsx(
|
|
811
1493
|
Text,
|
|
812
1494
|
{
|
|
813
|
-
|
|
1495
|
+
className: "text-text-primary",
|
|
1496
|
+
style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600" },
|
|
814
1497
|
testID: `body-map-detail-panel-upcoming-${index}-name`,
|
|
815
1498
|
children: exercise.name
|
|
816
1499
|
}
|
|
@@ -818,7 +1501,8 @@ function BodyMapDetailPanel({
|
|
|
818
1501
|
/* @__PURE__ */ jsx(
|
|
819
1502
|
Text,
|
|
820
1503
|
{
|
|
821
|
-
|
|
1504
|
+
className: "text-text-tertiary",
|
|
1505
|
+
style: { fontSize: 12, fontFamily: "Inter, sans-serif" },
|
|
822
1506
|
testID: `body-map-detail-panel-upcoming-${index}-detail`,
|
|
823
1507
|
children: `${exercise.workoutName} \xB7 ${exercise.sets} sets`
|
|
824
1508
|
}
|
|
@@ -844,7 +1528,7 @@ function BodyMapDetailPanel({
|
|
|
844
1528
|
borderColor: "rgba(255,121,0,0.3)"
|
|
845
1529
|
},
|
|
846
1530
|
testID: "body-map-detail-panel-view-exercises",
|
|
847
|
-
children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "700", color:
|
|
1531
|
+
children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "700", color: BRAND_PRIMARY2 }, children: "View exercises" })
|
|
848
1532
|
}
|
|
849
1533
|
)
|
|
850
1534
|
]
|
|
@@ -857,12 +1541,1222 @@ function BodyMapDetailPanel({
|
|
|
857
1541
|
}
|
|
858
1542
|
);
|
|
859
1543
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
1544
|
+
function hexToRgb(hex) {
|
|
1545
|
+
const cleaned = hex.replace("#", "");
|
|
1546
|
+
let r, g, b;
|
|
1547
|
+
if (cleaned.length === 3) {
|
|
1548
|
+
r = parseInt(cleaned[0] + cleaned[0], 16);
|
|
1549
|
+
g = parseInt(cleaned[1] + cleaned[1], 16);
|
|
1550
|
+
b = parseInt(cleaned[2] + cleaned[2], 16);
|
|
1551
|
+
} else if (cleaned.length === 6) {
|
|
1552
|
+
r = parseInt(cleaned.slice(0, 2), 16);
|
|
1553
|
+
g = parseInt(cleaned.slice(2, 4), 16);
|
|
1554
|
+
b = parseInt(cleaned.slice(4, 6), 16);
|
|
1555
|
+
} else {
|
|
1556
|
+
return null;
|
|
1557
|
+
}
|
|
1558
|
+
return { r, g, b };
|
|
1559
|
+
}
|
|
1560
|
+
function rgbToHsv(r, g, b) {
|
|
1561
|
+
const rNorm = r / 255;
|
|
1562
|
+
const gNorm = g / 255;
|
|
1563
|
+
const bNorm = b / 255;
|
|
1564
|
+
const max = Math.max(rNorm, gNorm, bNorm);
|
|
1565
|
+
const min = Math.min(rNorm, gNorm, bNorm);
|
|
1566
|
+
const delta = max - min;
|
|
1567
|
+
const v = max;
|
|
1568
|
+
const s = max === 0 ? 0 : delta / max;
|
|
1569
|
+
let h = 0;
|
|
1570
|
+
if (delta !== 0) {
|
|
1571
|
+
if (max === rNorm) {
|
|
1572
|
+
h = 60 * ((gNorm - bNorm) / delta % 6);
|
|
1573
|
+
} else if (max === gNorm) {
|
|
1574
|
+
h = 60 * ((bNorm - rNorm) / delta + 2);
|
|
1575
|
+
} else {
|
|
1576
|
+
h = 60 * ((rNorm - gNorm) / delta + 4);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
if (h < 0) h += 360;
|
|
1580
|
+
return { h, s, v };
|
|
1581
|
+
}
|
|
1582
|
+
function hsvToRgb(h, s, v) {
|
|
1583
|
+
const c = v * s;
|
|
1584
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
1585
|
+
const m = v - c;
|
|
1586
|
+
let rPrime, gPrime, bPrime;
|
|
1587
|
+
if (h >= 0 && h < 60) {
|
|
1588
|
+
rPrime = c;
|
|
1589
|
+
gPrime = x;
|
|
1590
|
+
bPrime = 0;
|
|
1591
|
+
} else if (h >= 60 && h < 120) {
|
|
1592
|
+
rPrime = x;
|
|
1593
|
+
gPrime = c;
|
|
1594
|
+
bPrime = 0;
|
|
1595
|
+
} else if (h >= 120 && h < 180) {
|
|
1596
|
+
rPrime = 0;
|
|
1597
|
+
gPrime = c;
|
|
1598
|
+
bPrime = x;
|
|
1599
|
+
} else if (h >= 180 && h < 240) {
|
|
1600
|
+
rPrime = 0;
|
|
1601
|
+
gPrime = x;
|
|
1602
|
+
bPrime = c;
|
|
1603
|
+
} else if (h >= 240 && h < 300) {
|
|
1604
|
+
rPrime = x;
|
|
1605
|
+
gPrime = 0;
|
|
1606
|
+
bPrime = c;
|
|
1607
|
+
} else {
|
|
1608
|
+
rPrime = c;
|
|
1609
|
+
gPrime = 0;
|
|
1610
|
+
bPrime = x;
|
|
1611
|
+
}
|
|
1612
|
+
return {
|
|
1613
|
+
r: Math.round((rPrime + m) * 255),
|
|
1614
|
+
g: Math.round((gPrime + m) * 255),
|
|
1615
|
+
b: Math.round((bPrime + m) * 255)
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
function rgbToHex(r, g, b) {
|
|
1619
|
+
const toHex = (n) => {
|
|
1620
|
+
const clamped = Math.max(0, Math.min(255, Math.round(n)));
|
|
1621
|
+
return clamped.toString(16).padStart(2, "0");
|
|
1622
|
+
};
|
|
1623
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
1624
|
+
}
|
|
1625
|
+
function lighten(hex, amount = 0.1) {
|
|
1626
|
+
const rgb = hexToRgb(hex);
|
|
1627
|
+
if (!rgb) return hex;
|
|
1628
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
1629
|
+
const newV = Math.min(1, hsv.v + amount);
|
|
1630
|
+
const newRgb = hsvToRgb(hsv.h, hsv.s, newV);
|
|
1631
|
+
return rgbToHex(newRgb.r, newRgb.g, newRgb.b);
|
|
1632
|
+
}
|
|
1633
|
+
var shadowColors = {
|
|
1634
|
+
// For charcoal surfaces (~#2C2C2C to #3C3C3C)
|
|
1635
|
+
charcoal: {
|
|
1636
|
+
dark: "rgba(0, 0, 0, 0.5)",
|
|
1637
|
+
light: "rgba(255, 255, 255, 0.12)",
|
|
1638
|
+
// brighter for crisp rim light
|
|
1639
|
+
darker: "rgba(0, 0, 0, 0.6)"
|
|
1640
|
+
},
|
|
1641
|
+
// For neutral dark surfaces (~#1F2937)
|
|
1642
|
+
neutralDark: {
|
|
1643
|
+
dark: "rgba(0, 0, 0, 0.4)",
|
|
1644
|
+
light: "rgba(255, 255, 255, 0.08)",
|
|
1645
|
+
darker: "rgba(0, 0, 0, 0.5)"
|
|
1646
|
+
},
|
|
1647
|
+
// For light surfaces (white/light gray backgrounds)
|
|
1648
|
+
neutralLight: {
|
|
1649
|
+
dark: "rgba(0, 0, 0, 0.15)",
|
|
1650
|
+
// Visible dark shadow for depth on light backgrounds
|
|
1651
|
+
light: "rgba(255, 255, 255, 1)",
|
|
1652
|
+
// Bright highlight for raised effect (visible on light gray)
|
|
1653
|
+
darker: "rgba(0, 0, 0, 0.2)"
|
|
1654
|
+
// Deeper shadow for pressed states
|
|
1655
|
+
}
|
|
1656
|
+
};
|
|
1657
|
+
var intensityConfig = {
|
|
1658
|
+
subtle: { offset: 1, blur: 2 },
|
|
1659
|
+
// very light, barely visible
|
|
1660
|
+
medium: { offset: 2, blur: 4 },
|
|
1661
|
+
// noticeable but restrained
|
|
1662
|
+
strong: { offset: 2, blur: 5 }
|
|
1663
|
+
// slightly deeper blur, same offset as medium
|
|
1664
|
+
};
|
|
1665
|
+
function createRaisedShadow(surface = "charcoal", intensity = "medium") {
|
|
1666
|
+
const colors = shadowColors[surface];
|
|
1667
|
+
const { offset, blur } = intensityConfig[intensity];
|
|
1668
|
+
const rimBlur = 1;
|
|
1669
|
+
return Platform.select({
|
|
1670
|
+
web: {
|
|
1671
|
+
boxShadow: `${offset}px ${offset}px ${blur}px ${colors.dark}, -${offset}px -${offset}px ${rimBlur}px ${colors.light}`
|
|
1672
|
+
},
|
|
1673
|
+
default: {
|
|
1674
|
+
// React Native shadow approximation (limited compared to web)
|
|
1675
|
+
shadowColor: "#000",
|
|
1676
|
+
shadowOffset: { width: offset, height: offset },
|
|
1677
|
+
shadowOpacity: 0.3,
|
|
1678
|
+
shadowRadius: blur / 2,
|
|
1679
|
+
elevation: offset
|
|
1680
|
+
}
|
|
1681
|
+
});
|
|
1682
|
+
}
|
|
1683
|
+
function createPressedShadow(surface = "charcoal", intensity = "medium") {
|
|
1684
|
+
const colors = shadowColors[surface];
|
|
1685
|
+
const { offset, blur } = intensityConfig[intensity];
|
|
1686
|
+
const rimOffset = 1;
|
|
1687
|
+
const rimBlur = 1;
|
|
1688
|
+
return Platform.select({
|
|
1689
|
+
web: {
|
|
1690
|
+
boxShadow: `inset ${offset}px ${offset}px ${blur}px ${colors.darker}, inset -${rimOffset}px -${rimOffset}px ${rimBlur}px ${colors.light}`
|
|
1691
|
+
},
|
|
1692
|
+
default: {
|
|
1693
|
+
// React Native doesn't support inset shadows, approximate with darker bg
|
|
1694
|
+
shadowOpacity: 0,
|
|
1695
|
+
elevation: 0
|
|
1696
|
+
}
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1699
|
+
function createFlatShadow() {
|
|
1700
|
+
return Platform.select({
|
|
1701
|
+
web: {
|
|
1702
|
+
boxShadow: "none"
|
|
1703
|
+
},
|
|
1704
|
+
default: {
|
|
1705
|
+
shadowOpacity: 0,
|
|
1706
|
+
elevation: 0
|
|
1707
|
+
}
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
function createRaisedHoverShadow(surface = "charcoal", intensity = "medium") {
|
|
1711
|
+
const colors = shadowColors[surface];
|
|
1712
|
+
const { offset, blur } = intensityConfig[intensity];
|
|
1713
|
+
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
1714
|
+
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
1715
|
+
const rimBlur = 1;
|
|
1716
|
+
return Platform.select({
|
|
1717
|
+
web: {
|
|
1718
|
+
// Keep same offsets as normal state for rim to prevent "shrinking" effect
|
|
1719
|
+
boxShadow: `${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${colors.dark}, -${offset}px -${offset}px ${rimBlur}px ${colors.light}`
|
|
1720
|
+
},
|
|
1721
|
+
default: {
|
|
1722
|
+
shadowColor: "#000",
|
|
1723
|
+
shadowOffset: { width: hoverOffset, height: hoverOffset },
|
|
1724
|
+
shadowOpacity: 0.2,
|
|
1725
|
+
shadowRadius: hoverBlur / 2,
|
|
1726
|
+
elevation: hoverOffset
|
|
1727
|
+
}
|
|
1728
|
+
});
|
|
1729
|
+
}
|
|
1730
|
+
function createPressedHoverShadow(surface = "charcoal", intensity = "medium") {
|
|
1731
|
+
const colors = shadowColors[surface];
|
|
1732
|
+
const { offset, blur } = intensityConfig[intensity];
|
|
1733
|
+
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
1734
|
+
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
1735
|
+
const rimBlur = 1;
|
|
1736
|
+
return Platform.select({
|
|
1737
|
+
web: {
|
|
1738
|
+
// Keep rim offset at 1px (same as pressed normal) to prevent "shrinking" effect
|
|
1739
|
+
boxShadow: `inset ${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${colors.darker}, inset -1px -1px ${rimBlur}px ${colors.light}`
|
|
1740
|
+
},
|
|
1741
|
+
default: {
|
|
1742
|
+
shadowOpacity: 0,
|
|
1743
|
+
elevation: 0
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
({
|
|
1748
|
+
// Charcoal surface shadows (for dark toolbars, cards)
|
|
1749
|
+
charcoal: {
|
|
1750
|
+
raised: {
|
|
1751
|
+
subtle: createRaisedShadow("charcoal", "subtle"),
|
|
1752
|
+
medium: createRaisedShadow("charcoal", "medium"),
|
|
1753
|
+
strong: createRaisedShadow("charcoal", "strong")
|
|
1754
|
+
},
|
|
1755
|
+
raisedHover: {
|
|
1756
|
+
subtle: createRaisedHoverShadow("charcoal", "subtle"),
|
|
1757
|
+
medium: createRaisedHoverShadow("charcoal", "medium"),
|
|
1758
|
+
strong: createRaisedHoverShadow("charcoal", "strong")
|
|
1759
|
+
},
|
|
1760
|
+
pressed: {
|
|
1761
|
+
subtle: createPressedShadow("charcoal", "subtle"),
|
|
1762
|
+
medium: createPressedShadow("charcoal", "medium"),
|
|
1763
|
+
strong: createPressedShadow("charcoal", "strong")
|
|
1764
|
+
},
|
|
1765
|
+
pressedHover: {
|
|
1766
|
+
subtle: createPressedHoverShadow("charcoal", "subtle"),
|
|
1767
|
+
medium: createPressedHoverShadow("charcoal", "medium"),
|
|
1768
|
+
strong: createPressedHoverShadow("charcoal", "strong")
|
|
1769
|
+
},
|
|
1770
|
+
flat: createFlatShadow()
|
|
1771
|
+
},
|
|
1772
|
+
// Neutral dark surface shadows
|
|
1773
|
+
neutralDark: {
|
|
1774
|
+
raised: {
|
|
1775
|
+
subtle: createRaisedShadow("neutralDark", "subtle"),
|
|
1776
|
+
medium: createRaisedShadow("neutralDark", "medium"),
|
|
1777
|
+
strong: createRaisedShadow("neutralDark", "strong")
|
|
1778
|
+
},
|
|
1779
|
+
raisedHover: {
|
|
1780
|
+
subtle: createRaisedHoverShadow("neutralDark", "subtle"),
|
|
1781
|
+
medium: createRaisedHoverShadow("neutralDark", "medium"),
|
|
1782
|
+
strong: createRaisedHoverShadow("neutralDark", "strong")
|
|
1783
|
+
},
|
|
1784
|
+
pressed: {
|
|
1785
|
+
subtle: createPressedShadow("neutralDark", "subtle"),
|
|
1786
|
+
medium: createPressedShadow("neutralDark", "medium"),
|
|
1787
|
+
strong: createPressedShadow("neutralDark", "strong")
|
|
1788
|
+
},
|
|
1789
|
+
pressedHover: {
|
|
1790
|
+
subtle: createPressedHoverShadow("neutralDark", "subtle"),
|
|
1791
|
+
medium: createPressedHoverShadow("neutralDark", "medium"),
|
|
1792
|
+
strong: createPressedHoverShadow("neutralDark", "strong")
|
|
1793
|
+
},
|
|
1794
|
+
flat: createFlatShadow()
|
|
1795
|
+
},
|
|
1796
|
+
// Neutral light surface shadows
|
|
1797
|
+
neutralLight: {
|
|
1798
|
+
raised: {
|
|
1799
|
+
subtle: createRaisedShadow("neutralLight", "subtle"),
|
|
1800
|
+
medium: createRaisedShadow("neutralLight", "medium"),
|
|
1801
|
+
strong: createRaisedShadow("neutralLight", "strong")
|
|
1802
|
+
},
|
|
1803
|
+
raisedHover: {
|
|
1804
|
+
subtle: createRaisedHoverShadow("neutralLight", "subtle"),
|
|
1805
|
+
medium: createRaisedHoverShadow("neutralLight", "medium"),
|
|
1806
|
+
strong: createRaisedHoverShadow("neutralLight", "strong")
|
|
1807
|
+
},
|
|
1808
|
+
pressed: {
|
|
1809
|
+
subtle: createPressedShadow("neutralLight", "subtle"),
|
|
1810
|
+
medium: createPressedShadow("neutralLight", "medium"),
|
|
1811
|
+
strong: createPressedShadow("neutralLight", "strong")
|
|
1812
|
+
},
|
|
1813
|
+
pressedHover: {
|
|
1814
|
+
subtle: createPressedHoverShadow("neutralLight", "subtle"),
|
|
1815
|
+
medium: createPressedHoverShadow("neutralLight", "medium"),
|
|
1816
|
+
strong: createPressedHoverShadow("neutralLight", "strong")
|
|
1817
|
+
},
|
|
1818
|
+
flat: createFlatShadow()
|
|
1819
|
+
}
|
|
1820
|
+
});
|
|
1821
|
+
var elevationSystem = {
|
|
1822
|
+
// Deep inset (recessed input fields, deeply pressed buttons)
|
|
1823
|
+
[-2]: {
|
|
1824
|
+
name: "deep-inset",
|
|
1825
|
+
colorAdjustment: 0,
|
|
1826
|
+
shadowIntensity: "strong",
|
|
1827
|
+
shadowStyle: "pressed",
|
|
1828
|
+
description: "Deeply recessed elements (e.g., input fields, deeply pressed buttons)"
|
|
1829
|
+
},
|
|
1830
|
+
// Shallow inset (pressed buttons, sunken panels)
|
|
1831
|
+
[-1]: {
|
|
1832
|
+
name: "inset",
|
|
1833
|
+
colorAdjustment: 0,
|
|
1834
|
+
shadowIntensity: "medium",
|
|
1835
|
+
shadowStyle: "pressed",
|
|
1836
|
+
description: "Shallow inset elements (e.g., pressed buttons, sunken panels within cards)"
|
|
1837
|
+
},
|
|
1838
|
+
// Base level (page background, default surface)
|
|
1839
|
+
[0]: {
|
|
1840
|
+
name: "base",
|
|
1841
|
+
colorAdjustment: 0,
|
|
1842
|
+
shadowIntensity: "subtle",
|
|
1843
|
+
shadowStyle: "raised",
|
|
1844
|
+
description: "Base surface level (page background, default containers)"
|
|
1845
|
+
},
|
|
1846
|
+
// Level 1: Subtle elevation (outline cards, subtle containers)
|
|
1847
|
+
[1]: {
|
|
1848
|
+
name: "subtle",
|
|
1849
|
+
colorAdjustment: 0.01,
|
|
1850
|
+
shadowIntensity: "subtle",
|
|
1851
|
+
shadowStyle: "raised",
|
|
1852
|
+
description: "Subtle elevation (outline cards, subtle containers)"
|
|
1853
|
+
},
|
|
1854
|
+
// Level 2: Standard elevation (default cards, buttons)
|
|
1855
|
+
[2]: {
|
|
1856
|
+
name: "standard",
|
|
1857
|
+
colorAdjustment: 0.02,
|
|
1858
|
+
shadowIntensity: "medium",
|
|
1859
|
+
shadowStyle: "raised",
|
|
1860
|
+
description: "Standard elevation (default cards, raised buttons)"
|
|
1861
|
+
},
|
|
1862
|
+
// Level 3: Prominent elevation (important cards, modals)
|
|
1863
|
+
[3]: {
|
|
1864
|
+
name: "prominent",
|
|
1865
|
+
colorAdjustment: 0.04,
|
|
1866
|
+
shadowIntensity: "strong",
|
|
1867
|
+
shadowStyle: "raised",
|
|
1868
|
+
description: "Prominent elevation (important cards, modals, dropdowns)"
|
|
1869
|
+
},
|
|
1870
|
+
// Level 4: High elevation (overlays, popovers)
|
|
1871
|
+
[4]: {
|
|
1872
|
+
name: "high",
|
|
1873
|
+
colorAdjustment: 0.06,
|
|
1874
|
+
shadowIntensity: "strong",
|
|
1875
|
+
shadowStyle: "raised",
|
|
1876
|
+
description: "High elevation (overlays, popovers, tooltips)"
|
|
1877
|
+
},
|
|
1878
|
+
// Level 5: Floating (toasts, floating action buttons)
|
|
1879
|
+
[5]: {
|
|
1880
|
+
name: "floating",
|
|
1881
|
+
colorAdjustment: 0.08,
|
|
1882
|
+
shadowIntensity: "strong",
|
|
1883
|
+
shadowStyle: "raised",
|
|
1884
|
+
description: "Floating elevation (toasts, floating action buttons, highest z-index)"
|
|
1885
|
+
}
|
|
1886
|
+
};
|
|
1887
|
+
function calculateRimLightColor(baseColor, level) {
|
|
1888
|
+
const rgb = hexToRgb(baseColor);
|
|
1889
|
+
if (!rgb) {
|
|
1890
|
+
return "rgba(255, 255, 255, 0.5)";
|
|
1891
|
+
}
|
|
1892
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
1893
|
+
const isLight = hsv.v > 0.6;
|
|
1894
|
+
const isSaturated = hsv.s > 0.3;
|
|
1895
|
+
const absLevel = Math.abs(level);
|
|
1896
|
+
const opacityBoost = Math.max(0, (absLevel - 1) * 0.05);
|
|
1897
|
+
if (isSaturated) {
|
|
1898
|
+
const rimLightValue = 0.95;
|
|
1899
|
+
const rimLightRgb = hsvToRgb(hsv.h, hsv.s * 0.3, rimLightValue);
|
|
1900
|
+
const baseOpacity = isLight ? 0.9 : 0.5;
|
|
1901
|
+
const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
|
|
1902
|
+
return `rgba(${rimLightRgb.r}, ${rimLightRgb.g}, ${rimLightRgb.b}, ${finalOpacity.toFixed(2)})`;
|
|
1903
|
+
} else {
|
|
1904
|
+
const baseOpacity = isLight ? 0.9 : 0.12;
|
|
1905
|
+
const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
|
|
1906
|
+
return `rgba(255, 255, 255, ${finalOpacity.toFixed(2)})`;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
function calculateDarkShadowColors(surfaceColor) {
|
|
1910
|
+
const rgb = hexToRgb(surfaceColor);
|
|
1911
|
+
if (!rgb) {
|
|
1912
|
+
return {
|
|
1913
|
+
dark: "rgba(0, 0, 0, 0.3)",
|
|
1914
|
+
darker: "rgba(0, 0, 0, 0.4)"
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1917
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
1918
|
+
const isLight = hsv.v > 0.6;
|
|
1919
|
+
const isSaturated = hsv.s > 0.3;
|
|
1920
|
+
if (isSaturated) {
|
|
1921
|
+
const darkShadowValue = 0.15;
|
|
1922
|
+
const darkShadowRgb = hsvToRgb(hsv.h, hsv.s, darkShadowValue);
|
|
1923
|
+
if (isLight) {
|
|
1924
|
+
return {
|
|
1925
|
+
dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.3)`,
|
|
1926
|
+
darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.4)`
|
|
1927
|
+
};
|
|
1928
|
+
} else {
|
|
1929
|
+
return {
|
|
1930
|
+
dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.5)`,
|
|
1931
|
+
darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.6)`
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1934
|
+
} else {
|
|
1935
|
+
if (isLight) {
|
|
1936
|
+
return {
|
|
1937
|
+
dark: "rgba(0, 0, 0, 0.2)",
|
|
1938
|
+
darker: "rgba(0, 0, 0, 0.3)"
|
|
1939
|
+
};
|
|
1940
|
+
} else {
|
|
1941
|
+
return {
|
|
1942
|
+
dark: "rgba(0, 0, 0, 0.5)",
|
|
1943
|
+
darker: "rgba(0, 0, 0, 0.6)"
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
function getRimLightConfig() {
|
|
1949
|
+
return {
|
|
1950
|
+
offset: 1,
|
|
1951
|
+
// Fixed 1px for crisp rim
|
|
1952
|
+
blur: 1
|
|
1953
|
+
// Tight blur for crisp edge
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
var elevationSurfaceCache = /* @__PURE__ */ new Map();
|
|
1957
|
+
var MAX_CACHE_SIZE = 100;
|
|
1958
|
+
function getCacheKey(baseColor, level, theme) {
|
|
1959
|
+
return `${baseColor}-${level}-${theme}`;
|
|
1960
|
+
}
|
|
1961
|
+
function calculateElevationSurface(baseColor, level, theme) {
|
|
1962
|
+
const config = elevationSystem[level];
|
|
1963
|
+
if (config.colorAdjustment === 0) {
|
|
1964
|
+
return baseColor;
|
|
1965
|
+
}
|
|
1966
|
+
if (level < 0) {
|
|
1967
|
+
return baseColor;
|
|
1968
|
+
}
|
|
1969
|
+
return lighten(baseColor, config.colorAdjustment);
|
|
1970
|
+
}
|
|
1971
|
+
function getElevationSurface(baseColor, level, theme) {
|
|
1972
|
+
const cacheKey = getCacheKey(baseColor, level, theme);
|
|
1973
|
+
if (elevationSurfaceCache.has(cacheKey)) {
|
|
1974
|
+
return elevationSurfaceCache.get(cacheKey);
|
|
1975
|
+
}
|
|
1976
|
+
const result = calculateElevationSurface(baseColor, level);
|
|
1977
|
+
if (elevationSurfaceCache.size >= MAX_CACHE_SIZE) {
|
|
1978
|
+
const firstKey = elevationSurfaceCache.keys().next().value;
|
|
1979
|
+
elevationSurfaceCache.delete(firstKey);
|
|
1980
|
+
}
|
|
1981
|
+
elevationSurfaceCache.set(cacheKey, result);
|
|
1982
|
+
return result;
|
|
1983
|
+
}
|
|
1984
|
+
var elevationShadowCache = /* @__PURE__ */ new Map();
|
|
1985
|
+
var MAX_SHADOW_CACHE_SIZE = 50;
|
|
1986
|
+
function getShadowCacheKey(baseColor, level, theme, isHovered) {
|
|
1987
|
+
return `${baseColor}-${level}-${theme}-${isHovered}`;
|
|
1988
|
+
}
|
|
1989
|
+
function calculateElevationShadow(baseColor, level, theme, isHovered = false) {
|
|
1990
|
+
const config = elevationSystem[level];
|
|
1991
|
+
if (level === 0) {
|
|
1992
|
+
return {};
|
|
1993
|
+
}
|
|
1994
|
+
const elevatedSurfaceColor = calculateElevationSurface(baseColor, level);
|
|
1995
|
+
const rimLightColor = calculateRimLightColor(baseColor, level);
|
|
1996
|
+
const darkShadowColors = calculateDarkShadowColors(elevatedSurfaceColor);
|
|
1997
|
+
const intensityConfig2 = {
|
|
1998
|
+
subtle: { offset: 1, blur: 2 },
|
|
1999
|
+
medium: { offset: 2, blur: 4 },
|
|
2000
|
+
strong: { offset: 2, blur: 5 }
|
|
2001
|
+
};
|
|
2002
|
+
const { offset, blur } = intensityConfig2[config.shadowIntensity];
|
|
2003
|
+
const rimConfig = getRimLightConfig();
|
|
2004
|
+
if (config.shadowStyle === "pressed") {
|
|
2005
|
+
if (isHovered) {
|
|
2006
|
+
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
2007
|
+
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
2008
|
+
return Platform.select({
|
|
2009
|
+
web: {
|
|
2010
|
+
boxShadow: `inset ${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
2011
|
+
},
|
|
2012
|
+
default: {
|
|
2013
|
+
shadowOpacity: 0,
|
|
2014
|
+
elevation: 0
|
|
2015
|
+
}
|
|
2016
|
+
});
|
|
2017
|
+
}
|
|
2018
|
+
return Platform.select({
|
|
2019
|
+
web: {
|
|
2020
|
+
boxShadow: `inset ${offset}px ${offset}px ${blur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
2021
|
+
},
|
|
2022
|
+
default: {
|
|
2023
|
+
shadowOpacity: 0,
|
|
2024
|
+
elevation: 0
|
|
2025
|
+
}
|
|
2026
|
+
});
|
|
2027
|
+
} else {
|
|
2028
|
+
if (isHovered) {
|
|
2029
|
+
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
2030
|
+
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
2031
|
+
return Platform.select({
|
|
2032
|
+
web: {
|
|
2033
|
+
boxShadow: `${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
2034
|
+
},
|
|
2035
|
+
default: {
|
|
2036
|
+
shadowColor: "#000",
|
|
2037
|
+
shadowOffset: { width: hoverOffset, height: hoverOffset },
|
|
2038
|
+
shadowOpacity: 0.2,
|
|
2039
|
+
shadowRadius: hoverBlur / 2,
|
|
2040
|
+
elevation: hoverOffset
|
|
2041
|
+
}
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
return Platform.select({
|
|
2045
|
+
web: {
|
|
2046
|
+
boxShadow: `${offset}px ${offset}px ${blur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
2047
|
+
},
|
|
2048
|
+
default: {
|
|
2049
|
+
shadowColor: "#000",
|
|
2050
|
+
shadowOffset: { width: offset, height: offset },
|
|
2051
|
+
shadowOpacity: 0.3,
|
|
2052
|
+
shadowRadius: blur / 2,
|
|
2053
|
+
elevation: offset
|
|
2054
|
+
}
|
|
2055
|
+
});
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
function getElevationShadow(baseColor, level, theme, isHovered = false) {
|
|
2059
|
+
const cacheKey = getShadowCacheKey(baseColor, level, theme, isHovered);
|
|
2060
|
+
if (elevationShadowCache.has(cacheKey)) {
|
|
2061
|
+
return elevationShadowCache.get(cacheKey);
|
|
2062
|
+
}
|
|
2063
|
+
const result = calculateElevationShadow(baseColor, level, theme, isHovered);
|
|
2064
|
+
if (elevationShadowCache.size >= MAX_SHADOW_CACHE_SIZE) {
|
|
2065
|
+
const firstKey = elevationShadowCache.keys().next().value;
|
|
2066
|
+
elevationShadowCache.delete(firstKey);
|
|
2067
|
+
}
|
|
2068
|
+
elevationShadowCache.set(cacheKey, result);
|
|
2069
|
+
return result;
|
|
2070
|
+
}
|
|
2071
|
+
function getBaseSurfaceColor(theme) {
|
|
2072
|
+
return theme === "light" ? semanticColorsLight["surface-raised"] : semanticColorsDark["surface-elevated"];
|
|
2073
|
+
}
|
|
2074
|
+
var componentElevationRanges = {
|
|
2075
|
+
button: {
|
|
2076
|
+
allowed: [2],
|
|
2077
|
+
default: 2,
|
|
2078
|
+
hover: 3
|
|
2079
|
+
},
|
|
2080
|
+
card: {
|
|
2081
|
+
allowed: [1, 2, 3],
|
|
2082
|
+
default: 2,
|
|
2083
|
+
hover: 3
|
|
2084
|
+
},
|
|
2085
|
+
input: {
|
|
2086
|
+
allowed: [-2, -1, 0],
|
|
2087
|
+
default: -1
|
|
2088
|
+
},
|
|
2089
|
+
overlay: {
|
|
2090
|
+
allowed: [4, 5],
|
|
2091
|
+
default: 4
|
|
2092
|
+
}
|
|
2093
|
+
};
|
|
2094
|
+
function getValidatedElevation(component, requested) {
|
|
2095
|
+
const range = componentElevationRanges[component];
|
|
2096
|
+
if (range.allowed.includes(requested)) {
|
|
2097
|
+
return requested;
|
|
2098
|
+
}
|
|
2099
|
+
const sorted = [...range.allowed].sort((a, b) => a - b);
|
|
2100
|
+
if (requested < sorted[0]) return sorted[0];
|
|
2101
|
+
if (requested > sorted[sorted.length - 1]) return sorted[sorted.length - 1];
|
|
2102
|
+
return sorted.reduce(
|
|
2103
|
+
(prev, curr) => Math.abs(curr - requested) < Math.abs(prev - requested) ? curr : prev
|
|
2104
|
+
);
|
|
2105
|
+
}
|
|
2106
|
+
function getTheme() {
|
|
2107
|
+
if (typeof document === "undefined") return "dark";
|
|
2108
|
+
return document.documentElement.classList.contains("light") ? "light" : "dark";
|
|
2109
|
+
}
|
|
2110
|
+
var listeners = [];
|
|
2111
|
+
function subscribe(listener) {
|
|
2112
|
+
listeners = [...listeners, listener];
|
|
2113
|
+
if (typeof document !== "undefined" && listeners.length === 1) {
|
|
2114
|
+
const observer = new MutationObserver((mutations) => {
|
|
2115
|
+
for (const mutation of mutations) {
|
|
2116
|
+
if (mutation.type === "attributes" && mutation.attributeName === "class") {
|
|
2117
|
+
listeners.forEach((l) => l());
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
});
|
|
2121
|
+
observer.observe(document.documentElement, {
|
|
2122
|
+
attributes: true,
|
|
2123
|
+
attributeFilter: ["class"]
|
|
2124
|
+
});
|
|
2125
|
+
subscribe._observer = observer;
|
|
2126
|
+
}
|
|
2127
|
+
return () => {
|
|
2128
|
+
listeners = listeners.filter((l) => l !== listener);
|
|
2129
|
+
if (listeners.length === 0 && subscribe._observer) {
|
|
2130
|
+
subscribe._observer.disconnect();
|
|
2131
|
+
subscribe._observer = null;
|
|
2132
|
+
}
|
|
2133
|
+
};
|
|
2134
|
+
}
|
|
2135
|
+
function getSnapshot() {
|
|
2136
|
+
return getTheme();
|
|
2137
|
+
}
|
|
2138
|
+
function getServerSnapshot() {
|
|
2139
|
+
return "dark";
|
|
2140
|
+
}
|
|
2141
|
+
function useTheme() {
|
|
2142
|
+
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
// src/components/ui/card/Card.tsx
|
|
2146
|
+
var variantStyles = {
|
|
2147
|
+
elevated: "",
|
|
2148
|
+
// Will be set dynamically via elevation system
|
|
2149
|
+
outline: "border-2 border-border-strong",
|
|
2150
|
+
// Thicker border with stronger contrast
|
|
2151
|
+
filled: "",
|
|
2152
|
+
// Will be set dynamically via elevation system
|
|
2153
|
+
accent: "border border-border",
|
|
2154
|
+
subtle: "border border-border-subtle"
|
|
2155
|
+
};
|
|
2156
|
+
function Card({
|
|
2157
|
+
variant = "elevated",
|
|
2158
|
+
elevation = 2,
|
|
2159
|
+
isInteractive = false,
|
|
2160
|
+
isLoading = false,
|
|
2161
|
+
onPress,
|
|
2162
|
+
borderColor,
|
|
2163
|
+
bgColor,
|
|
2164
|
+
accentColor,
|
|
2165
|
+
accentWidth,
|
|
2166
|
+
className,
|
|
2167
|
+
children,
|
|
2168
|
+
style,
|
|
2169
|
+
skeletonHasHeader = true,
|
|
2170
|
+
skeletonHasFooter = false,
|
|
2171
|
+
skeletonContentLines = 3,
|
|
2172
|
+
...props
|
|
2173
|
+
}) {
|
|
2174
|
+
const isClickable = isInteractive || !!onPress;
|
|
2175
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
2176
|
+
const theme = useTheme();
|
|
2177
|
+
const elevationLevel = useMemo(() => {
|
|
2178
|
+
const validated = getValidatedElevation("card", elevation);
|
|
2179
|
+
if (variant === "outline" || variant === "accent" || variant === "subtle") {
|
|
2180
|
+
return 1;
|
|
2181
|
+
}
|
|
2182
|
+
return validated;
|
|
2183
|
+
}, [variant, elevation]);
|
|
2184
|
+
const baseColor = useMemo(() => getBaseSurfaceColor(theme), [theme]);
|
|
2185
|
+
const surfaceColor = useMemo(() => {
|
|
2186
|
+
if ((variant === "outline" || variant === "accent") && theme === "light") {
|
|
2187
|
+
return "#FAFAFA";
|
|
2188
|
+
}
|
|
2189
|
+
if (variant === "subtle") {
|
|
2190
|
+
return getElevationSurface(baseColor, 0, theme);
|
|
2191
|
+
}
|
|
2192
|
+
return getElevationSurface(baseColor, elevationLevel, theme);
|
|
2193
|
+
}, [baseColor, elevationLevel, theme, variant]);
|
|
2194
|
+
const shadowStyle = useMemo(() => {
|
|
2195
|
+
const shouldHover = isHovered && isClickable;
|
|
2196
|
+
return getElevationShadow(baseColor, elevationLevel, theme, shouldHover);
|
|
2197
|
+
}, [baseColor, elevationLevel, theme, isHovered, isClickable]);
|
|
2198
|
+
const cardContent = isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2199
|
+
skeletonHasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
2200
|
+
/* @__PURE__ */ jsx(View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
|
|
2201
|
+
/* @__PURE__ */ jsx(View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
|
|
2202
|
+
] }),
|
|
2203
|
+
/* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: skeletonContentLines }).map((_, i) => /* @__PURE__ */ jsx(
|
|
2204
|
+
View,
|
|
2205
|
+
{
|
|
2206
|
+
className: cn(
|
|
2207
|
+
"h-4 bg-interactive-disabled rounded",
|
|
2208
|
+
i < skeletonContentLines - 1 ? "mb-2 w-full" : "w-4/5"
|
|
2209
|
+
)
|
|
2210
|
+
},
|
|
2211
|
+
i
|
|
2212
|
+
)) }),
|
|
2213
|
+
skeletonHasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
|
|
2214
|
+
] }) : children;
|
|
2215
|
+
const baseClassName = cn(
|
|
2216
|
+
"rounded-lg overflow-hidden relative",
|
|
2217
|
+
// Apply variant styles, but only use default border color if no custom borderColor
|
|
2218
|
+
variant === "outline" ? borderColor ? "border-2" : variantStyles[variant] : variantStyles[variant],
|
|
2219
|
+
// Remove Tailwind shadow classes - we're using elevation shadows via style prop
|
|
2220
|
+
isClickable && "web:cursor-pointer web:transition-all web:duration-150",
|
|
2221
|
+
isClickable && "web:hover:-translate-y-0.5 active:scale-[0.99]",
|
|
2222
|
+
isLoading && "pointer-events-none animate-pulse",
|
|
2223
|
+
className
|
|
2224
|
+
);
|
|
2225
|
+
const accentStyle = useMemo(() => variant === "accent" ? {
|
|
2226
|
+
borderLeftWidth: accentWidth ?? 3,
|
|
2227
|
+
borderLeftColor: accentColor ?? "var(--color-brand-primary)"
|
|
2228
|
+
} : {}, [variant, accentWidth, accentColor]);
|
|
2229
|
+
const mergedStyle = useMemo(() => {
|
|
2230
|
+
const elevationStyle = {
|
|
2231
|
+
backgroundColor: bgColor || surfaceColor,
|
|
2232
|
+
borderRadius: 8,
|
|
2233
|
+
overflow: "hidden",
|
|
2234
|
+
...shadowStyle,
|
|
2235
|
+
...accentStyle
|
|
2236
|
+
};
|
|
2237
|
+
if (borderColor) {
|
|
2238
|
+
elevationStyle.borderColor = borderColor;
|
|
2239
|
+
}
|
|
2240
|
+
if (!style) return elevationStyle;
|
|
2241
|
+
return [elevationStyle, style];
|
|
2242
|
+
}, [style, surfaceColor, shadowStyle, borderColor, bgColor, accentStyle]);
|
|
2243
|
+
if (isClickable) {
|
|
2244
|
+
return /* @__PURE__ */ jsx(
|
|
2245
|
+
Pressable,
|
|
2246
|
+
{
|
|
2247
|
+
onPress,
|
|
2248
|
+
onHoverIn: () => setIsHovered(true),
|
|
2249
|
+
onHoverOut: () => setIsHovered(false),
|
|
2250
|
+
accessibilityRole: "button",
|
|
2251
|
+
className: baseClassName,
|
|
2252
|
+
style: mergedStyle,
|
|
2253
|
+
...props,
|
|
2254
|
+
children: cardContent
|
|
2255
|
+
}
|
|
2256
|
+
);
|
|
2257
|
+
}
|
|
2258
|
+
return /* @__PURE__ */ jsx(View, { className: baseClassName, style: mergedStyle, ...props, children: cardContent });
|
|
2259
|
+
}
|
|
2260
|
+
function CardHeader({ children, className }) {
|
|
2261
|
+
return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-6", className), children });
|
|
2262
|
+
}
|
|
2263
|
+
function CardContent({ children, className }) {
|
|
2264
|
+
return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4", className), children });
|
|
2265
|
+
}
|
|
2266
|
+
function CardFooter({ children, className }) {
|
|
2267
|
+
return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4 flex-row items-center gap-2", className), children });
|
|
2268
|
+
}
|
|
2269
|
+
var solidVariantColors = {
|
|
2270
|
+
success: "#14B8A6",
|
|
2271
|
+
warning: "#FFB020",
|
|
2272
|
+
error: "#D14343",
|
|
2273
|
+
neutral: "#6B7280"
|
|
2274
|
+
};
|
|
2275
|
+
var ringVariantStyles = {
|
|
2276
|
+
"on-track": {
|
|
2277
|
+
backgroundColor: "rgba(20,184,166,0.15)",
|
|
2278
|
+
borderWidth: 1,
|
|
2279
|
+
borderColor: "rgba(20,184,166,0.3)"
|
|
2280
|
+
},
|
|
2281
|
+
deviation: {
|
|
2282
|
+
backgroundColor: "rgba(245,158,11,0.15)",
|
|
2283
|
+
borderWidth: 1,
|
|
2284
|
+
borderColor: "rgba(245,158,11,0.25)"
|
|
2285
|
+
},
|
|
2286
|
+
future: {
|
|
2287
|
+
backgroundColor: "rgba(107,114,128,0.1)",
|
|
2288
|
+
borderWidth: 1,
|
|
2289
|
+
borderStyle: "dashed",
|
|
2290
|
+
borderColor: "rgba(107,114,128,0.2)"
|
|
2291
|
+
}
|
|
2292
|
+
};
|
|
2293
|
+
var glowStyles = {
|
|
2294
|
+
success: { boxShadow: "0 0 4px rgba(20,184,166,0.4)" },
|
|
2295
|
+
warning: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
|
|
2296
|
+
error: { boxShadow: "0 0 4px rgba(239,68,68,0.4)" },
|
|
2297
|
+
neutral: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" },
|
|
2298
|
+
"on-track": { boxShadow: "0 0 4px rgba(20,184,166,0.4)" },
|
|
2299
|
+
deviation: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
|
|
2300
|
+
future: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" }
|
|
2301
|
+
};
|
|
2302
|
+
var iconChars = {
|
|
2303
|
+
check: "\u2713",
|
|
2304
|
+
exclamation: "!",
|
|
2305
|
+
dash: "\u2014"
|
|
2306
|
+
};
|
|
2307
|
+
var iconColors = {
|
|
2308
|
+
success: "#0A5C52",
|
|
2309
|
+
warning: "#6B4000",
|
|
2310
|
+
error: "#5C1A1A",
|
|
2311
|
+
neutral: "#D1D5DB",
|
|
2312
|
+
"on-track": "#14B8A6",
|
|
2313
|
+
deviation: "#FFB020",
|
|
2314
|
+
future: "#6B7280"
|
|
2315
|
+
};
|
|
2316
|
+
var sizeDimensions = {
|
|
2317
|
+
sm: { size: 8, showIcon: false },
|
|
2318
|
+
md: { size: 18, showIcon: true }
|
|
2319
|
+
};
|
|
2320
|
+
function isSolidVariant(variant) {
|
|
2321
|
+
return variant in solidVariantColors;
|
|
2322
|
+
}
|
|
2323
|
+
function StatusDot({
|
|
2324
|
+
variant,
|
|
2325
|
+
icon,
|
|
2326
|
+
size = "sm",
|
|
2327
|
+
glow,
|
|
2328
|
+
label,
|
|
2329
|
+
className,
|
|
2330
|
+
...props
|
|
2331
|
+
}) {
|
|
2332
|
+
const config = sizeDimensions[size];
|
|
2333
|
+
const solid = isSolidVariant(variant);
|
|
2334
|
+
const ring = ringVariantStyles[variant];
|
|
2335
|
+
const glowStyle = glow ? glowStyles[variant] : null;
|
|
2336
|
+
const dot = /* @__PURE__ */ jsx(
|
|
2337
|
+
View,
|
|
2338
|
+
{
|
|
2339
|
+
style: [
|
|
2340
|
+
{
|
|
2341
|
+
width: config.size,
|
|
2342
|
+
height: config.size,
|
|
2343
|
+
borderRadius: 9999,
|
|
2344
|
+
alignItems: "center",
|
|
2345
|
+
justifyContent: "center",
|
|
2346
|
+
flexShrink: 0
|
|
2347
|
+
},
|
|
2348
|
+
solid ? { backgroundColor: solidVariantColors[variant] } : void 0,
|
|
2349
|
+
ring ? ring : void 0,
|
|
2350
|
+
glowStyle ? glowStyle : void 0
|
|
2351
|
+
],
|
|
2352
|
+
accessibilityRole: "image",
|
|
2353
|
+
accessibilityLabel: `${variant} status`,
|
|
2354
|
+
testID: "status-dot",
|
|
2355
|
+
children: config.showIcon && icon && /* @__PURE__ */ jsx(
|
|
2356
|
+
Text,
|
|
2357
|
+
{
|
|
2358
|
+
style: {
|
|
2359
|
+
fontSize: 11,
|
|
2360
|
+
lineHeight: 11,
|
|
2361
|
+
fontWeight: "900",
|
|
2362
|
+
color: iconColors[variant]
|
|
2363
|
+
},
|
|
2364
|
+
accessibilityElementsHidden: true,
|
|
2365
|
+
children: iconChars[icon]
|
|
2366
|
+
}
|
|
2367
|
+
)
|
|
2368
|
+
}
|
|
2369
|
+
);
|
|
2370
|
+
if (label) {
|
|
2371
|
+
return /* @__PURE__ */ jsxs(
|
|
2372
|
+
View,
|
|
2373
|
+
{
|
|
2374
|
+
className,
|
|
2375
|
+
style: { flexDirection: "row", alignItems: "center", gap: 6 },
|
|
2376
|
+
accessibilityLabel: `${variant} status: ${label}`,
|
|
2377
|
+
...props,
|
|
2378
|
+
children: [
|
|
2379
|
+
/* @__PURE__ */ jsx(View, { accessibilityElementsHidden: true, children: dot }),
|
|
2380
|
+
/* @__PURE__ */ jsx(
|
|
2381
|
+
Text,
|
|
2382
|
+
{
|
|
2383
|
+
style: { fontSize: 12, lineHeight: 16, color: "#9CA3AF" },
|
|
2384
|
+
accessibilityElementsHidden: true,
|
|
2385
|
+
children: label
|
|
2386
|
+
}
|
|
2387
|
+
)
|
|
2388
|
+
]
|
|
2389
|
+
}
|
|
2390
|
+
);
|
|
2391
|
+
}
|
|
2392
|
+
return /* @__PURE__ */ jsx(View, { className, ...props, children: dot });
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
// src/components/custom/Workout/MesoStatusCard.tsx
|
|
2396
|
+
var BRAND_PRIMARY3 = "#FF7900";
|
|
2397
|
+
var BRAND_PRIMARY_DARK = "#C45E00";
|
|
2398
|
+
var BRAND_PRIMARY_LIGHT = "#FFB066";
|
|
2399
|
+
var SUCCESS = "#14B8A6";
|
|
2400
|
+
var WARNING = "#FFB020";
|
|
2401
|
+
var ERROR = "#D14343";
|
|
2402
|
+
var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY3, BRAND_PRIMARY_LIGHT];
|
|
2403
|
+
var CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor("surface-elevated")} 0%, ${resolveColor("surface-raised")} 100%)`;
|
|
2404
|
+
var GAUGE_GRADIENT = "linear-gradient(90deg, rgba(20,184,166,0.25) 0%, rgba(255,176,32,0.25) 50%, rgba(209,67,67,0.25) 100%)";
|
|
2405
|
+
var STATUS_VARIANTS = {
|
|
2406
|
+
success: { bg: "rgba(20,184,166,0.15)", border: "rgba(20,184,166,0.3)", text: SUCCESS },
|
|
2407
|
+
warning: { bg: "rgba(255,176,32,0.15)", border: "rgba(255,176,32,0.3)", text: WARNING },
|
|
2408
|
+
error: { bg: "rgba(209,67,67,0.15)", border: "rgba(209,67,67,0.25)", text: ERROR }
|
|
2409
|
+
};
|
|
2410
|
+
function clamp012(value) {
|
|
2411
|
+
if (!Number.isFinite(value)) return 0;
|
|
2412
|
+
if (value < 0) return 0;
|
|
2413
|
+
if (value > 1) return 1;
|
|
2414
|
+
return value;
|
|
2415
|
+
}
|
|
2416
|
+
function getGaugeZoneColor(level) {
|
|
2417
|
+
if (level >= 0.7) return ERROR;
|
|
2418
|
+
if (level >= 0.4) return WARNING;
|
|
2419
|
+
return SUCCESS;
|
|
2420
|
+
}
|
|
2421
|
+
function renderCoachingText(text, highlights) {
|
|
2422
|
+
if (!highlights || highlights.length === 0) return text;
|
|
2423
|
+
const escaped = highlights.filter(Boolean).map((h) => h.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
2424
|
+
if (escaped.length === 0) return text;
|
|
2425
|
+
const regex = new RegExp(`(${escaped.join("|")})`, "g");
|
|
2426
|
+
return text.split(regex).map(
|
|
2427
|
+
(part, index) => highlights.includes(part) ? /* @__PURE__ */ jsx(
|
|
2428
|
+
Text,
|
|
2429
|
+
{
|
|
2430
|
+
className: "text-text-primary",
|
|
2431
|
+
style: { fontWeight: "700" },
|
|
2432
|
+
children: part
|
|
2433
|
+
},
|
|
2434
|
+
`${part}-${index}`
|
|
2435
|
+
) : /* @__PURE__ */ jsx(Fragment$1, { children: part }, `t-${index}`)
|
|
2436
|
+
);
|
|
2437
|
+
}
|
|
2438
|
+
function StatusPill({ badge }) {
|
|
2439
|
+
const colors = STATUS_VARIANTS[badge.variant];
|
|
2440
|
+
return /* @__PURE__ */ jsxs(
|
|
2441
|
+
View,
|
|
2442
|
+
{
|
|
2443
|
+
className: "flex-row items-center",
|
|
2444
|
+
style: {
|
|
2445
|
+
gap: 5,
|
|
2446
|
+
paddingVertical: 3,
|
|
2447
|
+
paddingHorizontal: 8,
|
|
2448
|
+
borderRadius: 4,
|
|
2449
|
+
borderWidth: 1,
|
|
2450
|
+
backgroundColor: colors.bg,
|
|
2451
|
+
borderColor: colors.border
|
|
2452
|
+
},
|
|
2453
|
+
testID: "meso-status-card-badge",
|
|
2454
|
+
children: [
|
|
2455
|
+
/* @__PURE__ */ jsx(View, { accessibilityElementsHidden: true, children: /* @__PURE__ */ jsx(StatusDot, { variant: badge.variant, size: "sm" }) }),
|
|
2456
|
+
/* @__PURE__ */ jsx(
|
|
2457
|
+
Text,
|
|
2458
|
+
{
|
|
2459
|
+
style: {
|
|
2460
|
+
fontSize: 10,
|
|
2461
|
+
fontFamily: "Inter, sans-serif",
|
|
2462
|
+
fontWeight: "700",
|
|
2463
|
+
letterSpacing: 0.3,
|
|
2464
|
+
color: colors.text
|
|
2465
|
+
},
|
|
2466
|
+
children: badge.label
|
|
2467
|
+
}
|
|
2468
|
+
)
|
|
2469
|
+
]
|
|
2470
|
+
}
|
|
2471
|
+
);
|
|
2472
|
+
}
|
|
2473
|
+
function MetricCell({ metric }) {
|
|
2474
|
+
return /* @__PURE__ */ jsxs(View, { style: { width: "48%" }, testID: "meso-status-card-metric", children: [
|
|
2475
|
+
/* @__PURE__ */ jsx(
|
|
2476
|
+
Text,
|
|
2477
|
+
{
|
|
2478
|
+
className: "text-text-tertiary",
|
|
2479
|
+
style: {
|
|
2480
|
+
fontSize: 10,
|
|
2481
|
+
fontFamily: "Inter, sans-serif",
|
|
2482
|
+
fontWeight: "600",
|
|
2483
|
+
letterSpacing: 0.5,
|
|
2484
|
+
textTransform: "uppercase"
|
|
2485
|
+
},
|
|
2486
|
+
children: metric.label
|
|
2487
|
+
}
|
|
2488
|
+
),
|
|
2489
|
+
/* @__PURE__ */ jsx(
|
|
2490
|
+
Text,
|
|
2491
|
+
{
|
|
2492
|
+
className: "text-text-primary",
|
|
2493
|
+
style: {
|
|
2494
|
+
marginTop: 2,
|
|
2495
|
+
fontSize: 13,
|
|
2496
|
+
fontFamily: "Inter, sans-serif",
|
|
2497
|
+
fontWeight: "600"
|
|
2498
|
+
},
|
|
2499
|
+
children: metric.value
|
|
2500
|
+
}
|
|
2501
|
+
)
|
|
2502
|
+
] });
|
|
2503
|
+
}
|
|
2504
|
+
function Gauge({ gauge }) {
|
|
2505
|
+
const level = clamp012(gauge.level);
|
|
2506
|
+
const percentage = Math.round(level * 100);
|
|
2507
|
+
const markerColor = getGaugeZoneColor(level);
|
|
2508
|
+
return /* @__PURE__ */ jsxs(
|
|
2509
|
+
View,
|
|
2510
|
+
{
|
|
2511
|
+
style: { gap: 6 },
|
|
2512
|
+
accessibilityRole: "progressbar",
|
|
2513
|
+
accessibilityValue: { min: 0, max: 100, now: percentage },
|
|
2514
|
+
accessibilityLabel: `${gauge.label}: ${percentage}%`,
|
|
2515
|
+
"aria-valuenow": percentage,
|
|
2516
|
+
"aria-valuemin": 0,
|
|
2517
|
+
"aria-valuemax": 100,
|
|
2518
|
+
testID: "meso-status-card-gauge",
|
|
2519
|
+
children: [
|
|
2520
|
+
/* @__PURE__ */ jsxs(
|
|
2521
|
+
View,
|
|
2522
|
+
{
|
|
2523
|
+
className: "flex-row items-center justify-between",
|
|
2524
|
+
accessibilityElementsHidden: true,
|
|
2525
|
+
children: [
|
|
2526
|
+
/* @__PURE__ */ jsx(
|
|
2527
|
+
Text,
|
|
2528
|
+
{
|
|
2529
|
+
className: "text-text-secondary",
|
|
2530
|
+
style: {
|
|
2531
|
+
fontSize: 10,
|
|
2532
|
+
fontFamily: "Inter, sans-serif",
|
|
2533
|
+
fontWeight: "500",
|
|
2534
|
+
letterSpacing: 0.5,
|
|
2535
|
+
textTransform: "uppercase"
|
|
2536
|
+
},
|
|
2537
|
+
children: gauge.label
|
|
2538
|
+
}
|
|
2539
|
+
),
|
|
2540
|
+
gauge.sublabel != null && /* @__PURE__ */ jsx(
|
|
2541
|
+
Text,
|
|
2542
|
+
{
|
|
2543
|
+
className: "text-text-tertiary",
|
|
2544
|
+
style: {
|
|
2545
|
+
fontSize: 10,
|
|
2546
|
+
fontFamily: "Inter, sans-serif",
|
|
2547
|
+
fontWeight: "500"
|
|
2548
|
+
},
|
|
2549
|
+
children: gauge.sublabel
|
|
2550
|
+
}
|
|
2551
|
+
)
|
|
2552
|
+
]
|
|
2553
|
+
}
|
|
2554
|
+
),
|
|
2555
|
+
/* @__PURE__ */ jsxs(
|
|
2556
|
+
View,
|
|
2557
|
+
{
|
|
2558
|
+
style: {
|
|
2559
|
+
height: 8,
|
|
2560
|
+
borderRadius: 4,
|
|
2561
|
+
position: "relative",
|
|
2562
|
+
backgroundImage: GAUGE_GRADIENT
|
|
2563
|
+
},
|
|
2564
|
+
accessibilityElementsHidden: true,
|
|
2565
|
+
children: [
|
|
2566
|
+
/* @__PURE__ */ jsx(
|
|
2567
|
+
View,
|
|
2568
|
+
{
|
|
2569
|
+
style: {
|
|
2570
|
+
position: "absolute",
|
|
2571
|
+
left: "50%",
|
|
2572
|
+
top: 0,
|
|
2573
|
+
bottom: 0,
|
|
2574
|
+
width: 1,
|
|
2575
|
+
marginLeft: -0.5,
|
|
2576
|
+
backgroundColor: "rgba(255,255,255,0.3)"
|
|
2577
|
+
},
|
|
2578
|
+
testID: "meso-status-card-gauge-center"
|
|
2579
|
+
}
|
|
2580
|
+
),
|
|
2581
|
+
/* @__PURE__ */ jsx(
|
|
2582
|
+
View,
|
|
2583
|
+
{
|
|
2584
|
+
className: "border-text-primary",
|
|
2585
|
+
style: {
|
|
2586
|
+
position: "absolute",
|
|
2587
|
+
left: `${percentage}%`,
|
|
2588
|
+
top: -3,
|
|
2589
|
+
marginLeft: -7,
|
|
2590
|
+
width: 14,
|
|
2591
|
+
height: 14,
|
|
2592
|
+
borderRadius: 9999,
|
|
2593
|
+
borderWidth: 2,
|
|
2594
|
+
backgroundColor: markerColor,
|
|
2595
|
+
boxShadow: "0 0 4px rgba(0,0,0,0.5)"
|
|
2596
|
+
},
|
|
2597
|
+
testID: "meso-status-card-gauge-marker"
|
|
2598
|
+
}
|
|
2599
|
+
)
|
|
2600
|
+
]
|
|
2601
|
+
}
|
|
2602
|
+
)
|
|
2603
|
+
]
|
|
2604
|
+
}
|
|
2605
|
+
);
|
|
2606
|
+
}
|
|
2607
|
+
function MesoStatusCard({
|
|
2608
|
+
mesoName,
|
|
2609
|
+
mesoSubtitle,
|
|
2610
|
+
statusBadge,
|
|
2611
|
+
metrics,
|
|
2612
|
+
gauges,
|
|
2613
|
+
coaching,
|
|
2614
|
+
nextTarget,
|
|
2615
|
+
className,
|
|
2616
|
+
...props
|
|
2617
|
+
}) {
|
|
2618
|
+
return /* @__PURE__ */ jsxs(
|
|
2619
|
+
Card,
|
|
2620
|
+
{
|
|
2621
|
+
variant: "outline",
|
|
2622
|
+
elevation: 1,
|
|
2623
|
+
borderColor: BRAND_PRIMARY_DARK,
|
|
2624
|
+
className,
|
|
2625
|
+
style: {
|
|
2626
|
+
borderColor: BRAND_PRIMARY_DARK,
|
|
2627
|
+
borderWidth: 1,
|
|
2628
|
+
backgroundImage: CARD_GRADIENT
|
|
2629
|
+
},
|
|
2630
|
+
role: "article",
|
|
2631
|
+
"aria-label": `Mesocycle status for ${mesoName}`,
|
|
2632
|
+
testID: "meso-status-card",
|
|
2633
|
+
...props,
|
|
2634
|
+
children: [
|
|
2635
|
+
/* @__PURE__ */ jsx(
|
|
2636
|
+
View,
|
|
2637
|
+
{
|
|
2638
|
+
className: "flex-row",
|
|
2639
|
+
style: { position: "absolute", top: 0, left: 0, right: 0, height: 3, zIndex: 1 },
|
|
2640
|
+
accessibilityElementsHidden: true,
|
|
2641
|
+
testID: "meso-status-card-accent",
|
|
2642
|
+
children: ACCENT_STOPS.map((color) => /* @__PURE__ */ jsx(View, { style: { flex: 1, backgroundColor: color } }, color))
|
|
2643
|
+
}
|
|
2644
|
+
),
|
|
2645
|
+
/* @__PURE__ */ jsxs(View, { style: { padding: 14, gap: 14 }, testID: "meso-status-card-body", children: [
|
|
2646
|
+
/* @__PURE__ */ jsxs(View, { testID: "meso-status-card-header", children: [
|
|
2647
|
+
/* @__PURE__ */ jsxs(
|
|
2648
|
+
View,
|
|
2649
|
+
{
|
|
2650
|
+
className: "flex-row items-center justify-between",
|
|
2651
|
+
style: { gap: 8 },
|
|
2652
|
+
children: [
|
|
2653
|
+
/* @__PURE__ */ jsx(
|
|
2654
|
+
Text,
|
|
2655
|
+
{
|
|
2656
|
+
className: "text-text-primary",
|
|
2657
|
+
style: {
|
|
2658
|
+
flexShrink: 1,
|
|
2659
|
+
fontSize: 15,
|
|
2660
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
2661
|
+
fontWeight: "700"
|
|
2662
|
+
},
|
|
2663
|
+
testID: "meso-status-card-name",
|
|
2664
|
+
children: mesoName
|
|
2665
|
+
}
|
|
2666
|
+
),
|
|
2667
|
+
/* @__PURE__ */ jsx(StatusPill, { badge: statusBadge })
|
|
2668
|
+
]
|
|
2669
|
+
}
|
|
2670
|
+
),
|
|
2671
|
+
/* @__PURE__ */ jsx(
|
|
2672
|
+
Text,
|
|
2673
|
+
{
|
|
2674
|
+
className: "text-text-secondary",
|
|
2675
|
+
style: {
|
|
2676
|
+
marginTop: 4,
|
|
2677
|
+
fontSize: 12,
|
|
2678
|
+
fontFamily: "Inter, sans-serif"
|
|
2679
|
+
},
|
|
2680
|
+
testID: "meso-status-card-subtitle",
|
|
2681
|
+
children: mesoSubtitle
|
|
2682
|
+
}
|
|
2683
|
+
)
|
|
2684
|
+
] }),
|
|
2685
|
+
metrics.length > 0 && /* @__PURE__ */ jsx(
|
|
2686
|
+
View,
|
|
2687
|
+
{
|
|
2688
|
+
className: "flex-row flex-wrap",
|
|
2689
|
+
style: { gap: 8 },
|
|
2690
|
+
testID: "meso-status-card-metrics",
|
|
2691
|
+
children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell, { metric }, `${metric.label}-${index}`))
|
|
2692
|
+
}
|
|
2693
|
+
),
|
|
2694
|
+
gauges.length > 0 && /* @__PURE__ */ jsx(View, { style: { gap: 12 }, testID: "meso-status-card-gauges", children: gauges.map((gauge, index) => /* @__PURE__ */ jsx(Gauge, { gauge }, `${gauge.label}-${index}`)) }),
|
|
2695
|
+
coaching != null && /* @__PURE__ */ jsx(
|
|
2696
|
+
View,
|
|
2697
|
+
{
|
|
2698
|
+
style: {
|
|
2699
|
+
backgroundColor: "rgba(255,176,32,0.06)",
|
|
2700
|
+
borderWidth: 1,
|
|
2701
|
+
borderColor: "rgba(255,176,32,0.15)",
|
|
2702
|
+
borderRadius: 8,
|
|
2703
|
+
paddingVertical: 10,
|
|
2704
|
+
paddingHorizontal: 12
|
|
2705
|
+
},
|
|
2706
|
+
testID: "meso-status-card-coaching",
|
|
2707
|
+
children: /* @__PURE__ */ jsx(
|
|
2708
|
+
Text,
|
|
2709
|
+
{
|
|
2710
|
+
className: "text-text-secondary",
|
|
2711
|
+
style: {
|
|
2712
|
+
fontSize: 12,
|
|
2713
|
+
lineHeight: 17,
|
|
2714
|
+
fontFamily: "Inter, sans-serif"
|
|
2715
|
+
},
|
|
2716
|
+
children: renderCoachingText(coaching.text, coaching.highlights)
|
|
2717
|
+
}
|
|
2718
|
+
)
|
|
2719
|
+
}
|
|
2720
|
+
),
|
|
2721
|
+
nextTarget != null && /* @__PURE__ */ jsxs(
|
|
2722
|
+
View,
|
|
2723
|
+
{
|
|
2724
|
+
className: "flex-row items-center",
|
|
2725
|
+
style: {
|
|
2726
|
+
gap: 8,
|
|
2727
|
+
backgroundColor: "rgba(20,184,166,0.06)",
|
|
2728
|
+
borderWidth: 1,
|
|
2729
|
+
borderColor: "rgba(20,184,166,0.2)",
|
|
2730
|
+
borderRadius: 8,
|
|
2731
|
+
paddingVertical: 10,
|
|
2732
|
+
paddingHorizontal: 12
|
|
2733
|
+
},
|
|
2734
|
+
testID: "meso-status-card-next-target",
|
|
2735
|
+
children: [
|
|
2736
|
+
/* @__PURE__ */ jsx(Text, { style: { fontSize: 14, color: SUCCESS }, accessibilityElementsHidden: true, children: nextTarget.icon }),
|
|
2737
|
+
/* @__PURE__ */ jsx(
|
|
2738
|
+
Text,
|
|
2739
|
+
{
|
|
2740
|
+
style: {
|
|
2741
|
+
flexShrink: 1,
|
|
2742
|
+
fontSize: 12,
|
|
2743
|
+
fontFamily: "Inter, sans-serif",
|
|
2744
|
+
fontWeight: "600",
|
|
2745
|
+
color: SUCCESS
|
|
2746
|
+
},
|
|
2747
|
+
children: nextTarget.text
|
|
2748
|
+
}
|
|
2749
|
+
)
|
|
2750
|
+
]
|
|
2751
|
+
}
|
|
2752
|
+
)
|
|
2753
|
+
] })
|
|
2754
|
+
]
|
|
2755
|
+
}
|
|
2756
|
+
);
|
|
2757
|
+
}
|
|
2758
|
+
|
|
2759
|
+
// src/components/custom/Workout/TrainingStatusPage.tsx
|
|
866
2760
|
var STATUS_ORDER = ["under", "maintenance", "productive", "over"];
|
|
867
2761
|
function deriveTrainingSummary(muscles) {
|
|
868
2762
|
const statusCounts = {
|
|
@@ -898,25 +2792,24 @@ function SummaryCards({ summary }) {
|
|
|
898
2792
|
return /* @__PURE__ */ jsxs(
|
|
899
2793
|
View,
|
|
900
2794
|
{
|
|
2795
|
+
className: "bg-surface-elevated border-border",
|
|
901
2796
|
style: {
|
|
902
2797
|
flexGrow: 1,
|
|
903
2798
|
flexBasis: "46%",
|
|
904
2799
|
padding: 12,
|
|
905
2800
|
borderRadius: 10,
|
|
906
|
-
|
|
907
|
-
borderWidth: 1,
|
|
908
|
-
borderColor: BORDER_DEFAULT2
|
|
2801
|
+
borderWidth: 1
|
|
909
2802
|
},
|
|
910
2803
|
testID: `training-status-page-summary-${key}`,
|
|
911
2804
|
children: [
|
|
912
2805
|
/* @__PURE__ */ jsx(
|
|
913
2806
|
Text,
|
|
914
2807
|
{
|
|
2808
|
+
className: "text-text-primary",
|
|
915
2809
|
style: {
|
|
916
2810
|
fontSize: 22,
|
|
917
2811
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
918
|
-
fontWeight: "700"
|
|
919
|
-
color: TEXT_PRIMARY3
|
|
2812
|
+
fontWeight: "700"
|
|
920
2813
|
},
|
|
921
2814
|
children: value
|
|
922
2815
|
}
|
|
@@ -924,14 +2817,14 @@ function SummaryCards({ summary }) {
|
|
|
924
2817
|
/* @__PURE__ */ jsx(
|
|
925
2818
|
Text,
|
|
926
2819
|
{
|
|
2820
|
+
className: "text-text-tertiary",
|
|
927
2821
|
style: {
|
|
928
2822
|
marginTop: 2,
|
|
929
2823
|
fontSize: 11,
|
|
930
2824
|
fontFamily: "Inter, sans-serif",
|
|
931
2825
|
fontWeight: "600",
|
|
932
2826
|
letterSpacing: 0.4,
|
|
933
|
-
textTransform: "uppercase"
|
|
934
|
-
color: TEXT_TERTIARY2
|
|
2827
|
+
textTransform: "uppercase"
|
|
935
2828
|
},
|
|
936
2829
|
children: label
|
|
937
2830
|
}
|
|
@@ -971,10 +2864,10 @@ function StatusLegend() {
|
|
|
971
2864
|
/* @__PURE__ */ jsx(
|
|
972
2865
|
Text,
|
|
973
2866
|
{
|
|
2867
|
+
className: "text-text-secondary",
|
|
974
2868
|
style: {
|
|
975
2869
|
fontSize: 11,
|
|
976
2870
|
fontFamily: "Inter, sans-serif",
|
|
977
|
-
color: TEXT_SECONDARY3,
|
|
978
2871
|
textTransform: "capitalize"
|
|
979
2872
|
},
|
|
980
2873
|
children: VOLUME_STATUS_LABELS[status]
|
|
@@ -1013,8 +2906,8 @@ function TrainingStatusPage({
|
|
|
1013
2906
|
return /* @__PURE__ */ jsxs(
|
|
1014
2907
|
View,
|
|
1015
2908
|
{
|
|
1016
|
-
className,
|
|
1017
|
-
style: { position: "relative", width: 390
|
|
2909
|
+
className: ["bg-background-base", className].filter(Boolean).join(" "),
|
|
2910
|
+
style: { position: "relative", width: 390 },
|
|
1018
2911
|
accessibilityRole: "main",
|
|
1019
2912
|
"aria-label": title,
|
|
1020
2913
|
testID: "training-status-page",
|
|
@@ -1025,11 +2918,11 @@ function TrainingStatusPage({
|
|
|
1025
2918
|
Text,
|
|
1026
2919
|
{
|
|
1027
2920
|
accessibilityRole: "header",
|
|
2921
|
+
className: "text-text-primary",
|
|
1028
2922
|
style: {
|
|
1029
2923
|
fontSize: 20,
|
|
1030
2924
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
1031
|
-
fontWeight: "700"
|
|
1032
|
-
color: TEXT_PRIMARY3
|
|
2925
|
+
fontWeight: "700"
|
|
1033
2926
|
},
|
|
1034
2927
|
testID: "training-status-page-title",
|
|
1035
2928
|
children: title
|
|
@@ -1040,10 +2933,9 @@ function TrainingStatusPage({
|
|
|
1040
2933
|
/* @__PURE__ */ jsxs(
|
|
1041
2934
|
View,
|
|
1042
2935
|
{
|
|
2936
|
+
className: "bg-surface-elevated border-border",
|
|
1043
2937
|
style: {
|
|
1044
|
-
backgroundColor: SURFACE_ELEVATED2,
|
|
1045
2938
|
borderWidth: 1,
|
|
1046
|
-
borderColor: BORDER_DEFAULT2,
|
|
1047
2939
|
borderRadius: 12,
|
|
1048
2940
|
padding: 12,
|
|
1049
2941
|
gap: 12
|