@titan-design/react-ui 0.5.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 +241 -189
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +241 -189
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +1017 -130
- package/dist/index.d.ts +1017 -130
- package/dist/index.js +3058 -1090
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2992 -1091
- 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 +1797 -1292
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +1797 -1292
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +464 -268
- package/dist/theme/index.d.ts +464 -268
- package/dist/theme/index.js +303 -191
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +295 -192
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +160 -143
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +160 -143
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/package.json +3 -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 +83 -7
- package/src/components/custom/DateTime/DateTime.test.tsx +29 -3
- package/src/components/custom/DateTime/DateTime.tsx +55 -15
- package/src/components/custom/EmptyState/EmptyState.stories.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.stories.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.test.tsx +2 -2
- package/src/components/custom/Gauge/Gauge.tsx +6 -3
- package/src/components/custom/Metric/Metric.stories.tsx +1 -1
- package/src/components/custom/Scatter/Scatter.stories.tsx +1 -1
- package/src/components/custom/Scatter/Scatter.tsx +3 -5
- 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/Treemap/Treemap.tsx +3 -5
- package/src/components/custom/Typography/Typography.stories.tsx +46 -28
- package/src/components/custom/Typography/Typography.test.tsx +13 -3
- package/src/components/custom/Typography/Typography.tsx +5 -0
- 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 +11 -16
- 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/BodyMap.tsx +6 -3
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +1 -1
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +6 -3
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +1 -1
- package/src/components/custom/Workout/CapacityBandChart.test.tsx +2 -2
- package/src/components/custom/Workout/CapacityBandChart.tsx +9 -6
- package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.test.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.tsx +7 -4
- 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 +6 -6
- 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/InputBar.tsx +2 -1
- package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
- package/src/components/custom/Workout/IntensityBar.test.tsx +8 -8
- package/src/components/custom/Workout/IntensityBar.tsx +10 -6
- 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/MesoCard.tsx +8 -3
- package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoProgressBar.test.tsx +1 -1
- package/src/components/custom/Workout/MesoProgressBar.tsx +3 -2
- package/src/components/custom/Workout/MesoStatusCard.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoStatusCard.tsx +20 -13
- 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/MuscleGroupChip.tsx +7 -4
- 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/PrBadge.tsx +5 -2
- package/src/components/custom/Workout/PrHistoryModal.stories.tsx +1 -1
- package/src/components/custom/Workout/PrHistoryModal.tsx +4 -3
- package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +4 -16
- package/src/components/custom/Workout/ProgramPlanningPage.tsx +10 -7
- package/src/components/custom/Workout/README.md +146 -4
- package/src/components/custom/Workout/ReadinessCheck.stories.tsx +1 -1
- package/src/components/custom/Workout/ReadinessCheck.tsx +7 -4
- package/src/components/custom/Workout/RestTimer.stories.tsx +1 -1
- package/src/components/custom/Workout/RestTimer.tsx +17 -11
- 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 +170 -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/Sparkline.tsx +2 -1
- package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusDot.test.tsx +2 -2
- package/src/components/custom/Workout/StatusDot.tsx +12 -9
- 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/StrengthTrendChart.tsx +9 -6
- package/src/components/custom/Workout/SupersetWrapper.stories.tsx +1 -1
- package/src/components/custom/Workout/SupersetWrapper.tsx +2 -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 +29 -36
- 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 +379 -144
- 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/WeekRow.tsx +3 -2
- package/src/components/custom/Workout/WeightBadge.stories.tsx +1 -1
- package/src/components/custom/Workout/WeightBadge.tsx +6 -2
- 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/WorkoutCard.tsx +5 -2
- package/src/components/custom/Workout/WorkoutPill.stories.tsx +1 -1
- package/src/components/custom/Workout/WorkoutPill.tsx +12 -8
- 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/icons.tsx +6 -67
- 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/SvgIcon.tsx +50 -0
- package/src/components/icons/icons.stories.tsx +122 -0
- package/src/components/icons/icons.test.tsx +73 -0
- package/src/components/icons/icons.tsx +153 -0
- package/src/components/icons/index.ts +4 -0
- package/src/components/index.ts +6 -0
- package/src/components/shell/BrandLockup.stories.tsx +27 -0
- package/src/components/shell/BrandLockup.test.tsx +23 -0
- package/src/components/shell/BrandLockup.tsx +47 -0
- 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 +28 -0
- package/src/components/shell/DeviceIndicator.test.tsx +26 -0
- package/src/components/shell/DeviceIndicator.tsx +52 -0
- package/src/components/shell/DeviceMenu.stories.tsx +47 -0
- package/src/components/shell/DeviceMenu.test.tsx +40 -0
- package/src/components/shell/DeviceMenu.tsx +65 -0
- package/src/components/shell/DeviceRow.stories.tsx +38 -0
- package/src/components/shell/DeviceRow.test.tsx +37 -0
- package/src/components/shell/DeviceRow.tsx +58 -0
- 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 +116 -0
- package/src/components/shell/SessionRailSpecimen.stories.tsx +753 -0
- package/src/components/shell/SessionStatePill.stories.tsx +27 -0
- package/src/components/shell/SessionStatePill.test.tsx +25 -0
- package/src/components/shell/SessionStatePill.tsx +46 -0
- 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 +49 -0
- package/src/components/shell/TopBar.test.tsx +36 -0
- package/src/components/shell/TopBar.tsx +89 -0
- package/src/components/shell/index.ts +13 -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 +38 -2
- package/src/components/ui/indicator/Indicator.test.tsx +20 -1
- package/src/components/ui/indicator/Indicator.tsx +50 -6
- package/src/components/ui/indicator/index.ts +1 -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/spinner/Spinner.tsx +3 -2
- 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/toolbar-button/ToolbarButton.tsx +2 -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 +323 -0
- package/src/theme/Colors.stories.tsx +74 -9
- package/src/theme/barrel.ts +1 -0
- package/src/theme/config.ts +20 -3
- package/src/theme/elevation.stories.tsx +1 -1
- package/src/theme/extracted-colors-dataviz.ts +21 -0
- package/src/theme/extracted-colors-ui.ts +20 -0
- package/src/theme/global.css +69 -53
- package/src/theme/gradients.test.ts +25 -0
- package/src/theme/gradients.ts +36 -0
- package/src/theme/shadows.stories.tsx +1 -1
- package/src/theme/tokens/primitives.test.ts +232 -0
- package/src/theme/tokens/primitives.ts +238 -87
- package/src/theme/tokens/semantic.ts +101 -81
- package/src/theme/workout-tokens.ts +26 -21
- package/src/utils/avatar-color.ts +3 -3
- package/tailwind.config.js +15 -3
|
@@ -1,259 +1,197 @@
|
|
|
1
1
|
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
|
+
import { type ReactNode } from 'react'
|
|
2
3
|
import { View, Text } from 'react-native'
|
|
3
4
|
import { VelocityStrip, type VelocityZoneBandProp } from './VelocityStrip'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { roundWeight, roundRpe } from '../../../utils/workout-format'
|
|
6
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
7
|
+
import { WORKOUT_TOKENS } from '../../../theme/workout-tokens'
|
|
6
8
|
|
|
7
|
-
export type
|
|
9
|
+
export type SetRowUnit = 'lbs' | 'kg'
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
/** A set's lifecycle: logged (`done`), being performed now (`live`), or planned (`todo`). */
|
|
12
|
+
export type SetRowState = 'done' | 'live' | 'todo'
|
|
13
|
+
|
|
14
|
+
interface SetRowBase {
|
|
11
15
|
setNumber: number
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
rpe?: number | null
|
|
16
|
-
unit: 'lbs' | 'kg'
|
|
17
|
-
/** Per-rep MEAN concentric velocities (m/s). */
|
|
18
|
-
velocities?: number[]
|
|
16
|
+
unit: SetRowUnit
|
|
17
|
+
/** Optional set-type marker (e.g. "DROP", "AMRAP") shown in the SET cell. */
|
|
18
|
+
setType?: string
|
|
19
19
|
/** Optional velocity-zone bands (WA `VelocityZones.bands`); default scale when absent. */
|
|
20
20
|
velocityZones?: readonly VelocityZoneBandProp[]
|
|
21
|
-
/** Live mode: index of the newest rep bar to animate (pop / new-peak bounce). */
|
|
22
|
-
velocityLiveRepIndex?: number
|
|
23
|
-
velocityExpanded?: boolean
|
|
24
|
-
onVelocityToggle?: () => void
|
|
25
|
-
setType?: string
|
|
26
|
-
prBadges?: Array<{ type: PRType; label: string }>
|
|
27
|
-
isNextSet?: boolean
|
|
28
|
-
targets?: { reps: number; weight: number }
|
|
29
21
|
}
|
|
30
22
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
23
|
+
/**
|
|
24
|
+
* One row of the unified expanded exercise table (SET · REPS · LBS · RPE + a
|
|
25
|
+
* per-row velocity strip), as a lifecycle discriminated union:
|
|
26
|
+
* - `done` — a logged set: recorded reps / weight / rpe, a flat `mini` strip.
|
|
27
|
+
* - `live` — performed right now: shows its TARGET (never "reps-done/target"),
|
|
28
|
+
* stands out by brightness, and a compact velocity-HEIGHT spotlight strip.
|
|
29
|
+
* - `todo` — planned: shows its target, muted, a flat grey `mini` stub strip.
|
|
30
|
+
*
|
|
31
|
+
* `done` + `todo` share ONE muted treatment; only `live` is brightened. There is
|
|
32
|
+
* no PREV column (dropped in the unified design).
|
|
33
|
+
*/
|
|
34
|
+
export type SetRowProps =
|
|
35
|
+
| (SetRowBase & {
|
|
36
|
+
state: 'done'
|
|
37
|
+
reps: number
|
|
38
|
+
weight: number
|
|
39
|
+
rpe?: number | null
|
|
40
|
+
/** Per-rep MEAN concentric velocities (m/s). */
|
|
41
|
+
velocities: number[]
|
|
42
|
+
})
|
|
43
|
+
| (SetRowBase & {
|
|
44
|
+
state: 'live'
|
|
45
|
+
/** The prescribed target shown in the REPS / LBS cells (no live "5/10"). */
|
|
46
|
+
target: { reps: number; weight: number }
|
|
47
|
+
/** Reps / weight committed so far (available to hosts; the display shows `target`). */
|
|
48
|
+
reps: number
|
|
49
|
+
weight: number
|
|
50
|
+
rpe?: number | null
|
|
51
|
+
/** Per-rep MEAN concentric velocities logged so far this set. */
|
|
52
|
+
velocities: number[]
|
|
53
|
+
/** Newest rep index — reserved; the compact spotlight strip is static. */
|
|
54
|
+
liveRepIndex?: number
|
|
55
|
+
})
|
|
56
|
+
| (SetRowBase & {
|
|
57
|
+
state: 'todo'
|
|
58
|
+
/** The prescribed target shown in the REPS / LBS cells. */
|
|
59
|
+
target: { reps: number; weight: number }
|
|
60
|
+
/** Planned rep count backing the grey stub strip. Default `target.reps`. */
|
|
61
|
+
planned?: number
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const DARK = getSemanticColors('dark')
|
|
65
|
+
/** Live set — brightest (neutral 100). Done + upcoming share the muted neutral 400. */
|
|
66
|
+
const TEXT_ACTIVE = DARK['text-primary']
|
|
67
|
+
const TEXT_MUTED = DARK['text-secondary']
|
|
68
|
+
|
|
69
|
+
/** Column widths mirror SetTableHeader(showPrevious=false) so cells align under it. */
|
|
70
|
+
const COL = { set: 36, reps: 44, load: 56, rpe: 36 } as const
|
|
71
|
+
const cellText = { fontFamily: 'Inter, sans-serif', fontSize: 13, fontWeight: '600' as const }
|
|
72
|
+
const typeBadge = {
|
|
73
|
+
fontSize: 10,
|
|
74
|
+
fontWeight: '700' as const,
|
|
75
|
+
fontFamily: 'Inter, sans-serif',
|
|
76
|
+
color: WORKOUT_TOKENS.scale.orange,
|
|
77
|
+
backgroundColor: 'rgba(255,165,2,0.12)',
|
|
78
|
+
paddingVertical: 1,
|
|
79
|
+
paddingHorizontal: 5,
|
|
80
|
+
borderRadius: 3,
|
|
81
|
+
overflow: 'hidden' as const,
|
|
40
82
|
}
|
|
41
83
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
reps,
|
|
47
|
-
weight,
|
|
48
|
-
rpe,
|
|
49
|
-
unit,
|
|
50
|
-
velocities,
|
|
51
|
-
velocityZones,
|
|
52
|
-
velocityLiveRepIndex,
|
|
53
|
-
velocityExpanded,
|
|
54
|
-
onVelocityToggle,
|
|
55
|
-
setType,
|
|
56
|
-
prBadges,
|
|
57
|
-
isNextSet,
|
|
58
|
-
targets,
|
|
59
|
-
}: SetRowProps) {
|
|
60
|
-
const isActive = mode === 'active'
|
|
61
|
-
const isCompleted = mode === 'completed'
|
|
84
|
+
/** Reps to show: recorded for a `done` set, else the prescribed target. */
|
|
85
|
+
function displayReps(set: SetRowProps): number {
|
|
86
|
+
return set.state === 'done' ? set.reps : set.target.reps
|
|
87
|
+
}
|
|
62
88
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
padding: 7,
|
|
67
|
-
paddingHorizontal: 8,
|
|
68
|
-
gap: 8,
|
|
69
|
-
borderRadius: 8,
|
|
70
|
-
}
|
|
89
|
+
function displayWeight(set: SetRowProps): number {
|
|
90
|
+
return set.state === 'done' ? set.weight : set.target.weight
|
|
91
|
+
}
|
|
71
92
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
/** Planned rep count backing the row's strip. */
|
|
94
|
+
function plannedReps(set: SetRowProps): number {
|
|
95
|
+
if (set.state === 'done') return set.velocities.length
|
|
96
|
+
if (set.state === 'live') return set.target.reps
|
|
97
|
+
return set.planned ?? set.target.reps
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function accessibilityLabel(set: SetRowProps): string {
|
|
101
|
+
const base = `Set ${set.setNumber}: ${displayReps(set)} reps at ${roundWeight(displayWeight(set))} ${set.unit}`
|
|
102
|
+
if (set.state === 'live') return `${base}, in progress`
|
|
103
|
+
if (set.state === 'todo') return `${base}, upcoming`
|
|
104
|
+
return base
|
|
105
|
+
}
|
|
77
106
|
|
|
78
|
-
|
|
79
|
-
|
|
107
|
+
function Cell({
|
|
108
|
+
width,
|
|
109
|
+
children,
|
|
110
|
+
testID,
|
|
111
|
+
}: {
|
|
112
|
+
width: number
|
|
113
|
+
children: ReactNode
|
|
114
|
+
testID?: string
|
|
115
|
+
}) {
|
|
116
|
+
return (
|
|
117
|
+
<View style={{ width, alignItems: 'center', justifyContent: 'center' }} testID={testID}>
|
|
118
|
+
{children}
|
|
119
|
+
</View>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** The per-row velocity strip: compact spotlight for the live set, flat mini otherwise. */
|
|
124
|
+
function RowStrip({ set }: { set: SetRowProps }) {
|
|
125
|
+
const zones = set.velocityZones
|
|
126
|
+
if (set.state === 'live') {
|
|
127
|
+
// The active-set spotlight: the bare velocity-height `expanded` chart at 24px,
|
|
128
|
+
// fixed scale, no labels / info (both chrome flags off → the bare strip).
|
|
129
|
+
return (
|
|
130
|
+
<VelocityStrip
|
|
131
|
+
variant="expanded"
|
|
132
|
+
showNumbers={false}
|
|
133
|
+
showInfo={false}
|
|
134
|
+
height={24}
|
|
135
|
+
scale="fixed"
|
|
136
|
+
set={{ type: 'straight', velocities: set.velocities, planned: set.target.reps }}
|
|
137
|
+
zones={zones}
|
|
138
|
+
/>
|
|
139
|
+
)
|
|
80
140
|
}
|
|
141
|
+
const velocities = set.state === 'done' ? set.velocities : []
|
|
142
|
+
return (
|
|
143
|
+
<VelocityStrip
|
|
144
|
+
variant="mini"
|
|
145
|
+
set={{ type: 'straight', velocities, planned: plannedReps(set) }}
|
|
146
|
+
zones={zones}
|
|
147
|
+
/>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* ONE set row of the unified expanded exercise table. SET · REPS · LBS · RPE over
|
|
153
|
+
* a per-row {@link VelocityStrip}; `live` stands out by brightness with a compact
|
|
154
|
+
* velocity-height spotlight, `done`/`todo` are muted with a flat mini strip. Its
|
|
155
|
+
* column widths mirror {@link SetTableHeader}(`showPrevious={false}`).
|
|
156
|
+
*/
|
|
157
|
+
export function SetRow(set: SetRowProps) {
|
|
158
|
+
const live = set.state === 'live'
|
|
159
|
+
const valueColor = live ? TEXT_ACTIVE : TEXT_MUTED
|
|
160
|
+
const rpe = set.state === 'todo' ? null : set.rpe
|
|
81
161
|
|
|
82
162
|
return (
|
|
83
163
|
<View
|
|
84
|
-
style={
|
|
85
|
-
accessibilityLabel={
|
|
86
|
-
setNumber,
|
|
87
|
-
reps,
|
|
88
|
-
weight,
|
|
89
|
-
unit,
|
|
90
|
-
)}
|
|
164
|
+
style={{ paddingVertical: 6, paddingHorizontal: 8 }}
|
|
165
|
+
accessibilityLabel={accessibilityLabel(set)}
|
|
91
166
|
testID="set-row"
|
|
92
167
|
>
|
|
93
|
-
<View
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
168
|
+
<View className="flex-row items-center" style={{ justifyContent: 'space-between' }}>
|
|
169
|
+
<Cell width={COL.set} testID="set-row-set-number">
|
|
170
|
+
{set.setType ? (
|
|
171
|
+
<Text style={typeBadge} testID="set-row-type-badge">
|
|
172
|
+
{set.setType}
|
|
173
|
+
</Text>
|
|
174
|
+
) : (
|
|
175
|
+
<Text style={{ ...cellText, color: valueColor, fontWeight: live ? '700' : '600' }}>
|
|
176
|
+
{set.setNumber}
|
|
177
|
+
</Text>
|
|
178
|
+
)}
|
|
179
|
+
</Cell>
|
|
180
|
+
<Cell width={COL.reps} testID="set-row-reps">
|
|
181
|
+
<Text style={{ ...cellText, color: valueColor }}>{displayReps(set)}</Text>
|
|
182
|
+
</Cell>
|
|
183
|
+
<Cell width={COL.load} testID="set-row-weight">
|
|
184
|
+
<Text style={{ ...cellText, color: valueColor }}>{roundWeight(displayWeight(set))}</Text>
|
|
185
|
+
</Cell>
|
|
186
|
+
<Cell width={COL.rpe} testID="set-row-rpe">
|
|
187
|
+
<Text style={{ ...cellText, color: TEXT_MUTED }}>
|
|
188
|
+
{rpe != null ? roundRpe(rpe) : '—'}
|
|
113
189
|
</Text>
|
|
114
|
-
|
|
115
|
-
<Text
|
|
116
|
-
className="text-text-secondary"
|
|
117
|
-
style={{
|
|
118
|
-
fontSize: 13,
|
|
119
|
-
fontWeight: '600',
|
|
120
|
-
fontFamily: 'Inter, sans-serif',
|
|
121
|
-
}}
|
|
122
|
-
>
|
|
123
|
-
{setNumber}
|
|
124
|
-
</Text>
|
|
125
|
-
)}
|
|
190
|
+
</Cell>
|
|
126
191
|
</View>
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
className="flex-1"
|
|
130
|
-
testID="set-row-previous"
|
|
131
|
-
>
|
|
132
|
-
<Text
|
|
133
|
-
className="text-text-secondary"
|
|
134
|
-
style={{
|
|
135
|
-
fontSize: 12,
|
|
136
|
-
fontFamily: 'Inter, sans-serif',
|
|
137
|
-
}}
|
|
138
|
-
>
|
|
139
|
-
{previous
|
|
140
|
-
? `${previous.reps} x ${roundWeight(previous.weight)}`
|
|
141
|
-
: '\u2014'}
|
|
142
|
-
</Text>
|
|
143
|
-
</View>
|
|
144
|
-
|
|
145
|
-
<View
|
|
146
|
-
style={{ width: 44, alignItems: 'center', justifyContent: 'center' }}
|
|
147
|
-
testID="set-row-reps"
|
|
148
|
-
>
|
|
149
|
-
{isActive && reps == null && targets ? (
|
|
150
|
-
<Text
|
|
151
|
-
className="text-text-tertiary"
|
|
152
|
-
style={{
|
|
153
|
-
fontSize: 13,
|
|
154
|
-
fontStyle: 'italic',
|
|
155
|
-
fontFamily: 'Inter, sans-serif',
|
|
156
|
-
}}
|
|
157
|
-
testID="set-row-target-reps"
|
|
158
|
-
>
|
|
159
|
-
{targets.reps}
|
|
160
|
-
</Text>
|
|
161
|
-
) : (
|
|
162
|
-
<Text
|
|
163
|
-
className={reps != null ? 'text-text-primary' : 'text-text-tertiary'}
|
|
164
|
-
style={{
|
|
165
|
-
fontSize: 14,
|
|
166
|
-
fontWeight: '600',
|
|
167
|
-
fontFamily: 'Inter, sans-serif',
|
|
168
|
-
}}
|
|
169
|
-
>
|
|
170
|
-
{reps != null ? reps : '\u2014'}
|
|
171
|
-
</Text>
|
|
172
|
-
)}
|
|
192
|
+
<View style={{ marginTop: live ? 6 : 4 }} testID="set-row-strip">
|
|
193
|
+
<RowStrip set={set} />
|
|
173
194
|
</View>
|
|
174
|
-
|
|
175
|
-
<View
|
|
176
|
-
style={{ width: 56, alignItems: 'center', justifyContent: 'center' }}
|
|
177
|
-
testID="set-row-weight"
|
|
178
|
-
>
|
|
179
|
-
{isActive && weight == null && targets ? (
|
|
180
|
-
<Text
|
|
181
|
-
className="text-text-tertiary"
|
|
182
|
-
style={{
|
|
183
|
-
fontSize: 13,
|
|
184
|
-
fontStyle: 'italic',
|
|
185
|
-
fontFamily: 'Inter, sans-serif',
|
|
186
|
-
}}
|
|
187
|
-
testID="set-row-target-weight"
|
|
188
|
-
>
|
|
189
|
-
{roundWeight(targets.weight)}
|
|
190
|
-
</Text>
|
|
191
|
-
) : (
|
|
192
|
-
<Text
|
|
193
|
-
className={weight != null ? 'text-text-primary' : 'text-text-tertiary'}
|
|
194
|
-
style={{
|
|
195
|
-
fontSize: 14,
|
|
196
|
-
fontWeight: '600',
|
|
197
|
-
fontFamily: 'Inter, sans-serif',
|
|
198
|
-
}}
|
|
199
|
-
>
|
|
200
|
-
{weight != null ? roundWeight(weight) : '\u2014'}
|
|
201
|
-
</Text>
|
|
202
|
-
)}
|
|
203
|
-
</View>
|
|
204
|
-
|
|
205
|
-
<View
|
|
206
|
-
style={{ width: 36, alignItems: 'center', justifyContent: 'center' }}
|
|
207
|
-
testID="set-row-rpe"
|
|
208
|
-
>
|
|
209
|
-
<Text
|
|
210
|
-
className={rpe != null ? undefined : 'text-text-tertiary'}
|
|
211
|
-
style={{
|
|
212
|
-
fontSize: 13,
|
|
213
|
-
fontWeight: '600',
|
|
214
|
-
fontFamily: 'Inter, sans-serif',
|
|
215
|
-
// rpeColor returns a concrete hex (native-safe); only the tertiary
|
|
216
|
-
// fallback needs the className token.
|
|
217
|
-
color: rpe != null ? rpeColor(rpe) : undefined,
|
|
218
|
-
}}
|
|
219
|
-
>
|
|
220
|
-
{rpe != null ? roundRpe(rpe) : '\u2014'}
|
|
221
|
-
</Text>
|
|
222
|
-
</View>
|
|
223
|
-
|
|
224
|
-
{prBadges && prBadges.length > 0 && (
|
|
225
|
-
<View
|
|
226
|
-
className="flex-row items-center"
|
|
227
|
-
style={{ gap: 4 }}
|
|
228
|
-
testID="set-row-pr-badges"
|
|
229
|
-
>
|
|
230
|
-
{prBadges.map((badge, i) => (
|
|
231
|
-
<PrBadge
|
|
232
|
-
key={i}
|
|
233
|
-
type={badge.type}
|
|
234
|
-
label={badge.label}
|
|
235
|
-
animate={false}
|
|
236
|
-
compact
|
|
237
|
-
/>
|
|
238
|
-
))}
|
|
239
|
-
</View>
|
|
240
|
-
)}
|
|
241
|
-
|
|
242
|
-
{velocities && velocities.length > 0 && (
|
|
243
|
-
<View
|
|
244
|
-
style={{ position: 'absolute', bottom: 0, left: 8, right: 8 }}
|
|
245
|
-
testID="set-row-velocity-strip"
|
|
246
|
-
>
|
|
247
|
-
<VelocityStrip
|
|
248
|
-
velocities={velocities}
|
|
249
|
-
zones={velocityZones}
|
|
250
|
-
liveRepIndex={velocityLiveRepIndex}
|
|
251
|
-
expanded={velocityExpanded}
|
|
252
|
-
onToggle={onVelocityToggle}
|
|
253
|
-
variant={onVelocityToggle ? 'full' : 'mini'}
|
|
254
|
-
/>
|
|
255
|
-
</View>
|
|
256
|
-
)}
|
|
257
195
|
</View>
|
|
258
196
|
)
|
|
259
197
|
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { View, Text } from 'react-native'
|
|
3
|
+
import { SetStrip, type SetStripSet } from './SetStrip'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `SetStrip` — the per-set segmented performance strip. One continuous bar per
|
|
7
|
+
* set (rep intensities as butted color segments, no rep gaps); sets separated by
|
|
8
|
+
* a fixed gap. Colors are the real titan ramp pins (red-600 · orange-400 ·
|
|
9
|
+
* amber-300 · green-300).
|
|
10
|
+
*/
|
|
11
|
+
const meta: Meta<typeof SetStrip> = {
|
|
12
|
+
title: 'Workout/SetStrip',
|
|
13
|
+
component: SetStrip,
|
|
14
|
+
tags: ['autodocs'],
|
|
15
|
+
parameters: {
|
|
16
|
+
docs: {
|
|
17
|
+
description: {
|
|
18
|
+
component:
|
|
19
|
+
'**Molecule.** The per-set segmented performance strip — one bar per set, rep ' +
|
|
20
|
+
'intensities as butted ramp-pin segments (no rep gaps), active set pulses. Composes ' +
|
|
21
|
+
'[SetBar](?path=/docs/workout-setbar--docs) × N. ' +
|
|
22
|
+
'Used-by ↑ [ExerciseCardHeading](?path=/docs/workout-exercisecardheading--docs).',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
argTypes: {
|
|
27
|
+
height: { control: { type: 'range', min: 2, max: 16, step: 1 } },
|
|
28
|
+
},
|
|
29
|
+
decorators: [
|
|
30
|
+
(Story) => (
|
|
31
|
+
<View style={{ width: 210, padding: 16, backgroundColor: '#131313' }}>
|
|
32
|
+
<Story />
|
|
33
|
+
</View>
|
|
34
|
+
),
|
|
35
|
+
],
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default meta
|
|
39
|
+
type Story = StoryObj<typeof SetStrip>
|
|
40
|
+
|
|
41
|
+
const decay = (n: number, start: number, span = 0.4): number[] =>
|
|
42
|
+
Array.from({ length: n }, (_, r) => +(start - (span * r) / Math.max(1, n - 1)).toFixed(3))
|
|
43
|
+
|
|
44
|
+
export const Completed: Story = {
|
|
45
|
+
args: {
|
|
46
|
+
height: 8,
|
|
47
|
+
sets: [1.0, 0.9, 0.8, 0.7, 0.6].map(
|
|
48
|
+
(s): SetStripSet => ({ status: 'done', velocities: decay(8, s) })
|
|
49
|
+
),
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const InProgress: Story = {
|
|
54
|
+
args: {
|
|
55
|
+
height: 8,
|
|
56
|
+
sets: [
|
|
57
|
+
{ status: 'done', velocities: decay(10, 0.72) },
|
|
58
|
+
{ status: 'active', velocities: decay(5, 0.62), planned: 10 },
|
|
59
|
+
{ status: 'todo', planned: 10 },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
parameters: {
|
|
63
|
+
docs: { description: { story: 'Active set: performed reps pulse; the remainder is greyed.' } },
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const Upcoming: Story = {
|
|
68
|
+
args: {
|
|
69
|
+
height: 8,
|
|
70
|
+
sets: [1, 2, 3, 4, 5].map((): SetStripSet => ({ status: 'todo', planned: 20 })),
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const ShortStrip: Story = {
|
|
75
|
+
args: { ...Completed.args, height: 4 },
|
|
76
|
+
parameters: {
|
|
77
|
+
docs: { description: { story: 'The 4px height alternative (default is 8px).' } },
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ---- set-type variant sheet: every variant at the real rail width, for eyeballing
|
|
82
|
+
function SheetRow({ label, meta, sets }: { label: string; meta: string; sets: SetStripSet[] }) {
|
|
83
|
+
return (
|
|
84
|
+
<View style={{ gap: 6 }}>
|
|
85
|
+
<View style={{ flexDirection: 'row', alignItems: 'baseline', gap: 8 }}>
|
|
86
|
+
<Text style={{ color: '#F3F4F6', fontSize: 13, fontWeight: '800' }}>{label}</Text>
|
|
87
|
+
<Text style={{ color: '#6B7280', fontSize: 10, fontFamily: 'monospace' }}>{meta}</Text>
|
|
88
|
+
</View>
|
|
89
|
+
<SetStrip sets={sets} />
|
|
90
|
+
</View>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Every set-type variant at the real 232px rail width, alongside the flat sets — so the
|
|
96
|
+
* operator can eyeball the gap hierarchy (butted reps < 2px notch < 3px cluster < 5px set gap)
|
|
97
|
+
* and the shared cyan "variable / unknown / opportunity" pin across range + myo-upcoming.
|
|
98
|
+
*/
|
|
99
|
+
export const SetTypes: Story = {
|
|
100
|
+
render: () => (
|
|
101
|
+
<View style={{ width: 232, gap: 18 }}>
|
|
102
|
+
<SheetRow
|
|
103
|
+
label="Flat sets"
|
|
104
|
+
meta="5 × 8 — done + active + todo"
|
|
105
|
+
sets={[
|
|
106
|
+
{ status: 'done', velocities: decay(8, 0.9) },
|
|
107
|
+
{ status: 'active', velocities: decay(5, 0.62), planned: 8 },
|
|
108
|
+
{ status: 'todo', planned: 8 },
|
|
109
|
+
]}
|
|
110
|
+
/>
|
|
111
|
+
<SheetRow
|
|
112
|
+
label="Variable range"
|
|
113
|
+
meta="3 × 15–20 — todo · 12 · 17"
|
|
114
|
+
sets={[
|
|
115
|
+
{ status: 'range', floor: 15, max: 20, doneVels: [] },
|
|
116
|
+
{ status: 'range', floor: 15, max: 20, doneVels: decay(12, 0.9) },
|
|
117
|
+
{ status: 'range', floor: 15, max: 20, doneVels: decay(17, 0.8) },
|
|
118
|
+
]}
|
|
119
|
+
/>
|
|
120
|
+
<SheetRow
|
|
121
|
+
label="Drop set"
|
|
122
|
+
meta="1 drop — 10→8→6"
|
|
123
|
+
sets={[{ status: 'drop', subloads: [decay(10, 0.85), decay(8, 0.7), decay(6, 0.6)] }]}
|
|
124
|
+
/>
|
|
125
|
+
<SheetRow
|
|
126
|
+
label="Myo-rep"
|
|
127
|
+
meta="done — 15 + 5 + 5 + 5"
|
|
128
|
+
sets={[
|
|
129
|
+
{
|
|
130
|
+
status: 'myo',
|
|
131
|
+
activation: decay(15, 0.75),
|
|
132
|
+
clusters: [decay(5, 0.6), decay(5, 0.55), decay(5, 0.5)],
|
|
133
|
+
},
|
|
134
|
+
]}
|
|
135
|
+
/>
|
|
136
|
+
<SheetRow
|
|
137
|
+
label="Myo — upcoming"
|
|
138
|
+
meta="~15 + clusters to failure"
|
|
139
|
+
sets={[{ status: 'myo-upcoming', activationLen: 15 }]}
|
|
140
|
+
/>
|
|
141
|
+
</View>
|
|
142
|
+
),
|
|
143
|
+
parameters: {
|
|
144
|
+
layout: 'padded',
|
|
145
|
+
docs: {
|
|
146
|
+
description: {
|
|
147
|
+
story:
|
|
148
|
+
'The four set-type variants (range / drop / myo / myo-upcoming) plus the flat sets, ' +
|
|
149
|
+
'at rail width. Gap hierarchy: butted reps (0) < notch (2px, drop) < cluster (3px, myo) ' +
|
|
150
|
+
'< set gap (5px). Cyan is the shared variable/unknown/opportunity pin.',
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
}
|