@titan-design/react-ui 0.6.0 → 0.7.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.js +12 -7
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +12 -7
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +855 -124
- package/dist/index.d.ts +855 -124
- package/dist/index.js +2276 -801
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2230 -802
- package/dist/index.mjs.map +1 -1
- package/dist/{pages-MO0JCySL.d.mts → pages-8u_4WbL-.d.mts} +280 -57
- package/dist/{pages-D7Jlssvp.d.ts → pages-DaWiBOGa.d.ts} +280 -57
- package/dist/pages.d.mts +1 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +1255 -798
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +1255 -798
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +16 -82
- package/dist/theme/index.d.ts +16 -82
- package/dist/theme/index.js +13 -115
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +13 -115
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +14 -6
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +14 -6
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/package.json +1 -1
- package/src/arch/Architecture.stories.tsx +870 -0
- package/src/arch/annotations.json +48 -0
- package/src/arch/arch-graph.json +4301 -0
- package/src/components/custom/DateTime/DateTime.stories.tsx +1 -1
- package/src/components/custom/EmptyState/EmptyState.stories.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.stories.tsx +1 -1
- package/src/components/custom/Metric/Metric.stories.tsx +1 -1
- package/src/components/custom/Scatter/Scatter.stories.tsx +1 -1
- package/src/components/custom/Sidebar/Sidebar.stories.tsx +1 -1
- package/src/components/custom/Table/Table.stories.tsx +1 -1
- package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +62 -0
- package/src/components/custom/TimerReadout/TimerReadout.test.tsx +72 -0
- package/src/components/custom/TimerReadout/TimerReadout.tsx +75 -0
- package/src/components/custom/TimerReadout/index.ts +1 -0
- package/src/components/custom/Treemap/Treemap.stories.tsx +1 -1
- package/src/components/custom/Typography/Typography.stories.tsx +1 -1
- package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +21 -13
- package/src/components/custom/Workout/ActiveWorkoutPage.test.tsx +16 -13
- package/src/components/custom/Workout/ActiveWorkoutPage.tsx +9 -15
- package/src/components/custom/Workout/BaseBadge.stories.tsx +1 -1
- package/src/components/custom/Workout/BodyMap.stories.tsx +1 -1
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +1 -1
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
- package/src/components/custom/Workout/ExerciseCard.stories.tsx +51 -66
- package/src/components/custom/Workout/ExerciseCard.test.tsx +146 -143
- package/src/components/custom/Workout/ExerciseCard.tsx +176 -198
- package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +99 -0
- package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +72 -0
- package/src/components/custom/Workout/ExerciseCardHeading.tsx +43 -0
- package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +151 -0
- package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +5 -3
- package/src/components/custom/Workout/ExerciseDetailPage.test.tsx +4 -4
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +4 -5
- package/src/components/custom/Workout/ExerciseHeading.stories.tsx +81 -0
- package/src/components/custom/Workout/ExerciseHeading.test.tsx +77 -0
- package/src/components/custom/Workout/ExerciseHeading.tsx +85 -0
- package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +110 -0
- package/src/components/custom/Workout/ExerciseIndicator.test.tsx +93 -0
- package/src/components/custom/Workout/ExerciseIndicator.tsx +120 -0
- package/src/components/custom/Workout/FatigueMeter.stories.tsx +51 -0
- package/src/components/custom/Workout/FatigueMeter.test.tsx +73 -0
- package/src/components/custom/Workout/FatigueMeter.tsx +82 -0
- package/src/components/custom/Workout/InputBar.stories.tsx +1 -1
- package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
- package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +153 -0
- package/src/components/custom/Workout/LiveAuraFrame.test.tsx +74 -0
- package/src/components/custom/Workout/LiveAuraFrame.tsx +105 -0
- package/src/components/custom/Workout/MesoCard.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoStatusCard.stories.tsx +1 -1
- package/src/components/custom/Workout/MetricTiles.stories.tsx +60 -0
- package/src/components/custom/Workout/MetricTiles.test.tsx +58 -0
- package/src/components/custom/Workout/MetricTiles.tsx +48 -0
- package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +1 -1
- package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
- package/src/components/custom/Workout/PrBadge.stories.tsx +1 -1
- package/src/components/custom/Workout/PrHistoryModal.stories.tsx +1 -1
- package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +4 -16
- package/src/components/custom/Workout/ProgramPlanningPage.tsx +8 -6
- package/src/components/custom/Workout/README.md +146 -4
- package/src/components/custom/Workout/ReadinessCheck.stories.tsx +1 -1
- package/src/components/custom/Workout/RestTimer.stories.tsx +1 -1
- package/src/components/custom/Workout/RestTimer.tsx +15 -10
- package/src/components/custom/Workout/RowInventory.stories.tsx +405 -0
- package/src/components/custom/Workout/S3FullRail.stories.tsx +34 -0
- package/src/components/custom/Workout/S3SessionPace.stories.tsx +95 -0
- package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +61 -0
- package/src/components/custom/Workout/S3SetTypes.stories.tsx +176 -0
- package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +240 -0
- package/src/components/custom/Workout/ScheduleTiles.stories.tsx +40 -0
- package/src/components/custom/Workout/ScheduleTiles.test.tsx +34 -0
- package/src/components/custom/Workout/ScheduleTiles.tsx +70 -0
- package/src/components/custom/Workout/SegmentedBar.stories.tsx +99 -0
- package/src/components/custom/Workout/SegmentedBar.test.tsx +77 -0
- package/src/components/custom/Workout/SegmentedBar.tsx +172 -0
- package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +50 -0
- package/src/components/custom/Workout/SegmentedProgressBar.test.tsx +80 -0
- package/src/components/custom/Workout/SegmentedProgressBar.tsx +67 -0
- package/src/components/custom/Workout/SessionHeader.stories.tsx +121 -0
- package/src/components/custom/Workout/SessionHeader.test.tsx +122 -0
- package/src/components/custom/Workout/SessionHeader.tsx +152 -0
- package/src/components/custom/Workout/SessionRail.stories.tsx +153 -0
- package/src/components/custom/Workout/SessionRail.test.tsx +86 -0
- package/src/components/custom/Workout/SessionRail.tsx +126 -0
- package/src/components/custom/Workout/SetBar.stories.tsx +124 -0
- package/src/components/custom/Workout/SetBar.test.tsx +123 -0
- package/src/components/custom/Workout/SetBar.tsx +171 -0
- package/src/components/custom/Workout/SetRow.stories.tsx +50 -100
- package/src/components/custom/Workout/SetRow.test.tsx +94 -166
- package/src/components/custom/Workout/SetRow.tsx +169 -232
- package/src/components/custom/Workout/SetStrip.stories.tsx +154 -0
- package/src/components/custom/Workout/SetStrip.test.tsx +109 -0
- package/src/components/custom/Workout/SetStrip.tsx +71 -0
- package/src/components/custom/Workout/SetTableHeader.stories.tsx +66 -0
- package/src/components/custom/Workout/SetTableHeader.test.tsx +47 -0
- package/src/components/custom/Workout/SetTableHeader.tsx +88 -0
- package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +47 -0
- package/src/components/custom/Workout/SetsRepsLoad.test.tsx +44 -0
- package/src/components/custom/Workout/SetsRepsLoad.tsx +52 -0
- package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusPill.stories.tsx +59 -0
- package/src/components/custom/Workout/StatusPill.test.tsx +63 -0
- package/src/components/custom/Workout/StatusPill.tsx +88 -0
- package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +1 -1
- package/src/components/custom/Workout/SupersetWrapper.stories.tsx +1 -1
- package/src/components/custom/Workout/TempoBar.stories.tsx +1 -1
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +12 -1
- package/src/components/custom/Workout/TempoDisplay.tsx +23 -33
- package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +1 -1
- package/src/components/custom/Workout/VelocityStrip.modalities.stories.tsx +254 -0
- package/src/components/custom/Workout/VelocityStrip.responsive.stories.tsx +145 -0
- package/src/components/custom/Workout/VelocityStrip.stories.tsx +129 -66
- package/src/components/custom/Workout/VelocityStrip.test.tsx +376 -141
- package/src/components/custom/Workout/VelocityStrip.tsx +508 -120
- package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +73 -0
- package/src/components/custom/Workout/VolumeLandmarkBar.test.tsx +119 -0
- package/src/components/custom/Workout/VolumeLandmarkBar.tsx +154 -0
- package/src/components/custom/Workout/WeekRow.stories.tsx +1 -1
- package/src/components/custom/Workout/WeightBadge.stories.tsx +1 -1
- package/src/components/custom/Workout/WorkoutCard.stories.tsx +2 -6
- package/src/components/custom/Workout/WorkoutCard.test.tsx +13 -46
- package/src/components/custom/Workout/WorkoutPill.stories.tsx +1 -1
- package/src/components/custom/Workout/ZoneTrack.stories.tsx +140 -0
- package/src/components/custom/Workout/ZoneTrack.test.tsx +200 -0
- package/src/components/custom/Workout/ZoneTrack.tsx +315 -0
- package/src/components/custom/Workout/index.ts +55 -2
- package/src/components/custom/Workout/metricText.stories.tsx +69 -0
- package/src/components/custom/Workout/metricText.tsx +34 -0
- package/src/components/custom/Workout/paceTone.test.ts +29 -0
- package/src/components/custom/Workout/paceTone.ts +27 -0
- package/src/components/custom/Workout/setHeadingKit.tsx +177 -0
- package/src/components/custom/index.ts +1 -0
- package/src/components/custom/stepper/Stepper.stories.tsx +1 -1
- package/src/components/icons/icons.stories.tsx +67 -2
- package/src/components/icons/icons.test.tsx +32 -2
- package/src/components/icons/icons.tsx +108 -0
- package/src/components/shell/BrandLockup.stories.tsx +3 -3
- package/src/components/shell/DashboardShell.stories.tsx +65 -0
- package/src/components/shell/DashboardShell.test.tsx +42 -0
- package/src/components/shell/DashboardShell.tsx +74 -0
- package/src/components/shell/DeviceIndicator.stories.tsx +2 -2
- package/src/components/shell/DeviceMenu.stories.tsx +5 -5
- package/src/components/shell/DeviceRow.stories.tsx +3 -3
- package/src/components/shell/NavItem.stories.tsx +52 -0
- package/src/components/shell/NavItem.test.tsx +35 -0
- package/src/components/shell/NavItem.tsx +75 -0
- package/src/components/shell/README.md +30 -0
- package/src/components/shell/SessionRailSpecimen.stories.tsx +753 -0
- package/src/components/shell/SessionStatePill.stories.tsx +3 -3
- package/src/components/shell/SessionStatePill.tsx +1 -1
- package/src/components/shell/SideNav.stories.tsx +81 -0
- package/src/components/shell/SideNav.test.tsx +51 -0
- package/src/components/shell/SideNav.tsx +74 -0
- package/src/components/shell/TopBar.stories.tsx +5 -5
- package/src/components/shell/index.ts +5 -0
- package/src/components/ui/alert/Alert.stories.tsx +1 -1
- package/src/components/ui/autocomplete/Autocomplete.stories.tsx +1 -1
- package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
- package/src/components/ui/badge/Badge.stories.tsx +1 -1
- package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
- package/src/components/ui/button/Button.stories.tsx +1 -1
- package/src/components/ui/card/Card.stories.tsx +1 -1
- package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
- package/src/components/ui/chip/Chip.stories.tsx +1 -1
- package/src/components/ui/collapse/Collapse.stories.tsx +1 -1
- package/src/components/ui/data-row/DataRow.stories.tsx +1 -1
- package/src/components/ui/divider/Divider.stories.tsx +1 -1
- package/src/components/ui/drawer/Drawer.stories.tsx +1 -1
- package/src/components/ui/form-field/FormField.stories.tsx +1 -1
- package/src/components/ui/help-tip/HelpTip.stories.tsx +1 -1
- package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/indicator/Indicator.stories.tsx +2 -2
- package/src/components/ui/indicator/Indicator.test.tsx +1 -0
- package/src/components/ui/indicator/Indicator.tsx +6 -1
- package/src/components/ui/input/Input.stories.tsx +1 -1
- package/src/components/ui/link/Link.stories.tsx +1 -1
- package/src/components/ui/list-item/ListItem.stories.tsx +1 -1
- package/src/components/ui/menu/Menu.stories.tsx +1 -1
- package/src/components/ui/modal/Modal.stories.tsx +1 -1
- package/src/components/ui/pill/Pill.stories.tsx +1 -1
- package/src/components/ui/popover/Popover.stories.tsx +1 -1
- package/src/components/ui/progress/Progress.stories.tsx +1 -1
- package/src/components/ui/radio/Radio.stories.tsx +1 -1
- package/src/components/ui/section/Section.stories.tsx +1 -1
- package/src/components/ui/select/Select.stories.tsx +1 -1
- package/src/components/ui/skeleton/Skeleton.stories.tsx +1 -1
- package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
- package/src/components/ui/stack/Stack.stories.tsx +1 -1
- package/src/components/ui/surface/Surface.stories.tsx +1 -1
- package/src/components/ui/switch/Switch.stories.tsx +1 -1
- package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
- package/src/components/ui/tile/Tile.stories.tsx +79 -0
- package/src/components/ui/tile/Tile.test.tsx +48 -0
- package/src/components/ui/tile/Tile.tsx +64 -0
- package/src/components/ui/tile/index.ts +2 -0
- package/src/components/ui/toast/Toast.stories.tsx +1 -1
- package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +1 -1
- package/src/components/ui/tooltip/Tooltip.stories.tsx +1 -1
- package/src/examples/react-hook-form/ReactHookForm.stories.tsx +1 -1
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useTimer.test.ts +150 -0
- package/src/hooks/useTimer.ts +77 -0
- package/src/index.ts +3 -0
- package/src/pages.ts +1 -1
- package/src/stories/PresetShowcase.stories.tsx +1 -1
- package/src/stories/ThemePresets.stories.tsx +1 -1
- package/src/theme/ColorSystem.stories.tsx +1 -1
- package/src/theme/Colors.stories.tsx +5 -8
- package/src/theme/config.ts +4 -0
- package/src/theme/elevation.stories.tsx +1 -1
- package/src/theme/global.css +5 -1
- package/src/theme/shadows.stories.tsx +1 -1
- package/src/theme/tokens/primitives.ts +11 -107
- package/src/theme/tokens/semantic.ts +8 -0
- package/src/theme/workout-tokens.ts +11 -7
- package/tailwind.config.js +5 -0
package/dist/index.mjs
CHANGED
|
@@ -76,6 +76,72 @@ function DumbbellIcon(props) {
|
|
|
76
76
|
function StarIcon(props) {
|
|
77
77
|
return /* @__PURE__ */ jsx(SvgIcon, { ...props, children: /* @__PURE__ */ jsx("path", { d: "M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z" }) });
|
|
78
78
|
}
|
|
79
|
+
function ActivityIcon(props) {
|
|
80
|
+
return /* @__PURE__ */ jsx(SvgIcon, { ...props, children: /* @__PURE__ */ jsx("path", { d: "M22 12h-4l-3 9L9 3l-3 9H2" }) });
|
|
81
|
+
}
|
|
82
|
+
function HistoryIcon(props) {
|
|
83
|
+
return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
|
|
84
|
+
/* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 1 0 3-6.7L3 8" }),
|
|
85
|
+
/* @__PURE__ */ jsx("path", { d: "M3 3v5h5" }),
|
|
86
|
+
/* @__PURE__ */ jsx("path", { d: "M12 7v5l4 2" })
|
|
87
|
+
] });
|
|
88
|
+
}
|
|
89
|
+
function LayersIcon(props) {
|
|
90
|
+
return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
|
|
91
|
+
/* @__PURE__ */ jsx("path", { d: "m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z" }),
|
|
92
|
+
/* @__PURE__ */ jsx("path", { d: "m6.08 9.5-3.49 1.59a1 1 0 0 0 0 1.81l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9a1 1 0 0 0 0-1.83l-3.5-1.59" }),
|
|
93
|
+
/* @__PURE__ */ jsx("path", { d: "m6.08 14.5-3.49 1.59a1 1 0 0 0 0 1.81l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9a1 1 0 0 0 0-1.83l-3.5-1.59" })
|
|
94
|
+
] });
|
|
95
|
+
}
|
|
96
|
+
function PersonStandingIcon(props) {
|
|
97
|
+
return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
|
|
98
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "5", r: "1" }),
|
|
99
|
+
/* @__PURE__ */ jsx("path", { d: "m9 20 3-6 3 6" }),
|
|
100
|
+
/* @__PURE__ */ jsx("path", { d: "m6 8 6 2 6-2" }),
|
|
101
|
+
/* @__PURE__ */ jsx("path", { d: "M12 10v4" })
|
|
102
|
+
] });
|
|
103
|
+
}
|
|
104
|
+
function ScaleIcon(props) {
|
|
105
|
+
return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
|
|
106
|
+
/* @__PURE__ */ jsx("path", { d: "m16 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z" }),
|
|
107
|
+
/* @__PURE__ */ jsx("path", { d: "m2 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z" }),
|
|
108
|
+
/* @__PURE__ */ jsx("path", { d: "M7 21h10" }),
|
|
109
|
+
/* @__PURE__ */ jsx("path", { d: "M12 3v18" }),
|
|
110
|
+
/* @__PURE__ */ jsx("path", { d: "M3 7h2c2 0 5-1 7-2 2 1 5 2 7 2h2" })
|
|
111
|
+
] });
|
|
112
|
+
}
|
|
113
|
+
function AlertTriangleIcon(props) {
|
|
114
|
+
return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
|
|
115
|
+
/* @__PURE__ */ jsx("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z" }),
|
|
116
|
+
/* @__PURE__ */ jsx("path", { d: "M12 9v4" }),
|
|
117
|
+
/* @__PURE__ */ jsx("path", { d: "M12 17h.01" })
|
|
118
|
+
] });
|
|
119
|
+
}
|
|
120
|
+
function TrendingDownIcon(props) {
|
|
121
|
+
return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
|
|
122
|
+
/* @__PURE__ */ jsx("path", { d: "M16 17h6v-6" }),
|
|
123
|
+
/* @__PURE__ */ jsx("path", { d: "m22 17-8.5-8.5-5 5L2 7" })
|
|
124
|
+
] });
|
|
125
|
+
}
|
|
126
|
+
function CircleSlashIcon(props) {
|
|
127
|
+
return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
|
|
128
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
129
|
+
/* @__PURE__ */ jsx("path", { d: "m9 15 6-6" })
|
|
130
|
+
] });
|
|
131
|
+
}
|
|
132
|
+
function AwardIcon(props) {
|
|
133
|
+
return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
|
|
134
|
+
/* @__PURE__ */ jsx("path", { d: "m15.477 12.89 1.515 8.526a.5.5 0 0 1-.81.47l-3.58-2.687a1 1 0 0 0-1.197 0l-3.586 2.686a.5.5 0 0 1-.81-.469l1.514-8.526" }),
|
|
135
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "8", r: "6" })
|
|
136
|
+
] });
|
|
137
|
+
}
|
|
138
|
+
function InfoIcon(props) {
|
|
139
|
+
return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
|
|
140
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
141
|
+
/* @__PURE__ */ jsx("path", { d: "M12 16v-4" }),
|
|
142
|
+
/* @__PURE__ */ jsx("path", { d: "M12 8h.01" })
|
|
143
|
+
] });
|
|
144
|
+
}
|
|
79
145
|
function cn(...inputs) {
|
|
80
146
|
return twMerge(clsx(inputs));
|
|
81
147
|
}
|
|
@@ -174,7 +240,7 @@ function AlertDescription({ children, className }) {
|
|
|
174
240
|
|
|
175
241
|
// src/theme/tokens/primitives.ts
|
|
176
242
|
var primitiveColors = {
|
|
177
|
-
// Blue scale
|
|
243
|
+
// Blue scale
|
|
178
244
|
blue: {
|
|
179
245
|
50: "#EFF6FF",
|
|
180
246
|
100: "#DBEAFE",
|
|
@@ -183,124 +249,36 @@ var primitiveColors = {
|
|
|
183
249
|
400: "#60A5FA",
|
|
184
250
|
500: "#3B82F6",
|
|
185
251
|
600: "#5048E5",
|
|
186
|
-
// Primary main
|
|
187
252
|
700: "#3832A0",
|
|
188
|
-
// Primary dark
|
|
189
253
|
800: "#1E40AF",
|
|
190
254
|
900: "#1E3A8A"
|
|
191
255
|
},
|
|
192
|
-
//
|
|
193
|
-
green: {
|
|
194
|
-
50: "#ECFDF5",
|
|
195
|
-
100: "#D1FAE5",
|
|
196
|
-
200: "#A7F3D0",
|
|
197
|
-
300: "#6EE7B7",
|
|
198
|
-
400: "#3FC79A",
|
|
199
|
-
// Secondary light
|
|
200
|
-
500: "#10B981",
|
|
201
|
-
// Secondary main
|
|
202
|
-
600: "#059669",
|
|
203
|
-
700: "#0B815A",
|
|
204
|
-
// Secondary dark
|
|
205
|
-
800: "#065F46",
|
|
206
|
-
900: "#064E3B"
|
|
207
|
-
},
|
|
208
|
-
// Teal scale (success)
|
|
209
|
-
teal: {
|
|
210
|
-
50: "#F0FDFA",
|
|
211
|
-
100: "#CCFBF1",
|
|
212
|
-
200: "#99F6E4",
|
|
213
|
-
300: "#5EEAD4",
|
|
214
|
-
400: "#43C6B7",
|
|
215
|
-
// Success light
|
|
216
|
-
500: "#14B8A6",
|
|
217
|
-
// Success main
|
|
218
|
-
600: "#0D9488",
|
|
219
|
-
700: "#0E8074",
|
|
220
|
-
// Success dark
|
|
221
|
-
800: "#115E59",
|
|
222
|
-
900: "#134E4A"
|
|
223
|
-
},
|
|
224
|
-
// Red scale (error)
|
|
256
|
+
// Red scale
|
|
225
257
|
red: {
|
|
226
258
|
50: "#FEF2F2",
|
|
227
259
|
100: "#FEE2E2",
|
|
228
260
|
200: "#FECACA",
|
|
229
261
|
300: "#FCA5A5",
|
|
230
262
|
400: "#DA6868",
|
|
231
|
-
// Error light
|
|
232
263
|
500: "#EF4444",
|
|
233
264
|
600: "#D14343",
|
|
234
|
-
// Error main
|
|
235
265
|
700: "#922E2E",
|
|
236
|
-
// Error dark
|
|
237
266
|
800: "#991B1B",
|
|
238
267
|
900: "#7F1D1D"
|
|
239
268
|
},
|
|
240
|
-
// Vivid
|
|
241
|
-
greenVivid: {
|
|
242
|
-
50: "#E9FBF0",
|
|
243
|
-
100: "#C8F7DA",
|
|
244
|
-
200: "#9FF0BF",
|
|
245
|
-
300: "#6BE79D",
|
|
246
|
-
400: "#47DE84",
|
|
247
|
-
// Success vivid light
|
|
248
|
-
500: "#2ED573",
|
|
249
|
-
// Success vivid main
|
|
250
|
-
600: "#22B85F",
|
|
251
|
-
700: "#1A9950",
|
|
252
|
-
// Success vivid dark
|
|
253
|
-
800: "#157A40",
|
|
254
|
-
900: "#105C30"
|
|
255
|
-
},
|
|
256
|
-
// Vivid red scale (alert)
|
|
269
|
+
// Vivid red scale
|
|
257
270
|
redVivid: {
|
|
258
271
|
50: "#FFECEE",
|
|
259
272
|
100: "#FFD6DB",
|
|
260
273
|
200: "#FFB3BC",
|
|
261
274
|
300: "#FF8593",
|
|
262
275
|
400: "#FF6070",
|
|
263
|
-
// Error vivid light
|
|
264
276
|
500: "#FF4757",
|
|
265
|
-
// Error vivid main
|
|
266
277
|
600: "#E63548",
|
|
267
278
|
700: "#C42539",
|
|
268
|
-
// Error vivid dark
|
|
269
279
|
800: "#9E1C2C",
|
|
270
280
|
900: "#7A1520"
|
|
271
281
|
},
|
|
272
|
-
// Amber scale (warning)
|
|
273
|
-
amber: {
|
|
274
|
-
50: "#FFFBEB",
|
|
275
|
-
100: "#FEF3C7",
|
|
276
|
-
200: "#FDE68A",
|
|
277
|
-
300: "#FCD34D",
|
|
278
|
-
400: "#FFBF4C",
|
|
279
|
-
// Warning light
|
|
280
|
-
500: "#FFB020",
|
|
281
|
-
// Warning main
|
|
282
|
-
600: "#B27B16",
|
|
283
|
-
// Warning dark
|
|
284
|
-
700: "#B45309",
|
|
285
|
-
800: "#92400E",
|
|
286
|
-
900: "#78350F"
|
|
287
|
-
},
|
|
288
|
-
// Sky/Blue scale (info)
|
|
289
|
-
sky: {
|
|
290
|
-
50: "#F0F9FF",
|
|
291
|
-
100: "#E0F2FE",
|
|
292
|
-
200: "#BAE6FD",
|
|
293
|
-
300: "#7DD3FC",
|
|
294
|
-
400: "#64B6F7",
|
|
295
|
-
// Info light
|
|
296
|
-
500: "#2196F3",
|
|
297
|
-
// Info main
|
|
298
|
-
600: "#0284C7",
|
|
299
|
-
700: "#0B79D0",
|
|
300
|
-
// Info dark
|
|
301
|
-
800: "#075985",
|
|
302
|
-
900: "#0C4A6E"
|
|
303
|
-
},
|
|
304
282
|
// Neutral/Gray scale
|
|
305
283
|
neutral: {
|
|
306
284
|
50: "#FAFAFA",
|
|
@@ -315,18 +293,6 @@ var primitiveColors = {
|
|
|
315
293
|
900: "#111827",
|
|
316
294
|
950: "#030712"
|
|
317
295
|
},
|
|
318
|
-
// Orange scale (accent/brand color)
|
|
319
|
-
accent: {
|
|
320
|
-
100: "#FFA860",
|
|
321
|
-
200: "#FF9630",
|
|
322
|
-
300: "#FF8500",
|
|
323
|
-
400: "#FF7900",
|
|
324
|
-
500: "#F56C00",
|
|
325
|
-
600: "#E06D10",
|
|
326
|
-
700: "#D0620C",
|
|
327
|
-
800: "#B75500",
|
|
328
|
-
900: "#A34900"
|
|
329
|
-
},
|
|
330
296
|
// Charcoal scale (dark backgrounds)
|
|
331
297
|
charcoal: {
|
|
332
298
|
0: "#6E6E6E",
|
|
@@ -341,18 +307,6 @@ var primitiveColors = {
|
|
|
341
307
|
800: "#131313",
|
|
342
308
|
900: "#101010"
|
|
343
309
|
},
|
|
344
|
-
// Steel scale (cool accent)
|
|
345
|
-
steel: {
|
|
346
|
-
100: "#8AA4B8",
|
|
347
|
-
200: "#7894A8",
|
|
348
|
-
300: "#678498",
|
|
349
|
-
400: "#557488",
|
|
350
|
-
500: "#406D87",
|
|
351
|
-
600: "#39617A",
|
|
352
|
-
700: "#32556D",
|
|
353
|
-
800: "#243D53",
|
|
354
|
-
900: "#1D3146"
|
|
355
|
-
},
|
|
356
310
|
// Pure colors
|
|
357
311
|
white: "#FFFFFF",
|
|
358
312
|
black: "#000000",
|
|
@@ -743,6 +697,9 @@ var semanticColorsLight = {
|
|
|
743
697
|
"status-success-light": primitiveRamps.green[200],
|
|
744
698
|
"status-success-dark": primitiveRamps.green[600],
|
|
745
699
|
"status-success-subtle": primitiveRamps.green[50],
|
|
700
|
+
// Live-session accent — its OWN role, decoupled from success so the two can diverge
|
|
701
|
+
"status-live": primitiveRamps.green[300],
|
|
702
|
+
"status-live-muted": primitiveRamps.green[500],
|
|
746
703
|
"status-error": primitiveRamps.red[600],
|
|
747
704
|
"status-error-light": primitiveRamps.red[500],
|
|
748
705
|
"status-error-dark": primitiveRamps.red[700],
|
|
@@ -876,6 +833,9 @@ var semanticColorsDark = {
|
|
|
876
833
|
"status-success-light": primitiveRamps.green[200],
|
|
877
834
|
"status-success-dark": primitiveRamps.green[600],
|
|
878
835
|
"status-success-subtle": "rgba(46, 213, 115, 0.12)",
|
|
836
|
+
// Live-session accent — its OWN role, decoupled from success so the two can diverge
|
|
837
|
+
"status-live": primitiveRamps.green[300],
|
|
838
|
+
"status-live-muted": primitiveRamps.green[500],
|
|
879
839
|
"status-error": primitiveRamps.red[600],
|
|
880
840
|
"status-error-light": primitiveRamps.red[500],
|
|
881
841
|
"status-error-dark": primitiveRamps.red[700],
|
|
@@ -1470,6 +1430,8 @@ var lightThemeCSSVars = {
|
|
|
1470
1430
|
"--color-on-brand-secondary": semanticColorsLight["on-brand-secondary"],
|
|
1471
1431
|
"--color-status-success": semanticColorsLight["status-success"],
|
|
1472
1432
|
"--color-status-success-subtle": semanticColorsLight["status-success-subtle"],
|
|
1433
|
+
"--color-status-live": semanticColorsLight["status-live"],
|
|
1434
|
+
"--color-status-live-muted": semanticColorsLight["status-live-muted"],
|
|
1473
1435
|
"--color-status-error": semanticColorsLight["status-error"],
|
|
1474
1436
|
"--color-status-error-subtle": semanticColorsLight["status-error-subtle"],
|
|
1475
1437
|
"--color-status-warning": semanticColorsLight["status-warning"],
|
|
@@ -1566,6 +1528,8 @@ var darkThemeCSSVars = {
|
|
|
1566
1528
|
"--color-on-brand-secondary": semanticColorsDark["on-brand-secondary"],
|
|
1567
1529
|
"--color-status-success": semanticColorsDark["status-success"],
|
|
1568
1530
|
"--color-status-success-subtle": semanticColorsDark["status-success-subtle"],
|
|
1531
|
+
"--color-status-live": semanticColorsDark["status-live"],
|
|
1532
|
+
"--color-status-live-muted": semanticColorsDark["status-live-muted"],
|
|
1569
1533
|
"--color-status-error": semanticColorsDark["status-error"],
|
|
1570
1534
|
"--color-status-error-subtle": semanticColorsDark["status-error-subtle"],
|
|
1571
1535
|
"--color-status-warning": semanticColorsDark["status-warning"],
|
|
@@ -2783,6 +2747,7 @@ var colorStyles = {
|
|
|
2783
2747
|
default: "bg-text-tertiary",
|
|
2784
2748
|
primary: "bg-brand-primary",
|
|
2785
2749
|
success: "bg-status-success",
|
|
2750
|
+
live: "bg-status-live",
|
|
2786
2751
|
error: "bg-status-error",
|
|
2787
2752
|
warning: "bg-status-warning",
|
|
2788
2753
|
info: "bg-status-info",
|
|
@@ -2839,7 +2804,7 @@ function Indicator({
|
|
|
2839
2804
|
colorClass,
|
|
2840
2805
|
pulseMode === "opacity" && "animate-pulse",
|
|
2841
2806
|
ring && "border-2 border-background-base",
|
|
2842
|
-
glow && !customColor && color === "success" && "shadow-[0_0_6px_rgba(46,213,115,0.6)]",
|
|
2807
|
+
glow && !customColor && (color === "success" || color === "live") && "shadow-[0_0_6px_rgba(46,213,115,0.6)]",
|
|
2843
2808
|
glow && !customColor && color === "error" && "shadow-[0_0_6px_rgba(239,68,68,0.6)]",
|
|
2844
2809
|
glow && !customColor && color === "warning" && "shadow-[0_0_6px_rgba(245,158,11,0.6)]",
|
|
2845
2810
|
glow && !customColor && color === "primary" && "shadow-[0_0_6px_rgba(255,121,0,0.6)]",
|
|
@@ -5263,7 +5228,7 @@ function ToastProvider({
|
|
|
5263
5228
|
return id;
|
|
5264
5229
|
}, [defaultDuration, maxToasts]);
|
|
5265
5230
|
const removeToast = useCallback((id) => {
|
|
5266
|
-
setToasts((prev) => prev.filter((
|
|
5231
|
+
setToasts((prev) => prev.filter((t18) => t18.id !== id));
|
|
5267
5232
|
}, []);
|
|
5268
5233
|
const removeAllToasts = useCallback(() => {
|
|
5269
5234
|
setToasts([]);
|
|
@@ -6132,6 +6097,50 @@ function Pill({
|
|
|
6132
6097
|
}
|
|
6133
6098
|
return /* @__PURE__ */ jsx(View, { className: containerClasses, ...props, children: content });
|
|
6134
6099
|
}
|
|
6100
|
+
function Tile({
|
|
6101
|
+
label,
|
|
6102
|
+
value,
|
|
6103
|
+
valueColor,
|
|
6104
|
+
align = "center",
|
|
6105
|
+
className,
|
|
6106
|
+
...props
|
|
6107
|
+
}) {
|
|
6108
|
+
const isCenter = align === "center";
|
|
6109
|
+
return /* @__PURE__ */ jsxs(
|
|
6110
|
+
View,
|
|
6111
|
+
{
|
|
6112
|
+
className: cn(
|
|
6113
|
+
"flex-1 rounded-md bg-surface-raised px-1.5 py-2",
|
|
6114
|
+
isCenter ? "items-center" : "items-start",
|
|
6115
|
+
className
|
|
6116
|
+
),
|
|
6117
|
+
...props,
|
|
6118
|
+
children: [
|
|
6119
|
+
/* @__PURE__ */ jsx(
|
|
6120
|
+
Text,
|
|
6121
|
+
{
|
|
6122
|
+
className: cn(
|
|
6123
|
+
"text-[10px] font-bold uppercase tracking-wider text-text-tertiary",
|
|
6124
|
+
isCenter ? "text-center" : "text-left"
|
|
6125
|
+
),
|
|
6126
|
+
children: label
|
|
6127
|
+
}
|
|
6128
|
+
),
|
|
6129
|
+
/* @__PURE__ */ jsx(
|
|
6130
|
+
Text,
|
|
6131
|
+
{
|
|
6132
|
+
className: cn(
|
|
6133
|
+
"mt-0.5 font-mono text-sm font-bold text-text-primary",
|
|
6134
|
+
isCenter ? "text-center" : "text-left"
|
|
6135
|
+
),
|
|
6136
|
+
style: valueColor ? { color: valueColor } : void 0,
|
|
6137
|
+
children: value
|
|
6138
|
+
}
|
|
6139
|
+
)
|
|
6140
|
+
]
|
|
6141
|
+
}
|
|
6142
|
+
);
|
|
6143
|
+
}
|
|
6135
6144
|
var variantStyles4 = {
|
|
6136
6145
|
h1: "font-heading text-5xl font-bold leading-tight",
|
|
6137
6146
|
h2: "font-heading text-4xl font-bold leading-tight",
|
|
@@ -6991,6 +7000,79 @@ function formatDateTime(value, format = "datetime", isUTC = false, fallback = "-
|
|
|
6991
7000
|
}
|
|
6992
7001
|
return formatDate(value, format, isUTC);
|
|
6993
7002
|
}
|
|
7003
|
+
function formatDuration(ms) {
|
|
7004
|
+
const totalSeconds = Math.max(0, Math.ceil(ms / 1e3));
|
|
7005
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
7006
|
+
const seconds = totalSeconds % 60;
|
|
7007
|
+
return `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
7008
|
+
}
|
|
7009
|
+
function useTimer(options = {}) {
|
|
7010
|
+
const {
|
|
7011
|
+
mode = "up",
|
|
7012
|
+
durationMs,
|
|
7013
|
+
elapsedMs: controlledElapsedMs,
|
|
7014
|
+
running = false,
|
|
7015
|
+
autoTick = false,
|
|
7016
|
+
tickMs = 1e3
|
|
7017
|
+
} = options;
|
|
7018
|
+
const isControlled = controlledElapsedMs != null;
|
|
7019
|
+
const [internalElapsedMs, setInternalElapsedMs] = useState(0);
|
|
7020
|
+
useEffect(() => {
|
|
7021
|
+
if (isControlled || !autoTick || !running) return;
|
|
7022
|
+
const id = setInterval(() => {
|
|
7023
|
+
setInternalElapsedMs((prev) => prev + tickMs);
|
|
7024
|
+
}, tickMs);
|
|
7025
|
+
return () => clearInterval(id);
|
|
7026
|
+
}, [isControlled, autoTick, running, tickMs]);
|
|
7027
|
+
const elapsedMs = isControlled ? controlledElapsedMs : internalElapsedMs;
|
|
7028
|
+
const hasDuration = durationMs != null && durationMs > 0;
|
|
7029
|
+
const remainingMs = durationMs != null ? Math.max(0, durationMs - elapsedMs) : 0;
|
|
7030
|
+
let progress;
|
|
7031
|
+
if (hasDuration) {
|
|
7032
|
+
progress = Math.min(1, Math.max(0, elapsedMs / durationMs));
|
|
7033
|
+
} else {
|
|
7034
|
+
progress = mode === "down" ? 1 : 0;
|
|
7035
|
+
}
|
|
7036
|
+
const label = formatDuration(mode === "down" ? remainingMs : elapsedMs);
|
|
7037
|
+
const done = durationMs != null && elapsedMs >= durationMs;
|
|
7038
|
+
return { elapsedMs, remainingMs, progress, label, done };
|
|
7039
|
+
}
|
|
7040
|
+
|
|
7041
|
+
// src/components/custom/TimerReadout/TimerReadout.tsx
|
|
7042
|
+
var semantic = getSemanticColors("dark");
|
|
7043
|
+
var LIVE_GREEN = primitiveRamps.green[500];
|
|
7044
|
+
var SECONDARY = semantic["text-secondary"];
|
|
7045
|
+
var TERTIARY = semantic["text-tertiary"];
|
|
7046
|
+
var DEFAULT_GLYPH = "\u23F1";
|
|
7047
|
+
function TimerReadout({
|
|
7048
|
+
mode = "up",
|
|
7049
|
+
elapsedMs,
|
|
7050
|
+
durationMs,
|
|
7051
|
+
running = false,
|
|
7052
|
+
autoTick = false,
|
|
7053
|
+
showTotal = false,
|
|
7054
|
+
glyph = DEFAULT_GLYPH,
|
|
7055
|
+
className,
|
|
7056
|
+
...rest
|
|
7057
|
+
}) {
|
|
7058
|
+
const { label } = useTimer({ mode, durationMs, elapsedMs, running, autoTick });
|
|
7059
|
+
const currentColor = running ? LIVE_GREEN : SECONDARY;
|
|
7060
|
+
const total = showTotal && durationMs != null ? formatDuration(durationMs) : null;
|
|
7061
|
+
return /* @__PURE__ */ jsx(
|
|
7062
|
+
View,
|
|
7063
|
+
{
|
|
7064
|
+
accessibilityRole: "timer",
|
|
7065
|
+
accessibilityLabel: total != null ? `${label} of ${total}` : label,
|
|
7066
|
+
className: cn("flex-row items-baseline justify-end", className),
|
|
7067
|
+
...rest,
|
|
7068
|
+
children: /* @__PURE__ */ jsxs(Typography, { variant: "mono", style: { fontSize: 11, textAlign: "right" }, children: [
|
|
7069
|
+
/* @__PURE__ */ jsx(Text, { testID: "timer-readout-glyph", style: { color: currentColor, marginRight: 3 }, children: glyph }),
|
|
7070
|
+
/* @__PURE__ */ jsx(Text, { testID: "timer-readout-current", style: { color: currentColor }, children: label }),
|
|
7071
|
+
total != null ? /* @__PURE__ */ jsx(Text, { testID: "timer-readout-total", style: { color: TERTIARY }, children: ` / ${total}` }) : null
|
|
7072
|
+
] })
|
|
7073
|
+
}
|
|
7074
|
+
);
|
|
7075
|
+
}
|
|
6994
7076
|
var sizeConfig2 = {
|
|
6995
7077
|
sm: { value: "text-lg font-bold", label: "text-xs", unit: "text-xs" },
|
|
6996
7078
|
md: { value: "text-2xl font-bold", label: "text-xs", unit: "text-sm" },
|
|
@@ -7420,15 +7502,22 @@ var WORKOUT_TOKENS = {
|
|
|
7420
7502
|
// Canonical 4-band performance scale — the single source for BOTH the
|
|
7421
7503
|
// VelocityStrip zone bars and the SetRow RPE color (TD-03.43). The direction
|
|
7422
7504
|
// is intentionally inverted between the two consumers: for velocity, green =
|
|
7423
|
-
// fastest/best; for RPE, green = easiest. This is the [0,
|
|
7424
|
-
// the canonical `sequentialEffort` primitive
|
|
7425
|
-
//
|
|
7505
|
+
// fastest/best; for RPE, green = easiest. This is the [0,2,3,4] subsample of
|
|
7506
|
+
// the canonical `sequentialEffort` primitive: an EVEN hue walk across the ramp
|
|
7507
|
+
// (green → gold → orange → red). The earlier [0,1,2,4] spent two of its four
|
|
7508
|
+
// bands on adjacent yellows (amber-200 + amber-300) and skipped orange, reading
|
|
7509
|
+
// yellow-heavy with an abrupt jump to red; sampling amber-300 + orange-400
|
|
7510
|
+
// instead gives four cleanly separable bands that hold at 3px strip scale.
|
|
7511
|
+
// Consumed inline (RN).
|
|
7426
7512
|
scale: {
|
|
7427
7513
|
green: sequentialEffort[0],
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
// gold
|
|
7514
|
+
// green-300
|
|
7515
|
+
yellow: sequentialEffort[2],
|
|
7516
|
+
// amber-300 (gold)
|
|
7517
|
+
orange: sequentialEffort[3],
|
|
7518
|
+
// orange-400 (true orange)
|
|
7431
7519
|
red: sequentialEffort[4]
|
|
7520
|
+
// red-600
|
|
7432
7521
|
},
|
|
7433
7522
|
// BodyMap volume heatmap — the canonical `divergingScale` (under → optimal →
|
|
7434
7523
|
// over): a true diverging shape with a light green center, cool-blue under-
|
|
@@ -7553,8 +7642,8 @@ function roundTempo(tempo) {
|
|
|
7553
7642
|
return tempo.map((v) => Math.round(v * 10) / 10);
|
|
7554
7643
|
}
|
|
7555
7644
|
function formatSignedPct(ratio) {
|
|
7556
|
-
const
|
|
7557
|
-
return `${
|
|
7645
|
+
const pct2 = Math.round(ratio * 100);
|
|
7646
|
+
return `${pct2 > 0 ? "+" : ""}${pct2}%`;
|
|
7558
7647
|
}
|
|
7559
7648
|
function formatPrescription(p) {
|
|
7560
7649
|
if (p == null) return null;
|
|
@@ -7700,7 +7789,7 @@ function ActiveSegment({
|
|
|
7700
7789
|
const pacing = getTempoPacingState(phaseElapsedMs, targetMs);
|
|
7701
7790
|
const barColor = pacing === "behind" ? t2["status-error"] : config.color;
|
|
7702
7791
|
const fillPct = getTempoFillPct(phaseElapsedMs, targetMs);
|
|
7703
|
-
const label = targetMs ? `${
|
|
7792
|
+
const label = targetMs ? `${formatDuration2(phaseElapsedMs)} / ${formatDuration2(targetMs)}` : formatDuration2(phaseElapsedMs);
|
|
7704
7793
|
return /* @__PURE__ */ jsxs(View, { style: { height: "100%", position: "relative" }, testID: `tempo-segment-active-${config.label}`, children: [
|
|
7705
7794
|
/* @__PURE__ */ jsx(
|
|
7706
7795
|
View,
|
|
@@ -7750,16 +7839,32 @@ function CompletedSegment({
|
|
|
7750
7839
|
},
|
|
7751
7840
|
testID: `tempo-segment-completed-${config.label}`,
|
|
7752
7841
|
children: /* @__PURE__ */ jsxs(Text, { style: { fontSize: 12, fontWeight: "500", color: alpha(config.color, 0.7) }, children: [
|
|
7753
|
-
|
|
7842
|
+
formatDuration2(completedMs),
|
|
7754
7843
|
indicator
|
|
7755
7844
|
] })
|
|
7756
7845
|
}
|
|
7757
7846
|
);
|
|
7758
7847
|
}
|
|
7759
|
-
function
|
|
7848
|
+
function formatDuration2(ms) {
|
|
7760
7849
|
const s = ms / 1e3;
|
|
7761
7850
|
return s < 10 ? s.toFixed(1) : Math.round(s).toString();
|
|
7762
7851
|
}
|
|
7852
|
+
var METRIC_FONT = "Inter, sans-serif";
|
|
7853
|
+
function MetricCell({ children, color, fontSize = 11 }) {
|
|
7854
|
+
return /* @__PURE__ */ jsx(
|
|
7855
|
+
Text,
|
|
7856
|
+
{
|
|
7857
|
+
style: {
|
|
7858
|
+
fontFamily: METRIC_FONT,
|
|
7859
|
+
fontSize,
|
|
7860
|
+
color,
|
|
7861
|
+
fontWeight: "600",
|
|
7862
|
+
letterSpacing: 1
|
|
7863
|
+
},
|
|
7864
|
+
children
|
|
7865
|
+
}
|
|
7866
|
+
);
|
|
7867
|
+
}
|
|
7763
7868
|
|
|
7764
7869
|
// src/components/custom/Workout/TempoDisplay.tsx
|
|
7765
7870
|
var t3 = getSemanticColors("dark");
|
|
@@ -7778,34 +7883,10 @@ function TempoValue({
|
|
|
7778
7883
|
color,
|
|
7779
7884
|
fontSize
|
|
7780
7885
|
}) {
|
|
7781
|
-
return /* @__PURE__ */ jsx(
|
|
7782
|
-
Text,
|
|
7783
|
-
{
|
|
7784
|
-
style: {
|
|
7785
|
-
fontFamily: INTER,
|
|
7786
|
-
fontSize,
|
|
7787
|
-
color,
|
|
7788
|
-
fontWeight: "600",
|
|
7789
|
-
letterSpacing: 1
|
|
7790
|
-
},
|
|
7791
|
-
children: value
|
|
7792
|
-
}
|
|
7793
|
-
);
|
|
7886
|
+
return /* @__PURE__ */ jsx(MetricCell, { color, fontSize, children: value });
|
|
7794
7887
|
}
|
|
7795
7888
|
function TempoSeparator({ color, fontSize }) {
|
|
7796
|
-
return /* @__PURE__ */ jsx(
|
|
7797
|
-
Text,
|
|
7798
|
-
{
|
|
7799
|
-
style: {
|
|
7800
|
-
fontFamily: INTER,
|
|
7801
|
-
fontSize,
|
|
7802
|
-
color,
|
|
7803
|
-
fontWeight: "600",
|
|
7804
|
-
letterSpacing: 1
|
|
7805
|
-
},
|
|
7806
|
-
children: "-"
|
|
7807
|
-
}
|
|
7808
|
-
);
|
|
7889
|
+
return /* @__PURE__ */ jsx(MetricCell, { color, fontSize, children: "-" });
|
|
7809
7890
|
}
|
|
7810
7891
|
var LIVE_PHASES = [
|
|
7811
7892
|
{ key: "eccentric", color: phaseColors.eccentric },
|
|
@@ -7867,6 +7948,7 @@ function TempoDisplay({
|
|
|
7867
7948
|
tempo,
|
|
7868
7949
|
size = "md",
|
|
7869
7950
|
colored = true,
|
|
7951
|
+
showLabel = true,
|
|
7870
7952
|
showInfo = true,
|
|
7871
7953
|
live,
|
|
7872
7954
|
onPress,
|
|
@@ -7900,7 +7982,7 @@ function TempoDisplay({
|
|
|
7900
7982
|
},
|
|
7901
7983
|
...props,
|
|
7902
7984
|
children: [
|
|
7903
|
-
/* @__PURE__ */ jsx(
|
|
7985
|
+
showLabel && /* @__PURE__ */ jsx(
|
|
7904
7986
|
Text,
|
|
7905
7987
|
{
|
|
7906
7988
|
style: {
|
|
@@ -8128,12 +8210,12 @@ var ZONE = {
|
|
|
8128
8210
|
// severe over-target
|
|
8129
8211
|
};
|
|
8130
8212
|
var BULGE_SIZE = { 1: 8, 2: 10, 3: 11 };
|
|
8131
|
-
function zoneForPct(
|
|
8132
|
-
if (
|
|
8133
|
-
if (
|
|
8134
|
-
if (
|
|
8135
|
-
if (
|
|
8136
|
-
if (
|
|
8213
|
+
function zoneForPct(pct2) {
|
|
8214
|
+
if (pct2 >= 125) return { color: ZONE.over3, over: 3 };
|
|
8215
|
+
if (pct2 >= 115) return { color: ZONE.over2, over: 2 };
|
|
8216
|
+
if (pct2 > 100) return { color: ZONE.over1, over: 1 };
|
|
8217
|
+
if (pct2 === 100) return { color: ZONE.target, over: 0 };
|
|
8218
|
+
if (pct2 >= 75) return { color: ZONE.approaching, over: 0 };
|
|
8137
8219
|
return { color: ZONE.building, over: 0 };
|
|
8138
8220
|
}
|
|
8139
8221
|
function clampFill(value) {
|
|
@@ -8141,9 +8223,9 @@ function clampFill(value) {
|
|
|
8141
8223
|
if (value > 1) return 1;
|
|
8142
8224
|
return value;
|
|
8143
8225
|
}
|
|
8144
|
-
function isAtTarget(
|
|
8226
|
+
function isAtTarget(pct2, threshold) {
|
|
8145
8227
|
if (threshold == null) return false;
|
|
8146
|
-
return Math.abs(
|
|
8228
|
+
return Math.abs(pct2 - Math.round(threshold * 100)) <= 5;
|
|
8147
8229
|
}
|
|
8148
8230
|
function IntensityBar({
|
|
8149
8231
|
level,
|
|
@@ -8157,9 +8239,9 @@ function IntensityBar({
|
|
|
8157
8239
|
}) {
|
|
8158
8240
|
const isVertical = orientation === "vertical";
|
|
8159
8241
|
const fillLevel = clampFill(level);
|
|
8160
|
-
const
|
|
8161
|
-
const zone = zoneForPct(
|
|
8162
|
-
const atTarget = isAtTarget(
|
|
8242
|
+
const pct2 = Math.round(Math.max(0, level) * 100);
|
|
8243
|
+
const zone = zoneForPct(pct2);
|
|
8244
|
+
const atTarget = isAtTarget(pct2, threshold);
|
|
8163
8245
|
const [fillAnim] = useState(() => new Animated.Value(fillLevel));
|
|
8164
8246
|
useEffect(() => {
|
|
8165
8247
|
const animation = Animated.timing(fillAnim, {
|
|
@@ -8210,8 +8292,8 @@ function IntensityBar({
|
|
|
8210
8292
|
className,
|
|
8211
8293
|
style: { alignItems: "center" },
|
|
8212
8294
|
accessibilityRole: "progressbar",
|
|
8213
|
-
accessibilityValue: { min: 0, max: 100, now:
|
|
8214
|
-
accessibilityLabel: `Intensity level: ${
|
|
8295
|
+
accessibilityValue: { min: 0, max: 100, now: pct2 },
|
|
8296
|
+
accessibilityLabel: `Intensity level: ${pct2}%`,
|
|
8215
8297
|
testID: "intensity-bar",
|
|
8216
8298
|
...props,
|
|
8217
8299
|
children: [
|
|
@@ -8257,7 +8339,7 @@ function IntensityBar({
|
|
|
8257
8339
|
accessibilityElementsHidden: true,
|
|
8258
8340
|
testID: "intensity-label",
|
|
8259
8341
|
children: [
|
|
8260
|
-
|
|
8342
|
+
pct2,
|
|
8261
8343
|
"%"
|
|
8262
8344
|
]
|
|
8263
8345
|
}
|
|
@@ -8442,13 +8524,257 @@ function WorkoutPill({
|
|
|
8442
8524
|
}
|
|
8443
8525
|
return pill;
|
|
8444
8526
|
}
|
|
8527
|
+
var PULSE_HALF_MS = 950;
|
|
8528
|
+
var PULSE_MIN_OPACITY = 0.45;
|
|
8529
|
+
var SEGMENTED_BAR_GAP = 5;
|
|
8530
|
+
function usePulse2(active) {
|
|
8531
|
+
const [value] = useState(() => new Animated.Value(0));
|
|
8532
|
+
useEffect(() => {
|
|
8533
|
+
if (!active) return;
|
|
8534
|
+
const loop = Animated.loop(
|
|
8535
|
+
Animated.sequence([
|
|
8536
|
+
Animated.timing(value, {
|
|
8537
|
+
toValue: 1,
|
|
8538
|
+
duration: PULSE_HALF_MS,
|
|
8539
|
+
easing: Easing.inOut(Easing.ease),
|
|
8540
|
+
useNativeDriver: false
|
|
8541
|
+
}),
|
|
8542
|
+
Animated.timing(value, {
|
|
8543
|
+
toValue: 0,
|
|
8544
|
+
duration: PULSE_HALF_MS,
|
|
8545
|
+
easing: Easing.inOut(Easing.ease),
|
|
8546
|
+
useNativeDriver: false
|
|
8547
|
+
})
|
|
8548
|
+
])
|
|
8549
|
+
);
|
|
8550
|
+
loop.start();
|
|
8551
|
+
return () => loop.stop();
|
|
8552
|
+
}, [active, value]);
|
|
8553
|
+
return value;
|
|
8554
|
+
}
|
|
8555
|
+
function SegmentedBar({
|
|
8556
|
+
segments,
|
|
8557
|
+
height = 8,
|
|
8558
|
+
gap = SEGMENTED_BAR_GAP,
|
|
8559
|
+
radius = 2,
|
|
8560
|
+
marker = null,
|
|
8561
|
+
segmentTestID,
|
|
8562
|
+
style,
|
|
8563
|
+
...props
|
|
8564
|
+
}) {
|
|
8565
|
+
const pulse = usePulse2(segments.some((s) => s.pulse));
|
|
8566
|
+
return /* @__PURE__ */ jsxs(View, { style: [{ flexDirection: "row", height, gap, position: "relative" }, style], ...props, children: [
|
|
8567
|
+
segments.map((seg, i) => {
|
|
8568
|
+
const fillStyle = {
|
|
8569
|
+
width: `${(seg.fill ?? 1) * 100}%`,
|
|
8570
|
+
height: "100%",
|
|
8571
|
+
backgroundColor: seg.color,
|
|
8572
|
+
opacity: seg.opacity
|
|
8573
|
+
};
|
|
8574
|
+
const testID = segmentTestID?.(seg, i) ?? "segmented-bar-segment";
|
|
8575
|
+
return /* @__PURE__ */ jsx(
|
|
8576
|
+
View,
|
|
8577
|
+
{
|
|
8578
|
+
style: {
|
|
8579
|
+
flex: seg.weight ?? 1,
|
|
8580
|
+
minWidth: 0,
|
|
8581
|
+
height: "100%",
|
|
8582
|
+
marginLeft: seg.leadingGap,
|
|
8583
|
+
borderRadius: radius,
|
|
8584
|
+
overflow: "hidden"
|
|
8585
|
+
},
|
|
8586
|
+
children: seg.pulse ? /* @__PURE__ */ jsx(
|
|
8587
|
+
Animated.View,
|
|
8588
|
+
{
|
|
8589
|
+
style: {
|
|
8590
|
+
...fillStyle,
|
|
8591
|
+
...seg.pulseColor ? {
|
|
8592
|
+
backgroundColor: pulse.interpolate({
|
|
8593
|
+
inputRange: [0, 1],
|
|
8594
|
+
outputRange: seg.pulseColor
|
|
8595
|
+
})
|
|
8596
|
+
} : {
|
|
8597
|
+
opacity: pulse.interpolate({
|
|
8598
|
+
inputRange: [0, 1],
|
|
8599
|
+
outputRange: [PULSE_MIN_OPACITY, 1]
|
|
8600
|
+
})
|
|
8601
|
+
}
|
|
8602
|
+
},
|
|
8603
|
+
accessibilityElementsHidden: true,
|
|
8604
|
+
testID
|
|
8605
|
+
}
|
|
8606
|
+
) : /* @__PURE__ */ jsx(View, { style: fillStyle, accessibilityElementsHidden: true, testID })
|
|
8607
|
+
},
|
|
8608
|
+
i
|
|
8609
|
+
);
|
|
8610
|
+
}),
|
|
8611
|
+
marker ? /* @__PURE__ */ jsx(
|
|
8612
|
+
View,
|
|
8613
|
+
{
|
|
8614
|
+
style: {
|
|
8615
|
+
position: "absolute",
|
|
8616
|
+
left: `${marker.position * 100}%`,
|
|
8617
|
+
top: 0,
|
|
8618
|
+
bottom: 0,
|
|
8619
|
+
width: 2,
|
|
8620
|
+
backgroundColor: marker.color
|
|
8621
|
+
},
|
|
8622
|
+
accessibilityElementsHidden: true,
|
|
8623
|
+
testID: "segmented-bar-marker"
|
|
8624
|
+
}
|
|
8625
|
+
) : null
|
|
8626
|
+
] });
|
|
8627
|
+
}
|
|
8628
|
+
|
|
8629
|
+
// src/components/custom/Workout/SetBar.tsx
|
|
8630
|
+
var SET_STRIP_ZONES = {
|
|
8631
|
+
slow: primitiveRamps.red[600],
|
|
8632
|
+
moderate: primitiveRamps.orange[400],
|
|
8633
|
+
fast: primitiveRamps.amber[300],
|
|
8634
|
+
fastest: primitiveRamps.green[300]
|
|
8635
|
+
};
|
|
8636
|
+
var TODO_COLOR = primitiveColors.charcoal[300];
|
|
8637
|
+
var SET_STRIP_VARIABLE_COLOR = primitiveRamps.cyan[900];
|
|
8638
|
+
var NOTCH_GAP = 2;
|
|
8639
|
+
var CLUSTER_GAP = 3;
|
|
8640
|
+
var MYO_UPCOMING_CLUSTERS = 3;
|
|
8641
|
+
var MYO_UPCOMING_CLUSTER_LEN = 5;
|
|
8642
|
+
var MYO_UPCOMING_FADE = 0.6;
|
|
8643
|
+
var PULSE_RANGE = {
|
|
8644
|
+
[SET_STRIP_ZONES.slow]: [primitiveRamps.red[500], primitiveRamps.red[700]],
|
|
8645
|
+
[SET_STRIP_ZONES.moderate]: [primitiveRamps.orange[300], primitiveRamps.orange[500]],
|
|
8646
|
+
[SET_STRIP_ZONES.fast]: [primitiveRamps.amber[200], primitiveRamps.amber[400]],
|
|
8647
|
+
[SET_STRIP_ZONES.fastest]: [primitiveRamps.green[200], primitiveRamps.green[400]]
|
|
8648
|
+
};
|
|
8649
|
+
function velocityZoneColor(v) {
|
|
8650
|
+
if (v < 0.5) return SET_STRIP_ZONES.slow;
|
|
8651
|
+
if (v < 0.75) return SET_STRIP_ZONES.moderate;
|
|
8652
|
+
if (v < 1) return SET_STRIP_ZONES.fast;
|
|
8653
|
+
return SET_STRIP_ZONES.fastest;
|
|
8654
|
+
}
|
|
8655
|
+
function chunkedSegments(chunks, gap) {
|
|
8656
|
+
return chunks.flatMap(
|
|
8657
|
+
(vels, ci) => vels.map((v, ri) => ({
|
|
8658
|
+
color: velocityZoneColor(v),
|
|
8659
|
+
...ci > 0 && ri === 0 ? { leadingGap: gap } : {}
|
|
8660
|
+
}))
|
|
8661
|
+
);
|
|
8662
|
+
}
|
|
8663
|
+
function rangeSegments(floor, max, doneVels) {
|
|
8664
|
+
return Array.from({ length: max }, (_, i) => {
|
|
8665
|
+
if (i < doneVels.length) return { color: velocityZoneColor(doneVels[i]) };
|
|
8666
|
+
return { color: i < floor ? TODO_COLOR : SET_STRIP_VARIABLE_COLOR };
|
|
8667
|
+
});
|
|
8668
|
+
}
|
|
8669
|
+
function myoUpcomingSegments(activationLen, clusterCount) {
|
|
8670
|
+
const activation = Array.from({ length: activationLen }, () => ({ color: TODO_COLOR }));
|
|
8671
|
+
const trail = Array.from(
|
|
8672
|
+
{ length: clusterCount },
|
|
8673
|
+
(_, ci) => Array.from({ length: MYO_UPCOMING_CLUSTER_LEN }, (_2, ri) => ({
|
|
8674
|
+
color: SET_STRIP_VARIABLE_COLOR,
|
|
8675
|
+
opacity: MYO_UPCOMING_FADE ** ci,
|
|
8676
|
+
...ri === 0 ? { leadingGap: CLUSTER_GAP } : {}
|
|
8677
|
+
}))
|
|
8678
|
+
).flat();
|
|
8679
|
+
return [...activation, ...trail];
|
|
8680
|
+
}
|
|
8681
|
+
function setSegments(set) {
|
|
8682
|
+
if (set.status === "todo") {
|
|
8683
|
+
return [{ color: TODO_COLOR }];
|
|
8684
|
+
}
|
|
8685
|
+
if (set.status === "done") {
|
|
8686
|
+
return set.velocities.map((v) => ({ color: velocityZoneColor(v) }));
|
|
8687
|
+
}
|
|
8688
|
+
if (set.status === "range") {
|
|
8689
|
+
return rangeSegments(set.floor, set.max, set.doneVels);
|
|
8690
|
+
}
|
|
8691
|
+
if (set.status === "drop") {
|
|
8692
|
+
return chunkedSegments(set.subloads, NOTCH_GAP);
|
|
8693
|
+
}
|
|
8694
|
+
if (set.status === "myo") {
|
|
8695
|
+
return chunkedSegments([set.activation, ...set.clusters], CLUSTER_GAP);
|
|
8696
|
+
}
|
|
8697
|
+
if (set.status === "myo-upcoming") {
|
|
8698
|
+
return myoUpcomingSegments(set.activationLen, set.clusterCount ?? MYO_UPCOMING_CLUSTERS);
|
|
8699
|
+
}
|
|
8700
|
+
const performed = set.velocities.map((v) => {
|
|
8701
|
+
const color = velocityZoneColor(v);
|
|
8702
|
+
return { color, pulse: true, pulseColor: PULSE_RANGE[color] };
|
|
8703
|
+
});
|
|
8704
|
+
const remaining = Math.max(0, set.planned - set.velocities.length);
|
|
8705
|
+
return [...performed, ...Array.from({ length: remaining }, () => ({ color: TODO_COLOR }))];
|
|
8706
|
+
}
|
|
8707
|
+
function setBarSegmentTestID(seg) {
|
|
8708
|
+
if (seg.pulse) return "set-strip-pulse";
|
|
8709
|
+
if (seg.color === SET_STRIP_VARIABLE_COLOR) return "set-strip-variable";
|
|
8710
|
+
return seg.color === TODO_COLOR ? "set-strip-empty" : "set-strip-fill";
|
|
8711
|
+
}
|
|
8712
|
+
function SetBar({ set, height = 8 }) {
|
|
8713
|
+
return /* @__PURE__ */ jsx(
|
|
8714
|
+
SegmentedBar,
|
|
8715
|
+
{
|
|
8716
|
+
segments: setSegments(set),
|
|
8717
|
+
height,
|
|
8718
|
+
gap: 0,
|
|
8719
|
+
radius: 0,
|
|
8720
|
+
segmentTestID: setBarSegmentTestID,
|
|
8721
|
+
style: { flex: 1, minWidth: 0, borderRadius: 2, overflow: "hidden" },
|
|
8722
|
+
testID: "set-strip-set"
|
|
8723
|
+
}
|
|
8724
|
+
);
|
|
8725
|
+
}
|
|
8726
|
+
|
|
8727
|
+
// src/components/custom/Workout/SetStrip.tsx
|
|
8728
|
+
var SET_STRIP_GAP = 5;
|
|
8729
|
+
function setCategory(set) {
|
|
8730
|
+
switch (set.status) {
|
|
8731
|
+
case "done":
|
|
8732
|
+
case "drop":
|
|
8733
|
+
case "myo":
|
|
8734
|
+
return "done";
|
|
8735
|
+
case "active":
|
|
8736
|
+
return "active";
|
|
8737
|
+
case "range":
|
|
8738
|
+
return set.doneVels.length > 0 ? "active" : "upcoming";
|
|
8739
|
+
case "todo":
|
|
8740
|
+
case "myo-upcoming":
|
|
8741
|
+
return "upcoming";
|
|
8742
|
+
}
|
|
8743
|
+
}
|
|
8744
|
+
function describeSets(sets) {
|
|
8745
|
+
const done = sets.filter((s) => setCategory(s) === "done").length;
|
|
8746
|
+
const active = sets.filter((s) => setCategory(s) === "active").length;
|
|
8747
|
+
const upcoming = sets.filter((s) => setCategory(s) === "upcoming").length;
|
|
8748
|
+
return `Set progress: ${done} done, ${active} in progress, ${upcoming} upcoming`;
|
|
8749
|
+
}
|
|
8750
|
+
function SetStrip({ sets, height = 8, className, ...props }) {
|
|
8751
|
+
return /* @__PURE__ */ jsx(
|
|
8752
|
+
View,
|
|
8753
|
+
{
|
|
8754
|
+
className,
|
|
8755
|
+
style: { flexDirection: "row", width: "100%", height, gap: SET_STRIP_GAP },
|
|
8756
|
+
accessibilityRole: "image",
|
|
8757
|
+
accessibilityLabel: describeSets(sets),
|
|
8758
|
+
testID: "set-strip",
|
|
8759
|
+
...props,
|
|
8760
|
+
children: sets.map((set, i) => /* @__PURE__ */ jsx(SetBar, { set, height }, i))
|
|
8761
|
+
}
|
|
8762
|
+
);
|
|
8763
|
+
}
|
|
8764
|
+
|
|
8765
|
+
// src/components/custom/Workout/VelocityStrip.tsx
|
|
8445
8766
|
var VEL_COLORS = WORKOUT_TOKENS.scale;
|
|
8446
|
-
var
|
|
8447
|
-
speed:
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8767
|
+
var bandIdToEffortColor = {
|
|
8768
|
+
speed: sequentialEffort[0],
|
|
8769
|
+
// green-300
|
|
8770
|
+
power: sequentialEffort[2],
|
|
8771
|
+
// amber-300 (gold)
|
|
8772
|
+
strengthSpeed: sequentialEffort[3],
|
|
8773
|
+
// orange-400
|
|
8774
|
+
maximalStrength: sequentialEffort[4],
|
|
8775
|
+
// red-600
|
|
8776
|
+
grinding: sequentialEffort[5]
|
|
8777
|
+
// red-700 — the distinct 5th band
|
|
8452
8778
|
};
|
|
8453
8779
|
function getVelocityZoneColor(velocity) {
|
|
8454
8780
|
if (velocity >= 1) return "vel-green";
|
|
@@ -8487,14 +8813,132 @@ function classifyBand(velocity, bands) {
|
|
|
8487
8813
|
return bands[bands.length - 1];
|
|
8488
8814
|
}
|
|
8489
8815
|
function bandColor(band) {
|
|
8490
|
-
|
|
8491
|
-
return token ? VEL_COLORS[token] : VEL_COLORS.green;
|
|
8816
|
+
return bandIdToEffortColor[band.id] ?? VEL_COLORS.green;
|
|
8492
8817
|
}
|
|
8493
8818
|
function getLossStyle(loss) {
|
|
8494
8819
|
if (loss > 25) return { color: VEL_COLORS.red };
|
|
8495
8820
|
if (loss > 20) return { color: VEL_COLORS.orange };
|
|
8496
8821
|
return null;
|
|
8497
8822
|
}
|
|
8823
|
+
var REP_GAP = 2;
|
|
8824
|
+
var WIDE_GAP = 8;
|
|
8825
|
+
var TODO_COLOR2 = primitiveColors.charcoal[300];
|
|
8826
|
+
var CONTINUE_OUTLINE = primitiveRamps.cyan[800];
|
|
8827
|
+
function deriveDoneVelocities(set) {
|
|
8828
|
+
switch (set.type) {
|
|
8829
|
+
case "drop":
|
|
8830
|
+
return set.subloads.flat();
|
|
8831
|
+
case "myo":
|
|
8832
|
+
return [...set.activation, ...set.clusters.flat()];
|
|
8833
|
+
default:
|
|
8834
|
+
return set.velocities;
|
|
8835
|
+
}
|
|
8836
|
+
}
|
|
8837
|
+
function chunkedRepSlots(chunks) {
|
|
8838
|
+
const slots = [];
|
|
8839
|
+
chunks.forEach((chunk) => {
|
|
8840
|
+
chunk.forEach((velocity, ri) => {
|
|
8841
|
+
const first = slots.length === 0;
|
|
8842
|
+
slots.push({ kind: "rep", velocity, leadingGap: first ? 0 : ri === 0 ? WIDE_GAP : REP_GAP });
|
|
8843
|
+
});
|
|
8844
|
+
});
|
|
8845
|
+
return slots;
|
|
8846
|
+
}
|
|
8847
|
+
function buildSlots(set) {
|
|
8848
|
+
switch (set.type) {
|
|
8849
|
+
case "straight": {
|
|
8850
|
+
const total = Math.max(set.velocities.length, set.planned ?? set.velocities.length);
|
|
8851
|
+
return Array.from({ length: total }, (_, i) => {
|
|
8852
|
+
const done = i < set.velocities.length;
|
|
8853
|
+
return {
|
|
8854
|
+
kind: done ? "rep" : "todo",
|
|
8855
|
+
velocity: done ? set.velocities[i] : void 0,
|
|
8856
|
+
leadingGap: i === 0 ? 0 : REP_GAP
|
|
8857
|
+
};
|
|
8858
|
+
});
|
|
8859
|
+
}
|
|
8860
|
+
case "range": {
|
|
8861
|
+
const total = Math.max(set.max, set.velocities.length);
|
|
8862
|
+
return Array.from({ length: total }, (_, i) => {
|
|
8863
|
+
const kind = i < set.velocities.length ? "rep" : i < set.floor ? "todo" : "variable";
|
|
8864
|
+
return {
|
|
8865
|
+
kind,
|
|
8866
|
+
velocity: kind === "rep" ? set.velocities[i] : void 0,
|
|
8867
|
+
leadingGap: i === 0 ? 0 : REP_GAP
|
|
8868
|
+
};
|
|
8869
|
+
});
|
|
8870
|
+
}
|
|
8871
|
+
case "amrap": {
|
|
8872
|
+
const reps = set.velocities.map((velocity, i) => ({
|
|
8873
|
+
kind: "rep",
|
|
8874
|
+
velocity,
|
|
8875
|
+
leadingGap: i === 0 ? 0 : REP_GAP
|
|
8876
|
+
}));
|
|
8877
|
+
reps.push({ kind: "continue", leadingGap: reps.length === 0 ? 0 : REP_GAP });
|
|
8878
|
+
return reps;
|
|
8879
|
+
}
|
|
8880
|
+
case "drop":
|
|
8881
|
+
return chunkedRepSlots(set.subloads);
|
|
8882
|
+
case "myo": {
|
|
8883
|
+
const slots = chunkedRepSlots([set.activation, ...set.clusters]);
|
|
8884
|
+
if (set.open) slots.push({ kind: "continue", leadingGap: slots.length === 0 ? 0 : REP_GAP });
|
|
8885
|
+
return slots;
|
|
8886
|
+
}
|
|
8887
|
+
case "cluster": {
|
|
8888
|
+
const total = Math.max(set.velocities.length, set.planned ?? set.velocities.length);
|
|
8889
|
+
return Array.from({ length: total }, (_, i) => {
|
|
8890
|
+
const done = i < set.velocities.length;
|
|
8891
|
+
const boundary = i > 0 && i % set.groupSize === 0;
|
|
8892
|
+
return {
|
|
8893
|
+
kind: done ? "rep" : "todo",
|
|
8894
|
+
velocity: done ? set.velocities[i] : void 0,
|
|
8895
|
+
leadingGap: i === 0 ? 0 : boundary ? WIDE_GAP : REP_GAP
|
|
8896
|
+
};
|
|
8897
|
+
});
|
|
8898
|
+
}
|
|
8899
|
+
}
|
|
8900
|
+
}
|
|
8901
|
+
function setAccessibilityLabel(set, repCount) {
|
|
8902
|
+
switch (set.type) {
|
|
8903
|
+
case "straight":
|
|
8904
|
+
return `Velocity strip, straight set, ${repCount} reps`;
|
|
8905
|
+
case "range":
|
|
8906
|
+
return `Velocity strip, rep-range set, floor ${set.floor} to ${set.max}, ${repCount} reps done`;
|
|
8907
|
+
case "amrap":
|
|
8908
|
+
return `Velocity strip, AMRAP set, ${repCount} reps and counting`;
|
|
8909
|
+
case "drop":
|
|
8910
|
+
return `Velocity strip, drop set, ${set.subloads.length} loads, ${repCount} reps`;
|
|
8911
|
+
case "myo":
|
|
8912
|
+
return `Velocity strip, myo-reps set, ${set.clusters.length} clusters${set.open ? ", open" : ""}, ${repCount} reps`;
|
|
8913
|
+
case "cluster":
|
|
8914
|
+
return `Velocity strip, cluster set, groups of ${set.groupSize}, ${repCount} reps`;
|
|
8915
|
+
}
|
|
8916
|
+
}
|
|
8917
|
+
function slotAccessibilityLabel(slot, index) {
|
|
8918
|
+
switch (slot.kind) {
|
|
8919
|
+
case "rep":
|
|
8920
|
+
return `Rep ${index + 1}: ${formatVelocity(slot.velocity ?? 0)} meters per second`;
|
|
8921
|
+
case "todo":
|
|
8922
|
+
return `Rep ${index + 1}: planned`;
|
|
8923
|
+
case "variable":
|
|
8924
|
+
return `Rep ${index + 1}: variable`;
|
|
8925
|
+
case "continue":
|
|
8926
|
+
return "Keep going";
|
|
8927
|
+
}
|
|
8928
|
+
}
|
|
8929
|
+
var EXPANDED_TODO_STUB_PCT = 16;
|
|
8930
|
+
var EXPANDED_ENCODED_PCT = 45;
|
|
8931
|
+
var EXPANDED_HEIGHT = 60;
|
|
8932
|
+
var FIXED_MAX_VELOCITY = 1.15;
|
|
8933
|
+
var BARE_STUB_HEIGHT = 3;
|
|
8934
|
+
function scaleDenominator(scale, maxVelocity) {
|
|
8935
|
+
return scale === "fixed" ? FIXED_MAX_VELOCITY : maxVelocity * 1.15;
|
|
8936
|
+
}
|
|
8937
|
+
function bareSlotHeight(slot, height, denom) {
|
|
8938
|
+
if (slot.kind !== "rep" || denom <= 0) return BARE_STUB_HEIGHT;
|
|
8939
|
+
const ratio = Math.min(1, (slot.velocity ?? 0) / denom);
|
|
8940
|
+
return Math.max(BARE_STUB_HEIGHT, ratio * height);
|
|
8941
|
+
}
|
|
8498
8942
|
function getReducedMotionPreference() {
|
|
8499
8943
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
8500
8944
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
@@ -8516,31 +8960,48 @@ var ANIMATION_EASING = Easing.bezier(0.22, 1, 0.36, 1);
|
|
|
8516
8960
|
var POP_EASING = Easing.bezier(0.34, 1.56, 0.64, 1);
|
|
8517
8961
|
function VelocityStrip({
|
|
8518
8962
|
velocities,
|
|
8963
|
+
set,
|
|
8519
8964
|
zones,
|
|
8520
8965
|
liveRepIndex,
|
|
8521
|
-
expanded =
|
|
8966
|
+
expanded = true,
|
|
8522
8967
|
onToggle,
|
|
8523
8968
|
onRepPress,
|
|
8524
|
-
variant = "
|
|
8969
|
+
variant = "expanded",
|
|
8970
|
+
height = EXPANDED_HEIGHT,
|
|
8971
|
+
scale = "peak",
|
|
8972
|
+
showNumbers = true,
|
|
8525
8973
|
showInfo = true,
|
|
8526
8974
|
className,
|
|
8527
8975
|
...props
|
|
8528
8976
|
}) {
|
|
8529
|
-
const
|
|
8530
|
-
const
|
|
8531
|
-
|
|
8977
|
+
const doneVelocities = set ? deriveDoneVelocities(set) : velocities ?? [];
|
|
8978
|
+
const slots = set ? buildSlots(set) : doneVelocities.map((v, i) => ({
|
|
8979
|
+
kind: "rep",
|
|
8980
|
+
velocity: v,
|
|
8981
|
+
leadingGap: i === 0 ? 0 : REP_GAP
|
|
8982
|
+
}));
|
|
8983
|
+
const maxVelocity = Math.max(...doneVelocities, 0);
|
|
8984
|
+
const meanVelocity = calculateMeanVelocity(doneVelocities);
|
|
8985
|
+
const loss = calculateVelocityLoss(doneVelocities);
|
|
8986
|
+
const framed = showNumbers || showInfo;
|
|
8987
|
+
const scaleDenom = scaleDenominator(scale, maxVelocity);
|
|
8532
8988
|
const hasZones = zones != null && zones.length > 0;
|
|
8533
8989
|
const barColorFor = (v) => hasZones ? bandColor(classifyBand(v, zones)) : zoneHexMap[getVelocityZoneColor(v)];
|
|
8990
|
+
const slotColor = (slot) => {
|
|
8991
|
+
if (slot.kind === "rep") return barColorFor(slot.velocity ?? 0);
|
|
8992
|
+
if (slot.kind === "todo") return TODO_COLOR2;
|
|
8993
|
+
return SET_STRIP_VARIABLE_COLOR;
|
|
8994
|
+
};
|
|
8534
8995
|
const meanZone = hasZones ? classifyBand(meanVelocity, zones)?.label ?? "" : getVelocityZoneName(meanVelocity);
|
|
8535
8996
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
8536
|
-
const [heightAnim] = useState(() => new Animated.Value(expanded ?
|
|
8997
|
+
const [heightAnim] = useState(() => new Animated.Value(expanded ? height : 3));
|
|
8537
8998
|
const [labelOpacity] = useState(() => new Animated.Value(expanded ? 1 : 0));
|
|
8538
8999
|
const [infoOpacity] = useState(() => new Animated.Value(expanded ? 1 : 0));
|
|
8539
9000
|
const [liveScale] = useState(() => new Animated.Value(1));
|
|
8540
|
-
const liveVelocity = liveRepIndex != null ?
|
|
9001
|
+
const liveVelocity = liveRepIndex != null ? doneVelocities[liveRepIndex] : void 0;
|
|
8541
9002
|
const isNewPeak = liveVelocity != null && maxVelocity > 0 && liveVelocity === maxVelocity;
|
|
8542
9003
|
useEffect(() => {
|
|
8543
|
-
if (variant
|
|
9004
|
+
if (variant !== "expanded" || !framed || liveRepIndex == null || liveVelocity == null) return;
|
|
8544
9005
|
if (prefersReducedMotion) {
|
|
8545
9006
|
liveScale.setValue(1);
|
|
8546
9007
|
return;
|
|
@@ -8570,12 +9031,12 @@ function VelocityStrip({
|
|
|
8570
9031
|
useNativeDriver: true
|
|
8571
9032
|
}).start();
|
|
8572
9033
|
}
|
|
8573
|
-
}, [variant, liveRepIndex, liveVelocity, isNewPeak, prefersReducedMotion, liveScale]);
|
|
9034
|
+
}, [variant, framed, liveRepIndex, liveVelocity, isNewPeak, prefersReducedMotion, liveScale]);
|
|
8574
9035
|
useEffect(() => {
|
|
8575
|
-
if (variant
|
|
9036
|
+
if (variant !== "expanded" || !framed) return;
|
|
8576
9037
|
Animated.parallel([
|
|
8577
9038
|
Animated.timing(heightAnim, {
|
|
8578
|
-
toValue: expanded ?
|
|
9039
|
+
toValue: expanded ? height : 3,
|
|
8579
9040
|
duration: ANIMATION_DURATION,
|
|
8580
9041
|
easing: ANIMATION_EASING,
|
|
8581
9042
|
useNativeDriver: false
|
|
@@ -8593,52 +9054,133 @@ function VelocityStrip({
|
|
|
8593
9054
|
useNativeDriver: false
|
|
8594
9055
|
})
|
|
8595
9056
|
]).start();
|
|
8596
|
-
}, [expanded, variant, heightAnim, labelOpacity, infoOpacity]);
|
|
9057
|
+
}, [expanded, variant, framed, height, heightAnim, labelOpacity, infoOpacity]);
|
|
9058
|
+
if (set == null && velocities == null) return null;
|
|
9059
|
+
const repCount = doneVelocities.length;
|
|
9060
|
+
const miniLabel = set ? setAccessibilityLabel(set, repCount) : `Velocity strip, ${repCount} reps`;
|
|
8597
9061
|
if (variant === "mini") {
|
|
8598
9062
|
const { style: externalStyle, ...restProps } = props;
|
|
8599
9063
|
return /* @__PURE__ */ jsx(
|
|
8600
9064
|
View,
|
|
8601
9065
|
{
|
|
8602
9066
|
className,
|
|
8603
|
-
style: [
|
|
9067
|
+
style: [
|
|
9068
|
+
{ flexDirection: "row", height: 3, gap: REP_GAP, borderRadius: 2, overflow: "hidden" },
|
|
9069
|
+
externalStyle
|
|
9070
|
+
],
|
|
8604
9071
|
accessibilityRole: "image",
|
|
8605
|
-
accessibilityLabel:
|
|
9072
|
+
accessibilityLabel: miniLabel,
|
|
8606
9073
|
testID: "velocity-strip-mini",
|
|
8607
9074
|
...restProps,
|
|
8608
|
-
children:
|
|
9075
|
+
children: slots.map((slot, i) => /* @__PURE__ */ jsx(
|
|
8609
9076
|
View,
|
|
8610
9077
|
{
|
|
8611
9078
|
style: {
|
|
8612
9079
|
flex: 1,
|
|
8613
|
-
backgroundColor:
|
|
9080
|
+
backgroundColor: slotColor(slot),
|
|
8614
9081
|
borderRadius: 1,
|
|
8615
9082
|
minWidth: 4,
|
|
8616
|
-
height: "100%"
|
|
9083
|
+
height: "100%",
|
|
9084
|
+
// The container's uniform 2px gap covers rep spacing; a wide slot adds
|
|
9085
|
+
// only the EXTRA (WIDE_GAP − REP_GAP) so the notch totals WIDE_GAP.
|
|
9086
|
+
marginLeft: Math.max(0, slot.leadingGap - REP_GAP),
|
|
9087
|
+
...slot.kind === "continue" ? { borderWidth: 1, borderColor: CONTINUE_OUTLINE } : {}
|
|
9088
|
+
},
|
|
9089
|
+
accessibilityElementsHidden: true,
|
|
9090
|
+
testID: slot.kind === "rep" ? `velocity-bar-${i}` : `velocity-slot-${slot.kind}`
|
|
9091
|
+
},
|
|
9092
|
+
i
|
|
9093
|
+
))
|
|
9094
|
+
}
|
|
9095
|
+
);
|
|
9096
|
+
}
|
|
9097
|
+
if (!framed) {
|
|
9098
|
+
const { style: externalStyle, ...restProps } = props;
|
|
9099
|
+
return /* @__PURE__ */ jsx(
|
|
9100
|
+
View,
|
|
9101
|
+
{
|
|
9102
|
+
className,
|
|
9103
|
+
style: [
|
|
9104
|
+
{ flexDirection: "row", height, gap: REP_GAP, alignItems: "flex-end" },
|
|
9105
|
+
externalStyle
|
|
9106
|
+
],
|
|
9107
|
+
accessibilityRole: "image",
|
|
9108
|
+
accessibilityLabel: miniLabel,
|
|
9109
|
+
testID: "velocity-strip-compact",
|
|
9110
|
+
...restProps,
|
|
9111
|
+
children: slots.map((slot, i) => /* @__PURE__ */ jsx(
|
|
9112
|
+
View,
|
|
9113
|
+
{
|
|
9114
|
+
style: {
|
|
9115
|
+
flex: 1,
|
|
9116
|
+
minWidth: 4,
|
|
9117
|
+
height: bareSlotHeight(slot, height, scaleDenom),
|
|
9118
|
+
// Top-rounded to match the framed chart's bars (the "rounded tops from
|
|
9119
|
+
// the numbers one"); square bottoms since bars sit on the baseline.
|
|
9120
|
+
borderTopLeftRadius: 2,
|
|
9121
|
+
borderTopRightRadius: 2,
|
|
9122
|
+
backgroundColor: slotColor(slot),
|
|
9123
|
+
marginLeft: Math.max(0, slot.leadingGap - REP_GAP),
|
|
9124
|
+
...slot.kind === "continue" ? { borderWidth: 1, borderColor: CONTINUE_OUTLINE } : {}
|
|
8617
9125
|
},
|
|
8618
9126
|
accessibilityElementsHidden: true,
|
|
8619
|
-
testID: `velocity-bar-${i}`
|
|
9127
|
+
testID: slot.kind === "rep" ? `velocity-bar-${i}` : `velocity-slot-${slot.kind}`
|
|
8620
9128
|
},
|
|
8621
9129
|
i
|
|
8622
9130
|
))
|
|
8623
9131
|
}
|
|
8624
9132
|
);
|
|
8625
9133
|
}
|
|
8626
|
-
const stripLabel = `Velocity chart for set, ${
|
|
9134
|
+
const stripLabel = set ? `${setAccessibilityLabel(set, repCount)}, tap to ${expanded ? "collapse" : "expand"}` : `Velocity chart for set, ${repCount} reps, tap to ${expanded ? "collapse" : "expand"}`;
|
|
8627
9135
|
const hasInteractiveContainer = onToggle != null;
|
|
8628
9136
|
const hasInteractiveReps = onRepPress != null && expanded;
|
|
8629
|
-
const
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
9137
|
+
const setBars = set != null && slots.map((slot, i) => {
|
|
9138
|
+
const isStraightRep = set.type === "straight" && slot.kind === "rep";
|
|
9139
|
+
const heightPct = isStraightRep ? scaleDenom > 0 ? Math.round((slot.velocity ?? 0) / scaleDenom * 100) : 0 : set.type === "straight" ? EXPANDED_TODO_STUB_PCT : EXPANDED_ENCODED_PCT;
|
|
9140
|
+
return /* @__PURE__ */ jsx(
|
|
9141
|
+
View,
|
|
9142
|
+
{
|
|
9143
|
+
style: {
|
|
9144
|
+
flex: 1,
|
|
9145
|
+
height: "100%",
|
|
9146
|
+
justifyContent: "flex-end",
|
|
9147
|
+
marginLeft: slot.leadingGap
|
|
9148
|
+
},
|
|
9149
|
+
children: /* @__PURE__ */ jsx(
|
|
9150
|
+
View,
|
|
9151
|
+
{
|
|
9152
|
+
style: {
|
|
9153
|
+
height: `${heightPct}%`,
|
|
9154
|
+
minHeight: 2,
|
|
9155
|
+
borderTopLeftRadius: 2,
|
|
9156
|
+
borderTopRightRadius: 2,
|
|
9157
|
+
backgroundColor: slotColor(slot),
|
|
9158
|
+
...slot.kind === "continue" ? { borderWidth: 1, borderColor: CONTINUE_OUTLINE } : {}
|
|
9159
|
+
},
|
|
9160
|
+
testID: slot.kind === "rep" ? `velocity-bar-${i}` : `velocity-slot-${slot.kind}`,
|
|
9161
|
+
accessibilityRole: "image",
|
|
9162
|
+
accessibilityLabel: slotAccessibilityLabel(slot, i)
|
|
9163
|
+
}
|
|
9164
|
+
)
|
|
9165
|
+
},
|
|
9166
|
+
i
|
|
9167
|
+
);
|
|
9168
|
+
});
|
|
9169
|
+
const stripContent = /* @__PURE__ */ jsxs(
|
|
9170
|
+
Animated.View,
|
|
9171
|
+
{
|
|
9172
|
+
className: [className, expanded ? "bg-surface-raised" : "bg-transparent"].filter(Boolean).join(" "),
|
|
9173
|
+
style: [
|
|
9174
|
+
{
|
|
9175
|
+
height: heightAnim,
|
|
9176
|
+
width: "100%",
|
|
9177
|
+
gap: 2,
|
|
8638
9178
|
borderRadius: expanded ? 6 : 2,
|
|
8639
9179
|
paddingTop: expanded ? 16 : 0,
|
|
8640
9180
|
paddingBottom: expanded ? 24 : 0,
|
|
8641
|
-
|
|
9181
|
+
// No horizontal inset — the framed chart's bars span full width, matching
|
|
9182
|
+
// the bare spotlight and mini. Numbers/info sit in the vertical padding.
|
|
9183
|
+
paddingHorizontal: 0,
|
|
8642
9184
|
paddingVertical: expanded ? void 0 : 8,
|
|
8643
9185
|
overflow: expanded ? "visible" : "hidden"
|
|
8644
9186
|
}
|
|
@@ -8648,46 +9190,65 @@ function VelocityStrip({
|
|
|
8648
9190
|
testID: "velocity-strip",
|
|
8649
9191
|
...props,
|
|
8650
9192
|
children: [
|
|
8651
|
-
/* @__PURE__ */ jsx(
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
|
|
8662
|
-
|
|
8663
|
-
|
|
8664
|
-
|
|
8665
|
-
|
|
8666
|
-
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
|
|
8676
|
-
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
)
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
9193
|
+
/* @__PURE__ */ jsx(View, { style: { flexDirection: "row", flex: 1, gap: set ? 0 : 2, alignItems: "flex-end" }, children: set ? setBars : doneVelocities.map((v, i) => {
|
|
9194
|
+
const barBackground = barColorFor(v);
|
|
9195
|
+
const barHeightPct = scaleDenom > 0 ? Math.round(v / scaleDenom * 100) : 0;
|
|
9196
|
+
const isLive = liveRepIndex === i;
|
|
9197
|
+
const liveLabelSuffix = isLive ? isNewPeak ? ", latest rep, new set peak" : ", latest rep" : "";
|
|
9198
|
+
const barStyle = expanded ? {
|
|
9199
|
+
height: `${barHeightPct}%`,
|
|
9200
|
+
minHeight: 2,
|
|
9201
|
+
borderTopLeftRadius: 2,
|
|
9202
|
+
borderTopRightRadius: 2,
|
|
9203
|
+
backgroundColor: barBackground
|
|
9204
|
+
} : {
|
|
9205
|
+
minHeight: "100%",
|
|
9206
|
+
borderTopLeftRadius: 2,
|
|
9207
|
+
borderTopRightRadius: 2,
|
|
9208
|
+
borderBottomLeftRadius: 0,
|
|
9209
|
+
borderBottomRightRadius: 0,
|
|
9210
|
+
backgroundColor: barBackground
|
|
9211
|
+
};
|
|
9212
|
+
const barInner = isLive ? /* @__PURE__ */ jsx(
|
|
9213
|
+
Animated.View,
|
|
9214
|
+
{
|
|
9215
|
+
style: [barStyle, { transform: [{ scale: liveScale }] }],
|
|
9216
|
+
testID: `velocity-bar-${i}`,
|
|
9217
|
+
accessibilityRole: "image",
|
|
9218
|
+
accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second${liveLabelSuffix}`
|
|
9219
|
+
}
|
|
9220
|
+
) : /* @__PURE__ */ jsx(
|
|
9221
|
+
View,
|
|
9222
|
+
{
|
|
9223
|
+
style: barStyle,
|
|
9224
|
+
testID: `velocity-bar-${i}`,
|
|
9225
|
+
accessibilityRole: "image",
|
|
9226
|
+
accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second`
|
|
9227
|
+
}
|
|
9228
|
+
);
|
|
9229
|
+
const bar = /* @__PURE__ */ jsxs(
|
|
9230
|
+
View,
|
|
9231
|
+
{
|
|
9232
|
+
style: {
|
|
9233
|
+
flex: 1,
|
|
9234
|
+
height: "100%",
|
|
9235
|
+
justifyContent: "flex-end",
|
|
9236
|
+
position: "relative"
|
|
9237
|
+
},
|
|
9238
|
+
children: [
|
|
9239
|
+
expanded && showNumbers && /* @__PURE__ */ jsx(
|
|
9240
|
+
Animated.View,
|
|
9241
|
+
{
|
|
9242
|
+
style: {
|
|
9243
|
+
opacity: labelOpacity,
|
|
9244
|
+
alignItems: "center",
|
|
9245
|
+
position: "absolute",
|
|
9246
|
+
top: -13,
|
|
9247
|
+
left: 0,
|
|
9248
|
+
right: 0
|
|
9249
|
+
},
|
|
9250
|
+
accessibilityElementsHidden: true,
|
|
9251
|
+
children: /* @__PURE__ */ jsx(
|
|
8691
9252
|
Text,
|
|
8692
9253
|
{
|
|
8693
9254
|
className: "text-text-secondary",
|
|
@@ -8695,30 +9256,30 @@ function VelocityStrip({
|
|
|
8695
9256
|
testID: `velocity-label-${i}`,
|
|
8696
9257
|
children: formatVelocity(v)
|
|
8697
9258
|
}
|
|
8698
|
-
)
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
})
|
|
9259
|
+
)
|
|
9260
|
+
}
|
|
9261
|
+
),
|
|
9262
|
+
barInner
|
|
9263
|
+
]
|
|
9264
|
+
},
|
|
9265
|
+
i
|
|
9266
|
+
);
|
|
9267
|
+
if (onRepPress && expanded) {
|
|
9268
|
+
return /* @__PURE__ */ jsx(
|
|
9269
|
+
Pressable,
|
|
9270
|
+
{
|
|
9271
|
+
style: { flex: 1, height: "100%" },
|
|
9272
|
+
onPress: () => onRepPress(i, v),
|
|
9273
|
+
accessibilityRole: "button",
|
|
9274
|
+
accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second, tap for details`,
|
|
9275
|
+
testID: `velocity-bar-pressable-${i}`,
|
|
9276
|
+
children: bar
|
|
9277
|
+
},
|
|
9278
|
+
i
|
|
9279
|
+
);
|
|
8720
9280
|
}
|
|
8721
|
-
|
|
9281
|
+
return bar;
|
|
9282
|
+
}) }),
|
|
8722
9283
|
expanded && showInfo && /* @__PURE__ */ jsxs(
|
|
8723
9284
|
Animated.View,
|
|
8724
9285
|
{
|
|
@@ -9016,233 +9577,90 @@ function Sparkline({
|
|
|
9016
9577
|
}
|
|
9017
9578
|
);
|
|
9018
9579
|
}
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9580
|
+
var DARK = getSemanticColors("dark");
|
|
9581
|
+
var TEXT_ACTIVE = DARK["text-primary"];
|
|
9582
|
+
var TEXT_MUTED = DARK["text-secondary"];
|
|
9583
|
+
var COL = { set: 36, reps: 44, load: 56, rpe: 36 };
|
|
9584
|
+
var cellText = { fontFamily: "Inter, sans-serif", fontSize: 13, fontWeight: "600" };
|
|
9585
|
+
var typeBadge = {
|
|
9586
|
+
fontSize: 10,
|
|
9587
|
+
fontWeight: "700",
|
|
9588
|
+
fontFamily: "Inter, sans-serif",
|
|
9589
|
+
color: WORKOUT_TOKENS.scale.orange,
|
|
9590
|
+
backgroundColor: "rgba(255,165,2,0.12)",
|
|
9591
|
+
paddingVertical: 1,
|
|
9592
|
+
paddingHorizontal: 5,
|
|
9593
|
+
borderRadius: 3,
|
|
9594
|
+
overflow: "hidden"
|
|
9595
|
+
};
|
|
9596
|
+
function displayReps(set) {
|
|
9597
|
+
return set.state === "done" ? set.reps : set.target.reps;
|
|
9598
|
+
}
|
|
9599
|
+
function displayWeight(set) {
|
|
9600
|
+
return set.state === "done" ? set.weight : set.target.weight;
|
|
9601
|
+
}
|
|
9602
|
+
function plannedReps(set) {
|
|
9603
|
+
if (set.state === "done") return set.velocities.length;
|
|
9604
|
+
if (set.state === "live") return set.target.reps;
|
|
9605
|
+
return set.planned ?? set.target.reps;
|
|
9606
|
+
}
|
|
9607
|
+
function accessibilityLabel(set) {
|
|
9608
|
+
const base = `Set ${set.setNumber}: ${displayReps(set)} reps at ${roundWeight(displayWeight(set))} ${set.unit}`;
|
|
9609
|
+
if (set.state === "live") return `${base}, in progress`;
|
|
9610
|
+
if (set.state === "todo") return `${base}, upcoming`;
|
|
9611
|
+
return base;
|
|
9612
|
+
}
|
|
9613
|
+
function Cell({
|
|
9614
|
+
width,
|
|
9615
|
+
children,
|
|
9616
|
+
testID
|
|
9617
|
+
}) {
|
|
9618
|
+
return /* @__PURE__ */ jsx(View, { style: { width, alignItems: "center", justifyContent: "center" }, testID, children });
|
|
9023
9619
|
}
|
|
9024
|
-
function
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
isNextSet,
|
|
9040
|
-
targets
|
|
9041
|
-
}) {
|
|
9042
|
-
const isActive = mode === "active";
|
|
9043
|
-
const isCompleted = mode === "completed";
|
|
9044
|
-
const rowStyle = {
|
|
9045
|
-
flexDirection: "row",
|
|
9046
|
-
alignItems: "center",
|
|
9047
|
-
padding: 7,
|
|
9048
|
-
paddingHorizontal: 8,
|
|
9049
|
-
gap: 8,
|
|
9050
|
-
borderRadius: 8
|
|
9051
|
-
};
|
|
9052
|
-
if (isActive && isNextSet) {
|
|
9053
|
-
rowStyle.backgroundColor = "rgba(255,121,0,0.06)";
|
|
9054
|
-
rowStyle.borderWidth = 1;
|
|
9055
|
-
rowStyle.borderColor = "rgba(255,121,0,0.15)";
|
|
9056
|
-
}
|
|
9057
|
-
if (isCompleted && !isNextSet) {
|
|
9058
|
-
rowStyle.opacity = 0.55;
|
|
9620
|
+
function RowStrip({ set }) {
|
|
9621
|
+
const zones = set.velocityZones;
|
|
9622
|
+
if (set.state === "live") {
|
|
9623
|
+
return /* @__PURE__ */ jsx(
|
|
9624
|
+
VelocityStrip,
|
|
9625
|
+
{
|
|
9626
|
+
variant: "expanded",
|
|
9627
|
+
showNumbers: false,
|
|
9628
|
+
showInfo: false,
|
|
9629
|
+
height: 24,
|
|
9630
|
+
scale: "fixed",
|
|
9631
|
+
set: { type: "straight", velocities: set.velocities, planned: set.target.reps },
|
|
9632
|
+
zones
|
|
9633
|
+
}
|
|
9634
|
+
);
|
|
9059
9635
|
}
|
|
9636
|
+
const velocities = set.state === "done" ? set.velocities : [];
|
|
9637
|
+
return /* @__PURE__ */ jsx(
|
|
9638
|
+
VelocityStrip,
|
|
9639
|
+
{
|
|
9640
|
+
variant: "mini",
|
|
9641
|
+
set: { type: "straight", velocities, planned: plannedReps(set) },
|
|
9642
|
+
zones
|
|
9643
|
+
}
|
|
9644
|
+
);
|
|
9645
|
+
}
|
|
9646
|
+
function SetRow(set) {
|
|
9647
|
+
const live = set.state === "live";
|
|
9648
|
+
const valueColor = live ? TEXT_ACTIVE : TEXT_MUTED;
|
|
9649
|
+
const rpe = set.state === "todo" ? null : set.rpe;
|
|
9060
9650
|
return /* @__PURE__ */ jsxs(
|
|
9061
9651
|
View,
|
|
9062
9652
|
{
|
|
9063
|
-
style:
|
|
9064
|
-
accessibilityLabel:
|
|
9065
|
-
setNumber,
|
|
9066
|
-
reps,
|
|
9067
|
-
weight,
|
|
9068
|
-
unit
|
|
9069
|
-
),
|
|
9653
|
+
style: { paddingVertical: 6, paddingHorizontal: 8 },
|
|
9654
|
+
accessibilityLabel: accessibilityLabel(set),
|
|
9070
9655
|
testID: "set-row",
|
|
9071
9656
|
children: [
|
|
9072
|
-
/* @__PURE__ */
|
|
9073
|
-
|
|
9074
|
-
{
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
{
|
|
9080
|
-
style: {
|
|
9081
|
-
fontSize: 10,
|
|
9082
|
-
fontWeight: "700",
|
|
9083
|
-
fontFamily: "Inter, sans-serif",
|
|
9084
|
-
color: WORKOUT_TOKENS.scale.orange,
|
|
9085
|
-
backgroundColor: "rgba(255,165,2,0.12)",
|
|
9086
|
-
paddingVertical: 1,
|
|
9087
|
-
paddingHorizontal: 5,
|
|
9088
|
-
borderRadius: 3,
|
|
9089
|
-
overflow: "hidden"
|
|
9090
|
-
},
|
|
9091
|
-
testID: "set-row-type-badge",
|
|
9092
|
-
children: setType
|
|
9093
|
-
}
|
|
9094
|
-
) : /* @__PURE__ */ jsx(
|
|
9095
|
-
Text,
|
|
9096
|
-
{
|
|
9097
|
-
className: "text-text-secondary",
|
|
9098
|
-
style: {
|
|
9099
|
-
fontSize: 13,
|
|
9100
|
-
fontWeight: "600",
|
|
9101
|
-
fontFamily: "Inter, sans-serif"
|
|
9102
|
-
},
|
|
9103
|
-
children: setNumber
|
|
9104
|
-
}
|
|
9105
|
-
)
|
|
9106
|
-
}
|
|
9107
|
-
),
|
|
9108
|
-
/* @__PURE__ */ jsx(
|
|
9109
|
-
View,
|
|
9110
|
-
{
|
|
9111
|
-
className: "flex-1",
|
|
9112
|
-
testID: "set-row-previous",
|
|
9113
|
-
children: /* @__PURE__ */ jsx(
|
|
9114
|
-
Text,
|
|
9115
|
-
{
|
|
9116
|
-
className: "text-text-secondary",
|
|
9117
|
-
style: {
|
|
9118
|
-
fontSize: 12,
|
|
9119
|
-
fontFamily: "Inter, sans-serif"
|
|
9120
|
-
},
|
|
9121
|
-
children: previous ? `${previous.reps} x ${roundWeight(previous.weight)}` : "\u2014"
|
|
9122
|
-
}
|
|
9123
|
-
)
|
|
9124
|
-
}
|
|
9125
|
-
),
|
|
9126
|
-
/* @__PURE__ */ jsx(
|
|
9127
|
-
View,
|
|
9128
|
-
{
|
|
9129
|
-
style: { width: 44, alignItems: "center", justifyContent: "center" },
|
|
9130
|
-
testID: "set-row-reps",
|
|
9131
|
-
children: isActive && reps == null && targets ? /* @__PURE__ */ jsx(
|
|
9132
|
-
Text,
|
|
9133
|
-
{
|
|
9134
|
-
className: "text-text-tertiary",
|
|
9135
|
-
style: {
|
|
9136
|
-
fontSize: 13,
|
|
9137
|
-
fontStyle: "italic",
|
|
9138
|
-
fontFamily: "Inter, sans-serif"
|
|
9139
|
-
},
|
|
9140
|
-
testID: "set-row-target-reps",
|
|
9141
|
-
children: targets.reps
|
|
9142
|
-
}
|
|
9143
|
-
) : /* @__PURE__ */ jsx(
|
|
9144
|
-
Text,
|
|
9145
|
-
{
|
|
9146
|
-
className: reps != null ? "text-text-primary" : "text-text-tertiary",
|
|
9147
|
-
style: {
|
|
9148
|
-
fontSize: 14,
|
|
9149
|
-
fontWeight: "600",
|
|
9150
|
-
fontFamily: "Inter, sans-serif"
|
|
9151
|
-
},
|
|
9152
|
-
children: reps != null ? reps : "\u2014"
|
|
9153
|
-
}
|
|
9154
|
-
)
|
|
9155
|
-
}
|
|
9156
|
-
),
|
|
9157
|
-
/* @__PURE__ */ jsx(
|
|
9158
|
-
View,
|
|
9159
|
-
{
|
|
9160
|
-
style: { width: 56, alignItems: "center", justifyContent: "center" },
|
|
9161
|
-
testID: "set-row-weight",
|
|
9162
|
-
children: isActive && weight == null && targets ? /* @__PURE__ */ jsx(
|
|
9163
|
-
Text,
|
|
9164
|
-
{
|
|
9165
|
-
className: "text-text-tertiary",
|
|
9166
|
-
style: {
|
|
9167
|
-
fontSize: 13,
|
|
9168
|
-
fontStyle: "italic",
|
|
9169
|
-
fontFamily: "Inter, sans-serif"
|
|
9170
|
-
},
|
|
9171
|
-
testID: "set-row-target-weight",
|
|
9172
|
-
children: roundWeight(targets.weight)
|
|
9173
|
-
}
|
|
9174
|
-
) : /* @__PURE__ */ jsx(
|
|
9175
|
-
Text,
|
|
9176
|
-
{
|
|
9177
|
-
className: weight != null ? "text-text-primary" : "text-text-tertiary",
|
|
9178
|
-
style: {
|
|
9179
|
-
fontSize: 14,
|
|
9180
|
-
fontWeight: "600",
|
|
9181
|
-
fontFamily: "Inter, sans-serif"
|
|
9182
|
-
},
|
|
9183
|
-
children: weight != null ? roundWeight(weight) : "\u2014"
|
|
9184
|
-
}
|
|
9185
|
-
)
|
|
9186
|
-
}
|
|
9187
|
-
),
|
|
9188
|
-
/* @__PURE__ */ jsx(
|
|
9189
|
-
View,
|
|
9190
|
-
{
|
|
9191
|
-
style: { width: 36, alignItems: "center", justifyContent: "center" },
|
|
9192
|
-
testID: "set-row-rpe",
|
|
9193
|
-
children: /* @__PURE__ */ jsx(
|
|
9194
|
-
Text,
|
|
9195
|
-
{
|
|
9196
|
-
className: rpe != null ? void 0 : "text-text-tertiary",
|
|
9197
|
-
style: {
|
|
9198
|
-
fontSize: 13,
|
|
9199
|
-
fontWeight: "600",
|
|
9200
|
-
fontFamily: "Inter, sans-serif",
|
|
9201
|
-
// rpeColor returns a concrete hex (native-safe); only the tertiary
|
|
9202
|
-
// fallback needs the className token.
|
|
9203
|
-
color: rpe != null ? rpeColor(rpe) : void 0
|
|
9204
|
-
},
|
|
9205
|
-
children: rpe != null ? roundRpe(rpe) : "\u2014"
|
|
9206
|
-
}
|
|
9207
|
-
)
|
|
9208
|
-
}
|
|
9209
|
-
),
|
|
9210
|
-
prBadges && prBadges.length > 0 && /* @__PURE__ */ jsx(
|
|
9211
|
-
View,
|
|
9212
|
-
{
|
|
9213
|
-
className: "flex-row items-center",
|
|
9214
|
-
style: { gap: 4 },
|
|
9215
|
-
testID: "set-row-pr-badges",
|
|
9216
|
-
children: prBadges.map((badge, i) => /* @__PURE__ */ jsx(
|
|
9217
|
-
PrBadge,
|
|
9218
|
-
{
|
|
9219
|
-
type: badge.type,
|
|
9220
|
-
label: badge.label,
|
|
9221
|
-
animate: false,
|
|
9222
|
-
compact: true
|
|
9223
|
-
},
|
|
9224
|
-
i
|
|
9225
|
-
))
|
|
9226
|
-
}
|
|
9227
|
-
),
|
|
9228
|
-
velocities && velocities.length > 0 && /* @__PURE__ */ jsx(
|
|
9229
|
-
View,
|
|
9230
|
-
{
|
|
9231
|
-
style: { position: "absolute", bottom: 0, left: 8, right: 8 },
|
|
9232
|
-
testID: "set-row-velocity-strip",
|
|
9233
|
-
children: /* @__PURE__ */ jsx(
|
|
9234
|
-
VelocityStrip,
|
|
9235
|
-
{
|
|
9236
|
-
velocities,
|
|
9237
|
-
zones: velocityZones,
|
|
9238
|
-
liveRepIndex: velocityLiveRepIndex,
|
|
9239
|
-
expanded: velocityExpanded,
|
|
9240
|
-
onToggle: onVelocityToggle,
|
|
9241
|
-
variant: onVelocityToggle ? "full" : "mini"
|
|
9242
|
-
}
|
|
9243
|
-
)
|
|
9244
|
-
}
|
|
9245
|
-
)
|
|
9657
|
+
/* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { justifyContent: "space-between" }, children: [
|
|
9658
|
+
/* @__PURE__ */ jsx(Cell, { width: COL.set, testID: "set-row-set-number", children: set.setType ? /* @__PURE__ */ jsx(Text, { style: typeBadge, testID: "set-row-type-badge", children: set.setType }) : /* @__PURE__ */ jsx(Text, { style: { ...cellText, color: valueColor, fontWeight: live ? "700" : "600" }, children: set.setNumber }) }),
|
|
9659
|
+
/* @__PURE__ */ jsx(Cell, { width: COL.reps, testID: "set-row-reps", children: /* @__PURE__ */ jsx(Text, { style: { ...cellText, color: valueColor }, children: displayReps(set) }) }),
|
|
9660
|
+
/* @__PURE__ */ jsx(Cell, { width: COL.load, testID: "set-row-weight", children: /* @__PURE__ */ jsx(Text, { style: { ...cellText, color: valueColor }, children: roundWeight(displayWeight(set)) }) }),
|
|
9661
|
+
/* @__PURE__ */ jsx(Cell, { width: COL.rpe, testID: "set-row-rpe", children: /* @__PURE__ */ jsx(Text, { style: { ...cellText, color: TEXT_MUTED }, children: rpe != null ? roundRpe(rpe) : "\u2014" }) })
|
|
9662
|
+
] }),
|
|
9663
|
+
/* @__PURE__ */ jsx(View, { style: { marginTop: live ? 6 : 4 }, testID: "set-row-strip", children: /* @__PURE__ */ jsx(RowStrip, { set }) })
|
|
9246
9664
|
]
|
|
9247
9665
|
}
|
|
9248
9666
|
);
|
|
@@ -9413,14 +9831,18 @@ function RestTimer({
|
|
|
9413
9831
|
visible,
|
|
9414
9832
|
displayOnly = false
|
|
9415
9833
|
}) {
|
|
9416
|
-
|
|
9417
|
-
|
|
9834
|
+
const {
|
|
9835
|
+
remainingMs,
|
|
9836
|
+
progress,
|
|
9837
|
+
label: timeDisplay
|
|
9838
|
+
} = useTimer({
|
|
9839
|
+
mode: "down",
|
|
9840
|
+
durationMs: totalSeconds * 1e3,
|
|
9841
|
+
elapsedMs
|
|
9842
|
+
});
|
|
9418
9843
|
const remainingSec = Math.ceil(remainingMs / 1e3);
|
|
9419
|
-
const
|
|
9420
|
-
|
|
9421
|
-
const timeDisplay = `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
9422
|
-
const totalMs = totalSeconds * 1e3;
|
|
9423
|
-
const progressPct = totalMs > 0 ? Math.min(100, elapsedMs / totalMs * 100) : 100;
|
|
9844
|
+
const progressPct = progress * 100;
|
|
9845
|
+
if (!visible) return null;
|
|
9424
9846
|
return /* @__PURE__ */ jsxs(
|
|
9425
9847
|
View,
|
|
9426
9848
|
{
|
|
@@ -9578,15 +10000,319 @@ function RestTimer({
|
|
|
9578
10000
|
}
|
|
9579
10001
|
);
|
|
9580
10002
|
}
|
|
9581
|
-
|
|
9582
|
-
|
|
10003
|
+
var t8 = getSemanticColors("dark");
|
|
10004
|
+
var TIMES = "\xD7";
|
|
10005
|
+
var AT = "@";
|
|
10006
|
+
function SetsRepsLoad({
|
|
10007
|
+
sets,
|
|
10008
|
+
reps,
|
|
10009
|
+
load,
|
|
10010
|
+
unit = "lb",
|
|
10011
|
+
className,
|
|
10012
|
+
...props
|
|
10013
|
+
}) {
|
|
10014
|
+
const value = t8["text-primary"];
|
|
10015
|
+
const sep = t8["text-tertiary"];
|
|
10016
|
+
return /* @__PURE__ */ jsxs(
|
|
10017
|
+
View,
|
|
10018
|
+
{
|
|
10019
|
+
className,
|
|
10020
|
+
style: { flexDirection: "row", alignItems: "baseline" },
|
|
10021
|
+
accessibilityLabel: `${sets} sets of ${reps} reps at ${load} ${unit}`,
|
|
10022
|
+
testID: "sets-reps-load",
|
|
10023
|
+
...props,
|
|
10024
|
+
children: [
|
|
10025
|
+
/* @__PURE__ */ jsx(MetricCell, { color: value, children: sets }),
|
|
10026
|
+
/* @__PURE__ */ jsx(MetricCell, { color: sep, children: ` ${TIMES} ` }),
|
|
10027
|
+
/* @__PURE__ */ jsx(MetricCell, { color: value, children: reps }),
|
|
10028
|
+
/* @__PURE__ */ jsx(MetricCell, { color: sep, children: ` ${AT} ` }),
|
|
10029
|
+
/* @__PURE__ */ jsx(MetricCell, { color: value, children: load }),
|
|
10030
|
+
/* @__PURE__ */ jsx(MetricCell, { color: sep, children: ` ${unit}` })
|
|
10031
|
+
]
|
|
10032
|
+
}
|
|
10033
|
+
);
|
|
9583
10034
|
}
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
10035
|
+
|
|
10036
|
+
// src/components/custom/Workout/paceTone.ts
|
|
10037
|
+
function paceTone(progress, target) {
|
|
10038
|
+
if (target === void 0) return "neutral";
|
|
10039
|
+
return progress >= target ? "ahead" : "behind";
|
|
10040
|
+
}
|
|
10041
|
+
var PACE_TONE_COLORS = {
|
|
10042
|
+
ahead: getSemanticColors("dark")["status-success"],
|
|
10043
|
+
behind: getSemanticColors("dark")["status-warning"],
|
|
10044
|
+
neutral: primitiveRamps.cyan[400]
|
|
10045
|
+
};
|
|
10046
|
+
function paceToneColor(tone) {
|
|
10047
|
+
return PACE_TONE_COLORS[tone];
|
|
10048
|
+
}
|
|
10049
|
+
|
|
10050
|
+
// src/components/custom/Workout/SegmentedProgressBar.tsx
|
|
10051
|
+
var DEFAULT_MARKER_COLOR = primitiveRamps.green[500];
|
|
10052
|
+
function SegmentedProgressBar({
|
|
10053
|
+
segments,
|
|
10054
|
+
value,
|
|
10055
|
+
target,
|
|
10056
|
+
markerColor = DEFAULT_MARKER_COLOR,
|
|
10057
|
+
color,
|
|
10058
|
+
height,
|
|
10059
|
+
gap,
|
|
10060
|
+
...props
|
|
10061
|
+
}) {
|
|
10062
|
+
const total = segments.reduce((sum, s) => sum + s.weight, 0);
|
|
10063
|
+
const fillColor = color ?? paceToneColor(paceTone(total > 0 ? value / total : 0, target));
|
|
10064
|
+
const barSegments = segments.map((seg, i) => {
|
|
10065
|
+
const cumulativeBefore = segments.slice(0, i).reduce((sum, s) => sum + s.weight, 0);
|
|
10066
|
+
const fill = Math.max(0, Math.min(1, (value - cumulativeBefore) / seg.weight));
|
|
10067
|
+
return { weight: seg.weight, fill, color: fillColor };
|
|
10068
|
+
});
|
|
10069
|
+
return /* @__PURE__ */ jsx(
|
|
10070
|
+
SegmentedBar,
|
|
10071
|
+
{
|
|
10072
|
+
segments: barSegments,
|
|
10073
|
+
marker: target != null ? { position: target, color: markerColor } : null,
|
|
10074
|
+
height,
|
|
10075
|
+
gap,
|
|
10076
|
+
...props
|
|
10077
|
+
}
|
|
10078
|
+
);
|
|
10079
|
+
}
|
|
10080
|
+
|
|
10081
|
+
// src/components/custom/Workout/MetricTiles.tsx
|
|
10082
|
+
function MetricTiles({ metrics, gap = 1, ...props }) {
|
|
10083
|
+
return /* @__PURE__ */ jsx(HStack, { gap, align: "stretch", ...props, children: metrics.map((metric) => /* @__PURE__ */ jsx(
|
|
10084
|
+
Tile,
|
|
10085
|
+
{
|
|
10086
|
+
label: metric.label,
|
|
10087
|
+
value: metric.value,
|
|
10088
|
+
valueColor: metric.valueColor
|
|
10089
|
+
},
|
|
10090
|
+
metric.label
|
|
10091
|
+
)) });
|
|
10092
|
+
}
|
|
10093
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
10094
|
+
var SOON_ACCENT = primitiveRamps.orange[400];
|
|
10095
|
+
function compactUntil(ms) {
|
|
10096
|
+
if (ms <= 0) return "now";
|
|
10097
|
+
const min = Math.round(ms / 6e4);
|
|
10098
|
+
if (min < 60) return `${min}m`;
|
|
10099
|
+
const hr = Math.round(min / 60);
|
|
10100
|
+
if (hr < 24) return `${hr}h`;
|
|
10101
|
+
const d = Math.round(hr / 24);
|
|
10102
|
+
if (d < 7) return `${d}d`;
|
|
10103
|
+
return `${Math.round(d / 7)}w`;
|
|
10104
|
+
}
|
|
10105
|
+
function ScheduleTiles({ when, now, gap = 1, ...props }) {
|
|
10106
|
+
const [mountNow] = useState(() => Date.now());
|
|
10107
|
+
const reference = now ?? mountNow;
|
|
10108
|
+
const whenMs = when instanceof Date ? when.getTime() : when;
|
|
10109
|
+
const soon = whenMs - reference < DAY_MS;
|
|
10110
|
+
const time = new Date(whenMs).toLocaleTimeString(void 0, {
|
|
10111
|
+
hour: "numeric",
|
|
10112
|
+
minute: "2-digit",
|
|
10113
|
+
hour12: true
|
|
10114
|
+
});
|
|
10115
|
+
return /* @__PURE__ */ jsxs(HStack, { gap, ...props, children: [
|
|
10116
|
+
/* @__PURE__ */ jsx(Tile, { label: "Date", value: formatDateTime(when, "short") }),
|
|
10117
|
+
/* @__PURE__ */ jsx(Tile, { label: "Time", value: time }),
|
|
10118
|
+
/* @__PURE__ */ jsx(
|
|
10119
|
+
Tile,
|
|
10120
|
+
{
|
|
10121
|
+
label: "Until",
|
|
10122
|
+
value: compactUntil(whenMs - reference),
|
|
10123
|
+
valueColor: soon ? SOON_ACCENT : void 0
|
|
10124
|
+
}
|
|
10125
|
+
)
|
|
10126
|
+
] });
|
|
10127
|
+
}
|
|
10128
|
+
var t9 = getSemanticColors("dark");
|
|
10129
|
+
var INDICATOR_CONFIG = {
|
|
10130
|
+
imbalance: { Icon: ScaleIcon, color: t9["status-error"], label: "Left/right imbalance" },
|
|
10131
|
+
overshoot: { Icon: AlertTriangleIcon, color: t9["status-error"], label: "Load overshoot" },
|
|
10132
|
+
"velocity-loss": { Icon: TrendingDownIcon, color: t9["status-warning"], label: "Velocity loss" },
|
|
10133
|
+
"missed-reps": { Icon: CircleSlashIcon, color: t9["status-warning"], label: "Missed reps" },
|
|
10134
|
+
pr: { Icon: AwardIcon, color: t9["status-success"], label: "Personal record" },
|
|
10135
|
+
info: { Icon: InfoIcon, color: t9["status-info"], label: "More info" }
|
|
10136
|
+
};
|
|
10137
|
+
var INDICATOR_PRECEDENCE = [
|
|
10138
|
+
"imbalance",
|
|
10139
|
+
"overshoot",
|
|
10140
|
+
"velocity-loss",
|
|
10141
|
+
"missed-reps",
|
|
10142
|
+
"pr",
|
|
10143
|
+
"info"
|
|
10144
|
+
];
|
|
10145
|
+
function resolveIndicator(candidates) {
|
|
10146
|
+
return INDICATOR_PRECEDENCE.find((kind) => candidates.includes(kind));
|
|
10147
|
+
}
|
|
10148
|
+
function ExerciseIndicator({ kind, onPress, className, ...props }) {
|
|
10149
|
+
const { Icon, color, label } = INDICATOR_CONFIG[kind];
|
|
10150
|
+
const chip = /* @__PURE__ */ jsx(
|
|
10151
|
+
View,
|
|
10152
|
+
{
|
|
10153
|
+
className,
|
|
10154
|
+
style: {
|
|
10155
|
+
width: 16,
|
|
10156
|
+
height: 16,
|
|
10157
|
+
borderRadius: 8,
|
|
10158
|
+
borderWidth: 1,
|
|
10159
|
+
borderColor: color,
|
|
10160
|
+
alignItems: "center",
|
|
10161
|
+
justifyContent: "center"
|
|
10162
|
+
},
|
|
10163
|
+
accessibilityRole: "image",
|
|
10164
|
+
accessibilityLabel: label,
|
|
10165
|
+
testID: "exercise-indicator",
|
|
10166
|
+
...props,
|
|
10167
|
+
children: /* @__PURE__ */ jsx(Icon, { size: 11, color })
|
|
10168
|
+
}
|
|
10169
|
+
);
|
|
10170
|
+
if (onPress) {
|
|
10171
|
+
return /* @__PURE__ */ jsx(Pressable, { onPress, accessibilityRole: "button", accessibilityLabel: label, children: chip });
|
|
10172
|
+
}
|
|
10173
|
+
return chip;
|
|
10174
|
+
}
|
|
10175
|
+
function headingLabel(name, sets, reps, load, unit) {
|
|
10176
|
+
return `${name}, ${sets}\xD7${reps} @ ${roundWeight(load)} ${unit}`;
|
|
10177
|
+
}
|
|
10178
|
+
function ExerciseHeading({
|
|
10179
|
+
name,
|
|
10180
|
+
sets,
|
|
10181
|
+
reps,
|
|
10182
|
+
load,
|
|
10183
|
+
unit = "lbs",
|
|
10184
|
+
tempo,
|
|
10185
|
+
indicator,
|
|
10186
|
+
dimmed,
|
|
10187
|
+
onPress
|
|
10188
|
+
}) {
|
|
10189
|
+
return /* @__PURE__ */ jsxs(View, { style: { opacity: dimmed ? 0.55 : 1 }, testID: "exercise-heading", children: [
|
|
10190
|
+
/* @__PURE__ */ jsxs(
|
|
10191
|
+
Pressable,
|
|
10192
|
+
{
|
|
10193
|
+
onPress,
|
|
10194
|
+
accessibilityRole: "button",
|
|
10195
|
+
accessibilityLabel: headingLabel(name, sets, reps, load, unit),
|
|
10196
|
+
className: "flex-row items-center",
|
|
10197
|
+
style: { gap: 8 },
|
|
10198
|
+
testID: "exercise-card-header",
|
|
10199
|
+
children: [
|
|
10200
|
+
/* @__PURE__ */ jsx(
|
|
10201
|
+
Text,
|
|
10202
|
+
{
|
|
10203
|
+
className: "text-text-primary",
|
|
10204
|
+
style: { fontSize: 14, fontFamily: '"Space Grotesk", sans-serif', fontWeight: "700" },
|
|
10205
|
+
testID: "exercise-card-name",
|
|
10206
|
+
children: name
|
|
10207
|
+
}
|
|
10208
|
+
),
|
|
10209
|
+
/* @__PURE__ */ jsx(View, { className: "flex-1" }),
|
|
10210
|
+
indicator && /* @__PURE__ */ jsx(ExerciseIndicator, { kind: indicator })
|
|
10211
|
+
]
|
|
10212
|
+
}
|
|
10213
|
+
),
|
|
10214
|
+
/* @__PURE__ */ jsxs(
|
|
10215
|
+
View,
|
|
10216
|
+
{
|
|
10217
|
+
className: "flex-row items-center",
|
|
10218
|
+
style: { gap: 8, marginTop: 1 },
|
|
10219
|
+
testID: "exercise-card-summary",
|
|
10220
|
+
children: [
|
|
10221
|
+
/* @__PURE__ */ jsx(SetsRepsLoad, { sets, reps, load, unit }),
|
|
10222
|
+
/* @__PURE__ */ jsx(View, { className: "flex-1" }),
|
|
10223
|
+
tempo && /* @__PURE__ */ jsx(TempoDisplay, { tempo, size: "sm", showLabel: false, showInfo: false })
|
|
10224
|
+
]
|
|
10225
|
+
}
|
|
10226
|
+
)
|
|
10227
|
+
] });
|
|
10228
|
+
}
|
|
10229
|
+
function ExerciseCardHeading({
|
|
10230
|
+
setStates,
|
|
10231
|
+
stripHeight = 8,
|
|
10232
|
+
dimmed,
|
|
10233
|
+
testID = "exercise-card",
|
|
10234
|
+
...heading
|
|
10235
|
+
}) {
|
|
10236
|
+
return /* @__PURE__ */ jsxs(
|
|
10237
|
+
View,
|
|
10238
|
+
{
|
|
10239
|
+
style: { paddingVertical: 9, paddingHorizontal: 12, opacity: dimmed ? 0.55 : 1 },
|
|
10240
|
+
testID,
|
|
10241
|
+
children: [
|
|
10242
|
+
/* @__PURE__ */ jsx(ExerciseHeading, { ...heading }),
|
|
10243
|
+
setStates.length > 0 && /* @__PURE__ */ jsx(View, { style: { marginTop: 7 }, testID: "exercise-card-strip", children: /* @__PURE__ */ jsx(SetStrip, { sets: setStates, height: stripHeight }) })
|
|
10244
|
+
]
|
|
10245
|
+
}
|
|
10246
|
+
);
|
|
10247
|
+
}
|
|
10248
|
+
var PREV_COLUMN = { label: "PREV", width: void 0 };
|
|
10249
|
+
function buildColumns(unit, showPrevious) {
|
|
10250
|
+
return [
|
|
10251
|
+
{ label: "SET", width: 36 },
|
|
10252
|
+
...showPrevious ? [PREV_COLUMN] : [],
|
|
10253
|
+
{ label: "REPS", width: 44 },
|
|
10254
|
+
{ label: unit.toUpperCase(), width: 56 },
|
|
10255
|
+
{ label: "RPE", width: 36 }
|
|
10256
|
+
];
|
|
10257
|
+
}
|
|
10258
|
+
function SetTableHeader({
|
|
10259
|
+
unit = "lbs",
|
|
10260
|
+
showPrevious = true,
|
|
10261
|
+
testID = "table-header"
|
|
10262
|
+
}) {
|
|
10263
|
+
const columns = buildColumns(unit, showPrevious);
|
|
10264
|
+
return /* @__PURE__ */ jsx(
|
|
10265
|
+
View,
|
|
10266
|
+
{
|
|
10267
|
+
className: "flex-row",
|
|
10268
|
+
style: {
|
|
10269
|
+
paddingVertical: 8,
|
|
10270
|
+
paddingHorizontal: 8,
|
|
10271
|
+
paddingBottom: 4,
|
|
10272
|
+
...showPrevious ? {} : { justifyContent: "space-between" }
|
|
10273
|
+
},
|
|
10274
|
+
testID,
|
|
10275
|
+
children: columns.map(({ label, width }) => {
|
|
10276
|
+
const isFlex = width === void 0;
|
|
10277
|
+
return /* @__PURE__ */ jsx(
|
|
10278
|
+
View,
|
|
10279
|
+
{
|
|
10280
|
+
style: {
|
|
10281
|
+
...isFlex ? { minWidth: 44 } : { width, flexShrink: 1 },
|
|
10282
|
+
alignItems: "center",
|
|
10283
|
+
justifyContent: "center",
|
|
10284
|
+
gap: 8
|
|
10285
|
+
},
|
|
10286
|
+
...isFlex ? { className: "flex-1" } : {},
|
|
10287
|
+
children: /* @__PURE__ */ jsx(
|
|
10288
|
+
Text,
|
|
10289
|
+
{
|
|
10290
|
+
className: "text-text-tertiary",
|
|
10291
|
+
style: {
|
|
10292
|
+
fontSize: 10,
|
|
10293
|
+
fontWeight: "600",
|
|
10294
|
+
fontFamily: "Inter, sans-serif",
|
|
10295
|
+
textTransform: "uppercase",
|
|
10296
|
+
letterSpacing: 0.8
|
|
10297
|
+
},
|
|
10298
|
+
children: label
|
|
10299
|
+
}
|
|
10300
|
+
)
|
|
10301
|
+
},
|
|
10302
|
+
label
|
|
10303
|
+
);
|
|
10304
|
+
})
|
|
10305
|
+
}
|
|
10306
|
+
);
|
|
10307
|
+
}
|
|
10308
|
+
|
|
10309
|
+
// src/components/custom/Workout/ExerciseCard.tsx
|
|
10310
|
+
function getSupersetBorderRadius(position) {
|
|
10311
|
+
switch (position) {
|
|
10312
|
+
case "first":
|
|
10313
|
+
return {
|
|
10314
|
+
borderTopLeftRadius: 12,
|
|
10315
|
+
borderTopRightRadius: 12,
|
|
9590
10316
|
borderBottomLeftRadius: 8,
|
|
9591
10317
|
borderBottomRightRadius: 8
|
|
9592
10318
|
};
|
|
@@ -9623,7 +10349,7 @@ function formatSummary(summary) {
|
|
|
9623
10349
|
if (!summary) return "";
|
|
9624
10350
|
return `${summary.sets}\xD7${summary.reps} @ ${roundWeight(summary.weight)} ${summary.unit}`;
|
|
9625
10351
|
}
|
|
9626
|
-
function
|
|
10352
|
+
function formatAccessibilityLabel(name, summary, prescription) {
|
|
9627
10353
|
if (summary) return `${name}, ${formatSummary(summary)}`;
|
|
9628
10354
|
if (prescription) return `${name}, ${prescription}`;
|
|
9629
10355
|
return name;
|
|
@@ -9632,7 +10358,6 @@ function CollapsedCard({
|
|
|
9632
10358
|
name,
|
|
9633
10359
|
onToggle,
|
|
9634
10360
|
summary,
|
|
9635
|
-
e1rm,
|
|
9636
10361
|
isPR,
|
|
9637
10362
|
setVelocities,
|
|
9638
10363
|
velocityZones,
|
|
@@ -9651,7 +10376,7 @@ function CollapsedCard({
|
|
|
9651
10376
|
onPressIn: () => setPressed(true),
|
|
9652
10377
|
onPressOut: () => setPressed(false),
|
|
9653
10378
|
accessibilityRole: "button",
|
|
9654
|
-
accessibilityLabel:
|
|
10379
|
+
accessibilityLabel: formatAccessibilityLabel(name, summary, void 0),
|
|
9655
10380
|
testID: "exercise-card",
|
|
9656
10381
|
children: /* @__PURE__ */ jsxs(
|
|
9657
10382
|
View,
|
|
@@ -9665,100 +10390,93 @@ function CollapsedCard({
|
|
|
9665
10390
|
...supersetMargin
|
|
9666
10391
|
},
|
|
9667
10392
|
children: [
|
|
9668
|
-
/* @__PURE__ */ jsxs(
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
{
|
|
9718
|
-
className: "flex-row",
|
|
9719
|
-
style: { marginTop: 6, gap: 4 },
|
|
9720
|
-
testID: "exercise-card-strips",
|
|
9721
|
-
children: [
|
|
9722
|
-
setVelocities?.map((velocities, i) => /* @__PURE__ */ jsx(
|
|
9723
|
-
VelocityStrip,
|
|
9724
|
-
{
|
|
9725
|
-
velocities,
|
|
9726
|
-
zones: velocityZones,
|
|
9727
|
-
variant: "mini",
|
|
9728
|
-
testID: `exercise-card-velocity-strip-${i}`
|
|
9729
|
-
},
|
|
9730
|
-
i
|
|
9731
|
-
)),
|
|
9732
|
-
Array.from({ length: remaining }, (_, i) => /* @__PURE__ */ jsx(
|
|
9733
|
-
PlaceholderStrip,
|
|
9734
|
-
{
|
|
9735
|
-
testID: `exercise-card-placeholder-${i}`
|
|
9736
|
-
},
|
|
9737
|
-
`placeholder-${i}`
|
|
9738
|
-
))
|
|
9739
|
-
]
|
|
9740
|
-
}
|
|
9741
|
-
)
|
|
10393
|
+
/* @__PURE__ */ jsxs(View, { className: "flex-row items-center", testID: "exercise-card-header", children: [
|
|
10394
|
+
/* @__PURE__ */ jsx(
|
|
10395
|
+
Text,
|
|
10396
|
+
{
|
|
10397
|
+
className: "text-text-primary",
|
|
10398
|
+
style: {
|
|
10399
|
+
fontSize: 14,
|
|
10400
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
10401
|
+
fontWeight: "700"
|
|
10402
|
+
},
|
|
10403
|
+
testID: "exercise-card-name",
|
|
10404
|
+
children: name
|
|
10405
|
+
}
|
|
10406
|
+
),
|
|
10407
|
+
/* @__PURE__ */ jsx(View, { className: "flex-1" }),
|
|
10408
|
+
summary && /* @__PURE__ */ jsx(
|
|
10409
|
+
Text,
|
|
10410
|
+
{
|
|
10411
|
+
className: "text-text-secondary",
|
|
10412
|
+
style: {
|
|
10413
|
+
fontSize: 12,
|
|
10414
|
+
fontFamily: "Inter, sans-serif",
|
|
10415
|
+
marginRight: 8
|
|
10416
|
+
},
|
|
10417
|
+
testID: "exercise-card-summary",
|
|
10418
|
+
children: formatSummary(summary)
|
|
10419
|
+
}
|
|
10420
|
+
),
|
|
10421
|
+
isPR && /* @__PURE__ */ jsx(View, { style: { marginLeft: 4 }, children: /* @__PURE__ */ jsx(PrBadge, { type: "e1rm", compact: true, animate: false }) })
|
|
10422
|
+
] }),
|
|
10423
|
+
(completedSets > 0 || remaining > 0) && /* @__PURE__ */ jsxs(View, { className: "flex-row", style: { marginTop: 6, gap: 4 }, testID: "exercise-card-strips", children: [
|
|
10424
|
+
setVelocities?.map((velocities, i) => /* @__PURE__ */ jsx(
|
|
10425
|
+
VelocityStrip,
|
|
10426
|
+
{
|
|
10427
|
+
velocities,
|
|
10428
|
+
zones: velocityZones,
|
|
10429
|
+
variant: "mini",
|
|
10430
|
+
testID: `exercise-card-velocity-strip-${i}`
|
|
10431
|
+
},
|
|
10432
|
+
i
|
|
10433
|
+
)),
|
|
10434
|
+
Array.from({ length: remaining }, (_, i) => /* @__PURE__ */ jsx(
|
|
10435
|
+
PlaceholderStrip,
|
|
10436
|
+
{
|
|
10437
|
+
testID: `exercise-card-placeholder-${i}`
|
|
10438
|
+
},
|
|
10439
|
+
`placeholder-${i}`
|
|
10440
|
+
))
|
|
10441
|
+
] })
|
|
9742
10442
|
]
|
|
9743
10443
|
}
|
|
9744
10444
|
)
|
|
9745
10445
|
}
|
|
9746
10446
|
);
|
|
9747
10447
|
}
|
|
10448
|
+
var DARK2 = getSemanticColors("dark");
|
|
10449
|
+
var BODY_DIVIDER = DARK2["border-subtle"];
|
|
10450
|
+
function deriveHeaderSetStates(sets) {
|
|
10451
|
+
return sets.map((set) => {
|
|
10452
|
+
switch (set.state) {
|
|
10453
|
+
case "live":
|
|
10454
|
+
return { status: "active", velocities: set.velocities, planned: set.target.reps };
|
|
10455
|
+
case "done":
|
|
10456
|
+
return { status: "done", velocities: set.velocities };
|
|
10457
|
+
case "todo":
|
|
10458
|
+
return { status: "todo", planned: set.planned ?? set.target.reps };
|
|
10459
|
+
}
|
|
10460
|
+
});
|
|
10461
|
+
}
|
|
9748
10462
|
function ExpandedCard({
|
|
9749
10463
|
name,
|
|
9750
10464
|
onToggle,
|
|
9751
10465
|
summary,
|
|
9752
|
-
e1rm,
|
|
9753
10466
|
isPR,
|
|
9754
10467
|
sets,
|
|
9755
10468
|
tempo,
|
|
10469
|
+
indicator,
|
|
10470
|
+
setStates,
|
|
10471
|
+
stripHeight = 8,
|
|
10472
|
+
velocityZones,
|
|
9756
10473
|
supersetPosition
|
|
9757
10474
|
}) {
|
|
9758
10475
|
const borderRadius = getSupersetBorderRadius(supersetPosition);
|
|
9759
10476
|
const supersetMargin = getSupersetMargin(supersetPosition);
|
|
9760
10477
|
const unit = summary?.unit ?? sets?.[0]?.unit ?? "lbs";
|
|
9761
|
-
const
|
|
10478
|
+
const headerStates = setStates ?? (sets ? deriveHeaderSetStates(sets) : []);
|
|
10479
|
+
const headerIndicator = indicator ?? (isPR ? "pr" : void 0);
|
|
9762
10480
|
return /* @__PURE__ */ jsxs(
|
|
9763
10481
|
View,
|
|
9764
10482
|
{
|
|
@@ -9771,114 +10489,32 @@ function ExpandedCard({
|
|
|
9771
10489
|
testID: "exercise-card",
|
|
9772
10490
|
children: [
|
|
9773
10491
|
/* @__PURE__ */ jsx(
|
|
9774
|
-
|
|
10492
|
+
ExerciseCardHeading,
|
|
9775
10493
|
{
|
|
10494
|
+
name,
|
|
10495
|
+
sets: summary?.sets ?? sets?.length ?? 0,
|
|
10496
|
+
reps: summary?.reps ?? 0,
|
|
10497
|
+
load: summary?.weight ?? 0,
|
|
10498
|
+
unit,
|
|
10499
|
+
tempo,
|
|
10500
|
+
indicator: headerIndicator,
|
|
10501
|
+
setStates: headerStates,
|
|
10502
|
+
stripHeight,
|
|
9776
10503
|
onPress: onToggle,
|
|
9777
|
-
|
|
9778
|
-
accessibilityLabel: formatAccessibilityLabel2(name, summary, void 0),
|
|
9779
|
-
"aria-expanded": true,
|
|
9780
|
-
testID: "exercise-card-header",
|
|
9781
|
-
children: /* @__PURE__ */ jsxs(
|
|
9782
|
-
View,
|
|
9783
|
-
{
|
|
9784
|
-
className: "flex-row items-center",
|
|
9785
|
-
style: {
|
|
9786
|
-
padding: 12,
|
|
9787
|
-
paddingHorizontal: 14,
|
|
9788
|
-
paddingBottom: 10,
|
|
9789
|
-
borderBottomWidth: 1,
|
|
9790
|
-
borderBottomColor: resolveColor("border-default")
|
|
9791
|
-
},
|
|
9792
|
-
children: [
|
|
9793
|
-
/* @__PURE__ */ jsx(
|
|
9794
|
-
Text,
|
|
9795
|
-
{
|
|
9796
|
-
className: "text-text-primary",
|
|
9797
|
-
style: {
|
|
9798
|
-
fontSize: 14,
|
|
9799
|
-
fontFamily: '"Space Grotesk", sans-serif',
|
|
9800
|
-
fontWeight: "700"
|
|
9801
|
-
},
|
|
9802
|
-
testID: "exercise-card-name",
|
|
9803
|
-
children: name
|
|
9804
|
-
}
|
|
9805
|
-
),
|
|
9806
|
-
/* @__PURE__ */ jsx(View, { className: "flex-1" }),
|
|
9807
|
-
summary && /* @__PURE__ */ jsx(
|
|
9808
|
-
Text,
|
|
9809
|
-
{
|
|
9810
|
-
className: "text-text-secondary",
|
|
9811
|
-
style: {
|
|
9812
|
-
fontSize: 12,
|
|
9813
|
-
fontFamily: "Inter, sans-serif",
|
|
9814
|
-
marginRight: 8
|
|
9815
|
-
},
|
|
9816
|
-
testID: "exercise-card-summary",
|
|
9817
|
-
children: formatSummary(summary)
|
|
9818
|
-
}
|
|
9819
|
-
),
|
|
9820
|
-
e1rm && /* @__PURE__ */ jsx(
|
|
9821
|
-
WeightBadge,
|
|
9822
|
-
{
|
|
9823
|
-
value: roundWeight(e1rm.value),
|
|
9824
|
-
unit: e1rm.unit,
|
|
9825
|
-
size: "sm",
|
|
9826
|
-
showIcon: false,
|
|
9827
|
-
testID: "exercise-card-e1rm"
|
|
9828
|
-
}
|
|
9829
|
-
),
|
|
9830
|
-
isPR && /* @__PURE__ */ jsx(View, { style: { marginLeft: 4 }, children: /* @__PURE__ */ jsx(PrBadge, { type: "e1rm", compact: true, animate: false }) })
|
|
9831
|
-
]
|
|
9832
|
-
}
|
|
9833
|
-
)
|
|
10504
|
+
testID: "exercise-card-heading"
|
|
9834
10505
|
}
|
|
9835
10506
|
),
|
|
9836
|
-
|
|
9837
|
-
/* @__PURE__ */ jsx(
|
|
10507
|
+
/* @__PURE__ */ jsxs(
|
|
9838
10508
|
View,
|
|
9839
10509
|
{
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
testID: "exercise-card-column-headers",
|
|
9847
|
-
children: columnHeaders.map((header, i) => {
|
|
9848
|
-
const widths = [36, void 0, 44, 56, 36];
|
|
9849
|
-
const width = widths[i];
|
|
9850
|
-
const isFlex = width === void 0;
|
|
9851
|
-
return /* @__PURE__ */ jsx(
|
|
9852
|
-
View,
|
|
9853
|
-
{
|
|
9854
|
-
style: {
|
|
9855
|
-
...isFlex ? {} : { width },
|
|
9856
|
-
alignItems: "center",
|
|
9857
|
-
justifyContent: "center",
|
|
9858
|
-
gap: 8
|
|
9859
|
-
},
|
|
9860
|
-
...isFlex ? { className: "flex-1" } : {},
|
|
9861
|
-
children: /* @__PURE__ */ jsx(
|
|
9862
|
-
Text,
|
|
9863
|
-
{
|
|
9864
|
-
className: "text-text-tertiary",
|
|
9865
|
-
style: {
|
|
9866
|
-
fontSize: 10,
|
|
9867
|
-
fontWeight: "600",
|
|
9868
|
-
fontFamily: "Inter, sans-serif",
|
|
9869
|
-
textTransform: "uppercase",
|
|
9870
|
-
letterSpacing: 0.8
|
|
9871
|
-
},
|
|
9872
|
-
children: header
|
|
9873
|
-
}
|
|
9874
|
-
)
|
|
9875
|
-
},
|
|
9876
|
-
header
|
|
9877
|
-
);
|
|
9878
|
-
})
|
|
10510
|
+
style: { borderTopWidth: 1, borderTopColor: BODY_DIVIDER, paddingBottom: 6 },
|
|
10511
|
+
testID: "exercise-card-body",
|
|
10512
|
+
children: [
|
|
10513
|
+
/* @__PURE__ */ jsx(SetTableHeader, { unit, showPrevious: false, testID: "exercise-card-column-headers" }),
|
|
10514
|
+
sets && /* @__PURE__ */ jsx(View, { testID: "exercise-card-sets", children: sets.map((set, i) => /* @__PURE__ */ jsx(SetRow, { ...set, velocityZones: set.velocityZones ?? velocityZones }, i)) })
|
|
10515
|
+
]
|
|
9879
10516
|
}
|
|
9880
|
-
)
|
|
9881
|
-
sets && /* @__PURE__ */ jsx(View, { testID: "exercise-card-sets", children: sets.map((setProps, i) => /* @__PURE__ */ jsx(SetRow, { ...setProps }, i)) })
|
|
10517
|
+
)
|
|
9882
10518
|
]
|
|
9883
10519
|
}
|
|
9884
10520
|
);
|
|
@@ -9887,11 +10523,12 @@ function UpcomingCard({
|
|
|
9887
10523
|
name,
|
|
9888
10524
|
prescription,
|
|
9889
10525
|
previousBest,
|
|
9890
|
-
supersetPosition
|
|
10526
|
+
supersetPosition,
|
|
10527
|
+
onToggle
|
|
9891
10528
|
}) {
|
|
9892
10529
|
const borderRadius = getSupersetBorderRadius(supersetPosition);
|
|
9893
10530
|
const supersetMargin = getSupersetMargin(supersetPosition);
|
|
9894
|
-
return /* @__PURE__ */ jsx(
|
|
10531
|
+
return /* @__PURE__ */ jsx(Pressable, { onPress: onToggle, accessibilityRole: "button", children: /* @__PURE__ */ jsx(
|
|
9895
10532
|
View,
|
|
9896
10533
|
{
|
|
9897
10534
|
style: {
|
|
@@ -9901,7 +10538,7 @@ function UpcomingCard({
|
|
|
9901
10538
|
...borderRadius,
|
|
9902
10539
|
...supersetMargin
|
|
9903
10540
|
},
|
|
9904
|
-
accessibilityLabel:
|
|
10541
|
+
accessibilityLabel: formatAccessibilityLabel(name, void 0, prescription),
|
|
9905
10542
|
testID: "exercise-card",
|
|
9906
10543
|
children: /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", children: [
|
|
9907
10544
|
/* @__PURE__ */ jsx(
|
|
@@ -9909,6 +10546,7 @@ function UpcomingCard({
|
|
|
9909
10546
|
{
|
|
9910
10547
|
className: "text-text-primary",
|
|
9911
10548
|
style: {
|
|
10549
|
+
flexShrink: 0,
|
|
9912
10550
|
fontSize: 14,
|
|
9913
10551
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
9914
10552
|
fontWeight: "700"
|
|
@@ -9921,7 +10559,9 @@ function UpcomingCard({
|
|
|
9921
10559
|
Text,
|
|
9922
10560
|
{
|
|
9923
10561
|
className: "text-text-secondary",
|
|
10562
|
+
numberOfLines: 1,
|
|
9924
10563
|
style: {
|
|
10564
|
+
flexShrink: 1,
|
|
9925
10565
|
fontSize: 12,
|
|
9926
10566
|
fontFamily: "Inter, sans-serif",
|
|
9927
10567
|
marginLeft: 8
|
|
@@ -9930,12 +10570,14 @@ function UpcomingCard({
|
|
|
9930
10570
|
children: prescription
|
|
9931
10571
|
}
|
|
9932
10572
|
),
|
|
9933
|
-
/* @__PURE__ */ jsx(View, { className: "flex-1" }),
|
|
10573
|
+
/* @__PURE__ */ jsx(View, { className: "flex-1", style: { minWidth: 8 } }),
|
|
9934
10574
|
previousBest && /* @__PURE__ */ jsx(
|
|
9935
10575
|
Text,
|
|
9936
10576
|
{
|
|
9937
10577
|
className: "text-text-tertiary",
|
|
10578
|
+
numberOfLines: 1,
|
|
9938
10579
|
style: {
|
|
10580
|
+
flexShrink: 1,
|
|
9939
10581
|
fontSize: 11,
|
|
9940
10582
|
fontFamily: "Inter, sans-serif"
|
|
9941
10583
|
},
|
|
@@ -9945,17 +10587,208 @@ function UpcomingCard({
|
|
|
9945
10587
|
)
|
|
9946
10588
|
] })
|
|
9947
10589
|
}
|
|
10590
|
+
) });
|
|
10591
|
+
}
|
|
10592
|
+
function ExerciseCard({
|
|
10593
|
+
upcoming,
|
|
10594
|
+
expanded,
|
|
10595
|
+
defaultExpanded,
|
|
10596
|
+
onExpandedChange,
|
|
10597
|
+
...rest
|
|
10598
|
+
}) {
|
|
10599
|
+
const [internalExpanded, setInternalExpanded] = useState(defaultExpanded ?? false);
|
|
10600
|
+
const isControlled = expanded !== void 0;
|
|
10601
|
+
const isExpanded = isControlled ? expanded : internalExpanded;
|
|
10602
|
+
const onToggle = () => {
|
|
10603
|
+
const next = !isExpanded;
|
|
10604
|
+
onExpandedChange?.(next);
|
|
10605
|
+
if (!isControlled) setInternalExpanded(next);
|
|
10606
|
+
};
|
|
10607
|
+
if (upcoming) return /* @__PURE__ */ jsx(UpcomingCard, { ...rest, onToggle });
|
|
10608
|
+
return isExpanded ? /* @__PURE__ */ jsx(ExpandedCard, { ...rest, onToggle }) : /* @__PURE__ */ jsx(CollapsedCard, { ...rest, onToggle });
|
|
10609
|
+
}
|
|
10610
|
+
var t10 = getSemanticColors("dark");
|
|
10611
|
+
var RAISED = primitiveColors.charcoal[400];
|
|
10612
|
+
var BAR_HEIGHT = 9;
|
|
10613
|
+
var BAR_GAP = 3;
|
|
10614
|
+
function SessionHeader({
|
|
10615
|
+
title,
|
|
10616
|
+
plan,
|
|
10617
|
+
setsDone = 0,
|
|
10618
|
+
elapsedMs,
|
|
10619
|
+
budgetMs,
|
|
10620
|
+
running = true,
|
|
10621
|
+
metrics = [],
|
|
10622
|
+
next,
|
|
10623
|
+
className,
|
|
10624
|
+
style,
|
|
10625
|
+
...props
|
|
10626
|
+
}) {
|
|
10627
|
+
const upcoming = next != null;
|
|
10628
|
+
const totalSets = plan.reduce((sum, e) => sum + e.sets, 0);
|
|
10629
|
+
const hasPace = !upcoming && budgetMs != null && elapsedMs != null;
|
|
10630
|
+
const target = hasPace ? elapsedMs / budgetMs : void 0;
|
|
10631
|
+
const setsLabel = upcoming ? `${totalSets} sets` : `${Math.floor(setsDone)}/${totalSets} sets`;
|
|
10632
|
+
const setsLabelColor = upcoming ? t10["text-secondary"] : paceToneColor(paceTone(totalSets > 0 ? setsDone / totalSets : 0, target));
|
|
10633
|
+
return /* @__PURE__ */ jsxs(
|
|
10634
|
+
View,
|
|
10635
|
+
{
|
|
10636
|
+
className,
|
|
10637
|
+
style: [
|
|
10638
|
+
{
|
|
10639
|
+
backgroundColor: RAISED,
|
|
10640
|
+
paddingTop: 11,
|
|
10641
|
+
paddingRight: 12,
|
|
10642
|
+
paddingBottom: 12,
|
|
10643
|
+
paddingLeft: 12,
|
|
10644
|
+
zIndex: 2
|
|
10645
|
+
},
|
|
10646
|
+
style
|
|
10647
|
+
],
|
|
10648
|
+
testID: "session-rail-header",
|
|
10649
|
+
...props,
|
|
10650
|
+
children: [
|
|
10651
|
+
/* @__PURE__ */ jsx(
|
|
10652
|
+
Text,
|
|
10653
|
+
{
|
|
10654
|
+
accessibilityRole: "header",
|
|
10655
|
+
style: {
|
|
10656
|
+
fontSize: 16,
|
|
10657
|
+
lineHeight: 18,
|
|
10658
|
+
fontWeight: "700",
|
|
10659
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
10660
|
+
color: t10["text-primary"],
|
|
10661
|
+
marginBottom: 10
|
|
10662
|
+
},
|
|
10663
|
+
testID: "session-rail-title",
|
|
10664
|
+
children: title
|
|
10665
|
+
}
|
|
10666
|
+
),
|
|
10667
|
+
upcoming ? /* @__PURE__ */ jsx(ScheduleTiles, { when: next }) : /* @__PURE__ */ jsx(MetricTiles, { metrics }),
|
|
10668
|
+
/* @__PURE__ */ jsxs(View, { style: { marginTop: 10 }, children: [
|
|
10669
|
+
/* @__PURE__ */ jsx(
|
|
10670
|
+
SegmentedProgressBar,
|
|
10671
|
+
{
|
|
10672
|
+
segments: plan.map((e) => ({ weight: e.sets })),
|
|
10673
|
+
value: upcoming ? 0 : setsDone,
|
|
10674
|
+
target,
|
|
10675
|
+
height: BAR_HEIGHT,
|
|
10676
|
+
gap: BAR_GAP
|
|
10677
|
+
}
|
|
10678
|
+
),
|
|
10679
|
+
/* @__PURE__ */ jsxs(
|
|
10680
|
+
View,
|
|
10681
|
+
{
|
|
10682
|
+
style: {
|
|
10683
|
+
flexDirection: "row",
|
|
10684
|
+
justifyContent: "space-between",
|
|
10685
|
+
alignItems: "baseline",
|
|
10686
|
+
marginTop: 5
|
|
10687
|
+
},
|
|
10688
|
+
children: [
|
|
10689
|
+
/* @__PURE__ */ jsx(
|
|
10690
|
+
Typography,
|
|
10691
|
+
{
|
|
10692
|
+
variant: "mono",
|
|
10693
|
+
style: { fontSize: 10, color: setsLabelColor },
|
|
10694
|
+
testID: "session-rail-sets",
|
|
10695
|
+
children: setsLabel
|
|
10696
|
+
}
|
|
10697
|
+
),
|
|
10698
|
+
/* @__PURE__ */ jsx(
|
|
10699
|
+
TimerReadout,
|
|
10700
|
+
{
|
|
10701
|
+
mode: "up",
|
|
10702
|
+
elapsedMs: upcoming ? budgetMs : elapsedMs,
|
|
10703
|
+
durationMs: budgetMs,
|
|
10704
|
+
running: running && !upcoming,
|
|
10705
|
+
showTotal: budgetMs != null && !upcoming
|
|
10706
|
+
}
|
|
10707
|
+
)
|
|
10708
|
+
]
|
|
10709
|
+
}
|
|
10710
|
+
)
|
|
10711
|
+
] })
|
|
10712
|
+
]
|
|
10713
|
+
}
|
|
9948
10714
|
);
|
|
9949
10715
|
}
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
|
|
10716
|
+
var INSET = primitiveColors.charcoal[800];
|
|
10717
|
+
var DIVIDER = primitiveColors.charcoal[500];
|
|
10718
|
+
var DEFAULT_WIDTH = 246;
|
|
10719
|
+
function SessionRail({
|
|
10720
|
+
title,
|
|
10721
|
+
exercises,
|
|
10722
|
+
setsDone,
|
|
10723
|
+
elapsedMs,
|
|
10724
|
+
budgetMs,
|
|
10725
|
+
running,
|
|
10726
|
+
metrics,
|
|
10727
|
+
next,
|
|
10728
|
+
stripHeight = 8,
|
|
10729
|
+
width = DEFAULT_WIDTH,
|
|
10730
|
+
onExercisePress,
|
|
10731
|
+
className,
|
|
10732
|
+
style,
|
|
10733
|
+
...props
|
|
10734
|
+
}) {
|
|
10735
|
+
return /* @__PURE__ */ jsxs(
|
|
10736
|
+
View,
|
|
10737
|
+
{
|
|
10738
|
+
className,
|
|
10739
|
+
style: [{ width, flexDirection: "column", backgroundColor: INSET }, style],
|
|
10740
|
+
testID: "session-rail",
|
|
10741
|
+
...props,
|
|
10742
|
+
children: [
|
|
10743
|
+
/* @__PURE__ */ jsx(
|
|
10744
|
+
SessionHeader,
|
|
10745
|
+
{
|
|
10746
|
+
title,
|
|
10747
|
+
plan: exercises.map((ex) => ({ name: ex.name, sets: ex.summary.sets })),
|
|
10748
|
+
setsDone,
|
|
10749
|
+
elapsedMs,
|
|
10750
|
+
budgetMs,
|
|
10751
|
+
running,
|
|
10752
|
+
metrics,
|
|
10753
|
+
next
|
|
10754
|
+
}
|
|
10755
|
+
),
|
|
10756
|
+
/* @__PURE__ */ jsx(
|
|
10757
|
+
View,
|
|
10758
|
+
{
|
|
10759
|
+
style: [{ flex: 1, backgroundColor: INSET }, neumorphicShadows.charcoal.pressed.subtle],
|
|
10760
|
+
testID: "session-rail-list",
|
|
10761
|
+
children: exercises.map((ex, i) => /* @__PURE__ */ jsx(
|
|
10762
|
+
View,
|
|
10763
|
+
{
|
|
10764
|
+
style: {
|
|
10765
|
+
borderBottomWidth: i < exercises.length - 1 ? 1 : 0,
|
|
10766
|
+
borderBottomColor: DIVIDER
|
|
10767
|
+
},
|
|
10768
|
+
children: /* @__PURE__ */ jsx(
|
|
10769
|
+
ExerciseCardHeading,
|
|
10770
|
+
{
|
|
10771
|
+
name: ex.name,
|
|
10772
|
+
sets: ex.summary.sets,
|
|
10773
|
+
reps: ex.summary.reps,
|
|
10774
|
+
load: ex.summary.weight,
|
|
10775
|
+
unit: ex.summary.unit,
|
|
10776
|
+
tempo: ex.tempo,
|
|
10777
|
+
indicator: ex.indicator,
|
|
10778
|
+
setStates: ex.setStates,
|
|
10779
|
+
stripHeight,
|
|
10780
|
+
dimmed: ex.upcoming,
|
|
10781
|
+
onPress: () => onExercisePress?.(ex, i)
|
|
10782
|
+
}
|
|
10783
|
+
)
|
|
10784
|
+
},
|
|
10785
|
+
ex.id ?? i
|
|
10786
|
+
))
|
|
10787
|
+
}
|
|
10788
|
+
)
|
|
10789
|
+
]
|
|
10790
|
+
}
|
|
10791
|
+
);
|
|
9959
10792
|
}
|
|
9960
10793
|
var DEFAULTS = {
|
|
9961
10794
|
label: "SS",
|
|
@@ -10219,10 +11052,10 @@ function WeekRow({
|
|
|
10219
11052
|
}
|
|
10220
11053
|
);
|
|
10221
11054
|
}
|
|
10222
|
-
var
|
|
11055
|
+
var t11 = getSemanticColors("dark");
|
|
10223
11056
|
var COLORS = {
|
|
10224
|
-
statusSuccess:
|
|
10225
|
-
brandPrimary:
|
|
11057
|
+
statusSuccess: t11["status-success"],
|
|
11058
|
+
brandPrimary: t11["brand-primary"],
|
|
10226
11059
|
borderDefault: "#1F1F1F",
|
|
10227
11060
|
brandPrimarySubtle: "rgba(255,121,0,0.06)"
|
|
10228
11061
|
};
|
|
@@ -10706,12 +11539,12 @@ function PrHistoryModal({
|
|
|
10706
11539
|
}
|
|
10707
11540
|
);
|
|
10708
11541
|
}
|
|
10709
|
-
var
|
|
10710
|
-
var BRAND_PRIMARY9 =
|
|
11542
|
+
var t12 = getSemanticColors("dark");
|
|
11543
|
+
var BRAND_PRIMARY9 = t12["brand-primary"];
|
|
10711
11544
|
var BRAND_PRIMARY_SUBTLE = "rgba(255,121,0,0.12)";
|
|
10712
|
-
var STATUS_SUCCESS =
|
|
10713
|
-
var STATUS_WARNING =
|
|
10714
|
-
var STATUS_ERROR2 =
|
|
11545
|
+
var STATUS_SUCCESS = t12["status-success"];
|
|
11546
|
+
var STATUS_WARNING = t12["status-warning"];
|
|
11547
|
+
var STATUS_ERROR2 = t12["status-error"];
|
|
10715
11548
|
var EMOJI_SETS = {
|
|
10716
11549
|
sleep: ["\u{1F634}", "\u{1F610}", "\u{1F642}", "\u{1F60A}", "\u{1F929}"],
|
|
10717
11550
|
soreness: ["\u{1F635}", "\u{1F623}", "\u{1F610}", "\u{1F642}", "\u{1F4AA}"],
|
|
@@ -10901,13 +11734,13 @@ function ReadinessCheck({
|
|
|
10901
11734
|
)
|
|
10902
11735
|
] }) });
|
|
10903
11736
|
}
|
|
10904
|
-
var
|
|
10905
|
-
var BRAND_PRIMARY10 =
|
|
11737
|
+
var t13 = getSemanticColors("dark");
|
|
11738
|
+
var BRAND_PRIMARY10 = t13["brand-primary"];
|
|
10906
11739
|
var BRAND_PRIMARY_DARK2 = MESO_ACCENT_GRADIENT_DARK;
|
|
10907
11740
|
var BRAND_PRIMARY_LIGHT2 = MESO_ACCENT_GRADIENT_LIGHT;
|
|
10908
|
-
var SUCCESS =
|
|
10909
|
-
var WARNING =
|
|
10910
|
-
var ERROR =
|
|
11741
|
+
var SUCCESS = t13["status-success"];
|
|
11742
|
+
var WARNING = t13["status-warning"];
|
|
11743
|
+
var ERROR = t13["status-error"];
|
|
10911
11744
|
var ACCENT_STOPS2 = [BRAND_PRIMARY_DARK2, BRAND_PRIMARY10, BRAND_PRIMARY_LIGHT2];
|
|
10912
11745
|
var CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor("surface-elevated")} 0%, ${resolveColor("surface-raised")} 100%)`;
|
|
10913
11746
|
var GAUGE_GRADIENT = "linear-gradient(90deg, rgba(46,213,115,0.25) 0%, rgba(249,180,21,0.25) 50%, rgba(209,67,67,0.25) 100%)";
|
|
@@ -10979,7 +11812,7 @@ function StatusPill({ badge }) {
|
|
|
10979
11812
|
}
|
|
10980
11813
|
);
|
|
10981
11814
|
}
|
|
10982
|
-
function
|
|
11815
|
+
function MetricCell2({ metric }) {
|
|
10983
11816
|
return /* @__PURE__ */ jsxs(View, { style: { width: "48%" }, testID: "meso-status-card-metric", children: [
|
|
10984
11817
|
/* @__PURE__ */ jsx(
|
|
10985
11818
|
Text,
|
|
@@ -11197,7 +12030,7 @@ function MesoStatusCard({
|
|
|
11197
12030
|
className: "flex-row flex-wrap",
|
|
11198
12031
|
style: { gap: 8 },
|
|
11199
12032
|
testID: "meso-status-card-metrics",
|
|
11200
|
-
children: metrics.map((metric, index) => /* @__PURE__ */ jsx(
|
|
12033
|
+
children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell2, { metric }, `${metric.label}-${index}`))
|
|
11201
12034
|
}
|
|
11202
12035
|
),
|
|
11203
12036
|
gauges.length > 0 && /* @__PURE__ */ jsx(View, { style: { gap: 12 }, testID: "meso-status-card-gauges", children: gauges.map((gauge, index) => /* @__PURE__ */ jsx(Gauge, { gauge }, `${gauge.label}-${index}`)) }),
|
|
@@ -11278,8 +12111,8 @@ var ERROR_PILL_BORDER = "rgba(209,67,67,0.20)";
|
|
|
11278
12111
|
var PLOT_LEFT = 26;
|
|
11279
12112
|
var TOOLTIP_WIDTH = 124;
|
|
11280
12113
|
function timeOf(dateStr) {
|
|
11281
|
-
const
|
|
11282
|
-
return Number.isNaN(
|
|
12114
|
+
const t18 = Date.parse(dateStr);
|
|
12115
|
+
return Number.isNaN(t18) ? 0 : t18;
|
|
11283
12116
|
}
|
|
11284
12117
|
function formatValue(value) {
|
|
11285
12118
|
return `${Math.round(value)}`;
|
|
@@ -11768,10 +12601,10 @@ function StrengthTrendChart({
|
|
|
11768
12601
|
}
|
|
11769
12602
|
);
|
|
11770
12603
|
}
|
|
11771
|
-
var
|
|
11772
|
-
var STATUS_SUCCESS3 =
|
|
11773
|
-
var STATUS_WARNING3 =
|
|
11774
|
-
var STATUS_INFO =
|
|
12604
|
+
var t14 = getSemanticColors("dark");
|
|
12605
|
+
var STATUS_SUCCESS3 = t14["status-success"];
|
|
12606
|
+
var STATUS_WARNING3 = t14["status-warning"];
|
|
12607
|
+
var STATUS_INFO = t14["status-info"];
|
|
11775
12608
|
var DOT_BORDER = "#F3F4F6";
|
|
11776
12609
|
var BAND_FILL = "rgba(46,213,115,0.1)";
|
|
11777
12610
|
var BAND_EDGE = "rgba(46,213,115,0.45)";
|
|
@@ -11814,13 +12647,13 @@ function interpEdge(pixels, x, key) {
|
|
|
11814
12647
|
const a = pixels[i];
|
|
11815
12648
|
const b = pixels[i + 1];
|
|
11816
12649
|
if (x >= a.x && x <= b.x) {
|
|
11817
|
-
const
|
|
11818
|
-
return a[key] +
|
|
12650
|
+
const t18 = b.x === a.x ? 0 : (x - a.x) / (b.x - a.x);
|
|
12651
|
+
return a[key] + t18 * (b[key] - a[key]);
|
|
11819
12652
|
}
|
|
11820
12653
|
}
|
|
11821
12654
|
return pixels[pixels.length - 1][key];
|
|
11822
12655
|
}
|
|
11823
|
-
function
|
|
12656
|
+
function buildColumns2(pixels, step) {
|
|
11824
12657
|
if (pixels.length < 2) return [];
|
|
11825
12658
|
const start = pixels[0].x;
|
|
11826
12659
|
const end = pixels[pixels.length - 1].x;
|
|
@@ -11932,7 +12765,7 @@ function CapacityBandChart({
|
|
|
11932
12765
|
}
|
|
11933
12766
|
const { toX, toY } = scale;
|
|
11934
12767
|
const bandPixels = toPixels(band, toX, toY);
|
|
11935
|
-
const columns =
|
|
12768
|
+
const columns = buildColumns2(bandPixels, COLUMN_STEP);
|
|
11936
12769
|
const topEdge = buildEdges(bandPixels, "yHigh");
|
|
11937
12770
|
const bottomEdge = buildEdges(bandPixels, "yLow");
|
|
11938
12771
|
const lastBandPoint = band[band.length - 1];
|
|
@@ -12007,8 +12840,8 @@ function CapacityBandChart({
|
|
|
12007
12840
|
testID: "capacity-band-chart-reveal",
|
|
12008
12841
|
children: /* @__PURE__ */ jsxs(View, { style: { width, height, position: "relative" }, children: [
|
|
12009
12842
|
projection && /* @__PURE__ */ jsxs(View, { testID: "capacity-band-chart-projection", children: [
|
|
12010
|
-
renderColumns(
|
|
12011
|
-
renderColumns(
|
|
12843
|
+
renderColumns(buildColumns2(trainingPixels, COLUMN_STEP), PROJECTION_FILL, "capacity-band-chart-projection-fill"),
|
|
12844
|
+
renderColumns(buildColumns2(restPixels, COLUMN_STEP), PROJECTION_FILL, "capacity-band-chart-projection-fill"),
|
|
12012
12845
|
renderEdges(buildEdges(trainingPixels, "yHigh"), STATUS_SUCCESS3, true, "capacity-band-chart-projection-training"),
|
|
12013
12846
|
renderEdges(buildEdges(trainingPixels, "yLow"), STATUS_SUCCESS3, true, "capacity-band-chart-projection-training"),
|
|
12014
12847
|
renderEdges(buildEdges(restPixels, "yHigh"), STATUS_INFO, true, "capacity-band-chart-projection-rest"),
|
|
@@ -12075,72 +12908,546 @@ function CapacityBandChart({
|
|
|
12075
12908
|
return /* @__PURE__ */ jsx(
|
|
12076
12909
|
Text,
|
|
12077
12910
|
{
|
|
12078
|
-
className: "text-text-tertiary",
|
|
12911
|
+
className: "text-text-tertiary",
|
|
12912
|
+
style: {
|
|
12913
|
+
position: "absolute",
|
|
12914
|
+
left: toX(point.date) - 14,
|
|
12915
|
+
top: height - PADDING_BOTTOM + 2,
|
|
12916
|
+
width: 28,
|
|
12917
|
+
textAlign: "center",
|
|
12918
|
+
fontSize: 10,
|
|
12919
|
+
fontFamily: "Inter, sans-serif"
|
|
12920
|
+
},
|
|
12921
|
+
accessibilityElementsHidden: true,
|
|
12922
|
+
importantForAccessibility: "no-hide-descendants",
|
|
12923
|
+
testID: "capacity-band-chart-x-label",
|
|
12924
|
+
children: formatDate2(point.date)
|
|
12925
|
+
},
|
|
12926
|
+
`x-${point.date}`
|
|
12927
|
+
);
|
|
12928
|
+
})
|
|
12929
|
+
]
|
|
12930
|
+
}
|
|
12931
|
+
),
|
|
12932
|
+
workouts.map((workout, i) => {
|
|
12933
|
+
const cx = toX(workout.date);
|
|
12934
|
+
const cy = toY(workout.load);
|
|
12935
|
+
const color = DOT_COLORS[workout.status];
|
|
12936
|
+
const dotStyle = {
|
|
12937
|
+
width: DOT_SIZE,
|
|
12938
|
+
height: DOT_SIZE,
|
|
12939
|
+
borderRadius: DOT_SIZE / 2,
|
|
12940
|
+
backgroundColor: color,
|
|
12941
|
+
borderWidth: 2,
|
|
12942
|
+
borderColor: DOT_BORDER
|
|
12943
|
+
};
|
|
12944
|
+
const label = `Workout on ${formatDate2(workout.date)}, load ${workout.load}, ${STATUS_PHRASES[workout.status]}`;
|
|
12945
|
+
return /* @__PURE__ */ jsx(
|
|
12946
|
+
Animated.View,
|
|
12947
|
+
{
|
|
12948
|
+
style: {
|
|
12949
|
+
position: "absolute",
|
|
12950
|
+
left: cx - DOT_SIZE / 2,
|
|
12951
|
+
top: cy - DOT_SIZE / 2,
|
|
12952
|
+
transform: [{ scale: dotAnims[i] ?? 1 }]
|
|
12953
|
+
},
|
|
12954
|
+
testID: "capacity-band-chart-dot-wrapper",
|
|
12955
|
+
children: onWorkoutPress ? /* @__PURE__ */ jsx(
|
|
12956
|
+
Pressable,
|
|
12957
|
+
{
|
|
12958
|
+
onPress: () => onWorkoutPress(workout),
|
|
12959
|
+
accessibilityRole: "button",
|
|
12960
|
+
accessibilityLabel: label,
|
|
12961
|
+
style: dotStyle,
|
|
12962
|
+
testID: "capacity-band-chart-dot"
|
|
12963
|
+
}
|
|
12964
|
+
) : /* @__PURE__ */ jsx(
|
|
12965
|
+
View,
|
|
12966
|
+
{
|
|
12967
|
+
accessibilityElementsHidden: true,
|
|
12968
|
+
importantForAccessibility: "no-hide-descendants",
|
|
12969
|
+
style: dotStyle,
|
|
12970
|
+
testID: "capacity-band-chart-dot"
|
|
12971
|
+
}
|
|
12972
|
+
)
|
|
12973
|
+
},
|
|
12974
|
+
`dot-${workout.date}-${i}`
|
|
12975
|
+
);
|
|
12976
|
+
})
|
|
12977
|
+
]
|
|
12978
|
+
}
|
|
12979
|
+
);
|
|
12980
|
+
}
|
|
12981
|
+
var t15 = getSemanticColors("dark");
|
|
12982
|
+
function glowShadow(color) {
|
|
12983
|
+
return `0 0 5px 1px ${alpha(color, 0.3)}, 0 0 10px 3px ${alpha(color, 0.12)}`;
|
|
12984
|
+
}
|
|
12985
|
+
var DEFAULT_TRACK_COLOR = primitiveColors.charcoal[200];
|
|
12986
|
+
var DEFAULT_MARKER_COLOR2 = primitiveColors.white;
|
|
12987
|
+
var TICK_COLOR = t15["text-tertiary"];
|
|
12988
|
+
var DEFAULT_TRACK_HEIGHT = 14;
|
|
12989
|
+
var DEFAULT_NEEDLE_OVERHANG = 6;
|
|
12990
|
+
var NEEDLE_WIDTH = 4;
|
|
12991
|
+
function fraction(value, min, max) {
|
|
12992
|
+
if (max <= min) return 0;
|
|
12993
|
+
return Math.max(0, Math.min(1, (value - min) / (max - min)));
|
|
12994
|
+
}
|
|
12995
|
+
function pct(frac) {
|
|
12996
|
+
return `${frac * 100}%`;
|
|
12997
|
+
}
|
|
12998
|
+
function ZoneTrack({
|
|
12999
|
+
zones,
|
|
13000
|
+
max,
|
|
13001
|
+
min = 0,
|
|
13002
|
+
marker = null,
|
|
13003
|
+
ticks,
|
|
13004
|
+
band = null,
|
|
13005
|
+
trackHeight = DEFAULT_TRACK_HEIGHT,
|
|
13006
|
+
needleOverhang = DEFAULT_NEEDLE_OVERHANG,
|
|
13007
|
+
trackColor = DEFAULT_TRACK_COLOR,
|
|
13008
|
+
className,
|
|
13009
|
+
style,
|
|
13010
|
+
accessibilityLabel: accessibilityLabel2,
|
|
13011
|
+
...props
|
|
13012
|
+
}) {
|
|
13013
|
+
const isNeedle = marker?.type === "needle";
|
|
13014
|
+
const markerHeight = isNeedle ? trackHeight + needleOverhang * 2 : trackHeight;
|
|
13015
|
+
const markerFrac = marker != null ? fraction(marker.value, min, max) : 0;
|
|
13016
|
+
const bands = zones.map((zone, i) => {
|
|
13017
|
+
const prev = i === 0 ? min : zones[i - 1].upTo;
|
|
13018
|
+
const start = Math.max(min, Math.min(max, prev));
|
|
13019
|
+
const end = Math.max(min, Math.min(max, zone.upTo));
|
|
13020
|
+
return { color: zone.color, weight: Math.max(0, end - start) };
|
|
13021
|
+
});
|
|
13022
|
+
return /* @__PURE__ */ jsxs(
|
|
13023
|
+
View,
|
|
13024
|
+
{
|
|
13025
|
+
className,
|
|
13026
|
+
style: [{ width: "100%" }, style],
|
|
13027
|
+
accessibilityRole: "progressbar",
|
|
13028
|
+
accessibilityValue: marker != null ? { min, max, now: marker.value } : { min, max, now: min },
|
|
13029
|
+
accessibilityLabel: accessibilityLabel2 ?? `Zone track: ${marker?.value ?? min}`,
|
|
13030
|
+
testID: "zone-track",
|
|
13031
|
+
...props,
|
|
13032
|
+
children: [
|
|
13033
|
+
/* @__PURE__ */ jsxs(View, { style: { position: "relative", height: markerHeight }, children: [
|
|
13034
|
+
/* @__PURE__ */ jsxs(
|
|
13035
|
+
View,
|
|
13036
|
+
{
|
|
13037
|
+
testID: "zone-track-track",
|
|
13038
|
+
accessibilityElementsHidden: true,
|
|
13039
|
+
style: {
|
|
13040
|
+
position: "absolute",
|
|
13041
|
+
top: (markerHeight - trackHeight) / 2,
|
|
13042
|
+
left: 0,
|
|
13043
|
+
right: 0,
|
|
13044
|
+
height: trackHeight,
|
|
13045
|
+
borderRadius: trackHeight / 2,
|
|
13046
|
+
backgroundColor: trackColor,
|
|
13047
|
+
overflow: "hidden",
|
|
13048
|
+
flexDirection: "row",
|
|
13049
|
+
// The pill's own box-shadow renders outside its overflow:hidden, so
|
|
13050
|
+
// `glow` haloes the whole track in the marker colour.
|
|
13051
|
+
...marker?.glow ? { boxShadow: glowShadow(marker.color ?? DEFAULT_MARKER_COLOR2) } : null
|
|
13052
|
+
},
|
|
13053
|
+
children: [
|
|
13054
|
+
bands.map((b, i) => /* @__PURE__ */ jsx(
|
|
13055
|
+
View,
|
|
13056
|
+
{
|
|
13057
|
+
testID: "zone-track-band",
|
|
13058
|
+
style: {
|
|
13059
|
+
flexGrow: b.weight,
|
|
13060
|
+
flexShrink: 1,
|
|
13061
|
+
flexBasis: 0,
|
|
13062
|
+
minWidth: 0,
|
|
13063
|
+
height: "100%",
|
|
13064
|
+
backgroundColor: b.color
|
|
13065
|
+
}
|
|
13066
|
+
},
|
|
13067
|
+
i
|
|
13068
|
+
)),
|
|
13069
|
+
band != null && /* @__PURE__ */ jsx(
|
|
13070
|
+
View,
|
|
13071
|
+
{
|
|
13072
|
+
testID: "zone-track-band-highlight",
|
|
13073
|
+
style: {
|
|
13074
|
+
position: "absolute",
|
|
13075
|
+
top: 0,
|
|
13076
|
+
bottom: 0,
|
|
13077
|
+
left: pct(fraction(band.from, min, max)),
|
|
13078
|
+
width: pct(fraction(band.to, min, max) - fraction(band.from, min, max)),
|
|
13079
|
+
backgroundColor: band.color
|
|
13080
|
+
}
|
|
13081
|
+
}
|
|
13082
|
+
),
|
|
13083
|
+
marker?.type === "fill" && /* @__PURE__ */ jsx(
|
|
13084
|
+
View,
|
|
13085
|
+
{
|
|
13086
|
+
testID: "zone-track-unfilled",
|
|
13087
|
+
style: {
|
|
13088
|
+
position: "absolute",
|
|
13089
|
+
top: 0,
|
|
13090
|
+
bottom: 0,
|
|
13091
|
+
left: pct(markerFrac),
|
|
13092
|
+
right: 0,
|
|
13093
|
+
backgroundColor: trackColor
|
|
13094
|
+
}
|
|
13095
|
+
}
|
|
13096
|
+
),
|
|
13097
|
+
marker?.type === "fill" && marker.color != null && /* @__PURE__ */ jsx(
|
|
13098
|
+
View,
|
|
13099
|
+
{
|
|
13100
|
+
testID: "zone-track-fill",
|
|
12079
13101
|
style: {
|
|
12080
13102
|
position: "absolute",
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12085
|
-
|
|
12086
|
-
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12097
|
-
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
13103
|
+
top: 0,
|
|
13104
|
+
bottom: 0,
|
|
13105
|
+
left: 0,
|
|
13106
|
+
width: pct(markerFrac),
|
|
13107
|
+
backgroundColor: marker.color
|
|
13108
|
+
}
|
|
13109
|
+
}
|
|
13110
|
+
)
|
|
13111
|
+
]
|
|
13112
|
+
}
|
|
13113
|
+
),
|
|
13114
|
+
isNeedle && /* @__PURE__ */ jsx(
|
|
13115
|
+
View,
|
|
13116
|
+
{
|
|
13117
|
+
testID: "zone-track-needle",
|
|
13118
|
+
style: {
|
|
13119
|
+
position: "absolute",
|
|
13120
|
+
top: 0,
|
|
13121
|
+
left: pct(markerFrac),
|
|
13122
|
+
width: NEEDLE_WIDTH,
|
|
13123
|
+
height: markerHeight,
|
|
13124
|
+
borderRadius: NEEDLE_WIDTH / 2,
|
|
13125
|
+
backgroundColor: marker.color ?? DEFAULT_MARKER_COLOR2,
|
|
13126
|
+
transform: [{ translateX: -NEEDLE_WIDTH / 2 }]
|
|
13127
|
+
}
|
|
13128
|
+
}
|
|
13129
|
+
),
|
|
13130
|
+
ticks?.map((tick, i) => {
|
|
13131
|
+
const emphasized = tick.emphasized === true;
|
|
13132
|
+
const lineColor = tick.color ?? (emphasized ? t15["brand-primary"] : TICK_COLOR);
|
|
13133
|
+
const lineWidth = emphasized ? 2 : 1.5;
|
|
13134
|
+
return /* @__PURE__ */ jsx(
|
|
13135
|
+
View,
|
|
13136
|
+
{
|
|
13137
|
+
testID: "zone-track-tick-line",
|
|
13138
|
+
accessibilityElementsHidden: true,
|
|
13139
|
+
style: {
|
|
13140
|
+
position: "absolute",
|
|
13141
|
+
top: (markerHeight - trackHeight) / 2 - 2,
|
|
13142
|
+
left: pct(fraction(tick.value, min, max)),
|
|
13143
|
+
width: lineWidth,
|
|
13144
|
+
height: trackHeight + 4,
|
|
13145
|
+
borderRadius: lineWidth / 2,
|
|
13146
|
+
backgroundColor: lineColor,
|
|
13147
|
+
transform: [{ translateX: -lineWidth / 2 }],
|
|
13148
|
+
zIndex: 3
|
|
13149
|
+
}
|
|
13150
|
+
},
|
|
13151
|
+
`line-${i}`
|
|
13152
|
+
);
|
|
13153
|
+
})
|
|
13154
|
+
] }),
|
|
13155
|
+
ticks != null && ticks.length > 0 && /* @__PURE__ */ jsx(View, { style: { position: "relative", height: 16, marginTop: 5 }, children: ticks.map((tick, i) => {
|
|
13156
|
+
if (tick.label == null) return null;
|
|
13157
|
+
const emphasized = tick.emphasized === true;
|
|
13158
|
+
const labelColor = tick.color ?? (emphasized ? t15["brand-primary"] : TICK_COLOR);
|
|
13159
|
+
const labelNode = /* @__PURE__ */ jsx(
|
|
13160
|
+
Text,
|
|
13161
|
+
{
|
|
13162
|
+
testID: "zone-track-tick-label",
|
|
13163
|
+
style: {
|
|
13164
|
+
fontSize: 9,
|
|
13165
|
+
letterSpacing: 0.5,
|
|
13166
|
+
color: labelColor,
|
|
13167
|
+
fontFamily: "monospace",
|
|
13168
|
+
fontWeight: emphasized ? "700" : "400"
|
|
13169
|
+
},
|
|
13170
|
+
children: tick.label
|
|
13171
|
+
}
|
|
13172
|
+
);
|
|
12112
13173
|
return /* @__PURE__ */ jsx(
|
|
12113
|
-
|
|
13174
|
+
View,
|
|
12114
13175
|
{
|
|
13176
|
+
testID: "zone-track-tick",
|
|
12115
13177
|
style: {
|
|
12116
13178
|
position: "absolute",
|
|
12117
|
-
left:
|
|
12118
|
-
|
|
12119
|
-
|
|
13179
|
+
left: pct(fraction(tick.value, min, max)),
|
|
13180
|
+
transform: [{ translateX: -14 }],
|
|
13181
|
+
width: 28,
|
|
13182
|
+
alignItems: "center"
|
|
12120
13183
|
},
|
|
12121
|
-
|
|
12122
|
-
children: onWorkoutPress ? /* @__PURE__ */ jsx(
|
|
12123
|
-
Pressable,
|
|
12124
|
-
{
|
|
12125
|
-
onPress: () => onWorkoutPress(workout),
|
|
12126
|
-
accessibilityRole: "button",
|
|
12127
|
-
accessibilityLabel: label,
|
|
12128
|
-
style: dotStyle,
|
|
12129
|
-
testID: "capacity-band-chart-dot"
|
|
12130
|
-
}
|
|
12131
|
-
) : /* @__PURE__ */ jsx(
|
|
12132
|
-
View,
|
|
12133
|
-
{
|
|
12134
|
-
accessibilityElementsHidden: true,
|
|
12135
|
-
importantForAccessibility: "no-hide-descendants",
|
|
12136
|
-
style: dotStyle,
|
|
12137
|
-
testID: "capacity-band-chart-dot"
|
|
12138
|
-
}
|
|
12139
|
-
)
|
|
13184
|
+
children: tick.tooltip != null ? /* @__PURE__ */ jsx(Tooltip, { label: tick.tooltip, placement: "top", children: labelNode }) : labelNode
|
|
12140
13185
|
},
|
|
12141
|
-
`
|
|
13186
|
+
`label-${i}`
|
|
12142
13187
|
);
|
|
12143
|
-
})
|
|
13188
|
+
}) })
|
|
13189
|
+
]
|
|
13190
|
+
}
|
|
13191
|
+
);
|
|
13192
|
+
}
|
|
13193
|
+
|
|
13194
|
+
// src/components/custom/Workout/FatigueMeter.tsx
|
|
13195
|
+
var { green, yellow, orange, red } = WORKOUT_TOKENS.scale;
|
|
13196
|
+
var DEFAULT_ZONE_COLORS = [green, yellow, orange, red];
|
|
13197
|
+
var DEFAULT_THRESHOLDS = [10, 20, 30];
|
|
13198
|
+
var DEFAULT_LABELS = ["fresh", "VL10", "VL20", "VL30", "stop"];
|
|
13199
|
+
var DEFAULT_MAX = 40;
|
|
13200
|
+
function FatigueMeter({
|
|
13201
|
+
value,
|
|
13202
|
+
max = DEFAULT_MAX,
|
|
13203
|
+
thresholds = DEFAULT_THRESHOLDS,
|
|
13204
|
+
zoneColors = DEFAULT_ZONE_COLORS,
|
|
13205
|
+
labels = DEFAULT_LABELS,
|
|
13206
|
+
trackHeight = 14,
|
|
13207
|
+
needleColor,
|
|
13208
|
+
className,
|
|
13209
|
+
...props
|
|
13210
|
+
}) {
|
|
13211
|
+
const [t1, t22, t32] = thresholds;
|
|
13212
|
+
const zones = [
|
|
13213
|
+
{ upTo: t1, color: zoneColors[0] },
|
|
13214
|
+
{ upTo: t22, color: zoneColors[1] },
|
|
13215
|
+
{ upTo: t32, color: zoneColors[2] },
|
|
13216
|
+
{ upTo: max, color: zoneColors[3] }
|
|
13217
|
+
];
|
|
13218
|
+
const tickValues = [0, t1, t22, t32, max];
|
|
13219
|
+
const ticks = tickValues.map((v, i) => ({ value: v, label: labels[i] }));
|
|
13220
|
+
return /* @__PURE__ */ jsx(
|
|
13221
|
+
ZoneTrack,
|
|
13222
|
+
{
|
|
13223
|
+
className,
|
|
13224
|
+
zones,
|
|
13225
|
+
min: 0,
|
|
13226
|
+
max,
|
|
13227
|
+
trackHeight,
|
|
13228
|
+
ticks,
|
|
13229
|
+
marker: { type: "needle", value, color: needleColor },
|
|
13230
|
+
accessibilityLabel: `Fatigue: ${value}% velocity loss`,
|
|
13231
|
+
testID: "fatigue-meter",
|
|
13232
|
+
...props
|
|
13233
|
+
}
|
|
13234
|
+
);
|
|
13235
|
+
}
|
|
13236
|
+
var HEAT = WORKOUT_TOKENS.heatmap;
|
|
13237
|
+
var NEUTRAL_TRACK = primitiveColors.charcoal[200];
|
|
13238
|
+
var MONO = "monospace";
|
|
13239
|
+
var HEAT_BY_ZONE = {
|
|
13240
|
+
under: HEAT.under,
|
|
13241
|
+
maintenance: HEAT.maintenance,
|
|
13242
|
+
productive: HEAT.productive,
|
|
13243
|
+
approaching: HEAT.approaching,
|
|
13244
|
+
over: HEAT.over
|
|
13245
|
+
};
|
|
13246
|
+
var ZONE_DESCRIPTION = {
|
|
13247
|
+
under: "below MEV",
|
|
13248
|
+
maintenance: "building toward MAV",
|
|
13249
|
+
productive: "in the productive zone",
|
|
13250
|
+
approaching: "approaching MRV",
|
|
13251
|
+
over: "over MRV"
|
|
13252
|
+
};
|
|
13253
|
+
var LANDMARK_NAME = {
|
|
13254
|
+
MEV: "Minimum Effective Volume",
|
|
13255
|
+
MAV: "Maximum Adaptive Volume",
|
|
13256
|
+
MRV: "Maximum Recoverable Volume"
|
|
13257
|
+
};
|
|
13258
|
+
function zoneForSets(sets, { mev, mav, mrv }) {
|
|
13259
|
+
if (sets < mev) return "under";
|
|
13260
|
+
if (sets < mav) return "maintenance";
|
|
13261
|
+
if (sets >= mrv) return "over";
|
|
13262
|
+
const midpoint = (mav + mrv) / 2;
|
|
13263
|
+
return sets < midpoint ? "productive" : "approaching";
|
|
13264
|
+
}
|
|
13265
|
+
function VolumeLandmarkBar({
|
|
13266
|
+
muscle,
|
|
13267
|
+
currentSets,
|
|
13268
|
+
landmarks,
|
|
13269
|
+
width = 220,
|
|
13270
|
+
trackHeight = 10,
|
|
13271
|
+
scaleMax,
|
|
13272
|
+
className,
|
|
13273
|
+
style,
|
|
13274
|
+
...props
|
|
13275
|
+
}) {
|
|
13276
|
+
const { mev, mav, mrv } = landmarks;
|
|
13277
|
+
const max = scaleMax ?? mrv * 1.2;
|
|
13278
|
+
const zone = zoneForSets(currentSets, landmarks);
|
|
13279
|
+
const fillColor = HEAT_BY_ZONE[zone];
|
|
13280
|
+
const pct2 = mav > 0 ? Math.round(currentSets / mav * 100) : 0;
|
|
13281
|
+
return /* @__PURE__ */ jsxs(
|
|
13282
|
+
View,
|
|
13283
|
+
{
|
|
13284
|
+
className,
|
|
13285
|
+
style: [{ width, gap: 3 }, style],
|
|
13286
|
+
testID: "volume-landmark-bar",
|
|
13287
|
+
...props,
|
|
13288
|
+
children: [
|
|
13289
|
+
/* @__PURE__ */ jsx(
|
|
13290
|
+
DataRow,
|
|
13291
|
+
{
|
|
13292
|
+
label: muscle,
|
|
13293
|
+
value: /* @__PURE__ */ jsxs(
|
|
13294
|
+
Text,
|
|
13295
|
+
{
|
|
13296
|
+
testID: "volume-landmark-pct",
|
|
13297
|
+
style: { fontSize: 14, fontWeight: "700", fontFamily: MONO, color: fillColor },
|
|
13298
|
+
children: [
|
|
13299
|
+
pct2,
|
|
13300
|
+
"%"
|
|
13301
|
+
]
|
|
13302
|
+
}
|
|
13303
|
+
),
|
|
13304
|
+
className: "py-0",
|
|
13305
|
+
testID: "volume-landmark-header"
|
|
13306
|
+
}
|
|
13307
|
+
),
|
|
13308
|
+
/* @__PURE__ */ jsx(
|
|
13309
|
+
ZoneTrack,
|
|
13310
|
+
{
|
|
13311
|
+
zones: [{ upTo: max, color: NEUTRAL_TRACK }],
|
|
13312
|
+
max,
|
|
13313
|
+
marker: {
|
|
13314
|
+
type: "fill",
|
|
13315
|
+
value: currentSets,
|
|
13316
|
+
color: fillColor,
|
|
13317
|
+
// Glow when in the optimal productive band — the "sweet spot" cue.
|
|
13318
|
+
glow: zone === "productive"
|
|
13319
|
+
},
|
|
13320
|
+
trackColor: NEUTRAL_TRACK,
|
|
13321
|
+
trackHeight,
|
|
13322
|
+
ticks: [
|
|
13323
|
+
{ value: mev, label: "MEV", tooltip: `${LANDMARK_NAME.MEV} \xB7 ${mev} sets/wk` },
|
|
13324
|
+
{
|
|
13325
|
+
value: mav,
|
|
13326
|
+
label: "MAV",
|
|
13327
|
+
emphasized: true,
|
|
13328
|
+
tooltip: `${LANDMARK_NAME.MAV} (target) \xB7 ${mav} sets/wk`
|
|
13329
|
+
},
|
|
13330
|
+
{ value: mrv, label: "MRV", tooltip: `${LANDMARK_NAME.MRV} \xB7 ${mrv} sets/wk` }
|
|
13331
|
+
],
|
|
13332
|
+
accessibilityLabel: `${muscle} weekly volume: ${currentSets} sets, ${pct2}% of MAV target, ${ZONE_DESCRIPTION[zone]}`,
|
|
13333
|
+
testID: "volume-landmark-track"
|
|
13334
|
+
}
|
|
13335
|
+
)
|
|
13336
|
+
]
|
|
13337
|
+
}
|
|
13338
|
+
);
|
|
13339
|
+
}
|
|
13340
|
+
var t16 = getSemanticColors("dark");
|
|
13341
|
+
var statusToken = {
|
|
13342
|
+
productive: "status-success",
|
|
13343
|
+
threshold: "status-warning",
|
|
13344
|
+
stop: "status-error"
|
|
13345
|
+
};
|
|
13346
|
+
var statusDotVariant = {
|
|
13347
|
+
productive: "success",
|
|
13348
|
+
threshold: "warning",
|
|
13349
|
+
stop: "error"
|
|
13350
|
+
};
|
|
13351
|
+
var defaultLabel = {
|
|
13352
|
+
productive: "Productive",
|
|
13353
|
+
threshold: "Threshold",
|
|
13354
|
+
stop: "Stop"
|
|
13355
|
+
};
|
|
13356
|
+
function statusPillColor(status) {
|
|
13357
|
+
return t16[statusToken[status]];
|
|
13358
|
+
}
|
|
13359
|
+
function StatusPill2({ status, label, className, style, ...props }) {
|
|
13360
|
+
const color = statusPillColor(status);
|
|
13361
|
+
const text = label ?? defaultLabel[status];
|
|
13362
|
+
return /* @__PURE__ */ jsxs(
|
|
13363
|
+
View,
|
|
13364
|
+
{
|
|
13365
|
+
testID: "status-pill",
|
|
13366
|
+
className,
|
|
13367
|
+
style: [
|
|
13368
|
+
{
|
|
13369
|
+
flexDirection: "row",
|
|
13370
|
+
alignItems: "center",
|
|
13371
|
+
gap: 7,
|
|
13372
|
+
alignSelf: "flex-start",
|
|
13373
|
+
paddingVertical: 7,
|
|
13374
|
+
paddingHorizontal: 13,
|
|
13375
|
+
borderRadius: 9,
|
|
13376
|
+
backgroundColor: alpha(color, 0.14),
|
|
13377
|
+
borderWidth: 1,
|
|
13378
|
+
borderColor: alpha(color, 0.4)
|
|
13379
|
+
},
|
|
13380
|
+
style
|
|
13381
|
+
],
|
|
13382
|
+
...props,
|
|
13383
|
+
children: [
|
|
13384
|
+
/* @__PURE__ */ jsx(View, { accessibilityElementsHidden: true, children: /* @__PURE__ */ jsx(StatusDot, { variant: statusDotVariant[status], glow: true }) }),
|
|
13385
|
+
/* @__PURE__ */ jsx(Text, { testID: "status-pill-label", style: { fontSize: 13, fontWeight: "800", color }, children: text })
|
|
13386
|
+
]
|
|
13387
|
+
}
|
|
13388
|
+
);
|
|
13389
|
+
}
|
|
13390
|
+
var t17 = getSemanticColors("dark");
|
|
13391
|
+
var categoryToken = {
|
|
13392
|
+
productive: null,
|
|
13393
|
+
threshold: "status-warning",
|
|
13394
|
+
stop: "status-error"
|
|
13395
|
+
};
|
|
13396
|
+
var floodOpacity = {
|
|
13397
|
+
productive: 0,
|
|
13398
|
+
threshold: 0.12,
|
|
13399
|
+
stop: 0.18
|
|
13400
|
+
};
|
|
13401
|
+
function liveAuraColor(category) {
|
|
13402
|
+
const token = categoryToken[category];
|
|
13403
|
+
return token ? t17[token] : null;
|
|
13404
|
+
}
|
|
13405
|
+
function LiveAuraFrame({
|
|
13406
|
+
category,
|
|
13407
|
+
pulse = true,
|
|
13408
|
+
className,
|
|
13409
|
+
children,
|
|
13410
|
+
style,
|
|
13411
|
+
...props
|
|
13412
|
+
}) {
|
|
13413
|
+
const color = liveAuraColor(category);
|
|
13414
|
+
const tint = color ? alpha(color, floodOpacity[category]) : "transparent";
|
|
13415
|
+
const floodStyle = {
|
|
13416
|
+
...StyleSheet.absoluteFillObject,
|
|
13417
|
+
...Platform.OS === "web" ? (
|
|
13418
|
+
// backgroundImage is a runtime RNW style, not in RN ViewStyle types.
|
|
13419
|
+
{ backgroundImage: `radial-gradient(130% 95% at 50% 0%, ${tint}, transparent 62%)` }
|
|
13420
|
+
) : { backgroundColor: tint }
|
|
13421
|
+
};
|
|
13422
|
+
return /* @__PURE__ */ jsxs(
|
|
13423
|
+
View,
|
|
13424
|
+
{
|
|
13425
|
+
testID: "live-aura-frame",
|
|
13426
|
+
className,
|
|
13427
|
+
style: [
|
|
13428
|
+
{
|
|
13429
|
+
position: "relative",
|
|
13430
|
+
overflow: "hidden",
|
|
13431
|
+
borderRadius: 10,
|
|
13432
|
+
backgroundColor: t17["background-base"],
|
|
13433
|
+
borderWidth: 1,
|
|
13434
|
+
borderColor: t17["border-default"]
|
|
13435
|
+
},
|
|
13436
|
+
style
|
|
13437
|
+
],
|
|
13438
|
+
...props,
|
|
13439
|
+
children: [
|
|
13440
|
+
color && /* @__PURE__ */ jsx(
|
|
13441
|
+
View,
|
|
13442
|
+
{
|
|
13443
|
+
testID: "live-aura-flood",
|
|
13444
|
+
accessibilityElementsHidden: true,
|
|
13445
|
+
pointerEvents: "none",
|
|
13446
|
+
className: category === "stop" && pulse ? "animate-pulse" : void 0,
|
|
13447
|
+
style: floodStyle
|
|
13448
|
+
}
|
|
13449
|
+
),
|
|
13450
|
+
children
|
|
12144
13451
|
]
|
|
12145
13452
|
}
|
|
12146
13453
|
);
|
|
@@ -12351,28 +13658,28 @@ function Scatter({
|
|
|
12351
13658
|
testID: "scatter-canvas",
|
|
12352
13659
|
style: { position: "absolute", top: 0, left: 0, width, height, overflow: "hidden" },
|
|
12353
13660
|
children: [
|
|
12354
|
-
ticksOf(yd, TICK_COUNT).map((
|
|
12355
|
-
const y = toY(
|
|
13661
|
+
ticksOf(yd, TICK_COUNT).map((t18, i) => {
|
|
13662
|
+
const y = toY(t18);
|
|
12356
13663
|
return /* @__PURE__ */ jsx(
|
|
12357
13664
|
View,
|
|
12358
13665
|
{
|
|
12359
13666
|
accessibilityElementsHidden: true,
|
|
12360
13667
|
testID: "scatter-gridline-y",
|
|
12361
13668
|
style: { position: "absolute", left: PLOT_LEFT2, width: innerW, top: y, height: 1, backgroundColor: GRID_LINE2 },
|
|
12362
|
-
children: /* @__PURE__ */ jsx(Text, { className: "text-[9px] text-text-tertiary", style: { position: "absolute", left: -PLOT_LEFT2, top: -6, width: PLOT_LEFT2 - 6, textAlign: "right" }, children: formatTick(
|
|
13669
|
+
children: /* @__PURE__ */ jsx(Text, { className: "text-[9px] text-text-tertiary", style: { position: "absolute", left: -PLOT_LEFT2, top: -6, width: PLOT_LEFT2 - 6, textAlign: "right" }, children: formatTick(t18) })
|
|
12363
13670
|
},
|
|
12364
13671
|
`y-${i}`
|
|
12365
13672
|
);
|
|
12366
13673
|
}),
|
|
12367
|
-
ticksOf(xd, TICK_COUNT).map((
|
|
12368
|
-
const x = toX(
|
|
13674
|
+
ticksOf(xd, TICK_COUNT).map((t18, i) => {
|
|
13675
|
+
const x = toX(t18);
|
|
12369
13676
|
return /* @__PURE__ */ jsx(
|
|
12370
13677
|
View,
|
|
12371
13678
|
{
|
|
12372
13679
|
accessibilityElementsHidden: true,
|
|
12373
13680
|
testID: "scatter-gridline-x",
|
|
12374
13681
|
style: { position: "absolute", top: PLOT_TOP, height: innerH, left: x, width: 1, backgroundColor: GRID_LINE2 },
|
|
12375
|
-
children: /* @__PURE__ */ jsx(Text, { className: "text-[9px] text-text-tertiary", style: { position: "absolute", top: innerH + 4, left: -16, width: 32, textAlign: "center" }, children: formatTick(
|
|
13682
|
+
children: /* @__PURE__ */ jsx(Text, { className: "text-[9px] text-text-tertiary", style: { position: "absolute", top: innerH + 4, left: -16, width: 32, textAlign: "center" }, children: formatTick(t18) })
|
|
12376
13683
|
},
|
|
12377
13684
|
`x-${i}`
|
|
12378
13685
|
);
|
|
@@ -12437,7 +13744,7 @@ var STATUS_SUCCESS4 = sem2["status-success"];
|
|
|
12437
13744
|
var STATUS_WARNING4 = sem2["status-warning"];
|
|
12438
13745
|
var STATUS_ERROR4 = sem2["status-error"];
|
|
12439
13746
|
var TRACK = "rgba(255,255,255,0.08)";
|
|
12440
|
-
var
|
|
13747
|
+
var DEFAULT_THRESHOLDS2 = [
|
|
12441
13748
|
{ value: 0, color: STATUS_ERROR4 },
|
|
12442
13749
|
{ value: 60, color: STATUS_WARNING4 },
|
|
12443
13750
|
{ value: 80, color: STATUS_SUCCESS4 }
|
|
@@ -12452,8 +13759,8 @@ function clamp012(n) {
|
|
|
12452
13759
|
function formatValue2(v) {
|
|
12453
13760
|
return Number.isInteger(v) ? `${v}` : v.toFixed(1);
|
|
12454
13761
|
}
|
|
12455
|
-
function bandColor2(
|
|
12456
|
-
const value = min +
|
|
13762
|
+
function bandColor2(fraction2, bands, min, max) {
|
|
13763
|
+
const value = min + fraction2 * (max - min);
|
|
12457
13764
|
const sorted = [...bands].sort((a, b) => a.value - b.value);
|
|
12458
13765
|
let color = sorted[0]?.color ?? STATUS_SUCCESS4;
|
|
12459
13766
|
for (const band of sorted) {
|
|
@@ -12465,15 +13772,15 @@ function buildTicks(fill, size, activeColor) {
|
|
|
12465
13772
|
const center = size / 2;
|
|
12466
13773
|
const radius = center - size * 0.08;
|
|
12467
13774
|
return Array.from({ length: SEGMENTS }, (_, i) => {
|
|
12468
|
-
const
|
|
12469
|
-
const deg = ARC_START +
|
|
13775
|
+
const fraction2 = (i + 0.5) / SEGMENTS;
|
|
13776
|
+
const deg = ARC_START + fraction2 * ARC_SWEEP;
|
|
12470
13777
|
const rad = deg * Math.PI / 180;
|
|
12471
13778
|
return {
|
|
12472
13779
|
key: i,
|
|
12473
13780
|
left: center + radius * Math.cos(rad),
|
|
12474
13781
|
top: center + radius * Math.sin(rad),
|
|
12475
13782
|
rotate: `${deg - 90}deg`,
|
|
12476
|
-
color:
|
|
13783
|
+
color: fraction2 <= fill ? activeColor(fraction2) : TRACK
|
|
12477
13784
|
};
|
|
12478
13785
|
});
|
|
12479
13786
|
}
|
|
@@ -12484,7 +13791,7 @@ function Gauge2({
|
|
|
12484
13791
|
size = 160,
|
|
12485
13792
|
label,
|
|
12486
13793
|
unit,
|
|
12487
|
-
thresholds =
|
|
13794
|
+
thresholds = DEFAULT_THRESHOLDS2,
|
|
12488
13795
|
color,
|
|
12489
13796
|
className,
|
|
12490
13797
|
...props
|
|
@@ -12507,23 +13814,23 @@ function Gauge2({
|
|
|
12507
13814
|
testID: "gauge",
|
|
12508
13815
|
...props,
|
|
12509
13816
|
children: [
|
|
12510
|
-
ticks.map((
|
|
13817
|
+
ticks.map((t18) => /* @__PURE__ */ jsx(
|
|
12511
13818
|
View,
|
|
12512
13819
|
{
|
|
12513
13820
|
accessibilityElementsHidden: true,
|
|
12514
13821
|
testID: "gauge-segment",
|
|
12515
13822
|
style: {
|
|
12516
13823
|
position: "absolute",
|
|
12517
|
-
left:
|
|
12518
|
-
top:
|
|
13824
|
+
left: t18.left - tickThickness / 2,
|
|
13825
|
+
top: t18.top - tickLength / 2,
|
|
12519
13826
|
width: tickThickness,
|
|
12520
13827
|
height: tickLength,
|
|
12521
13828
|
borderRadius: tickThickness / 2,
|
|
12522
|
-
backgroundColor:
|
|
12523
|
-
transform: [{ rotate:
|
|
13829
|
+
backgroundColor: t18.color,
|
|
13830
|
+
transform: [{ rotate: t18.rotate }]
|
|
12524
13831
|
}
|
|
12525
13832
|
},
|
|
12526
|
-
|
|
13833
|
+
t18.key
|
|
12527
13834
|
)),
|
|
12528
13835
|
/* @__PURE__ */ jsxs(View, { style: { position: "absolute", top: 0, left: 0, width: size, height: size }, className: "items-center justify-center", children: [
|
|
12529
13836
|
/* @__PURE__ */ jsxs(View, { className: "flex-row items-baseline gap-0.5", children: [
|
|
@@ -12569,7 +13876,7 @@ function BrandLockup({
|
|
|
12569
13876
|
}
|
|
12570
13877
|
var stateConfig = {
|
|
12571
13878
|
// live = vivid green with an expanding ring; rest = solid amber (no pulse — operator); idle is dim.
|
|
12572
|
-
live: { label: "LIVE", color: "
|
|
13879
|
+
live: { label: "LIVE", color: "live", pulse: "ping", textColor: "primary" },
|
|
12573
13880
|
rest: { label: "REST", color: "warning", pulse: false, textColor: "primary" },
|
|
12574
13881
|
idle: { label: "IDLE", color: "default", pulse: false, textColor: "secondary" }
|
|
12575
13882
|
};
|
|
@@ -12733,6 +14040,127 @@ function TopBar({
|
|
|
12733
14040
|
}
|
|
12734
14041
|
);
|
|
12735
14042
|
}
|
|
14043
|
+
function NavItem({
|
|
14044
|
+
icon,
|
|
14045
|
+
label,
|
|
14046
|
+
active = false,
|
|
14047
|
+
live = false,
|
|
14048
|
+
onPress,
|
|
14049
|
+
className
|
|
14050
|
+
}) {
|
|
14051
|
+
const glyphColor = active ? "text-brand-primary" : "text-text-tertiary";
|
|
14052
|
+
const labelColor = active ? "text-brand-primary" : live ? "text-status-live-muted" : "text-text-tertiary";
|
|
14053
|
+
return /* @__PURE__ */ jsxs(
|
|
14054
|
+
Pressable,
|
|
14055
|
+
{
|
|
14056
|
+
accessibilityRole: "tab",
|
|
14057
|
+
accessibilityState: { selected: active },
|
|
14058
|
+
accessibilityLabel: label,
|
|
14059
|
+
onPress,
|
|
14060
|
+
className: cn("relative h-[46px] w-[60px] items-center justify-center", className),
|
|
14061
|
+
children: [
|
|
14062
|
+
active ? /* @__PURE__ */ jsx(
|
|
14063
|
+
View,
|
|
14064
|
+
{
|
|
14065
|
+
testID: "nav-item-accent",
|
|
14066
|
+
className: "absolute left-0 top-[13px] bottom-[13px] w-[3px] rounded-r-[3px] bg-brand-primary"
|
|
14067
|
+
}
|
|
14068
|
+
) : null,
|
|
14069
|
+
/* @__PURE__ */ jsxs(
|
|
14070
|
+
View,
|
|
14071
|
+
{
|
|
14072
|
+
className: cn(
|
|
14073
|
+
"h-[46px] w-[46px] items-center justify-center gap-[3px] rounded-[11px]",
|
|
14074
|
+
glyphColor
|
|
14075
|
+
),
|
|
14076
|
+
children: [
|
|
14077
|
+
icon,
|
|
14078
|
+
/* @__PURE__ */ jsx(
|
|
14079
|
+
Typography,
|
|
14080
|
+
{
|
|
14081
|
+
variant: "button",
|
|
14082
|
+
color: "inherit",
|
|
14083
|
+
className: cn("text-[8.5px] font-bold uppercase tracking-[0.4px]", labelColor),
|
|
14084
|
+
children: label
|
|
14085
|
+
}
|
|
14086
|
+
)
|
|
14087
|
+
]
|
|
14088
|
+
}
|
|
14089
|
+
)
|
|
14090
|
+
]
|
|
14091
|
+
}
|
|
14092
|
+
);
|
|
14093
|
+
}
|
|
14094
|
+
var defaultNavItems = [
|
|
14095
|
+
{ key: "live", label: "Live", icon: /* @__PURE__ */ jsx(ActivityIcon, { size: 20, color: "currentColor" }) },
|
|
14096
|
+
{ key: "review", label: "Review", icon: /* @__PURE__ */ jsx(HistoryIcon, { size: 20, color: "currentColor" }) },
|
|
14097
|
+
{ key: "program", label: "Plan", icon: /* @__PURE__ */ jsx(LayersIcon, { size: 20, color: "currentColor" }) },
|
|
14098
|
+
{ key: "body", label: "Body", icon: /* @__PURE__ */ jsx(PersonStandingIcon, { size: 20, color: "currentColor" }) }
|
|
14099
|
+
];
|
|
14100
|
+
function SideNav({
|
|
14101
|
+
items = defaultNavItems,
|
|
14102
|
+
activeKey,
|
|
14103
|
+
onNavigate,
|
|
14104
|
+
liveKey = null,
|
|
14105
|
+
className
|
|
14106
|
+
}) {
|
|
14107
|
+
return /* @__PURE__ */ jsx(
|
|
14108
|
+
View,
|
|
14109
|
+
{
|
|
14110
|
+
accessibilityRole: "tablist",
|
|
14111
|
+
className: cn(
|
|
14112
|
+
"w-[60px] items-center gap-[6px] border-r border-border bg-background-base py-3",
|
|
14113
|
+
className
|
|
14114
|
+
),
|
|
14115
|
+
children: items.map((item) => /* @__PURE__ */ jsx(
|
|
14116
|
+
NavItem,
|
|
14117
|
+
{
|
|
14118
|
+
icon: item.icon,
|
|
14119
|
+
label: item.label,
|
|
14120
|
+
active: item.key === activeKey,
|
|
14121
|
+
live: item.key === liveKey && item.key !== activeKey,
|
|
14122
|
+
onPress: () => onNavigate?.(item.key)
|
|
14123
|
+
},
|
|
14124
|
+
item.key
|
|
14125
|
+
))
|
|
14126
|
+
}
|
|
14127
|
+
);
|
|
14128
|
+
}
|
|
14129
|
+
var DEMO_DEVICES = [
|
|
14130
|
+
{ id: "Voltra-A3F2", nickname: "Left Cable", slot: "L", state: "connected" },
|
|
14131
|
+
{ id: "Voltra-9B1C", nickname: "Right Cable", slot: "R", state: "connected" }
|
|
14132
|
+
];
|
|
14133
|
+
function ContentPlaceholder() {
|
|
14134
|
+
return /* @__PURE__ */ jsx(View, { className: "flex-1 items-center justify-center", children: /* @__PURE__ */ jsx(Text, { className: "font-heading text-sm text-text-tertiary", children: "main content region" }) });
|
|
14135
|
+
}
|
|
14136
|
+
function DashboardShell({
|
|
14137
|
+
activeKey = "live",
|
|
14138
|
+
navItems,
|
|
14139
|
+
liveKey = null,
|
|
14140
|
+
state = "live",
|
|
14141
|
+
devices = DEMO_DEVICES,
|
|
14142
|
+
subtitle = "wall dashboard",
|
|
14143
|
+
onNavigate,
|
|
14144
|
+
onSelectDevice,
|
|
14145
|
+
children,
|
|
14146
|
+
className
|
|
14147
|
+
}) {
|
|
14148
|
+
return /* @__PURE__ */ jsxs(View, { className: cn("flex-1 flex-row bg-surface-base", className), children: [
|
|
14149
|
+
/* @__PURE__ */ jsx(SideNav, { activeKey, items: navItems, liveKey, onNavigate }),
|
|
14150
|
+
/* @__PURE__ */ jsxs(View, { className: "flex-1", children: [
|
|
14151
|
+
/* @__PURE__ */ jsx(
|
|
14152
|
+
TopBar,
|
|
14153
|
+
{
|
|
14154
|
+
state,
|
|
14155
|
+
devices,
|
|
14156
|
+
subtitle,
|
|
14157
|
+
onSelectDevice
|
|
14158
|
+
}
|
|
14159
|
+
),
|
|
14160
|
+
/* @__PURE__ */ jsx(View, { className: "flex-1", children: children ?? /* @__PURE__ */ jsx(ContentPlaceholder, {}) })
|
|
14161
|
+
] })
|
|
14162
|
+
] });
|
|
14163
|
+
}
|
|
12736
14164
|
|
|
12737
14165
|
// src/utils/form.ts
|
|
12738
14166
|
function getFieldValidationProps(state) {
|
|
@@ -12822,6 +14250,6 @@ function composeValidators(...validators) {
|
|
|
12822
14250
|
};
|
|
12823
14251
|
}
|
|
12824
14252
|
|
|
12825
|
-
export { Accordion, AccordionButton, AccordionItem, AccordionPanel, Alert, AlertDescription, AlertTitle, Autocomplete, Avatar, AvatarBadge, AvatarGroup, Badge, BadgeText, BaseBadge, BluetoothIcon, BrandLockup, BreadcrumbItem, Breadcrumbs, Button, ButtonIcon, ButtonSpinner, ButtonText, CATEGORICAL_CVD_SAFE_MAX, CapacityBandChart, Caption, Card, CardContent, CardDescription, CardFooter, CardHeader, CardSkeleton, CardTitle, Checkbox, CheckboxGroup, Chip, CircularProgress, Collapse, CollapseButton, CollapseContent, DataRow, DateTime, DeviationBar, DeviceIndicator, DeviceMenu, DeviceRow, Divider, Drawer, DrawerBody, DrawerFooter, DrawerHeader, DumbbellIcon, EmptyState, ExerciseCard, FormActions, FormField, FormRow, FormSection, Gauge2 as Gauge, HStack, Heading, HelpTip, IconBox, Indicator, Input, InputBar, InputGroup, IntensityBar, Label, LabelWithHelp, Link, ListItem, ListItemContent, ListItemDivider, ListItemIcon, ListItemTrailing, Menu, MenuDivider, MenuGroup, MenuItem, MenuList, MenuTrigger, MesoCard, MesoProgressBar, MesoStatusCard, Metric, MetricGroup, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalTitle, MuscleGroupChip, Overline, Paragraph, PasswordInput, Pill, PlaceholderStrip, Popover, PopoverCloseButton, PopoverContent, PopoverTrigger, PrBadge, PrHistoryModal, Progress, ProgressSteps, Radio, RadioGroup, ReadinessCheck, RestTimer, Scatter, Section, SectionContent, SectionHeader, Select, SessionStatePill, SetRow, Sidebar, SidebarContent, SidebarDivider, SidebarFooter, SidebarHeader, SidebarItem, SidebarSection, Skeleton, SkeletonCard, SkeletonCircle, SkeletonListItem, SkeletonText, Sparkline, Spinner, Stack, StarIcon, StatusDot, StepContent, StepIndicator, StepLabel, Stepper, Step as StepperStep, StrengthTrendChart, SupersetWrapper, Surface, SvgIcon, Switch, TEMPO_PACING, Tab, TabList, TabPanel, TabPanels, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TablePagination, TableRow, Tabs, TempoBar, TempoDisplay, Toast, ToastProvider, ToolbarButton, ToolbarButtonGroup, Tooltip, TopBar, Treemap, Typography, VStack, VelocityStrip, VoltrasMark, WeekRow, WeightBadge, WorkoutCard, WorkoutPill, alpha, applyThemePreset, audiobookPreset, bestTextColor, buttonSizes, calculateMeanVelocity, calculateVelocityLoss, categoricalPalette, cn, componentElevationRanges, composeValidators, createFieldId, createFlatShadow, createPressedHoverShadow, createPressedShadow, createRaisedHoverShadow, createRaisedShadow, darkThemeCSSVars, darken, defaultPreset, discreteRainbow, divergingScale, elevationSystem, formatDateTime, formatPrescription, formatSignedPct, formatVelocity, getBaseSurfaceColor, getCategoricalColor, getContrastText, getDiscreteRainbowColor, getElevationConfig, getElevationShadow, getElevationSurface, getFieldAriaProps, getFieldValidationProps, getGlowShadow, getHoverColors, getLuminance, getResultColor, getSemanticColors, getStatusColor, getTempoFillPct, getTempoPacingState, getThemeCSSVars, getValidatedElevation, getVelocityZoneColor, getVelocityZoneName, gluestackConfig, hasMaxLength, hasMinLength, hexToRgb, hsvToRgb, isCssPropertyManifest, isDark, isEmpty, isValidEmail, lightThemeCSSVars, lighten, linearGradient, neumorphicShadows, primitiveBorderRadius, primitiveBreakpoints, primitiveColors, primitiveRamps, primitiveShadows, primitiveSpacing, primitiveTypography, primitiveZIndex, resolveColor, rgbToHex, rgbToHsv, roundRpe, roundTempo, roundWeight, rpeColor, semanticColorsDark, semanticColorsLight, semanticTypography, sequentialEffort, shadowColors, surfaceGradient, useTable, useToast, useToolbarButton, validateCssPropertyManifest, validationRules };
|
|
14253
|
+
export { Accordion, AccordionButton, AccordionItem, AccordionPanel, ActivityIcon, Alert, AlertDescription, AlertTitle, AlertTriangleIcon, Autocomplete, Avatar, AvatarBadge, AvatarGroup, AwardIcon, Badge, BadgeText, BaseBadge, BluetoothIcon, BrandLockup, BreadcrumbItem, Breadcrumbs, Button, ButtonIcon, ButtonSpinner, ButtonText, CATEGORICAL_CVD_SAFE_MAX, CapacityBandChart, Caption, Card, CardContent, CardDescription, CardFooter, CardHeader, CardSkeleton, CardTitle, Checkbox, CheckboxGroup, Chip, CircleSlashIcon, CircularProgress, Collapse, CollapseButton, CollapseContent, DashboardShell, DataRow, DateTime, DeviationBar, DeviceIndicator, DeviceMenu, DeviceRow, Divider, Drawer, DrawerBody, DrawerFooter, DrawerHeader, DumbbellIcon, EmptyState, ExerciseCard, ExerciseCardHeading, ExerciseHeading, ExerciseIndicator, FatigueMeter, FormActions, FormField, FormRow, FormSection, Gauge2 as Gauge, HStack, Heading, HelpTip, HistoryIcon, INDICATOR_PRECEDENCE, IconBox, Indicator, InfoIcon, Input, InputBar, InputGroup, IntensityBar, Label, LabelWithHelp, LayersIcon, Link, ListItem, ListItemContent, ListItemDivider, ListItemIcon, ListItemTrailing, LiveAuraFrame, METRIC_FONT, Menu, MenuDivider, MenuGroup, MenuItem, MenuList, MenuTrigger, MesoCard, MesoProgressBar, MesoStatusCard, Metric, MetricCell, MetricGroup, MetricTiles, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalTitle, MuscleGroupChip, NavItem, Overline, Paragraph, PasswordInput, PersonStandingIcon, Pill, PlaceholderStrip, Popover, PopoverCloseButton, PopoverContent, PopoverTrigger, PrBadge, PrHistoryModal, Progress, ProgressSteps, Radio, RadioGroup, ReadinessCheck, RestTimer, SET_STRIP_VARIABLE_COLOR, SET_STRIP_ZONES, ScaleIcon, Scatter, ScheduleTiles, Section, SectionContent, SectionHeader, SegmentedBar, SegmentedProgressBar, Select, SessionHeader, SessionRail, SessionStatePill, SetBar, SetRow, SetStrip, SetTableHeader, SetsRepsLoad, SideNav, Sidebar, SidebarContent, SidebarDivider, SidebarFooter, SidebarHeader, SidebarItem, SidebarSection, Skeleton, SkeletonCard, SkeletonCircle, SkeletonListItem, SkeletonText, Sparkline, Spinner, Stack, StarIcon, StatusDot, StatusPill2 as StatusPill, StepContent, StepIndicator, StepLabel, Stepper, Step as StepperStep, StrengthTrendChart, SupersetWrapper, Surface, SvgIcon, Switch, TEMPO_PACING, Tab, TabList, TabPanel, TabPanels, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TablePagination, TableRow, Tabs, TempoBar, TempoDisplay, Tile, TimerReadout, Toast, ToastProvider, ToolbarButton, ToolbarButtonGroup, Tooltip, TopBar, Treemap, TrendingDownIcon, Typography, VStack, VelocityStrip, VoltrasMark, VolumeLandmarkBar, WeekRow, WeightBadge, WorkoutCard, WorkoutPill, ZoneTrack, alpha, applyThemePreset, audiobookPreset, bestTextColor, buttonSizes, calculateMeanVelocity, calculateVelocityLoss, categoricalPalette, cn, componentElevationRanges, composeValidators, createFieldId, createFlatShadow, createPressedHoverShadow, createPressedShadow, createRaisedHoverShadow, createRaisedShadow, darkThemeCSSVars, darken, defaultNavItems, defaultPreset, discreteRainbow, divergingScale, elevationSystem, formatDateTime, formatDuration, formatPrescription, formatSignedPct, formatVelocity, getBaseSurfaceColor, getCategoricalColor, getContrastText, getDiscreteRainbowColor, getElevationConfig, getElevationShadow, getElevationSurface, getFieldAriaProps, getFieldValidationProps, getGlowShadow, getHoverColors, getLuminance, getResultColor, getSemanticColors, getStatusColor, getTempoFillPct, getTempoPacingState, getThemeCSSVars, getValidatedElevation, getVelocityZoneColor, getVelocityZoneName, gluestackConfig, hasMaxLength, hasMinLength, hexToRgb, hsvToRgb, isCssPropertyManifest, isDark, isEmpty, isValidEmail, lightThemeCSSVars, lighten, linearGradient, liveAuraColor, neumorphicShadows, paceTone, paceToneColor, primitiveBorderRadius, primitiveBreakpoints, primitiveColors, primitiveRamps, primitiveShadows, primitiveSpacing, primitiveTypography, primitiveZIndex, resolveColor, resolveIndicator, rgbToHex, rgbToHsv, roundRpe, roundTempo, roundWeight, rpeColor, semanticColorsDark, semanticColorsLight, semanticTypography, sequentialEffort, shadowColors, statusPillColor, surfaceGradient, useTable, useTimer, useToast, useToolbarButton, validateCssPropertyManifest, validationRules, velocityZoneColor };
|
|
12826
14254
|
//# sourceMappingURL=index.mjs.map
|
|
12827
14255
|
//# sourceMappingURL=index.mjs.map
|