@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
package/dist/bodymap.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { useMemo, useState, useEffect, Fragment
|
|
1
|
+
import { createContext, useMemo, useState, useEffect, Fragment, useContext } from 'react';
|
|
2
2
|
import { Platform, Animated, Easing, View, Text, Pressable, ScrollView } from 'react-native';
|
|
3
3
|
import BodyHighlighter from 'react-native-body-highlighter';
|
|
4
4
|
import { clsx } from 'clsx';
|
|
5
5
|
import { twMerge } from 'tailwind-merge';
|
|
6
|
-
import { Fragment, jsx as jsx$1, jsxs as jsxs$1 } from 'react/jsx-runtime';
|
|
6
|
+
import { Fragment as Fragment$1, jsx as jsx$1, jsxs as jsxs$1 } from 'react/jsx-runtime';
|
|
7
7
|
|
|
8
8
|
// src/components/custom/Workout/BodyMap.tsx
|
|
9
9
|
function cn(...inputs) {
|
|
@@ -13,6 +13,7 @@ function cn(...inputs) {
|
|
|
13
13
|
// src/theme/tokens/primitives.ts
|
|
14
14
|
var primitiveColors = {
|
|
15
15
|
white: "#FFFFFF"};
|
|
16
|
+
var alertRedVivid = "#FF4757";
|
|
16
17
|
var greyRamp = {
|
|
17
18
|
50: "#F9F6F3",
|
|
18
19
|
// L*97.0 W6
|
|
@@ -135,12 +136,16 @@ var semanticColorsLight = {
|
|
|
135
136
|
"brand-primary-light": primitiveRamps.orange[300],
|
|
136
137
|
"brand-primary-dark": primitiveRamps.orange[500],
|
|
137
138
|
"brand-primary-subtle": "rgba(255, 121, 0, 0.08)",
|
|
139
|
+
"brand-primary-muted": "rgba(255, 121, 0, 0.30)",
|
|
140
|
+
"brand-primary-strong": "rgba(255, 121, 0, 0.50)",
|
|
138
141
|
"brand-primary-hover": primitiveRamps.orange[500],
|
|
139
142
|
"brand-primary-active": primitiveRamps.orange[600],
|
|
140
143
|
"brand-secondary": primitiveRamps.cyan[600],
|
|
141
144
|
"brand-secondary-light": primitiveRamps.cyan[500],
|
|
142
145
|
"brand-secondary-dark": primitiveRamps.cyan[700],
|
|
143
146
|
"brand-secondary-subtle": "rgba(48, 123, 155, 0.08)",
|
|
147
|
+
"brand-secondary-muted": "rgba(48, 123, 155, 0.30)",
|
|
148
|
+
"brand-secondary-strong": "rgba(48, 123, 155, 0.50)",
|
|
144
149
|
"brand-secondary-hover": primitiveRamps.cyan[700],
|
|
145
150
|
"brand-secondary-active": primitiveRamps.cyan[800],
|
|
146
151
|
// Text on brand backgrounds (on-*)
|
|
@@ -151,6 +156,8 @@ var semanticColorsLight = {
|
|
|
151
156
|
"status-success-light": primitiveRamps.green[200],
|
|
152
157
|
"status-success-dark": primitiveRamps.green[600],
|
|
153
158
|
"status-success-subtle": primitiveRamps.green[50],
|
|
159
|
+
"status-success-muted": "rgba(46, 213, 115, 0.30)",
|
|
160
|
+
"status-success-strong": "rgba(46, 213, 115, 0.50)",
|
|
154
161
|
// Live-session accent — its OWN role, decoupled from success so the two can diverge
|
|
155
162
|
"status-live": primitiveRamps.green[300],
|
|
156
163
|
"status-live-muted": primitiveRamps.green[500],
|
|
@@ -158,19 +165,27 @@ var semanticColorsLight = {
|
|
|
158
165
|
"status-error-light": primitiveRamps.red[500],
|
|
159
166
|
"status-error-dark": primitiveRamps.red[700],
|
|
160
167
|
"status-error-subtle": primitiveRamps.red[50],
|
|
161
|
-
"status-error-
|
|
162
|
-
|
|
168
|
+
"status-error-muted": "rgba(209, 67, 67, 0.30)",
|
|
169
|
+
"status-error-strong": "rgba(209, 67, 67, 0.50)",
|
|
170
|
+
"status-error-vivid": alertRedVivid,
|
|
171
|
+
// NOT red[600], that is status-error
|
|
163
172
|
"status-error-vivid-light": primitiveRamps.red[500],
|
|
164
173
|
"status-error-vivid-dark": primitiveRamps.red[700],
|
|
165
174
|
"status-error-vivid-subtle": "rgba(255, 71, 87, 0.12)",
|
|
175
|
+
"status-error-vivid-muted": "rgba(255, 71, 87, 0.30)",
|
|
176
|
+
"status-error-vivid-strong": "rgba(255, 71, 87, 0.50)",
|
|
166
177
|
"status-warning": primitiveRamps.amber[300],
|
|
167
178
|
"status-warning-light": primitiveRamps.amber[200],
|
|
168
179
|
"status-warning-dark": primitiveRamps.amber[500],
|
|
169
180
|
"status-warning-subtle": primitiveRamps.amber[50],
|
|
181
|
+
"status-warning-muted": "rgba(249, 180, 21, 0.30)",
|
|
182
|
+
"status-warning-strong": "rgba(249, 180, 21, 0.50)",
|
|
170
183
|
"status-info": primitiveRamps.blue[500],
|
|
171
184
|
"status-info-light": primitiveRamps.blue[300],
|
|
172
185
|
"status-info-dark": primitiveRamps.blue[600],
|
|
173
186
|
"status-info-subtle": primitiveRamps.blue[50],
|
|
187
|
+
"status-info-muted": "rgba(33, 150, 243, 0.30)",
|
|
188
|
+
"status-info-strong": "rgba(33, 150, 243, 0.50)",
|
|
174
189
|
// Text on status backgrounds (on-status-*)
|
|
175
190
|
"on-status-success": primitiveColors.white,
|
|
176
191
|
"on-status-error": primitiveColors.white,
|
|
@@ -265,7 +280,7 @@ var semanticColorsLight = {
|
|
|
265
280
|
"interactive-disabled": "rgba(55, 65, 81, 0.12)",
|
|
266
281
|
"interactive-disabled-text": "rgba(55, 65, 81, 0.26)",
|
|
267
282
|
// Divider
|
|
268
|
-
|
|
283
|
+
divider: "#E8E9EB",
|
|
269
284
|
// Avatar default
|
|
270
285
|
"avatar-background": greyRamp[600],
|
|
271
286
|
"avatar-text": primitiveColors.white
|
|
@@ -276,12 +291,16 @@ var semanticColorsDark = {
|
|
|
276
291
|
"brand-primary-light": primitiveRamps.orange[300],
|
|
277
292
|
"brand-primary-dark": primitiveRamps.orange[500],
|
|
278
293
|
"brand-primary-subtle": "rgba(255, 121, 0, 0.12)",
|
|
294
|
+
"brand-primary-muted": "rgba(255, 121, 0, 0.30)",
|
|
295
|
+
"brand-primary-strong": "rgba(255, 121, 0, 0.50)",
|
|
279
296
|
"brand-primary-hover": primitiveRamps.orange[300],
|
|
280
297
|
"brand-primary-active": primitiveRamps.orange[200],
|
|
281
298
|
"brand-secondary": primitiveRamps.cyan[600],
|
|
282
299
|
"brand-secondary-light": primitiveRamps.cyan[500],
|
|
283
300
|
"brand-secondary-dark": primitiveRamps.cyan[700],
|
|
284
301
|
"brand-secondary-subtle": "rgba(48, 123, 155, 0.12)",
|
|
302
|
+
"brand-secondary-muted": "rgba(48, 123, 155, 0.30)",
|
|
303
|
+
"brand-secondary-strong": "rgba(48, 123, 155, 0.50)",
|
|
285
304
|
"brand-secondary-hover": primitiveRamps.cyan[500],
|
|
286
305
|
"brand-secondary-active": primitiveRamps.cyan[400],
|
|
287
306
|
// Text on brand backgrounds
|
|
@@ -292,6 +311,8 @@ var semanticColorsDark = {
|
|
|
292
311
|
"status-success-light": primitiveRamps.green[200],
|
|
293
312
|
"status-success-dark": primitiveRamps.green[600],
|
|
294
313
|
"status-success-subtle": "rgba(46, 213, 115, 0.12)",
|
|
314
|
+
"status-success-muted": "rgba(46, 213, 115, 0.30)",
|
|
315
|
+
"status-success-strong": "rgba(46, 213, 115, 0.50)",
|
|
295
316
|
// Live-session accent — its OWN role, decoupled from success so the two can diverge
|
|
296
317
|
"status-live": primitiveRamps.green[300],
|
|
297
318
|
"status-live-muted": primitiveRamps.green[500],
|
|
@@ -299,18 +320,26 @@ var semanticColorsDark = {
|
|
|
299
320
|
"status-error-light": primitiveRamps.red[500],
|
|
300
321
|
"status-error-dark": primitiveRamps.red[700],
|
|
301
322
|
"status-error-subtle": "rgba(209, 67, 67, 0.12)",
|
|
302
|
-
"status-error-
|
|
323
|
+
"status-error-muted": "rgba(209, 67, 67, 0.30)",
|
|
324
|
+
"status-error-strong": "rgba(209, 67, 67, 0.50)",
|
|
325
|
+
"status-error-vivid": alertRedVivid,
|
|
303
326
|
"status-error-vivid-light": primitiveRamps.red[500],
|
|
304
327
|
"status-error-vivid-dark": primitiveRamps.red[700],
|
|
305
328
|
"status-error-vivid-subtle": "rgba(255, 71, 87, 0.12)",
|
|
329
|
+
"status-error-vivid-muted": "rgba(255, 71, 87, 0.30)",
|
|
330
|
+
"status-error-vivid-strong": "rgba(255, 71, 87, 0.50)",
|
|
306
331
|
"status-warning": primitiveRamps.amber[300],
|
|
307
332
|
"status-warning-light": primitiveRamps.amber[200],
|
|
308
333
|
"status-warning-dark": primitiveRamps.amber[500],
|
|
309
334
|
"status-warning-subtle": "rgba(249, 180, 21, 0.12)",
|
|
335
|
+
"status-warning-muted": "rgba(249, 180, 21, 0.30)",
|
|
336
|
+
"status-warning-strong": "rgba(249, 180, 21, 0.50)",
|
|
310
337
|
"status-info": primitiveRamps.blue[500],
|
|
311
338
|
"status-info-light": primitiveRamps.blue[300],
|
|
312
339
|
"status-info-dark": primitiveRamps.blue[600],
|
|
313
340
|
"status-info-subtle": "rgba(33, 150, 243, 0.12)",
|
|
341
|
+
"status-info-muted": "rgba(33, 150, 243, 0.30)",
|
|
342
|
+
"status-info-strong": "rgba(33, 150, 243, 0.50)",
|
|
314
343
|
// Text on status backgrounds
|
|
315
344
|
"on-status-success": primitiveColors.white,
|
|
316
345
|
"on-status-error": primitiveColors.white,
|
|
@@ -450,7 +479,7 @@ var semanticColorsDark = {
|
|
|
450
479
|
"interactive-disabled": "rgba(255, 255, 255, 0.12)",
|
|
451
480
|
"interactive-disabled-text": "rgba(255, 255, 255, 0.26)",
|
|
452
481
|
// Divider
|
|
453
|
-
|
|
482
|
+
divider: "rgba(255, 255, 255, 0.09)",
|
|
454
483
|
// Avatar default
|
|
455
484
|
"avatar-background": greyRamp[700],
|
|
456
485
|
"avatar-text": primitiveColors.white
|
|
@@ -464,6 +493,150 @@ function resolveColor(token, mode = "dark") {
|
|
|
464
493
|
return Platform.OS === "web" ? `var(--color-${token})` : getSemanticColors(mode)[token];
|
|
465
494
|
}
|
|
466
495
|
|
|
496
|
+
// src/theme/color-utils.ts
|
|
497
|
+
function hexToRgb(hex) {
|
|
498
|
+
const cleaned = hex.replace("#", "");
|
|
499
|
+
let r, g, b;
|
|
500
|
+
if (cleaned.length === 3) {
|
|
501
|
+
r = parseInt(cleaned[0] + cleaned[0], 16);
|
|
502
|
+
g = parseInt(cleaned[1] + cleaned[1], 16);
|
|
503
|
+
b = parseInt(cleaned[2] + cleaned[2], 16);
|
|
504
|
+
} else if (cleaned.length === 6) {
|
|
505
|
+
r = parseInt(cleaned.slice(0, 2), 16);
|
|
506
|
+
g = parseInt(cleaned.slice(2, 4), 16);
|
|
507
|
+
b = parseInt(cleaned.slice(4, 6), 16);
|
|
508
|
+
} else {
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
return { r, g, b };
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// src/theme/materials.ts
|
|
515
|
+
var c = getSemanticColors("dark");
|
|
516
|
+
function insetWell(tone = c["surface-input"]) {
|
|
517
|
+
return {
|
|
518
|
+
backgroundColor: tone,
|
|
519
|
+
boxShadow: "inset 0 2px 6px rgba(0,0,0,0.55), inset 0 -1px 0 rgba(255,255,255,0.12)"
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
var FLOATING_LIFT_MIN = 4;
|
|
523
|
+
var LIFT_RIM_ALPHA = { dark: 0.12, light: 0.9 };
|
|
524
|
+
var AMBIENT = {
|
|
525
|
+
1: [
|
|
526
|
+
{ y: 1, blur: 2, alpha: 0.35 },
|
|
527
|
+
{ y: 2, blur: 6, alpha: 0.3 }
|
|
528
|
+
],
|
|
529
|
+
2: [
|
|
530
|
+
{ y: 1, blur: 2, alpha: 0.35 },
|
|
531
|
+
{ y: 4, blur: 12, alpha: 0.32 }
|
|
532
|
+
],
|
|
533
|
+
3: [
|
|
534
|
+
{ y: 2, blur: 4, alpha: 0.35 },
|
|
535
|
+
{ y: 8, blur: 22, alpha: 0.35 }
|
|
536
|
+
],
|
|
537
|
+
4: [
|
|
538
|
+
{ y: 1, blur: 2, alpha: 0.35 },
|
|
539
|
+
{ y: 10, blur: 24, alpha: 0.3 },
|
|
540
|
+
{ y: 24, blur: 48, alpha: 0.2 }
|
|
541
|
+
],
|
|
542
|
+
5: [
|
|
543
|
+
{ y: 2, blur: 4, alpha: 0.4 },
|
|
544
|
+
{ y: 16, blur: 32, alpha: 0.35 },
|
|
545
|
+
{ y: 32, blur: 64, alpha: 0.25 }
|
|
546
|
+
]
|
|
547
|
+
};
|
|
548
|
+
var AMBIENT_ALPHA_SCALE = { dark: 1, light: 0.4 };
|
|
549
|
+
function ambientLayers(step, mode) {
|
|
550
|
+
const scale = AMBIENT_ALPHA_SCALE[mode];
|
|
551
|
+
return AMBIENT[step].map(
|
|
552
|
+
({ y, blur, alpha: alpha2 }) => `0 ${y}px ${blur}px rgba(0,0,0,${(alpha2 * scale).toFixed(2)})`
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
function liftShadow(step, mode = "dark", opts = {}) {
|
|
556
|
+
const rim = opts.rim ?? LIFT_RIM_ALPHA[mode];
|
|
557
|
+
const layers = ambientLayers(step, mode);
|
|
558
|
+
if (rim > 0) layers.unshift(`inset 0 1px 0 rgba(255,255,255,${rim.toFixed(2)})`);
|
|
559
|
+
return layers.join(", ");
|
|
560
|
+
}
|
|
561
|
+
function liftStyle(step, mode = "dark", opts = {}) {
|
|
562
|
+
const deepest = AMBIENT[step][AMBIENT[step].length - 1];
|
|
563
|
+
return Platform.select({
|
|
564
|
+
web: { boxShadow: liftShadow(step, mode, opts) },
|
|
565
|
+
default: {
|
|
566
|
+
shadowColor: "#000",
|
|
567
|
+
shadowOffset: { width: 0, height: Math.round(deepest.y / 2) },
|
|
568
|
+
shadowOpacity: deepest.alpha * AMBIENT_ALPHA_SCALE[mode],
|
|
569
|
+
shadowRadius: deepest.blur / 2,
|
|
570
|
+
elevation: step
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// src/theme/surface-planes.ts
|
|
576
|
+
var SURFACE_LEVEL_TOKEN = {
|
|
577
|
+
frame: "background-frame",
|
|
578
|
+
background: "background-base",
|
|
579
|
+
base: "surface-base",
|
|
580
|
+
elevated: "surface-elevated",
|
|
581
|
+
raised: "surface-raised",
|
|
582
|
+
overlay: "surface-overlay"
|
|
583
|
+
};
|
|
584
|
+
var PLANE_ORDER = [
|
|
585
|
+
"frame",
|
|
586
|
+
"background",
|
|
587
|
+
"base",
|
|
588
|
+
"elevated",
|
|
589
|
+
"raised",
|
|
590
|
+
"overlay"
|
|
591
|
+
];
|
|
592
|
+
function surfaceBackground(level, mode) {
|
|
593
|
+
return getSemanticColors(mode)[SURFACE_LEVEL_TOKEN[level]];
|
|
594
|
+
}
|
|
595
|
+
function stepPlane(from, delta) {
|
|
596
|
+
const index = PLANE_ORDER.indexOf(from);
|
|
597
|
+
const clamped = Math.min(PLANE_ORDER.length - 1, Math.max(0, index + delta));
|
|
598
|
+
return PLANE_ORDER[clamped];
|
|
599
|
+
}
|
|
600
|
+
function pressedLevel(parent) {
|
|
601
|
+
return stepPlane(parent, -1);
|
|
602
|
+
}
|
|
603
|
+
function raisedLevel(parent, steps) {
|
|
604
|
+
return stepPlane(parent, Math.max(0, steps));
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// src/theme/elevation.ts
|
|
608
|
+
var FLOATING_ELEVATION_MIN = FLOATING_LIFT_MIN;
|
|
609
|
+
function getPressedRecessShadow(fillColor, _mode = "dark") {
|
|
610
|
+
const { boxShadow } = insetWell(fillColor);
|
|
611
|
+
return Platform.select({
|
|
612
|
+
web: { boxShadow },
|
|
613
|
+
default: {}
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
var glowConfig = {
|
|
617
|
+
tight: { blur: 4, spread: 0, opacity: 0.4 },
|
|
618
|
+
subtle: { blur: 12, spread: 0, opacity: 0.25 },
|
|
619
|
+
medium: { blur: 20, spread: 2, opacity: 0.4 },
|
|
620
|
+
strong: { blur: 30, spread: 4, opacity: 0.55 }
|
|
621
|
+
};
|
|
622
|
+
function getGlowShadow(color, intensity = "medium") {
|
|
623
|
+
const config = glowConfig[intensity];
|
|
624
|
+
const rgb = hexToRgb(color);
|
|
625
|
+
if (!rgb) return {};
|
|
626
|
+
return Platform.select({
|
|
627
|
+
web: {
|
|
628
|
+
boxShadow: `0 0 ${config.blur}px ${config.spread}px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${config.opacity})`
|
|
629
|
+
},
|
|
630
|
+
default: {
|
|
631
|
+
shadowColor: color,
|
|
632
|
+
shadowOffset: { width: 0, height: 0 },
|
|
633
|
+
shadowOpacity: config.opacity,
|
|
634
|
+
shadowRadius: config.blur / 2,
|
|
635
|
+
elevation: 0
|
|
636
|
+
}
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
|
|
467
640
|
// src/theme/workout-tokens.ts
|
|
468
641
|
var WORKOUT_TOKENS = {
|
|
469
642
|
// BodyMap volume heatmap — the canonical `divergingScale` (under → optimal →
|
|
@@ -791,7 +964,8 @@ function BodyMap({
|
|
|
791
964
|
alignSelf: "center",
|
|
792
965
|
transform: [{ scale }]
|
|
793
966
|
},
|
|
794
|
-
|
|
967
|
+
// The highlight halo is emphasis, not depth.
|
|
968
|
+
glowColor ? getGlowShadow(glowColor, "medium") : void 0
|
|
795
969
|
],
|
|
796
970
|
"aria-hidden": true,
|
|
797
971
|
accessibilityElementsHidden: true,
|
|
@@ -953,6 +1127,17 @@ var colorStyles = {
|
|
|
953
1127
|
info: "bg-status-info",
|
|
954
1128
|
"error-vivid": "bg-status-error-vivid"
|
|
955
1129
|
};
|
|
1130
|
+
var t = getSemanticColors("dark");
|
|
1131
|
+
var glowColors = {
|
|
1132
|
+
default: greyRamp[500],
|
|
1133
|
+
primary: t["brand-primary"],
|
|
1134
|
+
success: t["status-success"],
|
|
1135
|
+
live: t["status-live"],
|
|
1136
|
+
error: t["status-error"],
|
|
1137
|
+
warning: t["status-warning"],
|
|
1138
|
+
info: t["status-info"],
|
|
1139
|
+
"error-vivid": t["status-error-vivid"]
|
|
1140
|
+
};
|
|
956
1141
|
function Indicator({
|
|
957
1142
|
size = "sm",
|
|
958
1143
|
color = "default",
|
|
@@ -990,11 +1175,7 @@ function Indicator({
|
|
|
990
1175
|
)
|
|
991
1176
|
] });
|
|
992
1177
|
}
|
|
993
|
-
const
|
|
994
|
-
...typeof style === "object" ? style : {},
|
|
995
|
-
...colorStyle ?? {},
|
|
996
|
-
...glow && customColor ? { boxShadow: `0 0 6px ${customColor}` } : {}
|
|
997
|
-
};
|
|
1178
|
+
const glowStyle = glow ? getGlowShadow(customColor ?? glowColors[color], "subtle") : null;
|
|
998
1179
|
return /* @__PURE__ */ jsx(
|
|
999
1180
|
View,
|
|
1000
1181
|
{
|
|
@@ -1004,54 +1185,165 @@ function Indicator({
|
|
|
1004
1185
|
colorClass,
|
|
1005
1186
|
pulseMode === "opacity" && "animate-pulse",
|
|
1006
1187
|
ring && "border-2 border-background-base",
|
|
1007
|
-
glow && !customColor && (color === "success" || color === "live") && "shadow-[0_0_6px_rgba(46,213,115,0.6)]",
|
|
1008
|
-
glow && !customColor && color === "error" && "shadow-[0_0_6px_rgba(239,68,68,0.6)]",
|
|
1009
|
-
glow && !customColor && color === "warning" && "shadow-[0_0_6px_rgba(245,158,11,0.6)]",
|
|
1010
|
-
glow && !customColor && color === "primary" && "shadow-[0_0_6px_rgba(255,121,0,0.6)]",
|
|
1011
|
-
glow && !customColor && color === "error-vivid" && "shadow-[0_0_6px_rgba(255,71,87,0.6)]",
|
|
1012
1188
|
className
|
|
1013
1189
|
),
|
|
1014
|
-
style:
|
|
1190
|
+
style: [style, colorStyle, glowStyle],
|
|
1015
1191
|
...props
|
|
1016
1192
|
}
|
|
1017
1193
|
);
|
|
1018
1194
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1195
|
+
var colorToTone = {
|
|
1196
|
+
default: "neutral",
|
|
1197
|
+
primary: "brand",
|
|
1198
|
+
secondary: "brand-secondary",
|
|
1199
|
+
success: "success",
|
|
1200
|
+
error: "error",
|
|
1201
|
+
warning: "warning",
|
|
1202
|
+
info: "info"
|
|
1203
|
+
};
|
|
1204
|
+
var toneStyles = {
|
|
1022
1205
|
solid: {
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
secondary: "bg-brand-secondary text-text-inverse",
|
|
1026
|
-
success: "bg-status-success text-text-inverse",
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
info: "bg-status-info text-text-inverse"
|
|
1206
|
+
neutral: "bg-hairline-strong border-transparent text-text-inverse",
|
|
1207
|
+
brand: "bg-brand-primary border-transparent text-text-inverse",
|
|
1208
|
+
"brand-secondary": "bg-brand-secondary border-transparent text-text-inverse",
|
|
1209
|
+
success: "bg-status-success border-transparent text-text-inverse",
|
|
1210
|
+
warning: "bg-status-warning border-transparent text-text-inverse",
|
|
1211
|
+
error: "bg-status-error border-transparent text-text-inverse",
|
|
1212
|
+
info: "bg-status-info border-transparent text-text-inverse"
|
|
1030
1213
|
},
|
|
1031
1214
|
subtle: {
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1215
|
+
// Alpha-white rather than a ramp step: a pill sits on whatever plane its
|
|
1216
|
+
// host is, and an alpha fill composites by the same amount on all of them.
|
|
1217
|
+
// A `surface-*` fill would vanish on the plane it names. Borderless like the
|
|
1218
|
+
// six coloured tones — the fill carries the capsule, not a ring.
|
|
1219
|
+
neutral: "bg-hairline-subtle border-transparent text-text-secondary",
|
|
1220
|
+
brand: "bg-brand-primary-subtle border-transparent text-brand-primary",
|
|
1221
|
+
"brand-secondary": "bg-brand-secondary-subtle border-transparent text-brand-secondary",
|
|
1222
|
+
success: "bg-status-success-subtle border-transparent text-status-success",
|
|
1223
|
+
warning: "bg-status-warning-subtle border-transparent text-status-warning",
|
|
1224
|
+
error: "bg-status-error-subtle border-transparent text-status-error",
|
|
1225
|
+
info: "bg-status-info-subtle border-transparent text-status-info"
|
|
1039
1226
|
},
|
|
1040
1227
|
outline: {
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
secondary: "border
|
|
1044
|
-
success: "border
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
info: "border
|
|
1228
|
+
neutral: "border-hairline text-text-secondary",
|
|
1229
|
+
brand: "border-brand-primary text-brand-primary",
|
|
1230
|
+
"brand-secondary": "border-brand-secondary text-brand-secondary",
|
|
1231
|
+
success: "border-status-success text-status-success",
|
|
1232
|
+
warning: "border-status-warning text-status-warning",
|
|
1233
|
+
error: "border-status-error text-status-error",
|
|
1234
|
+
info: "border-status-info text-status-info"
|
|
1048
1235
|
}
|
|
1049
1236
|
};
|
|
1237
|
+
var dotToneStyles = {
|
|
1238
|
+
neutral: "bg-text-tertiary",
|
|
1239
|
+
brand: "bg-brand-primary",
|
|
1240
|
+
"brand-secondary": "bg-brand-secondary",
|
|
1241
|
+
success: "bg-status-success",
|
|
1242
|
+
warning: "bg-status-warning",
|
|
1243
|
+
error: "bg-status-error",
|
|
1244
|
+
info: "bg-status-info"
|
|
1245
|
+
};
|
|
1050
1246
|
var sizeStyles2 = {
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1247
|
+
xs: { container: "px-1 py-px", text: "text-3xs" },
|
|
1248
|
+
sm: { container: "px-2 py-0.5", text: "text-2xs" },
|
|
1249
|
+
md: { container: "px-2.5 py-1", text: "text-xs" },
|
|
1250
|
+
lg: { container: "px-3 py-1.5", text: "text-sm" },
|
|
1251
|
+
xl: { container: "px-4 py-2", text: "text-base" }
|
|
1252
|
+
};
|
|
1253
|
+
function PillDot({ tone, testID }) {
|
|
1254
|
+
return /* @__PURE__ */ jsx(
|
|
1255
|
+
View,
|
|
1256
|
+
{
|
|
1257
|
+
className: cn("w-1.5 h-1.5 rounded-full shrink-0", dotToneStyles[tone]),
|
|
1258
|
+
accessibilityElementsHidden: true,
|
|
1259
|
+
testID: testID ? `${testID}-dot` : "pill-dot"
|
|
1260
|
+
}
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
function containerClasses(p, tone) {
|
|
1264
|
+
return cn(
|
|
1265
|
+
"flex-row items-center gap-1 border self-start shrink-0",
|
|
1266
|
+
p.rounded === false ? "rounded" : "rounded-full",
|
|
1267
|
+
toneStyles[p.variant ?? "subtle"][tone],
|
|
1268
|
+
sizeStyles2[p.size ?? "sm"].container,
|
|
1269
|
+
p.isDisabled && "opacity-50",
|
|
1270
|
+
p.className
|
|
1271
|
+
);
|
|
1272
|
+
}
|
|
1273
|
+
function PillContent({ tone, ...p }) {
|
|
1274
|
+
const textClasses = cn(
|
|
1275
|
+
"font-heading font-semibold text-inherit",
|
|
1276
|
+
sizeStyles2[p.size ?? "sm"].text,
|
|
1277
|
+
p.textClassName
|
|
1278
|
+
);
|
|
1279
|
+
const slot = p.leading ?? p.leftElement;
|
|
1280
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1281
|
+
slot === "dot" ? /* @__PURE__ */ jsx(PillDot, { tone: p.dotTone ?? tone, testID: p.testID }) : slot,
|
|
1282
|
+
typeof p.children === "string" ? /* @__PURE__ */ jsx(Text, { className: textClasses, children: p.children }) : p.children,
|
|
1283
|
+
p.trailing
|
|
1284
|
+
] });
|
|
1285
|
+
}
|
|
1286
|
+
function Pill(props) {
|
|
1287
|
+
const {
|
|
1288
|
+
variant,
|
|
1289
|
+
tone,
|
|
1290
|
+
color,
|
|
1291
|
+
size,
|
|
1292
|
+
rounded,
|
|
1293
|
+
leading,
|
|
1294
|
+
dotTone,
|
|
1295
|
+
leftElement,
|
|
1296
|
+
trailing,
|
|
1297
|
+
onPress,
|
|
1298
|
+
isDisabled,
|
|
1299
|
+
className,
|
|
1300
|
+
textClassName,
|
|
1301
|
+
children,
|
|
1302
|
+
...viewProps
|
|
1303
|
+
} = props;
|
|
1304
|
+
const resolvedTone = tone ?? (color ? colorToTone[color] : "neutral");
|
|
1305
|
+
const classes = containerClasses(props, resolvedTone);
|
|
1306
|
+
const content = /* @__PURE__ */ jsx(PillContent, { ...props, tone: resolvedTone });
|
|
1307
|
+
if (onPress) {
|
|
1308
|
+
return /* @__PURE__ */ jsx(
|
|
1309
|
+
Pressable,
|
|
1310
|
+
{
|
|
1311
|
+
onPress,
|
|
1312
|
+
disabled: isDisabled,
|
|
1313
|
+
accessibilityRole: "button",
|
|
1314
|
+
className: classes,
|
|
1315
|
+
...viewProps,
|
|
1316
|
+
children: content
|
|
1317
|
+
}
|
|
1318
|
+
);
|
|
1319
|
+
}
|
|
1320
|
+
return /* @__PURE__ */ jsx(View, { className: classes, ...viewProps, children: content });
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
// src/components/ui/badge/Badge.tsx
|
|
1324
|
+
var colorToTone2 = {
|
|
1325
|
+
default: "neutral",
|
|
1326
|
+
primary: "brand",
|
|
1327
|
+
secondary: "brand-secondary",
|
|
1328
|
+
success: "success",
|
|
1329
|
+
error: "error",
|
|
1330
|
+
warning: "warning",
|
|
1331
|
+
info: "info"
|
|
1332
|
+
};
|
|
1333
|
+
var sizeStyles3 = {
|
|
1334
|
+
sm: "px-1.5 py-0.5",
|
|
1335
|
+
md: "px-2 py-0.5",
|
|
1336
|
+
lg: "px-2.5 py-1"
|
|
1054
1337
|
};
|
|
1338
|
+
var textSizeStyles = {
|
|
1339
|
+
sm: "text-xs",
|
|
1340
|
+
md: "text-xs",
|
|
1341
|
+
lg: "text-sm"
|
|
1342
|
+
};
|
|
1343
|
+
function dotIndicatorColor(color, dotColor) {
|
|
1344
|
+
if (dotColor) return dotColor;
|
|
1345
|
+
return color === "default" || color === "secondary" ? "default" : color;
|
|
1346
|
+
}
|
|
1055
1347
|
function Badge({
|
|
1056
1348
|
variant = "subtle",
|
|
1057
1349
|
color = "default",
|
|
@@ -1062,31 +1354,116 @@ function Badge({
|
|
|
1062
1354
|
children,
|
|
1063
1355
|
...props
|
|
1064
1356
|
}) {
|
|
1065
|
-
return /* @__PURE__ */
|
|
1066
|
-
|
|
1357
|
+
return /* @__PURE__ */ jsx(
|
|
1358
|
+
Pill,
|
|
1067
1359
|
{
|
|
1360
|
+
variant,
|
|
1361
|
+
tone: colorToTone2[color],
|
|
1362
|
+
leading: dot ? /* @__PURE__ */ jsx(Indicator, { size: "xs", color: dotIndicatorColor(color, dotColor), className: "mr-0.5" }) : void 0,
|
|
1068
1363
|
className: cn(
|
|
1069
|
-
"
|
|
1070
|
-
|
|
1071
|
-
|
|
1364
|
+
"justify-center self-auto gap-0",
|
|
1365
|
+
variant === "outline" ? "border" : "border-0",
|
|
1366
|
+
sizeStyles3[size],
|
|
1072
1367
|
className
|
|
1073
1368
|
),
|
|
1369
|
+
textClassName: cn("font-sans font-medium", textSizeStyles[size]),
|
|
1074
1370
|
...props,
|
|
1075
|
-
children
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1371
|
+
children
|
|
1372
|
+
}
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
var variantStyles = {
|
|
1376
|
+
h1: "font-heading text-5xl font-bold leading-tight",
|
|
1377
|
+
h2: "font-heading text-4xl font-bold leading-tight",
|
|
1378
|
+
h3: "font-heading text-3xl font-bold leading-tight",
|
|
1379
|
+
h4: "font-heading text-2xl font-bold leading-tight",
|
|
1380
|
+
h5: "font-heading text-xl font-semibold leading-tight",
|
|
1381
|
+
h6: "font-heading text-lg font-semibold leading-tight",
|
|
1382
|
+
body1: "font-body text-base font-normal leading-normal",
|
|
1383
|
+
body2: "font-body text-sm font-normal leading-normal",
|
|
1384
|
+
subtitle1: "font-body text-base font-medium leading-relaxed",
|
|
1385
|
+
subtitle2: "font-body text-sm font-medium leading-normal",
|
|
1386
|
+
caption: "font-body text-xs font-normal leading-loose",
|
|
1387
|
+
overline: "font-body text-xs font-semibold uppercase tracking-widest leading-relaxed",
|
|
1388
|
+
button: "font-sans text-sm font-semibold leading-relaxed",
|
|
1389
|
+
// Monospace technical readouts (clocks, ids, metrics) and their all-caps label form.
|
|
1390
|
+
mono: "font-mono text-xs font-normal leading-normal",
|
|
1391
|
+
monoLabel: "font-mono text-xs font-bold uppercase tracking-wide leading-normal",
|
|
1392
|
+
// The sans (Inter) label pair: 10px for dense table/column headers, 12px bold for
|
|
1393
|
+
// badge and row labels. `overline` is the 12px font-body form of the same idea.
|
|
1394
|
+
microLabel: "font-sans text-2xs font-semibold uppercase tracking-widest leading-normal",
|
|
1395
|
+
boldLabel: "font-sans text-xs font-bold leading-normal"
|
|
1396
|
+
};
|
|
1397
|
+
var colorStyles2 = {
|
|
1398
|
+
primary: "text-text-primary",
|
|
1399
|
+
secondary: "text-text-secondary",
|
|
1400
|
+
tertiary: "text-text-tertiary",
|
|
1401
|
+
disabled: "text-text-disabled",
|
|
1402
|
+
inverse: "text-text-inverse",
|
|
1403
|
+
success: "text-status-success",
|
|
1404
|
+
error: "text-status-error",
|
|
1405
|
+
warning: "text-status-warning",
|
|
1406
|
+
info: "text-status-info",
|
|
1407
|
+
inherit: ""
|
|
1408
|
+
// No color class, inherit from parent
|
|
1409
|
+
};
|
|
1410
|
+
var alignStyles = {
|
|
1411
|
+
left: "text-left",
|
|
1412
|
+
center: "text-center",
|
|
1413
|
+
right: "text-right",
|
|
1414
|
+
justify: "text-justify"
|
|
1415
|
+
};
|
|
1416
|
+
var headingVariants = ["h1", "h2", "h3", "h4", "h5", "h6"];
|
|
1417
|
+
var marginBottomStyles = {
|
|
1418
|
+
none: "",
|
|
1419
|
+
sm: "mb-1",
|
|
1420
|
+
md: "mb-2",
|
|
1421
|
+
lg: "mb-4"
|
|
1422
|
+
};
|
|
1423
|
+
function Typography({
|
|
1424
|
+
variant = "body1",
|
|
1425
|
+
color = "primary",
|
|
1426
|
+
align,
|
|
1427
|
+
truncate = false,
|
|
1428
|
+
noWrap = false,
|
|
1429
|
+
// deprecated, kept for backward compatibility
|
|
1430
|
+
marginBottom,
|
|
1431
|
+
gutterBottom = false,
|
|
1432
|
+
// deprecated, kept for backward compatibility
|
|
1433
|
+
maxLines,
|
|
1434
|
+
className,
|
|
1435
|
+
children,
|
|
1436
|
+
...props
|
|
1437
|
+
}) {
|
|
1438
|
+
const isHeading = headingVariants.includes(variant);
|
|
1439
|
+
const shouldTruncate = truncate || noWrap;
|
|
1440
|
+
const mb = marginBottom || (gutterBottom ? "md" : "none");
|
|
1441
|
+
let numLines;
|
|
1442
|
+
if (maxLines) {
|
|
1443
|
+
numLines = maxLines;
|
|
1444
|
+
} else if (shouldTruncate) {
|
|
1445
|
+
numLines = 1;
|
|
1446
|
+
}
|
|
1447
|
+
return /* @__PURE__ */ jsx(
|
|
1448
|
+
Text,
|
|
1449
|
+
{
|
|
1450
|
+
accessibilityRole: isHeading ? "header" : "text",
|
|
1451
|
+
numberOfLines: numLines,
|
|
1452
|
+
className: cn(
|
|
1453
|
+
variantStyles[variant],
|
|
1454
|
+
color !== "inherit" && colorStyles2[color],
|
|
1455
|
+
align && alignStyles[align],
|
|
1456
|
+
shouldTruncate && "truncate",
|
|
1457
|
+
marginBottomStyles[mb],
|
|
1458
|
+
className
|
|
1459
|
+
),
|
|
1460
|
+
...props,
|
|
1461
|
+
children
|
|
1086
1462
|
}
|
|
1087
1463
|
);
|
|
1088
1464
|
}
|
|
1089
|
-
|
|
1465
|
+
|
|
1466
|
+
// src/components/custom/Workout/Sparkline.tsx
|
|
1090
1467
|
function normalizeData(data, height) {
|
|
1091
1468
|
if (data.length === 0) return [];
|
|
1092
1469
|
const min = Math.min(...data);
|
|
@@ -1123,7 +1500,7 @@ function Sparkline({
|
|
|
1123
1500
|
}
|
|
1124
1501
|
);
|
|
1125
1502
|
}
|
|
1126
|
-
const resolvedColor = color ??
|
|
1503
|
+
const resolvedColor = color ?? resolveColor("brand-primary");
|
|
1127
1504
|
const normalized = normalizeData(data, height);
|
|
1128
1505
|
const stepX = data.length > 1 ? width / (data.length - 1) : 0;
|
|
1129
1506
|
const dotSize = 3;
|
|
@@ -1163,14 +1540,19 @@ function Sparkline({
|
|
|
1163
1540
|
],
|
|
1164
1541
|
accessibilityElementsHidden: true,
|
|
1165
1542
|
testID: `sparkline-reference-${i}`,
|
|
1166
|
-
children: line.label &&
|
|
1167
|
-
|
|
1543
|
+
children: line.label && // `3xs` (9px) is the scale floor; the label was 7px, which is off it
|
|
1544
|
+
// entirely (TOKENS.md §4). The line box stays unpinned, as the raw
|
|
1545
|
+
// <Text> this replaced was, so the absolute offset still lands.
|
|
1546
|
+
/* @__PURE__ */ jsx(
|
|
1547
|
+
Typography,
|
|
1168
1548
|
{
|
|
1549
|
+
variant: "caption",
|
|
1550
|
+
color: "inherit",
|
|
1551
|
+
className: "text-3xs leading-[normal]",
|
|
1169
1552
|
style: {
|
|
1170
1553
|
position: "absolute",
|
|
1171
1554
|
right: 0,
|
|
1172
1555
|
top: -10,
|
|
1173
|
-
fontSize: 7,
|
|
1174
1556
|
color: line.color,
|
|
1175
1557
|
opacity: 1
|
|
1176
1558
|
},
|
|
@@ -1239,9 +1621,9 @@ function Sparkline({
|
|
|
1239
1621
|
}
|
|
1240
1622
|
|
|
1241
1623
|
// src/components/custom/Workout/BodyMapDetailPanel.tsx
|
|
1242
|
-
var
|
|
1243
|
-
var
|
|
1244
|
-
var VOLUME_GRADIENT = `linear-gradient(90deg, ${
|
|
1624
|
+
var t2 = getSemanticColors("dark");
|
|
1625
|
+
var BRAND_PRIMARY2 = t2["brand-primary"];
|
|
1626
|
+
var VOLUME_GRADIENT = `linear-gradient(90deg, ${t2["status-info"]} 0%, ${t2["status-success"]} 50%, ${t2["status-error"]} 100%)`;
|
|
1245
1627
|
var SLIDE_OFFSET = 400;
|
|
1246
1628
|
var BACKDROP_OPACITY = 0.4;
|
|
1247
1629
|
var STATUS_BADGE_COLOR = {
|
|
@@ -1306,7 +1688,14 @@ function BodyMapDetailPanel({
|
|
|
1306
1688
|
return /* @__PURE__ */ jsxs(
|
|
1307
1689
|
View,
|
|
1308
1690
|
{
|
|
1309
|
-
style: {
|
|
1691
|
+
style: {
|
|
1692
|
+
position: "absolute",
|
|
1693
|
+
top: 0,
|
|
1694
|
+
left: 0,
|
|
1695
|
+
right: 0,
|
|
1696
|
+
bottom: 0,
|
|
1697
|
+
justifyContent: "flex-end"
|
|
1698
|
+
},
|
|
1310
1699
|
testID: "body-map-detail-panel-root",
|
|
1311
1700
|
children: [
|
|
1312
1701
|
/* @__PURE__ */ jsx(
|
|
@@ -1441,8 +1830,22 @@ function BodyMapDetailPanel({
|
|
|
1441
1830
|
style: { marginBottom: 6 },
|
|
1442
1831
|
accessibilityElementsHidden: true,
|
|
1443
1832
|
children: [
|
|
1444
|
-
/* @__PURE__ */ jsx(
|
|
1445
|
-
|
|
1833
|
+
/* @__PURE__ */ jsx(
|
|
1834
|
+
Text,
|
|
1835
|
+
{
|
|
1836
|
+
className: "text-text-tertiary",
|
|
1837
|
+
style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" },
|
|
1838
|
+
children: `MEV ${landmarks.mev}`
|
|
1839
|
+
}
|
|
1840
|
+
),
|
|
1841
|
+
/* @__PURE__ */ jsx(
|
|
1842
|
+
Text,
|
|
1843
|
+
{
|
|
1844
|
+
className: "text-text-tertiary",
|
|
1845
|
+
style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" },
|
|
1846
|
+
children: `MRV ${landmarks.mrv}`
|
|
1847
|
+
}
|
|
1848
|
+
)
|
|
1446
1849
|
]
|
|
1447
1850
|
}
|
|
1448
1851
|
),
|
|
@@ -1477,7 +1880,8 @@ function BodyMapDetailPanel({
|
|
|
1477
1880
|
height: 14,
|
|
1478
1881
|
borderRadius: 7,
|
|
1479
1882
|
borderWidth: 2,
|
|
1480
|
-
|
|
1883
|
+
// A knob resting on the volume bar: lift, with the ring as its edge.
|
|
1884
|
+
...liftStyle(1, "dark", { rim: 0 })
|
|
1481
1885
|
},
|
|
1482
1886
|
accessibilityElementsHidden: true,
|
|
1483
1887
|
testID: "body-map-detail-panel-volume-marker"
|
|
@@ -1560,7 +1964,12 @@ function BodyMapDetailPanel({
|
|
|
1560
1964
|
Text,
|
|
1561
1965
|
{
|
|
1562
1966
|
className: "text-text-primary",
|
|
1563
|
-
style: {
|
|
1967
|
+
style: {
|
|
1968
|
+
flex: 1,
|
|
1969
|
+
fontSize: 13,
|
|
1970
|
+
fontFamily: "Inter, sans-serif",
|
|
1971
|
+
fontWeight: "600"
|
|
1972
|
+
},
|
|
1564
1973
|
testID: `body-map-detail-panel-contributing-${index}-name`,
|
|
1565
1974
|
children: exercise.name
|
|
1566
1975
|
}
|
|
@@ -1604,7 +2013,12 @@ function BodyMapDetailPanel({
|
|
|
1604
2013
|
Text,
|
|
1605
2014
|
{
|
|
1606
2015
|
className: "text-text-primary",
|
|
1607
|
-
style: {
|
|
2016
|
+
style: {
|
|
2017
|
+
flex: 1,
|
|
2018
|
+
fontSize: 13,
|
|
2019
|
+
fontFamily: "Inter, sans-serif",
|
|
2020
|
+
fontWeight: "600"
|
|
2021
|
+
},
|
|
1608
2022
|
testID: `body-map-detail-panel-upcoming-${index}-name`,
|
|
1609
2023
|
children: exercise.name
|
|
1610
2024
|
}
|
|
@@ -1639,7 +2053,18 @@ function BodyMapDetailPanel({
|
|
|
1639
2053
|
borderColor: "rgba(255,121,0,0.3)"
|
|
1640
2054
|
},
|
|
1641
2055
|
testID: "body-map-detail-panel-view-exercises",
|
|
1642
|
-
children: /* @__PURE__ */ jsx(
|
|
2056
|
+
children: /* @__PURE__ */ jsx(
|
|
2057
|
+
Text,
|
|
2058
|
+
{
|
|
2059
|
+
style: {
|
|
2060
|
+
fontSize: 13,
|
|
2061
|
+
fontFamily: "Inter, sans-serif",
|
|
2062
|
+
fontWeight: "700",
|
|
2063
|
+
color: BRAND_PRIMARY2
|
|
2064
|
+
},
|
|
2065
|
+
children: "View exercises"
|
|
2066
|
+
}
|
|
2067
|
+
)
|
|
1643
2068
|
}
|
|
1644
2069
|
)
|
|
1645
2070
|
]
|
|
@@ -1652,439 +2077,81 @@ function BodyMapDetailPanel({
|
|
|
1652
2077
|
}
|
|
1653
2078
|
);
|
|
1654
2079
|
}
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
function
|
|
1658
|
-
|
|
1659
|
-
let r, g, b;
|
|
1660
|
-
if (cleaned.length === 3) {
|
|
1661
|
-
r = parseInt(cleaned[0] + cleaned[0], 16);
|
|
1662
|
-
g = parseInt(cleaned[1] + cleaned[1], 16);
|
|
1663
|
-
b = parseInt(cleaned[2] + cleaned[2], 16);
|
|
1664
|
-
} else if (cleaned.length === 6) {
|
|
1665
|
-
r = parseInt(cleaned.slice(0, 2), 16);
|
|
1666
|
-
g = parseInt(cleaned.slice(2, 4), 16);
|
|
1667
|
-
b = parseInt(cleaned.slice(4, 6), 16);
|
|
1668
|
-
} else {
|
|
1669
|
-
return null;
|
|
1670
|
-
}
|
|
1671
|
-
return { r, g, b };
|
|
1672
|
-
}
|
|
1673
|
-
function rgbToHsv(r, g, b) {
|
|
1674
|
-
const rNorm = r / 255;
|
|
1675
|
-
const gNorm = g / 255;
|
|
1676
|
-
const bNorm = b / 255;
|
|
1677
|
-
const max = Math.max(rNorm, gNorm, bNorm);
|
|
1678
|
-
const min = Math.min(rNorm, gNorm, bNorm);
|
|
1679
|
-
const delta = max - min;
|
|
1680
|
-
const v = max;
|
|
1681
|
-
const s = max === 0 ? 0 : delta / max;
|
|
1682
|
-
let h = 0;
|
|
1683
|
-
if (delta !== 0) {
|
|
1684
|
-
if (max === rNorm) {
|
|
1685
|
-
h = 60 * ((gNorm - bNorm) / delta % 6);
|
|
1686
|
-
} else if (max === gNorm) {
|
|
1687
|
-
h = 60 * ((bNorm - rNorm) / delta + 2);
|
|
1688
|
-
} else {
|
|
1689
|
-
h = 60 * ((rNorm - gNorm) / delta + 4);
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1692
|
-
if (h < 0) h += 360;
|
|
1693
|
-
return { h, s, v };
|
|
1694
|
-
}
|
|
1695
|
-
function hsvToRgb(h, s, v) {
|
|
1696
|
-
const c = v * s;
|
|
1697
|
-
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
1698
|
-
const m = v - c;
|
|
1699
|
-
let rPrime, gPrime, bPrime;
|
|
1700
|
-
if (h >= 0 && h < 60) {
|
|
1701
|
-
rPrime = c;
|
|
1702
|
-
gPrime = x;
|
|
1703
|
-
bPrime = 0;
|
|
1704
|
-
} else if (h >= 60 && h < 120) {
|
|
1705
|
-
rPrime = x;
|
|
1706
|
-
gPrime = c;
|
|
1707
|
-
bPrime = 0;
|
|
1708
|
-
} else if (h >= 120 && h < 180) {
|
|
1709
|
-
rPrime = 0;
|
|
1710
|
-
gPrime = c;
|
|
1711
|
-
bPrime = x;
|
|
1712
|
-
} else if (h >= 180 && h < 240) {
|
|
1713
|
-
rPrime = 0;
|
|
1714
|
-
gPrime = x;
|
|
1715
|
-
bPrime = c;
|
|
1716
|
-
} else if (h >= 240 && h < 300) {
|
|
1717
|
-
rPrime = x;
|
|
1718
|
-
gPrime = 0;
|
|
1719
|
-
bPrime = c;
|
|
1720
|
-
} else {
|
|
1721
|
-
rPrime = c;
|
|
1722
|
-
gPrime = 0;
|
|
1723
|
-
bPrime = x;
|
|
1724
|
-
}
|
|
1725
|
-
return {
|
|
1726
|
-
r: Math.round((rPrime + m) * 255),
|
|
1727
|
-
g: Math.round((gPrime + m) * 255),
|
|
1728
|
-
b: Math.round((bPrime + m) * 255)
|
|
1729
|
-
};
|
|
2080
|
+
var DEFAULT_CONTEXT = { mode: "dark", level: "base" };
|
|
2081
|
+
var SurfaceContext = createContext(DEFAULT_CONTEXT);
|
|
2082
|
+
function useSurface() {
|
|
2083
|
+
return useContext(SurfaceContext);
|
|
1730
2084
|
}
|
|
1731
|
-
function
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
};
|
|
1736
|
-
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
1737
|
-
}
|
|
1738
|
-
function lighten(hex, amount = 0.1) {
|
|
1739
|
-
const rgb = hexToRgb(hex);
|
|
1740
|
-
if (!rgb) return hex;
|
|
1741
|
-
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
1742
|
-
const newV = Math.min(1, hsv.v + amount);
|
|
1743
|
-
const newRgb = hsvToRgb(hsv.h, hsv.s, newV);
|
|
1744
|
-
return rgbToHex(newRgb.r, newRgb.g, newRgb.b);
|
|
1745
|
-
}
|
|
1746
|
-
var elevationSystem = {
|
|
1747
|
-
// Deep inset (recessed input fields, deeply pressed buttons)
|
|
1748
|
-
[-2]: {
|
|
1749
|
-
name: "deep-inset",
|
|
1750
|
-
colorAdjustment: 0,
|
|
1751
|
-
shadowIntensity: "strong",
|
|
1752
|
-
shadowStyle: "pressed",
|
|
1753
|
-
description: "Deeply recessed elements (e.g., input fields, deeply pressed buttons)"
|
|
1754
|
-
},
|
|
1755
|
-
// Shallow inset (pressed buttons, sunken panels)
|
|
1756
|
-
[-1]: {
|
|
1757
|
-
name: "inset",
|
|
1758
|
-
colorAdjustment: 0,
|
|
1759
|
-
shadowIntensity: "medium",
|
|
1760
|
-
shadowStyle: "pressed",
|
|
1761
|
-
description: "Shallow inset elements (e.g., pressed buttons, sunken panels within cards)"
|
|
1762
|
-
},
|
|
1763
|
-
// Base level (page background, default surface)
|
|
1764
|
-
[0]: {
|
|
1765
|
-
name: "base",
|
|
1766
|
-
colorAdjustment: 0,
|
|
1767
|
-
shadowIntensity: "subtle",
|
|
1768
|
-
shadowStyle: "raised",
|
|
1769
|
-
description: "Base surface level (page background, default containers)"
|
|
1770
|
-
},
|
|
1771
|
-
// Level 1: Subtle elevation (outline cards, subtle containers)
|
|
1772
|
-
[1]: {
|
|
1773
|
-
name: "subtle",
|
|
1774
|
-
// The whole ladder was re-spaced in TD-07.16. It used to run
|
|
1775
|
-
// 0.01/0.02/0.04/0.06/0.08, where the first step was ~2 RGB values — under
|
|
1776
|
-
// the perceptual floor, so level 1 existed in the type system and nowhere on
|
|
1777
|
-
// screen. With drop-shadow now gated off below FLOATING_ELEVATION_MIN, TONE
|
|
1778
|
-
// is the only thing separating 0-3, so every step has to actually land.
|
|
1779
|
-
// Even 0.025 spacing, verified in elevation.test.ts as ΔL* > 1 per step.
|
|
1780
|
-
colorAdjustment: 0.025,
|
|
1781
|
-
shadowIntensity: "subtle",
|
|
1782
|
-
shadowStyle: "raised",
|
|
1783
|
-
description: "Subtle elevation (outline cards, subtle containers)"
|
|
1784
|
-
},
|
|
1785
|
-
// Level 2: Standard elevation (default cards, buttons)
|
|
1786
|
-
[2]: {
|
|
1787
|
-
name: "standard",
|
|
1788
|
-
colorAdjustment: 0.05,
|
|
1789
|
-
shadowIntensity: "medium",
|
|
1790
|
-
shadowStyle: "raised",
|
|
1791
|
-
description: "Standard elevation (default cards, raised buttons)"
|
|
1792
|
-
},
|
|
1793
|
-
// Level 3: Prominent elevation (important cards, modals)
|
|
1794
|
-
[3]: {
|
|
1795
|
-
name: "prominent",
|
|
1796
|
-
colorAdjustment: 0.075,
|
|
1797
|
-
shadowIntensity: "strong",
|
|
1798
|
-
shadowStyle: "raised",
|
|
1799
|
-
description: "Prominent elevation (important cards, modals, dropdowns)"
|
|
1800
|
-
},
|
|
1801
|
-
// Level 4: High elevation (overlays, popovers)
|
|
1802
|
-
[4]: {
|
|
1803
|
-
name: "high",
|
|
1804
|
-
colorAdjustment: 0.1,
|
|
1805
|
-
shadowIntensity: "strong",
|
|
1806
|
-
shadowStyle: "raised",
|
|
1807
|
-
description: "High elevation (overlays, popovers, tooltips)"
|
|
1808
|
-
},
|
|
1809
|
-
// Level 5: Floating (toasts, floating action buttons)
|
|
1810
|
-
[5]: {
|
|
1811
|
-
name: "floating",
|
|
1812
|
-
colorAdjustment: 0.13,
|
|
1813
|
-
shadowIntensity: "strong",
|
|
1814
|
-
shadowStyle: "raised",
|
|
1815
|
-
description: "Floating elevation (toasts, floating action buttons, highest z-index)"
|
|
1816
|
-
}
|
|
1817
|
-
};
|
|
1818
|
-
function calculateRimLightColor(baseColor, level) {
|
|
1819
|
-
const rgb = hexToRgb(baseColor);
|
|
1820
|
-
if (!rgb) {
|
|
1821
|
-
return "rgba(255, 255, 255, 0.5)";
|
|
1822
|
-
}
|
|
1823
|
-
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
1824
|
-
const isLight = hsv.v > 0.6;
|
|
1825
|
-
const isSaturated = hsv.s > 0.3;
|
|
1826
|
-
const absLevel = Math.abs(level);
|
|
1827
|
-
const opacityBoost = Math.max(0, (absLevel - 1) * 0.05);
|
|
1828
|
-
if (isSaturated) {
|
|
1829
|
-
const rimLightValue = 0.95;
|
|
1830
|
-
const rimLightRgb = hsvToRgb(hsv.h, hsv.s * 0.3, rimLightValue);
|
|
1831
|
-
const baseOpacity = isLight ? 0.9 : 0.5;
|
|
1832
|
-
const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
|
|
1833
|
-
return `rgba(${rimLightRgb.r}, ${rimLightRgb.g}, ${rimLightRgb.b}, ${finalOpacity.toFixed(2)})`;
|
|
1834
|
-
} else {
|
|
1835
|
-
const baseOpacity = isLight ? 0.9 : 0.12;
|
|
1836
|
-
const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
|
|
1837
|
-
return `rgba(255, 255, 255, ${finalOpacity.toFixed(2)})`;
|
|
1838
|
-
}
|
|
2085
|
+
function recessDepth(inherited, planesDown, mode) {
|
|
2086
|
+
let plane = inherited.level;
|
|
2087
|
+
for (let i = 0; i < planesDown; i++) plane = pressedLevel(plane);
|
|
2088
|
+
const backgroundColor = surfaceBackground(plane, mode);
|
|
2089
|
+
return { plane, backgroundColor, depthStyle: getPressedRecessShadow(backgroundColor, mode) };
|
|
1839
2090
|
}
|
|
1840
|
-
function
|
|
1841
|
-
const
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
};
|
|
2091
|
+
function resolveSurfaceDepth(inherited, props) {
|
|
2092
|
+
const mode = props.theme ?? inherited.mode;
|
|
2093
|
+
const elevation = props.elevation ?? 0;
|
|
2094
|
+
if (props.pressed || elevation < 0) {
|
|
2095
|
+
const down = props.pressed ? 1 : -elevation;
|
|
2096
|
+
return { mode, step: 0, lifted: false, ...recessDepth(inherited, down, mode) };
|
|
1847
2097
|
}
|
|
1848
|
-
const
|
|
1849
|
-
const
|
|
1850
|
-
const
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
return {
|
|
1856
|
-
dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.3)`,
|
|
1857
|
-
darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.4)`
|
|
1858
|
-
};
|
|
1859
|
-
} else {
|
|
1860
|
-
return {
|
|
1861
|
-
dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.5)`,
|
|
1862
|
-
darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.6)`
|
|
1863
|
-
};
|
|
1864
|
-
}
|
|
1865
|
-
} else {
|
|
1866
|
-
if (isLight) {
|
|
1867
|
-
return {
|
|
1868
|
-
dark: "rgba(0, 0, 0, 0.2)",
|
|
1869
|
-
darker: "rgba(0, 0, 0, 0.3)"
|
|
1870
|
-
};
|
|
1871
|
-
} else {
|
|
1872
|
-
return {
|
|
1873
|
-
dark: "rgba(0, 0, 0, 0.5)",
|
|
1874
|
-
darker: "rgba(0, 0, 0, 0.6)"
|
|
1875
|
-
};
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
function getRimLightConfig() {
|
|
1880
|
-
return {
|
|
1881
|
-
offset: 1,
|
|
1882
|
-
// Fixed 1px for crisp rim
|
|
1883
|
-
blur: 1
|
|
1884
|
-
// Tight blur for crisp edge
|
|
1885
|
-
};
|
|
1886
|
-
}
|
|
1887
|
-
var elevationSurfaceCache = /* @__PURE__ */ new Map();
|
|
1888
|
-
var MAX_CACHE_SIZE = 100;
|
|
1889
|
-
function getCacheKey(baseColor, level, theme) {
|
|
1890
|
-
return `${baseColor}-${level}-${theme}`;
|
|
2098
|
+
const step = props.level != null ? 0 : props.raise ?? elevation;
|
|
2099
|
+
const floating = step >= FLOATING_ELEVATION_MIN;
|
|
2100
|
+
const plane = props.level ?? (floating ? "overlay" : raisedLevel(inherited.level, step));
|
|
2101
|
+
const lifted = props.lift ?? step > 0;
|
|
2102
|
+
const liftStep = Math.max(1, Math.min(5, step));
|
|
2103
|
+
const depthStyle = lifted ? liftStyle(liftStep, mode, props.liftOptions) : {};
|
|
2104
|
+
return { mode, plane, backgroundColor: surfaceBackground(plane, mode), depthStyle, step, lifted };
|
|
1891
2105
|
}
|
|
1892
|
-
function
|
|
1893
|
-
const
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
}
|
|
1907
|
-
const result = calculateElevationSurface(baseColor, level);
|
|
1908
|
-
if (elevationSurfaceCache.size >= MAX_CACHE_SIZE) {
|
|
1909
|
-
const firstKey = elevationSurfaceCache.keys().next().value;
|
|
1910
|
-
elevationSurfaceCache.delete(firstKey);
|
|
1911
|
-
}
|
|
1912
|
-
elevationSurfaceCache.set(cacheKey, result);
|
|
1913
|
-
return result;
|
|
1914
|
-
}
|
|
1915
|
-
var elevationShadowCache = /* @__PURE__ */ new Map();
|
|
1916
|
-
var MAX_SHADOW_CACHE_SIZE = 50;
|
|
1917
|
-
function getShadowCacheKey(baseColor, level, theme, isHovered) {
|
|
1918
|
-
return `${baseColor}-${level}-${theme}-${isHovered}`;
|
|
1919
|
-
}
|
|
1920
|
-
function calculateElevationShadow(baseColor, level, theme, isHovered = false) {
|
|
1921
|
-
const config = elevationSystem[level];
|
|
1922
|
-
if (level === 0) {
|
|
1923
|
-
return {};
|
|
1924
|
-
}
|
|
1925
|
-
const elevatedSurfaceColor = calculateElevationSurface(baseColor, level);
|
|
1926
|
-
const rimLightColor = calculateRimLightColor(baseColor, level);
|
|
1927
|
-
const darkShadowColors = calculateDarkShadowColors(elevatedSurfaceColor);
|
|
1928
|
-
const intensityConfig = {
|
|
1929
|
-
subtle: { offset: 1, blur: 2 },
|
|
1930
|
-
medium: { offset: 2, blur: 4 },
|
|
1931
|
-
strong: { offset: 2, blur: 5 }
|
|
1932
|
-
};
|
|
1933
|
-
const { offset, blur } = intensityConfig[config.shadowIntensity];
|
|
1934
|
-
const rimConfig = getRimLightConfig();
|
|
1935
|
-
if (config.shadowStyle === "pressed") {
|
|
1936
|
-
if (isHovered) {
|
|
1937
|
-
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
1938
|
-
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
1939
|
-
return Platform.select({
|
|
1940
|
-
web: {
|
|
1941
|
-
boxShadow: `inset ${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
1942
|
-
},
|
|
1943
|
-
default: {
|
|
1944
|
-
shadowOpacity: 0,
|
|
1945
|
-
elevation: 0
|
|
1946
|
-
}
|
|
1947
|
-
});
|
|
1948
|
-
}
|
|
1949
|
-
return Platform.select({
|
|
1950
|
-
web: {
|
|
1951
|
-
boxShadow: `inset ${offset}px ${offset}px ${blur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
1952
|
-
},
|
|
1953
|
-
default: {
|
|
1954
|
-
shadowOpacity: 0,
|
|
1955
|
-
elevation: 0
|
|
1956
|
-
}
|
|
1957
|
-
});
|
|
1958
|
-
} else {
|
|
1959
|
-
if (isHovered) {
|
|
1960
|
-
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
1961
|
-
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
1962
|
-
return Platform.select({
|
|
1963
|
-
web: {
|
|
1964
|
-
boxShadow: `${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
1965
|
-
},
|
|
1966
|
-
default: {
|
|
1967
|
-
shadowColor: "#000",
|
|
1968
|
-
shadowOffset: { width: hoverOffset, height: hoverOffset },
|
|
1969
|
-
shadowOpacity: 0.2,
|
|
1970
|
-
shadowRadius: hoverBlur / 2,
|
|
1971
|
-
elevation: hoverOffset
|
|
1972
|
-
}
|
|
1973
|
-
});
|
|
1974
|
-
}
|
|
1975
|
-
return Platform.select({
|
|
1976
|
-
web: {
|
|
1977
|
-
boxShadow: `${offset}px ${offset}px ${blur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
1978
|
-
},
|
|
1979
|
-
default: {
|
|
1980
|
-
shadowColor: "#000",
|
|
1981
|
-
shadowOffset: { width: offset, height: offset },
|
|
1982
|
-
shadowOpacity: 0.3,
|
|
1983
|
-
shadowRadius: blur / 2,
|
|
1984
|
-
elevation: offset
|
|
1985
|
-
}
|
|
1986
|
-
});
|
|
1987
|
-
}
|
|
1988
|
-
}
|
|
1989
|
-
var FLOATING_ELEVATION_MIN = 4;
|
|
1990
|
-
function getElevationShadow(baseColor, level, theme, isHovered = false) {
|
|
1991
|
-
const cacheKey = getShadowCacheKey(baseColor, level, theme, isHovered);
|
|
1992
|
-
if (elevationShadowCache.has(cacheKey)) {
|
|
1993
|
-
return elevationShadowCache.get(cacheKey);
|
|
1994
|
-
}
|
|
1995
|
-
const result = level > 0 && level < FLOATING_ELEVATION_MIN ? {} : calculateElevationShadow(baseColor, level, theme, isHovered);
|
|
1996
|
-
if (elevationShadowCache.size >= MAX_SHADOW_CACHE_SIZE) {
|
|
1997
|
-
const firstKey = elevationShadowCache.keys().next().value;
|
|
1998
|
-
elevationShadowCache.delete(firstKey);
|
|
1999
|
-
}
|
|
2000
|
-
elevationShadowCache.set(cacheKey, result);
|
|
2001
|
-
return result;
|
|
2002
|
-
}
|
|
2003
|
-
function getBaseSurfaceColor(theme) {
|
|
2004
|
-
return theme === "light" ? semanticColorsLight["surface-raised"] : semanticColorsDark["surface-elevated"];
|
|
2005
|
-
}
|
|
2006
|
-
var componentElevationRanges = {
|
|
2007
|
-
button: {
|
|
2008
|
-
allowed: [2],
|
|
2009
|
-
default: 2,
|
|
2010
|
-
hover: 3
|
|
2011
|
-
},
|
|
2012
|
-
card: {
|
|
2013
|
-
allowed: [1, 2, 3],
|
|
2014
|
-
default: 2,
|
|
2015
|
-
hover: 3
|
|
2016
|
-
},
|
|
2017
|
-
input: {
|
|
2018
|
-
allowed: [-2, -1, 0],
|
|
2019
|
-
default: -1
|
|
2020
|
-
},
|
|
2021
|
-
overlay: {
|
|
2022
|
-
allowed: [4, 5],
|
|
2023
|
-
default: 4
|
|
2024
|
-
}
|
|
2025
|
-
};
|
|
2026
|
-
function getValidatedElevation(component, requested) {
|
|
2027
|
-
const range = componentElevationRanges[component];
|
|
2028
|
-
if (range.allowed.includes(requested)) {
|
|
2029
|
-
return requested;
|
|
2030
|
-
}
|
|
2031
|
-
const sorted = [...range.allowed].sort((a, b) => a - b);
|
|
2032
|
-
if (requested < sorted[0]) return sorted[0];
|
|
2033
|
-
if (requested > sorted[sorted.length - 1]) return sorted[sorted.length - 1];
|
|
2034
|
-
return sorted.reduce(
|
|
2035
|
-
(prev, curr) => Math.abs(curr - requested) < Math.abs(prev - requested) ? curr : prev
|
|
2106
|
+
function useResolvedSurface(props) {
|
|
2107
|
+
const inherited = useSurface();
|
|
2108
|
+
const { level, raise, elevation, pressed, lift, liftOptions, theme } = props;
|
|
2109
|
+
return useMemo(
|
|
2110
|
+
() => resolveSurfaceDepth(inherited, {
|
|
2111
|
+
level,
|
|
2112
|
+
raise,
|
|
2113
|
+
elevation,
|
|
2114
|
+
pressed,
|
|
2115
|
+
lift,
|
|
2116
|
+
liftOptions,
|
|
2117
|
+
theme
|
|
2118
|
+
}),
|
|
2119
|
+
[inherited, level, raise, elevation, pressed, lift, liftOptions, theme]
|
|
2036
2120
|
);
|
|
2037
2121
|
}
|
|
2038
|
-
function getTheme() {
|
|
2039
|
-
if (typeof document === "undefined") return "dark";
|
|
2040
|
-
return document.documentElement.classList.contains("light") ? "light" : "dark";
|
|
2041
|
-
}
|
|
2042
|
-
var listeners = [];
|
|
2043
|
-
function subscribe(listener) {
|
|
2044
|
-
listeners = [...listeners, listener];
|
|
2045
|
-
if (typeof document !== "undefined" && listeners.length === 1) {
|
|
2046
|
-
const observer = new MutationObserver((mutations) => {
|
|
2047
|
-
for (const mutation of mutations) {
|
|
2048
|
-
if (mutation.type === "attributes" && mutation.attributeName === "class") {
|
|
2049
|
-
listeners.forEach((l) => l());
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
2052
|
-
});
|
|
2053
|
-
observer.observe(document.documentElement, {
|
|
2054
|
-
attributes: true,
|
|
2055
|
-
attributeFilter: ["class"]
|
|
2056
|
-
});
|
|
2057
|
-
subscribe._observer = observer;
|
|
2058
|
-
}
|
|
2059
|
-
return () => {
|
|
2060
|
-
listeners = listeners.filter((l) => l !== listener);
|
|
2061
|
-
if (listeners.length === 0 && subscribe._observer) {
|
|
2062
|
-
subscribe._observer.disconnect();
|
|
2063
|
-
subscribe._observer = null;
|
|
2064
|
-
}
|
|
2065
|
-
};
|
|
2066
|
-
}
|
|
2067
|
-
function getSnapshot() {
|
|
2068
|
-
return getTheme();
|
|
2069
|
-
}
|
|
2070
|
-
function getServerSnapshot() {
|
|
2071
|
-
return "dark";
|
|
2072
|
-
}
|
|
2073
|
-
function useTheme() {
|
|
2074
|
-
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
2075
|
-
}
|
|
2076
2122
|
|
|
2077
2123
|
// src/components/ui/card/Card.tsx
|
|
2078
|
-
var
|
|
2124
|
+
var EDGE_CLASS = {
|
|
2079
2125
|
elevated: "",
|
|
2080
|
-
|
|
2081
|
-
outline: "border-2 border-hairline-strong",
|
|
2082
|
-
// Thicker border with stronger contrast
|
|
2126
|
+
accent: "",
|
|
2083
2127
|
filled: "",
|
|
2084
|
-
|
|
2085
|
-
accent: "border border-hairline",
|
|
2128
|
+
outline: "border border-hairline-strong",
|
|
2086
2129
|
subtle: "border border-hairline-subtle"
|
|
2087
2130
|
};
|
|
2131
|
+
var LIFTED = {
|
|
2132
|
+
elevated: true,
|
|
2133
|
+
accent: true,
|
|
2134
|
+
filled: false,
|
|
2135
|
+
outline: false,
|
|
2136
|
+
subtle: false
|
|
2137
|
+
};
|
|
2138
|
+
var STAYS_ON_HOST = {
|
|
2139
|
+
elevated: false,
|
|
2140
|
+
accent: false,
|
|
2141
|
+
filled: false,
|
|
2142
|
+
outline: true,
|
|
2143
|
+
subtle: true
|
|
2144
|
+
};
|
|
2145
|
+
function useCardDepth(variant, elevation, hovered) {
|
|
2146
|
+
const raise = STAYS_ON_HOST[variant] ? void 0 : elevation;
|
|
2147
|
+
const resolved = useResolvedSurface({ raise, lift: LIFTED[variant] });
|
|
2148
|
+
const depthStyle = useMemo(() => {
|
|
2149
|
+
if (!hovered || !LIFTED[variant]) return resolved.depthStyle;
|
|
2150
|
+
const hoverStep = Math.min(3, resolved.step + 1);
|
|
2151
|
+
return liftStyle(hoverStep, resolved.mode);
|
|
2152
|
+
}, [hovered, variant, resolved]);
|
|
2153
|
+
return { ...resolved, depthStyle };
|
|
2154
|
+
}
|
|
2088
2155
|
function Card({
|
|
2089
2156
|
variant = "elevated",
|
|
2090
2157
|
elevation = 2,
|
|
@@ -2105,89 +2172,54 @@ function Card({
|
|
|
2105
2172
|
}) {
|
|
2106
2173
|
const isClickable = isInteractive || !!onPress;
|
|
2107
2174
|
const [isHovered, setIsHovered] = useState(false);
|
|
2108
|
-
const
|
|
2109
|
-
const elevationLevel = useMemo(() => {
|
|
2110
|
-
const validated = getValidatedElevation("card", elevation);
|
|
2111
|
-
if (variant === "outline" || variant === "accent" || variant === "subtle") {
|
|
2112
|
-
return 1;
|
|
2113
|
-
}
|
|
2114
|
-
return validated;
|
|
2115
|
-
}, [variant, elevation]);
|
|
2116
|
-
const baseColor = useMemo(() => getBaseSurfaceColor(theme), [theme]);
|
|
2117
|
-
const surfaceColor = useMemo(() => {
|
|
2118
|
-
if ((variant === "outline" || variant === "accent") && theme === "light") {
|
|
2119
|
-
return "#FAFAFA";
|
|
2120
|
-
}
|
|
2121
|
-
if (variant === "subtle") {
|
|
2122
|
-
return getElevationSurface(baseColor, 0, theme);
|
|
2123
|
-
}
|
|
2124
|
-
return getElevationSurface(baseColor, elevationLevel, theme);
|
|
2125
|
-
}, [baseColor, elevationLevel, theme, variant]);
|
|
2126
|
-
const shadowStyle = useMemo(() => {
|
|
2127
|
-
const shouldHover = isHovered && isClickable;
|
|
2128
|
-
return getElevationShadow(baseColor, elevationLevel, theme, shouldHover);
|
|
2129
|
-
}, [baseColor, elevationLevel, theme, isHovered, isClickable]);
|
|
2130
|
-
const cardContent = isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2131
|
-
skeletonHasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
2132
|
-
/* @__PURE__ */ jsx(View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
|
|
2133
|
-
/* @__PURE__ */ jsx(View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
|
|
2134
|
-
] }),
|
|
2135
|
-
/* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: skeletonContentLines }).map((_, i) => /* @__PURE__ */ jsx(
|
|
2136
|
-
View,
|
|
2137
|
-
{
|
|
2138
|
-
className: cn(
|
|
2139
|
-
"h-4 bg-interactive-disabled rounded",
|
|
2140
|
-
i < skeletonContentLines - 1 ? "mb-2 w-full" : "w-4/5"
|
|
2141
|
-
)
|
|
2142
|
-
},
|
|
2143
|
-
i
|
|
2144
|
-
)) }),
|
|
2145
|
-
skeletonHasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
|
|
2146
|
-
] }) : children;
|
|
2175
|
+
const depth = useCardDepth(variant, elevation, isHovered && isClickable);
|
|
2147
2176
|
const baseClassName = cn(
|
|
2148
2177
|
"rounded-lg overflow-hidden relative",
|
|
2149
|
-
|
|
2150
|
-
variant === "outline" ? borderColor ? "border-2" : variantStyles[variant] : variantStyles[variant],
|
|
2151
|
-
// Remove Tailwind shadow classes - we're using elevation shadows via style prop
|
|
2178
|
+
borderColor ? "border" : EDGE_CLASS[variant],
|
|
2152
2179
|
isClickable && "web:cursor-pointer web:transition-all web:duration-150",
|
|
2153
2180
|
isClickable && "web:hover:-translate-y-0.5 active:scale-[0.99]",
|
|
2154
2181
|
isLoading && "pointer-events-none animate-pulse",
|
|
2155
2182
|
className
|
|
2156
2183
|
);
|
|
2157
|
-
const accentStyle = useMemo(() => variant === "accent" ? {
|
|
2158
|
-
borderLeftWidth: accentWidth ?? 3,
|
|
2159
|
-
borderLeftColor: accentColor ?? "var(--color-brand-primary)"
|
|
2160
|
-
} : {}, [variant, accentWidth, accentColor]);
|
|
2161
2184
|
const mergedStyle = useMemo(() => {
|
|
2162
|
-
const
|
|
2163
|
-
backgroundColor: bgColor ||
|
|
2185
|
+
const own = {
|
|
2186
|
+
backgroundColor: bgColor || depth.backgroundColor,
|
|
2164
2187
|
borderRadius: 8,
|
|
2165
2188
|
overflow: "hidden",
|
|
2166
|
-
...
|
|
2167
|
-
...accentStyle
|
|
2189
|
+
...depth.depthStyle
|
|
2168
2190
|
};
|
|
2169
|
-
if (
|
|
2170
|
-
|
|
2191
|
+
if (variant === "accent") {
|
|
2192
|
+
own.borderLeftWidth = accentWidth ?? 3;
|
|
2193
|
+
own.borderLeftColor = accentColor ?? "var(--color-brand-primary)";
|
|
2171
2194
|
}
|
|
2172
|
-
if (
|
|
2173
|
-
return [
|
|
2174
|
-
}, [style,
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2195
|
+
if (borderColor) own.borderColor = borderColor;
|
|
2196
|
+
return style ? [own, style] : own;
|
|
2197
|
+
}, [style, depth, bgColor, borderColor, variant, accentWidth, accentColor]);
|
|
2198
|
+
const context = useMemo(
|
|
2199
|
+
() => ({ mode: depth.mode, level: depth.plane }),
|
|
2200
|
+
[depth.mode, depth.plane]
|
|
2201
|
+
);
|
|
2202
|
+
const content = isLoading ? /* @__PURE__ */ jsx(
|
|
2203
|
+
SkeletonBody,
|
|
2204
|
+
{
|
|
2205
|
+
hasHeader: skeletonHasHeader,
|
|
2206
|
+
hasFooter: skeletonHasFooter,
|
|
2207
|
+
contentLines: skeletonContentLines
|
|
2208
|
+
}
|
|
2209
|
+
) : children;
|
|
2210
|
+
return /* @__PURE__ */ jsx(SurfaceContext.Provider, { value: context, children: isClickable ? /* @__PURE__ */ jsx(
|
|
2211
|
+
Pressable,
|
|
2212
|
+
{
|
|
2213
|
+
onPress,
|
|
2214
|
+
onHoverIn: () => setIsHovered(true),
|
|
2215
|
+
onHoverOut: () => setIsHovered(false),
|
|
2216
|
+
accessibilityRole: "button",
|
|
2217
|
+
className: baseClassName,
|
|
2218
|
+
style: mergedStyle,
|
|
2219
|
+
...props,
|
|
2220
|
+
children: content
|
|
2221
|
+
}
|
|
2222
|
+
) : /* @__PURE__ */ jsx(View, { className: baseClassName, style: mergedStyle, ...props, children: content }) });
|
|
2191
2223
|
}
|
|
2192
2224
|
function CardHeader({ children, className }) {
|
|
2193
2225
|
return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-6", className), children });
|
|
@@ -2198,60 +2230,122 @@ function CardContent({ children, className }) {
|
|
|
2198
2230
|
function CardFooter({ children, className }) {
|
|
2199
2231
|
return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4 flex-row items-center gap-2", className), children });
|
|
2200
2232
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
}
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
}
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2233
|
+
function SkeletonBody({ hasHeader, hasFooter, contentLines }) {
|
|
2234
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2235
|
+
hasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
2236
|
+
/* @__PURE__ */ jsx(View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
|
|
2237
|
+
/* @__PURE__ */ jsx(View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
|
|
2238
|
+
] }),
|
|
2239
|
+
/* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: contentLines }).map((_, i) => /* @__PURE__ */ jsx(
|
|
2240
|
+
View,
|
|
2241
|
+
{
|
|
2242
|
+
className: cn(
|
|
2243
|
+
"h-4 bg-interactive-disabled rounded",
|
|
2244
|
+
i < contentLines - 1 ? "mb-2 w-full" : "w-4/5"
|
|
2245
|
+
)
|
|
2246
|
+
},
|
|
2247
|
+
i
|
|
2248
|
+
)) }),
|
|
2249
|
+
hasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
|
|
2250
|
+
] });
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
// src/utils/colors.ts
|
|
2254
|
+
function alpha(color, opacity) {
|
|
2255
|
+
const clampedOpacity = Math.max(0, Math.min(1, opacity));
|
|
2256
|
+
if (color.startsWith("#")) {
|
|
2257
|
+
const hex = color.slice(1);
|
|
2258
|
+
let r, g, b;
|
|
2259
|
+
if (hex.length === 3) {
|
|
2260
|
+
r = parseInt(hex[0] + hex[0], 16);
|
|
2261
|
+
g = parseInt(hex[1] + hex[1], 16);
|
|
2262
|
+
b = parseInt(hex[2] + hex[2], 16);
|
|
2263
|
+
} else if (hex.length === 6) {
|
|
2264
|
+
r = parseInt(hex.slice(0, 2), 16);
|
|
2265
|
+
g = parseInt(hex.slice(2, 4), 16);
|
|
2266
|
+
b = parseInt(hex.slice(4, 6), 16);
|
|
2267
|
+
} else {
|
|
2268
|
+
return color;
|
|
2269
|
+
}
|
|
2270
|
+
return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
|
|
2271
|
+
}
|
|
2272
|
+
const rgbMatch = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
|
|
2273
|
+
if (rgbMatch) {
|
|
2274
|
+
const [, r, g, b] = rgbMatch;
|
|
2275
|
+
return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
|
|
2224
2276
|
}
|
|
2277
|
+
const rgbaMatch = color.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/);
|
|
2278
|
+
if (rgbaMatch) {
|
|
2279
|
+
const [, r, g, b] = rgbaMatch;
|
|
2280
|
+
return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
|
|
2281
|
+
}
|
|
2282
|
+
return color;
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
// src/components/custom/Workout/StatusDot.tsx
|
|
2286
|
+
var solidFillToken = {
|
|
2287
|
+
success: "status-success",
|
|
2288
|
+
warning: "status-warning",
|
|
2289
|
+
error: "status-error",
|
|
2290
|
+
neutral: "text-tertiary"
|
|
2225
2291
|
};
|
|
2226
|
-
var
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
error: { boxShadow: "0 0 4px rgba(239,68,68,0.4)" },
|
|
2230
|
-
neutral: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" },
|
|
2231
|
-
"on-track": { boxShadow: "0 0 4px rgba(46,213,115,0.4)" },
|
|
2232
|
-
deviation: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
|
|
2233
|
-
future: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" }
|
|
2292
|
+
var ringWashToken = {
|
|
2293
|
+
"on-track": { fill: "status-success-subtle", border: "status-success-muted" },
|
|
2294
|
+
deviation: { fill: "status-warning-subtle", border: "status-warning-muted" }
|
|
2234
2295
|
};
|
|
2296
|
+
var FUTURE_FILL = alpha(greyRamp[500], 0.1);
|
|
2297
|
+
var FUTURE_BORDER = alpha(greyRamp[500], 0.2);
|
|
2298
|
+
var glyphToken = {
|
|
2299
|
+
success: "text-inverse",
|
|
2300
|
+
warning: "text-inverse",
|
|
2301
|
+
error: "text-inverse",
|
|
2302
|
+
neutral: "text-inverse",
|
|
2303
|
+
"on-track": "status-success",
|
|
2304
|
+
deviation: "status-warning",
|
|
2305
|
+
future: "text-tertiary"
|
|
2306
|
+
};
|
|
2307
|
+
var glowColors2 = {
|
|
2308
|
+
success: semanticColorsDark["status-success"],
|
|
2309
|
+
warning: semanticColorsDark["status-warning"],
|
|
2310
|
+
error: semanticColorsDark["status-error"],
|
|
2311
|
+
neutral: greyRamp[500],
|
|
2312
|
+
"on-track": semanticColorsDark["status-success"],
|
|
2313
|
+
deviation: semanticColorsDark["status-warning"],
|
|
2314
|
+
future: greyRamp[500]
|
|
2315
|
+
};
|
|
2316
|
+
var glowStyles = Object.fromEntries(
|
|
2317
|
+
Object.entries(glowColors2).map(([variant, color]) => [variant, getGlowShadow(color, "subtle")])
|
|
2318
|
+
);
|
|
2235
2319
|
var iconChars = {
|
|
2236
2320
|
check: "\u2713",
|
|
2237
2321
|
exclamation: "!",
|
|
2238
2322
|
dash: "\u2014"
|
|
2239
2323
|
};
|
|
2240
|
-
var iconColors = {
|
|
2241
|
-
success: "#0A5C52",
|
|
2242
|
-
warning: "#6B4000",
|
|
2243
|
-
error: "#5C1A1A",
|
|
2244
|
-
neutral: greyRamp[200],
|
|
2245
|
-
"on-track": t2["status-success"],
|
|
2246
|
-
deviation: t2["status-warning"],
|
|
2247
|
-
future: greyRamp[500]
|
|
2248
|
-
};
|
|
2249
2324
|
var sizeDimensions = {
|
|
2250
2325
|
sm: { size: 8, showIcon: false },
|
|
2251
2326
|
md: { size: 18, showIcon: true }
|
|
2252
2327
|
};
|
|
2253
2328
|
function isSolidVariant(variant) {
|
|
2254
|
-
return variant in
|
|
2329
|
+
return variant in solidFillToken;
|
|
2330
|
+
}
|
|
2331
|
+
function ringStyle(variant) {
|
|
2332
|
+
if (variant === "future") {
|
|
2333
|
+
return {
|
|
2334
|
+
backgroundColor: FUTURE_FILL,
|
|
2335
|
+
borderWidth: 1,
|
|
2336
|
+
borderStyle: "dashed",
|
|
2337
|
+
borderColor: FUTURE_BORDER
|
|
2338
|
+
};
|
|
2339
|
+
}
|
|
2340
|
+
if (variant === "on-track" || variant === "deviation") {
|
|
2341
|
+
const tokens = ringWashToken[variant];
|
|
2342
|
+
return {
|
|
2343
|
+
backgroundColor: resolveColor(tokens.fill),
|
|
2344
|
+
borderWidth: 1,
|
|
2345
|
+
borderColor: resolveColor(tokens.border)
|
|
2346
|
+
};
|
|
2347
|
+
}
|
|
2348
|
+
return void 0;
|
|
2255
2349
|
}
|
|
2256
2350
|
function StatusDot({
|
|
2257
2351
|
variant,
|
|
@@ -2264,7 +2358,7 @@ function StatusDot({
|
|
|
2264
2358
|
}) {
|
|
2265
2359
|
const config = sizeDimensions[size];
|
|
2266
2360
|
const solid = isSolidVariant(variant);
|
|
2267
|
-
const ring =
|
|
2361
|
+
const ring = ringStyle(variant);
|
|
2268
2362
|
const glowStyle = glow ? glowStyles[variant] : null;
|
|
2269
2363
|
const dot = /* @__PURE__ */ jsx(
|
|
2270
2364
|
View,
|
|
@@ -2278,22 +2372,22 @@ function StatusDot({
|
|
|
2278
2372
|
justifyContent: "center",
|
|
2279
2373
|
flexShrink: 0
|
|
2280
2374
|
},
|
|
2281
|
-
solid ? { backgroundColor:
|
|
2282
|
-
ring
|
|
2375
|
+
solid ? { backgroundColor: resolveColor(solidFillToken[variant]) } : void 0,
|
|
2376
|
+
ring,
|
|
2283
2377
|
glowStyle ? glowStyle : void 0
|
|
2284
2378
|
],
|
|
2285
2379
|
accessibilityRole: "image",
|
|
2286
2380
|
accessibilityLabel: `${variant} status`,
|
|
2287
2381
|
testID: "status-dot",
|
|
2288
|
-
children: config.showIcon && icon &&
|
|
2289
|
-
|
|
2382
|
+
children: config.showIcon && icon && // The glyph was 11px/900, off the type scale (TOKENS.md §4); `boldLabel` is
|
|
2383
|
+
// the 12px sans label step and `font-black` keeps the original weight.
|
|
2384
|
+
/* @__PURE__ */ jsx(
|
|
2385
|
+
Typography,
|
|
2290
2386
|
{
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
color: iconColors[variant]
|
|
2296
|
-
},
|
|
2387
|
+
variant: "boldLabel",
|
|
2388
|
+
color: "inherit",
|
|
2389
|
+
className: "font-black leading-none",
|
|
2390
|
+
style: { color: resolveColor(glyphToken[variant]) },
|
|
2297
2391
|
accessibilityElementsHidden: true,
|
|
2298
2392
|
children: iconChars[icon]
|
|
2299
2393
|
}
|
|
@@ -2311,9 +2405,11 @@ function StatusDot({
|
|
|
2311
2405
|
children: [
|
|
2312
2406
|
/* @__PURE__ */ jsx(View, { accessibilityElementsHidden: true, children: dot }),
|
|
2313
2407
|
/* @__PURE__ */ jsx(
|
|
2314
|
-
|
|
2408
|
+
Typography,
|
|
2315
2409
|
{
|
|
2316
|
-
|
|
2410
|
+
variant: "caption",
|
|
2411
|
+
color: "secondary",
|
|
2412
|
+
className: "leading-4",
|
|
2317
2413
|
accessibilityElementsHidden: true,
|
|
2318
2414
|
children: label
|
|
2319
2415
|
}
|
|
@@ -2329,13 +2425,13 @@ var MESO_ACCENT_GRADIENT_LIGHT = primitiveRamps.orange[300];
|
|
|
2329
2425
|
|
|
2330
2426
|
// src/components/custom/Workout/MesoStatusCard.tsx
|
|
2331
2427
|
var t3 = getSemanticColors("dark");
|
|
2332
|
-
var
|
|
2428
|
+
var BRAND_PRIMARY3 = t3["brand-primary"];
|
|
2333
2429
|
var BRAND_PRIMARY_DARK = MESO_ACCENT_GRADIENT_DARK;
|
|
2334
2430
|
var BRAND_PRIMARY_LIGHT = MESO_ACCENT_GRADIENT_LIGHT;
|
|
2335
2431
|
var SUCCESS = t3["status-success"];
|
|
2336
2432
|
var WARNING = t3["status-warning"];
|
|
2337
2433
|
var ERROR = t3["status-error"];
|
|
2338
|
-
var ACCENT_STOPS = [BRAND_PRIMARY_DARK,
|
|
2434
|
+
var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY3, BRAND_PRIMARY_LIGHT];
|
|
2339
2435
|
var CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor("surface-elevated")} 0%, ${resolveColor("surface-raised")} 100%)`;
|
|
2340
2436
|
var GAUGE_GRADIENT = "linear-gradient(90deg, rgba(46,213,115,0.25) 0%, rgba(249,180,21,0.25) 50%, rgba(209,67,67,0.25) 100%)";
|
|
2341
2437
|
var STATUS_VARIANTS = {
|
|
@@ -2360,15 +2456,7 @@ function renderCoachingText(text, highlights) {
|
|
|
2360
2456
|
if (escaped.length === 0) return text;
|
|
2361
2457
|
const regex = new RegExp(`(${escaped.join("|")})`, "g");
|
|
2362
2458
|
return text.split(regex).map(
|
|
2363
|
-
(part, index) => highlights.includes(part) ? /* @__PURE__ */ jsx(
|
|
2364
|
-
Text,
|
|
2365
|
-
{
|
|
2366
|
-
className: "text-text-primary",
|
|
2367
|
-
style: { fontWeight: "700" },
|
|
2368
|
-
children: part
|
|
2369
|
-
},
|
|
2370
|
-
`${part}-${index}`
|
|
2371
|
-
) : /* @__PURE__ */ jsx(Fragment$1, { children: part }, `t-${index}`)
|
|
2459
|
+
(part, index) => highlights.includes(part) ? /* @__PURE__ */ jsx(Text, { className: "text-text-primary", style: { fontWeight: "700" }, children: part }, `${part}-${index}`) : /* @__PURE__ */ jsx(Fragment, { children: part }, `t-${index}`)
|
|
2372
2460
|
);
|
|
2373
2461
|
}
|
|
2374
2462
|
function StatusPill({ badge }) {
|
|
@@ -2453,41 +2541,34 @@ function Gauge({ gauge }) {
|
|
|
2453
2541
|
"aria-valuemax": 100,
|
|
2454
2542
|
testID: "meso-status-card-gauge",
|
|
2455
2543
|
children: [
|
|
2456
|
-
/* @__PURE__ */ jsxs(
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
},
|
|
2485
|
-
children: gauge.sublabel
|
|
2486
|
-
}
|
|
2487
|
-
)
|
|
2488
|
-
]
|
|
2489
|
-
}
|
|
2490
|
-
),
|
|
2544
|
+
/* @__PURE__ */ jsxs(View, { className: "flex-row items-center justify-between", accessibilityElementsHidden: true, children: [
|
|
2545
|
+
/* @__PURE__ */ jsx(
|
|
2546
|
+
Text,
|
|
2547
|
+
{
|
|
2548
|
+
className: "text-text-secondary",
|
|
2549
|
+
style: {
|
|
2550
|
+
fontSize: 10,
|
|
2551
|
+
fontFamily: "Inter, sans-serif",
|
|
2552
|
+
fontWeight: "500",
|
|
2553
|
+
letterSpacing: 0.5,
|
|
2554
|
+
textTransform: "uppercase"
|
|
2555
|
+
},
|
|
2556
|
+
children: gauge.label
|
|
2557
|
+
}
|
|
2558
|
+
),
|
|
2559
|
+
gauge.sublabel != null && /* @__PURE__ */ jsx(
|
|
2560
|
+
Text,
|
|
2561
|
+
{
|
|
2562
|
+
className: "text-text-tertiary",
|
|
2563
|
+
style: {
|
|
2564
|
+
fontSize: 10,
|
|
2565
|
+
fontFamily: "Inter, sans-serif",
|
|
2566
|
+
fontWeight: "500"
|
|
2567
|
+
},
|
|
2568
|
+
children: gauge.sublabel
|
|
2569
|
+
}
|
|
2570
|
+
)
|
|
2571
|
+
] }),
|
|
2491
2572
|
/* @__PURE__ */ jsxs(
|
|
2492
2573
|
View,
|
|
2493
2574
|
{
|
|
@@ -2528,7 +2609,8 @@ function Gauge({ gauge }) {
|
|
|
2528
2609
|
borderRadius: 9999,
|
|
2529
2610
|
borderWidth: 2,
|
|
2530
2611
|
backgroundColor: markerColor,
|
|
2531
|
-
|
|
2612
|
+
// A knob resting on the gauge: lift, with the ring as its edge.
|
|
2613
|
+
...liftStyle(1, "dark", { rim: 0 })
|
|
2532
2614
|
},
|
|
2533
2615
|
testID: "meso-status-card-gauge-marker"
|
|
2534
2616
|
}
|
|
@@ -2580,30 +2662,23 @@ function MesoStatusCard({
|
|
|
2580
2662
|
),
|
|
2581
2663
|
/* @__PURE__ */ jsxs(View, { style: { padding: 14, gap: 14 }, testID: "meso-status-card-body", children: [
|
|
2582
2664
|
/* @__PURE__ */ jsxs(View, { testID: "meso-status-card-header", children: [
|
|
2583
|
-
/* @__PURE__ */ jsxs(
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
children: mesoName
|
|
2601
|
-
}
|
|
2602
|
-
),
|
|
2603
|
-
/* @__PURE__ */ jsx(StatusPill, { badge: statusBadge })
|
|
2604
|
-
]
|
|
2605
|
-
}
|
|
2606
|
-
),
|
|
2665
|
+
/* @__PURE__ */ jsxs(View, { className: "flex-row items-center justify-between", style: { gap: 8 }, children: [
|
|
2666
|
+
/* @__PURE__ */ jsx(
|
|
2667
|
+
Text,
|
|
2668
|
+
{
|
|
2669
|
+
className: "text-text-primary",
|
|
2670
|
+
style: {
|
|
2671
|
+
flexShrink: 1,
|
|
2672
|
+
fontSize: 15,
|
|
2673
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
2674
|
+
fontWeight: "700"
|
|
2675
|
+
},
|
|
2676
|
+
testID: "meso-status-card-name",
|
|
2677
|
+
children: mesoName
|
|
2678
|
+
}
|
|
2679
|
+
),
|
|
2680
|
+
/* @__PURE__ */ jsx(StatusPill, { badge: statusBadge })
|
|
2681
|
+
] }),
|
|
2607
2682
|
/* @__PURE__ */ jsx(
|
|
2608
2683
|
Text,
|
|
2609
2684
|
{
|
|
@@ -2618,15 +2693,7 @@ function MesoStatusCard({
|
|
|
2618
2693
|
}
|
|
2619
2694
|
)
|
|
2620
2695
|
] }),
|
|
2621
|
-
metrics.length > 0 && /* @__PURE__ */ jsx(
|
|
2622
|
-
View,
|
|
2623
|
-
{
|
|
2624
|
-
className: "flex-row flex-wrap",
|
|
2625
|
-
style: { gap: 8 },
|
|
2626
|
-
testID: "meso-status-card-metrics",
|
|
2627
|
-
children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell, { metric }, `${metric.label}-${index}`))
|
|
2628
|
-
}
|
|
2629
|
-
),
|
|
2696
|
+
metrics.length > 0 && /* @__PURE__ */ jsx(View, { className: "flex-row flex-wrap", style: { gap: 8 }, testID: "meso-status-card-metrics", children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell, { metric }, `${metric.label}-${index}`)) }),
|
|
2630
2697
|
gauges.length > 0 && /* @__PURE__ */ jsx(View, { style: { gap: 12 }, testID: "meso-status-card-gauges", children: gauges.map((gauge, index) => /* @__PURE__ */ jsx(Gauge, { gauge }, `${gauge.label}-${index}`)) }),
|
|
2631
2698
|
coaching != null && /* @__PURE__ */ jsx(
|
|
2632
2699
|
View,
|