@titan-design/react-ui 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bodymap.js +12 -7
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +12 -7
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +956 -128
- package/dist/index.d.ts +956 -128
- package/dist/index.js +2873 -981
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2826 -982
- package/dist/index.mjs.map +1 -1
- package/dist/{pages-MO0JCySL.d.mts → pages-DCFBqp79.d.mts} +289 -57
- package/dist/{pages-D7Jlssvp.d.ts → pages-_fI3-x7Z.d.ts} +289 -57
- package/dist/pages.d.mts +1 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +1659 -799
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +1660 -800
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +16 -82
- package/dist/theme/index.d.ts +16 -82
- package/dist/theme/index.js +13 -115
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +13 -115
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +14 -6
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +14 -6
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/package.json +1 -1
- package/src/arch/Architecture.stories.tsx +870 -0
- package/src/arch/annotations.json +48 -0
- package/src/arch/arch-graph.json +4301 -0
- package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +90 -0
- package/src/components/custom/CircularTimer/CircularTimer.test.tsx +62 -0
- package/src/components/custom/CircularTimer/CircularTimer.tsx +112 -0
- package/src/components/custom/CircularTimer/index.ts +1 -0
- package/src/components/custom/DateTime/DateTime.stories.tsx +1 -1
- package/src/components/custom/EmptyState/EmptyState.stories.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.stories.tsx +1 -1
- package/src/components/custom/Metric/Metric.stories.tsx +1 -1
- package/src/components/custom/Scatter/Scatter.stories.tsx +1 -1
- package/src/components/custom/Sidebar/Sidebar.stories.tsx +1 -1
- package/src/components/custom/Table/Table.stories.tsx +1 -1
- package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +62 -0
- package/src/components/custom/TimerReadout/TimerReadout.test.tsx +72 -0
- package/src/components/custom/TimerReadout/TimerReadout.tsx +75 -0
- package/src/components/custom/TimerReadout/index.ts +1 -0
- package/src/components/custom/Treemap/Treemap.stories.tsx +1 -1
- package/src/components/custom/Typography/Typography.stories.tsx +1 -1
- package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +21 -13
- package/src/components/custom/Workout/ActiveWorkoutPage.test.tsx +16 -13
- package/src/components/custom/Workout/ActiveWorkoutPage.tsx +9 -15
- package/src/components/custom/Workout/BaseBadge.stories.tsx +1 -1
- package/src/components/custom/Workout/BodyMap.stories.tsx +1 -1
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +1 -1
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
- package/src/components/custom/Workout/ExerciseCard.stories.tsx +51 -66
- package/src/components/custom/Workout/ExerciseCard.test.tsx +146 -143
- package/src/components/custom/Workout/ExerciseCard.tsx +176 -198
- package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +99 -0
- package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +72 -0
- package/src/components/custom/Workout/ExerciseCardHeading.tsx +43 -0
- package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +151 -0
- package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +5 -3
- package/src/components/custom/Workout/ExerciseDetailPage.test.tsx +4 -4
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +4 -5
- package/src/components/custom/Workout/ExerciseHeading.stories.tsx +81 -0
- package/src/components/custom/Workout/ExerciseHeading.test.tsx +77 -0
- package/src/components/custom/Workout/ExerciseHeading.tsx +85 -0
- package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +110 -0
- package/src/components/custom/Workout/ExerciseIndicator.test.tsx +93 -0
- package/src/components/custom/Workout/ExerciseIndicator.tsx +120 -0
- package/src/components/custom/Workout/FatigueMeter.stories.tsx +51 -0
- package/src/components/custom/Workout/FatigueMeter.test.tsx +85 -0
- package/src/components/custom/Workout/FatigueMeter.tsx +86 -0
- package/src/components/custom/Workout/InputBar.stories.tsx +1 -1
- package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
- package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +153 -0
- package/src/components/custom/Workout/LiveAuraFrame.test.tsx +74 -0
- package/src/components/custom/Workout/LiveAuraFrame.tsx +105 -0
- package/src/components/custom/Workout/MesoCard.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoStatusCard.stories.tsx +1 -1
- package/src/components/custom/Workout/MetricTiles.stories.tsx +60 -0
- package/src/components/custom/Workout/MetricTiles.test.tsx +58 -0
- package/src/components/custom/Workout/MetricTiles.tsx +48 -0
- package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +1 -1
- package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
- package/src/components/custom/Workout/PrBadge.stories.tsx +1 -1
- package/src/components/custom/Workout/PrHistoryModal.stories.tsx +1 -1
- package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +4 -16
- package/src/components/custom/Workout/ProgramPlanningPage.tsx +8 -6
- package/src/components/custom/Workout/README.md +193 -4
- package/src/components/custom/Workout/ReadinessCheck.stories.tsx +1 -1
- package/src/components/custom/Workout/RestTimer.stories.tsx +133 -3
- package/src/components/custom/Workout/RestTimer.test.tsx +73 -0
- package/src/components/custom/Workout/RestTimer.tsx +155 -59
- package/src/components/custom/Workout/RowInventory.stories.tsx +405 -0
- package/src/components/custom/Workout/S3FullRail.stories.tsx +34 -0
- package/src/components/custom/Workout/S3SessionPace.stories.tsx +95 -0
- package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +61 -0
- package/src/components/custom/Workout/S3SetTypes.stories.tsx +176 -0
- package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +240 -0
- package/src/components/custom/Workout/ScheduleTiles.stories.tsx +40 -0
- package/src/components/custom/Workout/ScheduleTiles.test.tsx +34 -0
- package/src/components/custom/Workout/ScheduleTiles.tsx +70 -0
- package/src/components/custom/Workout/SegmentedBar.stories.tsx +99 -0
- package/src/components/custom/Workout/SegmentedBar.test.tsx +77 -0
- package/src/components/custom/Workout/SegmentedBar.tsx +172 -0
- package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +50 -0
- package/src/components/custom/Workout/SegmentedProgressBar.test.tsx +80 -0
- package/src/components/custom/Workout/SegmentedProgressBar.tsx +67 -0
- package/src/components/custom/Workout/SessionHeader.stories.tsx +121 -0
- package/src/components/custom/Workout/SessionHeader.test.tsx +122 -0
- package/src/components/custom/Workout/SessionHeader.tsx +152 -0
- package/src/components/custom/Workout/SessionRail.stories.tsx +153 -0
- package/src/components/custom/Workout/SessionRail.test.tsx +86 -0
- package/src/components/custom/Workout/SessionRail.tsx +126 -0
- package/src/components/custom/Workout/SetBar.stories.tsx +124 -0
- package/src/components/custom/Workout/SetBar.test.tsx +123 -0
- package/src/components/custom/Workout/SetBar.tsx +171 -0
- package/src/components/custom/Workout/SetRow.stories.tsx +50 -100
- package/src/components/custom/Workout/SetRow.test.tsx +94 -166
- package/src/components/custom/Workout/SetRow.tsx +169 -232
- package/src/components/custom/Workout/SetStrip.stories.tsx +154 -0
- package/src/components/custom/Workout/SetStrip.test.tsx +109 -0
- package/src/components/custom/Workout/SetStrip.tsx +71 -0
- package/src/components/custom/Workout/SetTableHeader.stories.tsx +66 -0
- package/src/components/custom/Workout/SetTableHeader.test.tsx +47 -0
- package/src/components/custom/Workout/SetTableHeader.tsx +88 -0
- package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +47 -0
- package/src/components/custom/Workout/SetsRepsLoad.test.tsx +44 -0
- package/src/components/custom/Workout/SetsRepsLoad.tsx +52 -0
- package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusPill.stories.tsx +59 -0
- package/src/components/custom/Workout/StatusPill.test.tsx +63 -0
- package/src/components/custom/Workout/StatusPill.tsx +88 -0
- package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +1 -1
- package/src/components/custom/Workout/SupersetWrapper.stories.tsx +1 -1
- package/src/components/custom/Workout/TempoBar.stories.tsx +70 -1
- package/src/components/custom/Workout/TempoBar.test.tsx +119 -4
- package/src/components/custom/Workout/TempoBar.tsx +107 -22
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +12 -1
- package/src/components/custom/Workout/TempoDisplay.tsx +23 -33
- package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +1 -1
- package/src/components/custom/Workout/VelocityStrip.modalities.stories.tsx +254 -0
- package/src/components/custom/Workout/VelocityStrip.responsive.stories.tsx +145 -0
- package/src/components/custom/Workout/VelocityStrip.stories.tsx +262 -56
- package/src/components/custom/Workout/VelocityStrip.test.tsx +440 -141
- package/src/components/custom/Workout/VelocityStrip.tsx +776 -141
- package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +73 -0
- package/src/components/custom/Workout/VolumeLandmarkBar.test.tsx +119 -0
- package/src/components/custom/Workout/VolumeLandmarkBar.tsx +154 -0
- package/src/components/custom/Workout/WeekRow.stories.tsx +1 -1
- package/src/components/custom/Workout/WeightBadge.stories.tsx +1 -1
- package/src/components/custom/Workout/WorkoutCard.stories.tsx +2 -6
- package/src/components/custom/Workout/WorkoutCard.test.tsx +13 -46
- package/src/components/custom/Workout/WorkoutPill.stories.tsx +1 -1
- package/src/components/custom/Workout/ZoneTrack.stories.tsx +139 -0
- package/src/components/custom/Workout/ZoneTrack.test.tsx +234 -0
- package/src/components/custom/Workout/ZoneTrack.tsx +373 -0
- package/src/components/custom/Workout/index.ts +55 -2
- package/src/components/custom/Workout/metricText.stories.tsx +69 -0
- package/src/components/custom/Workout/metricText.tsx +34 -0
- package/src/components/custom/Workout/paceTone.test.ts +29 -0
- package/src/components/custom/Workout/paceTone.ts +27 -0
- package/src/components/custom/Workout/setHeadingKit.tsx +177 -0
- package/src/components/custom/index.ts +2 -0
- package/src/components/custom/stepper/Stepper.stories.tsx +1 -1
- package/src/components/icons/icons.stories.tsx +67 -2
- package/src/components/icons/icons.test.tsx +32 -2
- package/src/components/icons/icons.tsx +108 -0
- package/src/components/shell/BrandLockup.stories.tsx +3 -3
- package/src/components/shell/DashboardShell.stories.tsx +65 -0
- package/src/components/shell/DashboardShell.test.tsx +42 -0
- package/src/components/shell/DashboardShell.tsx +74 -0
- package/src/components/shell/DeviceIndicator.stories.tsx +2 -2
- package/src/components/shell/DeviceMenu.stories.tsx +5 -5
- package/src/components/shell/DeviceRow.stories.tsx +3 -3
- package/src/components/shell/NavItem.stories.tsx +52 -0
- package/src/components/shell/NavItem.test.tsx +35 -0
- package/src/components/shell/NavItem.tsx +75 -0
- package/src/components/shell/README.md +30 -0
- package/src/components/shell/SessionRailSpecimen.stories.tsx +753 -0
- package/src/components/shell/SessionStatePill.stories.tsx +3 -3
- package/src/components/shell/SessionStatePill.tsx +1 -1
- package/src/components/shell/SideNav.stories.tsx +81 -0
- package/src/components/shell/SideNav.test.tsx +51 -0
- package/src/components/shell/SideNav.tsx +74 -0
- package/src/components/shell/TopBar.stories.tsx +5 -5
- package/src/components/shell/index.ts +5 -0
- package/src/components/ui/alert/Alert.stories.tsx +86 -3
- package/src/components/ui/alert/Alert.test.tsx +52 -0
- package/src/components/ui/alert/Alert.tsx +54 -20
- package/src/components/ui/autocomplete/Autocomplete.stories.tsx +1 -1
- package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
- package/src/components/ui/badge/Badge.stories.tsx +1 -1
- package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
- package/src/components/ui/button/Button.stories.tsx +1 -1
- package/src/components/ui/card/Card.stories.tsx +1 -1
- package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
- package/src/components/ui/chip/Chip.stories.tsx +1 -1
- package/src/components/ui/collapse/Collapse.stories.tsx +1 -1
- package/src/components/ui/data-row/DataRow.stories.tsx +1 -1
- package/src/components/ui/divider/Divider.stories.tsx +1 -1
- package/src/components/ui/drawer/Drawer.stories.tsx +1 -1
- package/src/components/ui/form-field/FormField.stories.tsx +1 -1
- package/src/components/ui/help-tip/HelpTip.stories.tsx +1 -1
- package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/indicator/Indicator.stories.tsx +2 -2
- package/src/components/ui/indicator/Indicator.test.tsx +1 -0
- package/src/components/ui/indicator/Indicator.tsx +6 -1
- package/src/components/ui/input/Input.stories.tsx +1 -1
- package/src/components/ui/link/Link.stories.tsx +1 -1
- package/src/components/ui/list-item/ListItem.stories.tsx +1 -1
- package/src/components/ui/menu/Menu.stories.tsx +1 -1
- package/src/components/ui/modal/Modal.stories.tsx +1 -1
- package/src/components/ui/pill/Pill.stories.tsx +1 -1
- package/src/components/ui/popover/Popover.stories.tsx +1 -1
- package/src/components/ui/progress/Progress.stories.tsx +1 -1
- package/src/components/ui/progress/Progress.tsx +47 -22
- package/src/components/ui/radio/Radio.stories.tsx +1 -1
- package/src/components/ui/section/Section.stories.tsx +1 -1
- package/src/components/ui/select/Select.stories.tsx +1 -1
- package/src/components/ui/skeleton/Skeleton.stories.tsx +1 -1
- package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
- package/src/components/ui/stack/Stack.stories.tsx +1 -1
- package/src/components/ui/surface/Surface.stories.tsx +1 -1
- package/src/components/ui/switch/Switch.stories.tsx +1 -1
- package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
- package/src/components/ui/tile/Tile.stories.tsx +79 -0
- package/src/components/ui/tile/Tile.test.tsx +48 -0
- package/src/components/ui/tile/Tile.tsx +64 -0
- package/src/components/ui/tile/index.ts +2 -0
- package/src/components/ui/toast/Toast.stories.tsx +1 -1
- package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +1 -1
- package/src/components/ui/tooltip/Tooltip.stories.tsx +1 -1
- package/src/examples/react-hook-form/ReactHookForm.stories.tsx +1 -1
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useTimer.test.ts +150 -0
- package/src/hooks/useTimer.ts +77 -0
- package/src/index.ts +3 -0
- package/src/pages.ts +1 -1
- package/src/stories/PresetShowcase.stories.tsx +1 -1
- package/src/stories/ThemePresets.stories.tsx +1 -1
- package/src/theme/ColorSystem.stories.tsx +1 -1
- package/src/theme/Colors.stories.tsx +5 -8
- package/src/theme/config.ts +4 -0
- package/src/theme/elevation.stories.tsx +1 -1
- package/src/theme/global.css +5 -1
- package/src/theme/shadows.stories.tsx +1 -1
- package/src/theme/tokens/primitives.ts +11 -107
- package/src/theme/tokens/semantic.ts +8 -0
- package/src/theme/workout-tokens.ts +11 -7
- package/tailwind.config.js +5 -0
|
@@ -5,7 +5,7 @@ import { Drawer, DrawerBody, DrawerFooter } from './Drawer'
|
|
|
5
5
|
import { Button, ButtonText } from '../button'
|
|
6
6
|
|
|
7
7
|
const meta: Meta<typeof Drawer> = {
|
|
8
|
-
title: 'Components/Drawer',
|
|
8
|
+
title: 'Components/Organisms/Drawer',
|
|
9
9
|
component: Drawer,
|
|
10
10
|
tags: ['autodocs'],
|
|
11
11
|
argTypes: {
|
|
@@ -3,14 +3,14 @@ import { View } from 'react-native'
|
|
|
3
3
|
import { Indicator } from './Indicator'
|
|
4
4
|
|
|
5
5
|
const meta: Meta<typeof Indicator> = {
|
|
6
|
-
title: 'Components/Indicator',
|
|
6
|
+
title: 'Components/Atoms/Indicator',
|
|
7
7
|
component: Indicator,
|
|
8
8
|
tags: ['autodocs'],
|
|
9
9
|
argTypes: {
|
|
10
10
|
size: { control: 'select', options: ['xs', 'sm', 'md', 'lg'] },
|
|
11
11
|
color: {
|
|
12
12
|
control: 'select',
|
|
13
|
-
options: ['default', 'primary', 'success', 'error', 'warning', 'info'],
|
|
13
|
+
options: ['default', 'primary', 'success', 'live', 'error', 'warning', 'info'],
|
|
14
14
|
},
|
|
15
15
|
glow: { control: 'boolean' },
|
|
16
16
|
ring: { control: 'boolean' },
|
|
@@ -6,6 +6,7 @@ export type IndicatorColor =
|
|
|
6
6
|
| 'default'
|
|
7
7
|
| 'primary'
|
|
8
8
|
| 'success'
|
|
9
|
+
| 'live'
|
|
9
10
|
| 'error'
|
|
10
11
|
| 'warning'
|
|
11
12
|
| 'info'
|
|
@@ -42,6 +43,7 @@ const colorStyles: Record<IndicatorColor, string> = {
|
|
|
42
43
|
default: 'bg-text-tertiary',
|
|
43
44
|
primary: 'bg-brand-primary',
|
|
44
45
|
success: 'bg-status-success',
|
|
46
|
+
live: 'bg-status-live',
|
|
45
47
|
error: 'bg-status-error',
|
|
46
48
|
warning: 'bg-status-warning',
|
|
47
49
|
info: 'bg-status-info',
|
|
@@ -98,7 +100,10 @@ export function Indicator({
|
|
|
98
100
|
colorClass,
|
|
99
101
|
pulseMode === 'opacity' && 'animate-pulse',
|
|
100
102
|
ring && 'border-2 border-background-base',
|
|
101
|
-
glow &&
|
|
103
|
+
glow &&
|
|
104
|
+
!customColor &&
|
|
105
|
+
(color === 'success' || color === 'live') &&
|
|
106
|
+
'shadow-[0_0_6px_rgba(46,213,115,0.6)]',
|
|
102
107
|
glow && !customColor && color === 'error' && 'shadow-[0_0_6px_rgba(239,68,68,0.6)]',
|
|
103
108
|
glow && !customColor && color === 'warning' && 'shadow-[0_0_6px_rgba(245,158,11,0.6)]',
|
|
104
109
|
glow && !customColor && color === 'primary' && 'shadow-[0_0_6px_rgba(255,121,0,0.6)]',
|
|
@@ -4,7 +4,7 @@ import { Menu, MenuTrigger, MenuList, MenuItem, MenuDivider, MenuGroup } from '.
|
|
|
4
4
|
import { Button, ButtonText } from '../button/Button'
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof Menu> = {
|
|
7
|
-
title: 'Components/Menu',
|
|
7
|
+
title: 'Components/Molecules/Menu',
|
|
8
8
|
component: Menu,
|
|
9
9
|
tags: ['autodocs'],
|
|
10
10
|
argTypes: {
|
|
@@ -4,7 +4,7 @@ import { Popover, PopoverTrigger, PopoverContent, PopoverCloseButton } from './P
|
|
|
4
4
|
import { Button, ButtonText } from '../button/Button'
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof Popover> = {
|
|
7
|
-
title: 'Components/Popover',
|
|
7
|
+
title: 'Components/Molecules/Popover',
|
|
8
8
|
component: Popover,
|
|
9
9
|
tags: ['autodocs'],
|
|
10
10
|
argTypes: {
|
|
@@ -3,7 +3,7 @@ import { View, Text } from 'react-native'
|
|
|
3
3
|
import { Progress, CircularProgress, ProgressSteps } from './Progress'
|
|
4
4
|
|
|
5
5
|
const meta: Meta<typeof Progress> = {
|
|
6
|
-
title: 'Components/Progress',
|
|
6
|
+
title: 'Components/Molecules/Progress',
|
|
7
7
|
component: Progress,
|
|
8
8
|
tags: ['autodocs'],
|
|
9
9
|
argTypes: {
|
|
@@ -7,7 +7,7 @@ export type ProgressColor = 'primary' | 'secondary' | 'success' | 'error' | 'war
|
|
|
7
7
|
export type ProgressVariant = 'linear' | 'circular'
|
|
8
8
|
|
|
9
9
|
/** Maps the color prop to a CSS variable reference for inline styles */
|
|
10
|
-
const colorVarMap: Record<ProgressColor, string> = {
|
|
10
|
+
export const colorVarMap: Record<ProgressColor, string> = {
|
|
11
11
|
primary: 'var(--color-brand-primary)',
|
|
12
12
|
secondary: 'var(--color-brand-secondary)',
|
|
13
13
|
success: 'var(--color-status-success)',
|
|
@@ -101,13 +101,9 @@ export function Progress({
|
|
|
101
101
|
{/* Label and Value Row */}
|
|
102
102
|
{(label || showValue) && (
|
|
103
103
|
<View className="flex-row justify-between items-center mb-1">
|
|
104
|
-
{label &&
|
|
105
|
-
<Text className="text-sm text-text-secondary">{label}</Text>
|
|
106
|
-
)}
|
|
104
|
+
{label && <Text className="text-sm text-text-secondary">{label}</Text>}
|
|
107
105
|
{showValue && !isIndeterminate && (
|
|
108
|
-
<Text className="text-sm font-medium text-text-primary">
|
|
109
|
-
{formatValue(value, max)}
|
|
110
|
-
</Text>
|
|
106
|
+
<Text className="text-sm font-medium text-text-primary">{formatValue(value, max)}</Text>
|
|
111
107
|
)}
|
|
112
108
|
</View>
|
|
113
109
|
)}
|
|
@@ -162,6 +158,19 @@ export interface CircularProgressProps extends ViewProps {
|
|
|
162
158
|
showValue?: boolean
|
|
163
159
|
/** Custom value format function */
|
|
164
160
|
formatValue?: (value: number, max: number) => string
|
|
161
|
+
/**
|
|
162
|
+
* Custom center content (a numeral, a timer readout, an icon). When provided it
|
|
163
|
+
* replaces the {@link showValue} text — the ring becomes a generic container for
|
|
164
|
+
* any centered element. See {@link CircularTimer} for the batteries-included timer.
|
|
165
|
+
*/
|
|
166
|
+
children?: React.ReactNode
|
|
167
|
+
/**
|
|
168
|
+
* Fill the parent container (responsive) instead of drawing a fixed `size` box.
|
|
169
|
+
* The SVG uses a `0 0 size size` viewBox scaled to the container, so `size` still
|
|
170
|
+
* sets the geometry proportions (radius, stroke) while the ring grows/shrinks with
|
|
171
|
+
* its parent — e.g. a wall column. Default false (fixed `size` px).
|
|
172
|
+
*/
|
|
173
|
+
fill?: boolean
|
|
165
174
|
/** Additional className */
|
|
166
175
|
className?: string
|
|
167
176
|
}
|
|
@@ -181,6 +190,8 @@ export function CircularProgress({
|
|
|
181
190
|
color = 'primary',
|
|
182
191
|
showValue = false,
|
|
183
192
|
formatValue = (v, m) => `${Math.round((v / m) * 100)}%`,
|
|
193
|
+
children,
|
|
194
|
+
fill = false,
|
|
184
195
|
className,
|
|
185
196
|
...props
|
|
186
197
|
}: CircularProgressProps) {
|
|
@@ -189,11 +200,14 @@ export function CircularProgress({
|
|
|
189
200
|
const circumference = 2 * Math.PI * radius
|
|
190
201
|
const strokeDashoffset = circumference - (percentage / 100) * circumference
|
|
191
202
|
const center = size / 2
|
|
203
|
+
// Fixed: a `size × size` px box. Fill: fill the parent, staying square, and let
|
|
204
|
+
// the `0 0 size size` viewBox scale the geometry to fit (a responsive ring).
|
|
205
|
+
const boxStyle = fill ? { width: '100%' as const, aspectRatio: 1 } : { width: size, height: size }
|
|
192
206
|
|
|
193
207
|
return (
|
|
194
208
|
<View
|
|
195
209
|
className={cn('items-center justify-center', className)}
|
|
196
|
-
style={
|
|
210
|
+
style={boxStyle}
|
|
197
211
|
accessibilityRole="progressbar"
|
|
198
212
|
accessibilityValue={{
|
|
199
213
|
min: 0,
|
|
@@ -202,14 +216,11 @@ export function CircularProgress({
|
|
|
202
216
|
}}
|
|
203
217
|
{...props}
|
|
204
218
|
>
|
|
205
|
-
{/* SVG implementation for web */}
|
|
206
|
-
<View
|
|
207
|
-
className={cn(isIndeterminate && 'animate-spin')}
|
|
208
|
-
style={{ width: size, height: size }}
|
|
209
|
-
>
|
|
219
|
+
{/* SVG implementation for web — width/height 100% so it scales with `boxStyle`. */}
|
|
220
|
+
<View className={cn(isIndeterminate && 'animate-spin')} style={boxStyle}>
|
|
210
221
|
<svg
|
|
211
|
-
width=
|
|
212
|
-
height=
|
|
222
|
+
width="100%"
|
|
223
|
+
height="100%"
|
|
213
224
|
viewBox={`0 0 ${size} ${size}`}
|
|
214
225
|
style={{ position: 'absolute' }}
|
|
215
226
|
>
|
|
@@ -239,14 +250,28 @@ export function CircularProgress({
|
|
|
239
250
|
</svg>
|
|
240
251
|
</View>
|
|
241
252
|
|
|
242
|
-
{/* Center
|
|
243
|
-
{
|
|
244
|
-
<
|
|
245
|
-
|
|
246
|
-
|
|
253
|
+
{/* Center: custom children take precedence over the showValue readout. */}
|
|
254
|
+
{children != null ? (
|
|
255
|
+
<View
|
|
256
|
+
style={{
|
|
257
|
+
position: 'absolute',
|
|
258
|
+
alignItems: 'center',
|
|
259
|
+
justifyContent: 'center',
|
|
260
|
+
pointerEvents: 'none',
|
|
261
|
+
}}
|
|
247
262
|
>
|
|
248
|
-
{
|
|
249
|
-
</
|
|
263
|
+
{children}
|
|
264
|
+
</View>
|
|
265
|
+
) : (
|
|
266
|
+
showValue &&
|
|
267
|
+
!isIndeterminate && (
|
|
268
|
+
<Text
|
|
269
|
+
className="text-xs font-semibold text-text-primary absolute"
|
|
270
|
+
style={{ fontSize: Math.max(size * 0.22, 10) }}
|
|
271
|
+
>
|
|
272
|
+
{formatValue(value, max)}
|
|
273
|
+
</Text>
|
|
274
|
+
)
|
|
250
275
|
)}
|
|
251
276
|
</View>
|
|
252
277
|
)
|
|
@@ -4,7 +4,7 @@ import { Surface } from './Surface'
|
|
|
4
4
|
import type { ElevationLevel } from '../../../theme/elevation'
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof Surface> = {
|
|
7
|
-
title: 'Components/Surface',
|
|
7
|
+
title: 'Components/Atoms/Surface',
|
|
8
8
|
component: Surface,
|
|
9
9
|
tags: ['autodocs'],
|
|
10
10
|
argTypes: {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { View } from 'react-native'
|
|
3
|
+
import { Tile } from './Tile'
|
|
4
|
+
import { getSemanticColors } from '../../../theme'
|
|
5
|
+
|
|
6
|
+
const ACCENT = getSemanticColors('dark')['status-warning']
|
|
7
|
+
const SUCCESS = getSemanticColors('dark')['status-success']
|
|
8
|
+
|
|
9
|
+
const meta: Meta<typeof Tile> = {
|
|
10
|
+
title: 'Components/Atoms/Tile',
|
|
11
|
+
component: Tile,
|
|
12
|
+
tags: ['autodocs'],
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component: '**Atom.** A compact card preset; grouped by SessionMetrics / ScheduleTiles.',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
argTypes: {
|
|
21
|
+
label: { control: 'text', description: 'Uppercase micro-label' },
|
|
22
|
+
value: { control: 'text', description: 'Primary mono value' },
|
|
23
|
+
valueColor: { control: 'color', description: 'Tints the value' },
|
|
24
|
+
align: {
|
|
25
|
+
control: 'radio',
|
|
26
|
+
options: ['center', 'start'],
|
|
27
|
+
description: 'Content alignment',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default meta
|
|
33
|
+
type Story = StoryObj<typeof Tile>
|
|
34
|
+
|
|
35
|
+
export const Default: Story = {
|
|
36
|
+
args: {
|
|
37
|
+
label: 'Volume',
|
|
38
|
+
value: '76%',
|
|
39
|
+
align: 'center',
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const Row: Story = {
|
|
44
|
+
render: () => (
|
|
45
|
+
<View style={{ flexDirection: 'row', gap: 4, width: 246 }}>
|
|
46
|
+
<Tile label="Volume" value="76%" />
|
|
47
|
+
<Tile label="Load" value="7.3k" />
|
|
48
|
+
<Tile label="Fatigue" value="MOD" valueColor={ACCENT} />
|
|
49
|
+
</View>
|
|
50
|
+
),
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const ScheduleTiles: Story = {
|
|
54
|
+
render: () => (
|
|
55
|
+
<View style={{ flexDirection: 'row', gap: 4, width: 246 }}>
|
|
56
|
+
<Tile label="Date" value="Jul 10" />
|
|
57
|
+
<Tile label="Time" value="6:30 PM" />
|
|
58
|
+
<Tile label="Until" value="5h" valueColor={ACCENT} />
|
|
59
|
+
</View>
|
|
60
|
+
),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const ValueColors: Story = {
|
|
64
|
+
render: () => (
|
|
65
|
+
<View style={{ flexDirection: 'row', gap: 4, width: 246 }}>
|
|
66
|
+
<Tile label="Default" value="12" />
|
|
67
|
+
<Tile label="Success" value="OK" valueColor={SUCCESS} />
|
|
68
|
+
<Tile label="Warning" value="MOD" valueColor={ACCENT} />
|
|
69
|
+
</View>
|
|
70
|
+
),
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const StartAligned: Story = {
|
|
74
|
+
args: {
|
|
75
|
+
label: 'Program',
|
|
76
|
+
value: 'Pull A',
|
|
77
|
+
align: 'start',
|
|
78
|
+
},
|
|
79
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import { axe } from 'jest-axe'
|
|
4
|
+
import { Tile } from './Tile'
|
|
5
|
+
|
|
6
|
+
describe('Tile', () => {
|
|
7
|
+
it('renders label and value', () => {
|
|
8
|
+
render(<Tile label="Volume" value="76%" />)
|
|
9
|
+
expect(screen.getByText('Volume')).toBeInTheDocument()
|
|
10
|
+
expect(screen.getByText('76%')).toBeInTheDocument()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('applies valueColor to the value text', () => {
|
|
14
|
+
render(<Tile label="Fatigue" value="MOD" valueColor="#F5A623" />)
|
|
15
|
+
const value = screen.getByText('MOD')
|
|
16
|
+
expect(value).toHaveStyle({ color: '#F5A623' })
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('does not set an inline color when valueColor is omitted', () => {
|
|
20
|
+
render(<Tile label="Volume" value="76%" />)
|
|
21
|
+
const value = screen.getByText('76%')
|
|
22
|
+
expect(value.style.color).toBe('')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('renders with start alignment', () => {
|
|
26
|
+
render(<Tile label="Program" value="Pull A" align="start" />)
|
|
27
|
+
expect(screen.getByText('Program')).toBeInTheDocument()
|
|
28
|
+
expect(screen.getByText('Pull A')).toBeInTheDocument()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('applies custom className', () => {
|
|
32
|
+
const { container } = render(<Tile label="Load" value="7.3k" className="custom-class" />)
|
|
33
|
+
expect(container.firstChild).toBeInTheDocument()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('passes additional props through', () => {
|
|
37
|
+
render(<Tile label="Load" value="7.3k" testID="tile-test" />)
|
|
38
|
+
expect(screen.getByText('7.3k')).toBeInTheDocument()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('accessibility', () => {
|
|
42
|
+
it('has no accessibility violations', async () => {
|
|
43
|
+
const { container } = render(<Tile label="Volume" value="76%" />)
|
|
44
|
+
const results = await axe(container)
|
|
45
|
+
expect(results).toHaveNoViolations()
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
})
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { View, Text, type ViewProps } from 'react-native'
|
|
2
|
+
import { cn } from '../../../utils/cn'
|
|
3
|
+
|
|
4
|
+
export interface TileProps extends ViewProps {
|
|
5
|
+
/** Uppercase micro-label shown above the value */
|
|
6
|
+
label: string
|
|
7
|
+
/** Primary value, rendered in a bold mono face */
|
|
8
|
+
value: string
|
|
9
|
+
/** Tints the value (status/accent hex or CSS color); defaults to primary text */
|
|
10
|
+
valueColor?: string
|
|
11
|
+
/** Content alignment within the tile (default: 'center') */
|
|
12
|
+
align?: 'center' | 'start'
|
|
13
|
+
/** Additional className */
|
|
14
|
+
className?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Tile — a compact label-over-value stat card.
|
|
19
|
+
*
|
|
20
|
+
* A rounded raised box with an uppercase micro-label stacked over a bold mono
|
|
21
|
+
* value. Fills its flex slot so a row of Tiles reads as an even HStack.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* <Tile label="Volume" value="76%" />
|
|
25
|
+
* <Tile label="Fatigue" value="MOD" valueColor="#F5A623" />
|
|
26
|
+
*/
|
|
27
|
+
export function Tile({
|
|
28
|
+
label,
|
|
29
|
+
value,
|
|
30
|
+
valueColor,
|
|
31
|
+
align = 'center',
|
|
32
|
+
className,
|
|
33
|
+
...props
|
|
34
|
+
}: TileProps) {
|
|
35
|
+
const isCenter = align === 'center'
|
|
36
|
+
return (
|
|
37
|
+
<View
|
|
38
|
+
className={cn(
|
|
39
|
+
'flex-1 rounded-md bg-surface-raised px-1.5 py-2',
|
|
40
|
+
isCenter ? 'items-center' : 'items-start',
|
|
41
|
+
className
|
|
42
|
+
)}
|
|
43
|
+
{...props}
|
|
44
|
+
>
|
|
45
|
+
<Text
|
|
46
|
+
className={cn(
|
|
47
|
+
'text-[10px] font-bold uppercase tracking-wider text-text-tertiary',
|
|
48
|
+
isCenter ? 'text-center' : 'text-left'
|
|
49
|
+
)}
|
|
50
|
+
>
|
|
51
|
+
{label}
|
|
52
|
+
</Text>
|
|
53
|
+
<Text
|
|
54
|
+
className={cn(
|
|
55
|
+
'mt-0.5 font-mono text-sm font-bold text-text-primary',
|
|
56
|
+
isCenter ? 'text-center' : 'text-left'
|
|
57
|
+
)}
|
|
58
|
+
style={valueColor ? { color: valueColor } : undefined}
|
|
59
|
+
>
|
|
60
|
+
{value}
|
|
61
|
+
</Text>
|
|
62
|
+
</View>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
@@ -4,7 +4,7 @@ import { Toast, ToastProvider, useToast } from './Toast'
|
|
|
4
4
|
import { Button, ButtonText } from '../button'
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof Toast> = {
|
|
7
|
-
title: 'Components/Toast',
|
|
7
|
+
title: 'Components/Molecules/Toast',
|
|
8
8
|
component: Toast,
|
|
9
9
|
tags: ['autodocs'],
|
|
10
10
|
argTypes: {
|
|
@@ -4,7 +4,7 @@ import { View, Text } from 'react-native'
|
|
|
4
4
|
import { ToolbarButton, ToolbarButtonGroup } from './ToolbarButton'
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof ToolbarButton> = {
|
|
7
|
-
title: 'Components/ToolbarButton',
|
|
7
|
+
title: 'Components/Molecules/ToolbarButton',
|
|
8
8
|
component: ToolbarButton,
|
|
9
9
|
tags: ['autodocs'],
|
|
10
10
|
argTypes: {
|