@titan-design/react-ui 0.2.7 → 0.3.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/bodymap-BhG55xHM.d.mts +318 -0
- package/dist/bodymap-BhG55xHM.d.ts +318 -0
- package/dist/bodymap.d.mts +3 -0
- package/dist/bodymap.d.ts +3 -0
- package/dist/bodymap.js +2670 -0
- package/dist/bodymap.js.map +1 -0
- package/dist/bodymap.mjs +1101 -0
- package/dist/bodymap.mjs.map +1 -0
- package/dist/{chunk-5SSKGS6E.mjs → chunk-7XPB4NAO.mjs} +124 -4
- package/dist/chunk-7XPB4NAO.mjs.map +1 -0
- package/dist/{chunk-3VLOBS6O.mjs → chunk-P7TSQUN6.mjs} +3 -3
- package/dist/{chunk-3VLOBS6O.mjs.map → chunk-P7TSQUN6.mjs.map} +1 -1
- package/dist/chunk-TOD2WQBG.mjs +1048 -0
- package/dist/chunk-TOD2WQBG.mjs.map +1 -0
- package/dist/index.d.mts +375 -249
- package/dist/index.d.ts +375 -249
- package/dist/index.js +1259 -918
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1314 -2107
- package/dist/index.mjs.map +1 -1
- package/dist/theme/index.d.mts +260 -0
- package/dist/theme/index.d.ts +260 -0
- package/dist/theme/index.js +122 -2
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +2 -2
- package/dist/theme/tokens-css.d.mts +5 -3
- package/dist/theme/tokens-css.d.ts +5 -3
- package/dist/theme/tokens-css.js +318 -9
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +1 -1
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/package.json +10 -1
- package/src/bodymap.ts +37 -0
- package/src/components/custom/Table/Table.test.tsx +27 -0
- package/src/components/custom/Table/Table.tsx +33 -17
- package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +118 -0
- package/src/components/custom/Workout/ActiveWorkoutPage.test.tsx +171 -0
- package/src/components/custom/Workout/ActiveWorkoutPage.tsx +447 -0
- package/src/components/custom/Workout/BodyMap.tsx +5 -6
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +7 -8
- package/src/components/custom/Workout/CapacityBandChart.tsx +1 -1
- package/src/components/custom/Workout/ExerciseCard.test.tsx +24 -0
- package/src/components/custom/Workout/ExerciseCard.tsx +28 -15
- package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +225 -0
- package/src/components/custom/Workout/ExerciseDetailPage.test.tsx +128 -0
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +630 -0
- package/src/components/custom/Workout/InputBar.tsx +6 -7
- package/src/components/custom/Workout/MesoCard.tsx +4 -2
- package/src/components/custom/Workout/MesoProgressBar.test.tsx +12 -0
- package/src/components/custom/Workout/MesoProgressBar.tsx +5 -1
- package/src/components/custom/Workout/MesoStatusCard.tsx +5 -5
- package/src/components/custom/Workout/PlaceholderStrip.tsx +2 -3
- package/src/components/custom/Workout/PrHistoryModal.tsx +5 -5
- package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +257 -0
- package/src/components/custom/Workout/ProgramPlanningPage.test.tsx +142 -0
- package/src/components/custom/Workout/ProgramPlanningPage.tsx +422 -0
- package/src/components/custom/Workout/ReadinessCheck.tsx +7 -8
- package/src/components/custom/Workout/RestTimer.test.tsx +10 -0
- package/src/components/custom/Workout/RestTimer.tsx +11 -9
- package/src/components/custom/Workout/SetRow.tsx +13 -19
- package/src/components/custom/Workout/StatusDot.tsx +1 -0
- package/src/components/custom/Workout/StrengthTrendChart.tsx +5 -5
- package/src/components/custom/Workout/TempoDisplay.tsx +3 -1
- package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +212 -0
- package/src/components/custom/Workout/TrainingStatusPage.test.tsx +131 -0
- package/src/components/custom/Workout/TrainingStatusPage.tsx +321 -0
- package/src/components/custom/Workout/VelocityStrip.test.tsx +10 -0
- package/src/components/custom/Workout/VelocityStrip.tsx +16 -15
- package/src/components/custom/Workout/WeekRow.tsx +1 -1
- package/src/components/custom/Workout/WorkoutCard.tsx +5 -3
- package/src/components/custom/Workout/index.ts +71 -32
- package/src/theme/config.completeness.test.ts +77 -0
- package/src/theme/config.ts +151 -0
- package/src/theme/manifest/design-freeze.test.ts +155 -0
- package/src/theme/manifest/extract-css-properties.fixture.html +29 -0
- package/src/theme/manifest/extract-css-properties.test.ts +112 -0
- package/src/theme/tokens-css.ts +5 -3
- package/src/theme/workout-tokens.ts +12 -14
- package/src/utils/index.ts +10 -0
- package/src/utils/workout-format.test.ts +81 -0
- package/src/utils/workout-format.ts +83 -0
- package/dist/chunk-5SSKGS6E.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -6,12 +6,10 @@ var tailwindMerge = require('tailwind-merge');
|
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
var React24 = require('react');
|
|
8
8
|
var lucideReact = require('lucide-react');
|
|
9
|
-
var BodyHighlighter = require('react-native-body-highlighter');
|
|
10
9
|
|
|
11
10
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
11
|
|
|
13
12
|
var React24__default = /*#__PURE__*/_interopDefault(React24);
|
|
14
|
-
var BodyHighlighter__default = /*#__PURE__*/_interopDefault(BodyHighlighter);
|
|
15
13
|
|
|
16
14
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
17
15
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
@@ -1211,6 +1209,28 @@ var PasswordInput = React24.forwardRef(function PasswordInput2({ showIcon, hideI
|
|
|
1211
1209
|
});
|
|
1212
1210
|
|
|
1213
1211
|
// src/theme/config.ts
|
|
1212
|
+
var themeIndependentCSSVars = {
|
|
1213
|
+
// RGB decomposed values for glow shadows
|
|
1214
|
+
"--color-brand-primary-rgb": "255, 121, 0",
|
|
1215
|
+
"--color-brand-secondary-rgb": "64, 109, 135",
|
|
1216
|
+
"--color-status-success-rgb": "20, 184, 166",
|
|
1217
|
+
"--color-status-error-rgb": "209, 67, 67",
|
|
1218
|
+
"--color-status-warning-rgb": "255, 176, 32",
|
|
1219
|
+
"--color-status-info-rgb": "33, 150, 243",
|
|
1220
|
+
"--color-background-base-rgb": "16, 16, 16",
|
|
1221
|
+
// Font families
|
|
1222
|
+
"--font-family-sans": "'Inter'",
|
|
1223
|
+
"--font-family-body": "'Nunito Sans'",
|
|
1224
|
+
"--font-family-heading": "'Space Grotesk'",
|
|
1225
|
+
"--font-family-mono": "'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace",
|
|
1226
|
+
// Animation tokens
|
|
1227
|
+
"--ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
|
|
1228
|
+
"--ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
|
|
1229
|
+
"--ease-spring": "cubic-bezier(0.34, 1.56, 0.64, 1)",
|
|
1230
|
+
"--duration-fast": "150ms",
|
|
1231
|
+
"--duration-normal": "250ms",
|
|
1232
|
+
"--duration-slow": "400ms"
|
|
1233
|
+
};
|
|
1214
1234
|
var lightThemeCSSVars = {
|
|
1215
1235
|
"--color-brand-primary": semanticColorsLight["brand-primary"],
|
|
1216
1236
|
"--color-brand-primary-light": semanticColorsLight["brand-primary-light"],
|
|
@@ -1251,7 +1271,56 @@ var lightThemeCSSVars = {
|
|
|
1251
1271
|
"--color-interactive-active": semanticColorsLight["interactive-active"],
|
|
1252
1272
|
"--color-interactive-selected": semanticColorsLight["interactive-selected"],
|
|
1253
1273
|
"--color-interactive-disabled": semanticColorsLight["interactive-disabled"],
|
|
1254
|
-
"--color-divider": semanticColorsLight["divider"]
|
|
1274
|
+
"--color-divider": semanticColorsLight["divider"],
|
|
1275
|
+
"--color-brand-primary-hover": semanticColorsLight["brand-primary-hover"],
|
|
1276
|
+
"--color-brand-primary-active": semanticColorsLight["brand-primary-active"],
|
|
1277
|
+
"--color-brand-secondary-hover": semanticColorsLight["brand-secondary-hover"],
|
|
1278
|
+
"--color-brand-secondary-active": semanticColorsLight["brand-secondary-active"],
|
|
1279
|
+
"--color-status-success-light": semanticColorsLight["status-success-light"],
|
|
1280
|
+
"--color-status-success-dark": semanticColorsLight["status-success-dark"],
|
|
1281
|
+
"--color-status-error-light": semanticColorsLight["status-error-light"],
|
|
1282
|
+
"--color-status-error-dark": semanticColorsLight["status-error-dark"],
|
|
1283
|
+
"--color-status-warning-light": semanticColorsLight["status-warning-light"],
|
|
1284
|
+
"--color-status-warning-dark": semanticColorsLight["status-warning-dark"],
|
|
1285
|
+
"--color-status-info-light": semanticColorsLight["status-info-light"],
|
|
1286
|
+
"--color-status-info-dark": semanticColorsLight["status-info-dark"],
|
|
1287
|
+
"--color-on-status-success": semanticColorsLight["on-status-success"],
|
|
1288
|
+
"--color-on-status-error": semanticColorsLight["on-status-error"],
|
|
1289
|
+
"--color-on-status-warning": semanticColorsLight["on-status-warning"],
|
|
1290
|
+
"--color-on-status-info": semanticColorsLight["on-status-info"],
|
|
1291
|
+
"--color-result-improve": semanticColorsLight["result-improve"],
|
|
1292
|
+
"--color-result-improve-light": semanticColorsLight["result-improve-light"],
|
|
1293
|
+
"--color-result-improve-dark": semanticColorsLight["result-improve-dark"],
|
|
1294
|
+
"--color-result-degrade": semanticColorsLight["result-degrade"],
|
|
1295
|
+
"--color-result-degrade-light": semanticColorsLight["result-degrade-light"],
|
|
1296
|
+
"--color-result-degrade-dark": semanticColorsLight["result-degrade-dark"],
|
|
1297
|
+
"--color-result-inconclusive": semanticColorsLight["result-inconclusive"],
|
|
1298
|
+
"--color-result-inconclusive-light": semanticColorsLight["result-inconclusive-light"],
|
|
1299
|
+
"--color-result-neutral": semanticColorsLight["result-neutral"],
|
|
1300
|
+
"--color-on-result-improve": semanticColorsLight["on-result-improve"],
|
|
1301
|
+
"--color-on-result-degrade": semanticColorsLight["on-result-degrade"],
|
|
1302
|
+
"--color-on-result-inconclusive": semanticColorsLight["on-result-inconclusive"],
|
|
1303
|
+
"--color-data-1": semanticColorsLight["data-1"],
|
|
1304
|
+
"--color-data-2": semanticColorsLight["data-2"],
|
|
1305
|
+
"--color-data-3": semanticColorsLight["data-3"],
|
|
1306
|
+
"--color-data-4": semanticColorsLight["data-4"],
|
|
1307
|
+
"--color-data-5": semanticColorsLight["data-5"],
|
|
1308
|
+
"--color-data-6": semanticColorsLight["data-6"],
|
|
1309
|
+
"--color-data-7": semanticColorsLight["data-7"],
|
|
1310
|
+
"--color-data-8": semanticColorsLight["data-8"],
|
|
1311
|
+
"--color-data-9": semanticColorsLight["data-9"],
|
|
1312
|
+
"--color-data-10": semanticColorsLight["data-10"],
|
|
1313
|
+
"--color-text-link-hover": semanticColorsLight["text-link-hover"],
|
|
1314
|
+
"--color-surface-overlay": semanticColorsLight["surface-overlay"],
|
|
1315
|
+
"--color-surface-input": semanticColorsLight["surface-input"],
|
|
1316
|
+
"--color-border-input": semanticColorsLight["border-input"],
|
|
1317
|
+
"--color-border-input-hover": semanticColorsLight["border-input-hover"],
|
|
1318
|
+
"--color-border-input-focus": semanticColorsLight["border-input-focus"],
|
|
1319
|
+
"--color-border-input-error": semanticColorsLight["border-input-error"],
|
|
1320
|
+
"--color-interactive-disabled-text": semanticColorsLight["interactive-disabled-text"],
|
|
1321
|
+
"--color-avatar-background": semanticColorsLight["avatar-background"],
|
|
1322
|
+
"--color-avatar-text": semanticColorsLight["avatar-text"],
|
|
1323
|
+
...themeIndependentCSSVars
|
|
1255
1324
|
};
|
|
1256
1325
|
var darkThemeCSSVars = {
|
|
1257
1326
|
"--color-brand-primary": semanticColorsDark["brand-primary"],
|
|
@@ -1293,7 +1362,56 @@ var darkThemeCSSVars = {
|
|
|
1293
1362
|
"--color-interactive-active": semanticColorsDark["interactive-active"],
|
|
1294
1363
|
"--color-interactive-selected": semanticColorsDark["interactive-selected"],
|
|
1295
1364
|
"--color-interactive-disabled": semanticColorsDark["interactive-disabled"],
|
|
1296
|
-
"--color-divider": semanticColorsDark["divider"]
|
|
1365
|
+
"--color-divider": semanticColorsDark["divider"],
|
|
1366
|
+
"--color-brand-primary-hover": semanticColorsDark["brand-primary-hover"],
|
|
1367
|
+
"--color-brand-primary-active": semanticColorsDark["brand-primary-active"],
|
|
1368
|
+
"--color-brand-secondary-hover": semanticColorsDark["brand-secondary-hover"],
|
|
1369
|
+
"--color-brand-secondary-active": semanticColorsDark["brand-secondary-active"],
|
|
1370
|
+
"--color-status-success-light": semanticColorsDark["status-success-light"],
|
|
1371
|
+
"--color-status-success-dark": semanticColorsDark["status-success-dark"],
|
|
1372
|
+
"--color-status-error-light": semanticColorsDark["status-error-light"],
|
|
1373
|
+
"--color-status-error-dark": semanticColorsDark["status-error-dark"],
|
|
1374
|
+
"--color-status-warning-light": semanticColorsDark["status-warning-light"],
|
|
1375
|
+
"--color-status-warning-dark": semanticColorsDark["status-warning-dark"],
|
|
1376
|
+
"--color-status-info-light": semanticColorsDark["status-info-light"],
|
|
1377
|
+
"--color-status-info-dark": semanticColorsDark["status-info-dark"],
|
|
1378
|
+
"--color-on-status-success": semanticColorsDark["on-status-success"],
|
|
1379
|
+
"--color-on-status-error": semanticColorsDark["on-status-error"],
|
|
1380
|
+
"--color-on-status-warning": semanticColorsDark["on-status-warning"],
|
|
1381
|
+
"--color-on-status-info": semanticColorsDark["on-status-info"],
|
|
1382
|
+
"--color-result-improve": semanticColorsDark["result-improve"],
|
|
1383
|
+
"--color-result-improve-light": semanticColorsDark["result-improve-light"],
|
|
1384
|
+
"--color-result-improve-dark": semanticColorsDark["result-improve-dark"],
|
|
1385
|
+
"--color-result-degrade": semanticColorsDark["result-degrade"],
|
|
1386
|
+
"--color-result-degrade-light": semanticColorsDark["result-degrade-light"],
|
|
1387
|
+
"--color-result-degrade-dark": semanticColorsDark["result-degrade-dark"],
|
|
1388
|
+
"--color-result-inconclusive": semanticColorsDark["result-inconclusive"],
|
|
1389
|
+
"--color-result-inconclusive-light": semanticColorsDark["result-inconclusive-light"],
|
|
1390
|
+
"--color-result-neutral": semanticColorsDark["result-neutral"],
|
|
1391
|
+
"--color-on-result-improve": semanticColorsDark["on-result-improve"],
|
|
1392
|
+
"--color-on-result-degrade": semanticColorsDark["on-result-degrade"],
|
|
1393
|
+
"--color-on-result-inconclusive": semanticColorsDark["on-result-inconclusive"],
|
|
1394
|
+
"--color-data-1": semanticColorsDark["data-1"],
|
|
1395
|
+
"--color-data-2": semanticColorsDark["data-2"],
|
|
1396
|
+
"--color-data-3": semanticColorsDark["data-3"],
|
|
1397
|
+
"--color-data-4": semanticColorsDark["data-4"],
|
|
1398
|
+
"--color-data-5": semanticColorsDark["data-5"],
|
|
1399
|
+
"--color-data-6": semanticColorsDark["data-6"],
|
|
1400
|
+
"--color-data-7": semanticColorsDark["data-7"],
|
|
1401
|
+
"--color-data-8": semanticColorsDark["data-8"],
|
|
1402
|
+
"--color-data-9": semanticColorsDark["data-9"],
|
|
1403
|
+
"--color-data-10": semanticColorsDark["data-10"],
|
|
1404
|
+
"--color-text-link-hover": semanticColorsDark["text-link-hover"],
|
|
1405
|
+
"--color-surface-overlay": semanticColorsDark["surface-overlay"],
|
|
1406
|
+
"--color-surface-input": semanticColorsDark["surface-input"],
|
|
1407
|
+
"--color-border-input": semanticColorsDark["border-input"],
|
|
1408
|
+
"--color-border-input-hover": semanticColorsDark["border-input-hover"],
|
|
1409
|
+
"--color-border-input-focus": semanticColorsDark["border-input-focus"],
|
|
1410
|
+
"--color-border-input-error": semanticColorsDark["border-input-error"],
|
|
1411
|
+
"--color-interactive-disabled-text": semanticColorsDark["interactive-disabled-text"],
|
|
1412
|
+
"--color-avatar-background": semanticColorsDark["avatar-background"],
|
|
1413
|
+
"--color-avatar-text": semanticColorsDark["avatar-text"],
|
|
1414
|
+
...themeIndependentCSSVars
|
|
1297
1415
|
};
|
|
1298
1416
|
function getThemeCSSVars(mode) {
|
|
1299
1417
|
return mode === "dark" ? darkThemeCSSVars : lightThemeCSSVars;
|
|
@@ -5982,7 +6100,7 @@ function Table({
|
|
|
5982
6100
|
selectable,
|
|
5983
6101
|
allRowIds: rowIds
|
|
5984
6102
|
},
|
|
5985
|
-
children: /* @__PURE__ */ jsx(reactNative.View, { className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsx(reactNative.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: /* @__PURE__ */ jsx(reactNative.View, { className: "w-full min-w-full", children: isLoading ? /* @__PURE__ */ jsx(TableLoadingSkeleton, { rowCount: loadingRowCount }) : children }) }) })
|
|
6103
|
+
children: /* @__PURE__ */ jsx(reactNative.View, { className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsx(reactNative.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: /* @__PURE__ */ jsx(reactNative.View, { role: "table", className: "w-full min-w-full", children: isLoading ? /* @__PURE__ */ jsx(TableLoadingSkeleton, { rowCount: loadingRowCount }) : children }) }) })
|
|
5986
6104
|
}
|
|
5987
6105
|
);
|
|
5988
6106
|
}
|
|
@@ -5990,14 +6108,14 @@ function TableHeader({ children, className }) {
|
|
|
5990
6108
|
return /* @__PURE__ */ jsx(
|
|
5991
6109
|
reactNative.View,
|
|
5992
6110
|
{
|
|
5993
|
-
|
|
6111
|
+
role: "rowgroup",
|
|
5994
6112
|
className: cn("bg-background-subtle rounded-t-lg", className),
|
|
5995
6113
|
children
|
|
5996
6114
|
}
|
|
5997
6115
|
);
|
|
5998
6116
|
}
|
|
5999
6117
|
function TableBody({ children, className }) {
|
|
6000
|
-
return /* @__PURE__ */ jsx(reactNative.View, {
|
|
6118
|
+
return /* @__PURE__ */ jsx(reactNative.View, { role: "rowgroup", className, children });
|
|
6001
6119
|
}
|
|
6002
6120
|
function TableRow({
|
|
6003
6121
|
isSelected = false,
|
|
@@ -6009,7 +6127,7 @@ function TableRow({
|
|
|
6009
6127
|
return /* @__PURE__ */ jsx(
|
|
6010
6128
|
reactNative.View,
|
|
6011
6129
|
{
|
|
6012
|
-
|
|
6130
|
+
role: "row",
|
|
6013
6131
|
className: cn(
|
|
6014
6132
|
"flex-row border-b border-divider",
|
|
6015
6133
|
isHoverable && "web:hover:bg-interactive-hover",
|
|
@@ -6033,6 +6151,7 @@ function TableHeaderCell({
|
|
|
6033
6151
|
const { sortColumn, sortDirection, onSort } = React24.useContext(TableContext);
|
|
6034
6152
|
const isSorted = sortKey && sortColumn === sortKey;
|
|
6035
6153
|
const isSortable = !!sortKey && !!onSort;
|
|
6154
|
+
const ariaSort = isSorted ? sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : "none" : "none";
|
|
6036
6155
|
const handlePress = (e) => {
|
|
6037
6156
|
if (isSortable && sortKey) {
|
|
6038
6157
|
onSort(sortKey);
|
|
@@ -6059,26 +6178,34 @@ function TableHeaderCell({
|
|
|
6059
6178
|
] });
|
|
6060
6179
|
if (isSortable) {
|
|
6061
6180
|
return /* @__PURE__ */ jsx(
|
|
6062
|
-
reactNative.
|
|
6181
|
+
reactNative.View,
|
|
6063
6182
|
{
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
onPress: handlePress,
|
|
6183
|
+
role: "columnheader",
|
|
6184
|
+
"aria-sort": ariaSort,
|
|
6067
6185
|
style: width ? { width } : { flex: 1 },
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6186
|
+
children: /* @__PURE__ */ jsx(
|
|
6187
|
+
reactNative.Pressable,
|
|
6188
|
+
{
|
|
6189
|
+
accessibilityRole: "button",
|
|
6190
|
+
accessibilityLabel: `Sort by ${children}`,
|
|
6191
|
+
onPress: handlePress,
|
|
6192
|
+
className: cn(
|
|
6193
|
+
"flex-row items-center px-4 py-3",
|
|
6194
|
+
alignStyles3[align],
|
|
6195
|
+
"web:hover:bg-interactive-hover active:bg-interactive-active",
|
|
6196
|
+
className
|
|
6197
|
+
),
|
|
6198
|
+
...props,
|
|
6199
|
+
children: content
|
|
6200
|
+
}
|
|
6201
|
+
)
|
|
6076
6202
|
}
|
|
6077
6203
|
);
|
|
6078
6204
|
}
|
|
6079
6205
|
return /* @__PURE__ */ jsx(
|
|
6080
6206
|
reactNative.View,
|
|
6081
6207
|
{
|
|
6208
|
+
role: "columnheader",
|
|
6082
6209
|
style: width ? { width } : { flex: 1 },
|
|
6083
6210
|
className: cn(
|
|
6084
6211
|
"flex-row items-center px-4 py-3",
|
|
@@ -6104,6 +6231,7 @@ function TableCell({
|
|
|
6104
6231
|
return /* @__PURE__ */ jsx(
|
|
6105
6232
|
reactNative.View,
|
|
6106
6233
|
{
|
|
6234
|
+
role: "cell",
|
|
6107
6235
|
style: width ? { width } : { flex: 1 },
|
|
6108
6236
|
className: cn(
|
|
6109
6237
|
"justify-center px-4 py-3.5",
|
|
@@ -6985,36 +7113,6 @@ function StatusDot({
|
|
|
6985
7113
|
}
|
|
6986
7114
|
return /* @__PURE__ */ jsx(reactNative.View, { className, ...props, children: dot });
|
|
6987
7115
|
}
|
|
6988
|
-
|
|
6989
|
-
// src/theme/workout-tokens.ts
|
|
6990
|
-
var WORKOUT_TOKENS = {
|
|
6991
|
-
// BodyMap volume heatmap scale (drive dynamic SVG fills, so inline values).
|
|
6992
|
-
// Maps weekly-volume status against MEV/MAV/MRV landmarks to a fill color.
|
|
6993
|
-
heatmap: {
|
|
6994
|
-
none: "#E0E0E0",
|
|
6995
|
-
// gray — no training data
|
|
6996
|
-
under: "#4A90D9",
|
|
6997
|
-
// cool blue — below MEV
|
|
6998
|
-
maintenance: "#F5C842",
|
|
6999
|
-
// warm yellow — MEV to MAV
|
|
7000
|
-
productive: "#4CAF50",
|
|
7001
|
-
// green — MAV to MRV
|
|
7002
|
-
approaching: "#FFA502",
|
|
7003
|
-
// orange — near MRV
|
|
7004
|
-
over: "#FF6B35"
|
|
7005
|
-
// red-orange — over MRV
|
|
7006
|
-
},
|
|
7007
|
-
// Border colors (use inline to avoid 'border' class pitfall)
|
|
7008
|
-
border: {
|
|
7009
|
-
default: "#1F1F1F",
|
|
7010
|
-
strong: "#2C2C2C"},
|
|
7011
|
-
// Surface colors for inline use
|
|
7012
|
-
surface: {
|
|
7013
|
-
raised: "#1C1C1C",
|
|
7014
|
-
elevated: "#191919"
|
|
7015
|
-
}};
|
|
7016
|
-
|
|
7017
|
-
// src/components/custom/Workout/PlaceholderStrip.tsx
|
|
7018
7116
|
function SingleStrip({
|
|
7019
7117
|
width,
|
|
7020
7118
|
className,
|
|
@@ -7030,7 +7128,7 @@ function SingleStrip({
|
|
|
7030
7128
|
backgroundColor: "transparent",
|
|
7031
7129
|
borderWidth: 1,
|
|
7032
7130
|
borderStyle: "dashed",
|
|
7033
|
-
borderColor:
|
|
7131
|
+
borderColor: "var(--color-border-strong)",
|
|
7034
7132
|
borderRadius: 1,
|
|
7035
7133
|
opacity: 0.5
|
|
7036
7134
|
},
|
|
@@ -7070,7 +7168,7 @@ function SegmentedStrip({
|
|
|
7070
7168
|
backgroundColor: "transparent",
|
|
7071
7169
|
borderWidth: 1,
|
|
7072
7170
|
borderStyle: "dashed",
|
|
7073
|
-
borderColor:
|
|
7171
|
+
borderColor: "var(--color-border-strong)",
|
|
7074
7172
|
borderRadius: 1,
|
|
7075
7173
|
minWidth: 4
|
|
7076
7174
|
},
|
|
@@ -7092,6 +7190,63 @@ function PlaceholderStrip({
|
|
|
7092
7190
|
}
|
|
7093
7191
|
return /* @__PURE__ */ jsx(SingleStrip, { ...props });
|
|
7094
7192
|
}
|
|
7193
|
+
|
|
7194
|
+
// src/theme/workout-tokens.ts
|
|
7195
|
+
var WORKOUT_TOKENS = {
|
|
7196
|
+
// Canonical 4-band performance scale — the single source for BOTH the
|
|
7197
|
+
// VelocityStrip zone bars and the SetRow RPE color (TD-03.43). The direction
|
|
7198
|
+
// is intentionally inverted between the two consumers: for velocity, green =
|
|
7199
|
+
// fastest/best; for RPE, green = easiest. Each component maps its own
|
|
7200
|
+
// thresholds onto these four colors. Kept as vivid data-viz values (distinct
|
|
7201
|
+
// from the muted status tokens) and theme-independent, so — like the heatmap
|
|
7202
|
+
// scale below — they are consumed inline as a JS import rather than CSS vars.
|
|
7203
|
+
// A JS import also resolves on native RN, unlike var(--…) strings.
|
|
7204
|
+
scale: {
|
|
7205
|
+
green: "#2ed573",
|
|
7206
|
+
yellow: "#ffd43b",
|
|
7207
|
+
orange: "#ffa502",
|
|
7208
|
+
red: "#ff4757"
|
|
7209
|
+
}};
|
|
7210
|
+
|
|
7211
|
+
// src/utils/workout-format.ts
|
|
7212
|
+
function roundRpe(rpe) {
|
|
7213
|
+
return Math.round(rpe * 2) / 2;
|
|
7214
|
+
}
|
|
7215
|
+
function rpeColor(rpe) {
|
|
7216
|
+
if (rpe >= 9.5) return WORKOUT_TOKENS.scale.red;
|
|
7217
|
+
if (rpe >= 8.5) return WORKOUT_TOKENS.scale.orange;
|
|
7218
|
+
if (rpe >= 7) return WORKOUT_TOKENS.scale.yellow;
|
|
7219
|
+
return WORKOUT_TOKENS.scale.green;
|
|
7220
|
+
}
|
|
7221
|
+
function roundWeight(weight) {
|
|
7222
|
+
return Math.round(weight);
|
|
7223
|
+
}
|
|
7224
|
+
function formatVelocity(velocity) {
|
|
7225
|
+
return velocity.toFixed(2);
|
|
7226
|
+
}
|
|
7227
|
+
function roundTempo(tempo) {
|
|
7228
|
+
return tempo.map((v) => Math.round(v * 10) / 10);
|
|
7229
|
+
}
|
|
7230
|
+
function formatSignedPct(ratio) {
|
|
7231
|
+
const pct = Math.round(ratio * 100);
|
|
7232
|
+
return `${pct > 0 ? "+" : ""}${pct}%`;
|
|
7233
|
+
}
|
|
7234
|
+
function formatPrescription(p) {
|
|
7235
|
+
if (p == null) return null;
|
|
7236
|
+
let reps = null;
|
|
7237
|
+
if (p.repsLow != null && p.repsHigh != null) {
|
|
7238
|
+
reps = p.repsLow === p.repsHigh ? `${p.repsLow}` : `${p.repsLow}\u2013${p.repsHigh}`;
|
|
7239
|
+
} else if (p.repsLow != null) {
|
|
7240
|
+
reps = `${p.repsLow}`;
|
|
7241
|
+
}
|
|
7242
|
+
const weight = p.weightLbs != null ? `${p.weightLbs} lb` : null;
|
|
7243
|
+
const head = [reps, weight].filter((s) => s != null).join(" @ ");
|
|
7244
|
+
const rpe = p.rpe != null ? `RPE ${p.rpe}` : null;
|
|
7245
|
+
const full = [head.length > 0 ? head : null, rpe].filter((s) => s != null).join(" \xB7 ");
|
|
7246
|
+
return full.length > 0 ? full : null;
|
|
7247
|
+
}
|
|
7248
|
+
|
|
7249
|
+
// src/components/custom/Workout/TempoDisplay.tsx
|
|
7095
7250
|
var INTER = "Inter, sans-serif";
|
|
7096
7251
|
var TEXT_TERTIARY = "#6B7280";
|
|
7097
7252
|
var phaseColors = {
|
|
@@ -7147,7 +7302,7 @@ function TempoDisplay({
|
|
|
7147
7302
|
...props
|
|
7148
7303
|
}) {
|
|
7149
7304
|
const [showTooltip, setShowTooltip] = React24.useState(false);
|
|
7150
|
-
const [eccentric, pauseBottom, concentric, pauseTop] = tempo;
|
|
7305
|
+
const [eccentric, pauseBottom, concentric, pauseTop] = roundTempo(tempo);
|
|
7151
7306
|
const isSm = size === "sm";
|
|
7152
7307
|
const fontSize = isSm ? 9 : 11;
|
|
7153
7308
|
const monoColor = TEXT_TERTIARY;
|
|
@@ -7655,12 +7810,7 @@ function WorkoutPill({
|
|
|
7655
7810
|
}
|
|
7656
7811
|
return pill;
|
|
7657
7812
|
}
|
|
7658
|
-
var VEL_COLORS =
|
|
7659
|
-
green: "#2ed573",
|
|
7660
|
-
yellow: "#ffd43b",
|
|
7661
|
-
orange: "#ffa502",
|
|
7662
|
-
red: "#ff4757"
|
|
7663
|
-
};
|
|
7813
|
+
var VEL_COLORS = WORKOUT_TOKENS.scale;
|
|
7664
7814
|
function getVelocityZoneColor(velocity) {
|
|
7665
7815
|
if (velocity >= 1) return "vel-green";
|
|
7666
7816
|
if (velocity >= 0.75) return "vel-yellow";
|
|
@@ -7798,7 +7948,7 @@ function VelocityStrip({
|
|
|
7798
7948
|
paddingBottom: expanded ? 24 : 0,
|
|
7799
7949
|
paddingHorizontal: expanded ? 6 : 0,
|
|
7800
7950
|
paddingVertical: expanded ? void 0 : 8,
|
|
7801
|
-
backgroundColor: expanded ? "
|
|
7951
|
+
backgroundColor: expanded ? "var(--color-surface-raised)" : "transparent",
|
|
7802
7952
|
overflow: expanded ? "visible" : "hidden"
|
|
7803
7953
|
}
|
|
7804
7954
|
],
|
|
@@ -7813,7 +7963,7 @@ function VelocityStrip({
|
|
|
7813
7963
|
style: { flexDirection: "row", flex: 1, gap: 2, alignItems: "flex-end" },
|
|
7814
7964
|
children: velocities.map((v, i) => {
|
|
7815
7965
|
const zone = getVelocityZoneColor(v);
|
|
7816
|
-
const barHeightPct = Math.round(v / (maxVelocity * 1.15) * 100);
|
|
7966
|
+
const barHeightPct = maxVelocity > 0 ? Math.round(v / (maxVelocity * 1.15) * 100) : 0;
|
|
7817
7967
|
const bar = /* @__PURE__ */ jsxs(
|
|
7818
7968
|
reactNative.View,
|
|
7819
7969
|
{
|
|
@@ -7822,9 +7972,9 @@ function VelocityStrip({
|
|
|
7822
7972
|
expanded && /* @__PURE__ */ jsx(reactNative.Animated.View, { style: { opacity: labelOpacity, alignItems: "center", position: "absolute", top: -13, left: 0, right: 0 }, accessibilityElementsHidden: true, children: /* @__PURE__ */ jsx(
|
|
7823
7973
|
reactNative.Text,
|
|
7824
7974
|
{
|
|
7825
|
-
style: { fontSize: 8, fontWeight: "600", color: "
|
|
7975
|
+
style: { fontSize: 8, fontWeight: "600", color: "var(--color-text-secondary)" },
|
|
7826
7976
|
testID: `velocity-label-${i}`,
|
|
7827
|
-
children: v
|
|
7977
|
+
children: formatVelocity(v)
|
|
7828
7978
|
}
|
|
7829
7979
|
) }),
|
|
7830
7980
|
/* @__PURE__ */ jsx(
|
|
@@ -7840,7 +7990,7 @@ function VelocityStrip({
|
|
|
7840
7990
|
},
|
|
7841
7991
|
testID: `velocity-bar-${i}`,
|
|
7842
7992
|
accessibilityRole: "image",
|
|
7843
|
-
accessibilityLabel: `Rep ${i + 1}: ${v
|
|
7993
|
+
accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second`
|
|
7844
7994
|
}
|
|
7845
7995
|
)
|
|
7846
7996
|
]
|
|
@@ -7854,7 +8004,7 @@ function VelocityStrip({
|
|
|
7854
8004
|
style: { flex: 1, height: "100%" },
|
|
7855
8005
|
onPress: () => onRepPress(i, v),
|
|
7856
8006
|
accessibilityRole: "button",
|
|
7857
|
-
accessibilityLabel: `Rep ${i + 1}: ${v
|
|
8007
|
+
accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second, tap for details`,
|
|
7858
8008
|
testID: `velocity-bar-pressable-${i}`,
|
|
7859
8009
|
children: bar
|
|
7860
8010
|
},
|
|
@@ -7884,7 +8034,7 @@ function VelocityStrip({
|
|
|
7884
8034
|
{
|
|
7885
8035
|
style: {
|
|
7886
8036
|
fontSize: 10,
|
|
7887
|
-
color: "
|
|
8037
|
+
color: "var(--color-text-secondary)",
|
|
7888
8038
|
fontFamily: "Inter, sans-serif"
|
|
7889
8039
|
},
|
|
7890
8040
|
children: [
|
|
@@ -7892,7 +8042,7 @@ function VelocityStrip({
|
|
|
7892
8042
|
" ",
|
|
7893
8043
|
"\xB7",
|
|
7894
8044
|
" ",
|
|
7895
|
-
meanVelocity
|
|
8045
|
+
formatVelocity(meanVelocity),
|
|
7896
8046
|
" m/s"
|
|
7897
8047
|
]
|
|
7898
8048
|
}
|
|
@@ -7902,7 +8052,7 @@ function VelocityStrip({
|
|
|
7902
8052
|
{
|
|
7903
8053
|
style: {
|
|
7904
8054
|
fontSize: 10,
|
|
7905
|
-
color: "
|
|
8055
|
+
color: "var(--color-text-secondary)",
|
|
7906
8056
|
fontFamily: "Inter, sans-serif",
|
|
7907
8057
|
...getLossStyle(loss)
|
|
7908
8058
|
},
|
|
@@ -8163,15 +8313,9 @@ function Sparkline({
|
|
|
8163
8313
|
}
|
|
8164
8314
|
);
|
|
8165
8315
|
}
|
|
8166
|
-
function getRPEColor(rpe) {
|
|
8167
|
-
if (rpe >= 9.5) return "#ff4757";
|
|
8168
|
-
if (rpe >= 8.5) return "#ffa502";
|
|
8169
|
-
if (rpe >= 7) return "#ffd43b";
|
|
8170
|
-
return "#2ed573";
|
|
8171
|
-
}
|
|
8172
8316
|
function formatAccessibilityLabel(setNumber, reps, weight, unit) {
|
|
8173
8317
|
const repsText = reps != null ? `${reps} reps` : "no reps";
|
|
8174
|
-
const weightText = weight != null ? `at ${weight} ${unit}` : "";
|
|
8318
|
+
const weightText = weight != null ? `at ${roundWeight(weight)} ${unit}` : "";
|
|
8175
8319
|
return `Set ${setNumber}: ${repsText}${weightText ? ` ${weightText}` : ""}`;
|
|
8176
8320
|
}
|
|
8177
8321
|
function SetRow({
|
|
@@ -8249,7 +8393,7 @@ function SetRow({
|
|
|
8249
8393
|
fontSize: 13,
|
|
8250
8394
|
fontWeight: "600",
|
|
8251
8395
|
fontFamily: "Inter, sans-serif",
|
|
8252
|
-
color: "
|
|
8396
|
+
color: "var(--color-text-secondary)"
|
|
8253
8397
|
},
|
|
8254
8398
|
children: setNumber
|
|
8255
8399
|
}
|
|
@@ -8267,9 +8411,9 @@ function SetRow({
|
|
|
8267
8411
|
style: {
|
|
8268
8412
|
fontSize: 12,
|
|
8269
8413
|
fontFamily: "Inter, sans-serif",
|
|
8270
|
-
color: "
|
|
8414
|
+
color: "var(--color-text-secondary)"
|
|
8271
8415
|
},
|
|
8272
|
-
children: previous ? `${previous.reps} x ${previous.weight}` : "\u2014"
|
|
8416
|
+
children: previous ? `${previous.reps} x ${roundWeight(previous.weight)}` : "\u2014"
|
|
8273
8417
|
}
|
|
8274
8418
|
)
|
|
8275
8419
|
}
|
|
@@ -8286,7 +8430,7 @@ function SetRow({
|
|
|
8286
8430
|
fontSize: 13,
|
|
8287
8431
|
fontStyle: "italic",
|
|
8288
8432
|
fontFamily: "Inter, sans-serif",
|
|
8289
|
-
color: "
|
|
8433
|
+
color: "var(--color-text-tertiary)"
|
|
8290
8434
|
},
|
|
8291
8435
|
testID: "set-row-target-reps",
|
|
8292
8436
|
children: targets.reps
|
|
@@ -8298,7 +8442,7 @@ function SetRow({
|
|
|
8298
8442
|
fontSize: 14,
|
|
8299
8443
|
fontWeight: "600",
|
|
8300
8444
|
fontFamily: "Inter, sans-serif",
|
|
8301
|
-
color: reps != null ? "
|
|
8445
|
+
color: reps != null ? "var(--color-text-primary)" : "var(--color-text-tertiary)"
|
|
8302
8446
|
},
|
|
8303
8447
|
children: reps != null ? reps : "\u2014"
|
|
8304
8448
|
}
|
|
@@ -8317,10 +8461,10 @@ function SetRow({
|
|
|
8317
8461
|
fontSize: 13,
|
|
8318
8462
|
fontStyle: "italic",
|
|
8319
8463
|
fontFamily: "Inter, sans-serif",
|
|
8320
|
-
color: "
|
|
8464
|
+
color: "var(--color-text-tertiary)"
|
|
8321
8465
|
},
|
|
8322
8466
|
testID: "set-row-target-weight",
|
|
8323
|
-
children: targets.weight
|
|
8467
|
+
children: roundWeight(targets.weight)
|
|
8324
8468
|
}
|
|
8325
8469
|
) : /* @__PURE__ */ jsx(
|
|
8326
8470
|
reactNative.Text,
|
|
@@ -8329,9 +8473,9 @@ function SetRow({
|
|
|
8329
8473
|
fontSize: 14,
|
|
8330
8474
|
fontWeight: "600",
|
|
8331
8475
|
fontFamily: "Inter, sans-serif",
|
|
8332
|
-
color: weight != null ? "
|
|
8476
|
+
color: weight != null ? "var(--color-text-primary)" : "var(--color-text-tertiary)"
|
|
8333
8477
|
},
|
|
8334
|
-
children: weight != null ? weight : "\u2014"
|
|
8478
|
+
children: weight != null ? roundWeight(weight) : "\u2014"
|
|
8335
8479
|
}
|
|
8336
8480
|
)
|
|
8337
8481
|
}
|
|
@@ -8348,9 +8492,9 @@ function SetRow({
|
|
|
8348
8492
|
fontSize: 13,
|
|
8349
8493
|
fontWeight: "600",
|
|
8350
8494
|
fontFamily: "Inter, sans-serif",
|
|
8351
|
-
color: rpe != null ?
|
|
8495
|
+
color: rpe != null ? rpeColor(rpe) : "var(--color-text-tertiary)"
|
|
8352
8496
|
},
|
|
8353
|
-
children: rpe != null ? rpe : "\u2014"
|
|
8497
|
+
children: rpe != null ? roundRpe(rpe) : "\u2014"
|
|
8354
8498
|
}
|
|
8355
8499
|
)
|
|
8356
8500
|
}
|
|
@@ -8394,15 +8538,15 @@ function SetRow({
|
|
|
8394
8538
|
);
|
|
8395
8539
|
}
|
|
8396
8540
|
var BRAND_PRIMARY2 = "#FF7900";
|
|
8397
|
-
var TEXT_PRIMARY = "
|
|
8398
|
-
var TEXT_TERTIARY2 = "
|
|
8541
|
+
var TEXT_PRIMARY = "var(--color-text-primary)";
|
|
8542
|
+
var TEXT_TERTIARY2 = "var(--color-text-tertiary)";
|
|
8399
8543
|
var inputStyle = {
|
|
8400
8544
|
fontSize: 14,
|
|
8401
8545
|
fontWeight: "600",
|
|
8402
8546
|
fontFamily: "Inter, sans-serif",
|
|
8403
|
-
backgroundColor:
|
|
8547
|
+
backgroundColor: "var(--color-surface-raised)",
|
|
8404
8548
|
borderWidth: 1,
|
|
8405
|
-
borderColor:
|
|
8549
|
+
borderColor: "var(--color-border-strong)",
|
|
8406
8550
|
borderRadius: 6,
|
|
8407
8551
|
textAlign: "center",
|
|
8408
8552
|
color: TEXT_PRIMARY,
|
|
@@ -8429,9 +8573,9 @@ function InputBar({
|
|
|
8429
8573
|
{
|
|
8430
8574
|
style: {
|
|
8431
8575
|
width: "100%",
|
|
8432
|
-
backgroundColor:
|
|
8576
|
+
backgroundColor: "var(--color-surface-elevated)",
|
|
8433
8577
|
borderTopWidth: 1,
|
|
8434
|
-
borderTopColor:
|
|
8578
|
+
borderTopColor: "var(--color-border-default)",
|
|
8435
8579
|
paddingTop: 10,
|
|
8436
8580
|
paddingHorizontal: 16,
|
|
8437
8581
|
paddingBottom: 12,
|
|
@@ -8566,15 +8710,16 @@ function RestTimer({
|
|
|
8566
8710
|
const minutes = Math.floor(remainingSec / 60);
|
|
8567
8711
|
const seconds = remainingSec % 60;
|
|
8568
8712
|
const timeDisplay = `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
8569
|
-
const
|
|
8713
|
+
const totalMs = totalSeconds * 1e3;
|
|
8714
|
+
const progressPct = totalMs > 0 ? Math.min(100, elapsedMs / totalMs * 100) : 100;
|
|
8570
8715
|
return /* @__PURE__ */ jsxs(
|
|
8571
8716
|
reactNative.View,
|
|
8572
8717
|
{
|
|
8573
8718
|
style: {
|
|
8574
8719
|
width: "100%",
|
|
8575
|
-
backgroundColor:
|
|
8720
|
+
backgroundColor: "var(--color-surface-raised)",
|
|
8576
8721
|
borderTopWidth: 1,
|
|
8577
|
-
borderTopColor:
|
|
8722
|
+
borderTopColor: "var(--color-border-default)",
|
|
8578
8723
|
paddingVertical: 12,
|
|
8579
8724
|
paddingHorizontal: 16
|
|
8580
8725
|
},
|
|
@@ -8602,7 +8747,7 @@ function RestTimer({
|
|
|
8602
8747
|
fontWeight: "600",
|
|
8603
8748
|
textTransform: "uppercase",
|
|
8604
8749
|
letterSpacing: 1,
|
|
8605
|
-
color: "
|
|
8750
|
+
color: "var(--color-text-secondary)"
|
|
8606
8751
|
},
|
|
8607
8752
|
testID: "rest-timer-label",
|
|
8608
8753
|
children: "REST"
|
|
@@ -8614,7 +8759,7 @@ function RestTimer({
|
|
|
8614
8759
|
style: {
|
|
8615
8760
|
fontSize: 11,
|
|
8616
8761
|
fontFamily: "Inter, sans-serif",
|
|
8617
|
-
color: "
|
|
8762
|
+
color: "var(--color-text-tertiary)",
|
|
8618
8763
|
marginTop: 2
|
|
8619
8764
|
},
|
|
8620
8765
|
testID: "rest-timer-next-set",
|
|
@@ -8629,7 +8774,7 @@ function RestTimer({
|
|
|
8629
8774
|
fontSize: 28,
|
|
8630
8775
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
8631
8776
|
fontWeight: "700",
|
|
8632
|
-
color: "
|
|
8777
|
+
color: "var(--color-text-primary)",
|
|
8633
8778
|
fontVariant: ["tabular-nums"],
|
|
8634
8779
|
letterSpacing: -0.5
|
|
8635
8780
|
},
|
|
@@ -8645,7 +8790,7 @@ function RestTimer({
|
|
|
8645
8790
|
{
|
|
8646
8791
|
style: {
|
|
8647
8792
|
height: 3,
|
|
8648
|
-
backgroundColor:
|
|
8793
|
+
backgroundColor: "var(--color-border-default)",
|
|
8649
8794
|
borderRadius: 2,
|
|
8650
8795
|
marginBottom: 12
|
|
8651
8796
|
},
|
|
@@ -8685,7 +8830,7 @@ function RestTimer({
|
|
|
8685
8830
|
fontSize: 11,
|
|
8686
8831
|
fontFamily: "Inter, sans-serif",
|
|
8687
8832
|
fontWeight: "600",
|
|
8688
|
-
color: "
|
|
8833
|
+
color: "var(--color-text-secondary)"
|
|
8689
8834
|
},
|
|
8690
8835
|
children: "+30s"
|
|
8691
8836
|
}
|
|
@@ -8725,10 +8870,21 @@ function RestTimer({
|
|
|
8725
8870
|
);
|
|
8726
8871
|
}
|
|
8727
8872
|
var COLORS = {
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8873
|
+
// Theme-aware tokens: text foregrounds and this card's own surfaces/borders
|
|
8874
|
+
// must flip together so text stays readable in both light and dark. The
|
|
8875
|
+
// expanded/pressed surfaces are self-owned here (not from a themed Card), so
|
|
8876
|
+
// hardcoding dark values would leave dark-on-dark once the text flips.
|
|
8877
|
+
// react-native-web passes the CSS var through to the inline style.
|
|
8878
|
+
textPrimary: "var(--color-text-primary)",
|
|
8879
|
+
textSecondary: "var(--color-text-secondary)",
|
|
8880
|
+
textTertiary: "var(--color-text-tertiary)",
|
|
8881
|
+
surfaceRaised: "var(--color-surface-raised)",
|
|
8882
|
+
surfaceElevated: "var(--color-surface-elevated)",
|
|
8883
|
+
borderDefault: "var(--color-border-default)"
|
|
8884
|
+
};
|
|
8885
|
+
function buildColumnHeaders(unit) {
|
|
8886
|
+
return ["SET", "PREV", "REPS", unit.toUpperCase(), "RPE"];
|
|
8887
|
+
}
|
|
8732
8888
|
function getSupersetBorderRadius(position) {
|
|
8733
8889
|
switch (position) {
|
|
8734
8890
|
case "first":
|
|
@@ -8769,7 +8925,7 @@ function getSupersetMargin(position) {
|
|
|
8769
8925
|
}
|
|
8770
8926
|
function formatSummary(summary) {
|
|
8771
8927
|
if (!summary) return "";
|
|
8772
|
-
return `${summary.sets}\xD7${summary.reps} @ ${summary.weight} ${summary.unit}`;
|
|
8928
|
+
return `${summary.sets}\xD7${summary.reps} @ ${roundWeight(summary.weight)} ${summary.unit}`;
|
|
8773
8929
|
}
|
|
8774
8930
|
function formatAccessibilityLabel2(name, summary, prescription) {
|
|
8775
8931
|
if (summary) return `${name}, ${formatSummary(summary)}`;
|
|
@@ -8807,7 +8963,7 @@ function CollapsedCard({
|
|
|
8807
8963
|
padding: 12,
|
|
8808
8964
|
paddingHorizontal: 14,
|
|
8809
8965
|
cursor: "pointer",
|
|
8810
|
-
backgroundColor: pressed ?
|
|
8966
|
+
backgroundColor: pressed ? COLORS.surfaceRaised : "transparent",
|
|
8811
8967
|
...borderRadius,
|
|
8812
8968
|
...supersetMargin
|
|
8813
8969
|
},
|
|
@@ -8848,7 +9004,7 @@ function CollapsedCard({
|
|
|
8848
9004
|
e1rm && /* @__PURE__ */ jsx(
|
|
8849
9005
|
WeightBadge,
|
|
8850
9006
|
{
|
|
8851
|
-
value: e1rm.value,
|
|
9007
|
+
value: roundWeight(e1rm.value),
|
|
8852
9008
|
unit: e1rm.unit,
|
|
8853
9009
|
size: "sm",
|
|
8854
9010
|
showIcon: false,
|
|
@@ -8903,13 +9059,15 @@ function ExpandedCard({
|
|
|
8903
9059
|
}) {
|
|
8904
9060
|
const borderRadius = getSupersetBorderRadius(supersetPosition);
|
|
8905
9061
|
const supersetMargin = getSupersetMargin(supersetPosition);
|
|
9062
|
+
const unit = summary?.unit ?? sets?.[0]?.unit ?? "lbs";
|
|
9063
|
+
const columnHeaders = buildColumnHeaders(unit);
|
|
8906
9064
|
return /* @__PURE__ */ jsxs(
|
|
8907
9065
|
reactNative.View,
|
|
8908
9066
|
{
|
|
8909
9067
|
style: {
|
|
8910
|
-
backgroundColor:
|
|
9068
|
+
backgroundColor: COLORS.surfaceElevated,
|
|
8911
9069
|
borderWidth: 1,
|
|
8912
|
-
borderColor:
|
|
9070
|
+
borderColor: COLORS.borderDefault,
|
|
8913
9071
|
...borderRadius,
|
|
8914
9072
|
...supersetMargin
|
|
8915
9073
|
},
|
|
@@ -8932,7 +9090,7 @@ function ExpandedCard({
|
|
|
8932
9090
|
paddingHorizontal: 14,
|
|
8933
9091
|
paddingBottom: 10,
|
|
8934
9092
|
borderBottomWidth: 1,
|
|
8935
|
-
borderBottomColor:
|
|
9093
|
+
borderBottomColor: COLORS.borderDefault
|
|
8936
9094
|
},
|
|
8937
9095
|
children: [
|
|
8938
9096
|
/* @__PURE__ */ jsx(
|
|
@@ -8965,7 +9123,7 @@ function ExpandedCard({
|
|
|
8965
9123
|
e1rm && /* @__PURE__ */ jsx(
|
|
8966
9124
|
WeightBadge,
|
|
8967
9125
|
{
|
|
8968
|
-
value: e1rm.value,
|
|
9126
|
+
value: roundWeight(e1rm.value),
|
|
8969
9127
|
unit: e1rm.unit,
|
|
8970
9128
|
size: "sm",
|
|
8971
9129
|
showIcon: false,
|
|
@@ -8989,7 +9147,7 @@ function ExpandedCard({
|
|
|
8989
9147
|
paddingBottom: 4
|
|
8990
9148
|
},
|
|
8991
9149
|
testID: "exercise-card-column-headers",
|
|
8992
|
-
children:
|
|
9150
|
+
children: columnHeaders.map((header, i) => {
|
|
8993
9151
|
const widths = [36, void 0, 44, 56, 36];
|
|
8994
9152
|
const width = widths[i];
|
|
8995
9153
|
const isFlex = width === void 0;
|
|
@@ -9183,10 +9341,11 @@ function MesoSegment({ meso, isActive, onPress }) {
|
|
|
9183
9341
|
}).start();
|
|
9184
9342
|
};
|
|
9185
9343
|
const progress = meso.status === "current" ? clampProgress(meso.currentWeek, meso.weekCount) : 0;
|
|
9344
|
+
const segmentFlex = Math.max(1, meso.weekCount);
|
|
9186
9345
|
return /* @__PURE__ */ jsx(
|
|
9187
9346
|
reactNative.Pressable,
|
|
9188
9347
|
{
|
|
9189
|
-
style: { flex:
|
|
9348
|
+
style: { flex: segmentFlex },
|
|
9190
9349
|
onPress: () => onPress(meso.id),
|
|
9191
9350
|
onPressIn: handlePressIn,
|
|
9192
9351
|
onPressOut: handlePressOut,
|
|
@@ -9323,7 +9482,7 @@ function WeekRow({
|
|
|
9323
9482
|
fontSize: 13,
|
|
9324
9483
|
fontWeight: "700",
|
|
9325
9484
|
fontFamily: "Inter, sans-serif",
|
|
9326
|
-
color: isCurrent ? BRAND_PRIMARY5 : "
|
|
9485
|
+
color: isCurrent ? BRAND_PRIMARY5 : "var(--color-text-primary)"
|
|
9327
9486
|
},
|
|
9328
9487
|
accessibilityElementsHidden: true,
|
|
9329
9488
|
children: `W${weekNumber}`
|
|
@@ -9363,9 +9522,11 @@ function WeekRow({
|
|
|
9363
9522
|
);
|
|
9364
9523
|
}
|
|
9365
9524
|
var COLORS2 = {
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9525
|
+
// Theme-aware foregrounds: resolve to a readable color in both light and dark
|
|
9526
|
+
// (react-native-web passes the CSS var through to the inline style).
|
|
9527
|
+
textPrimary: "var(--color-text-primary)",
|
|
9528
|
+
textSecondary: "var(--color-text-secondary)",
|
|
9529
|
+
textTertiary: "var(--color-text-tertiary)",
|
|
9369
9530
|
statusSuccess: "#14B8A6",
|
|
9370
9531
|
brandPrimary: "#FF7900",
|
|
9371
9532
|
borderDefault: "#1F1F1F",
|
|
@@ -9513,8 +9674,8 @@ var BRAND_PRIMARY6 = "#FF7900";
|
|
|
9513
9674
|
var BRAND_PRIMARY_DARK = "#C45E00";
|
|
9514
9675
|
var BRAND_PRIMARY_LIGHT = "#FFB066";
|
|
9515
9676
|
var BORDER_DEFAULT = "#1F1F1F";
|
|
9516
|
-
var TEXT_PRIMARY2 = "
|
|
9517
|
-
var TEXT_SECONDARY = "
|
|
9677
|
+
var TEXT_PRIMARY2 = "var(--color-text-primary)";
|
|
9678
|
+
var TEXT_SECONDARY = "var(--color-text-secondary)";
|
|
9518
9679
|
var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY6, BRAND_PRIMARY_LIGHT];
|
|
9519
9680
|
function heatmapColor(percentage) {
|
|
9520
9681
|
const clamped = Math.max(0, Math.min(100, percentage));
|
|
@@ -9670,11 +9831,11 @@ function MesoCard({
|
|
|
9670
9831
|
var BRAND_PRIMARY7 = "#FF7900";
|
|
9671
9832
|
var RECENT_BORDER = "rgba(255,176,32,0.3)";
|
|
9672
9833
|
var RECENT_GLOW = "0 0 12px rgba(255,176,32,0.06)";
|
|
9673
|
-
var SURFACE_RAISED = "
|
|
9674
|
-
var BORDER_DEFAULT2 = "
|
|
9675
|
-
var TEXT_PRIMARY3 = "
|
|
9676
|
-
var TEXT_SECONDARY2 = "
|
|
9677
|
-
var TEXT_TERTIARY3 = "
|
|
9834
|
+
var SURFACE_RAISED = "var(--color-surface-raised)";
|
|
9835
|
+
var BORDER_DEFAULT2 = "var(--color-border-default)";
|
|
9836
|
+
var TEXT_PRIMARY3 = "var(--color-text-primary)";
|
|
9837
|
+
var TEXT_SECONDARY2 = "var(--color-text-secondary)";
|
|
9838
|
+
var TEXT_TERTIARY3 = "var(--color-text-tertiary)";
|
|
9678
9839
|
var TYPE_LABELS = {
|
|
9679
9840
|
e1rm: "e1RM",
|
|
9680
9841
|
weight: "Weight",
|
|
@@ -9863,8 +10024,8 @@ var BRAND_PRIMARY_SUBTLE = "rgba(255,121,0,0.12)";
|
|
|
9863
10024
|
var STATUS_SUCCESS = "#14B8A6";
|
|
9864
10025
|
var STATUS_WARNING = "#FFB020";
|
|
9865
10026
|
var STATUS_ERROR = "#D14343";
|
|
9866
|
-
var TEXT_PRIMARY4 = "
|
|
9867
|
-
var TEXT_SECONDARY3 = "
|
|
10027
|
+
var TEXT_PRIMARY4 = "var(--color-text-primary)";
|
|
10028
|
+
var TEXT_SECONDARY3 = "var(--color-text-secondary)";
|
|
9868
10029
|
var EMOJI_SETS = {
|
|
9869
10030
|
sleep: ["\u{1F634}", "\u{1F610}", "\u{1F642}", "\u{1F60A}", "\u{1F929}"],
|
|
9870
10031
|
soreness: ["\u{1F635}", "\u{1F623}", "\u{1F610}", "\u{1F642}", "\u{1F4AA}"],
|
|
@@ -9926,8 +10087,8 @@ function EmojiSlider({ factor }) {
|
|
|
9926
10087
|
paddingVertical: 8,
|
|
9927
10088
|
borderRadius: 8,
|
|
9928
10089
|
borderWidth: 1,
|
|
9929
|
-
borderColor: selected ? BRAND_PRIMARY8 :
|
|
9930
|
-
backgroundColor: selected ? BRAND_PRIMARY_SUBTLE :
|
|
10090
|
+
borderColor: selected ? BRAND_PRIMARY8 : "var(--color-border-default)",
|
|
10091
|
+
backgroundColor: selected ? BRAND_PRIMARY_SUBTLE : "var(--color-surface-raised)",
|
|
9931
10092
|
opacity: selected ? 1 : pressed ? 0.8 : 0.55,
|
|
9932
10093
|
transform: [{ scale: selected ? 1.06 : 1 }]
|
|
9933
10094
|
}),
|
|
@@ -9954,7 +10115,7 @@ function ScoreGauge({ score }) {
|
|
|
9954
10115
|
borderRadius: 30,
|
|
9955
10116
|
borderWidth: 4,
|
|
9956
10117
|
borderColor: color,
|
|
9957
|
-
backgroundColor:
|
|
10118
|
+
backgroundColor: "var(--color-surface-raised)",
|
|
9958
10119
|
alignItems: "center",
|
|
9959
10120
|
justifyContent: "center"
|
|
9960
10121
|
},
|
|
@@ -9979,8 +10140,8 @@ function WarmUpCard({ validation }) {
|
|
|
9979
10140
|
padding: 12,
|
|
9980
10141
|
borderRadius: 8,
|
|
9981
10142
|
borderWidth: 1,
|
|
9982
|
-
borderColor:
|
|
9983
|
-
backgroundColor:
|
|
10143
|
+
borderColor: "var(--color-border-default)",
|
|
10144
|
+
backgroundColor: "var(--color-surface-raised)"
|
|
9984
10145
|
},
|
|
9985
10146
|
testID: "readiness-check-warmup",
|
|
9986
10147
|
children: [
|
|
@@ -10053,14 +10214,14 @@ function ReadinessCheck({
|
|
|
10053
10214
|
var BRAND_PRIMARY9 = "#FF7900";
|
|
10054
10215
|
var BRAND_PRIMARY_DARK2 = "#C45E00";
|
|
10055
10216
|
var BRAND_PRIMARY_LIGHT2 = "#FFB066";
|
|
10056
|
-
var TEXT_PRIMARY5 = "
|
|
10057
|
-
var TEXT_SECONDARY4 = "
|
|
10058
|
-
var TEXT_TERTIARY4 = "
|
|
10217
|
+
var TEXT_PRIMARY5 = "var(--color-text-primary)";
|
|
10218
|
+
var TEXT_SECONDARY4 = "var(--color-text-secondary)";
|
|
10219
|
+
var TEXT_TERTIARY4 = "var(--color-text-tertiary)";
|
|
10059
10220
|
var SUCCESS = "#14B8A6";
|
|
10060
10221
|
var WARNING = "#FFB020";
|
|
10061
10222
|
var ERROR = "#D14343";
|
|
10062
10223
|
var ACCENT_STOPS2 = [BRAND_PRIMARY_DARK2, BRAND_PRIMARY9, BRAND_PRIMARY_LIGHT2];
|
|
10063
|
-
var CARD_GRADIENT = "linear-gradient(135deg,
|
|
10224
|
+
var CARD_GRADIENT = "linear-gradient(135deg, var(--color-surface-elevated) 0%, var(--color-surface-raised) 100%)";
|
|
10064
10225
|
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%)";
|
|
10065
10226
|
var STATUS_VARIANTS = {
|
|
10066
10227
|
success: { bg: "rgba(20,184,166,0.15)", border: "rgba(20,184,166,0.3)", text: SUCCESS },
|
|
@@ -10415,15 +10576,15 @@ function MesoStatusCard({
|
|
|
10415
10576
|
);
|
|
10416
10577
|
}
|
|
10417
10578
|
var BRAND_PRIMARY10 = "#FF7900";
|
|
10418
|
-
var TEXT_PRIMARY6 = "
|
|
10419
|
-
var TEXT_SECONDARY5 = "
|
|
10420
|
-
var TEXT_TERTIARY5 = "
|
|
10421
|
-
var BORDER_STRONG = "
|
|
10579
|
+
var TEXT_PRIMARY6 = "var(--color-text-primary)";
|
|
10580
|
+
var TEXT_SECONDARY5 = "var(--color-text-secondary)";
|
|
10581
|
+
var TEXT_TERTIARY5 = "var(--color-text-tertiary)";
|
|
10582
|
+
var BORDER_STRONG = "var(--color-border-strong)";
|
|
10422
10583
|
var STATUS_SUCCESS2 = "#14B8A6";
|
|
10423
10584
|
var STATUS_ERROR2 = "#D14343";
|
|
10424
10585
|
var STATUS_WARNING2 = "#FFB020";
|
|
10425
10586
|
var GRID_LINE = "rgba(255,255,255,0.06)";
|
|
10426
|
-
var TOOLTIP_BG = "
|
|
10587
|
+
var TOOLTIP_BG = "var(--color-surface-elevated)";
|
|
10427
10588
|
var SUCCESS_PILL_BG = "rgba(20,184,166,0.10)";
|
|
10428
10589
|
var SUCCESS_PILL_BORDER = "rgba(20,184,166,0.20)";
|
|
10429
10590
|
var ERROR_PILL_BG = "rgba(209,67,67,0.10)";
|
|
@@ -10926,7 +11087,7 @@ var STATUS_SUCCESS3 = "#14B8A6";
|
|
|
10926
11087
|
var STATUS_WARNING3 = "#FFB020";
|
|
10927
11088
|
var STATUS_INFO = "#2196F3";
|
|
10928
11089
|
var DOT_BORDER = "#F3F4F6";
|
|
10929
|
-
var TEXT_TERTIARY6 = "
|
|
11090
|
+
var TEXT_TERTIARY6 = "var(--color-text-tertiary)";
|
|
10930
11091
|
var BAND_FILL = "rgba(20,184,166,0.1)";
|
|
10931
11092
|
var BAND_EDGE = "rgba(20,184,166,0.45)";
|
|
10932
11093
|
var PROJECTION_FILL = "rgba(20,184,166,0.05)";
|
|
@@ -11299,847 +11460,674 @@ function CapacityBandChart({
|
|
|
11299
11460
|
}
|
|
11300
11461
|
);
|
|
11301
11462
|
}
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
var
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
SimpleMuscleGroup3["SHOULDERS"] = "shoulders";
|
|
11326
|
-
SimpleMuscleGroup3["BICEPS"] = "biceps";
|
|
11327
|
-
SimpleMuscleGroup3["TRICEPS"] = "triceps";
|
|
11328
|
-
SimpleMuscleGroup3["LEGS"] = "legs";
|
|
11329
|
-
SimpleMuscleGroup3["CORE"] = "core";
|
|
11330
|
-
SimpleMuscleGroup3["FOREARMS"] = "forearms";
|
|
11331
|
-
return SimpleMuscleGroup3;
|
|
11332
|
-
})(SimpleMuscleGroup || {});
|
|
11333
|
-
var SIMPLE_TO_DETAILED = {
|
|
11334
|
-
["chest" /* CHEST */]: ["chest" /* CHEST */],
|
|
11335
|
-
["back" /* BACK */]: ["lats" /* LATS */, "upper_back" /* UPPER_BACK */],
|
|
11336
|
-
["shoulders" /* SHOULDERS */]: [
|
|
11337
|
-
"front_delts" /* FRONT_DELTS */,
|
|
11338
|
-
"side_delts" /* SIDE_DELTS */,
|
|
11339
|
-
"rear_delts" /* REAR_DELTS */
|
|
11340
|
-
],
|
|
11341
|
-
["biceps" /* BICEPS */]: ["biceps" /* BICEPS */],
|
|
11342
|
-
["triceps" /* TRICEPS */]: ["triceps" /* TRICEPS */],
|
|
11343
|
-
["legs" /* LEGS */]: [
|
|
11344
|
-
"quads" /* QUADS */,
|
|
11345
|
-
"hamstrings" /* HAMSTRINGS */,
|
|
11346
|
-
"glutes" /* GLUTES */,
|
|
11347
|
-
"calves" /* CALVES */
|
|
11348
|
-
],
|
|
11349
|
-
["core" /* CORE */]: ["abs" /* ABS */, "obliques" /* OBLIQUES */],
|
|
11350
|
-
["forearms" /* FOREARMS */]: ["forearms" /* FOREARMS */]
|
|
11351
|
-
};
|
|
11352
|
-
var DETAILED_TO_SIMPLE = Object.entries(
|
|
11353
|
-
SIMPLE_TO_DETAILED
|
|
11354
|
-
).reduce(
|
|
11355
|
-
(acc, [simple, groups]) => {
|
|
11356
|
-
for (const group of groups) {
|
|
11357
|
-
acc[group] = simple;
|
|
11358
|
-
}
|
|
11359
|
-
return acc;
|
|
11360
|
-
},
|
|
11361
|
-
{}
|
|
11362
|
-
);
|
|
11363
|
-
var MUSCLE_TO_CATEGORY = {
|
|
11364
|
-
["chest" /* CHEST */]: "push",
|
|
11365
|
-
["front_delts" /* FRONT_DELTS */]: "push",
|
|
11366
|
-
["side_delts" /* SIDE_DELTS */]: "push",
|
|
11367
|
-
["triceps" /* TRICEPS */]: "push",
|
|
11368
|
-
["lats" /* LATS */]: "pull",
|
|
11369
|
-
["upper_back" /* UPPER_BACK */]: "pull",
|
|
11370
|
-
["rear_delts" /* REAR_DELTS */]: "pull",
|
|
11371
|
-
["biceps" /* BICEPS */]: "pull",
|
|
11372
|
-
["forearms" /* FOREARMS */]: "pull",
|
|
11373
|
-
["quads" /* QUADS */]: "legs",
|
|
11374
|
-
["hamstrings" /* HAMSTRINGS */]: "legs",
|
|
11375
|
-
["glutes" /* GLUTES */]: "legs",
|
|
11376
|
-
["calves" /* CALVES */]: "legs",
|
|
11377
|
-
["abs" /* ABS */]: "core",
|
|
11378
|
-
["obliques" /* OBLIQUES */]: "core"
|
|
11379
|
-
};
|
|
11380
|
-
var MUSCLE_TO_SVG_SLUGS = {
|
|
11381
|
-
["chest" /* CHEST */]: ["chest"],
|
|
11382
|
-
["front_delts" /* FRONT_DELTS */]: ["deltoids"],
|
|
11383
|
-
["side_delts" /* SIDE_DELTS */]: ["deltoids"],
|
|
11384
|
-
["rear_delts" /* REAR_DELTS */]: ["deltoids"],
|
|
11385
|
-
["triceps" /* TRICEPS */]: ["triceps"],
|
|
11386
|
-
["lats" /* LATS */]: ["upper-back"],
|
|
11387
|
-
["upper_back" /* UPPER_BACK */]: ["upper-back", "trapezius"],
|
|
11388
|
-
["biceps" /* BICEPS */]: ["biceps"],
|
|
11389
|
-
["forearms" /* FOREARMS */]: ["forearm"],
|
|
11390
|
-
["quads" /* QUADS */]: ["quadriceps"],
|
|
11391
|
-
["hamstrings" /* HAMSTRINGS */]: ["hamstring"],
|
|
11392
|
-
["glutes" /* GLUTES */]: ["gluteal"],
|
|
11393
|
-
["calves" /* CALVES */]: ["calves"],
|
|
11394
|
-
["abs" /* ABS */]: ["abs"],
|
|
11395
|
-
["obliques" /* OBLIQUES */]: ["obliques"]
|
|
11396
|
-
};
|
|
11397
|
-
var MUSCLE_DISPLAY_NAMES = {
|
|
11398
|
-
["chest" /* CHEST */]: "Chest",
|
|
11399
|
-
["front_delts" /* FRONT_DELTS */]: "Front Delts",
|
|
11400
|
-
["side_delts" /* SIDE_DELTS */]: "Side Delts",
|
|
11401
|
-
["rear_delts" /* REAR_DELTS */]: "Rear Delts",
|
|
11402
|
-
["triceps" /* TRICEPS */]: "Triceps",
|
|
11403
|
-
["lats" /* LATS */]: "Lats",
|
|
11404
|
-
["upper_back" /* UPPER_BACK */]: "Upper Back",
|
|
11405
|
-
["biceps" /* BICEPS */]: "Biceps",
|
|
11406
|
-
["forearms" /* FOREARMS */]: "Forearms",
|
|
11407
|
-
["quads" /* QUADS */]: "Quads",
|
|
11408
|
-
["hamstrings" /* HAMSTRINGS */]: "Hamstrings",
|
|
11409
|
-
["glutes" /* GLUTES */]: "Glutes",
|
|
11410
|
-
["calves" /* CALVES */]: "Calves",
|
|
11411
|
-
["abs" /* ABS */]: "Abs",
|
|
11412
|
-
["obliques" /* OBLIQUES */]: "Obliques"
|
|
11413
|
-
};
|
|
11414
|
-
var SIMPLE_DISPLAY_NAMES = {
|
|
11415
|
-
["chest" /* CHEST */]: "Chest",
|
|
11416
|
-
["back" /* BACK */]: "Back",
|
|
11417
|
-
["shoulders" /* SHOULDERS */]: "Shoulders",
|
|
11418
|
-
["biceps" /* BICEPS */]: "Biceps",
|
|
11419
|
-
["triceps" /* TRICEPS */]: "Triceps",
|
|
11420
|
-
["legs" /* LEGS */]: "Legs",
|
|
11421
|
-
["core" /* CORE */]: "Core",
|
|
11422
|
-
["forearms" /* FOREARMS */]: "Forearms"
|
|
11423
|
-
};
|
|
11424
|
-
var DEFAULT_VOLUME_LANDMARKS = {
|
|
11425
|
-
["chest" /* CHEST */]: { mev: 8, mav: 14, mrv: 20 },
|
|
11426
|
-
["lats" /* LATS */]: { mev: 8, mav: 14, mrv: 20 },
|
|
11427
|
-
["upper_back" /* UPPER_BACK */]: { mev: 6, mav: 12, mrv: 18 },
|
|
11428
|
-
["front_delts" /* FRONT_DELTS */]: { mev: 2, mav: 6, mrv: 10 },
|
|
11429
|
-
["side_delts" /* SIDE_DELTS */]: { mev: 6, mav: 14, mrv: 22 },
|
|
11430
|
-
["rear_delts" /* REAR_DELTS */]: { mev: 6, mav: 12, mrv: 18 },
|
|
11431
|
-
["biceps" /* BICEPS */]: { mev: 4, mav: 10, mrv: 18 },
|
|
11432
|
-
["triceps" /* TRICEPS */]: { mev: 4, mav: 8, mrv: 14 },
|
|
11433
|
-
["forearms" /* FOREARMS */]: { mev: 2, mav: 6, mrv: 12 },
|
|
11434
|
-
["quads" /* QUADS */]: { mev: 6, mav: 12, mrv: 18 },
|
|
11435
|
-
["hamstrings" /* HAMSTRINGS */]: { mev: 4, mav: 10, mrv: 16 },
|
|
11436
|
-
["glutes" /* GLUTES */]: { mev: 4, mav: 10, mrv: 16 },
|
|
11437
|
-
["calves" /* CALVES */]: { mev: 6, mav: 10, mrv: 16 },
|
|
11438
|
-
["abs" /* ABS */]: { mev: 0, mav: 8, mrv: 16 },
|
|
11439
|
-
["obliques" /* OBLIQUES */]: { mev: 0, mav: 6, mrv: 12 }
|
|
11440
|
-
};
|
|
11441
|
-
var VOLUME_STATUS_LABELS = {
|
|
11442
|
-
under: "under-trained",
|
|
11443
|
-
maintenance: "maintenance",
|
|
11444
|
-
productive: "productive",
|
|
11445
|
-
over: "over-reaching"
|
|
11446
|
-
};
|
|
11447
|
-
var STATUS_SEVERITY = {
|
|
11448
|
-
under: 1,
|
|
11449
|
-
maintenance: 2,
|
|
11450
|
-
productive: 3,
|
|
11451
|
-
over: 4
|
|
11452
|
-
};
|
|
11453
|
-
function getHeatmapColor(status, intensity = 0) {
|
|
11454
|
-
const heatmap = WORKOUT_TOKENS.heatmap;
|
|
11455
|
-
switch (status) {
|
|
11456
|
-
case "under":
|
|
11457
|
-
return heatmap.under;
|
|
11458
|
-
case "maintenance":
|
|
11459
|
-
return heatmap.maintenance;
|
|
11460
|
-
case "productive":
|
|
11461
|
-
return intensity >= 0.85 ? heatmap.approaching : heatmap.productive;
|
|
11462
|
-
case "over":
|
|
11463
|
-
return heatmap.over;
|
|
11464
|
-
default:
|
|
11465
|
-
return heatmap.none;
|
|
11466
|
-
}
|
|
11467
|
-
}
|
|
11468
|
-
function isMoreSevere(a, b) {
|
|
11469
|
-
return STATUS_SEVERITY[a] >= STATUS_SEVERITY[b];
|
|
11470
|
-
}
|
|
11471
|
-
var SLUG_TO_PRIMARY_MUSCLE = {
|
|
11472
|
-
chest: "chest" /* CHEST */,
|
|
11473
|
-
deltoids: "side_delts" /* SIDE_DELTS */,
|
|
11474
|
-
triceps: "triceps" /* TRICEPS */,
|
|
11475
|
-
"upper-back": "lats" /* LATS */,
|
|
11476
|
-
trapezius: "upper_back" /* UPPER_BACK */,
|
|
11477
|
-
biceps: "biceps" /* BICEPS */,
|
|
11478
|
-
forearm: "forearms" /* FOREARMS */,
|
|
11479
|
-
quadriceps: "quads" /* QUADS */,
|
|
11480
|
-
hamstring: "hamstrings" /* HAMSTRINGS */,
|
|
11481
|
-
gluteal: "glutes" /* GLUTES */,
|
|
11482
|
-
calves: "calves" /* CALVES */,
|
|
11483
|
-
abs: "abs" /* ABS */,
|
|
11484
|
-
obliques: "obliques" /* OBLIQUES */
|
|
11485
|
-
};
|
|
11486
|
-
|
|
11487
|
-
// src/components/custom/Workout/BodyMap.tsx
|
|
11488
|
-
var Body = BodyHighlighter__default.default.default ?? BodyHighlighter__default.default;
|
|
11489
|
-
var OUTLINE_FILL = "rgba(255,255,255,0.08)";
|
|
11490
|
-
var OUTLINE_BORDER = "rgba(255,255,255,0.12)";
|
|
11491
|
-
var BODY_SCALE = 0.8;
|
|
11492
|
-
var TEXT_PRIMARY7 = "#F3F4F6";
|
|
11493
|
-
var TEXT_SECONDARY6 = "#9CA3AF";
|
|
11494
|
-
function buildSlugParts(data) {
|
|
11495
|
-
const bySlug = /* @__PURE__ */ new Map();
|
|
11496
|
-
for (const d of data) {
|
|
11497
|
-
for (const slug of MUSCLE_TO_SVG_SLUGS[d.muscleGroup] ?? []) {
|
|
11498
|
-
const existing = bySlug.get(slug);
|
|
11499
|
-
if (!existing || isMoreSevere(d.volumeStatus, existing.status)) {
|
|
11500
|
-
bySlug.set(slug, { status: d.volumeStatus, intensity: d.intensity });
|
|
11501
|
-
}
|
|
11502
|
-
}
|
|
11503
|
-
}
|
|
11504
|
-
return Array.from(bySlug.entries()).map(([slug, v]) => ({
|
|
11505
|
-
slug,
|
|
11506
|
-
color: getHeatmapColor(v.status, v.intensity)
|
|
11463
|
+
var SURFACE_ELEVATED = "var(--color-surface-elevated)";
|
|
11464
|
+
var BORDER_DEFAULT3 = "var(--color-border-default)";
|
|
11465
|
+
var BRAND_PRIMARY11 = "#FF7900";
|
|
11466
|
+
var TEXT_PRIMARY7 = "var(--color-text-primary)";
|
|
11467
|
+
var TEXT_TERTIARY7 = "var(--color-text-tertiary)";
|
|
11468
|
+
var PAGE_BG = "var(--color-background-base)";
|
|
11469
|
+
var WORKOUT_PILL_STATUS = {
|
|
11470
|
+
completed: "completed",
|
|
11471
|
+
today: "current",
|
|
11472
|
+
upcoming: "upcoming"
|
|
11473
|
+
};
|
|
11474
|
+
function deriveNavLevel(selection) {
|
|
11475
|
+
if (selection.workoutId != null) return "workout";
|
|
11476
|
+
if (selection.weekNumber != null) return "week";
|
|
11477
|
+
return "meso";
|
|
11478
|
+
}
|
|
11479
|
+
function toProgressBarMesos(mesos) {
|
|
11480
|
+
return mesos.map(({ id, name, weekCount, status, currentWeek }) => ({
|
|
11481
|
+
id,
|
|
11482
|
+
name,
|
|
11483
|
+
weekCount,
|
|
11484
|
+
status,
|
|
11485
|
+
currentWeek
|
|
11507
11486
|
}));
|
|
11508
11487
|
}
|
|
11509
|
-
function
|
|
11510
|
-
|
|
11511
|
-
|
|
11512
|
-
|
|
11513
|
-
|
|
11514
|
-
|
|
11515
|
-
|
|
11516
|
-
|
|
11517
|
-
|
|
11518
|
-
|
|
11519
|
-
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11524
|
-
}
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
existing.status = d.volumeStatus;
|
|
11529
|
-
existing.muscle = d.muscleGroup;
|
|
11530
|
-
}
|
|
11488
|
+
function findMeso(mesos, id) {
|
|
11489
|
+
if (id == null) return null;
|
|
11490
|
+
return mesos.find((meso) => meso.id === id) ?? null;
|
|
11491
|
+
}
|
|
11492
|
+
function findWeek(meso, weekNumber) {
|
|
11493
|
+
if (meso == null || weekNumber == null) return null;
|
|
11494
|
+
return meso.weeks.find((week) => week.weekNumber === weekNumber) ?? null;
|
|
11495
|
+
}
|
|
11496
|
+
function findWorkout(week, workoutId) {
|
|
11497
|
+
if (week == null || workoutId == null) return null;
|
|
11498
|
+
return week.workouts.find((workout) => workout.id === workoutId) ?? null;
|
|
11499
|
+
}
|
|
11500
|
+
function buildBreadcrumbs(meso, weekNumber, workout) {
|
|
11501
|
+
const crumbs = [{ key: "meso", label: meso.name, level: "meso" }];
|
|
11502
|
+
if (weekNumber != null) {
|
|
11503
|
+
crumbs.push({ key: "week", label: `Week ${weekNumber}`, level: "week" });
|
|
11504
|
+
}
|
|
11505
|
+
if (workout != null) {
|
|
11506
|
+
crumbs.push({ key: "workout", label: workout.name, level: "workout" });
|
|
11531
11507
|
}
|
|
11532
|
-
return
|
|
11508
|
+
return crumbs;
|
|
11533
11509
|
}
|
|
11534
|
-
function
|
|
11535
|
-
return
|
|
11536
|
-
|
|
11537
|
-
|
|
11538
|
-
|
|
11539
|
-
|
|
11540
|
-
|
|
11541
|
-
|
|
11510
|
+
function Breadcrumbs2({ crumbs, onNavigate }) {
|
|
11511
|
+
return /* @__PURE__ */ jsx(
|
|
11512
|
+
reactNative.View,
|
|
11513
|
+
{
|
|
11514
|
+
className: "flex-row items-center flex-wrap",
|
|
11515
|
+
style: { gap: 4 },
|
|
11516
|
+
testID: "program-planning-page-breadcrumbs",
|
|
11517
|
+
children: crumbs.map((crumb, index) => {
|
|
11518
|
+
const isLast = index === crumbs.length - 1;
|
|
11519
|
+
return /* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-center", style: { gap: 4 }, children: [
|
|
11520
|
+
index > 0 && /* @__PURE__ */ jsx(reactNative.Text, { style: { fontSize: 12, color: TEXT_TERTIARY7 }, children: "\u203A" }),
|
|
11521
|
+
/* @__PURE__ */ jsx(
|
|
11522
|
+
reactNative.Pressable,
|
|
11523
|
+
{
|
|
11524
|
+
onPress: () => onNavigate(crumb.level),
|
|
11525
|
+
disabled: isLast,
|
|
11526
|
+
accessibilityRole: "button",
|
|
11527
|
+
testID: `program-planning-page-crumb-${crumb.key}`,
|
|
11528
|
+
children: /* @__PURE__ */ jsx(
|
|
11529
|
+
reactNative.Text,
|
|
11530
|
+
{
|
|
11531
|
+
style: {
|
|
11532
|
+
fontSize: 12,
|
|
11533
|
+
fontFamily: "Inter, sans-serif",
|
|
11534
|
+
fontWeight: isLast ? "700" : "500",
|
|
11535
|
+
color: isLast ? TEXT_PRIMARY7 : BRAND_PRIMARY11
|
|
11536
|
+
},
|
|
11537
|
+
children: crumb.label
|
|
11538
|
+
}
|
|
11539
|
+
)
|
|
11540
|
+
}
|
|
11541
|
+
)
|
|
11542
|
+
] }, crumb.key);
|
|
11543
|
+
})
|
|
11544
|
+
}
|
|
11545
|
+
);
|
|
11546
|
+
}
|
|
11547
|
+
function toWeekRow(week, meso, onSelectWeek) {
|
|
11548
|
+
const workouts = week.workouts.map((workout) => ({
|
|
11549
|
+
name: workout.name,
|
|
11550
|
+
status: WORKOUT_PILL_STATUS[workout.status],
|
|
11551
|
+
onPress: () => onSelectWeek(week.weekNumber)
|
|
11542
11552
|
}));
|
|
11553
|
+
return {
|
|
11554
|
+
weekNumber: week.weekNumber,
|
|
11555
|
+
totalWeeks: meso.weekCount,
|
|
11556
|
+
workouts,
|
|
11557
|
+
intensityLevel: week.intensityLevel,
|
|
11558
|
+
intensityThreshold: week.intensityThreshold,
|
|
11559
|
+
isCurrent: week.isCurrent ?? week.weekNumber === meso.currentWeek,
|
|
11560
|
+
isDeload: week.isDeload
|
|
11561
|
+
};
|
|
11543
11562
|
}
|
|
11544
|
-
function
|
|
11545
|
-
|
|
11546
|
-
|
|
11547
|
-
|
|
11548
|
-
|
|
11549
|
-
|
|
11550
|
-
|
|
11563
|
+
function MesoLevel({ mesos, activeMesoId, onSelectMeso, onSelectWeek }) {
|
|
11564
|
+
return /* @__PURE__ */ jsx(reactNative.View, { style: { gap: 12 }, testID: "program-planning-page-meso-level", children: mesos.map((meso) => {
|
|
11565
|
+
const expanded = meso.id === activeMesoId;
|
|
11566
|
+
return /* @__PURE__ */ jsx(
|
|
11567
|
+
MesoCard,
|
|
11568
|
+
{
|
|
11569
|
+
name: meso.name,
|
|
11570
|
+
goal: meso.goal,
|
|
11571
|
+
split: meso.split,
|
|
11572
|
+
weekRange: meso.weekRange,
|
|
11573
|
+
currentWeek: meso.currentWeek,
|
|
11574
|
+
totalWeeks: meso.weekCount,
|
|
11575
|
+
weeks: expanded ? meso.weeks.map((week) => toWeekRow(week, meso, onSelectWeek)) : [],
|
|
11576
|
+
volumeHeatmap: meso.volumeHeatmap,
|
|
11577
|
+
expanded,
|
|
11578
|
+
onToggle: () => onSelectMeso(meso.id),
|
|
11579
|
+
highlighted: expanded
|
|
11580
|
+
},
|
|
11581
|
+
meso.id
|
|
11582
|
+
);
|
|
11583
|
+
}) });
|
|
11584
|
+
}
|
|
11585
|
+
function WeekLevel({ week, onSelectWorkout }) {
|
|
11586
|
+
return /* @__PURE__ */ jsx(reactNative.View, { style: { gap: 10 }, testID: "program-planning-page-week-level", children: week.workouts.map((workout) => /* @__PURE__ */ jsx(
|
|
11587
|
+
WorkoutCard,
|
|
11588
|
+
{
|
|
11589
|
+
name: workout.name,
|
|
11590
|
+
date: workout.date,
|
|
11591
|
+
duration: workout.duration,
|
|
11592
|
+
status: workout.status,
|
|
11593
|
+
muscleGroups: workout.muscleGroups,
|
|
11594
|
+
totalSets: workout.totalSets,
|
|
11595
|
+
totalVolume: workout.totalVolume,
|
|
11596
|
+
unit: workout.unit,
|
|
11597
|
+
exercises: workout.exercises,
|
|
11598
|
+
expanded: false,
|
|
11599
|
+
onToggle: () => onSelectWorkout(workout.id)
|
|
11600
|
+
},
|
|
11601
|
+
workout.id
|
|
11602
|
+
)) });
|
|
11603
|
+
}
|
|
11604
|
+
function WorkoutLevel({ workout, expandedExercise, onToggleExercise }) {
|
|
11605
|
+
const exercises = workout.exercises.map((exercise, index) => ({
|
|
11606
|
+
...exercise,
|
|
11607
|
+
state: exercise.state === "upcoming" ? exercise.state : index === expandedExercise ? "expanded" : "collapsed",
|
|
11608
|
+
onToggle: () => onToggleExercise(index)
|
|
11609
|
+
}));
|
|
11610
|
+
return /* @__PURE__ */ jsx(reactNative.View, { testID: "program-planning-page-workout-level", children: /* @__PURE__ */ jsx(
|
|
11611
|
+
WorkoutCard,
|
|
11612
|
+
{
|
|
11613
|
+
name: workout.name,
|
|
11614
|
+
date: workout.date,
|
|
11615
|
+
duration: workout.duration,
|
|
11616
|
+
status: workout.status,
|
|
11617
|
+
muscleGroups: workout.muscleGroups,
|
|
11618
|
+
totalSets: workout.totalSets,
|
|
11619
|
+
totalVolume: workout.totalVolume,
|
|
11620
|
+
unit: workout.unit,
|
|
11621
|
+
exercises,
|
|
11622
|
+
expanded: true,
|
|
11623
|
+
onToggle: () => void 0
|
|
11624
|
+
}
|
|
11625
|
+
) });
|
|
11626
|
+
}
|
|
11627
|
+
function ProgramPlanningPage({
|
|
11628
|
+
title = "Program Plan",
|
|
11629
|
+
mesos,
|
|
11551
11630
|
className,
|
|
11552
11631
|
...props
|
|
11553
11632
|
}) {
|
|
11554
|
-
const
|
|
11555
|
-
const
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
);
|
|
11559
|
-
const
|
|
11560
|
-
|
|
11561
|
-
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
|
|
11565
|
-
|
|
11566
|
-
|
|
11567
|
-
animation.start();
|
|
11568
|
-
return () => animation.stop();
|
|
11569
|
-
}, [highlightedMuscle, highlight]);
|
|
11570
|
-
const scale = highlight.interpolate({ inputRange: [0, 1], outputRange: [1, 1.02] });
|
|
11571
|
-
const glowColor = highlightedMuscle ? getHeatmapColor(
|
|
11572
|
-
data.find((d) => d.muscleGroup === highlightedMuscle)?.volumeStatus,
|
|
11573
|
-
data.find((d) => d.muscleGroup === highlightedMuscle)?.intensity ?? 0
|
|
11574
|
-
) : null;
|
|
11575
|
-
const handleBodyPress = (part) => {
|
|
11576
|
-
if (!onMusclePress || !part.slug) return;
|
|
11577
|
-
const fromData = data.find(
|
|
11578
|
-
(d) => (MUSCLE_TO_SVG_SLUGS[d.muscleGroup] ?? []).includes(part.slug)
|
|
11579
|
-
);
|
|
11580
|
-
const muscle = fromData?.muscleGroup ?? SLUG_TO_PRIMARY_MUSCLE[part.slug];
|
|
11581
|
-
if (muscle) onMusclePress(muscle);
|
|
11633
|
+
const [activeMesoId, setActiveMesoId] = React24.useState(mesos[0]?.id ?? null);
|
|
11634
|
+
const [selectedWeek, setSelectedWeek] = React24.useState(null);
|
|
11635
|
+
const [selectedWorkoutId, setSelectedWorkoutId] = React24.useState(null);
|
|
11636
|
+
const [expandedExercise, setExpandedExercise] = React24.useState(null);
|
|
11637
|
+
const progressMesos = React24.useMemo(() => toProgressBarMesos(mesos), [mesos]);
|
|
11638
|
+
const activeMeso = findMeso(mesos, activeMesoId);
|
|
11639
|
+
const level = deriveNavLevel({ weekNumber: selectedWeek, workoutId: selectedWorkoutId });
|
|
11640
|
+
const activeWeek = findWeek(activeMeso, selectedWeek);
|
|
11641
|
+
const activeWorkout = findWorkout(activeWeek, selectedWorkoutId);
|
|
11642
|
+
const selectMeso = (id) => {
|
|
11643
|
+
setActiveMesoId(id);
|
|
11644
|
+
setSelectedWeek(null);
|
|
11645
|
+
setSelectedWorkoutId(null);
|
|
11582
11646
|
};
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
11587
|
-
|
|
11588
|
-
|
|
11647
|
+
const selectWeek = (weekNumber) => {
|
|
11648
|
+
setSelectedWeek(weekNumber);
|
|
11649
|
+
setSelectedWorkoutId(null);
|
|
11650
|
+
setExpandedExercise(null);
|
|
11651
|
+
};
|
|
11652
|
+
const selectWorkout = (id) => {
|
|
11653
|
+
setSelectedWorkoutId(id);
|
|
11654
|
+
setExpandedExercise(null);
|
|
11655
|
+
};
|
|
11656
|
+
const toggleExercise = (index) => setExpandedExercise((current) => current === index ? null : index);
|
|
11657
|
+
const navigateTo = (target) => {
|
|
11658
|
+
if (target === "meso") selectMeso(activeMesoId ?? mesos[0]?.id);
|
|
11659
|
+
else if (target === "week" && selectedWeek != null) selectWeek(selectedWeek);
|
|
11660
|
+
};
|
|
11661
|
+
return /* @__PURE__ */ jsx(
|
|
11662
|
+
reactNative.View,
|
|
11663
|
+
{
|
|
11664
|
+
className,
|
|
11665
|
+
style: { width: 390, backgroundColor: PAGE_BG },
|
|
11666
|
+
accessibilityRole: "main",
|
|
11667
|
+
"aria-label": title,
|
|
11668
|
+
testID: "program-planning-page",
|
|
11669
|
+
...props,
|
|
11670
|
+
children: /* @__PURE__ */ jsxs(reactNative.View, { style: { padding: 16, gap: 14 }, testID: "program-planning-page-content", children: [
|
|
11671
|
+
/* @__PURE__ */ jsx(
|
|
11672
|
+
reactNative.Text,
|
|
11589
11673
|
{
|
|
11590
|
-
|
|
11591
|
-
|
|
11592
|
-
|
|
11593
|
-
|
|
11594
|
-
|
|
11595
|
-
|
|
11596
|
-
|
|
11597
|
-
|
|
11598
|
-
|
|
11599
|
-
|
|
11600
|
-
|
|
11601
|
-
|
|
11674
|
+
accessibilityRole: "header",
|
|
11675
|
+
style: {
|
|
11676
|
+
fontSize: 20,
|
|
11677
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
11678
|
+
fontWeight: "700",
|
|
11679
|
+
color: TEXT_PRIMARY7
|
|
11680
|
+
},
|
|
11681
|
+
testID: "program-planning-page-title",
|
|
11682
|
+
children: title
|
|
11683
|
+
}
|
|
11684
|
+
),
|
|
11685
|
+
/* @__PURE__ */ jsx(reactNative.View, { style: { marginHorizontal: -16 }, children: /* @__PURE__ */ jsx(
|
|
11686
|
+
MesoProgressBar,
|
|
11602
11687
|
{
|
|
11603
|
-
|
|
11604
|
-
|
|
11605
|
-
|
|
11606
|
-
gender: "male",
|
|
11607
|
-
defaultFill: OUTLINE_FILL,
|
|
11608
|
-
border: OUTLINE_BORDER,
|
|
11609
|
-
onBodyPartPress: handleBodyPress
|
|
11688
|
+
mesos: progressMesos,
|
|
11689
|
+
activeMesoId,
|
|
11690
|
+
onMesoPress: selectMeso
|
|
11610
11691
|
}
|
|
11611
|
-
)
|
|
11612
|
-
|
|
11613
|
-
|
|
11614
|
-
legend.length === 0 ? /* @__PURE__ */ jsx(
|
|
11615
|
-
reactNative.Text,
|
|
11616
|
-
{
|
|
11617
|
-
style: {
|
|
11618
|
-
marginTop: 8,
|
|
11619
|
-
fontSize: 12,
|
|
11620
|
-
color: TEXT_SECONDARY6,
|
|
11621
|
-
textAlign: "center",
|
|
11622
|
-
fontFamily: "Inter, sans-serif"
|
|
11623
|
-
},
|
|
11624
|
-
testID: "body-map-empty",
|
|
11625
|
-
children: "No training data"
|
|
11626
|
-
}
|
|
11627
|
-
) : /* @__PURE__ */ jsx(
|
|
11628
|
-
reactNative.View,
|
|
11629
|
-
{
|
|
11630
|
-
className: "flex-row flex-wrap",
|
|
11631
|
-
style: { marginTop: 10, gap: 6, justifyContent: "center" },
|
|
11632
|
-
testID: "body-map-legend",
|
|
11633
|
-
children: legend.map((entry) => /* @__PURE__ */ jsx(
|
|
11634
|
-
MuscleButton,
|
|
11692
|
+
) }),
|
|
11693
|
+
activeMeso != null && /* @__PURE__ */ jsx(
|
|
11694
|
+
Breadcrumbs2,
|
|
11635
11695
|
{
|
|
11636
|
-
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
|
|
11640
|
-
|
|
11641
|
-
|
|
11642
|
-
|
|
11643
|
-
|
|
11644
|
-
|
|
11696
|
+
crumbs: buildBreadcrumbs(activeMeso, selectedWeek, activeWorkout),
|
|
11697
|
+
onNavigate: navigateTo
|
|
11698
|
+
}
|
|
11699
|
+
),
|
|
11700
|
+
/* @__PURE__ */ jsxs(
|
|
11701
|
+
reactNative.View,
|
|
11702
|
+
{
|
|
11703
|
+
style: {
|
|
11704
|
+
backgroundColor: SURFACE_ELEVATED,
|
|
11705
|
+
borderWidth: 1,
|
|
11706
|
+
borderColor: BORDER_DEFAULT3,
|
|
11707
|
+
borderRadius: 12,
|
|
11708
|
+
padding: 12
|
|
11709
|
+
},
|
|
11710
|
+
testID: "program-planning-page-body",
|
|
11711
|
+
children: [
|
|
11712
|
+
level === "meso" && /* @__PURE__ */ jsx(
|
|
11713
|
+
MesoLevel,
|
|
11714
|
+
{
|
|
11715
|
+
mesos,
|
|
11716
|
+
activeMesoId,
|
|
11717
|
+
onSelectMeso: selectMeso,
|
|
11718
|
+
onSelectWeek: selectWeek
|
|
11719
|
+
}
|
|
11720
|
+
),
|
|
11721
|
+
level === "week" && activeWeek != null && /* @__PURE__ */ jsx(WeekLevel, { week: activeWeek, onSelectWorkout: selectWorkout }),
|
|
11722
|
+
level === "workout" && activeWorkout != null && /* @__PURE__ */ jsx(
|
|
11723
|
+
WorkoutLevel,
|
|
11724
|
+
{
|
|
11725
|
+
workout: activeWorkout,
|
|
11726
|
+
expandedExercise,
|
|
11727
|
+
onToggleExercise: toggleExercise
|
|
11728
|
+
}
|
|
11729
|
+
)
|
|
11730
|
+
]
|
|
11731
|
+
}
|
|
11732
|
+
)
|
|
11733
|
+
] })
|
|
11734
|
+
}
|
|
11735
|
+
);
|
|
11736
|
+
}
|
|
11737
|
+
var SURFACE_ELEVATED2 = "var(--color-surface-elevated)";
|
|
11738
|
+
var BORDER_DEFAULT4 = "var(--color-border-default)";
|
|
11739
|
+
var BRAND_PRIMARY12 = "#FF7900";
|
|
11740
|
+
var TEXT_PRIMARY8 = "var(--color-text-primary)";
|
|
11741
|
+
var TEXT_SECONDARY6 = "var(--color-text-secondary)";
|
|
11742
|
+
var TEXT_TERTIARY8 = "var(--color-text-tertiary)";
|
|
11743
|
+
var PAGE_BG2 = "var(--color-background-base)";
|
|
11744
|
+
var CHART_WIDTH = 326;
|
|
11745
|
+
var CHART_HEIGHT = 150;
|
|
11746
|
+
var EXERCISE_DETAIL_TABS = [
|
|
11747
|
+
{ key: "progress", label: "Progress" },
|
|
11748
|
+
{ key: "history", label: "History" },
|
|
11749
|
+
{ key: "advanced", label: "Advanced" }
|
|
11750
|
+
];
|
|
11751
|
+
function deriveExerciseStats(entries) {
|
|
11752
|
+
let bestE1rm = null;
|
|
11753
|
+
let prCount = 0;
|
|
11754
|
+
for (const entry of entries) {
|
|
11755
|
+
if (entry.e1rm != null && (bestE1rm == null || entry.e1rm.value > bestE1rm)) {
|
|
11756
|
+
bestE1rm = entry.e1rm.value;
|
|
11757
|
+
}
|
|
11758
|
+
if (entry.isPR) prCount += 1;
|
|
11759
|
+
}
|
|
11760
|
+
return { sessions: entries.length, bestE1rm, prCount };
|
|
11761
|
+
}
|
|
11762
|
+
function toExerciseCardProps(entry, expanded, onToggle) {
|
|
11763
|
+
return {
|
|
11764
|
+
name: entry.title,
|
|
11765
|
+
state: expanded ? "expanded" : "collapsed",
|
|
11766
|
+
onToggle,
|
|
11767
|
+
summary: entry.summary,
|
|
11768
|
+
e1rm: entry.e1rm,
|
|
11769
|
+
isPR: entry.isPR,
|
|
11770
|
+
tempo: entry.tempo,
|
|
11771
|
+
sets: expanded ? entry.sets : void 0
|
|
11772
|
+
};
|
|
11773
|
+
}
|
|
11774
|
+
function summarizeVbt(sets) {
|
|
11775
|
+
const allReps = sets.flatMap((set) => set.velocities);
|
|
11776
|
+
const meanVelocity = calculateMeanVelocity(allReps);
|
|
11777
|
+
let velocityLoss = 0;
|
|
11778
|
+
for (const set of sets) {
|
|
11779
|
+
velocityLoss = Math.max(velocityLoss, calculateVelocityLoss(set.velocities));
|
|
11780
|
+
}
|
|
11781
|
+
return { meanVelocity, velocityLoss };
|
|
11645
11782
|
}
|
|
11646
|
-
function
|
|
11783
|
+
function TabBar({ active, onSelect }) {
|
|
11647
11784
|
return /* @__PURE__ */ jsx(
|
|
11648
11785
|
reactNative.View,
|
|
11649
11786
|
{
|
|
11650
|
-
className: "flex-row
|
|
11651
|
-
style: {
|
|
11652
|
-
|
|
11653
|
-
|
|
11654
|
-
|
|
11787
|
+
className: "flex-row",
|
|
11788
|
+
style: {
|
|
11789
|
+
borderBottomWidth: 1,
|
|
11790
|
+
borderBottomColor: BORDER_DEFAULT4
|
|
11791
|
+
},
|
|
11792
|
+
accessibilityRole: "tablist",
|
|
11793
|
+
testID: "exercise-detail-page-tabs",
|
|
11794
|
+
children: EXERCISE_DETAIL_TABS.map(({ key, label }) => {
|
|
11795
|
+
const isActive = key === active;
|
|
11655
11796
|
return /* @__PURE__ */ jsx(
|
|
11656
11797
|
reactNative.Pressable,
|
|
11657
11798
|
{
|
|
11658
|
-
onPress: () =>
|
|
11659
|
-
accessibilityRole: "
|
|
11660
|
-
|
|
11661
|
-
"aria-pressed": active,
|
|
11662
|
-
disabled: !onViewChange,
|
|
11799
|
+
onPress: () => onSelect(key),
|
|
11800
|
+
accessibilityRole: "tab",
|
|
11801
|
+
accessibilityState: { selected: isActive },
|
|
11663
11802
|
style: {
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
|
|
11667
|
-
|
|
11668
|
-
|
|
11669
|
-
borderColor: active ? "#FF7900" : WORKOUT_TOKENS.border.strong
|
|
11803
|
+
flex: 1,
|
|
11804
|
+
alignItems: "center",
|
|
11805
|
+
paddingVertical: 10,
|
|
11806
|
+
borderBottomWidth: 2,
|
|
11807
|
+
borderBottomColor: isActive ? BRAND_PRIMARY12 : "transparent"
|
|
11670
11808
|
},
|
|
11671
|
-
testID: `
|
|
11809
|
+
testID: `exercise-detail-page-tab-${key}`,
|
|
11672
11810
|
children: /* @__PURE__ */ jsx(
|
|
11673
11811
|
reactNative.Text,
|
|
11674
11812
|
{
|
|
11675
11813
|
style: {
|
|
11676
|
-
fontSize:
|
|
11814
|
+
fontSize: 13,
|
|
11677
11815
|
fontFamily: "Inter, sans-serif",
|
|
11678
|
-
fontWeight:
|
|
11679
|
-
color:
|
|
11680
|
-
textTransform: "capitalize"
|
|
11816
|
+
fontWeight: isActive ? "700" : "500",
|
|
11817
|
+
color: isActive ? TEXT_PRIMARY8 : TEXT_TERTIARY8
|
|
11681
11818
|
},
|
|
11682
|
-
children:
|
|
11819
|
+
children: label
|
|
11683
11820
|
}
|
|
11684
11821
|
)
|
|
11685
11822
|
},
|
|
11686
|
-
|
|
11823
|
+
key
|
|
11687
11824
|
);
|
|
11688
11825
|
})
|
|
11689
11826
|
}
|
|
11690
11827
|
);
|
|
11691
11828
|
}
|
|
11692
|
-
|
|
11693
|
-
|
|
11694
|
-
|
|
11829
|
+
var STAT_CARDS = [
|
|
11830
|
+
{ key: "sessions", label: "Sessions" },
|
|
11831
|
+
{ key: "bestE1rm", label: "Best e1RM" },
|
|
11832
|
+
{ key: "prCount", label: "PRs" }
|
|
11833
|
+
];
|
|
11834
|
+
function StatStrip({ stats, unit }) {
|
|
11835
|
+
return /* @__PURE__ */ jsx(reactNative.View, { className: "flex-row", style: { gap: 8 }, testID: "exercise-detail-page-stats", children: STAT_CARDS.map(({ key, label }) => {
|
|
11836
|
+
const raw = stats[key];
|
|
11837
|
+
const value = key === "bestE1rm" ? raw == null ? "\u2014" : `${raw} ${unit}` : `${raw}`;
|
|
11838
|
+
return /* @__PURE__ */ jsxs(
|
|
11839
|
+
reactNative.View,
|
|
11840
|
+
{
|
|
11841
|
+
style: {
|
|
11842
|
+
flex: 1,
|
|
11843
|
+
padding: 12,
|
|
11844
|
+
borderRadius: 10,
|
|
11845
|
+
backgroundColor: SURFACE_ELEVATED2,
|
|
11846
|
+
borderWidth: 1,
|
|
11847
|
+
borderColor: BORDER_DEFAULT4
|
|
11848
|
+
},
|
|
11849
|
+
testID: `exercise-detail-page-stat-${key}`,
|
|
11850
|
+
children: [
|
|
11851
|
+
/* @__PURE__ */ jsx(
|
|
11852
|
+
reactNative.Text,
|
|
11853
|
+
{
|
|
11854
|
+
style: {
|
|
11855
|
+
fontSize: 18,
|
|
11856
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
11857
|
+
fontWeight: "700",
|
|
11858
|
+
color: TEXT_PRIMARY8
|
|
11859
|
+
},
|
|
11860
|
+
children: value
|
|
11861
|
+
}
|
|
11862
|
+
),
|
|
11863
|
+
/* @__PURE__ */ jsx(
|
|
11864
|
+
reactNative.Text,
|
|
11865
|
+
{
|
|
11866
|
+
style: {
|
|
11867
|
+
marginTop: 2,
|
|
11868
|
+
fontSize: 10,
|
|
11869
|
+
fontFamily: "Inter, sans-serif",
|
|
11870
|
+
fontWeight: "600",
|
|
11871
|
+
letterSpacing: 0.4,
|
|
11872
|
+
textTransform: "uppercase",
|
|
11873
|
+
color: TEXT_TERTIARY8
|
|
11874
|
+
},
|
|
11875
|
+
children: label
|
|
11876
|
+
}
|
|
11877
|
+
)
|
|
11878
|
+
]
|
|
11879
|
+
},
|
|
11880
|
+
key
|
|
11881
|
+
);
|
|
11882
|
+
}) });
|
|
11883
|
+
}
|
|
11884
|
+
function SectionCard({
|
|
11885
|
+
title,
|
|
11886
|
+
children,
|
|
11887
|
+
testID
|
|
11888
|
+
}) {
|
|
11695
11889
|
return /* @__PURE__ */ jsxs(
|
|
11696
|
-
reactNative.
|
|
11890
|
+
reactNative.View,
|
|
11697
11891
|
{
|
|
11698
|
-
onPress: () => onMusclePress?.(entry.muscle),
|
|
11699
|
-
accessibilityRole: "button",
|
|
11700
|
-
accessibilityLabel: label,
|
|
11701
|
-
"aria-pressed": highlighted,
|
|
11702
11892
|
style: {
|
|
11703
|
-
|
|
11704
|
-
alignItems: "center",
|
|
11705
|
-
gap: 5,
|
|
11706
|
-
paddingHorizontal: 8,
|
|
11707
|
-
paddingVertical: 3,
|
|
11708
|
-
borderRadius: 9999,
|
|
11893
|
+
backgroundColor: SURFACE_ELEVATED2,
|
|
11709
11894
|
borderWidth: 1,
|
|
11710
|
-
borderColor:
|
|
11711
|
-
|
|
11895
|
+
borderColor: BORDER_DEFAULT4,
|
|
11896
|
+
borderRadius: 12,
|
|
11897
|
+
padding: 12,
|
|
11898
|
+
gap: 10
|
|
11712
11899
|
},
|
|
11713
|
-
testID
|
|
11900
|
+
testID,
|
|
11714
11901
|
children: [
|
|
11715
|
-
/* @__PURE__ */ jsx(
|
|
11716
|
-
reactNative.View,
|
|
11717
|
-
{
|
|
11718
|
-
style: { width: 7, height: 7, borderRadius: 9999, backgroundColor: dotColor },
|
|
11719
|
-
accessibilityElementsHidden: true,
|
|
11720
|
-
testID: `body-map-muscle-dot-${entry.key}`
|
|
11721
|
-
}
|
|
11722
|
-
),
|
|
11723
11902
|
/* @__PURE__ */ jsx(
|
|
11724
11903
|
reactNative.Text,
|
|
11725
11904
|
{
|
|
11726
11905
|
style: {
|
|
11727
11906
|
fontSize: 11,
|
|
11728
11907
|
fontFamily: "Inter, sans-serif",
|
|
11729
|
-
fontWeight: "
|
|
11730
|
-
|
|
11908
|
+
fontWeight: "600",
|
|
11909
|
+
letterSpacing: 0.6,
|
|
11910
|
+
textTransform: "uppercase",
|
|
11911
|
+
color: TEXT_TERTIARY8
|
|
11731
11912
|
},
|
|
11732
|
-
|
|
11733
|
-
children: entry.name
|
|
11913
|
+
children: title
|
|
11734
11914
|
}
|
|
11735
|
-
)
|
|
11915
|
+
),
|
|
11916
|
+
children
|
|
11736
11917
|
]
|
|
11737
11918
|
}
|
|
11738
11919
|
);
|
|
11739
11920
|
}
|
|
11740
|
-
|
|
11741
|
-
|
|
11742
|
-
|
|
11743
|
-
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
-
|
|
11747
|
-
|
|
11748
|
-
|
|
11749
|
-
|
|
11750
|
-
|
|
11751
|
-
|
|
11752
|
-
|
|
11753
|
-
|
|
11754
|
-
|
|
11755
|
-
|
|
11756
|
-
|
|
11757
|
-
|
|
11758
|
-
if (value < 0) return 0;
|
|
11759
|
-
if (value > 1) return 1;
|
|
11760
|
-
return value;
|
|
11921
|
+
function EntryList({ entries, expandedId, onToggle, emptyLabel, testID }) {
|
|
11922
|
+
if (entries.length === 0) {
|
|
11923
|
+
return /* @__PURE__ */ jsx(
|
|
11924
|
+
reactNative.Text,
|
|
11925
|
+
{
|
|
11926
|
+
style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_TERTIARY8 },
|
|
11927
|
+
testID: `${testID}-empty`,
|
|
11928
|
+
children: emptyLabel
|
|
11929
|
+
}
|
|
11930
|
+
);
|
|
11931
|
+
}
|
|
11932
|
+
return /* @__PURE__ */ jsx(reactNative.View, { style: { gap: 8 }, testID, children: entries.map((entry) => /* @__PURE__ */ jsx(
|
|
11933
|
+
ExerciseCard,
|
|
11934
|
+
{
|
|
11935
|
+
...toExerciseCardProps(entry, entry.id === expandedId, () => onToggle(entry.id))
|
|
11936
|
+
},
|
|
11937
|
+
entry.id
|
|
11938
|
+
)) });
|
|
11761
11939
|
}
|
|
11762
|
-
function
|
|
11763
|
-
|
|
11764
|
-
|
|
11765
|
-
|
|
11940
|
+
function VbtBreakdown({ sets }) {
|
|
11941
|
+
return /* @__PURE__ */ jsx(reactNative.View, { style: { gap: 10 }, testID: "exercise-detail-page-vbt-breakdown", children: sets.map((set) => {
|
|
11942
|
+
const mean = calculateMeanVelocity(set.velocities);
|
|
11943
|
+
const loss = calculateVelocityLoss(set.velocities);
|
|
11944
|
+
return /* @__PURE__ */ jsxs(
|
|
11945
|
+
reactNative.View,
|
|
11946
|
+
{
|
|
11947
|
+
className: "flex-row items-center",
|
|
11948
|
+
style: { gap: 10 },
|
|
11949
|
+
testID: "exercise-detail-page-vbt-set",
|
|
11950
|
+
children: [
|
|
11951
|
+
/* @__PURE__ */ jsx(
|
|
11952
|
+
reactNative.Text,
|
|
11953
|
+
{
|
|
11954
|
+
style: {
|
|
11955
|
+
width: 44,
|
|
11956
|
+
fontSize: 11,
|
|
11957
|
+
fontFamily: "Inter, sans-serif",
|
|
11958
|
+
fontWeight: "600",
|
|
11959
|
+
color: TEXT_SECONDARY6
|
|
11960
|
+
},
|
|
11961
|
+
children: set.label
|
|
11962
|
+
}
|
|
11963
|
+
),
|
|
11964
|
+
/* @__PURE__ */ jsx(reactNative.View, { className: "flex-1", style: { height: 8, justifyContent: "center" }, children: /* @__PURE__ */ jsx(VelocityStrip, { velocities: set.velocities, variant: "mini" }) }),
|
|
11965
|
+
/* @__PURE__ */ jsx(
|
|
11966
|
+
reactNative.Text,
|
|
11967
|
+
{
|
|
11968
|
+
style: {
|
|
11969
|
+
fontSize: 11,
|
|
11970
|
+
fontFamily: "Inter, sans-serif",
|
|
11971
|
+
fontVariant: ["tabular-nums"],
|
|
11972
|
+
color: TEXT_TERTIARY8
|
|
11973
|
+
},
|
|
11974
|
+
children: `${mean.toFixed(2)} \xB7 -${loss}%`
|
|
11975
|
+
}
|
|
11976
|
+
)
|
|
11977
|
+
]
|
|
11978
|
+
},
|
|
11979
|
+
set.label
|
|
11980
|
+
);
|
|
11981
|
+
}) });
|
|
11766
11982
|
}
|
|
11767
|
-
function
|
|
11768
|
-
|
|
11769
|
-
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
lastTrained,
|
|
11774
|
-
weeklyHistory,
|
|
11775
|
-
contributingExercises,
|
|
11776
|
-
upcomingExercises,
|
|
11777
|
-
isOpen,
|
|
11778
|
-
visible,
|
|
11779
|
-
onClose,
|
|
11780
|
-
onViewExercises,
|
|
11781
|
-
...props
|
|
11782
|
-
}) {
|
|
11783
|
-
const open = isOpen ?? visible ?? false;
|
|
11784
|
-
const [translateY] = React24.useState(() => new reactNative.Animated.Value(SLIDE_OFFSET));
|
|
11785
|
-
const [backdrop] = React24.useState(() => new reactNative.Animated.Value(0));
|
|
11786
|
-
React24.useEffect(() => {
|
|
11787
|
-
if (!open) return;
|
|
11788
|
-
const animation = reactNative.Animated.parallel([
|
|
11789
|
-
reactNative.Animated.timing(translateY, {
|
|
11790
|
-
toValue: 0,
|
|
11791
|
-
duration: 400,
|
|
11792
|
-
easing: reactNative.Easing.out(reactNative.Easing.ease),
|
|
11793
|
-
useNativeDriver: false
|
|
11794
|
-
}),
|
|
11795
|
-
reactNative.Animated.timing(backdrop, {
|
|
11796
|
-
toValue: BACKDROP_OPACITY,
|
|
11797
|
-
duration: 300,
|
|
11798
|
-
easing: reactNative.Easing.out(reactNative.Easing.ease),
|
|
11799
|
-
useNativeDriver: false
|
|
11800
|
-
})
|
|
11801
|
-
]);
|
|
11802
|
-
animation.start();
|
|
11803
|
-
return () => animation.stop();
|
|
11804
|
-
}, [open, translateY, backdrop]);
|
|
11805
|
-
if (!open) return null;
|
|
11806
|
-
const dialogLabel = `${displayName} volume details`;
|
|
11807
|
-
const markerLeft = markerFraction(weeklySets, landmarks) * 100;
|
|
11808
|
-
const hasContributing = (contributingExercises?.length ?? 0) > 0;
|
|
11809
|
-
const hasUpcoming = (upcomingExercises?.length ?? 0) > 0;
|
|
11810
|
-
return /* @__PURE__ */ jsxs(
|
|
11983
|
+
function VbtSummaryRow({ summary }) {
|
|
11984
|
+
const cells = [
|
|
11985
|
+
{ label: "Mean Velocity", value: `${summary.meanVelocity.toFixed(2)} m/s` },
|
|
11986
|
+
{ label: "Peak Vel. Loss", value: `-${summary.velocityLoss}%` }
|
|
11987
|
+
];
|
|
11988
|
+
return /* @__PURE__ */ jsx(reactNative.View, { className: "flex-row", style: { gap: 8 }, testID: "exercise-detail-page-vbt-summary", children: cells.map((cell) => /* @__PURE__ */ jsxs(
|
|
11811
11989
|
reactNative.View,
|
|
11812
11990
|
{
|
|
11813
|
-
style: {
|
|
11814
|
-
|
|
11991
|
+
style: {
|
|
11992
|
+
flex: 1,
|
|
11993
|
+
padding: 12,
|
|
11994
|
+
borderRadius: 10,
|
|
11995
|
+
backgroundColor: SURFACE_ELEVATED2,
|
|
11996
|
+
borderWidth: 1,
|
|
11997
|
+
borderColor: BORDER_DEFAULT4
|
|
11998
|
+
},
|
|
11815
11999
|
children: [
|
|
11816
12000
|
/* @__PURE__ */ jsx(
|
|
11817
|
-
reactNative.
|
|
12001
|
+
reactNative.Text,
|
|
11818
12002
|
{
|
|
11819
12003
|
style: {
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
bottom: 0,
|
|
11825
|
-
backgroundColor: "#000000",
|
|
11826
|
-
opacity: backdrop
|
|
12004
|
+
fontSize: 16,
|
|
12005
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
12006
|
+
fontWeight: "700",
|
|
12007
|
+
color: TEXT_PRIMARY8
|
|
11827
12008
|
},
|
|
11828
|
-
|
|
11829
|
-
children: /* @__PURE__ */ jsx(
|
|
11830
|
-
reactNative.Pressable,
|
|
11831
|
-
{
|
|
11832
|
-
onPress: onClose,
|
|
11833
|
-
accessibilityRole: "button",
|
|
11834
|
-
accessibilityLabel: `Close ${displayName} details`,
|
|
11835
|
-
style: { flex: 1 },
|
|
11836
|
-
testID: "body-map-detail-panel-backdrop"
|
|
11837
|
-
}
|
|
11838
|
-
)
|
|
12009
|
+
children: cell.value
|
|
11839
12010
|
}
|
|
11840
12011
|
),
|
|
11841
|
-
/* @__PURE__ */
|
|
11842
|
-
reactNative.
|
|
12012
|
+
/* @__PURE__ */ jsx(
|
|
12013
|
+
reactNative.Text,
|
|
11843
12014
|
{
|
|
11844
|
-
accessibilityRole: "dialog",
|
|
11845
|
-
accessibilityLabel: dialogLabel,
|
|
11846
|
-
"aria-label": dialogLabel,
|
|
11847
12015
|
style: {
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
|
|
11851
|
-
|
|
11852
|
-
|
|
12016
|
+
marginTop: 2,
|
|
12017
|
+
fontSize: 10,
|
|
12018
|
+
fontFamily: "Inter, sans-serif",
|
|
12019
|
+
fontWeight: "600",
|
|
12020
|
+
letterSpacing: 0.4,
|
|
12021
|
+
textTransform: "uppercase",
|
|
12022
|
+
color: TEXT_TERTIARY8
|
|
11853
12023
|
},
|
|
11854
|
-
|
|
11855
|
-
|
|
12024
|
+
children: cell.label
|
|
12025
|
+
}
|
|
12026
|
+
)
|
|
12027
|
+
]
|
|
12028
|
+
},
|
|
12029
|
+
cell.label
|
|
12030
|
+
)) });
|
|
12031
|
+
}
|
|
12032
|
+
function ExerciseDetailPage({
|
|
12033
|
+
exercise,
|
|
12034
|
+
meso,
|
|
12035
|
+
trend,
|
|
12036
|
+
progression,
|
|
12037
|
+
history,
|
|
12038
|
+
vbt,
|
|
12039
|
+
className,
|
|
12040
|
+
...props
|
|
12041
|
+
}) {
|
|
12042
|
+
const [tab, setTab] = React24.useState("progress");
|
|
12043
|
+
const [expandedProgressId, setExpandedProgressId] = React24.useState(null);
|
|
12044
|
+
const [expandedHistoryId, setExpandedHistoryId] = React24.useState(null);
|
|
12045
|
+
const stats = React24.useMemo(() => deriveExerciseStats(history), [history]);
|
|
12046
|
+
const vbtSummary = React24.useMemo(() => summarizeVbt(vbt.sets), [vbt.sets]);
|
|
12047
|
+
const toggle = (setId) => (id) => setId((current) => current === id ? null : id);
|
|
12048
|
+
return /* @__PURE__ */ jsx(
|
|
12049
|
+
reactNative.View,
|
|
12050
|
+
{
|
|
12051
|
+
className,
|
|
12052
|
+
style: { width: 390, backgroundColor: PAGE_BG2 },
|
|
12053
|
+
accessibilityRole: "main",
|
|
12054
|
+
"aria-label": exercise.name,
|
|
12055
|
+
testID: "exercise-detail-page",
|
|
12056
|
+
...props,
|
|
12057
|
+
children: /* @__PURE__ */ jsxs(reactNative.View, { style: { padding: 16, gap: 14 }, testID: "exercise-detail-page-content", children: [
|
|
12058
|
+
/* @__PURE__ */ jsxs(
|
|
12059
|
+
reactNative.View,
|
|
12060
|
+
{
|
|
12061
|
+
className: "flex-row items-start justify-between",
|
|
12062
|
+
style: { gap: 8 },
|
|
12063
|
+
testID: "exercise-detail-page-header",
|
|
11856
12064
|
children: [
|
|
11857
|
-
/* @__PURE__ */
|
|
11858
|
-
|
|
11859
|
-
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
|
|
11870
|
-
|
|
11871
|
-
|
|
11872
|
-
|
|
11873
|
-
|
|
11874
|
-
|
|
11875
|
-
|
|
11876
|
-
|
|
12065
|
+
/* @__PURE__ */ jsxs(reactNative.View, { style: { flexShrink: 1 }, children: [
|
|
12066
|
+
/* @__PURE__ */ jsx(
|
|
12067
|
+
reactNative.Text,
|
|
12068
|
+
{
|
|
12069
|
+
accessibilityRole: "header",
|
|
12070
|
+
style: {
|
|
12071
|
+
fontSize: 20,
|
|
12072
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
12073
|
+
fontWeight: "700",
|
|
12074
|
+
color: TEXT_PRIMARY8
|
|
12075
|
+
},
|
|
12076
|
+
testID: "exercise-detail-page-title",
|
|
12077
|
+
children: exercise.name
|
|
12078
|
+
}
|
|
12079
|
+
),
|
|
12080
|
+
/* @__PURE__ */ jsx(
|
|
12081
|
+
reactNative.Text,
|
|
12082
|
+
{
|
|
12083
|
+
style: {
|
|
12084
|
+
marginTop: 2,
|
|
12085
|
+
fontSize: 12,
|
|
12086
|
+
fontFamily: "Inter, sans-serif",
|
|
12087
|
+
color: TEXT_SECONDARY6
|
|
12088
|
+
},
|
|
12089
|
+
testID: "exercise-detail-page-subtitle",
|
|
12090
|
+
children: exercise.subtitle
|
|
12091
|
+
}
|
|
12092
|
+
)
|
|
12093
|
+
] }),
|
|
12094
|
+
exercise.currentE1rm != null && /* @__PURE__ */ jsxs(
|
|
12095
|
+
reactNative.View,
|
|
11877
12096
|
{
|
|
11878
|
-
style: {
|
|
11879
|
-
|
|
11880
|
-
|
|
12097
|
+
style: {
|
|
12098
|
+
paddingVertical: 4,
|
|
12099
|
+
paddingHorizontal: 10,
|
|
12100
|
+
borderRadius: 6,
|
|
12101
|
+
backgroundColor: "rgba(255,121,0,0.10)",
|
|
12102
|
+
borderWidth: 1,
|
|
12103
|
+
borderColor: "rgba(255,121,0,0.25)"
|
|
12104
|
+
},
|
|
12105
|
+
testID: "exercise-detail-page-e1rm",
|
|
11881
12106
|
children: [
|
|
11882
|
-
/* @__PURE__ */
|
|
11883
|
-
reactNative.View,
|
|
11884
|
-
{
|
|
11885
|
-
className: "flex-row items-center justify-between",
|
|
11886
|
-
style: { gap: 8, paddingTop: 4, paddingBottom: 4 },
|
|
11887
|
-
testID: "body-map-detail-panel-header",
|
|
11888
|
-
children: [
|
|
11889
|
-
/* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-center", style: { gap: 8, flexShrink: 1 }, children: [
|
|
11890
|
-
/* @__PURE__ */ jsx(
|
|
11891
|
-
reactNative.Text,
|
|
11892
|
-
{
|
|
11893
|
-
accessibilityRole: "header",
|
|
11894
|
-
style: {
|
|
11895
|
-
fontSize: 16,
|
|
11896
|
-
fontFamily: '"Space Grotesk", sans-serif',
|
|
11897
|
-
fontWeight: "700",
|
|
11898
|
-
color: TEXT_PRIMARY8
|
|
11899
|
-
},
|
|
11900
|
-
testID: "body-map-detail-panel-title",
|
|
11901
|
-
children: displayName
|
|
11902
|
-
}
|
|
11903
|
-
),
|
|
11904
|
-
/* @__PURE__ */ jsx(
|
|
11905
|
-
Badge,
|
|
11906
|
-
{
|
|
11907
|
-
variant: "subtle",
|
|
11908
|
-
color: STATUS_BADGE_COLOR[volumeStatus],
|
|
11909
|
-
size: "sm",
|
|
11910
|
-
testID: "body-map-detail-panel-status-badge",
|
|
11911
|
-
children: VOLUME_STATUS_LABELS[volumeStatus]
|
|
11912
|
-
}
|
|
11913
|
-
)
|
|
11914
|
-
] }),
|
|
11915
|
-
/* @__PURE__ */ jsx(
|
|
11916
|
-
reactNative.Pressable,
|
|
11917
|
-
{
|
|
11918
|
-
onPress: onClose,
|
|
11919
|
-
accessibilityRole: "button",
|
|
11920
|
-
accessibilityLabel: `Close ${displayName} details`,
|
|
11921
|
-
hitSlop: 8,
|
|
11922
|
-
style: { padding: 4, margin: -4 },
|
|
11923
|
-
testID: "body-map-detail-panel-close",
|
|
11924
|
-
children: /* @__PURE__ */ jsx(reactNative.Text, { style: { fontSize: 22, lineHeight: 22, color: TEXT_SECONDARY7 }, children: "\xD7" })
|
|
11925
|
-
}
|
|
11926
|
-
)
|
|
11927
|
-
]
|
|
11928
|
-
}
|
|
11929
|
-
),
|
|
11930
|
-
lastTrained != null && /* @__PURE__ */ jsx(
|
|
12107
|
+
/* @__PURE__ */ jsx(
|
|
11931
12108
|
reactNative.Text,
|
|
11932
12109
|
{
|
|
11933
|
-
style: {
|
|
11934
|
-
|
|
11935
|
-
|
|
12110
|
+
style: {
|
|
12111
|
+
fontSize: 9,
|
|
12112
|
+
fontFamily: "Inter, sans-serif",
|
|
12113
|
+
fontWeight: "600",
|
|
12114
|
+
letterSpacing: 0.4,
|
|
12115
|
+
textTransform: "uppercase",
|
|
12116
|
+
color: TEXT_TERTIARY8
|
|
12117
|
+
},
|
|
12118
|
+
children: "e1RM"
|
|
11936
12119
|
}
|
|
11937
12120
|
),
|
|
11938
|
-
/* @__PURE__ */
|
|
11939
|
-
|
|
11940
|
-
reactNative.View,
|
|
11941
|
-
{
|
|
11942
|
-
className: "flex-row items-center justify-between",
|
|
11943
|
-
style: { marginBottom: 6 },
|
|
11944
|
-
accessibilityElementsHidden: true,
|
|
11945
|
-
children: [
|
|
11946
|
-
/* @__PURE__ */ jsx(reactNative.Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_TERTIARY7 }, children: `MEV ${landmarks.mev}` }),
|
|
11947
|
-
/* @__PURE__ */ jsx(reactNative.Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_TERTIARY7 }, children: `MRV ${landmarks.mrv}` })
|
|
11948
|
-
]
|
|
11949
|
-
}
|
|
11950
|
-
),
|
|
11951
|
-
/* @__PURE__ */ jsxs(
|
|
11952
|
-
reactNative.View,
|
|
11953
|
-
{
|
|
11954
|
-
style: { height: 14, justifyContent: "center" },
|
|
11955
|
-
accessibilityRole: "progressbar",
|
|
11956
|
-
accessibilityValue: { min: landmarks.mev, max: landmarks.mrv, now: weeklySets },
|
|
11957
|
-
accessibilityLabel: `${weeklySets} weekly sets, between MEV ${landmarks.mev} and MRV ${landmarks.mrv}`,
|
|
11958
|
-
"aria-valuenow": weeklySets,
|
|
11959
|
-
"aria-valuemin": landmarks.mev,
|
|
11960
|
-
"aria-valuemax": landmarks.mrv,
|
|
11961
|
-
testID: "body-map-detail-panel-volume-bar",
|
|
11962
|
-
children: [
|
|
11963
|
-
/* @__PURE__ */ jsx(
|
|
11964
|
-
reactNative.View,
|
|
11965
|
-
{
|
|
11966
|
-
style: { height: 8, borderRadius: 4, backgroundImage: VOLUME_GRADIENT },
|
|
11967
|
-
accessibilityElementsHidden: true
|
|
11968
|
-
}
|
|
11969
|
-
),
|
|
11970
|
-
/* @__PURE__ */ jsx(
|
|
11971
|
-
reactNative.View,
|
|
11972
|
-
{
|
|
11973
|
-
style: {
|
|
11974
|
-
position: "absolute",
|
|
11975
|
-
left: `${markerLeft}%`,
|
|
11976
|
-
marginLeft: -7,
|
|
11977
|
-
width: 14,
|
|
11978
|
-
height: 14,
|
|
11979
|
-
borderRadius: 7,
|
|
11980
|
-
borderWidth: 2,
|
|
11981
|
-
borderColor: TEXT_PRIMARY8,
|
|
11982
|
-
backgroundColor: SURFACE_ELEVATED,
|
|
11983
|
-
boxShadow: "0 0 4px rgba(0,0,0,0.5)"
|
|
11984
|
-
},
|
|
11985
|
-
accessibilityElementsHidden: true,
|
|
11986
|
-
testID: "body-map-detail-panel-volume-marker"
|
|
11987
|
-
}
|
|
11988
|
-
)
|
|
11989
|
-
]
|
|
11990
|
-
}
|
|
11991
|
-
)
|
|
11992
|
-
] }),
|
|
11993
|
-
/* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-baseline", style: { marginTop: 14, gap: 4 }, children: [
|
|
11994
|
-
/* @__PURE__ */ jsx(
|
|
11995
|
-
reactNative.Text,
|
|
11996
|
-
{
|
|
11997
|
-
style: {
|
|
11998
|
-
fontSize: 24,
|
|
11999
|
-
fontFamily: '"Space Grotesk", sans-serif',
|
|
12000
|
-
fontWeight: "700",
|
|
12001
|
-
color: TEXT_PRIMARY8
|
|
12002
|
-
},
|
|
12003
|
-
testID: "body-map-detail-panel-set-count",
|
|
12004
|
-
children: weeklySets
|
|
12005
|
-
}
|
|
12006
|
-
),
|
|
12007
|
-
/* @__PURE__ */ jsx(
|
|
12008
|
-
reactNative.Text,
|
|
12009
|
-
{
|
|
12010
|
-
style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY7 },
|
|
12011
|
-
testID: "body-map-detail-panel-mrv-suffix",
|
|
12012
|
-
children: `/ ${landmarks.mrv} MRV`
|
|
12013
|
-
}
|
|
12014
|
-
)
|
|
12015
|
-
] }),
|
|
12016
|
-
weeklyHistory != null && weeklyHistory.length > 0 && /* @__PURE__ */ jsxs(reactNative.View, { style: { marginTop: 14 }, testID: "body-map-detail-panel-sparkline", children: [
|
|
12017
|
-
/* @__PURE__ */ jsx(
|
|
12018
|
-
reactNative.Text,
|
|
12019
|
-
{
|
|
12020
|
-
style: {
|
|
12021
|
-
fontSize: 10,
|
|
12022
|
-
fontFamily: "Inter, sans-serif",
|
|
12023
|
-
fontWeight: "600",
|
|
12024
|
-
color: TEXT_TERTIARY7,
|
|
12025
|
-
marginBottom: 6
|
|
12026
|
-
},
|
|
12027
|
-
accessibilityElementsHidden: true,
|
|
12028
|
-
children: "VOLUME TREND"
|
|
12029
|
-
}
|
|
12030
|
-
),
|
|
12031
|
-
/* @__PURE__ */ jsx(Sparkline, { data: weeklyHistory, width: 80, height: 30, highlightLast: true })
|
|
12032
|
-
] }),
|
|
12033
|
-
hasContributing && /* @__PURE__ */ jsxs(reactNative.View, { style: { marginTop: 16 }, testID: "body-map-detail-panel-contributing", children: [
|
|
12034
|
-
/* @__PURE__ */ jsx(
|
|
12035
|
-
reactNative.Text,
|
|
12036
|
-
{
|
|
12037
|
-
style: {
|
|
12038
|
-
fontSize: 10,
|
|
12039
|
-
fontFamily: "Inter, sans-serif",
|
|
12040
|
-
fontWeight: "600",
|
|
12041
|
-
color: TEXT_TERTIARY7,
|
|
12042
|
-
marginBottom: 8
|
|
12043
|
-
},
|
|
12044
|
-
children: "CONTRIBUTING EXERCISES"
|
|
12045
|
-
}
|
|
12046
|
-
),
|
|
12047
|
-
contributingExercises.map((exercise, index) => /* @__PURE__ */ jsxs(
|
|
12048
|
-
reactNative.View,
|
|
12049
|
-
{
|
|
12050
|
-
className: "flex-row items-center justify-between",
|
|
12051
|
-
style: {
|
|
12052
|
-
gap: 10,
|
|
12053
|
-
paddingVertical: 8,
|
|
12054
|
-
paddingHorizontal: 12,
|
|
12055
|
-
marginBottom: 6,
|
|
12056
|
-
borderRadius: 8,
|
|
12057
|
-
backgroundColor: SURFACE_RAISED2,
|
|
12058
|
-
borderWidth: 1,
|
|
12059
|
-
borderColor: BORDER_DEFAULT3
|
|
12060
|
-
},
|
|
12061
|
-
testID: `body-map-detail-panel-contributing-${index}`,
|
|
12062
|
-
children: [
|
|
12063
|
-
/* @__PURE__ */ jsx(
|
|
12064
|
-
reactNative.Text,
|
|
12065
|
-
{
|
|
12066
|
-
style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_PRIMARY8 },
|
|
12067
|
-
testID: `body-map-detail-panel-contributing-${index}-name`,
|
|
12068
|
-
children: exercise.name
|
|
12069
|
-
}
|
|
12070
|
-
),
|
|
12071
|
-
/* @__PURE__ */ jsx(
|
|
12072
|
-
reactNative.Text,
|
|
12073
|
-
{
|
|
12074
|
-
style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY7 },
|
|
12075
|
-
testID: `body-map-detail-panel-contributing-${index}-detail`,
|
|
12076
|
-
children: `${exercise.sets} sets \xB7 ${Math.round(exercise.contributionWeight * 100)}%`
|
|
12077
|
-
}
|
|
12078
|
-
)
|
|
12079
|
-
]
|
|
12080
|
-
},
|
|
12081
|
-
`${exercise.name}-${index}`
|
|
12082
|
-
))
|
|
12083
|
-
] }),
|
|
12084
|
-
hasUpcoming && /* @__PURE__ */ jsxs(reactNative.View, { style: { marginTop: 16 }, testID: "body-map-detail-panel-upcoming", children: [
|
|
12085
|
-
/* @__PURE__ */ jsx(
|
|
12086
|
-
reactNative.Text,
|
|
12087
|
-
{
|
|
12088
|
-
style: {
|
|
12089
|
-
fontSize: 10,
|
|
12090
|
-
fontFamily: "Inter, sans-serif",
|
|
12091
|
-
fontWeight: "600",
|
|
12092
|
-
color: TEXT_TERTIARY7,
|
|
12093
|
-
marginBottom: 8
|
|
12094
|
-
},
|
|
12095
|
-
children: "UPCOMING"
|
|
12096
|
-
}
|
|
12097
|
-
),
|
|
12098
|
-
upcomingExercises.map((exercise, index) => /* @__PURE__ */ jsxs(
|
|
12099
|
-
reactNative.View,
|
|
12100
|
-
{
|
|
12101
|
-
className: "flex-row items-center justify-between",
|
|
12102
|
-
style: { gap: 10, paddingVertical: 6 },
|
|
12103
|
-
testID: `body-map-detail-panel-upcoming-${index}`,
|
|
12104
|
-
children: [
|
|
12105
|
-
/* @__PURE__ */ jsx(
|
|
12106
|
-
reactNative.Text,
|
|
12107
|
-
{
|
|
12108
|
-
style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_PRIMARY8 },
|
|
12109
|
-
testID: `body-map-detail-panel-upcoming-${index}-name`,
|
|
12110
|
-
children: exercise.name
|
|
12111
|
-
}
|
|
12112
|
-
),
|
|
12113
|
-
/* @__PURE__ */ jsx(
|
|
12114
|
-
reactNative.Text,
|
|
12115
|
-
{
|
|
12116
|
-
style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_TERTIARY7 },
|
|
12117
|
-
testID: `body-map-detail-panel-upcoming-${index}-detail`,
|
|
12118
|
-
children: `${exercise.workoutName} \xB7 ${exercise.sets} sets`
|
|
12119
|
-
}
|
|
12120
|
-
)
|
|
12121
|
-
]
|
|
12122
|
-
},
|
|
12123
|
-
`${exercise.name}-${index}`
|
|
12124
|
-
))
|
|
12125
|
-
] }),
|
|
12126
|
-
onViewExercises != null && /* @__PURE__ */ jsx(
|
|
12127
|
-
reactNative.Pressable,
|
|
12121
|
+
/* @__PURE__ */ jsx(
|
|
12122
|
+
reactNative.Text,
|
|
12128
12123
|
{
|
|
12129
|
-
onPress: onViewExercises,
|
|
12130
|
-
accessibilityRole: "button",
|
|
12131
|
-
accessibilityLabel: `View ${displayName} exercises`,
|
|
12132
12124
|
style: {
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
backgroundColor: "rgba(255,121,0,0.12)",
|
|
12138
|
-
borderWidth: 1,
|
|
12139
|
-
borderColor: "rgba(255,121,0,0.3)"
|
|
12125
|
+
fontSize: 15,
|
|
12126
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
12127
|
+
fontWeight: "700",
|
|
12128
|
+
color: BRAND_PRIMARY12
|
|
12140
12129
|
},
|
|
12141
|
-
|
|
12142
|
-
children: /* @__PURE__ */ jsx(reactNative.Text, { style: { fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "700", color: BRAND_PRIMARY11 }, children: "View exercises" })
|
|
12130
|
+
children: `${exercise.currentE1rm} ${exercise.unit}`
|
|
12143
12131
|
}
|
|
12144
12132
|
)
|
|
12145
12133
|
]
|
|
@@ -12147,6 +12135,346 @@ function BodyMapDetailPanel({
|
|
|
12147
12135
|
)
|
|
12148
12136
|
]
|
|
12149
12137
|
}
|
|
12138
|
+
),
|
|
12139
|
+
/* @__PURE__ */ jsx(TabBar, { active: tab, onSelect: setTab }),
|
|
12140
|
+
tab === "progress" && /* @__PURE__ */ jsxs(reactNative.View, { style: { gap: 14 }, testID: "exercise-detail-page-panel-progress", children: [
|
|
12141
|
+
/* @__PURE__ */ jsx(MesoStatusCard, { ...meso }),
|
|
12142
|
+
/* @__PURE__ */ jsx(StatStrip, { stats, unit: exercise.unit }),
|
|
12143
|
+
/* @__PURE__ */ jsx(SectionCard, { title: "Strength Trend", testID: "exercise-detail-page-trend", children: /* @__PURE__ */ jsx(
|
|
12144
|
+
StrengthTrendChart,
|
|
12145
|
+
{
|
|
12146
|
+
data: trend.data,
|
|
12147
|
+
projection: trend.projection,
|
|
12148
|
+
mesoBoundaries: trend.mesoBoundaries,
|
|
12149
|
+
width: CHART_WIDTH,
|
|
12150
|
+
height: CHART_HEIGHT,
|
|
12151
|
+
unit: exercise.unit,
|
|
12152
|
+
animateOnMount: false
|
|
12153
|
+
}
|
|
12154
|
+
) }),
|
|
12155
|
+
/* @__PURE__ */ jsx(SectionCard, { title: "Week-by-Week", testID: "exercise-detail-page-progression", children: /* @__PURE__ */ jsx(
|
|
12156
|
+
EntryList,
|
|
12157
|
+
{
|
|
12158
|
+
entries: progression,
|
|
12159
|
+
expandedId: expandedProgressId,
|
|
12160
|
+
onToggle: toggle(setExpandedProgressId),
|
|
12161
|
+
emptyLabel: "No progression logged yet",
|
|
12162
|
+
testID: "exercise-detail-page-progression-list"
|
|
12163
|
+
}
|
|
12164
|
+
) })
|
|
12165
|
+
] }),
|
|
12166
|
+
tab === "history" && /* @__PURE__ */ jsx(reactNative.View, { style: { gap: 14 }, testID: "exercise-detail-page-panel-history", children: /* @__PURE__ */ jsx(SectionCard, { title: "All Sessions", testID: "exercise-detail-page-history", children: /* @__PURE__ */ jsx(
|
|
12167
|
+
EntryList,
|
|
12168
|
+
{
|
|
12169
|
+
entries: history,
|
|
12170
|
+
expandedId: expandedHistoryId,
|
|
12171
|
+
onToggle: toggle(setExpandedHistoryId),
|
|
12172
|
+
emptyLabel: "No sessions logged yet",
|
|
12173
|
+
testID: "exercise-detail-page-history-list"
|
|
12174
|
+
}
|
|
12175
|
+
) }) }),
|
|
12176
|
+
tab === "advanced" && /* @__PURE__ */ jsxs(reactNative.View, { style: { gap: 14 }, testID: "exercise-detail-page-panel-advanced", children: [
|
|
12177
|
+
/* @__PURE__ */ jsx(SectionCard, { title: "Capacity Band", testID: "exercise-detail-page-capacity", children: /* @__PURE__ */ jsx(
|
|
12178
|
+
CapacityBandChart,
|
|
12179
|
+
{
|
|
12180
|
+
band: vbt.band,
|
|
12181
|
+
workouts: vbt.workouts,
|
|
12182
|
+
projection: vbt.projection,
|
|
12183
|
+
width: CHART_WIDTH,
|
|
12184
|
+
height: CHART_HEIGHT
|
|
12185
|
+
}
|
|
12186
|
+
) }),
|
|
12187
|
+
/* @__PURE__ */ jsx(VbtSummaryRow, { summary: vbtSummary }),
|
|
12188
|
+
/* @__PURE__ */ jsx(SectionCard, { title: "Velocity Breakdown", testID: "exercise-detail-page-velocity", children: /* @__PURE__ */ jsx(VbtBreakdown, { sets: vbt.sets }) })
|
|
12189
|
+
] })
|
|
12190
|
+
] })
|
|
12191
|
+
}
|
|
12192
|
+
);
|
|
12193
|
+
}
|
|
12194
|
+
var SURFACE_ELEVATED3 = "var(--color-surface-elevated)";
|
|
12195
|
+
var BORDER_DEFAULT5 = "var(--color-border-default)";
|
|
12196
|
+
var BRAND_PRIMARY13 = "#FF7900";
|
|
12197
|
+
var TEXT_PRIMARY9 = "var(--color-text-primary)";
|
|
12198
|
+
var TEXT_SECONDARY7 = "var(--color-text-secondary)";
|
|
12199
|
+
var TEXT_TERTIARY9 = "var(--color-text-tertiary)";
|
|
12200
|
+
var PAGE_BG3 = "var(--color-background-base)";
|
|
12201
|
+
function countCompletedSets(exercise) {
|
|
12202
|
+
if (exercise.setVelocities != null) return exercise.setVelocities.length;
|
|
12203
|
+
if (exercise.status === "completed") return exercise.totalPlannedSets;
|
|
12204
|
+
return 0;
|
|
12205
|
+
}
|
|
12206
|
+
function deriveWorkoutProgress(exercises) {
|
|
12207
|
+
let completedExercises = 0;
|
|
12208
|
+
let completedSets = 0;
|
|
12209
|
+
let totalSets = 0;
|
|
12210
|
+
for (const exercise of exercises) {
|
|
12211
|
+
if (exercise.status === "completed") completedExercises += 1;
|
|
12212
|
+
completedSets += countCompletedSets(exercise);
|
|
12213
|
+
totalSets += exercise.totalPlannedSets;
|
|
12214
|
+
}
|
|
12215
|
+
return {
|
|
12216
|
+
completedExercises,
|
|
12217
|
+
totalExercises: exercises.length,
|
|
12218
|
+
completedSets,
|
|
12219
|
+
totalSets,
|
|
12220
|
+
fraction: totalSets === 0 ? 0 : completedSets / totalSets
|
|
12221
|
+
};
|
|
12222
|
+
}
|
|
12223
|
+
function findActiveExercise(exercises) {
|
|
12224
|
+
return exercises.find((exercise) => exercise.status === "active") ?? null;
|
|
12225
|
+
}
|
|
12226
|
+
function statusToCardState(status, focused) {
|
|
12227
|
+
if (status === "upcoming") return "upcoming";
|
|
12228
|
+
return focused ? "expanded" : "collapsed";
|
|
12229
|
+
}
|
|
12230
|
+
function toActiveCardProps(exercise, focused, onToggle, supersetPosition = null, supersetColor) {
|
|
12231
|
+
const state = statusToCardState(exercise.status, focused);
|
|
12232
|
+
return {
|
|
12233
|
+
name: exercise.name,
|
|
12234
|
+
state,
|
|
12235
|
+
onToggle,
|
|
12236
|
+
summary: exercise.summary,
|
|
12237
|
+
e1rm: exercise.e1rm,
|
|
12238
|
+
isPR: exercise.isPR,
|
|
12239
|
+
tempo: exercise.tempo,
|
|
12240
|
+
setVelocities: exercise.setVelocities,
|
|
12241
|
+
totalPlannedSets: exercise.totalPlannedSets,
|
|
12242
|
+
sets: state === "expanded" ? exercise.sets : void 0,
|
|
12243
|
+
prescription: exercise.prescription,
|
|
12244
|
+
previousBest: exercise.previousBest,
|
|
12245
|
+
supersetPosition,
|
|
12246
|
+
supersetColor
|
|
12247
|
+
};
|
|
12248
|
+
}
|
|
12249
|
+
function groupExercises(exercises, supersets) {
|
|
12250
|
+
const byId = new Map(supersets.map((superset) => [superset.id, superset]));
|
|
12251
|
+
const groups = [];
|
|
12252
|
+
for (const exercise of exercises) {
|
|
12253
|
+
const superset = exercise.supersetId != null ? byId.get(exercise.supersetId) : void 0;
|
|
12254
|
+
const last = groups[groups.length - 1];
|
|
12255
|
+
if (superset != null && last?.type === "superset" && last.superset.id === superset.id) {
|
|
12256
|
+
last.exercises.push(exercise);
|
|
12257
|
+
} else if (superset != null) {
|
|
12258
|
+
groups.push({ type: "superset", superset, exercises: [exercise] });
|
|
12259
|
+
} else {
|
|
12260
|
+
groups.push({ type: "single", exercise });
|
|
12261
|
+
}
|
|
12262
|
+
}
|
|
12263
|
+
return groups;
|
|
12264
|
+
}
|
|
12265
|
+
function supersetPositionAt(index, length) {
|
|
12266
|
+
if (length === 1) return null;
|
|
12267
|
+
if (index === 0) return "first";
|
|
12268
|
+
if (index === length - 1) return "last";
|
|
12269
|
+
return "middle";
|
|
12270
|
+
}
|
|
12271
|
+
function WorkoutHeader({
|
|
12272
|
+
title,
|
|
12273
|
+
subtitle,
|
|
12274
|
+
progress
|
|
12275
|
+
}) {
|
|
12276
|
+
return /* @__PURE__ */ jsxs(reactNative.View, { style: { gap: 10 }, testID: "active-workout-page-header", children: [
|
|
12277
|
+
/* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-start justify-between", style: { gap: 8 }, children: [
|
|
12278
|
+
/* @__PURE__ */ jsxs(reactNative.View, { style: { flexShrink: 1 }, children: [
|
|
12279
|
+
/* @__PURE__ */ jsx(
|
|
12280
|
+
reactNative.Text,
|
|
12281
|
+
{
|
|
12282
|
+
accessibilityRole: "header",
|
|
12283
|
+
style: {
|
|
12284
|
+
fontSize: 20,
|
|
12285
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
12286
|
+
fontWeight: "700",
|
|
12287
|
+
color: TEXT_PRIMARY9
|
|
12288
|
+
},
|
|
12289
|
+
testID: "active-workout-page-title",
|
|
12290
|
+
children: title
|
|
12291
|
+
}
|
|
12292
|
+
),
|
|
12293
|
+
subtitle != null && /* @__PURE__ */ jsx(
|
|
12294
|
+
reactNative.Text,
|
|
12295
|
+
{
|
|
12296
|
+
style: {
|
|
12297
|
+
marginTop: 2,
|
|
12298
|
+
fontSize: 12,
|
|
12299
|
+
fontFamily: "Inter, sans-serif",
|
|
12300
|
+
color: TEXT_SECONDARY7
|
|
12301
|
+
},
|
|
12302
|
+
testID: "active-workout-page-subtitle",
|
|
12303
|
+
children: subtitle
|
|
12304
|
+
}
|
|
12305
|
+
)
|
|
12306
|
+
] }),
|
|
12307
|
+
/* @__PURE__ */ jsxs(reactNative.View, { style: { alignItems: "flex-end" }, testID: "active-workout-page-progress-count", children: [
|
|
12308
|
+
/* @__PURE__ */ jsx(
|
|
12309
|
+
reactNative.Text,
|
|
12310
|
+
{
|
|
12311
|
+
style: {
|
|
12312
|
+
fontSize: 15,
|
|
12313
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
12314
|
+
fontWeight: "700",
|
|
12315
|
+
color: BRAND_PRIMARY13,
|
|
12316
|
+
fontVariant: ["tabular-nums"]
|
|
12317
|
+
},
|
|
12318
|
+
children: `${progress.completedExercises}/${progress.totalExercises}`
|
|
12319
|
+
}
|
|
12320
|
+
),
|
|
12321
|
+
/* @__PURE__ */ jsx(
|
|
12322
|
+
reactNative.Text,
|
|
12323
|
+
{
|
|
12324
|
+
style: {
|
|
12325
|
+
fontSize: 10,
|
|
12326
|
+
fontFamily: "Inter, sans-serif",
|
|
12327
|
+
fontWeight: "600",
|
|
12328
|
+
letterSpacing: 0.4,
|
|
12329
|
+
textTransform: "uppercase",
|
|
12330
|
+
color: TEXT_TERTIARY9
|
|
12331
|
+
},
|
|
12332
|
+
children: `${progress.completedSets}/${progress.totalSets} sets`
|
|
12333
|
+
}
|
|
12334
|
+
)
|
|
12335
|
+
] })
|
|
12336
|
+
] }),
|
|
12337
|
+
/* @__PURE__ */ jsx(
|
|
12338
|
+
reactNative.View,
|
|
12339
|
+
{
|
|
12340
|
+
style: { height: 4, backgroundColor: BORDER_DEFAULT5, borderRadius: 2 },
|
|
12341
|
+
testID: "active-workout-page-progress-track",
|
|
12342
|
+
children: /* @__PURE__ */ jsx(
|
|
12343
|
+
reactNative.View,
|
|
12344
|
+
{
|
|
12345
|
+
style: {
|
|
12346
|
+
height: "100%",
|
|
12347
|
+
width: `${Math.round(progress.fraction * 100)}%`,
|
|
12348
|
+
backgroundColor: BRAND_PRIMARY13,
|
|
12349
|
+
borderRadius: 2
|
|
12350
|
+
},
|
|
12351
|
+
testID: "active-workout-page-progress-fill"
|
|
12352
|
+
}
|
|
12353
|
+
)
|
|
12354
|
+
}
|
|
12355
|
+
)
|
|
12356
|
+
] });
|
|
12357
|
+
}
|
|
12358
|
+
function ExerciseList({ groups, focusedId, onToggle }) {
|
|
12359
|
+
return /* @__PURE__ */ jsx(reactNative.View, { style: { gap: 10 }, testID: "active-workout-page-exercises", children: groups.map((group) => {
|
|
12360
|
+
if (group.type === "single") {
|
|
12361
|
+
return /* @__PURE__ */ jsx(
|
|
12362
|
+
reactNative.View,
|
|
12363
|
+
{
|
|
12364
|
+
style: {
|
|
12365
|
+
backgroundColor: SURFACE_ELEVATED3,
|
|
12366
|
+
borderWidth: 1,
|
|
12367
|
+
borderColor: BORDER_DEFAULT5,
|
|
12368
|
+
borderRadius: 12
|
|
12369
|
+
},
|
|
12370
|
+
children: /* @__PURE__ */ jsx(
|
|
12371
|
+
ExerciseCard,
|
|
12372
|
+
{
|
|
12373
|
+
...toActiveCardProps(
|
|
12374
|
+
group.exercise,
|
|
12375
|
+
group.exercise.id === focusedId,
|
|
12376
|
+
() => onToggle(group.exercise.id)
|
|
12377
|
+
)
|
|
12378
|
+
}
|
|
12379
|
+
)
|
|
12380
|
+
},
|
|
12381
|
+
group.exercise.id
|
|
12382
|
+
);
|
|
12383
|
+
}
|
|
12384
|
+
return /* @__PURE__ */ jsx(
|
|
12385
|
+
SupersetWrapper,
|
|
12386
|
+
{
|
|
12387
|
+
label: group.superset.label,
|
|
12388
|
+
color: group.superset.color,
|
|
12389
|
+
children: group.exercises.map((exercise, index) => /* @__PURE__ */ jsx(
|
|
12390
|
+
ExerciseCard,
|
|
12391
|
+
{
|
|
12392
|
+
...toActiveCardProps(
|
|
12393
|
+
exercise,
|
|
12394
|
+
exercise.id === focusedId,
|
|
12395
|
+
() => onToggle(exercise.id),
|
|
12396
|
+
supersetPositionAt(index, group.exercises.length),
|
|
12397
|
+
group.superset.color
|
|
12398
|
+
)
|
|
12399
|
+
},
|
|
12400
|
+
exercise.id
|
|
12401
|
+
))
|
|
12402
|
+
},
|
|
12403
|
+
group.superset.id
|
|
12404
|
+
);
|
|
12405
|
+
}) });
|
|
12406
|
+
}
|
|
12407
|
+
function ActiveWorkoutPage({
|
|
12408
|
+
title = "Active Workout",
|
|
12409
|
+
subtitle,
|
|
12410
|
+
exercises,
|
|
12411
|
+
supersets = [],
|
|
12412
|
+
input,
|
|
12413
|
+
rest,
|
|
12414
|
+
initialResting = false,
|
|
12415
|
+
className,
|
|
12416
|
+
...props
|
|
12417
|
+
}) {
|
|
12418
|
+
const active = findActiveExercise(exercises);
|
|
12419
|
+
const [focusedId, setFocusedId] = React24.useState(active?.id ?? null);
|
|
12420
|
+
const [resting, setResting] = React24.useState(initialResting);
|
|
12421
|
+
const [reps, setReps] = React24.useState(input?.reps ?? "");
|
|
12422
|
+
const [weight, setWeight] = React24.useState(input?.weight ?? "");
|
|
12423
|
+
const progress = React24.useMemo(() => deriveWorkoutProgress(exercises), [exercises]);
|
|
12424
|
+
const groups = React24.useMemo(() => groupExercises(exercises, supersets), [exercises, supersets]);
|
|
12425
|
+
const toggleFocus = (id) => setFocusedId((current) => current === id ? null : id);
|
|
12426
|
+
const nextSetNumber = active != null ? countCompletedSets(active) + 1 : 1;
|
|
12427
|
+
const canRecord = reps.trim() !== "" && weight.trim() !== "";
|
|
12428
|
+
const showRest = resting && rest != null;
|
|
12429
|
+
const showInput = !showRest && active != null;
|
|
12430
|
+
return /* @__PURE__ */ jsxs(
|
|
12431
|
+
reactNative.View,
|
|
12432
|
+
{
|
|
12433
|
+
className,
|
|
12434
|
+
style: { position: "relative", width: 390, backgroundColor: PAGE_BG3 },
|
|
12435
|
+
accessibilityRole: "main",
|
|
12436
|
+
"aria-label": title,
|
|
12437
|
+
testID: "active-workout-page",
|
|
12438
|
+
...props,
|
|
12439
|
+
children: [
|
|
12440
|
+
/* @__PURE__ */ jsxs(reactNative.View, { style: { padding: 16, gap: 14 }, testID: "active-workout-page-content", children: [
|
|
12441
|
+
/* @__PURE__ */ jsx(WorkoutHeader, { title, subtitle, progress }),
|
|
12442
|
+
/* @__PURE__ */ jsx(ExerciseList, { groups, focusedId, onToggle: toggleFocus })
|
|
12443
|
+
] }),
|
|
12444
|
+
(showRest || showInput) && /* @__PURE__ */ jsx(
|
|
12445
|
+
reactNative.View,
|
|
12446
|
+
{
|
|
12447
|
+
style: { borderTopWidth: 1, borderTopColor: BORDER_DEFAULT5 },
|
|
12448
|
+
testID: "active-workout-page-bottom-bar",
|
|
12449
|
+
children: showRest && rest != null ? /* @__PURE__ */ jsx(
|
|
12450
|
+
RestTimer,
|
|
12451
|
+
{
|
|
12452
|
+
totalSeconds: rest.totalSeconds,
|
|
12453
|
+
elapsedMs: rest.elapsedMs,
|
|
12454
|
+
nextSetInfo: rest.nextSetInfo,
|
|
12455
|
+
onSkip: () => setResting(false),
|
|
12456
|
+
onAddTime: () => void 0,
|
|
12457
|
+
visible: true
|
|
12458
|
+
}
|
|
12459
|
+
) : active != null && /* @__PURE__ */ jsx(
|
|
12460
|
+
InputBar,
|
|
12461
|
+
{
|
|
12462
|
+
exerciseName: active.name,
|
|
12463
|
+
setNumber: nextSetNumber,
|
|
12464
|
+
totalSets: active.totalPlannedSets,
|
|
12465
|
+
reps,
|
|
12466
|
+
weight,
|
|
12467
|
+
unit: active.unit,
|
|
12468
|
+
onRepsChange: setReps,
|
|
12469
|
+
onWeightChange: setWeight,
|
|
12470
|
+
onRecord: () => {
|
|
12471
|
+
if (rest != null) setResting(true);
|
|
12472
|
+
},
|
|
12473
|
+
canRecord,
|
|
12474
|
+
visible: true
|
|
12475
|
+
}
|
|
12476
|
+
)
|
|
12477
|
+
}
|
|
12150
12478
|
)
|
|
12151
12479
|
]
|
|
12152
12480
|
}
|
|
@@ -12469,7 +12797,7 @@ var DEFAULT_THRESHOLDS = [
|
|
|
12469
12797
|
var ARC_START = 135;
|
|
12470
12798
|
var ARC_SWEEP = 270;
|
|
12471
12799
|
var SEGMENTS = 40;
|
|
12472
|
-
function
|
|
12800
|
+
function clamp013(n) {
|
|
12473
12801
|
if (Number.isNaN(n)) return 0;
|
|
12474
12802
|
return Math.max(0, Math.min(1, n));
|
|
12475
12803
|
}
|
|
@@ -12514,7 +12842,7 @@ function Gauge2({
|
|
|
12514
12842
|
...props
|
|
12515
12843
|
}) {
|
|
12516
12844
|
const span = max - min || 1;
|
|
12517
|
-
const fill =
|
|
12845
|
+
const fill = clamp013((value - min) / span);
|
|
12518
12846
|
const activeColor = (f) => color ?? bandColor(f, thresholds, min, max);
|
|
12519
12847
|
const ticks = buildTicks(fill, size, activeColor);
|
|
12520
12848
|
const displayColor = color ?? bandColor(fill, thresholds, min, max);
|
|
@@ -12712,6 +13040,7 @@ exports.Accordion = Accordion;
|
|
|
12712
13040
|
exports.AccordionButton = AccordionButton;
|
|
12713
13041
|
exports.AccordionItem = AccordionItem;
|
|
12714
13042
|
exports.AccordionPanel = AccordionPanel;
|
|
13043
|
+
exports.ActiveWorkoutPage = ActiveWorkoutPage;
|
|
12715
13044
|
exports.Alert = Alert;
|
|
12716
13045
|
exports.AlertDescription = AlertDescription;
|
|
12717
13046
|
exports.AlertTitle = AlertTitle;
|
|
@@ -12722,8 +13051,6 @@ exports.AvatarGroup = AvatarGroup;
|
|
|
12722
13051
|
exports.Badge = Badge;
|
|
12723
13052
|
exports.BadgeText = BadgeText;
|
|
12724
13053
|
exports.BaseBadge = BaseBadge;
|
|
12725
|
-
exports.BodyMap = BodyMap;
|
|
12726
|
-
exports.BodyMapDetailPanel = BodyMapDetailPanel;
|
|
12727
13054
|
exports.BreadcrumbItem = BreadcrumbItem;
|
|
12728
13055
|
exports.Breadcrumbs = Breadcrumbs;
|
|
12729
13056
|
exports.Button = Button;
|
|
@@ -12746,8 +13073,6 @@ exports.CircularProgress = CircularProgress;
|
|
|
12746
13073
|
exports.Collapse = Collapse;
|
|
12747
13074
|
exports.CollapseButton = CollapseButton;
|
|
12748
13075
|
exports.CollapseContent = CollapseContent;
|
|
12749
|
-
exports.DEFAULT_VOLUME_LANDMARKS = DEFAULT_VOLUME_LANDMARKS;
|
|
12750
|
-
exports.DETAILED_TO_SIMPLE = DETAILED_TO_SIMPLE;
|
|
12751
13076
|
exports.DataRow = DataRow;
|
|
12752
13077
|
exports.DateTime = DateTime;
|
|
12753
13078
|
exports.DeviationBar = DeviationBar;
|
|
@@ -12756,8 +13081,10 @@ exports.Drawer = Drawer;
|
|
|
12756
13081
|
exports.DrawerBody = DrawerBody;
|
|
12757
13082
|
exports.DrawerFooter = DrawerFooter;
|
|
12758
13083
|
exports.DrawerHeader = DrawerHeader;
|
|
13084
|
+
exports.EXERCISE_DETAIL_TABS = EXERCISE_DETAIL_TABS;
|
|
12759
13085
|
exports.EmptyState = EmptyState;
|
|
12760
13086
|
exports.ExerciseCard = ExerciseCard;
|
|
13087
|
+
exports.ExerciseDetailPage = ExerciseDetailPage;
|
|
12761
13088
|
exports.FormActions = FormActions;
|
|
12762
13089
|
exports.FormField = FormField;
|
|
12763
13090
|
exports.FormRow = FormRow;
|
|
@@ -12780,9 +13107,6 @@ exports.ListItemContent = ListItemContent;
|
|
|
12780
13107
|
exports.ListItemDivider = ListItemDivider;
|
|
12781
13108
|
exports.ListItemIcon = ListItemIcon;
|
|
12782
13109
|
exports.ListItemTrailing = ListItemTrailing;
|
|
12783
|
-
exports.MUSCLE_DISPLAY_NAMES = MUSCLE_DISPLAY_NAMES;
|
|
12784
|
-
exports.MUSCLE_TO_CATEGORY = MUSCLE_TO_CATEGORY;
|
|
12785
|
-
exports.MUSCLE_TO_SVG_SLUGS = MUSCLE_TO_SVG_SLUGS;
|
|
12786
13110
|
exports.Menu = Menu;
|
|
12787
13111
|
exports.MenuDivider = MenuDivider;
|
|
12788
13112
|
exports.MenuGroup = MenuGroup;
|
|
@@ -12801,7 +13125,6 @@ exports.ModalContent = ModalContent;
|
|
|
12801
13125
|
exports.ModalFooter = ModalFooter;
|
|
12802
13126
|
exports.ModalHeader = ModalHeader;
|
|
12803
13127
|
exports.ModalTitle = ModalTitle;
|
|
12804
|
-
exports.MuscleGroup = MuscleGroup;
|
|
12805
13128
|
exports.MuscleGroupChip = MuscleGroupChip;
|
|
12806
13129
|
exports.Overline = Overline;
|
|
12807
13130
|
exports.Paragraph = Paragraph;
|
|
@@ -12814,14 +13137,13 @@ exports.PopoverContent = PopoverContent;
|
|
|
12814
13137
|
exports.PopoverTrigger = PopoverTrigger;
|
|
12815
13138
|
exports.PrBadge = PrBadge;
|
|
12816
13139
|
exports.PrHistoryModal = PrHistoryModal;
|
|
13140
|
+
exports.ProgramPlanningPage = ProgramPlanningPage;
|
|
12817
13141
|
exports.Progress = Progress;
|
|
12818
13142
|
exports.ProgressSteps = ProgressSteps;
|
|
12819
13143
|
exports.Radio = Radio;
|
|
12820
13144
|
exports.RadioGroup = RadioGroup;
|
|
12821
13145
|
exports.ReadinessCheck = ReadinessCheck;
|
|
12822
13146
|
exports.RestTimer = RestTimer;
|
|
12823
|
-
exports.SIMPLE_DISPLAY_NAMES = SIMPLE_DISPLAY_NAMES;
|
|
12824
|
-
exports.SIMPLE_TO_DETAILED = SIMPLE_TO_DETAILED;
|
|
12825
13147
|
exports.Scatter = Scatter;
|
|
12826
13148
|
exports.Section = Section;
|
|
12827
13149
|
exports.SectionContent = SectionContent;
|
|
@@ -12835,7 +13157,6 @@ exports.SidebarFooter = SidebarFooter;
|
|
|
12835
13157
|
exports.SidebarHeader = SidebarHeader;
|
|
12836
13158
|
exports.SidebarItem = SidebarItem;
|
|
12837
13159
|
exports.SidebarSection = SidebarSection;
|
|
12838
|
-
exports.SimpleMuscleGroup = SimpleMuscleGroup;
|
|
12839
13160
|
exports.Skeleton = Skeleton;
|
|
12840
13161
|
exports.SkeletonCard = SkeletonCard;
|
|
12841
13162
|
exports.SkeletonCircle = SkeletonCircle;
|
|
@@ -12874,7 +13195,6 @@ exports.ToolbarButtonGroup = ToolbarButtonGroup;
|
|
|
12874
13195
|
exports.Tooltip = Tooltip;
|
|
12875
13196
|
exports.Treemap = Treemap;
|
|
12876
13197
|
exports.Typography = Typography;
|
|
12877
|
-
exports.VOLUME_STATUS_LABELS = VOLUME_STATUS_LABELS;
|
|
12878
13198
|
exports.VStack = VStack;
|
|
12879
13199
|
exports.VelocityStrip = VelocityStrip;
|
|
12880
13200
|
exports.WeekRow = WeekRow;
|
|
@@ -12884,12 +13204,14 @@ exports.WorkoutPill = WorkoutPill;
|
|
|
12884
13204
|
exports.alpha = alpha;
|
|
12885
13205
|
exports.applyThemePreset = applyThemePreset;
|
|
12886
13206
|
exports.audiobookPreset = audiobookPreset;
|
|
13207
|
+
exports.buildBreadcrumbs = buildBreadcrumbs;
|
|
12887
13208
|
exports.buttonSizes = buttonSizes;
|
|
12888
13209
|
exports.calculateMeanVelocity = calculateMeanVelocity;
|
|
12889
13210
|
exports.calculateVelocityLoss = calculateVelocityLoss;
|
|
12890
13211
|
exports.cn = cn;
|
|
12891
13212
|
exports.componentElevationRanges = componentElevationRanges;
|
|
12892
13213
|
exports.composeValidators = composeValidators;
|
|
13214
|
+
exports.countCompletedSets = countCompletedSets;
|
|
12893
13215
|
exports.createFieldId = createFieldId;
|
|
12894
13216
|
exports.createFlatShadow = createFlatShadow;
|
|
12895
13217
|
exports.createPressedHoverShadow = createPressedHoverShadow;
|
|
@@ -12899,9 +13221,19 @@ exports.createRaisedShadow = createRaisedShadow;
|
|
|
12899
13221
|
exports.darkThemeCSSVars = darkThemeCSSVars;
|
|
12900
13222
|
exports.darken = darken;
|
|
12901
13223
|
exports.defaultPreset = defaultPreset;
|
|
13224
|
+
exports.deriveExerciseStats = deriveExerciseStats;
|
|
13225
|
+
exports.deriveNavLevel = deriveNavLevel;
|
|
13226
|
+
exports.deriveWorkoutProgress = deriveWorkoutProgress;
|
|
12902
13227
|
exports.discreteRainbow = discreteRainbow;
|
|
12903
13228
|
exports.elevationSystem = elevationSystem;
|
|
13229
|
+
exports.findActiveExercise = findActiveExercise;
|
|
13230
|
+
exports.findMeso = findMeso;
|
|
13231
|
+
exports.findWeek = findWeek;
|
|
13232
|
+
exports.findWorkout = findWorkout;
|
|
12904
13233
|
exports.formatDateTime = formatDateTime;
|
|
13234
|
+
exports.formatPrescription = formatPrescription;
|
|
13235
|
+
exports.formatSignedPct = formatSignedPct;
|
|
13236
|
+
exports.formatVelocity = formatVelocity;
|
|
12905
13237
|
exports.getBaseSurfaceColor = getBaseSurfaceColor;
|
|
12906
13238
|
exports.getContrastText = getContrastText;
|
|
12907
13239
|
exports.getDiscreteRainbowColor = getDiscreteRainbowColor;
|
|
@@ -12911,7 +13243,6 @@ exports.getElevationSurface = getElevationSurface;
|
|
|
12911
13243
|
exports.getFieldAriaProps = getFieldAriaProps;
|
|
12912
13244
|
exports.getFieldValidationProps = getFieldValidationProps;
|
|
12913
13245
|
exports.getGlowShadow = getGlowShadow;
|
|
12914
|
-
exports.getHeatmapColor = getHeatmapColor;
|
|
12915
13246
|
exports.getHoverColors = getHoverColors;
|
|
12916
13247
|
exports.getLuminance = getLuminance;
|
|
12917
13248
|
exports.getResultColor = getResultColor;
|
|
@@ -12922,6 +13253,7 @@ exports.getValidatedElevation = getValidatedElevation;
|
|
|
12922
13253
|
exports.getVelocityZoneColor = getVelocityZoneColor;
|
|
12923
13254
|
exports.getVelocityZoneName = getVelocityZoneName;
|
|
12924
13255
|
exports.gluestackConfig = gluestackConfig;
|
|
13256
|
+
exports.groupExercises = groupExercises;
|
|
12925
13257
|
exports.hasMaxLength = hasMaxLength;
|
|
12926
13258
|
exports.hasMinLength = hasMinLength;
|
|
12927
13259
|
exports.hexToRgb = hexToRgb;
|
|
@@ -12942,10 +13274,19 @@ exports.primitiveTypography = primitiveTypography;
|
|
|
12942
13274
|
exports.primitiveZIndex = primitiveZIndex;
|
|
12943
13275
|
exports.rgbToHex = rgbToHex;
|
|
12944
13276
|
exports.rgbToHsv = rgbToHsv;
|
|
13277
|
+
exports.roundRpe = roundRpe;
|
|
13278
|
+
exports.roundTempo = roundTempo;
|
|
13279
|
+
exports.roundWeight = roundWeight;
|
|
13280
|
+
exports.rpeColor = rpeColor;
|
|
12945
13281
|
exports.semanticColorsDark = semanticColorsDark;
|
|
12946
13282
|
exports.semanticColorsLight = semanticColorsLight;
|
|
12947
13283
|
exports.semanticTypography = semanticTypography;
|
|
12948
13284
|
exports.shadowColors = shadowColors;
|
|
13285
|
+
exports.statusToCardState = statusToCardState;
|
|
13286
|
+
exports.summarizeVbt = summarizeVbt;
|
|
13287
|
+
exports.toActiveCardProps = toActiveCardProps;
|
|
13288
|
+
exports.toExerciseCardProps = toExerciseCardProps;
|
|
13289
|
+
exports.toProgressBarMesos = toProgressBarMesos;
|
|
12949
13290
|
exports.useTable = useTable;
|
|
12950
13291
|
exports.useToast = useToast;
|
|
12951
13292
|
exports.useToolbarButton = useToolbarButton;
|