@titan-design/react-ui 0.12.0 → 0.13.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/README.md +46 -47
- package/dist/bodymap.js +768 -701
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +770 -703
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +1320 -215
- package/dist/index.d.ts +1320 -215
- package/dist/index.js +5996 -4498
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5773 -4357
- package/dist/index.mjs.map +1 -1
- package/dist/{pages-CvsFqNtx.d.mts → pages-CpW3OB3g.d.mts} +21 -3
- package/dist/{pages-B1hqnGIC.d.ts → pages-_3Ajpiqu.d.ts} +21 -3
- package/dist/pages.d.mts +1 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +1435 -1428
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +1443 -1436
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +202 -1042
- package/dist/theme/index.d.ts +202 -1042
- package/dist/theme/index.js +215 -300
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +202 -296
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +62 -5
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +62 -5
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/dist/theme/tokens.d.mts +972 -0
- package/dist/theme/tokens.d.ts +972 -0
- package/dist/theme/tokens.js +904 -0
- package/dist/theme/tokens.js.map +1 -0
- package/dist/theme/tokens.mjs +880 -0
- package/dist/theme/tokens.mjs.map +1 -0
- package/docs/audits/2026-09-08-critique-addenda.md +51 -0
- package/docs/audits/2026-09-08-library-critique.md +212 -0
- package/docs/library-roadmap.md +99 -0
- package/package.json +7 -1
- package/src/arch/arch-graph.freshness.test.ts +52 -0
- package/src/arch/arch-graph.json +5021 -1617
- package/src/components/custom/ActiveWork/CoChangeChip.stories.tsx +44 -0
- package/src/components/custom/ActiveWork/CoChangeChip.test.tsx +29 -0
- package/src/components/custom/ActiveWork/CoChangeChip.tsx +48 -0
- package/src/components/custom/ActiveWork/Eyebrow.stories.tsx +25 -0
- package/src/components/custom/ActiveWork/Eyebrow.test.tsx +16 -0
- package/src/components/custom/ActiveWork/Eyebrow.tsx +26 -0
- package/src/components/custom/ActiveWork/FileActivityDetail.stories.tsx +50 -0
- package/src/components/custom/ActiveWork/FileActivityDetail.test.tsx +66 -0
- package/src/components/custom/ActiveWork/FileActivityDetail.tsx +202 -0
- package/src/components/custom/ActiveWork/FileActivityRow.stories.tsx +70 -0
- package/src/components/custom/ActiveWork/FileActivityRow.test.tsx +67 -0
- package/src/components/custom/ActiveWork/FileActivityRow.tsx +130 -0
- package/src/components/custom/ActiveWork/FileHistoryExplorer.stories.tsx +84 -0
- package/src/components/custom/ActiveWork/FileHistoryExplorer.test.tsx +99 -0
- package/src/components/custom/ActiveWork/FileHistoryExplorer.tsx +138 -0
- package/src/components/custom/ActiveWork/FilePathLabel.stories.tsx +39 -0
- package/src/components/custom/ActiveWork/FilePathLabel.test.tsx +53 -0
- package/src/components/custom/ActiveWork/FilePathLabel.tsx +63 -0
- package/src/components/custom/ActiveWork/InitiativeBrief.stories.tsx +50 -0
- package/src/components/custom/ActiveWork/InitiativeBrief.test.tsx +62 -0
- package/src/components/custom/ActiveWork/InitiativeBrief.tsx +181 -0
- package/src/components/custom/ActiveWork/InitiativeCard.stories.tsx +73 -0
- package/src/components/custom/ActiveWork/InitiativeCard.test.tsx +68 -0
- package/src/components/custom/ActiveWork/InitiativeCard.tsx +136 -0
- package/src/components/custom/ActiveWork/InitiativeHeader.stories.tsx +59 -0
- package/src/components/custom/ActiveWork/InitiativeHeader.test.tsx +40 -0
- package/src/components/custom/ActiveWork/InitiativeHeader.tsx +73 -0
- package/src/components/custom/ActiveWork/InitiativeReader.stories.tsx +145 -0
- package/src/components/custom/ActiveWork/OpenLoops.stories.tsx +58 -0
- package/src/components/custom/ActiveWork/OpenLoops.test.tsx +61 -0
- package/src/components/custom/ActiveWork/OpenLoops.tsx +107 -0
- package/src/components/custom/ActiveWork/PortfolioOverview.stories.tsx +101 -0
- package/src/components/custom/ActiveWork/PortfolioOverview.test.tsx +81 -0
- package/src/components/custom/ActiveWork/PortfolioOverview.tsx +83 -0
- package/src/components/custom/ActiveWork/README.md +305 -0
- package/src/components/custom/ActiveWork/SessionDetail.stories.tsx +71 -0
- package/src/components/custom/ActiveWork/SessionDetail.test.tsx +84 -0
- package/src/components/custom/ActiveWork/SessionDetail.tsx +180 -0
- package/src/components/custom/ActiveWork/SessionList.stories.tsx +69 -0
- package/src/components/custom/ActiveWork/SessionList.test.tsx +78 -0
- package/src/components/custom/ActiveWork/SessionList.tsx +103 -0
- package/src/components/custom/ActiveWork/SessionListItem.stories.tsx +64 -0
- package/src/components/custom/ActiveWork/SessionListItem.test.tsx +62 -0
- package/src/components/custom/ActiveWork/SessionListItem.tsx +152 -0
- package/src/components/custom/ActiveWork/SessionReader.stories.tsx +113 -0
- package/src/components/custom/ActiveWork/SeverityLabel.stories.tsx +51 -0
- package/src/components/custom/ActiveWork/SeverityLabel.test.tsx +68 -0
- package/src/components/custom/ActiveWork/SeverityLabel.tsx +97 -0
- package/src/components/custom/ActiveWork/TaskRow.stories.tsx +63 -0
- package/src/components/custom/ActiveWork/TaskRow.test.tsx +112 -0
- package/src/components/custom/ActiveWork/TaskRow.tsx +176 -0
- package/src/components/custom/ActiveWork/TaskTable.stories.tsx +123 -0
- package/src/components/custom/ActiveWork/TaskTable.test.tsx +233 -0
- package/src/components/custom/ActiveWork/TaskTable.tsx +321 -0
- package/src/components/custom/ActiveWork/active-work-depth.test.tsx +102 -0
- package/src/components/custom/ActiveWork/file-history-fixture.ts +91 -0
- package/src/components/custom/ActiveWork/format-time.test.ts +23 -0
- package/src/components/custom/ActiveWork/format-time.ts +32 -0
- package/src/components/custom/ActiveWork/index.ts +19 -0
- package/src/components/custom/ActiveWork/initiative-fixture.ts +104 -0
- package/src/components/custom/ActiveWork/session-fixture.ts +267 -0
- package/src/components/custom/ActiveWork/session-linkers.ts +56 -0
- package/src/components/custom/ActiveWork/task-list-fixture.ts +97 -0
- package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +4 -3
- package/src/components/custom/DateTime/DateTime.stories.tsx +2 -1
- package/src/components/custom/DateTime/DateTime.test.tsx +3 -1
- package/src/components/custom/EmptyState/EmptyState.stories.tsx +22 -9
- package/src/components/custom/EmptyState/EmptyState.test.tsx +7 -13
- package/src/components/custom/EmptyState/EmptyState.tsx +4 -18
- package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +4 -3
- package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
- package/src/components/custom/Fatigue/GhostSpark.stories.tsx +4 -3
- package/src/components/custom/Fatigue/LiveFatigueCard.stories.tsx +2 -2
- package/src/components/custom/Fatigue/LiveFatigueCard.tsx +8 -4
- package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +116 -6
- package/src/components/custom/Fatigue/LiveFatiguePanel.test.tsx +134 -0
- package/src/components/custom/Fatigue/LiveFatiguePanel.tsx +54 -83
- package/src/components/custom/Fatigue/README.md +40 -3
- package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
- package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +2 -1
- package/src/components/custom/Fatigue/VelocityHero.stories.tsx +4 -3
- package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
- package/src/components/custom/Fatigue/fatigue-mock.test.ts +0 -5
- package/src/components/custom/Fatigue/fatigue-mock.ts +2 -10
- package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -0
- package/src/components/custom/Fatigue/index.ts +17 -5
- package/src/components/custom/Fatigue/panel-layout.test.ts +149 -0
- package/src/components/custom/Fatigue/panel-layout.ts +185 -0
- package/src/components/custom/Gauge/Gauge.stories.tsx +2 -2
- package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.tsx +4 -1
- package/src/components/custom/Metric/Metric.stories.tsx +10 -1
- package/src/components/custom/Metric/Metric.test.tsx +1 -3
- package/src/components/custom/Metric/Metric.tsx +5 -20
- package/src/components/custom/Prose/MarkdownProse.stories.tsx +88 -0
- package/src/components/custom/Prose/MarkdownProse.test.tsx +87 -0
- package/src/components/custom/Prose/MarkdownProse.tsx +201 -0
- package/src/components/custom/Prose/README.md +58 -0
- package/src/components/custom/Prose/index.ts +1 -0
- package/src/components/custom/Scatter/Scatter.stories.tsx +46 -8
- package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
- package/src/components/custom/Scatter/Scatter.tsx +116 -14
- package/src/components/custom/Sidebar/Sidebar.stories.tsx +40 -7
- package/src/components/custom/Sidebar/Sidebar.test.tsx +5 -1
- package/src/components/custom/Sidebar/Sidebar.tsx +16 -33
- package/src/components/custom/Table/Table.stories.tsx +98 -15
- package/src/components/custom/Table/Table.test.tsx +273 -86
- package/src/components/custom/Table/Table.tsx +159 -67
- package/src/components/custom/Table/column-fit.test.ts +75 -0
- package/src/components/custom/Table/column-fit.ts +116 -0
- package/src/components/custom/Table/index.ts +9 -0
- package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +8 -6
- package/src/components/custom/Treemap/Treemap.stories.tsx +2 -2
- package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
- package/src/components/custom/Treemap/Treemap.tsx +7 -2
- package/src/components/custom/Typography/Typography.stories.tsx +28 -1
- package/src/components/custom/Typography/Typography.test.tsx +34 -0
- package/src/components/custom/Typography/Typography.tsx +6 -0
- package/src/components/custom/Typography/index.ts +1 -8
- package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +9 -1
- package/src/components/custom/Workout/BaseBadge.stories.tsx +19 -7
- package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
- package/src/components/custom/Workout/BaseBadge.tsx +3 -0
- package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
- package/src/components/custom/Workout/BodyMap.tsx +3 -1
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +16 -4
- package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +45 -9
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +10 -8
- package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
- package/src/components/custom/Workout/CapacityBandChart.tsx +139 -108
- package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.test.tsx +5 -2
- package/src/components/custom/Workout/DeviationBar.tsx +21 -16
- package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +182 -0
- package/src/components/custom/Workout/DualVelocityStrip.test.tsx +3 -2
- package/src/components/custom/Workout/ExerciseCard.stories.tsx +8 -7
- package/src/components/custom/Workout/ExerciseCard.test.tsx +13 -3
- package/src/components/custom/Workout/ExerciseCard.tsx +42 -51
- package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +7 -7
- package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
- package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
- package/src/components/custom/Workout/ExerciseHeading.tsx +8 -5
- package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +6 -4
- package/src/components/custom/Workout/ExerciseIndicator.test.tsx +27 -11
- package/src/components/custom/Workout/ExerciseIndicator.tsx +14 -15
- package/src/components/custom/Workout/FatigueMeter.stories.tsx +5 -5
- package/src/components/custom/Workout/InputBar.stories.tsx +4 -5
- package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
- package/src/components/custom/Workout/IntensityBar.test.tsx +5 -1
- package/src/components/custom/Workout/IntensityBar.tsx +4 -2
- package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +5 -4
- package/src/components/custom/Workout/MesoCard.stories.tsx +4 -1
- package/src/components/custom/Workout/MesoCard.test.tsx +7 -18
- package/src/components/custom/Workout/MesoCard.tsx +12 -9
- package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoProgressBar.test.tsx +18 -11
- package/src/components/custom/Workout/MesoProgressBar.tsx +15 -13
- package/src/components/custom/Workout/MesoStatusCard.stories.tsx +2 -1
- package/src/components/custom/Workout/MesoStatusCard.test.tsx +14 -44
- package/src/components/custom/Workout/MesoStatusCard.tsx +9 -23
- package/src/components/custom/Workout/MetricTiles.stories.tsx +3 -2
- package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +2 -8
- package/src/components/custom/Workout/MuscleGroupChip.test.tsx +23 -31
- package/src/components/custom/Workout/MuscleGroupChip.tsx +28 -67
- package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
- package/src/components/custom/Workout/PlaceholderStrip.test.tsx +17 -10
- package/src/components/custom/Workout/PlaceholderStrip.tsx +9 -8
- package/src/components/custom/Workout/PrBadge.stories.tsx +2 -1
- package/src/components/custom/Workout/PrBadge.test.tsx +3 -9
- package/src/components/custom/Workout/PrBadge.tsx +13 -17
- package/src/components/custom/Workout/PrHistoryModal.stories.tsx +4 -1
- package/src/components/custom/Workout/PrHistoryModal.test.tsx +13 -36
- package/src/components/custom/Workout/PrHistoryModal.tsx +8 -4
- package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +6 -1
- package/src/components/custom/Workout/README.md +12 -7
- package/src/components/custom/Workout/ReadinessCheck.stories.tsx +3 -2
- package/src/components/custom/Workout/ReadinessCheck.test.tsx +12 -18
- package/src/components/custom/Workout/ReadinessCheck.tsx +19 -3
- package/src/components/custom/Workout/RestTimer.stories.tsx +3 -2
- package/src/components/custom/Workout/ScheduleTiles.stories.tsx +3 -2
- package/src/components/custom/Workout/ScheduleTiles.test.tsx +3 -4
- package/src/components/custom/Workout/ScheduleTiles.tsx +4 -7
- package/src/components/custom/Workout/SegmentedBar.stories.tsx +5 -5
- package/src/components/custom/Workout/SegmentedBar.tsx +6 -2
- package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +5 -5
- package/src/components/custom/Workout/SessionHeader.stories.tsx +6 -6
- package/src/components/custom/Workout/SessionHeader.tsx +12 -12
- package/src/components/custom/Workout/SessionRail.stories.tsx +12 -11
- package/src/components/custom/Workout/SessionRail.tsx +7 -9
- package/src/components/custom/Workout/SetBar.stories.tsx +10 -6
- package/src/components/custom/Workout/SetBar.test.tsx +49 -4
- package/src/components/custom/Workout/SetBar.tsx +38 -12
- package/src/components/custom/Workout/SetRow.stories.tsx +3 -2
- package/src/components/custom/Workout/SetRow.test.tsx +16 -2
- package/src/components/custom/Workout/SetRow.tsx +61 -23
- package/src/components/custom/Workout/SetStrip.stories.tsx +60 -5
- package/src/components/custom/Workout/SetStrip.test.tsx +25 -0
- package/src/components/custom/Workout/SetStrip.tsx +24 -4
- package/src/components/custom/Workout/SetTableHeader.stories.tsx +6 -6
- package/src/components/custom/Workout/SetTableHeader.tsx +9 -12
- package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +7 -7
- package/src/components/custom/Workout/SetsRepsLoad.tsx +3 -5
- package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
- package/src/components/custom/Workout/Sparkline.test.tsx +37 -19
- package/src/components/custom/Workout/Sparkline.tsx +14 -18
- package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusDot.test.tsx +44 -5
- package/src/components/custom/Workout/StatusDot.tsx +93 -63
- package/src/components/custom/Workout/StatusPill.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusPill.test.tsx +6 -15
- package/src/components/custom/Workout/StatusPill.tsx +27 -38
- package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +9 -3
- package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
- package/src/components/custom/Workout/StrengthTrendChart.tsx +31 -30
- package/src/components/custom/Workout/SupersetWrapper.stories.tsx +27 -64
- package/src/components/custom/Workout/SupersetWrapper.test.tsx +16 -14
- package/src/components/custom/Workout/SupersetWrapper.tsx +17 -21
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +22 -7
- package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
- package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +9 -1
- package/src/components/custom/Workout/VelocityStrip.compact.stories.tsx +4 -1
- package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +7 -4
- package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +4 -1
- package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +4 -1
- package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
- package/src/components/custom/Workout/VelocityStrip.tsx +3 -0
- package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +6 -7
- package/src/components/custom/Workout/VolumeLandmarkBar.tsx +15 -6
- package/src/components/custom/Workout/WeekRow.stories.tsx +4 -1
- package/src/components/custom/Workout/WeekRow.test.tsx +18 -15
- package/src/components/custom/Workout/WeekRow.tsx +23 -16
- package/src/components/custom/Workout/WeightBadge.stories.tsx +2 -1
- package/src/components/custom/Workout/WeightBadge.test.tsx +50 -19
- package/src/components/custom/Workout/WeightBadge.tsx +28 -27
- package/src/components/custom/Workout/WorkoutCard.stories.tsx +6 -1
- package/src/components/custom/Workout/WorkoutCard.test.tsx +18 -0
- package/src/components/custom/Workout/WorkoutCard.tsx +35 -57
- package/src/components/custom/Workout/WorkoutPill.stories.tsx +5 -2
- package/src/components/custom/Workout/WorkoutPill.test.tsx +39 -7
- package/src/components/custom/Workout/WorkoutPill.tsx +88 -57
- package/src/components/custom/Workout/ZoneTrack.stories.tsx +7 -6
- package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
- package/src/components/custom/Workout/index.ts +5 -0
- package/src/components/custom/Workout/metricText.stories.tsx +6 -5
- package/src/components/custom/Workout/metricText.tsx +4 -0
- package/src/components/custom/Workout/setHeadingKit.tsx +207 -26
- package/src/components/custom/charts/README.md +61 -0
- package/src/components/custom/charts/SetBarChart.test.tsx +30 -1
- package/src/components/custom/charts/SetBarChart.tsx +42 -4
- package/src/components/custom/charts/SparkBars.stories.tsx +55 -0
- package/src/components/custom/charts/SparkBars.test.tsx +69 -0
- package/src/components/custom/charts/SparkBars.tsx +85 -0
- package/src/components/custom/charts/index.ts +3 -0
- package/src/components/custom/index.ts +3 -0
- package/src/components/custom/stepper/Stepper.stories.tsx +13 -10
- package/src/components/custom/stepper/Stepper.test.tsx +1 -7
- package/src/components/custom/stepper/Stepper.tsx +13 -28
- package/src/components/icons/icons.stories.tsx +1 -1
- package/src/components/icons/icons.tsx +51 -0
- package/src/components/shell/AppShell.stories.tsx +150 -0
- package/src/components/shell/AppShell.test.tsx +70 -0
- package/src/components/shell/AppShell.tsx +90 -0
- package/src/components/shell/BrandLockup.stories.tsx +66 -5
- package/src/components/shell/BrandLockup.test.tsx +34 -1
- package/src/components/shell/BrandLockup.tsx +27 -11
- package/src/components/shell/NavItem.stories.tsx +4 -4
- package/src/components/shell/NavItem.test.tsx +17 -0
- package/src/components/shell/NavItem.tsx +17 -5
- package/src/components/shell/README.md +90 -27
- package/src/components/shell/SideNav.stories.tsx +38 -7
- package/src/components/shell/SideNav.test.tsx +16 -8
- package/src/components/shell/SideNav.tsx +17 -17
- package/src/components/shell/TopBar.stories.tsx +44 -19
- package/src/components/shell/TopBar.test.tsx +34 -12
- package/src/components/shell/TopBar.tsx +61 -40
- package/src/components/shell/brands.tsx +66 -0
- package/src/components/shell/index.ts +9 -8
- package/src/components/shell/{DeviceIndicator.stories.tsx → workout/DeviceIndicator.stories.tsx} +2 -2
- package/src/components/shell/{DeviceIndicator.tsx → workout/DeviceIndicator.tsx} +2 -2
- package/src/components/shell/{DeviceMenu.stories.tsx → workout/DeviceMenu.stories.tsx} +2 -2
- package/src/components/shell/{DeviceMenu.tsx → workout/DeviceMenu.tsx} +3 -3
- package/src/components/shell/{DeviceRow.stories.tsx → workout/DeviceRow.stories.tsx} +2 -2
- package/src/components/shell/{DeviceRow.tsx → workout/DeviceRow.tsx} +3 -3
- package/src/components/shell/{SessionStatePill.stories.tsx → workout/SessionStatePill.stories.tsx} +2 -2
- package/src/components/shell/{SessionStatePill.tsx → workout/SessionStatePill.tsx} +5 -3
- package/src/components/shell/workout/WorkoutShell.stories.tsx +71 -0
- package/src/components/shell/{DashboardShell.test.tsx → workout/WorkoutShell.test.tsx} +19 -8
- package/src/components/shell/workout/WorkoutShell.tsx +77 -0
- package/src/components/shell/workout/WorkoutTopBar.stories.tsx +58 -0
- package/src/components/shell/workout/WorkoutTopBar.test.tsx +39 -0
- package/src/components/shell/workout/WorkoutTopBar.tsx +52 -0
- package/src/components/shell/workout/index.ts +9 -0
- package/src/components/shell/workout/workoutNavItems.tsx +16 -0
- package/src/components/ui/README.md +110 -0
- package/src/components/ui/alert/Alert.stories.tsx +1 -1
- package/src/components/ui/autocomplete/Autocomplete.stories.tsx +11 -13
- package/src/components/ui/autocomplete/Autocomplete.test.tsx +7 -25
- package/src/components/ui/autocomplete/Autocomplete.tsx +21 -28
- package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
- package/src/components/ui/avatar/Avatar.tsx +2 -10
- package/src/components/ui/badge/Badge.stories.tsx +83 -28
- package/src/components/ui/badge/Badge.test.tsx +19 -3
- package/src/components/ui/badge/Badge.tsx +48 -55
- package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
- package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +4 -16
- package/src/components/ui/button/Button.stories.tsx +46 -12
- package/src/components/ui/button/Button.tsx +32 -25
- package/src/components/ui/card/Card.stories.tsx +90 -94
- package/src/components/ui/card/Card.test.tsx +80 -6
- package/src/components/ui/card/Card.tsx +150 -203
- package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
- package/src/components/ui/checkbox/Checkbox.tsx +6 -26
- package/src/components/ui/chip/Chip.stories.tsx +37 -13
- package/src/components/ui/chip/Chip.test.tsx +10 -6
- package/src/components/ui/chip/Chip.tsx +76 -91
- package/src/components/ui/collapse/Collapse.stories.tsx +23 -23
- package/src/components/ui/collapse/Collapse.tsx +6 -11
- package/src/components/ui/data-row/DataRow.stories.tsx +9 -2
- package/src/components/ui/data-row/DataRow.test.tsx +5 -15
- package/src/components/ui/data-row/DataRow.tsx +18 -7
- package/src/components/ui/divider/Divider.stories.tsx +1 -1
- package/src/components/ui/divider/Divider.tsx +1 -5
- package/src/components/ui/drawer/Drawer.stories.tsx +5 -16
- package/src/components/ui/drawer/Drawer.tsx +13 -30
- package/src/components/ui/floating-overlay-depth.test.tsx +143 -0
- package/src/components/ui/form-field/FormField.stories.tsx +6 -20
- package/src/components/ui/form-field/FormField.test.tsx +1 -5
- package/src/components/ui/form-field/FormField.tsx +10 -46
- package/src/components/ui/help-tip/HelpTip.stories.tsx +8 -19
- package/src/components/ui/help-tip/HelpTip.test.tsx +1 -3
- package/src/components/ui/help-tip/HelpTip.tsx +21 -22
- package/src/components/ui/help-tip/index.ts +7 -1
- package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
- package/src/components/ui/icon-box/IconBox.test.tsx +1 -7
- package/src/components/ui/icon-box/IconBox.tsx +2 -12
- package/src/components/ui/indicator/Indicator.stories.tsx +1 -1
- package/src/components/ui/indicator/Indicator.tsx +20 -14
- package/src/components/ui/input/Input.stories.tsx +3 -11
- package/src/components/ui/input/Input.test.tsx +2 -10
- package/src/components/ui/input/Input.tsx +10 -25
- package/src/components/ui/input/index.ts +7 -1
- package/src/components/ui/link/Link.stories.tsx +19 -7
- package/src/components/ui/list-item/ListItem.stories.tsx +11 -2
- package/src/components/ui/list-item/ListItem.tsx +2 -9
- package/src/components/ui/menu/Menu.stories.tsx +21 -15
- package/src/components/ui/menu/Menu.test.tsx +2 -11
- package/src/components/ui/menu/Menu.tsx +12 -14
- package/src/components/ui/menu/index.ts +8 -1
- package/src/components/ui/modal/Modal.stories.tsx +2 -2
- package/src/components/ui/modal/Modal.tsx +29 -19
- package/src/components/ui/pill/Pill.stories.tsx +58 -23
- package/src/components/ui/pill/Pill.test.tsx +101 -3
- package/src/components/ui/pill/Pill.tsx +164 -49
- package/src/components/ui/pill/index.ts +1 -1
- package/src/components/ui/popover/Popover.stories.tsx +5 -7
- package/src/components/ui/popover/Popover.test.tsx +1 -6
- package/src/components/ui/popover/Popover.tsx +20 -15
- package/src/components/ui/popover/index.ts +7 -1
- package/src/components/ui/progress/Progress.stories.tsx +3 -12
- package/src/components/ui/progress/Progress.test.tsx +1 -5
- package/src/components/ui/radio/Radio.stories.tsx +42 -21
- package/src/components/ui/radio/Radio.test.tsx +6 -2
- package/src/components/ui/radio/Radio.tsx +23 -22
- package/src/components/ui/section/Section.stories.tsx +5 -14
- package/src/components/ui/section/Section.test.tsx +1 -6
- package/src/components/ui/section/Section.tsx +1 -3
- package/src/components/ui/section/index.ts +1 -5
- package/src/components/ui/select/Select.stories.tsx +3 -13
- package/src/components/ui/select/Select.test.tsx +2 -11
- package/src/components/ui/select/Select.tsx +14 -14
- package/src/components/ui/skeleton/Skeleton.stories.tsx +3 -11
- package/src/components/ui/skeleton/Skeleton.tsx +3 -14
- package/src/components/ui/skeleton/index.ts +1 -7
- package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
- package/src/components/ui/spinner/Spinner.tsx +1 -4
- package/src/components/ui/stack/Stack.stories.tsx +1 -1
- package/src/components/ui/stack/Stack.tsx +1 -1
- package/src/components/ui/surface/Surface.stories.tsx +17 -5
- package/src/components/ui/surface/Surface.test.tsx +88 -28
- package/src/components/ui/surface/Surface.tsx +37 -87
- package/src/components/ui/surface/SurfaceContext.ts +22 -62
- package/src/components/ui/surface/index.ts +8 -0
- package/src/components/ui/surface/resolveSurface.ts +98 -0
- package/src/components/ui/surface/surface.contract.test.ts +6 -1
- package/src/components/ui/switch/Switch.stories.tsx +1 -1
- package/src/components/ui/switch/Switch.tsx +7 -6
- package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
- package/src/components/ui/tabs/Tabs.tsx +7 -22
- package/src/components/ui/tabs/index.ts +1 -7
- package/src/components/ui/tile/Tile.stories.tsx +1 -1
- package/src/components/ui/tile/Tile.tsx +3 -0
- package/src/components/ui/toast/Toast.stories.tsx +1 -1
- package/src/components/ui/toast/Toast.test.tsx +2 -8
- package/src/components/ui/toast/Toast.tsx +43 -53
- package/src/components/ui/toast/index.ts +0 -1
- package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +92 -71
- package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +3 -18
- package/src/components/ui/toolbar-button/ToolbarButton.tsx +25 -43
- package/src/components/ui/tooltip/Tooltip.stories.tsx +12 -3
- package/src/components/ui/tooltip/Tooltip.test.tsx +21 -3
- package/src/components/ui/tooltip/Tooltip.tsx +55 -36
- package/src/components/ui/tooltip/index.ts +1 -1
- package/src/components/ui/trigger/TriggerSurface.test.tsx +215 -0
- package/src/components/ui/trigger/TriggerSurface.tsx +81 -0
- package/src/components/ui/trigger/index.ts +2 -0
- package/src/stories/PresetShowcase.stories.tsx +100 -47
- package/src/test/no-device-internals.test.ts +3 -3
- package/src/theme/ChoosingTokens.stories.tsx +48 -0
- package/src/theme/ColorPalettes.stories.tsx +62 -45
- package/src/theme/ColorPrimitives.stories.tsx +35 -35
- package/src/theme/Depth.stories.tsx +132 -65
- package/src/theme/DepthCalibration.stories.tsx +24 -22
- package/src/theme/ThemeProvider.test.tsx +4 -4
- package/src/theme/barrel.ts +7 -6
- package/src/theme/color-stories.coverage.test.ts +1 -1
- package/src/theme/color-utils.ts +41 -29
- package/src/theme/config.completeness.test.ts +1 -1
- package/src/theme/config.ts +28 -0
- package/src/theme/elevation.test.ts +82 -56
- package/src/theme/elevation.ts +77 -561
- package/src/theme/global.css +30 -2
- package/src/theme/grey-ramp.test.ts +24 -8
- package/src/theme/lift.test.ts +39 -0
- package/src/theme/lift.ts +102 -0
- package/src/theme/materials.test.ts +5 -2
- package/src/theme/materials.ts +38 -4
- package/src/theme/native-theming-guard.test.ts +5 -5
- package/src/theme/presets/apply.ts +4 -0
- package/src/theme/presets/audiobook.ts +5 -2
- package/src/theme/presets/default.ts +4 -0
- package/src/theme/presets/index.ts +14 -1
- package/src/theme/presets/types.ts +1 -1
- package/src/theme/semantic-contrast.test.ts +13 -4
- package/src/theme/status-distinctness.test.ts +66 -0
- package/src/theme/surface-planes.test.ts +37 -0
- package/src/theme/surface-planes.ts +68 -0
- package/src/theme/token-export-guard.test.ts +102 -0
- package/src/theme/tokens/primitives.test.ts +15 -7
- package/src/theme/tokens/primitives.ts +67 -35
- package/src/theme/tokens/semantic.ts +71 -37
- package/src/theme/wash-ladder.test.ts +58 -0
- package/src/theme/workout-tokens.ts +1 -7
- package/src/types/jest-axe.d.ts +2 -6
- package/src/types/raw-md.d.ts +5 -0
- package/src/utils/colors.ts +4 -4
- package/src/utils/form.ts +1 -3
- package/src/utils/index.ts +2 -7
- package/src/utils/number-format.ts +17 -0
- package/src/utils/workout-format.ts +15 -6
- package/src/web-jsx/jsx-runtime.ts +1 -5
- package/tailwind.config.js +5 -0
- package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +0 -151
- package/src/components/custom/Workout/RowInventory.stories.tsx +0 -408
- package/src/components/custom/Workout/S3FullRail.stories.tsx +0 -46
- package/src/components/custom/Workout/S3SessionPace.stories.tsx +0 -95
- package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +0 -61
- package/src/components/custom/Workout/S3SetTypes.stories.tsx +0 -176
- package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +0 -240
- package/src/components/shell/DashboardShell.stories.tsx +0 -65
- package/src/components/shell/DashboardShell.tsx +0 -75
- package/src/components/shell/SessionRailSpecimen.stories.tsx +0 -753
- package/src/theme/elevation.stories.tsx +0 -346
- package/src/utils/useTheme.ts +0 -72
- /package/src/components/shell/{DeviceIndicator.test.tsx → workout/DeviceIndicator.test.tsx} +0 -0
- /package/src/components/shell/{DeviceMenu.test.tsx → workout/DeviceMenu.test.tsx} +0 -0
- /package/src/components/shell/{DeviceRow.test.tsx → workout/DeviceRow.test.tsx} +0 -0
- /package/src/components/shell/{SessionStatePill.test.tsx → workout/SessionStatePill.test.tsx} +0 -0
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SHEET · Session Rail — set-type encodings (R&D). Throwaway specimen at real rail width, on real tokens.
|
|
3
|
-
* Explores the cases the flat `sets × reps @ load` strip doesn't model:
|
|
4
|
-
* 1. Variable rep-range — range-max segments; the variable zone (floor→max) upcoming part gets its OWN color.
|
|
5
|
-
* 2. Drop set — ONE bar, sub-loads separated by thin NOTCHES (< the between-set gap); reps velocity-colored.
|
|
6
|
-
* 3. Myo-rep / rest-pause — activation chunk + mini-clusters separated by small cluster gaps.
|
|
7
|
-
* Gap hierarchy: butted reps (0) < notch (2, drop sub-load) < cluster gap (3, myo rest-pause) < SET_GAP (5, sets).
|
|
8
|
-
* Hardens into a SetStrip model extension (SetState variants: range/drop/myo) — a post-harden follow-up.
|
|
9
|
-
*/
|
|
10
|
-
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
11
|
-
import { Fragment } from 'react'
|
|
12
|
-
import { primitiveRamps as ramp, greyRamp } from '../../../theme/tokens/primitives'
|
|
13
|
-
import { GREY, RAIL_W, SET_GAP, T_PRIMARY, T_SECONDARY, T_TERTIARY, INSET, velColor, reps, Page, sectionTitle } from './setHeadingKit'
|
|
14
|
-
|
|
15
|
-
// ---- variable-zone (floor→max) upcoming color — real ramp candidates (no invented hex)
|
|
16
|
-
const VAR_GREY = greyRamp[800] // #3C3C3C — lighter grey (the paler-grey reference)
|
|
17
|
-
const VAR_BLUE_800 = ramp.blue[800] // #14407E — clearly blue, a touch brighter
|
|
18
|
-
const VAR_BLUE_900 = ramp.blue[900] // #112C5A — dark muted navy, recessive
|
|
19
|
-
const VAR_CYAN_900 = ramp.cyan[900] // #0B3149 — teal alt, sidesteps info-blue adjacency
|
|
20
|
-
const NOTCH = 2 // drop sub-load divider
|
|
21
|
-
const CLUSTER_GAP = 3 // myo rest-pause divider
|
|
22
|
-
|
|
23
|
-
type Chunk = { colors: string[]; gapAfter?: number }
|
|
24
|
-
function Bar({ chunks, h }: { chunks: Chunk[]; h: number }) {
|
|
25
|
-
return (
|
|
26
|
-
<div style={{ display: 'flex', width: '100%', height: h, borderRadius: 2, overflow: 'hidden' }}>
|
|
27
|
-
{chunks.map((ch, ci) => (
|
|
28
|
-
<Fragment key={ci}>
|
|
29
|
-
{ch.colors.map((c, i) => (
|
|
30
|
-
<div key={i} style={{ flex: 1, minWidth: 0, height: '100%', background: c }} />
|
|
31
|
-
))}
|
|
32
|
-
{ci < chunks.length - 1 && <div style={{ flex: `0 0 ${ch.gapAfter ?? NOTCH}px`, height: '100%', background: INSET }} />}
|
|
33
|
-
</Fragment>
|
|
34
|
-
))}
|
|
35
|
-
</div>
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// ---- 1. variable rep-range: `max` segments; committed 0..floor, variable floor..max; variable-todo gets VAR color
|
|
40
|
-
function rangeColors(floor: number, max: number, doneVels: number[], varColor: string): string[] {
|
|
41
|
-
return Array.from({ length: max }, (_, i) => {
|
|
42
|
-
if (i < doneVels.length) return velColor(doneVels[i])
|
|
43
|
-
return i < floor ? GREY : varColor
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
function RangeBar({ floor, max, done, varColor, h }: { floor: number; max: number; done: number[]; varColor: string; h: number }) {
|
|
47
|
-
return <Bar chunks={[{ colors: rangeColors(floor, max, done, varColor) }]} h={h} />
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ---- 2. drop set: one bar, sub-loads butted internally, separated by thin notches
|
|
51
|
-
function DropBar({ subloads, h }: { subloads: number[][]; h: number }) {
|
|
52
|
-
const chunks: Chunk[] = subloads.map((vels, i) => ({ colors: vels.map(velColor), gapAfter: NOTCH, ...(i === subloads.length - 1 ? { gapAfter: undefined } : {}) }))
|
|
53
|
-
return <Bar chunks={chunks} h={h} />
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// ---- 3. myo-rep: activation chunk + mini-clusters, separated by cluster gaps
|
|
57
|
-
function MyoBar({ activation, clusters, h }: { activation: number[]; clusters: number[][]; h: number }) {
|
|
58
|
-
const chunks: Chunk[] = [{ colors: activation.map(velColor), gapAfter: CLUSTER_GAP }, ...clusters.map((c) => ({ colors: c.map(velColor), gapAfter: CLUSTER_GAP }))]
|
|
59
|
-
return <Bar chunks={chunks} h={h} />
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// ---- 3b. UPCOMING myo, unknown length: grey activation (expected) + a blue "clusters-to-failure" trail
|
|
63
|
-
// that fades and leaves the right edge open — signalling "N more clusters, count unknown".
|
|
64
|
-
function MyoUpcomingBar({ activationLen, blue, h }: { activationLen: number; blue: string; h: number }) {
|
|
65
|
-
const fades = [1, 0.6, 0.32] // decreasing opacity per expected cluster → "and maybe more"
|
|
66
|
-
return (
|
|
67
|
-
<div style={{ display: 'flex', width: '100%', height: h, gap: 0 }}>
|
|
68
|
-
<div style={{ display: 'flex', flex: activationLen, height: '100%', borderRadius: '2px 0 0 2px', overflow: 'hidden' }}>
|
|
69
|
-
{Array.from({ length: activationLen }, (_, i) => (
|
|
70
|
-
<div key={i} style={{ flex: 1, height: '100%', background: GREY }} />
|
|
71
|
-
))}
|
|
72
|
-
</div>
|
|
73
|
-
{fades.map((op, ci) => (
|
|
74
|
-
<Fragment key={ci}>
|
|
75
|
-
<div style={{ flex: `0 0 ${CLUSTER_GAP}px`, height: '100%', background: INSET }} />
|
|
76
|
-
<div style={{ display: 'flex', flex: 5, height: '100%', overflow: 'hidden', opacity: op }}>
|
|
77
|
-
{Array.from({ length: 5 }, (_, i) => (
|
|
78
|
-
<div key={i} style={{ flex: 1, height: '100%', background: blue }} />
|
|
79
|
-
))}
|
|
80
|
-
</div>
|
|
81
|
-
</Fragment>
|
|
82
|
-
))}
|
|
83
|
-
</div>
|
|
84
|
-
)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// ---- row scaffold at real rail width, on the sunk inset surface
|
|
88
|
-
function Row({ name, meta, children }: { name: string; meta: string; children: React.ReactNode }) {
|
|
89
|
-
return (
|
|
90
|
-
<div style={{ width: RAIL_W, background: INSET, padding: '9px 12px', borderRadius: 4 }}>
|
|
91
|
-
<div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginBottom: 6 }}>
|
|
92
|
-
<span style={{ fontSize: 14, fontWeight: 800, color: T_PRIMARY }}>{name}</span>
|
|
93
|
-
<div style={{ flex: 1 }} />
|
|
94
|
-
<span style={{ fontSize: 10, fontFamily: 'monospace', color: T_TERTIARY }}>{meta}</span>
|
|
95
|
-
</div>
|
|
96
|
-
{children}
|
|
97
|
-
</div>
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
function Col({ label, children }: { label: string; children: React.ReactNode }) {
|
|
101
|
-
return (
|
|
102
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
|
|
103
|
-
<span style={{ ...sectionTitle, color: T_SECONDARY }}>{label}</span>
|
|
104
|
-
{children}
|
|
105
|
-
</div>
|
|
106
|
-
)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const H = 8
|
|
110
|
-
|
|
111
|
-
function Sheet() {
|
|
112
|
-
return (
|
|
113
|
-
<Page title="Session Rail — set-type encodings" note="R&D for prescriptions the flat sets×reps strip doesn't model. Rail width, real velocity ramp pins. Rep-range: range-max segments, the variable zone (floor→max) upcoming part gets its own color. Drop: one bar, sub-loads split by thin notches. Myo: activation + mini-clusters split by cluster gaps.">
|
|
114
|
-
<div style={{ display: 'flex', gap: 40, flexWrap: 'wrap', alignItems: 'flex-start' }}>
|
|
115
|
-
{/* 1. variable rep-range — real ramp candidates for the variable zone */}
|
|
116
|
-
<Col label="1 · variable rep-range — LOCKED: cyan 900">
|
|
117
|
-
{([
|
|
118
|
-
['grey · grey 200', VAR_GREY],
|
|
119
|
-
['blue 800 · #14407E', VAR_BLUE_800],
|
|
120
|
-
['blue 900 · #112C5A', VAR_BLUE_900],
|
|
121
|
-
['cyan 900 · #0B3149', VAR_CYAN_900],
|
|
122
|
-
] as const).map(([label, c]) => (
|
|
123
|
-
<Row key={label} name="Face Pull" meta="3 × 15–20 @ 40">
|
|
124
|
-
<span style={{ fontSize: 9, color: T_TERTIARY, display: 'block', marginBottom: 5 }}>{label}</span>
|
|
125
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: SET_GAP }}>
|
|
126
|
-
<RangeBar floor={15} max={20} done={[]} varColor={c} h={H} />
|
|
127
|
-
<RangeBar floor={15} max={20} done={reps(12, 0.9)} varColor={c} h={H} />
|
|
128
|
-
<RangeBar floor={15} max={20} done={reps(17, 0.8)} varColor={c} h={H} />
|
|
129
|
-
</div>
|
|
130
|
-
</Row>
|
|
131
|
-
))}
|
|
132
|
-
<span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>Each block: todo · 12 done (committed) · 17 done (into the variable zone). Variable-todo = the swatch; committed-todo = grey.</span>
|
|
133
|
-
</Col>
|
|
134
|
-
|
|
135
|
-
{/* 2. drop set */}
|
|
136
|
-
<Col label="2 · drop set">
|
|
137
|
-
<Row name="Lat Pulldown" meta="1 drop · 10→8→6 @ 120→80">
|
|
138
|
-
<DropBar subloads={[reps(10, 0.85), reps(8, 0.7), reps(6, 0.6)]} h={H} />
|
|
139
|
-
</Row>
|
|
140
|
-
<Row name="Leg Extension" meta="1 drop · 12→10→8→6 @ 90→45">
|
|
141
|
-
<DropBar subloads={[reps(12, 0.8), reps(10, 0.7), reps(8, 0.62), reps(6, 0.55)]} h={H} />
|
|
142
|
-
</Row>
|
|
143
|
-
<span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>One set, no rest; notches mark each load drop. Notch (2px) < set gap (5px) so drops read as sub-structure of a single set.</span>
|
|
144
|
-
</Col>
|
|
145
|
-
|
|
146
|
-
{/* 3. myo-rep */}
|
|
147
|
-
<Col label="3 · myo-rep / rest-pause">
|
|
148
|
-
<Row name="Cable Curl" meta="myo · done · 15 + 5 + 5 + 5">
|
|
149
|
-
<MyoBar activation={reps(15, 0.75)} clusters={[reps(5, 0.6), reps(5, 0.55), reps(5, 0.5)]} h={H} />
|
|
150
|
-
</Row>
|
|
151
|
-
<Row name="Triceps Pushdown" meta="myo · done · 12 + 4 + 4">
|
|
152
|
-
<MyoBar activation={reps(12, 0.7)} clusters={[reps(4, 0.55), reps(4, 0.5)]} h={H} />
|
|
153
|
-
</Row>
|
|
154
|
-
<span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>Done: activation to near-failure, then rest-pause clusters. Cluster gap (3px) between notch and set gap.</span>
|
|
155
|
-
<span style={{ ...sectionTitle, color: T_SECONDARY, marginTop: 6 }}>upcoming · length unknown</span>
|
|
156
|
-
<Row name="Cable Curl" meta="myo · ~15 + clusters to failure">
|
|
157
|
-
<MyoUpcomingBar activationLen={15} blue={VAR_CYAN_900} h={H} />
|
|
158
|
-
</Row>
|
|
159
|
-
<Row name="Triceps Pushdown" meta="myo · ~12 + clusters to failure">
|
|
160
|
-
<MyoUpcomingBar activationLen={12} blue={VAR_CYAN_900} h={H} />
|
|
161
|
-
</Row>
|
|
162
|
-
<span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>{'Grey activation (expected) + blue "clusters-to-failure" trail that fades and leaves the right edge open — reuses the variable/opportunity blue, signalling "more coming, count unknown."'}</span>
|
|
163
|
-
</Col>
|
|
164
|
-
</div>
|
|
165
|
-
</Page>
|
|
166
|
-
)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const meta: Meta = {
|
|
170
|
-
title: 'Lab/Explorations/Set Types',
|
|
171
|
-
parameters: { layout: 'fullscreen' },
|
|
172
|
-
}
|
|
173
|
-
export default meta
|
|
174
|
-
type Story = StoryObj
|
|
175
|
-
|
|
176
|
-
export const Encodings: Story = { render: () => <Sheet /> }
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SHEET · Workout Expansion (page 2) — what a rail item reveals when expanded.
|
|
3
|
-
* Anchored on the REAL unexpanded rail row (`ExerciseCardHeading`) as the persistent header, then the
|
|
4
|
-
* revealed body in two REAL-component directions so the fork is concrete:
|
|
5
|
-
* A — Table (real `SetTableHeader` + real `SetRow`s — the current expanded body).
|
|
6
|
-
* C — Embed (real `VelocityStrip` full/expanded per set + a compact caption — the bar IS the set).
|
|
7
|
-
* B (drop PREV) is a trivial prop on the table, noted but not forked here. Same data across both: set 1 done
|
|
8
|
-
* · set 2 LIVE 5/10 · set 3 upcoming, with velocities that DECAY within a set so the "shape" reading is real.
|
|
9
|
-
* OPEN: A-vs-C · live-set treatment in the body · read-only density (drop TEMPO row? per-row strips?). DECISIONS doc.
|
|
10
|
-
*/
|
|
11
|
-
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
12
|
-
import { View, Text } from 'react-native'
|
|
13
|
-
import { ExerciseCardHeading } from './ExerciseCardHeading'
|
|
14
|
-
import { SetTableHeader } from './SetTableHeader'
|
|
15
|
-
import { SetRow, type SetRowProps } from './SetRow'
|
|
16
|
-
import { VelocityStrip } from './VelocityStrip'
|
|
17
|
-
import { type SetStripSet } from './SetStrip'
|
|
18
|
-
import {
|
|
19
|
-
INSET,
|
|
20
|
-
INSET_SHADOW,
|
|
21
|
-
RAISED,
|
|
22
|
-
BORDER_SUBTLE,
|
|
23
|
-
GREEN,
|
|
24
|
-
T_PRIMARY,
|
|
25
|
-
T_SECONDARY,
|
|
26
|
-
T_TERTIARY,
|
|
27
|
-
Page,
|
|
28
|
-
sectionTitle,
|
|
29
|
-
monoTag,
|
|
30
|
-
} from './setHeadingKit'
|
|
31
|
-
|
|
32
|
-
// Per-rep mean velocity that DECAYS across a set (fast → slow) so bar height/color carries shape.
|
|
33
|
-
const decay = (n: number, start: number, span = 0.5) =>
|
|
34
|
-
Array.from({ length: n }, (_, r) => +(start - (span * r) / Math.max(1, n - 1)).toFixed(3))
|
|
35
|
-
|
|
36
|
-
// ---- shared data (real prop shapes) ------------------------------------------------
|
|
37
|
-
// Heading strip (SetStripSet[]): set1 done · set2 active 5/10 · set3 todo.
|
|
38
|
-
const HEADING_STATES: SetStripSet[] = [
|
|
39
|
-
{ status: 'done', velocities: decay(10, 1.05) },
|
|
40
|
-
{ status: 'active', velocities: decay(5, 0.95, 0.3), planned: 10 },
|
|
41
|
-
{ status: 'todo', planned: 10 },
|
|
42
|
-
]
|
|
43
|
-
// Expanded-body per-set rows (real SetRowProps): set 1 done · set 2 LIVE · set 3 todo.
|
|
44
|
-
const BODY_SETS: SetRowProps[] = [
|
|
45
|
-
{
|
|
46
|
-
state: 'done',
|
|
47
|
-
setNumber: 1,
|
|
48
|
-
reps: 10,
|
|
49
|
-
weight: 90,
|
|
50
|
-
rpe: 7.5,
|
|
51
|
-
unit: 'lbs',
|
|
52
|
-
velocities: decay(10, 1.05),
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
state: 'live',
|
|
56
|
-
setNumber: 2,
|
|
57
|
-
unit: 'lbs',
|
|
58
|
-
target: { reps: 10, weight: 90 },
|
|
59
|
-
reps: 10,
|
|
60
|
-
weight: 90,
|
|
61
|
-
velocities: decay(5, 0.95, 0.3),
|
|
62
|
-
},
|
|
63
|
-
{ state: 'todo', setNumber: 3, unit: 'lbs', target: { reps: 10, weight: 90 } },
|
|
64
|
-
]
|
|
65
|
-
|
|
66
|
-
// ---- the real unexpanded rail row, used as the persistent expansion header ---------
|
|
67
|
-
function RailHeader() {
|
|
68
|
-
return (
|
|
69
|
-
<View style={{ position: 'relative', zIndex: 2, backgroundColor: RAISED }}>
|
|
70
|
-
<ExerciseCardHeading
|
|
71
|
-
name="Cable Chest Press"
|
|
72
|
-
sets={3}
|
|
73
|
-
reps={10}
|
|
74
|
-
load={90}
|
|
75
|
-
unit="lbs"
|
|
76
|
-
tempo={[2, 1, 2, 0]}
|
|
77
|
-
indicator="info"
|
|
78
|
-
setStates={HEADING_STATES}
|
|
79
|
-
/>
|
|
80
|
-
</View>
|
|
81
|
-
)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// ---- A · table body: real SetTableHeader + real SetRow (LOCKED: drop PREV, keep strips)
|
|
85
|
-
function TableBody() {
|
|
86
|
-
return (
|
|
87
|
-
<View>
|
|
88
|
-
<SetTableHeader unit="lbs" showPrevious={false} />
|
|
89
|
-
{BODY_SETS.map((s, i) => (
|
|
90
|
-
<SetRow key={i} {...s} />
|
|
91
|
-
))}
|
|
92
|
-
</View>
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// ---- C · embed body: real VelocityStrip (full/expanded) per set + compact caption ---
|
|
97
|
-
const capText = {
|
|
98
|
-
fontFamily: 'Inter, sans-serif',
|
|
99
|
-
fontSize: 11,
|
|
100
|
-
fontWeight: '600' as const,
|
|
101
|
-
color: T_PRIMARY,
|
|
102
|
-
}
|
|
103
|
-
const dimText = { ...capText, color: T_SECONDARY, fontWeight: '500' as const }
|
|
104
|
-
function EmbedSetRow({ s }: { s: SetRowProps }) {
|
|
105
|
-
const live = s.state === 'live'
|
|
106
|
-
const todo = s.state === 'todo'
|
|
107
|
-
const vels = s.state === 'done' || s.state === 'live' ? s.velocities : []
|
|
108
|
-
const rpe = s.state === 'todo' ? null : s.rpe
|
|
109
|
-
return (
|
|
110
|
-
<View
|
|
111
|
-
style={{
|
|
112
|
-
paddingVertical: 7,
|
|
113
|
-
paddingHorizontal: 10,
|
|
114
|
-
marginHorizontal: 2,
|
|
115
|
-
marginBottom: 4,
|
|
116
|
-
borderRadius: 8,
|
|
117
|
-
opacity: todo ? 0.55 : 1,
|
|
118
|
-
...(live
|
|
119
|
-
? {
|
|
120
|
-
backgroundColor: 'rgba(46,213,115,0.06)',
|
|
121
|
-
borderWidth: 1,
|
|
122
|
-
borderColor: 'rgba(46,213,115,0.30)',
|
|
123
|
-
}
|
|
124
|
-
: {}),
|
|
125
|
-
}}
|
|
126
|
-
>
|
|
127
|
-
<View style={{ flexDirection: 'row', alignItems: 'baseline', marginBottom: 6 }}>
|
|
128
|
-
<Text style={{ ...dimText, width: 22, color: T_TERTIARY }}>{s.setNumber}</Text>
|
|
129
|
-
{s.state === 'live' ? (
|
|
130
|
-
<Text style={{ ...capText, color: GREEN, fontWeight: '700' }}>
|
|
131
|
-
{vels.length}/{s.target.reps} × {s.target.weight}
|
|
132
|
-
</Text>
|
|
133
|
-
) : s.state === 'done' ? (
|
|
134
|
-
<Text style={capText}>
|
|
135
|
-
{s.reps} × {s.weight}
|
|
136
|
-
</Text>
|
|
137
|
-
) : (
|
|
138
|
-
<Text style={dimText}>
|
|
139
|
-
{s.target.reps} × {s.target.weight}
|
|
140
|
-
</Text>
|
|
141
|
-
)}
|
|
142
|
-
<View style={{ flex: 1 }} />
|
|
143
|
-
{rpe != null && <Text style={dimText}>RPE {rpe}</Text>}
|
|
144
|
-
{live && <Text style={{ ...capText, color: GREEN, fontWeight: '700' }}>live</Text>}
|
|
145
|
-
</View>
|
|
146
|
-
{vels.length > 0 ? (
|
|
147
|
-
<VelocityStrip velocities={vels} variant="expanded" showInfo={false} />
|
|
148
|
-
) : (
|
|
149
|
-
<View style={{ height: 24, flexDirection: 'row', gap: 2 }}>
|
|
150
|
-
{Array.from({ length: s.state === 'todo' ? s.target.reps : 10 }).map((_, i) => (
|
|
151
|
-
<View
|
|
152
|
-
key={i}
|
|
153
|
-
style={{
|
|
154
|
-
flex: 1,
|
|
155
|
-
height: 6,
|
|
156
|
-
alignSelf: 'flex-end',
|
|
157
|
-
backgroundColor: '#2C2C2C',
|
|
158
|
-
borderRadius: 1,
|
|
159
|
-
opacity: 0.5,
|
|
160
|
-
}}
|
|
161
|
-
/>
|
|
162
|
-
))}
|
|
163
|
-
</View>
|
|
164
|
-
)}
|
|
165
|
-
</View>
|
|
166
|
-
)
|
|
167
|
-
}
|
|
168
|
-
function EmbedBody() {
|
|
169
|
-
return (
|
|
170
|
-
<View style={{ paddingTop: 6 }}>
|
|
171
|
-
{BODY_SETS.map((s, i) => (
|
|
172
|
-
<EmbedSetRow key={i} s={s} />
|
|
173
|
-
))}
|
|
174
|
-
</View>
|
|
175
|
-
)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// ---- expanded item = real rail header + revealed body ------------------------------
|
|
179
|
-
function ExpandedItem({ label, children }: { label: string; children: React.ReactNode }) {
|
|
180
|
-
return (
|
|
181
|
-
<View style={{ gap: 8 }}>
|
|
182
|
-
<Text style={{ ...monoTag, color: T_SECONDARY }}>{label}</Text>
|
|
183
|
-
<View
|
|
184
|
-
style={
|
|
185
|
-
{
|
|
186
|
-
width: 260,
|
|
187
|
-
backgroundColor: INSET,
|
|
188
|
-
boxShadow: INSET_SHADOW,
|
|
189
|
-
borderRadius: 4,
|
|
190
|
-
overflow: 'hidden',
|
|
191
|
-
} as object
|
|
192
|
-
}
|
|
193
|
-
>
|
|
194
|
-
<RailHeader />
|
|
195
|
-
<View
|
|
196
|
-
style={{
|
|
197
|
-
backgroundColor: INSET,
|
|
198
|
-
paddingBottom: 8,
|
|
199
|
-
borderTopWidth: 1,
|
|
200
|
-
borderTopColor: BORDER_SUBTLE,
|
|
201
|
-
}}
|
|
202
|
-
>
|
|
203
|
-
{children}
|
|
204
|
-
</View>
|
|
205
|
-
</View>
|
|
206
|
-
</View>
|
|
207
|
-
)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const meta: Meta = {
|
|
211
|
-
title: 'Lab/Explorations/Workout Expansion',
|
|
212
|
-
parameters: { layout: 'fullscreen' },
|
|
213
|
-
}
|
|
214
|
-
export default meta
|
|
215
|
-
type Story = StoryObj
|
|
216
|
-
|
|
217
|
-
export const DirectionStudy: Story = {
|
|
218
|
-
name: 'Expanded item · A table / C embed-in-bar (real components)',
|
|
219
|
-
render: () => (
|
|
220
|
-
<Page
|
|
221
|
-
title="Workout expansion — direction study (page 2)"
|
|
222
|
-
note="LOCKED (2026-07-10): body = direction A, the SetTableHeader+SetRow table, with PREV dropped (real showPrevious={false}) and the per-row velocity strips kept. C (per-rep VelocityStrip becomes the set row) shown for the record — rejected as too novel; the table already carries velocity shape via the per-row strip. Anchored on the REAL unexpanded rail row (ExerciseCardHeading) as the persistent header; data: set 1 done · set 2 live 5/10 · set 3 upcoming, velocities decaying within a set."
|
|
223
|
-
>
|
|
224
|
-
<View style={{ flexDirection: 'row', gap: 44, alignItems: 'flex-start', flexWrap: 'wrap' }}>
|
|
225
|
-
<View style={{ gap: 12 }}>
|
|
226
|
-
<Text style={sectionTitle}>A · Table (current body)</Text>
|
|
227
|
-
<ExpandedItem label="real SetTableHeader + SetRow">
|
|
228
|
-
<TableBody />
|
|
229
|
-
</ExpandedItem>
|
|
230
|
-
</View>
|
|
231
|
-
<View style={{ gap: 12 }}>
|
|
232
|
-
<Text style={sectionTitle}>C · Embed in the bar</Text>
|
|
233
|
-
<ExpandedItem label="real VelocityStrip (full) + caption">
|
|
234
|
-
<EmbedBody />
|
|
235
|
-
</ExpandedItem>
|
|
236
|
-
</View>
|
|
237
|
-
</View>
|
|
238
|
-
</Page>
|
|
239
|
-
),
|
|
240
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
-
import { View, Text } from 'react-native'
|
|
3
|
-
import { DashboardShell } from './DashboardShell'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* `Pages/DashboardShell` — the wall-dashboard chrome as one registered surface.
|
|
7
|
-
* Composes the shell-nav island (SideNav + TopBar and everything they pull in) over a
|
|
8
|
-
* `children` content slot, so the dashboard app mounts a single component.
|
|
9
|
-
*/
|
|
10
|
-
const meta: Meta<typeof DashboardShell> = {
|
|
11
|
-
title: 'Pages/DashboardShell',
|
|
12
|
-
component: DashboardShell,
|
|
13
|
-
tags: ['autodocs'],
|
|
14
|
-
parameters: {
|
|
15
|
-
layout: 'fullscreen',
|
|
16
|
-
docs: {
|
|
17
|
-
description: {
|
|
18
|
-
component:
|
|
19
|
-
'**Page shell.** The wall-dashboard chrome. Composes ' +
|
|
20
|
-
'[SideNav](?path=/docs/shell-sidenav--docs) + ' +
|
|
21
|
-
'[TopBar](?path=/docs/shell-topbar--docs) — which pulls in DeviceMenu, DeviceRow, ' +
|
|
22
|
-
'DeviceIndicator, SessionStatePill, BrandLockup, DateTime and Divider — over a ' +
|
|
23
|
-
'`children` content slot. Mount this instead of re-assembling the chrome per view.',
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
argTypes: {
|
|
28
|
-
state: { control: 'select', options: ['live', 'rest', 'idle'] },
|
|
29
|
-
activeKey: { control: 'select', options: ['live', 'review', 'program', 'body'] },
|
|
30
|
-
liveKey: { control: 'select', options: [null, 'live', 'review', 'program', 'body'] },
|
|
31
|
-
onNavigate: { control: false },
|
|
32
|
-
onSelectDevice: { control: false },
|
|
33
|
-
},
|
|
34
|
-
decorators: [
|
|
35
|
-
(Story) => (
|
|
36
|
-
<View style={{ height: '100vh' as unknown as number, backgroundColor: '#0E0E0E' }}>
|
|
37
|
-
<Story />
|
|
38
|
-
</View>
|
|
39
|
-
),
|
|
40
|
-
],
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export default meta
|
|
44
|
-
type Story = StoryObj<typeof DashboardShell>
|
|
45
|
-
|
|
46
|
-
export const Default: Story = {
|
|
47
|
-
args: { activeKey: 'live', state: 'live' },
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export const WithContent: Story = {
|
|
51
|
-
args: { activeKey: 'review', state: 'rest', liveKey: 'live' },
|
|
52
|
-
render: (args) => (
|
|
53
|
-
<DashboardShell {...args}>
|
|
54
|
-
<View style={{ flex: 1, padding: 28 }}>
|
|
55
|
-
<Text style={{ color: '#E5E5E5', fontSize: 22, fontWeight: '700' }}>Review</Text>
|
|
56
|
-
<Text style={{ color: '#8A8A8A', fontSize: 13, marginTop: 6 }}>
|
|
57
|
-
A page mounts its content here; the shell keeps the nav + top-bar chrome persistent.
|
|
58
|
-
</Text>
|
|
59
|
-
</View>
|
|
60
|
-
</DashboardShell>
|
|
61
|
-
),
|
|
62
|
-
parameters: {
|
|
63
|
-
docs: { description: { story: 'The shell with a page mounted in its content slot.' } },
|
|
64
|
-
},
|
|
65
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react'
|
|
2
|
-
import { View, Text } from 'react-native'
|
|
3
|
-
import { cn } from '../../utils/cn'
|
|
4
|
-
import { Surface } from '../ui/surface'
|
|
5
|
-
import { SideNav, type SideNavItem } from './SideNav'
|
|
6
|
-
import { TopBar } from './TopBar'
|
|
7
|
-
import { type Device } from './DeviceRow'
|
|
8
|
-
import { type SessionState } from './SessionStatePill'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* `DashboardShell` — the wall-dashboard chrome: a persistent {@link SideNav} rail +
|
|
12
|
-
* {@link TopBar} over a main content region. A thin frame that wires the shell-nav
|
|
13
|
-
* organisms together and exposes a `children` content slot, so the dashboard app
|
|
14
|
-
* mounts one component instead of re-assembling the chrome. Driven entirely by props.
|
|
15
|
-
*/
|
|
16
|
-
export interface DashboardShellProps {
|
|
17
|
-
/** Active nav category key. */
|
|
18
|
-
activeKey?: string
|
|
19
|
-
/** Nav categories, top → bottom. Defaults to SideNav's four dashboard categories. */
|
|
20
|
-
navItems?: SideNavItem[]
|
|
21
|
-
/** A category with off-view live activity → a quiet cue on that item. */
|
|
22
|
-
liveKey?: string | null
|
|
23
|
-
/** Global session state → the TopBar status pill. */
|
|
24
|
-
state?: SessionState
|
|
25
|
-
/** Connected devices → the TopBar connection glyph + dropdown. */
|
|
26
|
-
devices?: Device[]
|
|
27
|
-
/** TopBar brand subtitle. */
|
|
28
|
-
subtitle?: string
|
|
29
|
-
onNavigate?: (key: string) => void
|
|
30
|
-
onSelectDevice?: (device: Device) => void
|
|
31
|
-
/** Main content region. A placeholder renders when omitted. */
|
|
32
|
-
children?: ReactNode
|
|
33
|
-
className?: string
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const DEMO_DEVICES: Device[] = [
|
|
37
|
-
{ id: 'Voltra-A3F2', nickname: 'Left Cable', slot: 'L', state: 'connected' },
|
|
38
|
-
{ id: 'Voltra-9B1C', nickname: 'Right Cable', slot: 'R', state: 'connected' },
|
|
39
|
-
]
|
|
40
|
-
|
|
41
|
-
function ContentPlaceholder() {
|
|
42
|
-
return (
|
|
43
|
-
<View className="flex-1 items-center justify-center">
|
|
44
|
-
<Text className="font-heading text-sm text-text-tertiary">main content region</Text>
|
|
45
|
-
</View>
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function DashboardShell({
|
|
50
|
-
activeKey = 'live',
|
|
51
|
-
navItems,
|
|
52
|
-
liveKey = null,
|
|
53
|
-
state = 'live',
|
|
54
|
-
devices = DEMO_DEVICES,
|
|
55
|
-
subtitle = 'wall dashboard',
|
|
56
|
-
onNavigate,
|
|
57
|
-
onSelectDevice,
|
|
58
|
-
children,
|
|
59
|
-
className,
|
|
60
|
-
}: DashboardShellProps) {
|
|
61
|
-
return (
|
|
62
|
-
// Column: the TopBar spans the FULL width across the top, and the SideNav sits BELOW it
|
|
63
|
-
// in the content row (not a full-height left rail). This keeps the brand/status band
|
|
64
|
-
// unbroken edge-to-edge and lets the nav align under it. The shell is the outermost
|
|
65
|
-
// Surface — it owns the base plane and seeds the on-surface colour context (mode) for
|
|
66
|
-
// the whole dashboard tree.
|
|
67
|
-
<Surface level="base" className={cn('flex-1', className)}>
|
|
68
|
-
<TopBar state={state} devices={devices} subtitle={subtitle} onSelectDevice={onSelectDevice} />
|
|
69
|
-
<View className="flex-1 flex-row">
|
|
70
|
-
<SideNav activeKey={activeKey} items={navItems} liveKey={liveKey} onNavigate={onNavigate} />
|
|
71
|
-
<View className="flex-1">{children ?? <ContentPlaceholder />}</View>
|
|
72
|
-
</View>
|
|
73
|
-
</Surface>
|
|
74
|
-
)
|
|
75
|
-
}
|