@titan-design/react-ui 0.12.1 → 0.14.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 +60 -47
- package/dist/bodymap.js +856 -736
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +858 -738
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +1431 -237
- package/dist/index.d.ts +1431 -237
- package/dist/index.js +6506 -4781
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6280 -4642
- package/dist/index.mjs.map +1 -1
- package/dist/{pages-B1hqnGIC.d.ts → pages-CsjsUn0G.d.ts} +51 -16
- package/dist/{pages-CvsFqNtx.d.mts → pages-ZbT_pD_U.d.mts} +51 -16
- package/dist/pages.d.mts +1 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +1919 -1937
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +1927 -1945
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +225 -140
- package/dist/theme/index.d.ts +225 -140
- package/dist/theme/index.js +298 -319
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +283 -315
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +145 -24
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +145 -24
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/dist/theme/tokens.d.mts +128 -11
- package/dist/theme/tokens.d.ts +128 -11
- package/dist/theme/tokens.js +126 -26
- package/dist/theme/tokens.js.map +1 -1
- package/dist/theme/tokens.mjs +124 -27
- package/dist/theme/tokens.mjs.map +1 -1
- 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/docs/render-testing-pattern.md +130 -0
- package/package.json +1 -1
- package/src/arch/Architecture.stories.tsx +3 -1
- package/src/arch/arch-graph.freshness.test.ts +52 -0
- package/src/arch/arch-graph.json +4989 -1583
- 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 +182 -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 +12 -6
- 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 +6 -3
- package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.tsx +7 -2
- 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 +55 -14
- package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
- package/src/components/custom/Scatter/Scatter.tsx +122 -18
- package/src/components/custom/Sidebar/Sidebar.stories.tsx +41 -8
- 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 +99 -16
- 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 +15 -12
- package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
- package/src/components/custom/Treemap/Treemap.tsx +11 -3
- 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 +11 -2
- package/src/components/custom/Workout/BaseBadge.stories.tsx +27 -11
- package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
- package/src/components/custom/Workout/BaseBadge.tsx +6 -2
- package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
- package/src/components/custom/Workout/BodyMap.tsx +8 -4
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +28 -6
- package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +50 -12
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +12 -9
- package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
- package/src/components/custom/Workout/CapacityBandChart.tsx +144 -111
- package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.test.tsx +10 -4
- package/src/components/custom/Workout/DeviationBar.tsx +24 -16
- package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +183 -0
- package/src/components/custom/Workout/DualVelocityStrip.test.tsx +32 -18
- package/src/components/custom/Workout/ExerciseCard.stories.tsx +12 -11
- package/src/components/custom/Workout/ExerciseCard.test.tsx +52 -22
- package/src/components/custom/Workout/ExerciseCard.tsx +99 -183
- package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +95 -12
- package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +189 -1
- package/src/components/custom/Workout/ExerciseCardHeading.tsx +167 -18
- package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +3 -2
- package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
- package/src/components/custom/Workout/ExerciseHeading.tsx +194 -46
- package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +12 -9
- 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/InputBar.tsx +4 -2
- 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 +8 -3
- 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 +14 -10
- 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 +20 -33
- 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 +9 -4
- 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 +16 -3
- 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 +68 -17
- 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 +22 -4
- package/src/components/custom/Workout/RestTimer.stories.tsx +16 -4
- package/src/components/custom/Workout/RestTimer.tsx +4 -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 +21 -17
- package/src/components/custom/Workout/SegmentedBar.tsx +10 -5
- 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 +63 -7
- 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 +24 -12
- package/src/components/custom/Workout/Sparkline.stories.tsx +14 -11
- 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 +11 -4
- package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
- package/src/components/custom/Workout/StrengthTrendChart.tsx +39 -36
- 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 +26 -10
- package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
- package/src/components/custom/Workout/TempoDisplay.tsx +2 -0
- 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 +10 -6
- package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +5 -2
- package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +44 -1
- package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
- package/src/components/custom/Workout/VelocityStrip.test.tsx +48 -6
- package/src/components/custom/Workout/VelocityStrip.tsx +26 -14
- 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 +10 -7
- package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
- package/src/components/custom/Workout/exerciseRowState.ts +29 -0
- package/src/components/custom/Workout/index.ts +17 -2
- package/src/components/custom/Workout/metricText.stories.tsx +15 -13
- package/src/components/custom/Workout/metricText.tsx +8 -2
- package/src/components/custom/Workout/setHeadingKit.tsx +219 -36
- package/src/components/custom/Workout/velocity-story-kit.tsx +2 -2
- package/src/components/custom/charts/README.md +66 -0
- package/src/components/custom/charts/SetBarChart.test.tsx +46 -1
- package/src/components/custom/charts/SetBarChart.tsx +56 -9
- 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/flatBarGeometry.test.ts +41 -0
- package/src/components/custom/charts/flatBarGeometry.ts +32 -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 +21 -34
- 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 +89 -26
- 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 +15 -5
- package/src/components/ui/alert/Alert.tsx +24 -3
- 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 +44 -37
- 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 +7 -27
- 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 +14 -3
- 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 -27
- 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 +10 -18
- package/src/components/ui/indicator/Indicator.stories.tsx +5 -4
- 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 +17 -5
- 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 +31 -19
- package/src/components/ui/pill/Pill.stories.tsx +111 -23
- package/src/components/ui/pill/Pill.test.tsx +101 -3
- package/src/components/ui/pill/Pill.tsx +168 -49
- package/src/components/ui/pill/index.ts +1 -1
- package/src/components/ui/popover/Popover.stories.tsx +6 -8
- 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/progress/Progress.tsx +9 -6
- 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 +12 -21
- 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 +16 -15
- 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 +4 -5
- package/src/components/ui/stack/Stack.stories.tsx +8 -8
- package/src/components/ui/stack/Stack.tsx +1 -1
- package/src/components/ui/surface/Surface.stories.tsx +92 -33
- 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 +8 -21
- 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 +49 -57
- 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 +38 -49
- 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 +101 -48
- package/src/test/no-device-internals.test.ts +3 -3
- package/src/test/no-raw-color.test.ts +39 -0
- package/src/theme/Alpha.stories.tsx +103 -0
- 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 +23 -21
- package/src/theme/ProposedTokensVW82.stories.tsx +414 -0
- 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 +40 -0
- package/src/theme/elevation.test.ts +82 -56
- package/src/theme/elevation.ts +77 -561
- package/src/theme/global.css +45 -5
- 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/subtle-tone-weight.test.ts +163 -0
- package/src/theme/surface-planes.test.ts +37 -0
- package/src/theme/surface-planes.ts +68 -0
- package/src/theme/tailwind-var-opacity.test.ts +163 -0
- package/src/theme/token-export-guard.test.ts +1 -3
- package/src/theme/tokens/primitives.test.ts +15 -7
- package/src/theme/tokens/primitives.ts +98 -33
- package/src/theme/tokens/semantic-hex-guard.test.ts +322 -0
- package/src/theme/tokens/semantic.ts +124 -54
- 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.alpha-adoption.test.ts +408 -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 +55 -9
- 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.js
CHANGED
|
@@ -18,7 +18,29 @@ function cn(...inputs) {
|
|
|
18
18
|
|
|
19
19
|
// src/theme/tokens/primitives.ts
|
|
20
20
|
var primitiveColors = {
|
|
21
|
-
white: "#FFFFFF"
|
|
21
|
+
white: "#FFFFFF",
|
|
22
|
+
black: "#000000"};
|
|
23
|
+
var alertRedVivid = "#FF4757";
|
|
24
|
+
var resultPaletteColors = {
|
|
25
|
+
improve: "#4caf50",
|
|
26
|
+
improveDark: "#248a24",
|
|
27
|
+
degrade: "#ef5350",
|
|
28
|
+
degradeDark: "#b30000",
|
|
29
|
+
inconclusive: "#9E9A97"
|
|
30
|
+
};
|
|
31
|
+
var semanticPins = {
|
|
32
|
+
// Cool navy-black; darker and more blue-shifted than any warm greyRamp step.
|
|
33
|
+
textPrimaryLight: "#121828",
|
|
34
|
+
// Cool blue-grey; outside greyRamp's warm (R>=G>=B) scale.
|
|
35
|
+
textSecondaryLight: "#65748B",
|
|
36
|
+
// Pure neutral grey (R=G=B); no warm greyRamp step lands on it exactly.
|
|
37
|
+
backgroundBaseLight: "#EBEBEB",
|
|
38
|
+
// Near-neutral grey, kept one step off backgroundBaseLight by design.
|
|
39
|
+
dividerLight: "#E8E9EB",
|
|
40
|
+
// Periwinkle/indigo; more purple than any primitiveRamps.blue step. Shared by
|
|
41
|
+
// dark-mode text-link, border-focus and border-input-focus.
|
|
42
|
+
focusIndigoDark: "#828DF8"
|
|
43
|
+
};
|
|
22
44
|
var greyRamp = {
|
|
23
45
|
50: "#F9F6F3",
|
|
24
46
|
// L*97.0 W6
|
|
@@ -52,6 +74,7 @@ var greyRamp = {
|
|
|
52
74
|
var primitiveRamps = {
|
|
53
75
|
red: {
|
|
54
76
|
50: "#FFF4F4",
|
|
77
|
+
400: "#F77175",
|
|
55
78
|
500: "#E05254",
|
|
56
79
|
600: "#D14343",
|
|
57
80
|
// pin
|
|
@@ -141,22 +164,34 @@ var semanticColorsLight = {
|
|
|
141
164
|
"brand-primary-light": primitiveRamps.orange[300],
|
|
142
165
|
"brand-primary-dark": primitiveRamps.orange[500],
|
|
143
166
|
"brand-primary-subtle": "rgba(255, 121, 0, 0.08)",
|
|
167
|
+
"brand-primary-muted": "rgba(255, 121, 0, 0.30)",
|
|
168
|
+
"brand-primary-strong": "rgba(255, 121, 0, 0.50)",
|
|
144
169
|
"brand-primary-hover": primitiveRamps.orange[500],
|
|
145
170
|
"brand-primary-active": primitiveRamps.orange[600],
|
|
146
171
|
"brand-secondary": primitiveRamps.cyan[600],
|
|
147
172
|
"brand-secondary-light": primitiveRamps.cyan[500],
|
|
148
173
|
"brand-secondary-dark": primitiveRamps.cyan[700],
|
|
149
174
|
"brand-secondary-subtle": "rgba(48, 123, 155, 0.08)",
|
|
175
|
+
"brand-secondary-muted": "rgba(48, 123, 155, 0.30)",
|
|
176
|
+
"brand-secondary-strong": "rgba(48, 123, 155, 0.50)",
|
|
150
177
|
"brand-secondary-hover": primitiveRamps.cyan[700],
|
|
151
178
|
"brand-secondary-active": primitiveRamps.cyan[800],
|
|
152
179
|
// Text on brand backgrounds (on-*)
|
|
153
180
|
"on-brand-primary": primitiveColors.white,
|
|
154
181
|
"on-brand-secondary": primitiveColors.white,
|
|
182
|
+
// Text ON a `-subtle` fill. Light mode keeps today's pairing (the base token) so
|
|
183
|
+
// nothing moves here: light has the same disease mirrored — a light rung on a
|
|
184
|
+
// near-white ramp[50] fill — but correcting it belongs with the light-mode pass
|
|
185
|
+
// in AW-121, not this one.
|
|
186
|
+
"on-brand-primary-subtle": primitiveRamps.orange[400],
|
|
187
|
+
"on-brand-secondary-subtle": primitiveRamps.cyan[600],
|
|
155
188
|
// Status colors (status-*)
|
|
156
189
|
"status-success": primitiveRamps.green[300],
|
|
157
190
|
"status-success-light": primitiveRamps.green[200],
|
|
158
191
|
"status-success-dark": primitiveRamps.green[600],
|
|
159
192
|
"status-success-subtle": primitiveRamps.green[50],
|
|
193
|
+
"status-success-muted": "rgba(46, 213, 115, 0.30)",
|
|
194
|
+
"status-success-strong": "rgba(46, 213, 115, 0.50)",
|
|
160
195
|
// Live-session accent — its OWN role, decoupled from success so the two can diverge
|
|
161
196
|
"status-live": primitiveRamps.green[300],
|
|
162
197
|
"status-live-muted": primitiveRamps.green[500],
|
|
@@ -164,34 +199,47 @@ var semanticColorsLight = {
|
|
|
164
199
|
"status-error-light": primitiveRamps.red[500],
|
|
165
200
|
"status-error-dark": primitiveRamps.red[700],
|
|
166
201
|
"status-error-subtle": primitiveRamps.red[50],
|
|
167
|
-
"status-error-
|
|
168
|
-
|
|
202
|
+
"status-error-muted": "rgba(209, 67, 67, 0.30)",
|
|
203
|
+
"status-error-strong": "rgba(209, 67, 67, 0.50)",
|
|
204
|
+
"status-error-vivid": alertRedVivid,
|
|
205
|
+
// NOT red[600], that is status-error
|
|
169
206
|
"status-error-vivid-light": primitiveRamps.red[500],
|
|
170
207
|
"status-error-vivid-dark": primitiveRamps.red[700],
|
|
171
208
|
"status-error-vivid-subtle": "rgba(255, 71, 87, 0.12)",
|
|
209
|
+
"status-error-vivid-muted": "rgba(255, 71, 87, 0.30)",
|
|
210
|
+
"status-error-vivid-strong": "rgba(255, 71, 87, 0.50)",
|
|
172
211
|
"status-warning": primitiveRamps.amber[300],
|
|
173
212
|
"status-warning-light": primitiveRamps.amber[200],
|
|
174
213
|
"status-warning-dark": primitiveRamps.amber[500],
|
|
175
214
|
"status-warning-subtle": primitiveRamps.amber[50],
|
|
215
|
+
"status-warning-muted": "rgba(249, 180, 21, 0.30)",
|
|
216
|
+
"status-warning-strong": "rgba(249, 180, 21, 0.50)",
|
|
176
217
|
"status-info": primitiveRamps.blue[500],
|
|
177
218
|
"status-info-light": primitiveRamps.blue[300],
|
|
178
219
|
"status-info-dark": primitiveRamps.blue[600],
|
|
179
220
|
"status-info-subtle": primitiveRamps.blue[50],
|
|
221
|
+
"status-info-muted": "rgba(33, 150, 243, 0.30)",
|
|
222
|
+
"status-info-strong": "rgba(33, 150, 243, 0.50)",
|
|
223
|
+
// Text ON a `-subtle` fill — see the on-brand-*-subtle note above.
|
|
224
|
+
"on-status-success-subtle": primitiveRamps.green[300],
|
|
225
|
+
"on-status-error-subtle": primitiveRamps.red[600],
|
|
226
|
+
"on-status-warning-subtle": primitiveRamps.amber[300],
|
|
227
|
+
"on-status-info-subtle": primitiveRamps.blue[500],
|
|
180
228
|
// Text on status backgrounds (on-status-*)
|
|
181
229
|
"on-status-success": primitiveColors.white,
|
|
182
230
|
"on-status-error": primitiveColors.white,
|
|
183
231
|
"on-status-warning": primitiveColors.white,
|
|
184
232
|
"on-status-info": primitiveColors.white,
|
|
185
233
|
// Result/outcome indicators (result-*)
|
|
186
|
-
"result-improve":
|
|
234
|
+
"result-improve": resultPaletteColors.improve,
|
|
187
235
|
// Green - positive outcome
|
|
188
236
|
"result-improve-light": "rgba(76, 175, 80, 0.12)",
|
|
189
|
-
"result-improve-dark":
|
|
190
|
-
"result-degrade":
|
|
237
|
+
"result-improve-dark": resultPaletteColors.improveDark,
|
|
238
|
+
"result-degrade": resultPaletteColors.degrade,
|
|
191
239
|
// Red - negative outcome
|
|
192
240
|
"result-degrade-light": "rgba(239, 83, 80, 0.12)",
|
|
193
|
-
"result-degrade-dark":
|
|
194
|
-
"result-inconclusive":
|
|
241
|
+
"result-degrade-dark": resultPaletteColors.degradeDark,
|
|
242
|
+
"result-inconclusive": resultPaletteColors.inconclusive,
|
|
195
243
|
// Gray - no clear result
|
|
196
244
|
"result-inconclusive-light": "rgba(158, 154, 151, 0.12)",
|
|
197
245
|
"result-neutral": greyRamp[600],
|
|
@@ -223,8 +271,8 @@ var semanticColorsLight = {
|
|
|
223
271
|
"data-10": discreteRainbow[22],
|
|
224
272
|
// Dark Orange
|
|
225
273
|
// Text colors (text-*)
|
|
226
|
-
"text-primary":
|
|
227
|
-
"text-secondary":
|
|
274
|
+
"text-primary": semanticPins.textPrimaryLight,
|
|
275
|
+
"text-secondary": semanticPins.textSecondaryLight,
|
|
228
276
|
"text-tertiary": greyRamp[400],
|
|
229
277
|
"text-disabled": "rgba(55, 65, 81, 0.48)",
|
|
230
278
|
"text-inverse": primitiveColors.white,
|
|
@@ -240,7 +288,7 @@ var semanticColorsLight = {
|
|
|
240
288
|
"surface-input": greyRamp[50],
|
|
241
289
|
// Input field background (filled variant)
|
|
242
290
|
// Background colors (background-*)
|
|
243
|
-
"background-base":
|
|
291
|
+
"background-base": semanticPins.backgroundBaseLight,
|
|
244
292
|
"background-default": primitiveColors.white,
|
|
245
293
|
"background-subtle": greyRamp[50],
|
|
246
294
|
// Frame/bezel chrome — top bar + side nav shell, one step below
|
|
@@ -271,7 +319,7 @@ var semanticColorsLight = {
|
|
|
271
319
|
"interactive-disabled": "rgba(55, 65, 81, 0.12)",
|
|
272
320
|
"interactive-disabled-text": "rgba(55, 65, 81, 0.26)",
|
|
273
321
|
// Divider
|
|
274
|
-
|
|
322
|
+
divider: semanticPins.dividerLight,
|
|
275
323
|
// Avatar default
|
|
276
324
|
"avatar-background": greyRamp[600],
|
|
277
325
|
"avatar-text": primitiveColors.white
|
|
@@ -282,54 +330,87 @@ var semanticColorsDark = {
|
|
|
282
330
|
"brand-primary-light": primitiveRamps.orange[300],
|
|
283
331
|
"brand-primary-dark": primitiveRamps.orange[500],
|
|
284
332
|
"brand-primary-subtle": "rgba(255, 121, 0, 0.12)",
|
|
333
|
+
"brand-primary-muted": "rgba(255, 121, 0, 0.30)",
|
|
334
|
+
"brand-primary-strong": "rgba(255, 121, 0, 0.50)",
|
|
285
335
|
"brand-primary-hover": primitiveRamps.orange[300],
|
|
286
336
|
"brand-primary-active": primitiveRamps.orange[200],
|
|
287
337
|
"brand-secondary": primitiveRamps.cyan[600],
|
|
288
338
|
"brand-secondary-light": primitiveRamps.cyan[500],
|
|
289
339
|
"brand-secondary-dark": primitiveRamps.cyan[700],
|
|
290
|
-
"brand-secondary-subtle": "rgba(
|
|
340
|
+
"brand-secondary-subtle": "rgba(34, 211, 238, 0.12)",
|
|
341
|
+
"brand-secondary-muted": "rgba(48, 123, 155, 0.30)",
|
|
342
|
+
"brand-secondary-strong": "rgba(48, 123, 155, 0.50)",
|
|
291
343
|
"brand-secondary-hover": primitiveRamps.cyan[500],
|
|
292
344
|
"brand-secondary-active": primitiveRamps.cyan[400],
|
|
293
345
|
// Text on brand backgrounds
|
|
294
346
|
"on-brand-primary": primitiveColors.white,
|
|
295
347
|
"on-brand-secondary": primitiveColors.white,
|
|
348
|
+
// Text ON a `-subtle` fill. Its own role: `brand-primary` and friends are tuned to
|
|
349
|
+
// carry a white label as a solid fill, which makes the two deepest of them
|
|
350
|
+
// (cyan[600], red[600]) too dark to read as text on a dark plane. Levelling the
|
|
351
|
+
// family at rung 300 puts every tone within OKLCH L 0.769-0.813 instead of
|
|
352
|
+
// 0.550-0.813. Brand is deliberately left at its own orange[400] (operator, AW-133)
|
|
353
|
+
// so the Voltras tone never drifts; it is the one tone under AA on a raised card.
|
|
354
|
+
"on-brand-primary-subtle": primitiveRamps.orange[400],
|
|
355
|
+
"on-brand-secondary-subtle": primitiveRamps.cyan[300],
|
|
296
356
|
// Status colors
|
|
297
357
|
"status-success": primitiveRamps.green[300],
|
|
298
358
|
"status-success-light": primitiveRamps.green[200],
|
|
299
359
|
"status-success-dark": primitiveRamps.green[600],
|
|
300
360
|
"status-success-subtle": "rgba(46, 213, 115, 0.12)",
|
|
361
|
+
"status-success-muted": "rgba(46, 213, 115, 0.30)",
|
|
362
|
+
"status-success-strong": "rgba(46, 213, 115, 0.50)",
|
|
301
363
|
// Live-session accent — its OWN role, decoupled from success so the two can diverge
|
|
302
364
|
"status-live": primitiveRamps.green[300],
|
|
303
365
|
"status-live-muted": primitiveRamps.green[500],
|
|
304
366
|
"status-error": primitiveRamps.red[600],
|
|
305
367
|
"status-error-light": primitiveRamps.red[500],
|
|
306
368
|
"status-error-dark": primitiveRamps.red[700],
|
|
307
|
-
|
|
308
|
-
|
|
369
|
+
// Alpha 0.08, not the family's 0.12: error's label is red[400], a rung darker than
|
|
370
|
+
// its siblings so it reads RED rather than pink (rung 300 has only 0.121 chroma).
|
|
371
|
+
// Thinning the fill buys back the contrast that extra darkness costs. See AW-133.
|
|
372
|
+
"status-error-subtle": "rgba(247, 113, 117, 0.08)",
|
|
373
|
+
"status-error-muted": "rgba(209, 67, 67, 0.30)",
|
|
374
|
+
"status-error-strong": "rgba(209, 67, 67, 0.50)",
|
|
375
|
+
"status-error-vivid": alertRedVivid,
|
|
309
376
|
"status-error-vivid-light": primitiveRamps.red[500],
|
|
310
377
|
"status-error-vivid-dark": primitiveRamps.red[700],
|
|
311
378
|
"status-error-vivid-subtle": "rgba(255, 71, 87, 0.12)",
|
|
379
|
+
"status-error-vivid-muted": "rgba(255, 71, 87, 0.30)",
|
|
380
|
+
"status-error-vivid-strong": "rgba(255, 71, 87, 0.50)",
|
|
312
381
|
"status-warning": primitiveRamps.amber[300],
|
|
313
382
|
"status-warning-light": primitiveRamps.amber[200],
|
|
314
383
|
"status-warning-dark": primitiveRamps.amber[500],
|
|
315
384
|
"status-warning-subtle": "rgba(249, 180, 21, 0.12)",
|
|
385
|
+
"status-warning-muted": "rgba(249, 180, 21, 0.30)",
|
|
386
|
+
"status-warning-strong": "rgba(249, 180, 21, 0.50)",
|
|
316
387
|
"status-info": primitiveRamps.blue[500],
|
|
317
388
|
"status-info-light": primitiveRamps.blue[300],
|
|
318
389
|
"status-info-dark": primitiveRamps.blue[600],
|
|
319
|
-
"status-info-subtle": "rgba(
|
|
390
|
+
"status-info-subtle": "rgba(120, 194, 255, 0.12)",
|
|
391
|
+
"status-info-muted": "rgba(33, 150, 243, 0.30)",
|
|
392
|
+
"status-info-strong": "rgba(33, 150, 243, 0.50)",
|
|
320
393
|
// Text on status backgrounds
|
|
321
394
|
"on-status-success": primitiveColors.white,
|
|
322
395
|
"on-status-error": primitiveColors.white,
|
|
323
396
|
"on-status-warning": primitiveColors.white,
|
|
324
397
|
"on-status-info": primitiveColors.white,
|
|
398
|
+
// Text ON a `-subtle` fill — see the on-brand-*-subtle note above. Error is the
|
|
399
|
+
// second deliberate exception to the rung-300 rule (operator, AW-133): red[300]
|
|
400
|
+
// levelled perfectly but read PINK, because a red that light can only hold 0.121
|
|
401
|
+
// chroma. red[400] carries 0.165 and reads red; its fill is thinned to compensate.
|
|
402
|
+
"on-status-success-subtle": primitiveRamps.green[300],
|
|
403
|
+
"on-status-error-subtle": primitiveRamps.red[400],
|
|
404
|
+
"on-status-warning-subtle": primitiveRamps.amber[300],
|
|
405
|
+
"on-status-info-subtle": primitiveRamps.blue[300],
|
|
325
406
|
// Result/outcome indicators (result-*)
|
|
326
|
-
"result-improve":
|
|
407
|
+
"result-improve": resultPaletteColors.improve,
|
|
327
408
|
"result-improve-light": "rgba(76, 175, 80, 0.16)",
|
|
328
|
-
"result-improve-dark":
|
|
329
|
-
"result-degrade":
|
|
409
|
+
"result-improve-dark": resultPaletteColors.improveDark,
|
|
410
|
+
"result-degrade": resultPaletteColors.degrade,
|
|
330
411
|
"result-degrade-light": "rgba(239, 83, 80, 0.16)",
|
|
331
|
-
"result-degrade-dark":
|
|
332
|
-
"result-inconclusive":
|
|
412
|
+
"result-degrade-dark": resultPaletteColors.degradeDark,
|
|
413
|
+
"result-inconclusive": resultPaletteColors.inconclusive,
|
|
333
414
|
"result-inconclusive-light": "rgba(158, 154, 151, 0.16)",
|
|
334
415
|
"result-neutral": greyRamp[400],
|
|
335
416
|
// Text on result backgrounds
|
|
@@ -360,7 +441,7 @@ var semanticColorsDark = {
|
|
|
360
441
|
"text-tertiary": greyRamp[500],
|
|
361
442
|
"text-disabled": "rgba(255, 255, 255, 0.38)",
|
|
362
443
|
"text-inverse": greyRamp[950],
|
|
363
|
-
"text-link":
|
|
444
|
+
"text-link": semanticPins.focusIndigoDark,
|
|
364
445
|
"text-link-hover": primitiveRamps.blue[400],
|
|
365
446
|
// Surface colors - dark backgrounds — warm-tapered DERIVED ramp (TD-surface-tokens,
|
|
366
447
|
// S-1, re-spaced S-3). Shipped verbatim from `deriveSurfaceRamp()` — see
|
|
@@ -410,10 +491,10 @@ var semanticColorsDark = {
|
|
|
410
491
|
// plane, so it keeps its job without collision.
|
|
411
492
|
"border-prominent": greyRamp[800],
|
|
412
493
|
// high-visibility divider
|
|
413
|
-
"border-focus":
|
|
494
|
+
"border-focus": semanticPins.focusIndigoDark,
|
|
414
495
|
"border-input": greyRamp[700],
|
|
415
496
|
"border-input-hover": greyRamp[600],
|
|
416
|
-
"border-input-focus":
|
|
497
|
+
"border-input-focus": semanticPins.focusIndigoDark,
|
|
417
498
|
"border-input-error": primitiveRamps.red[500],
|
|
418
499
|
// Alpha hairline separators — the primary separation cue (§4/S-2). Self-
|
|
419
500
|
// normalizing: composites toward white by ~the same amount on ANY plane, so
|
|
@@ -456,7 +537,7 @@ var semanticColorsDark = {
|
|
|
456
537
|
"interactive-disabled": "rgba(255, 255, 255, 0.12)",
|
|
457
538
|
"interactive-disabled-text": "rgba(255, 255, 255, 0.26)",
|
|
458
539
|
// Divider
|
|
459
|
-
|
|
540
|
+
divider: "rgba(255, 255, 255, 0.09)",
|
|
460
541
|
// Avatar default
|
|
461
542
|
"avatar-background": greyRamp[700],
|
|
462
543
|
"avatar-text": primitiveColors.white
|
|
@@ -470,6 +551,182 @@ function resolveColor(token, mode = "dark") {
|
|
|
470
551
|
return reactNative.Platform.OS === "web" ? `var(--color-${token})` : getSemanticColors(mode)[token];
|
|
471
552
|
}
|
|
472
553
|
|
|
554
|
+
// src/theme/color-utils.ts
|
|
555
|
+
function hexToRgb(hex) {
|
|
556
|
+
const cleaned = hex.replace("#", "");
|
|
557
|
+
let r, g, b;
|
|
558
|
+
if (cleaned.length === 3) {
|
|
559
|
+
r = parseInt(cleaned[0] + cleaned[0], 16);
|
|
560
|
+
g = parseInt(cleaned[1] + cleaned[1], 16);
|
|
561
|
+
b = parseInt(cleaned[2] + cleaned[2], 16);
|
|
562
|
+
} else if (cleaned.length === 6) {
|
|
563
|
+
r = parseInt(cleaned.slice(0, 2), 16);
|
|
564
|
+
g = parseInt(cleaned.slice(2, 4), 16);
|
|
565
|
+
b = parseInt(cleaned.slice(4, 6), 16);
|
|
566
|
+
} else {
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
return { r, g, b };
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// src/utils/colors.ts
|
|
573
|
+
function alpha(color, opacity) {
|
|
574
|
+
const clampedOpacity = Math.max(0, Math.min(1, opacity));
|
|
575
|
+
if (color.startsWith("#")) {
|
|
576
|
+
const hex = color.slice(1);
|
|
577
|
+
let r, g, b;
|
|
578
|
+
if (hex.length === 3) {
|
|
579
|
+
r = parseInt(hex[0] + hex[0], 16);
|
|
580
|
+
g = parseInt(hex[1] + hex[1], 16);
|
|
581
|
+
b = parseInt(hex[2] + hex[2], 16);
|
|
582
|
+
} else if (hex.length === 6) {
|
|
583
|
+
r = parseInt(hex.slice(0, 2), 16);
|
|
584
|
+
g = parseInt(hex.slice(2, 4), 16);
|
|
585
|
+
b = parseInt(hex.slice(4, 6), 16);
|
|
586
|
+
} else {
|
|
587
|
+
return color;
|
|
588
|
+
}
|
|
589
|
+
return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
|
|
590
|
+
}
|
|
591
|
+
const rgbMatch = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
|
|
592
|
+
if (rgbMatch) {
|
|
593
|
+
const [, r, g, b] = rgbMatch;
|
|
594
|
+
return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
|
|
595
|
+
}
|
|
596
|
+
const rgbaMatch = color.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/);
|
|
597
|
+
if (rgbaMatch) {
|
|
598
|
+
const [, r, g, b] = rgbaMatch;
|
|
599
|
+
return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
|
|
600
|
+
}
|
|
601
|
+
return color;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// src/theme/materials.ts
|
|
605
|
+
var c = getSemanticColors("dark");
|
|
606
|
+
function insetWell(tone = c["surface-input"]) {
|
|
607
|
+
return {
|
|
608
|
+
backgroundColor: tone,
|
|
609
|
+
boxShadow: "inset 0 2px 6px rgba(0,0,0,0.55), inset 0 -1px 0 rgba(255,255,255,0.12)"
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
var FLOATING_LIFT_MIN = 4;
|
|
613
|
+
var LIFT_RIM_ALPHA = { dark: 0.12, light: 0.9 };
|
|
614
|
+
var AMBIENT = {
|
|
615
|
+
1: [
|
|
616
|
+
{ y: 1, blur: 2, alpha: 0.35 },
|
|
617
|
+
{ y: 2, blur: 6, alpha: 0.3 }
|
|
618
|
+
],
|
|
619
|
+
2: [
|
|
620
|
+
{ y: 1, blur: 2, alpha: 0.35 },
|
|
621
|
+
{ y: 4, blur: 12, alpha: 0.32 }
|
|
622
|
+
],
|
|
623
|
+
3: [
|
|
624
|
+
{ y: 2, blur: 4, alpha: 0.35 },
|
|
625
|
+
{ y: 8, blur: 22, alpha: 0.35 }
|
|
626
|
+
],
|
|
627
|
+
4: [
|
|
628
|
+
{ y: 1, blur: 2, alpha: 0.35 },
|
|
629
|
+
{ y: 10, blur: 24, alpha: 0.3 },
|
|
630
|
+
{ y: 24, blur: 48, alpha: 0.2 }
|
|
631
|
+
],
|
|
632
|
+
5: [
|
|
633
|
+
{ y: 2, blur: 4, alpha: 0.4 },
|
|
634
|
+
{ y: 16, blur: 32, alpha: 0.35 },
|
|
635
|
+
{ y: 32, blur: 64, alpha: 0.25 }
|
|
636
|
+
]
|
|
637
|
+
};
|
|
638
|
+
var AMBIENT_ALPHA_SCALE = { dark: 1, light: 0.4 };
|
|
639
|
+
function ambientLayers(step, mode) {
|
|
640
|
+
const scale = AMBIENT_ALPHA_SCALE[mode];
|
|
641
|
+
return AMBIENT[step].map(
|
|
642
|
+
({ y, blur, alpha: alpha2 }) => `0 ${y}px ${blur}px rgba(0,0,0,${(alpha2 * scale).toFixed(2)})`
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
function liftShadow(step, mode = "dark", opts = {}) {
|
|
646
|
+
const rim = opts.rim ?? LIFT_RIM_ALPHA[mode];
|
|
647
|
+
const layers = ambientLayers(step, mode);
|
|
648
|
+
if (rim > 0) layers.unshift(`inset 0 1px 0 rgba(255,255,255,${rim.toFixed(2)})`);
|
|
649
|
+
return layers.join(", ");
|
|
650
|
+
}
|
|
651
|
+
function liftStyle(step, mode = "dark", opts = {}) {
|
|
652
|
+
const deepest = AMBIENT[step][AMBIENT[step].length - 1];
|
|
653
|
+
return reactNative.Platform.select({
|
|
654
|
+
web: { boxShadow: liftShadow(step, mode, opts) },
|
|
655
|
+
default: {
|
|
656
|
+
shadowColor: "#000",
|
|
657
|
+
shadowOffset: { width: 0, height: Math.round(deepest.y / 2) },
|
|
658
|
+
shadowOpacity: deepest.alpha * AMBIENT_ALPHA_SCALE[mode],
|
|
659
|
+
shadowRadius: deepest.blur / 2,
|
|
660
|
+
elevation: step
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// src/theme/surface-planes.ts
|
|
666
|
+
var SURFACE_LEVEL_TOKEN = {
|
|
667
|
+
frame: "background-frame",
|
|
668
|
+
background: "background-base",
|
|
669
|
+
base: "surface-base",
|
|
670
|
+
elevated: "surface-elevated",
|
|
671
|
+
raised: "surface-raised",
|
|
672
|
+
overlay: "surface-overlay"
|
|
673
|
+
};
|
|
674
|
+
var PLANE_ORDER = [
|
|
675
|
+
"frame",
|
|
676
|
+
"background",
|
|
677
|
+
"base",
|
|
678
|
+
"elevated",
|
|
679
|
+
"raised",
|
|
680
|
+
"overlay"
|
|
681
|
+
];
|
|
682
|
+
function surfaceBackground(level, mode) {
|
|
683
|
+
return getSemanticColors(mode)[SURFACE_LEVEL_TOKEN[level]];
|
|
684
|
+
}
|
|
685
|
+
function stepPlane(from, delta) {
|
|
686
|
+
const index = PLANE_ORDER.indexOf(from);
|
|
687
|
+
const clamped = Math.min(PLANE_ORDER.length - 1, Math.max(0, index + delta));
|
|
688
|
+
return PLANE_ORDER[clamped];
|
|
689
|
+
}
|
|
690
|
+
function pressedLevel(parent) {
|
|
691
|
+
return stepPlane(parent, -1);
|
|
692
|
+
}
|
|
693
|
+
function raisedLevel(parent, steps) {
|
|
694
|
+
return stepPlane(parent, Math.max(0, steps));
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// src/theme/elevation.ts
|
|
698
|
+
var FLOATING_ELEVATION_MIN = FLOATING_LIFT_MIN;
|
|
699
|
+
function getPressedRecessShadow(fillColor, _mode = "dark") {
|
|
700
|
+
const { boxShadow } = insetWell(fillColor);
|
|
701
|
+
return reactNative.Platform.select({
|
|
702
|
+
web: { boxShadow },
|
|
703
|
+
default: {}
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
var glowConfig = {
|
|
707
|
+
tight: { blur: 4, spread: 0, opacity: 0.4 },
|
|
708
|
+
subtle: { blur: 12, spread: 0, opacity: 0.25 },
|
|
709
|
+
medium: { blur: 20, spread: 2, opacity: 0.4 },
|
|
710
|
+
strong: { blur: 30, spread: 4, opacity: 0.55 }
|
|
711
|
+
};
|
|
712
|
+
function getGlowShadow(color, intensity = "medium") {
|
|
713
|
+
const config = glowConfig[intensity];
|
|
714
|
+
const rgb = hexToRgb(color);
|
|
715
|
+
if (!rgb) return {};
|
|
716
|
+
return reactNative.Platform.select({
|
|
717
|
+
web: {
|
|
718
|
+
boxShadow: `0 0 ${config.blur}px ${config.spread}px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${config.opacity})`
|
|
719
|
+
},
|
|
720
|
+
default: {
|
|
721
|
+
shadowColor: color,
|
|
722
|
+
shadowOffset: { width: 0, height: 0 },
|
|
723
|
+
shadowOpacity: config.opacity,
|
|
724
|
+
shadowRadius: config.blur / 2,
|
|
725
|
+
elevation: 0
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
|
|
473
730
|
// src/theme/workout-tokens.ts
|
|
474
731
|
var WORKOUT_TOKENS = {
|
|
475
732
|
// BodyMap volume heatmap — the canonical `divergingScale` (under → optimal →
|
|
@@ -694,8 +951,8 @@ var jsxs = wrapJsx(jsxRuntime.jsxs);
|
|
|
694
951
|
// src/components/custom/Workout/BodyMap.tsx
|
|
695
952
|
var Body = BodyHighlighter__default.default.default ?? BodyHighlighter__default.default;
|
|
696
953
|
var BRAND_PRIMARY = getSemanticColors("dark")["brand-primary"];
|
|
697
|
-
var OUTLINE_FILL =
|
|
698
|
-
var OUTLINE_BORDER =
|
|
954
|
+
var OUTLINE_FILL = alpha(primitiveColors.white, 0.08);
|
|
955
|
+
var OUTLINE_BORDER = alpha(primitiveColors.white, 0.12);
|
|
699
956
|
var BODY_SCALE = 0.8;
|
|
700
957
|
function buildSlugParts(data) {
|
|
701
958
|
const bySlug = /* @__PURE__ */ new Map();
|
|
@@ -797,7 +1054,8 @@ function BodyMap({
|
|
|
797
1054
|
alignSelf: "center",
|
|
798
1055
|
transform: [{ scale }]
|
|
799
1056
|
},
|
|
800
|
-
|
|
1057
|
+
// The highlight halo is emphasis, not depth.
|
|
1058
|
+
glowColor ? getGlowShadow(glowColor, "medium") : void 0
|
|
801
1059
|
],
|
|
802
1060
|
"aria-hidden": true,
|
|
803
1061
|
accessibilityElementsHidden: true,
|
|
@@ -870,7 +1128,7 @@ function ViewToggle({ view, onViewChange }) {
|
|
|
870
1128
|
paddingHorizontal: 12,
|
|
871
1129
|
paddingVertical: 4,
|
|
872
1130
|
borderRadius: 9999,
|
|
873
|
-
backgroundColor: active ?
|
|
1131
|
+
backgroundColor: active ? alpha(BRAND_PRIMARY, 0.16) : "transparent",
|
|
874
1132
|
borderWidth: 1,
|
|
875
1133
|
borderColor: active ? BRAND_PRIMARY : resolveColor("hairline-strong")
|
|
876
1134
|
},
|
|
@@ -959,6 +1217,17 @@ var colorStyles = {
|
|
|
959
1217
|
info: "bg-status-info",
|
|
960
1218
|
"error-vivid": "bg-status-error-vivid"
|
|
961
1219
|
};
|
|
1220
|
+
var t = getSemanticColors("dark");
|
|
1221
|
+
var glowColors = {
|
|
1222
|
+
default: greyRamp[500],
|
|
1223
|
+
primary: t["brand-primary"],
|
|
1224
|
+
success: t["status-success"],
|
|
1225
|
+
live: t["status-live"],
|
|
1226
|
+
error: t["status-error"],
|
|
1227
|
+
warning: t["status-warning"],
|
|
1228
|
+
info: t["status-info"],
|
|
1229
|
+
"error-vivid": t["status-error-vivid"]
|
|
1230
|
+
};
|
|
962
1231
|
function Indicator({
|
|
963
1232
|
size = "sm",
|
|
964
1233
|
color = "default",
|
|
@@ -996,11 +1265,7 @@ function Indicator({
|
|
|
996
1265
|
)
|
|
997
1266
|
] });
|
|
998
1267
|
}
|
|
999
|
-
const
|
|
1000
|
-
...typeof style === "object" ? style : {},
|
|
1001
|
-
...colorStyle ?? {},
|
|
1002
|
-
...glow && customColor ? { boxShadow: `0 0 6px ${customColor}` } : {}
|
|
1003
|
-
};
|
|
1268
|
+
const glowStyle = glow ? getGlowShadow(customColor ?? glowColors[color], "subtle") : null;
|
|
1004
1269
|
return /* @__PURE__ */ jsx(
|
|
1005
1270
|
reactNative.View,
|
|
1006
1271
|
{
|
|
@@ -1010,54 +1275,168 @@ function Indicator({
|
|
|
1010
1275
|
colorClass,
|
|
1011
1276
|
pulseMode === "opacity" && "animate-pulse",
|
|
1012
1277
|
ring && "border-2 border-background-base",
|
|
1013
|
-
glow && !customColor && (color === "success" || color === "live") && "shadow-[0_0_6px_rgba(46,213,115,0.6)]",
|
|
1014
|
-
glow && !customColor && color === "error" && "shadow-[0_0_6px_rgba(239,68,68,0.6)]",
|
|
1015
|
-
glow && !customColor && color === "warning" && "shadow-[0_0_6px_rgba(245,158,11,0.6)]",
|
|
1016
|
-
glow && !customColor && color === "primary" && "shadow-[0_0_6px_rgba(255,121,0,0.6)]",
|
|
1017
|
-
glow && !customColor && color === "error-vivid" && "shadow-[0_0_6px_rgba(255,71,87,0.6)]",
|
|
1018
1278
|
className
|
|
1019
1279
|
),
|
|
1020
|
-
style:
|
|
1280
|
+
style: [style, colorStyle, glowStyle],
|
|
1021
1281
|
...props
|
|
1022
1282
|
}
|
|
1023
1283
|
);
|
|
1024
1284
|
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1285
|
+
var colorToTone = {
|
|
1286
|
+
default: "neutral",
|
|
1287
|
+
primary: "brand",
|
|
1288
|
+
secondary: "brand-secondary",
|
|
1289
|
+
success: "success",
|
|
1290
|
+
error: "error",
|
|
1291
|
+
warning: "warning",
|
|
1292
|
+
info: "info"
|
|
1293
|
+
};
|
|
1294
|
+
var toneStyles = {
|
|
1028
1295
|
solid: {
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
secondary: "bg-brand-secondary text-text-inverse",
|
|
1032
|
-
success: "bg-status-success text-text-inverse",
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
info: "bg-status-info text-text-inverse"
|
|
1296
|
+
neutral: "bg-hairline-strong border-transparent text-text-inverse",
|
|
1297
|
+
brand: "bg-brand-primary border-transparent text-text-inverse",
|
|
1298
|
+
"brand-secondary": "bg-brand-secondary border-transparent text-text-inverse",
|
|
1299
|
+
success: "bg-status-success border-transparent text-text-inverse",
|
|
1300
|
+
warning: "bg-status-warning border-transparent text-text-inverse",
|
|
1301
|
+
error: "bg-status-error border-transparent text-text-inverse",
|
|
1302
|
+
info: "bg-status-info border-transparent text-text-inverse"
|
|
1036
1303
|
},
|
|
1037
1304
|
subtle: {
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1305
|
+
// Alpha-white rather than a ramp step: a pill sits on whatever plane its
|
|
1306
|
+
// host is, and an alpha fill composites by the same amount on all of them.
|
|
1307
|
+
// A `surface-*` fill would vanish on the plane it names. Borderless like the
|
|
1308
|
+
// six coloured tones — the fill carries the capsule, not a ring.
|
|
1309
|
+
// Label comes from `on-*-subtle`, not the base tone token: the base is tuned to
|
|
1310
|
+
// carry a white label as a solid fill, which left error and accent unreadable
|
|
1311
|
+
// here (AW-133). The on-subtle tokens level the family at one weight.
|
|
1312
|
+
neutral: "bg-hairline-subtle border-transparent text-text-secondary",
|
|
1313
|
+
brand: "bg-brand-primary-subtle border-transparent text-on-brand-primary-subtle",
|
|
1314
|
+
"brand-secondary": "bg-brand-secondary-subtle border-transparent text-on-brand-secondary-subtle",
|
|
1315
|
+
success: "bg-status-success-subtle border-transparent text-on-status-success-subtle",
|
|
1316
|
+
warning: "bg-status-warning-subtle border-transparent text-on-status-warning-subtle",
|
|
1317
|
+
error: "bg-status-error-subtle border-transparent text-on-status-error-subtle",
|
|
1318
|
+
info: "bg-status-info-subtle border-transparent text-on-status-info-subtle"
|
|
1045
1319
|
},
|
|
1046
1320
|
outline: {
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
secondary: "border
|
|
1050
|
-
success: "border
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
info: "border
|
|
1321
|
+
neutral: "border-hairline text-text-secondary",
|
|
1322
|
+
brand: "border-brand-primary text-brand-primary",
|
|
1323
|
+
"brand-secondary": "border-brand-secondary text-brand-secondary",
|
|
1324
|
+
success: "border-status-success text-status-success",
|
|
1325
|
+
warning: "border-status-warning text-status-warning",
|
|
1326
|
+
error: "border-status-error text-status-error",
|
|
1327
|
+
info: "border-status-info text-status-info"
|
|
1054
1328
|
}
|
|
1055
1329
|
};
|
|
1330
|
+
var dotToneStyles = {
|
|
1331
|
+
neutral: "bg-text-tertiary",
|
|
1332
|
+
brand: "bg-brand-primary",
|
|
1333
|
+
"brand-secondary": "bg-brand-secondary",
|
|
1334
|
+
success: "bg-status-success",
|
|
1335
|
+
warning: "bg-status-warning",
|
|
1336
|
+
error: "bg-status-error",
|
|
1337
|
+
info: "bg-status-info"
|
|
1338
|
+
};
|
|
1056
1339
|
var sizeStyles2 = {
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1340
|
+
xs: { container: "px-1 py-px", text: "text-3xs" },
|
|
1341
|
+
sm: { container: "px-2 py-0.5", text: "text-2xs" },
|
|
1342
|
+
md: { container: "px-2.5 py-1", text: "text-xs" },
|
|
1343
|
+
lg: { container: "px-3 py-1.5", text: "text-sm" },
|
|
1344
|
+
xl: { container: "px-4 py-2", text: "text-base" }
|
|
1345
|
+
};
|
|
1346
|
+
function PillDot({ tone, testID }) {
|
|
1347
|
+
return /* @__PURE__ */ jsx(
|
|
1348
|
+
reactNative.View,
|
|
1349
|
+
{
|
|
1350
|
+
className: cn("w-1.5 h-1.5 rounded-full shrink-0", dotToneStyles[tone]),
|
|
1351
|
+
accessibilityElementsHidden: true,
|
|
1352
|
+
testID: testID ? `${testID}-dot` : "pill-dot"
|
|
1353
|
+
}
|
|
1354
|
+
);
|
|
1355
|
+
}
|
|
1356
|
+
function containerClasses(p, tone) {
|
|
1357
|
+
return cn(
|
|
1358
|
+
"flex-row items-center gap-1 border self-start shrink-0",
|
|
1359
|
+
p.rounded === false ? "rounded" : "rounded-full",
|
|
1360
|
+
toneStyles[p.variant ?? "subtle"][tone],
|
|
1361
|
+
sizeStyles2[p.size ?? "sm"].container,
|
|
1362
|
+
p.isDisabled && "opacity-50",
|
|
1363
|
+
p.className
|
|
1364
|
+
);
|
|
1365
|
+
}
|
|
1366
|
+
function PillContent({ tone, ...p }) {
|
|
1367
|
+
const textClasses = cn(
|
|
1368
|
+
"font-heading font-semibold text-inherit",
|
|
1369
|
+
sizeStyles2[p.size ?? "sm"].text,
|
|
1370
|
+
p.textClassName
|
|
1371
|
+
);
|
|
1372
|
+
const slot = p.leading ?? p.leftElement;
|
|
1373
|
+
return /* @__PURE__ */ jsxs(jsxRuntime.Fragment, { children: [
|
|
1374
|
+
slot === "dot" ? /* @__PURE__ */ jsx(PillDot, { tone: p.dotTone ?? tone, testID: p.testID }) : slot,
|
|
1375
|
+
typeof p.children === "string" ? /* @__PURE__ */ jsx(reactNative.Text, { className: textClasses, children: p.children }) : p.children,
|
|
1376
|
+
p.trailing
|
|
1377
|
+
] });
|
|
1378
|
+
}
|
|
1379
|
+
function Pill(props) {
|
|
1380
|
+
const {
|
|
1381
|
+
variant,
|
|
1382
|
+
tone,
|
|
1383
|
+
color,
|
|
1384
|
+
size,
|
|
1385
|
+
rounded,
|
|
1386
|
+
leading,
|
|
1387
|
+
dotTone,
|
|
1388
|
+
leftElement,
|
|
1389
|
+
trailing,
|
|
1390
|
+
onPress,
|
|
1391
|
+
isDisabled,
|
|
1392
|
+
className,
|
|
1393
|
+
textClassName,
|
|
1394
|
+
children,
|
|
1395
|
+
...viewProps
|
|
1396
|
+
} = props;
|
|
1397
|
+
const resolvedTone = tone ?? (color ? colorToTone[color] : "neutral");
|
|
1398
|
+
const classes = containerClasses(props, resolvedTone);
|
|
1399
|
+
const content = /* @__PURE__ */ jsx(PillContent, { ...props, tone: resolvedTone });
|
|
1400
|
+
if (onPress) {
|
|
1401
|
+
return /* @__PURE__ */ jsx(
|
|
1402
|
+
reactNative.Pressable,
|
|
1403
|
+
{
|
|
1404
|
+
onPress,
|
|
1405
|
+
disabled: isDisabled,
|
|
1406
|
+
accessibilityRole: "button",
|
|
1407
|
+
className: classes,
|
|
1408
|
+
...viewProps,
|
|
1409
|
+
children: content
|
|
1410
|
+
}
|
|
1411
|
+
);
|
|
1412
|
+
}
|
|
1413
|
+
return /* @__PURE__ */ jsx(reactNative.View, { className: classes, ...viewProps, children: content });
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// src/components/ui/badge/Badge.tsx
|
|
1417
|
+
var colorToTone2 = {
|
|
1418
|
+
default: "neutral",
|
|
1419
|
+
primary: "brand",
|
|
1420
|
+
secondary: "brand-secondary",
|
|
1421
|
+
success: "success",
|
|
1422
|
+
error: "error",
|
|
1423
|
+
warning: "warning",
|
|
1424
|
+
info: "info"
|
|
1425
|
+
};
|
|
1426
|
+
var sizeStyles3 = {
|
|
1427
|
+
sm: "px-1.5 py-0.5",
|
|
1428
|
+
md: "px-2 py-0.5",
|
|
1429
|
+
lg: "px-2.5 py-1"
|
|
1060
1430
|
};
|
|
1431
|
+
var textSizeStyles = {
|
|
1432
|
+
sm: "text-xs",
|
|
1433
|
+
md: "text-xs",
|
|
1434
|
+
lg: "text-sm"
|
|
1435
|
+
};
|
|
1436
|
+
function dotIndicatorColor(color, dotColor) {
|
|
1437
|
+
if (dotColor) return dotColor;
|
|
1438
|
+
return color === "default" || color === "secondary" ? "default" : color;
|
|
1439
|
+
}
|
|
1061
1440
|
function Badge({
|
|
1062
1441
|
variant = "subtle",
|
|
1063
1442
|
color = "default",
|
|
@@ -1068,31 +1447,116 @@ function Badge({
|
|
|
1068
1447
|
children,
|
|
1069
1448
|
...props
|
|
1070
1449
|
}) {
|
|
1071
|
-
return /* @__PURE__ */
|
|
1072
|
-
|
|
1450
|
+
return /* @__PURE__ */ jsx(
|
|
1451
|
+
Pill,
|
|
1073
1452
|
{
|
|
1453
|
+
variant,
|
|
1454
|
+
tone: colorToTone2[color],
|
|
1455
|
+
leading: dot ? /* @__PURE__ */ jsx(Indicator, { size: "xs", color: dotIndicatorColor(color, dotColor), className: "mr-0.5" }) : void 0,
|
|
1074
1456
|
className: cn(
|
|
1075
|
-
"
|
|
1076
|
-
|
|
1077
|
-
|
|
1457
|
+
"justify-center self-auto gap-0",
|
|
1458
|
+
variant === "outline" ? "border" : "border-0",
|
|
1459
|
+
sizeStyles3[size],
|
|
1078
1460
|
className
|
|
1079
1461
|
),
|
|
1462
|
+
textClassName: cn("font-sans font-medium", textSizeStyles[size]),
|
|
1080
1463
|
...props,
|
|
1081
|
-
children
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1464
|
+
children
|
|
1465
|
+
}
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1468
|
+
var variantStyles = {
|
|
1469
|
+
h1: "font-heading text-5xl font-bold leading-tight",
|
|
1470
|
+
h2: "font-heading text-4xl font-bold leading-tight",
|
|
1471
|
+
h3: "font-heading text-3xl font-bold leading-tight",
|
|
1472
|
+
h4: "font-heading text-2xl font-bold leading-tight",
|
|
1473
|
+
h5: "font-heading text-xl font-semibold leading-tight",
|
|
1474
|
+
h6: "font-heading text-lg font-semibold leading-tight",
|
|
1475
|
+
body1: "font-body text-base font-normal leading-normal",
|
|
1476
|
+
body2: "font-body text-sm font-normal leading-normal",
|
|
1477
|
+
subtitle1: "font-body text-base font-medium leading-relaxed",
|
|
1478
|
+
subtitle2: "font-body text-sm font-medium leading-normal",
|
|
1479
|
+
caption: "font-body text-xs font-normal leading-loose",
|
|
1480
|
+
overline: "font-body text-xs font-semibold uppercase tracking-widest leading-relaxed",
|
|
1481
|
+
button: "font-sans text-sm font-semibold leading-relaxed",
|
|
1482
|
+
// Monospace technical readouts (clocks, ids, metrics) and their all-caps label form.
|
|
1483
|
+
mono: "font-mono text-xs font-normal leading-normal",
|
|
1484
|
+
monoLabel: "font-mono text-xs font-bold uppercase tracking-wide leading-normal",
|
|
1485
|
+
// The sans (Inter) label pair: 10px for dense table/column headers, 12px bold for
|
|
1486
|
+
// badge and row labels. `overline` is the 12px font-body form of the same idea.
|
|
1487
|
+
microLabel: "font-sans text-2xs font-semibold uppercase tracking-widest leading-normal",
|
|
1488
|
+
boldLabel: "font-sans text-xs font-bold leading-normal"
|
|
1489
|
+
};
|
|
1490
|
+
var colorStyles2 = {
|
|
1491
|
+
primary: "text-text-primary",
|
|
1492
|
+
secondary: "text-text-secondary",
|
|
1493
|
+
tertiary: "text-text-tertiary",
|
|
1494
|
+
disabled: "text-text-disabled",
|
|
1495
|
+
inverse: "text-text-inverse",
|
|
1496
|
+
success: "text-status-success",
|
|
1497
|
+
error: "text-status-error",
|
|
1498
|
+
warning: "text-status-warning",
|
|
1499
|
+
info: "text-status-info",
|
|
1500
|
+
inherit: ""
|
|
1501
|
+
// No color class, inherit from parent
|
|
1502
|
+
};
|
|
1503
|
+
var alignStyles = {
|
|
1504
|
+
left: "text-left",
|
|
1505
|
+
center: "text-center",
|
|
1506
|
+
right: "text-right",
|
|
1507
|
+
justify: "text-justify"
|
|
1508
|
+
};
|
|
1509
|
+
var headingVariants = ["h1", "h2", "h3", "h4", "h5", "h6"];
|
|
1510
|
+
var marginBottomStyles = {
|
|
1511
|
+
none: "",
|
|
1512
|
+
sm: "mb-1",
|
|
1513
|
+
md: "mb-2",
|
|
1514
|
+
lg: "mb-4"
|
|
1515
|
+
};
|
|
1516
|
+
function Typography({
|
|
1517
|
+
variant = "body1",
|
|
1518
|
+
color = "primary",
|
|
1519
|
+
align,
|
|
1520
|
+
truncate = false,
|
|
1521
|
+
noWrap = false,
|
|
1522
|
+
// deprecated, kept for backward compatibility
|
|
1523
|
+
marginBottom,
|
|
1524
|
+
gutterBottom = false,
|
|
1525
|
+
// deprecated, kept for backward compatibility
|
|
1526
|
+
maxLines,
|
|
1527
|
+
className,
|
|
1528
|
+
children,
|
|
1529
|
+
...props
|
|
1530
|
+
}) {
|
|
1531
|
+
const isHeading = headingVariants.includes(variant);
|
|
1532
|
+
const shouldTruncate = truncate || noWrap;
|
|
1533
|
+
const mb = marginBottom || (gutterBottom ? "md" : "none");
|
|
1534
|
+
let numLines;
|
|
1535
|
+
if (maxLines) {
|
|
1536
|
+
numLines = maxLines;
|
|
1537
|
+
} else if (shouldTruncate) {
|
|
1538
|
+
numLines = 1;
|
|
1539
|
+
}
|
|
1540
|
+
return /* @__PURE__ */ jsx(
|
|
1541
|
+
reactNative.Text,
|
|
1542
|
+
{
|
|
1543
|
+
accessibilityRole: isHeading ? "header" : "text",
|
|
1544
|
+
numberOfLines: numLines,
|
|
1545
|
+
className: cn(
|
|
1546
|
+
variantStyles[variant],
|
|
1547
|
+
color !== "inherit" && colorStyles2[color],
|
|
1548
|
+
align && alignStyles[align],
|
|
1549
|
+
shouldTruncate && "truncate",
|
|
1550
|
+
marginBottomStyles[mb],
|
|
1551
|
+
className
|
|
1552
|
+
),
|
|
1553
|
+
...props,
|
|
1554
|
+
children
|
|
1092
1555
|
}
|
|
1093
1556
|
);
|
|
1094
1557
|
}
|
|
1095
|
-
|
|
1558
|
+
|
|
1559
|
+
// src/components/custom/Workout/Sparkline.tsx
|
|
1096
1560
|
function normalizeData(data, height) {
|
|
1097
1561
|
if (data.length === 0) return [];
|
|
1098
1562
|
const min = Math.min(...data);
|
|
@@ -1129,7 +1593,7 @@ function Sparkline({
|
|
|
1129
1593
|
}
|
|
1130
1594
|
);
|
|
1131
1595
|
}
|
|
1132
|
-
const resolvedColor = color ??
|
|
1596
|
+
const resolvedColor = color ?? resolveColor("brand-primary");
|
|
1133
1597
|
const normalized = normalizeData(data, height);
|
|
1134
1598
|
const stepX = data.length > 1 ? width / (data.length - 1) : 0;
|
|
1135
1599
|
const dotSize = 3;
|
|
@@ -1169,14 +1633,19 @@ function Sparkline({
|
|
|
1169
1633
|
],
|
|
1170
1634
|
accessibilityElementsHidden: true,
|
|
1171
1635
|
testID: `sparkline-reference-${i}`,
|
|
1172
|
-
children: line.label &&
|
|
1173
|
-
|
|
1636
|
+
children: line.label && // `3xs` (9px) is the scale floor; the label was 7px, which is off it
|
|
1637
|
+
// entirely (TOKENS.md §4). The line box stays unpinned, as the raw
|
|
1638
|
+
// <Text> this replaced was, so the absolute offset still lands.
|
|
1639
|
+
/* @__PURE__ */ jsx(
|
|
1640
|
+
Typography,
|
|
1174
1641
|
{
|
|
1642
|
+
variant: "caption",
|
|
1643
|
+
color: "inherit",
|
|
1644
|
+
className: "text-3xs leading-[normal]",
|
|
1175
1645
|
style: {
|
|
1176
1646
|
position: "absolute",
|
|
1177
1647
|
right: 0,
|
|
1178
1648
|
top: -10,
|
|
1179
|
-
fontSize: 7,
|
|
1180
1649
|
color: line.color,
|
|
1181
1650
|
opacity: 1
|
|
1182
1651
|
},
|
|
@@ -1245,9 +1714,9 @@ function Sparkline({
|
|
|
1245
1714
|
}
|
|
1246
1715
|
|
|
1247
1716
|
// src/components/custom/Workout/BodyMapDetailPanel.tsx
|
|
1248
|
-
var
|
|
1249
|
-
var
|
|
1250
|
-
var VOLUME_GRADIENT = `linear-gradient(90deg, ${
|
|
1717
|
+
var t2 = getSemanticColors("dark");
|
|
1718
|
+
var BRAND_PRIMARY2 = t2["brand-primary"];
|
|
1719
|
+
var VOLUME_GRADIENT = `linear-gradient(90deg, ${t2["status-info"]} 0%, ${t2["status-success"]} 50%, ${t2["status-error"]} 100%)`;
|
|
1251
1720
|
var SLIDE_OFFSET = 400;
|
|
1252
1721
|
var BACKDROP_OPACITY = 0.4;
|
|
1253
1722
|
var STATUS_BADGE_COLOR = {
|
|
@@ -1312,7 +1781,14 @@ function BodyMapDetailPanel({
|
|
|
1312
1781
|
return /* @__PURE__ */ jsxs(
|
|
1313
1782
|
reactNative.View,
|
|
1314
1783
|
{
|
|
1315
|
-
style: {
|
|
1784
|
+
style: {
|
|
1785
|
+
position: "absolute",
|
|
1786
|
+
top: 0,
|
|
1787
|
+
left: 0,
|
|
1788
|
+
right: 0,
|
|
1789
|
+
bottom: 0,
|
|
1790
|
+
justifyContent: "flex-end"
|
|
1791
|
+
},
|
|
1316
1792
|
testID: "body-map-detail-panel-root",
|
|
1317
1793
|
children: [
|
|
1318
1794
|
/* @__PURE__ */ jsx(
|
|
@@ -1324,7 +1800,7 @@ function BodyMapDetailPanel({
|
|
|
1324
1800
|
left: 0,
|
|
1325
1801
|
right: 0,
|
|
1326
1802
|
bottom: 0,
|
|
1327
|
-
backgroundColor:
|
|
1803
|
+
backgroundColor: primitiveColors.black,
|
|
1328
1804
|
opacity: backdrop
|
|
1329
1805
|
},
|
|
1330
1806
|
testID: "body-map-detail-panel-backdrop-anim",
|
|
@@ -1447,8 +1923,22 @@ function BodyMapDetailPanel({
|
|
|
1447
1923
|
style: { marginBottom: 6 },
|
|
1448
1924
|
accessibilityElementsHidden: true,
|
|
1449
1925
|
children: [
|
|
1450
|
-
/* @__PURE__ */ jsx(
|
|
1451
|
-
|
|
1926
|
+
/* @__PURE__ */ jsx(
|
|
1927
|
+
reactNative.Text,
|
|
1928
|
+
{
|
|
1929
|
+
className: "text-text-tertiary",
|
|
1930
|
+
style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" },
|
|
1931
|
+
children: `MEV ${landmarks.mev}`
|
|
1932
|
+
}
|
|
1933
|
+
),
|
|
1934
|
+
/* @__PURE__ */ jsx(
|
|
1935
|
+
reactNative.Text,
|
|
1936
|
+
{
|
|
1937
|
+
className: "text-text-tertiary",
|
|
1938
|
+
style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" },
|
|
1939
|
+
children: `MRV ${landmarks.mrv}`
|
|
1940
|
+
}
|
|
1941
|
+
)
|
|
1452
1942
|
]
|
|
1453
1943
|
}
|
|
1454
1944
|
),
|
|
@@ -1483,7 +1973,8 @@ function BodyMapDetailPanel({
|
|
|
1483
1973
|
height: 14,
|
|
1484
1974
|
borderRadius: 7,
|
|
1485
1975
|
borderWidth: 2,
|
|
1486
|
-
|
|
1976
|
+
// A knob resting on the volume bar: lift, with the ring as its edge.
|
|
1977
|
+
...liftStyle(1, "dark", { rim: 0 })
|
|
1487
1978
|
},
|
|
1488
1979
|
accessibilityElementsHidden: true,
|
|
1489
1980
|
testID: "body-map-detail-panel-volume-marker"
|
|
@@ -1566,7 +2057,12 @@ function BodyMapDetailPanel({
|
|
|
1566
2057
|
reactNative.Text,
|
|
1567
2058
|
{
|
|
1568
2059
|
className: "text-text-primary",
|
|
1569
|
-
style: {
|
|
2060
|
+
style: {
|
|
2061
|
+
flex: 1,
|
|
2062
|
+
fontSize: 13,
|
|
2063
|
+
fontFamily: "Inter, sans-serif",
|
|
2064
|
+
fontWeight: "600"
|
|
2065
|
+
},
|
|
1570
2066
|
testID: `body-map-detail-panel-contributing-${index}-name`,
|
|
1571
2067
|
children: exercise.name
|
|
1572
2068
|
}
|
|
@@ -1610,7 +2106,12 @@ function BodyMapDetailPanel({
|
|
|
1610
2106
|
reactNative.Text,
|
|
1611
2107
|
{
|
|
1612
2108
|
className: "text-text-primary",
|
|
1613
|
-
style: {
|
|
2109
|
+
style: {
|
|
2110
|
+
flex: 1,
|
|
2111
|
+
fontSize: 13,
|
|
2112
|
+
fontFamily: "Inter, sans-serif",
|
|
2113
|
+
fontWeight: "600"
|
|
2114
|
+
},
|
|
1614
2115
|
testID: `body-map-detail-panel-upcoming-${index}-name`,
|
|
1615
2116
|
children: exercise.name
|
|
1616
2117
|
}
|
|
@@ -1640,12 +2141,23 @@ function BodyMapDetailPanel({
|
|
|
1640
2141
|
paddingVertical: 10,
|
|
1641
2142
|
borderRadius: 8,
|
|
1642
2143
|
alignItems: "center",
|
|
1643
|
-
backgroundColor:
|
|
2144
|
+
backgroundColor: alpha(BRAND_PRIMARY2, 0.12),
|
|
1644
2145
|
borderWidth: 1,
|
|
1645
|
-
borderColor:
|
|
2146
|
+
borderColor: alpha(BRAND_PRIMARY2, 0.3)
|
|
1646
2147
|
},
|
|
1647
2148
|
testID: "body-map-detail-panel-view-exercises",
|
|
1648
|
-
children: /* @__PURE__ */ jsx(
|
|
2149
|
+
children: /* @__PURE__ */ jsx(
|
|
2150
|
+
reactNative.Text,
|
|
2151
|
+
{
|
|
2152
|
+
style: {
|
|
2153
|
+
fontSize: 13,
|
|
2154
|
+
fontFamily: "Inter, sans-serif",
|
|
2155
|
+
fontWeight: "700",
|
|
2156
|
+
color: BRAND_PRIMARY2
|
|
2157
|
+
},
|
|
2158
|
+
children: "View exercises"
|
|
2159
|
+
}
|
|
2160
|
+
)
|
|
1649
2161
|
}
|
|
1650
2162
|
)
|
|
1651
2163
|
]
|
|
@@ -1658,439 +2170,81 @@ function BodyMapDetailPanel({
|
|
|
1658
2170
|
}
|
|
1659
2171
|
);
|
|
1660
2172
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
function
|
|
1664
|
-
|
|
1665
|
-
let r, g, b;
|
|
1666
|
-
if (cleaned.length === 3) {
|
|
1667
|
-
r = parseInt(cleaned[0] + cleaned[0], 16);
|
|
1668
|
-
g = parseInt(cleaned[1] + cleaned[1], 16);
|
|
1669
|
-
b = parseInt(cleaned[2] + cleaned[2], 16);
|
|
1670
|
-
} else if (cleaned.length === 6) {
|
|
1671
|
-
r = parseInt(cleaned.slice(0, 2), 16);
|
|
1672
|
-
g = parseInt(cleaned.slice(2, 4), 16);
|
|
1673
|
-
b = parseInt(cleaned.slice(4, 6), 16);
|
|
1674
|
-
} else {
|
|
1675
|
-
return null;
|
|
1676
|
-
}
|
|
1677
|
-
return { r, g, b };
|
|
1678
|
-
}
|
|
1679
|
-
function rgbToHsv(r, g, b) {
|
|
1680
|
-
const rNorm = r / 255;
|
|
1681
|
-
const gNorm = g / 255;
|
|
1682
|
-
const bNorm = b / 255;
|
|
1683
|
-
const max = Math.max(rNorm, gNorm, bNorm);
|
|
1684
|
-
const min = Math.min(rNorm, gNorm, bNorm);
|
|
1685
|
-
const delta = max - min;
|
|
1686
|
-
const v = max;
|
|
1687
|
-
const s = max === 0 ? 0 : delta / max;
|
|
1688
|
-
let h = 0;
|
|
1689
|
-
if (delta !== 0) {
|
|
1690
|
-
if (max === rNorm) {
|
|
1691
|
-
h = 60 * ((gNorm - bNorm) / delta % 6);
|
|
1692
|
-
} else if (max === gNorm) {
|
|
1693
|
-
h = 60 * ((bNorm - rNorm) / delta + 2);
|
|
1694
|
-
} else {
|
|
1695
|
-
h = 60 * ((rNorm - gNorm) / delta + 4);
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1698
|
-
if (h < 0) h += 360;
|
|
1699
|
-
return { h, s, v };
|
|
1700
|
-
}
|
|
1701
|
-
function hsvToRgb(h, s, v) {
|
|
1702
|
-
const c = v * s;
|
|
1703
|
-
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
1704
|
-
const m = v - c;
|
|
1705
|
-
let rPrime, gPrime, bPrime;
|
|
1706
|
-
if (h >= 0 && h < 60) {
|
|
1707
|
-
rPrime = c;
|
|
1708
|
-
gPrime = x;
|
|
1709
|
-
bPrime = 0;
|
|
1710
|
-
} else if (h >= 60 && h < 120) {
|
|
1711
|
-
rPrime = x;
|
|
1712
|
-
gPrime = c;
|
|
1713
|
-
bPrime = 0;
|
|
1714
|
-
} else if (h >= 120 && h < 180) {
|
|
1715
|
-
rPrime = 0;
|
|
1716
|
-
gPrime = c;
|
|
1717
|
-
bPrime = x;
|
|
1718
|
-
} else if (h >= 180 && h < 240) {
|
|
1719
|
-
rPrime = 0;
|
|
1720
|
-
gPrime = x;
|
|
1721
|
-
bPrime = c;
|
|
1722
|
-
} else if (h >= 240 && h < 300) {
|
|
1723
|
-
rPrime = x;
|
|
1724
|
-
gPrime = 0;
|
|
1725
|
-
bPrime = c;
|
|
1726
|
-
} else {
|
|
1727
|
-
rPrime = c;
|
|
1728
|
-
gPrime = 0;
|
|
1729
|
-
bPrime = x;
|
|
1730
|
-
}
|
|
1731
|
-
return {
|
|
1732
|
-
r: Math.round((rPrime + m) * 255),
|
|
1733
|
-
g: Math.round((gPrime + m) * 255),
|
|
1734
|
-
b: Math.round((bPrime + m) * 255)
|
|
1735
|
-
};
|
|
1736
|
-
}
|
|
1737
|
-
function rgbToHex(r, g, b) {
|
|
1738
|
-
const toHex = (n) => {
|
|
1739
|
-
const clamped = Math.max(0, Math.min(255, Math.round(n)));
|
|
1740
|
-
return clamped.toString(16).padStart(2, "0");
|
|
1741
|
-
};
|
|
1742
|
-
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
1743
|
-
}
|
|
1744
|
-
function lighten(hex, amount = 0.1) {
|
|
1745
|
-
const rgb = hexToRgb(hex);
|
|
1746
|
-
if (!rgb) return hex;
|
|
1747
|
-
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
1748
|
-
const newV = Math.min(1, hsv.v + amount);
|
|
1749
|
-
const newRgb = hsvToRgb(hsv.h, hsv.s, newV);
|
|
1750
|
-
return rgbToHex(newRgb.r, newRgb.g, newRgb.b);
|
|
1751
|
-
}
|
|
1752
|
-
var elevationSystem = {
|
|
1753
|
-
// Deep inset (recessed input fields, deeply pressed buttons)
|
|
1754
|
-
[-2]: {
|
|
1755
|
-
name: "deep-inset",
|
|
1756
|
-
colorAdjustment: 0,
|
|
1757
|
-
shadowIntensity: "strong",
|
|
1758
|
-
shadowStyle: "pressed",
|
|
1759
|
-
description: "Deeply recessed elements (e.g., input fields, deeply pressed buttons)"
|
|
1760
|
-
},
|
|
1761
|
-
// Shallow inset (pressed buttons, sunken panels)
|
|
1762
|
-
[-1]: {
|
|
1763
|
-
name: "inset",
|
|
1764
|
-
colorAdjustment: 0,
|
|
1765
|
-
shadowIntensity: "medium",
|
|
1766
|
-
shadowStyle: "pressed",
|
|
1767
|
-
description: "Shallow inset elements (e.g., pressed buttons, sunken panels within cards)"
|
|
1768
|
-
},
|
|
1769
|
-
// Base level (page background, default surface)
|
|
1770
|
-
[0]: {
|
|
1771
|
-
name: "base",
|
|
1772
|
-
colorAdjustment: 0,
|
|
1773
|
-
shadowIntensity: "subtle",
|
|
1774
|
-
shadowStyle: "raised",
|
|
1775
|
-
description: "Base surface level (page background, default containers)"
|
|
1776
|
-
},
|
|
1777
|
-
// Level 1: Subtle elevation (outline cards, subtle containers)
|
|
1778
|
-
[1]: {
|
|
1779
|
-
name: "subtle",
|
|
1780
|
-
// The whole ladder was re-spaced in TD-07.16. It used to run
|
|
1781
|
-
// 0.01/0.02/0.04/0.06/0.08, where the first step was ~2 RGB values — under
|
|
1782
|
-
// the perceptual floor, so level 1 existed in the type system and nowhere on
|
|
1783
|
-
// screen. With drop-shadow now gated off below FLOATING_ELEVATION_MIN, TONE
|
|
1784
|
-
// is the only thing separating 0-3, so every step has to actually land.
|
|
1785
|
-
// Even 0.025 spacing, verified in elevation.test.ts as ΔL* > 1 per step.
|
|
1786
|
-
colorAdjustment: 0.025,
|
|
1787
|
-
shadowIntensity: "subtle",
|
|
1788
|
-
shadowStyle: "raised",
|
|
1789
|
-
description: "Subtle elevation (outline cards, subtle containers)"
|
|
1790
|
-
},
|
|
1791
|
-
// Level 2: Standard elevation (default cards, buttons)
|
|
1792
|
-
[2]: {
|
|
1793
|
-
name: "standard",
|
|
1794
|
-
colorAdjustment: 0.05,
|
|
1795
|
-
shadowIntensity: "medium",
|
|
1796
|
-
shadowStyle: "raised",
|
|
1797
|
-
description: "Standard elevation (default cards, raised buttons)"
|
|
1798
|
-
},
|
|
1799
|
-
// Level 3: Prominent elevation (important cards, modals)
|
|
1800
|
-
[3]: {
|
|
1801
|
-
name: "prominent",
|
|
1802
|
-
colorAdjustment: 0.075,
|
|
1803
|
-
shadowIntensity: "strong",
|
|
1804
|
-
shadowStyle: "raised",
|
|
1805
|
-
description: "Prominent elevation (important cards, modals, dropdowns)"
|
|
1806
|
-
},
|
|
1807
|
-
// Level 4: High elevation (overlays, popovers)
|
|
1808
|
-
[4]: {
|
|
1809
|
-
name: "high",
|
|
1810
|
-
colorAdjustment: 0.1,
|
|
1811
|
-
shadowIntensity: "strong",
|
|
1812
|
-
shadowStyle: "raised",
|
|
1813
|
-
description: "High elevation (overlays, popovers, tooltips)"
|
|
1814
|
-
},
|
|
1815
|
-
// Level 5: Floating (toasts, floating action buttons)
|
|
1816
|
-
[5]: {
|
|
1817
|
-
name: "floating",
|
|
1818
|
-
colorAdjustment: 0.13,
|
|
1819
|
-
shadowIntensity: "strong",
|
|
1820
|
-
shadowStyle: "raised",
|
|
1821
|
-
description: "Floating elevation (toasts, floating action buttons, highest z-index)"
|
|
1822
|
-
}
|
|
1823
|
-
};
|
|
1824
|
-
function calculateRimLightColor(baseColor, level) {
|
|
1825
|
-
const rgb = hexToRgb(baseColor);
|
|
1826
|
-
if (!rgb) {
|
|
1827
|
-
return "rgba(255, 255, 255, 0.5)";
|
|
1828
|
-
}
|
|
1829
|
-
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
1830
|
-
const isLight = hsv.v > 0.6;
|
|
1831
|
-
const isSaturated = hsv.s > 0.3;
|
|
1832
|
-
const absLevel = Math.abs(level);
|
|
1833
|
-
const opacityBoost = Math.max(0, (absLevel - 1) * 0.05);
|
|
1834
|
-
if (isSaturated) {
|
|
1835
|
-
const rimLightValue = 0.95;
|
|
1836
|
-
const rimLightRgb = hsvToRgb(hsv.h, hsv.s * 0.3, rimLightValue);
|
|
1837
|
-
const baseOpacity = isLight ? 0.9 : 0.5;
|
|
1838
|
-
const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
|
|
1839
|
-
return `rgba(${rimLightRgb.r}, ${rimLightRgb.g}, ${rimLightRgb.b}, ${finalOpacity.toFixed(2)})`;
|
|
1840
|
-
} else {
|
|
1841
|
-
const baseOpacity = isLight ? 0.9 : 0.12;
|
|
1842
|
-
const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
|
|
1843
|
-
return `rgba(255, 255, 255, ${finalOpacity.toFixed(2)})`;
|
|
1844
|
-
}
|
|
1845
|
-
}
|
|
1846
|
-
function calculateDarkShadowColors(surfaceColor) {
|
|
1847
|
-
const rgb = hexToRgb(surfaceColor);
|
|
1848
|
-
if (!rgb) {
|
|
1849
|
-
return {
|
|
1850
|
-
dark: "rgba(0, 0, 0, 0.3)",
|
|
1851
|
-
darker: "rgba(0, 0, 0, 0.4)"
|
|
1852
|
-
};
|
|
1853
|
-
}
|
|
1854
|
-
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
1855
|
-
const isLight = hsv.v > 0.6;
|
|
1856
|
-
const isSaturated = hsv.s > 0.3;
|
|
1857
|
-
if (isSaturated) {
|
|
1858
|
-
const darkShadowValue = 0.15;
|
|
1859
|
-
const darkShadowRgb = hsvToRgb(hsv.h, hsv.s, darkShadowValue);
|
|
1860
|
-
if (isLight) {
|
|
1861
|
-
return {
|
|
1862
|
-
dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.3)`,
|
|
1863
|
-
darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.4)`
|
|
1864
|
-
};
|
|
1865
|
-
} else {
|
|
1866
|
-
return {
|
|
1867
|
-
dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.5)`,
|
|
1868
|
-
darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.6)`
|
|
1869
|
-
};
|
|
1870
|
-
}
|
|
1871
|
-
} else {
|
|
1872
|
-
if (isLight) {
|
|
1873
|
-
return {
|
|
1874
|
-
dark: "rgba(0, 0, 0, 0.2)",
|
|
1875
|
-
darker: "rgba(0, 0, 0, 0.3)"
|
|
1876
|
-
};
|
|
1877
|
-
} else {
|
|
1878
|
-
return {
|
|
1879
|
-
dark: "rgba(0, 0, 0, 0.5)",
|
|
1880
|
-
darker: "rgba(0, 0, 0, 0.6)"
|
|
1881
|
-
};
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
function getRimLightConfig() {
|
|
1886
|
-
return {
|
|
1887
|
-
offset: 1,
|
|
1888
|
-
// Fixed 1px for crisp rim
|
|
1889
|
-
blur: 1
|
|
1890
|
-
// Tight blur for crisp edge
|
|
1891
|
-
};
|
|
1892
|
-
}
|
|
1893
|
-
var elevationSurfaceCache = /* @__PURE__ */ new Map();
|
|
1894
|
-
var MAX_CACHE_SIZE = 100;
|
|
1895
|
-
function getCacheKey(baseColor, level, theme) {
|
|
1896
|
-
return `${baseColor}-${level}-${theme}`;
|
|
2173
|
+
var DEFAULT_CONTEXT = { mode: "dark", level: "base" };
|
|
2174
|
+
var SurfaceContext = react.createContext(DEFAULT_CONTEXT);
|
|
2175
|
+
function useSurface() {
|
|
2176
|
+
return react.useContext(SurfaceContext);
|
|
1897
2177
|
}
|
|
1898
|
-
function
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
}
|
|
1903
|
-
if (level < 0) {
|
|
1904
|
-
return baseColor;
|
|
1905
|
-
}
|
|
1906
|
-
return lighten(baseColor, config.colorAdjustment);
|
|
1907
|
-
}
|
|
1908
|
-
function getElevationSurface(baseColor, level, theme) {
|
|
1909
|
-
const cacheKey = getCacheKey(baseColor, level, theme);
|
|
1910
|
-
if (elevationSurfaceCache.has(cacheKey)) {
|
|
1911
|
-
return elevationSurfaceCache.get(cacheKey);
|
|
1912
|
-
}
|
|
1913
|
-
const result = calculateElevationSurface(baseColor, level);
|
|
1914
|
-
if (elevationSurfaceCache.size >= MAX_CACHE_SIZE) {
|
|
1915
|
-
const firstKey = elevationSurfaceCache.keys().next().value;
|
|
1916
|
-
elevationSurfaceCache.delete(firstKey);
|
|
1917
|
-
}
|
|
1918
|
-
elevationSurfaceCache.set(cacheKey, result);
|
|
1919
|
-
return result;
|
|
1920
|
-
}
|
|
1921
|
-
var elevationShadowCache = /* @__PURE__ */ new Map();
|
|
1922
|
-
var MAX_SHADOW_CACHE_SIZE = 50;
|
|
1923
|
-
function getShadowCacheKey(baseColor, level, theme, isHovered) {
|
|
1924
|
-
return `${baseColor}-${level}-${theme}-${isHovered}`;
|
|
1925
|
-
}
|
|
1926
|
-
function calculateElevationShadow(baseColor, level, theme, isHovered = false) {
|
|
1927
|
-
const config = elevationSystem[level];
|
|
1928
|
-
if (level === 0) {
|
|
1929
|
-
return {};
|
|
1930
|
-
}
|
|
1931
|
-
const elevatedSurfaceColor = calculateElevationSurface(baseColor, level);
|
|
1932
|
-
const rimLightColor = calculateRimLightColor(baseColor, level);
|
|
1933
|
-
const darkShadowColors = calculateDarkShadowColors(elevatedSurfaceColor);
|
|
1934
|
-
const intensityConfig = {
|
|
1935
|
-
subtle: { offset: 1, blur: 2 },
|
|
1936
|
-
medium: { offset: 2, blur: 4 },
|
|
1937
|
-
strong: { offset: 2, blur: 5 }
|
|
1938
|
-
};
|
|
1939
|
-
const { offset, blur } = intensityConfig[config.shadowIntensity];
|
|
1940
|
-
const rimConfig = getRimLightConfig();
|
|
1941
|
-
if (config.shadowStyle === "pressed") {
|
|
1942
|
-
if (isHovered) {
|
|
1943
|
-
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
1944
|
-
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
1945
|
-
return reactNative.Platform.select({
|
|
1946
|
-
web: {
|
|
1947
|
-
boxShadow: `inset ${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
1948
|
-
},
|
|
1949
|
-
default: {
|
|
1950
|
-
shadowOpacity: 0,
|
|
1951
|
-
elevation: 0
|
|
1952
|
-
}
|
|
1953
|
-
});
|
|
1954
|
-
}
|
|
1955
|
-
return reactNative.Platform.select({
|
|
1956
|
-
web: {
|
|
1957
|
-
boxShadow: `inset ${offset}px ${offset}px ${blur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
1958
|
-
},
|
|
1959
|
-
default: {
|
|
1960
|
-
shadowOpacity: 0,
|
|
1961
|
-
elevation: 0
|
|
1962
|
-
}
|
|
1963
|
-
});
|
|
1964
|
-
} else {
|
|
1965
|
-
if (isHovered) {
|
|
1966
|
-
const hoverOffset = Math.max(1, Math.round(offset / 2));
|
|
1967
|
-
const hoverBlur = Math.max(1, Math.round(blur / 2));
|
|
1968
|
-
return reactNative.Platform.select({
|
|
1969
|
-
web: {
|
|
1970
|
-
boxShadow: `${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
1971
|
-
},
|
|
1972
|
-
default: {
|
|
1973
|
-
shadowColor: "#000",
|
|
1974
|
-
shadowOffset: { width: hoverOffset, height: hoverOffset },
|
|
1975
|
-
shadowOpacity: 0.2,
|
|
1976
|
-
shadowRadius: hoverBlur / 2,
|
|
1977
|
-
elevation: hoverOffset
|
|
1978
|
-
}
|
|
1979
|
-
});
|
|
1980
|
-
}
|
|
1981
|
-
return reactNative.Platform.select({
|
|
1982
|
-
web: {
|
|
1983
|
-
boxShadow: `${offset}px ${offset}px ${blur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
|
|
1984
|
-
},
|
|
1985
|
-
default: {
|
|
1986
|
-
shadowColor: "#000",
|
|
1987
|
-
shadowOffset: { width: offset, height: offset },
|
|
1988
|
-
shadowOpacity: 0.3,
|
|
1989
|
-
shadowRadius: blur / 2,
|
|
1990
|
-
elevation: offset
|
|
1991
|
-
}
|
|
1992
|
-
});
|
|
1993
|
-
}
|
|
2178
|
+
function recessDepth(inherited, planesDown, mode) {
|
|
2179
|
+
let plane = inherited.level;
|
|
2180
|
+
for (let i = 0; i < planesDown; i++) plane = pressedLevel(plane);
|
|
2181
|
+
const backgroundColor = surfaceBackground(plane, mode);
|
|
2182
|
+
return { plane, backgroundColor, depthStyle: getPressedRecessShadow(backgroundColor, mode) };
|
|
1994
2183
|
}
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
const
|
|
1998
|
-
if (
|
|
1999
|
-
|
|
2184
|
+
function resolveSurfaceDepth(inherited, props) {
|
|
2185
|
+
const mode = props.theme ?? inherited.mode;
|
|
2186
|
+
const elevation = props.elevation ?? 0;
|
|
2187
|
+
if (props.pressed || elevation < 0) {
|
|
2188
|
+
const down = props.pressed ? 1 : -elevation;
|
|
2189
|
+
return { mode, step: 0, lifted: false, ...recessDepth(inherited, down, mode) };
|
|
2000
2190
|
}
|
|
2001
|
-
const
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
return
|
|
2008
|
-
}
|
|
2009
|
-
function getBaseSurfaceColor(theme) {
|
|
2010
|
-
return theme === "light" ? semanticColorsLight["surface-raised"] : semanticColorsDark["surface-elevated"];
|
|
2191
|
+
const step = props.level != null ? 0 : props.raise ?? elevation;
|
|
2192
|
+
const floating = step >= FLOATING_ELEVATION_MIN;
|
|
2193
|
+
const plane = props.level ?? (floating ? "overlay" : raisedLevel(inherited.level, step));
|
|
2194
|
+
const lifted = props.lift ?? step > 0;
|
|
2195
|
+
const liftStep = Math.max(1, Math.min(5, step));
|
|
2196
|
+
const depthStyle = lifted ? liftStyle(liftStep, mode, props.liftOptions) : {};
|
|
2197
|
+
return { mode, plane, backgroundColor: surfaceBackground(plane, mode), depthStyle, step, lifted };
|
|
2011
2198
|
}
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
},
|
|
2027
|
-
overlay: {
|
|
2028
|
-
allowed: [4, 5],
|
|
2029
|
-
default: 4
|
|
2030
|
-
}
|
|
2031
|
-
};
|
|
2032
|
-
function getValidatedElevation(component, requested) {
|
|
2033
|
-
const range = componentElevationRanges[component];
|
|
2034
|
-
if (range.allowed.includes(requested)) {
|
|
2035
|
-
return requested;
|
|
2036
|
-
}
|
|
2037
|
-
const sorted = [...range.allowed].sort((a, b) => a - b);
|
|
2038
|
-
if (requested < sorted[0]) return sorted[0];
|
|
2039
|
-
if (requested > sorted[sorted.length - 1]) return sorted[sorted.length - 1];
|
|
2040
|
-
return sorted.reduce(
|
|
2041
|
-
(prev, curr) => Math.abs(curr - requested) < Math.abs(prev - requested) ? curr : prev
|
|
2199
|
+
function useResolvedSurface(props) {
|
|
2200
|
+
const inherited = useSurface();
|
|
2201
|
+
const { level, raise, elevation, pressed, lift, liftOptions, theme } = props;
|
|
2202
|
+
return react.useMemo(
|
|
2203
|
+
() => resolveSurfaceDepth(inherited, {
|
|
2204
|
+
level,
|
|
2205
|
+
raise,
|
|
2206
|
+
elevation,
|
|
2207
|
+
pressed,
|
|
2208
|
+
lift,
|
|
2209
|
+
liftOptions,
|
|
2210
|
+
theme
|
|
2211
|
+
}),
|
|
2212
|
+
[inherited, level, raise, elevation, pressed, lift, liftOptions, theme]
|
|
2042
2213
|
);
|
|
2043
2214
|
}
|
|
2044
|
-
function getTheme() {
|
|
2045
|
-
if (typeof document === "undefined") return "dark";
|
|
2046
|
-
return document.documentElement.classList.contains("light") ? "light" : "dark";
|
|
2047
|
-
}
|
|
2048
|
-
var listeners = [];
|
|
2049
|
-
function subscribe(listener) {
|
|
2050
|
-
listeners = [...listeners, listener];
|
|
2051
|
-
if (typeof document !== "undefined" && listeners.length === 1) {
|
|
2052
|
-
const observer = new MutationObserver((mutations) => {
|
|
2053
|
-
for (const mutation of mutations) {
|
|
2054
|
-
if (mutation.type === "attributes" && mutation.attributeName === "class") {
|
|
2055
|
-
listeners.forEach((l) => l());
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
});
|
|
2059
|
-
observer.observe(document.documentElement, {
|
|
2060
|
-
attributes: true,
|
|
2061
|
-
attributeFilter: ["class"]
|
|
2062
|
-
});
|
|
2063
|
-
subscribe._observer = observer;
|
|
2064
|
-
}
|
|
2065
|
-
return () => {
|
|
2066
|
-
listeners = listeners.filter((l) => l !== listener);
|
|
2067
|
-
if (listeners.length === 0 && subscribe._observer) {
|
|
2068
|
-
subscribe._observer.disconnect();
|
|
2069
|
-
subscribe._observer = null;
|
|
2070
|
-
}
|
|
2071
|
-
};
|
|
2072
|
-
}
|
|
2073
|
-
function getSnapshot() {
|
|
2074
|
-
return getTheme();
|
|
2075
|
-
}
|
|
2076
|
-
function getServerSnapshot() {
|
|
2077
|
-
return "dark";
|
|
2078
|
-
}
|
|
2079
|
-
function useTheme() {
|
|
2080
|
-
return react.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
2081
|
-
}
|
|
2082
2215
|
|
|
2083
2216
|
// src/components/ui/card/Card.tsx
|
|
2084
|
-
var
|
|
2217
|
+
var EDGE_CLASS = {
|
|
2085
2218
|
elevated: "",
|
|
2086
|
-
|
|
2087
|
-
outline: "border-2 border-hairline-strong",
|
|
2088
|
-
// Thicker border with stronger contrast
|
|
2219
|
+
accent: "",
|
|
2089
2220
|
filled: "",
|
|
2090
|
-
|
|
2091
|
-
accent: "border border-hairline",
|
|
2221
|
+
outline: "border border-hairline-strong",
|
|
2092
2222
|
subtle: "border border-hairline-subtle"
|
|
2093
2223
|
};
|
|
2224
|
+
var LIFTED = {
|
|
2225
|
+
elevated: true,
|
|
2226
|
+
accent: true,
|
|
2227
|
+
filled: false,
|
|
2228
|
+
outline: false,
|
|
2229
|
+
subtle: false
|
|
2230
|
+
};
|
|
2231
|
+
var STAYS_ON_HOST = {
|
|
2232
|
+
elevated: false,
|
|
2233
|
+
accent: false,
|
|
2234
|
+
filled: false,
|
|
2235
|
+
outline: true,
|
|
2236
|
+
subtle: true
|
|
2237
|
+
};
|
|
2238
|
+
function useCardDepth(variant, elevation, hovered) {
|
|
2239
|
+
const raise = STAYS_ON_HOST[variant] ? void 0 : elevation;
|
|
2240
|
+
const resolved = useResolvedSurface({ raise, lift: LIFTED[variant] });
|
|
2241
|
+
const depthStyle = react.useMemo(() => {
|
|
2242
|
+
if (!hovered || !LIFTED[variant]) return resolved.depthStyle;
|
|
2243
|
+
const hoverStep = Math.min(3, resolved.step + 1);
|
|
2244
|
+
return liftStyle(hoverStep, resolved.mode);
|
|
2245
|
+
}, [hovered, variant, resolved]);
|
|
2246
|
+
return { ...resolved, depthStyle };
|
|
2247
|
+
}
|
|
2094
2248
|
function Card({
|
|
2095
2249
|
variant = "elevated",
|
|
2096
2250
|
elevation = 2,
|
|
@@ -2111,89 +2265,54 @@ function Card({
|
|
|
2111
2265
|
}) {
|
|
2112
2266
|
const isClickable = isInteractive || !!onPress;
|
|
2113
2267
|
const [isHovered, setIsHovered] = react.useState(false);
|
|
2114
|
-
const
|
|
2115
|
-
const elevationLevel = react.useMemo(() => {
|
|
2116
|
-
const validated = getValidatedElevation("card", elevation);
|
|
2117
|
-
if (variant === "outline" || variant === "accent" || variant === "subtle") {
|
|
2118
|
-
return 1;
|
|
2119
|
-
}
|
|
2120
|
-
return validated;
|
|
2121
|
-
}, [variant, elevation]);
|
|
2122
|
-
const baseColor = react.useMemo(() => getBaseSurfaceColor(theme), [theme]);
|
|
2123
|
-
const surfaceColor = react.useMemo(() => {
|
|
2124
|
-
if ((variant === "outline" || variant === "accent") && theme === "light") {
|
|
2125
|
-
return "#FAFAFA";
|
|
2126
|
-
}
|
|
2127
|
-
if (variant === "subtle") {
|
|
2128
|
-
return getElevationSurface(baseColor, 0, theme);
|
|
2129
|
-
}
|
|
2130
|
-
return getElevationSurface(baseColor, elevationLevel, theme);
|
|
2131
|
-
}, [baseColor, elevationLevel, theme, variant]);
|
|
2132
|
-
const shadowStyle = react.useMemo(() => {
|
|
2133
|
-
const shouldHover = isHovered && isClickable;
|
|
2134
|
-
return getElevationShadow(baseColor, elevationLevel, theme, shouldHover);
|
|
2135
|
-
}, [baseColor, elevationLevel, theme, isHovered, isClickable]);
|
|
2136
|
-
const cardContent = isLoading ? /* @__PURE__ */ jsxs(jsxRuntime.Fragment, { children: [
|
|
2137
|
-
skeletonHasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
2138
|
-
/* @__PURE__ */ jsx(reactNative.View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
|
|
2139
|
-
/* @__PURE__ */ jsx(reactNative.View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
|
|
2140
|
-
] }),
|
|
2141
|
-
/* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: skeletonContentLines }).map((_, i) => /* @__PURE__ */ jsx(
|
|
2142
|
-
reactNative.View,
|
|
2143
|
-
{
|
|
2144
|
-
className: cn(
|
|
2145
|
-
"h-4 bg-interactive-disabled rounded",
|
|
2146
|
-
i < skeletonContentLines - 1 ? "mb-2 w-full" : "w-4/5"
|
|
2147
|
-
)
|
|
2148
|
-
},
|
|
2149
|
-
i
|
|
2150
|
-
)) }),
|
|
2151
|
-
skeletonHasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(reactNative.View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
|
|
2152
|
-
] }) : children;
|
|
2268
|
+
const depth = useCardDepth(variant, elevation, isHovered && isClickable);
|
|
2153
2269
|
const baseClassName = cn(
|
|
2154
2270
|
"rounded-lg overflow-hidden relative",
|
|
2155
|
-
|
|
2156
|
-
variant === "outline" ? borderColor ? "border-2" : variantStyles[variant] : variantStyles[variant],
|
|
2157
|
-
// Remove Tailwind shadow classes - we're using elevation shadows via style prop
|
|
2271
|
+
borderColor ? "border" : EDGE_CLASS[variant],
|
|
2158
2272
|
isClickable && "web:cursor-pointer web:transition-all web:duration-150",
|
|
2159
2273
|
isClickable && "web:hover:-translate-y-0.5 active:scale-[0.99]",
|
|
2160
2274
|
isLoading && "pointer-events-none animate-pulse",
|
|
2161
2275
|
className
|
|
2162
2276
|
);
|
|
2163
|
-
const accentStyle = react.useMemo(() => variant === "accent" ? {
|
|
2164
|
-
borderLeftWidth: accentWidth ?? 3,
|
|
2165
|
-
borderLeftColor: accentColor ?? "var(--color-brand-primary)"
|
|
2166
|
-
} : {}, [variant, accentWidth, accentColor]);
|
|
2167
2277
|
const mergedStyle = react.useMemo(() => {
|
|
2168
|
-
const
|
|
2169
|
-
backgroundColor: bgColor ||
|
|
2278
|
+
const own = {
|
|
2279
|
+
backgroundColor: bgColor || depth.backgroundColor,
|
|
2170
2280
|
borderRadius: 8,
|
|
2171
2281
|
overflow: "hidden",
|
|
2172
|
-
...
|
|
2173
|
-
...accentStyle
|
|
2282
|
+
...depth.depthStyle
|
|
2174
2283
|
};
|
|
2175
|
-
if (
|
|
2176
|
-
|
|
2284
|
+
if (variant === "accent") {
|
|
2285
|
+
own.borderLeftWidth = accentWidth ?? 3;
|
|
2286
|
+
own.borderLeftColor = accentColor ?? "var(--color-brand-primary)";
|
|
2177
2287
|
}
|
|
2178
|
-
if (
|
|
2179
|
-
return [
|
|
2180
|
-
}, [style,
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2288
|
+
if (borderColor) own.borderColor = borderColor;
|
|
2289
|
+
return style ? [own, style] : own;
|
|
2290
|
+
}, [style, depth, bgColor, borderColor, variant, accentWidth, accentColor]);
|
|
2291
|
+
const context = react.useMemo(
|
|
2292
|
+
() => ({ mode: depth.mode, level: depth.plane }),
|
|
2293
|
+
[depth.mode, depth.plane]
|
|
2294
|
+
);
|
|
2295
|
+
const content = isLoading ? /* @__PURE__ */ jsx(
|
|
2296
|
+
SkeletonBody,
|
|
2297
|
+
{
|
|
2298
|
+
hasHeader: skeletonHasHeader,
|
|
2299
|
+
hasFooter: skeletonHasFooter,
|
|
2300
|
+
contentLines: skeletonContentLines
|
|
2301
|
+
}
|
|
2302
|
+
) : children;
|
|
2303
|
+
return /* @__PURE__ */ jsx(SurfaceContext.Provider, { value: context, children: isClickable ? /* @__PURE__ */ jsx(
|
|
2304
|
+
reactNative.Pressable,
|
|
2305
|
+
{
|
|
2306
|
+
onPress,
|
|
2307
|
+
onHoverIn: () => setIsHovered(true),
|
|
2308
|
+
onHoverOut: () => setIsHovered(false),
|
|
2309
|
+
accessibilityRole: "button",
|
|
2310
|
+
className: baseClassName,
|
|
2311
|
+
style: mergedStyle,
|
|
2312
|
+
...props,
|
|
2313
|
+
children: content
|
|
2314
|
+
}
|
|
2315
|
+
) : /* @__PURE__ */ jsx(reactNative.View, { className: baseClassName, style: mergedStyle, ...props, children: content }) });
|
|
2197
2316
|
}
|
|
2198
2317
|
function CardHeader({ children, className }) {
|
|
2199
2318
|
return /* @__PURE__ */ jsx(reactNative.View, { className: cn("px-6 py-6", className), children });
|
|
@@ -2204,60 +2323,88 @@ function CardContent({ children, className }) {
|
|
|
2204
2323
|
function CardFooter({ children, className }) {
|
|
2205
2324
|
return /* @__PURE__ */ jsx(reactNative.View, { className: cn("px-6 py-4 flex-row items-center gap-2", className), children });
|
|
2206
2325
|
}
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2326
|
+
function SkeletonBody({ hasHeader, hasFooter, contentLines }) {
|
|
2327
|
+
return /* @__PURE__ */ jsxs(jsxRuntime.Fragment, { children: [
|
|
2328
|
+
hasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
2329
|
+
/* @__PURE__ */ jsx(reactNative.View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
|
|
2330
|
+
/* @__PURE__ */ jsx(reactNative.View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
|
|
2331
|
+
] }),
|
|
2332
|
+
/* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: contentLines }).map((_, i) => /* @__PURE__ */ jsx(
|
|
2333
|
+
reactNative.View,
|
|
2334
|
+
{
|
|
2335
|
+
className: cn(
|
|
2336
|
+
"h-4 bg-interactive-disabled rounded",
|
|
2337
|
+
i < contentLines - 1 ? "mb-2 w-full" : "w-4/5"
|
|
2338
|
+
)
|
|
2339
|
+
},
|
|
2340
|
+
i
|
|
2341
|
+
)) }),
|
|
2342
|
+
hasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(reactNative.View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
|
|
2343
|
+
] });
|
|
2344
|
+
}
|
|
2345
|
+
var solidFillToken = {
|
|
2346
|
+
success: "status-success",
|
|
2347
|
+
warning: "status-warning",
|
|
2348
|
+
error: "status-error",
|
|
2349
|
+
neutral: "text-tertiary"
|
|
2213
2350
|
};
|
|
2214
|
-
var
|
|
2215
|
-
"on-track": {
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
borderStyle: "dashed",
|
|
2229
|
-
borderColor: "rgba(107,114,128,0.2)"
|
|
2230
|
-
}
|
|
2351
|
+
var ringWashToken = {
|
|
2352
|
+
"on-track": { fill: "status-success-subtle", border: "status-success-muted" },
|
|
2353
|
+
deviation: { fill: "status-warning-subtle", border: "status-warning-muted" }
|
|
2354
|
+
};
|
|
2355
|
+
var FUTURE_FILL = alpha(greyRamp[500], 0.1);
|
|
2356
|
+
var FUTURE_BORDER = alpha(greyRamp[500], 0.2);
|
|
2357
|
+
var glyphToken = {
|
|
2358
|
+
success: "text-inverse",
|
|
2359
|
+
warning: "text-inverse",
|
|
2360
|
+
error: "text-inverse",
|
|
2361
|
+
neutral: "text-inverse",
|
|
2362
|
+
"on-track": "status-success",
|
|
2363
|
+
deviation: "status-warning",
|
|
2364
|
+
future: "text-tertiary"
|
|
2231
2365
|
};
|
|
2232
|
-
var
|
|
2233
|
-
success:
|
|
2234
|
-
warning:
|
|
2235
|
-
error:
|
|
2236
|
-
neutral:
|
|
2237
|
-
"on-track":
|
|
2238
|
-
deviation:
|
|
2239
|
-
future:
|
|
2366
|
+
var glowColors2 = {
|
|
2367
|
+
success: semanticColorsDark["status-success"],
|
|
2368
|
+
warning: semanticColorsDark["status-warning"],
|
|
2369
|
+
error: semanticColorsDark["status-error"],
|
|
2370
|
+
neutral: greyRamp[500],
|
|
2371
|
+
"on-track": semanticColorsDark["status-success"],
|
|
2372
|
+
deviation: semanticColorsDark["status-warning"],
|
|
2373
|
+
future: greyRamp[500]
|
|
2240
2374
|
};
|
|
2375
|
+
var glowStyles = Object.fromEntries(
|
|
2376
|
+
Object.entries(glowColors2).map(([variant, color]) => [variant, getGlowShadow(color, "subtle")])
|
|
2377
|
+
);
|
|
2241
2378
|
var iconChars = {
|
|
2242
2379
|
check: "\u2713",
|
|
2243
2380
|
exclamation: "!",
|
|
2244
2381
|
dash: "\u2014"
|
|
2245
2382
|
};
|
|
2246
|
-
var iconColors = {
|
|
2247
|
-
success: "#0A5C52",
|
|
2248
|
-
warning: "#6B4000",
|
|
2249
|
-
error: "#5C1A1A",
|
|
2250
|
-
neutral: greyRamp[200],
|
|
2251
|
-
"on-track": t2["status-success"],
|
|
2252
|
-
deviation: t2["status-warning"],
|
|
2253
|
-
future: greyRamp[500]
|
|
2254
|
-
};
|
|
2255
2383
|
var sizeDimensions = {
|
|
2256
2384
|
sm: { size: 8, showIcon: false },
|
|
2257
2385
|
md: { size: 18, showIcon: true }
|
|
2258
2386
|
};
|
|
2259
2387
|
function isSolidVariant(variant) {
|
|
2260
|
-
return variant in
|
|
2388
|
+
return variant in solidFillToken;
|
|
2389
|
+
}
|
|
2390
|
+
function ringStyle(variant) {
|
|
2391
|
+
if (variant === "future") {
|
|
2392
|
+
return {
|
|
2393
|
+
backgroundColor: FUTURE_FILL,
|
|
2394
|
+
borderWidth: 1,
|
|
2395
|
+
borderStyle: "dashed",
|
|
2396
|
+
borderColor: FUTURE_BORDER
|
|
2397
|
+
};
|
|
2398
|
+
}
|
|
2399
|
+
if (variant === "on-track" || variant === "deviation") {
|
|
2400
|
+
const tokens = ringWashToken[variant];
|
|
2401
|
+
return {
|
|
2402
|
+
backgroundColor: resolveColor(tokens.fill),
|
|
2403
|
+
borderWidth: 1,
|
|
2404
|
+
borderColor: resolveColor(tokens.border)
|
|
2405
|
+
};
|
|
2406
|
+
}
|
|
2407
|
+
return void 0;
|
|
2261
2408
|
}
|
|
2262
2409
|
function StatusDot({
|
|
2263
2410
|
variant,
|
|
@@ -2270,7 +2417,7 @@ function StatusDot({
|
|
|
2270
2417
|
}) {
|
|
2271
2418
|
const config = sizeDimensions[size];
|
|
2272
2419
|
const solid = isSolidVariant(variant);
|
|
2273
|
-
const ring =
|
|
2420
|
+
const ring = ringStyle(variant);
|
|
2274
2421
|
const glowStyle = glow ? glowStyles[variant] : null;
|
|
2275
2422
|
const dot = /* @__PURE__ */ jsx(
|
|
2276
2423
|
reactNative.View,
|
|
@@ -2284,22 +2431,22 @@ function StatusDot({
|
|
|
2284
2431
|
justifyContent: "center",
|
|
2285
2432
|
flexShrink: 0
|
|
2286
2433
|
},
|
|
2287
|
-
solid ? { backgroundColor:
|
|
2288
|
-
ring
|
|
2434
|
+
solid ? { backgroundColor: resolveColor(solidFillToken[variant]) } : void 0,
|
|
2435
|
+
ring,
|
|
2289
2436
|
glowStyle ? glowStyle : void 0
|
|
2290
2437
|
],
|
|
2291
2438
|
accessibilityRole: "image",
|
|
2292
2439
|
accessibilityLabel: `${variant} status`,
|
|
2293
2440
|
testID: "status-dot",
|
|
2294
|
-
children: config.showIcon && icon &&
|
|
2295
|
-
|
|
2441
|
+
children: config.showIcon && icon && // The glyph was 11px/900, off the type scale (TOKENS.md §4); `boldLabel` is
|
|
2442
|
+
// the 12px sans label step and `font-black` keeps the original weight.
|
|
2443
|
+
/* @__PURE__ */ jsx(
|
|
2444
|
+
Typography,
|
|
2296
2445
|
{
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
color: iconColors[variant]
|
|
2302
|
-
},
|
|
2446
|
+
variant: "boldLabel",
|
|
2447
|
+
color: "inherit",
|
|
2448
|
+
className: "font-black leading-none",
|
|
2449
|
+
style: { color: resolveColor(glyphToken[variant]) },
|
|
2303
2450
|
accessibilityElementsHidden: true,
|
|
2304
2451
|
children: iconChars[icon]
|
|
2305
2452
|
}
|
|
@@ -2317,9 +2464,11 @@ function StatusDot({
|
|
|
2317
2464
|
children: [
|
|
2318
2465
|
/* @__PURE__ */ jsx(reactNative.View, { accessibilityElementsHidden: true, children: dot }),
|
|
2319
2466
|
/* @__PURE__ */ jsx(
|
|
2320
|
-
|
|
2467
|
+
Typography,
|
|
2321
2468
|
{
|
|
2322
|
-
|
|
2469
|
+
variant: "caption",
|
|
2470
|
+
color: "secondary",
|
|
2471
|
+
className: "leading-4",
|
|
2323
2472
|
accessibilityElementsHidden: true,
|
|
2324
2473
|
children: label
|
|
2325
2474
|
}
|
|
@@ -2335,19 +2484,19 @@ var MESO_ACCENT_GRADIENT_LIGHT = primitiveRamps.orange[300];
|
|
|
2335
2484
|
|
|
2336
2485
|
// src/components/custom/Workout/MesoStatusCard.tsx
|
|
2337
2486
|
var t3 = getSemanticColors("dark");
|
|
2338
|
-
var
|
|
2487
|
+
var BRAND_PRIMARY3 = t3["brand-primary"];
|
|
2339
2488
|
var BRAND_PRIMARY_DARK = MESO_ACCENT_GRADIENT_DARK;
|
|
2340
2489
|
var BRAND_PRIMARY_LIGHT = MESO_ACCENT_GRADIENT_LIGHT;
|
|
2341
2490
|
var SUCCESS = t3["status-success"];
|
|
2342
2491
|
var WARNING = t3["status-warning"];
|
|
2343
2492
|
var ERROR = t3["status-error"];
|
|
2344
|
-
var ACCENT_STOPS = [BRAND_PRIMARY_DARK,
|
|
2493
|
+
var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY3, BRAND_PRIMARY_LIGHT];
|
|
2345
2494
|
var CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor("surface-elevated")} 0%, ${resolveColor("surface-raised")} 100%)`;
|
|
2346
|
-
var GAUGE_GRADIENT =
|
|
2495
|
+
var GAUGE_GRADIENT = `linear-gradient(90deg, ${alpha(SUCCESS, 0.25)} 0%, ${alpha(WARNING, 0.25)} 50%, ${alpha(ERROR, 0.25)} 100%)`;
|
|
2347
2496
|
var STATUS_VARIANTS = {
|
|
2348
|
-
success: { bg:
|
|
2349
|
-
warning: { bg:
|
|
2350
|
-
error: { bg:
|
|
2497
|
+
success: { bg: alpha(SUCCESS, 0.15), border: alpha(SUCCESS, 0.3), text: SUCCESS },
|
|
2498
|
+
warning: { bg: alpha(WARNING, 0.15), border: alpha(WARNING, 0.3), text: WARNING },
|
|
2499
|
+
error: { bg: alpha(ERROR, 0.15), border: alpha(ERROR, 0.25), text: ERROR }
|
|
2351
2500
|
};
|
|
2352
2501
|
function clamp012(value) {
|
|
2353
2502
|
if (!Number.isFinite(value)) return 0;
|
|
@@ -2366,15 +2515,7 @@ function renderCoachingText(text, highlights) {
|
|
|
2366
2515
|
if (escaped.length === 0) return text;
|
|
2367
2516
|
const regex = new RegExp(`(${escaped.join("|")})`, "g");
|
|
2368
2517
|
return text.split(regex).map(
|
|
2369
|
-
(part, index) => highlights.includes(part) ? /* @__PURE__ */ jsx(
|
|
2370
|
-
reactNative.Text,
|
|
2371
|
-
{
|
|
2372
|
-
className: "text-text-primary",
|
|
2373
|
-
style: { fontWeight: "700" },
|
|
2374
|
-
children: part
|
|
2375
|
-
},
|
|
2376
|
-
`${part}-${index}`
|
|
2377
|
-
) : /* @__PURE__ */ jsx(react.Fragment, { children: part }, `t-${index}`)
|
|
2518
|
+
(part, index) => highlights.includes(part) ? /* @__PURE__ */ jsx(reactNative.Text, { className: "text-text-primary", style: { fontWeight: "700" }, children: part }, `${part}-${index}`) : /* @__PURE__ */ jsx(react.Fragment, { children: part }, `t-${index}`)
|
|
2378
2519
|
);
|
|
2379
2520
|
}
|
|
2380
2521
|
function StatusPill({ badge }) {
|
|
@@ -2459,41 +2600,34 @@ function Gauge({ gauge }) {
|
|
|
2459
2600
|
"aria-valuemax": 100,
|
|
2460
2601
|
testID: "meso-status-card-gauge",
|
|
2461
2602
|
children: [
|
|
2462
|
-
/* @__PURE__ */ jsxs(
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
},
|
|
2491
|
-
children: gauge.sublabel
|
|
2492
|
-
}
|
|
2493
|
-
)
|
|
2494
|
-
]
|
|
2495
|
-
}
|
|
2496
|
-
),
|
|
2603
|
+
/* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-center justify-between", accessibilityElementsHidden: true, children: [
|
|
2604
|
+
/* @__PURE__ */ jsx(
|
|
2605
|
+
reactNative.Text,
|
|
2606
|
+
{
|
|
2607
|
+
className: "text-text-secondary",
|
|
2608
|
+
style: {
|
|
2609
|
+
fontSize: 10,
|
|
2610
|
+
fontFamily: "Inter, sans-serif",
|
|
2611
|
+
fontWeight: "500",
|
|
2612
|
+
letterSpacing: 0.5,
|
|
2613
|
+
textTransform: "uppercase"
|
|
2614
|
+
},
|
|
2615
|
+
children: gauge.label
|
|
2616
|
+
}
|
|
2617
|
+
),
|
|
2618
|
+
gauge.sublabel != null && /* @__PURE__ */ jsx(
|
|
2619
|
+
reactNative.Text,
|
|
2620
|
+
{
|
|
2621
|
+
className: "text-text-tertiary",
|
|
2622
|
+
style: {
|
|
2623
|
+
fontSize: 10,
|
|
2624
|
+
fontFamily: "Inter, sans-serif",
|
|
2625
|
+
fontWeight: "500"
|
|
2626
|
+
},
|
|
2627
|
+
children: gauge.sublabel
|
|
2628
|
+
}
|
|
2629
|
+
)
|
|
2630
|
+
] }),
|
|
2497
2631
|
/* @__PURE__ */ jsxs(
|
|
2498
2632
|
reactNative.View,
|
|
2499
2633
|
{
|
|
@@ -2515,7 +2649,7 @@ function Gauge({ gauge }) {
|
|
|
2515
2649
|
bottom: 0,
|
|
2516
2650
|
width: 1,
|
|
2517
2651
|
marginLeft: -0.5,
|
|
2518
|
-
backgroundColor:
|
|
2652
|
+
backgroundColor: alpha(primitiveColors.white, 0.3)
|
|
2519
2653
|
},
|
|
2520
2654
|
testID: "meso-status-card-gauge-center"
|
|
2521
2655
|
}
|
|
@@ -2534,7 +2668,8 @@ function Gauge({ gauge }) {
|
|
|
2534
2668
|
borderRadius: 9999,
|
|
2535
2669
|
borderWidth: 2,
|
|
2536
2670
|
backgroundColor: markerColor,
|
|
2537
|
-
|
|
2671
|
+
// A knob resting on the gauge: lift, with the ring as its edge.
|
|
2672
|
+
...liftStyle(1, "dark", { rim: 0 })
|
|
2538
2673
|
},
|
|
2539
2674
|
testID: "meso-status-card-gauge-marker"
|
|
2540
2675
|
}
|
|
@@ -2586,30 +2721,23 @@ function MesoStatusCard({
|
|
|
2586
2721
|
),
|
|
2587
2722
|
/* @__PURE__ */ jsxs(reactNative.View, { style: { padding: 14, gap: 14 }, testID: "meso-status-card-body", children: [
|
|
2588
2723
|
/* @__PURE__ */ jsxs(reactNative.View, { testID: "meso-status-card-header", children: [
|
|
2589
|
-
/* @__PURE__ */ jsxs(
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
children: mesoName
|
|
2607
|
-
}
|
|
2608
|
-
),
|
|
2609
|
-
/* @__PURE__ */ jsx(StatusPill, { badge: statusBadge })
|
|
2610
|
-
]
|
|
2611
|
-
}
|
|
2612
|
-
),
|
|
2724
|
+
/* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-center justify-between", style: { gap: 8 }, children: [
|
|
2725
|
+
/* @__PURE__ */ jsx(
|
|
2726
|
+
reactNative.Text,
|
|
2727
|
+
{
|
|
2728
|
+
className: "text-text-primary",
|
|
2729
|
+
style: {
|
|
2730
|
+
flexShrink: 1,
|
|
2731
|
+
fontSize: 15,
|
|
2732
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
2733
|
+
fontWeight: "700"
|
|
2734
|
+
},
|
|
2735
|
+
testID: "meso-status-card-name",
|
|
2736
|
+
children: mesoName
|
|
2737
|
+
}
|
|
2738
|
+
),
|
|
2739
|
+
/* @__PURE__ */ jsx(StatusPill, { badge: statusBadge })
|
|
2740
|
+
] }),
|
|
2613
2741
|
/* @__PURE__ */ jsx(
|
|
2614
2742
|
reactNative.Text,
|
|
2615
2743
|
{
|
|
@@ -2624,23 +2752,15 @@ function MesoStatusCard({
|
|
|
2624
2752
|
}
|
|
2625
2753
|
)
|
|
2626
2754
|
] }),
|
|
2627
|
-
metrics.length > 0 && /* @__PURE__ */ jsx(
|
|
2628
|
-
reactNative.View,
|
|
2629
|
-
{
|
|
2630
|
-
className: "flex-row flex-wrap",
|
|
2631
|
-
style: { gap: 8 },
|
|
2632
|
-
testID: "meso-status-card-metrics",
|
|
2633
|
-
children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell, { metric }, `${metric.label}-${index}`))
|
|
2634
|
-
}
|
|
2635
|
-
),
|
|
2755
|
+
metrics.length > 0 && /* @__PURE__ */ jsx(reactNative.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}`)) }),
|
|
2636
2756
|
gauges.length > 0 && /* @__PURE__ */ jsx(reactNative.View, { style: { gap: 12 }, testID: "meso-status-card-gauges", children: gauges.map((gauge, index) => /* @__PURE__ */ jsx(Gauge, { gauge }, `${gauge.label}-${index}`)) }),
|
|
2637
2757
|
coaching != null && /* @__PURE__ */ jsx(
|
|
2638
2758
|
reactNative.View,
|
|
2639
2759
|
{
|
|
2640
2760
|
style: {
|
|
2641
|
-
backgroundColor:
|
|
2761
|
+
backgroundColor: alpha(WARNING, 0.06),
|
|
2642
2762
|
borderWidth: 1,
|
|
2643
|
-
borderColor:
|
|
2763
|
+
borderColor: alpha(WARNING, 0.15),
|
|
2644
2764
|
borderRadius: 8,
|
|
2645
2765
|
paddingVertical: 10,
|
|
2646
2766
|
paddingHorizontal: 12
|
|
@@ -2666,9 +2786,9 @@ function MesoStatusCard({
|
|
|
2666
2786
|
className: "flex-row items-center",
|
|
2667
2787
|
style: {
|
|
2668
2788
|
gap: 8,
|
|
2669
|
-
backgroundColor:
|
|
2789
|
+
backgroundColor: alpha(SUCCESS, 0.06),
|
|
2670
2790
|
borderWidth: 1,
|
|
2671
|
-
borderColor:
|
|
2791
|
+
borderColor: alpha(SUCCESS, 0.2),
|
|
2672
2792
|
borderRadius: 8,
|
|
2673
2793
|
paddingVertical: 10,
|
|
2674
2794
|
paddingHorizontal: 12
|