@titan-design/react-ui 0.10.0 → 0.11.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.
Files changed (84) hide show
  1. package/dist/index.d.mts +399 -4
  2. package/dist/index.d.ts +399 -4
  3. package/dist/index.js +2295 -895
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +2279 -905
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/{pages-DyEx-lBf.d.ts → pages-B1hqnGIC.d.ts} +149 -15
  8. package/dist/{pages-D7hOD4Vj.d.mts → pages-CvsFqNtx.d.mts} +149 -15
  9. package/dist/pages.d.mts +1 -1
  10. package/dist/pages.d.ts +1 -1
  11. package/dist/pages.js +1974 -1740
  12. package/dist/pages.js.map +1 -1
  13. package/dist/pages.mjs +1975 -1741
  14. package/dist/pages.mjs.map +1 -1
  15. package/package.json +8 -3
  16. package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +258 -0
  17. package/src/components/custom/Fatigue/DualGhostSpark.test.tsx +138 -0
  18. package/src/components/custom/Fatigue/DualGhostSpark.tsx +208 -0
  19. package/src/components/custom/Fatigue/FatigueLights.stories.tsx +74 -0
  20. package/src/components/custom/Fatigue/FatigueLights.test.tsx +33 -0
  21. package/src/components/custom/Fatigue/FatigueLights.tsx +83 -0
  22. package/src/components/custom/Fatigue/GhostBand.test.tsx +235 -0
  23. package/src/components/custom/Fatigue/GhostBand.tsx +246 -0
  24. package/src/components/custom/Fatigue/GhostBloom.tsx +132 -0
  25. package/src/components/custom/Fatigue/GhostSpark.stories.tsx +175 -0
  26. package/src/components/custom/Fatigue/GhostSpark.test.tsx +45 -0
  27. package/src/components/custom/Fatigue/GhostSpark.tsx +126 -0
  28. package/src/components/custom/Fatigue/LiveFatigueCard.stories.tsx +126 -0
  29. package/src/components/custom/Fatigue/LiveFatigueCard.test.tsx +28 -0
  30. package/src/components/custom/Fatigue/LiveFatigueCard.tsx +86 -0
  31. package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +95 -0
  32. package/src/components/custom/Fatigue/LiveFatiguePanel.tsx +151 -0
  33. package/src/components/custom/Fatigue/README.md +93 -0
  34. package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +94 -0
  35. package/src/components/custom/Fatigue/RomProgressionChart.test.tsx +31 -0
  36. package/src/components/custom/Fatigue/RomProgressionChart.tsx +132 -0
  37. package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +226 -0
  38. package/src/components/custom/Fatigue/VelocityHero.stories.tsx +70 -0
  39. package/src/components/custom/Fatigue/VelocityHero.test.tsx +26 -0
  40. package/src/components/custom/Fatigue/VelocityHero.tsx +46 -0
  41. package/src/components/custom/Fatigue/VerdictHero.stories.tsx +59 -0
  42. package/src/components/custom/Fatigue/VerdictHero.test.tsx +49 -0
  43. package/src/components/custom/Fatigue/VerdictHero.tsx +79 -0
  44. package/src/components/custom/Fatigue/fatigue-mock.test.ts +59 -0
  45. package/src/components/custom/Fatigue/fatigue-mock.ts +268 -0
  46. package/src/components/custom/Fatigue/fatigue-model.ts +129 -0
  47. package/src/components/custom/Fatigue/fatigue-tokens.test.ts +70 -0
  48. package/src/components/custom/Fatigue/fatigue-tokens.ts +180 -0
  49. package/src/components/custom/Fatigue/index.ts +41 -0
  50. package/src/components/custom/Fatigue/tempo-pacing.test.ts +176 -0
  51. package/src/components/custom/Fatigue/tempo-pacing.ts +112 -0
  52. package/src/components/custom/Workout/DualVelocityStrip.test.tsx +685 -0
  53. package/src/components/custom/Workout/ExerciseCard.test.tsx +4 -4
  54. package/src/components/custom/Workout/ExerciseCard.tsx +3 -1
  55. package/src/components/custom/Workout/ExerciseDetailPage.tsx +7 -1
  56. package/src/components/custom/Workout/README.md +62 -16
  57. package/src/components/custom/Workout/SegmentedBar.stories.tsx +3 -3
  58. package/src/components/custom/Workout/SessionRail.test.tsx +43 -0
  59. package/src/components/custom/Workout/SessionRail.tsx +50 -13
  60. package/src/components/custom/Workout/SetRow.test.tsx +6 -6
  61. package/src/components/custom/Workout/SetRow.tsx +9 -2
  62. package/src/components/custom/Workout/VelocityStrip.compact.stories.tsx +191 -0
  63. package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +186 -0
  64. package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +296 -0
  65. package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +259 -0
  66. package/src/components/custom/Workout/VelocityStrip.stories.tsx +217 -250
  67. package/src/components/custom/Workout/VelocityStrip.test.tsx +196 -79
  68. package/src/components/custom/Workout/VelocityStrip.tsx +953 -609
  69. package/src/components/custom/Workout/index.ts +3 -0
  70. package/src/components/custom/Workout/velocity-story-kit.tsx +438 -0
  71. package/src/components/custom/charts/SetBarChart.test.tsx +275 -0
  72. package/src/components/custom/charts/SetBarChart.tsx +651 -0
  73. package/src/components/custom/charts/live-rep-growth.ts +91 -0
  74. package/src/components/custom/index.ts +1 -0
  75. package/src/test/raw-color-patterns.test.ts +71 -0
  76. package/src/theme/ColorPalettes.stories.tsx +871 -0
  77. package/src/theme/ColorPrimitives.stories.tsx +300 -0
  78. package/src/theme/bar-paper.ts +59 -0
  79. package/src/theme/color-stories.coverage.test.ts +130 -0
  80. package/src/theme/color-story-kit.tsx +170 -0
  81. package/src/components/custom/Workout/VelocityStrip.modalities.stories.tsx +0 -254
  82. package/src/components/custom/Workout/VelocityStrip.responsive.stories.tsx +0 -145
  83. package/src/theme/ColorSystem.stories.tsx +0 -508
  84. package/src/theme/Colors.stories.tsx +0 -323
@@ -0,0 +1,259 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import { View } from 'react-native'
3
+ import { VelocityStrip, DualVelocityStrip } from './VelocityStrip'
4
+ import {
5
+ Sheet,
6
+ Note,
7
+ ViewLabel,
8
+ ScenarioPair,
9
+ SetTypeBoard,
10
+ RepTypeBoard,
11
+ REP_SET,
12
+ REP_SET_LAGGING,
13
+ FATIGUE_SET,
14
+ FATIGUE_SET_LAGGING,
15
+ IN_PROGRESS_SET,
16
+ IN_PROGRESS_LAGGING,
17
+ wallDecorator,
18
+ } from './velocity-story-kit'
19
+
20
+ /**
21
+ * `hero` — the across-the-room wall treatment. Tall bars, per-bar value labels,
22
+ * a dashed running-best reference line, and dashed placeholders for the reps
23
+ * still to come via `targetReps`.
24
+ *
25
+ * No horizontal axis: the single baseline and the dual centre axis were both
26
+ * removed. The dual hero is two composed heroes — an up-oriented strip over a
27
+ * mirrored down-oriented one — separated by the same 2px gap the expanded rail
28
+ * uses, so the pair reads as one lockup without needing a rule between them.
29
+ *
30
+ * A live hero should run `scale="fixed"` so bar heights stay comparable across
31
+ * sets and do not reflow as each rep lands.
32
+ */
33
+ const meta: Meta<typeof VelocityStrip> = {
34
+ title: 'Workout/DataViz/VelocityStrip/Hero',
35
+ component: VelocityStrip,
36
+ tags: ['autodocs'],
37
+ }
38
+ export default meta
39
+ type Story = StoryObj<typeof VelocityStrip>
40
+
41
+ export const Default: Story = {
42
+ name: 'Default',
43
+ render: () => (
44
+ <Sheet width={700}>
45
+ <Note>The representative set on the wall — same data, same geometry, wall scale.</Note>
46
+ <ScenarioPair
47
+ view="hero"
48
+ title="Default"
49
+ single={REP_SET}
50
+ left={REP_SET}
51
+ right={REP_SET_LAGGING}
52
+ />
53
+ </Sheet>
54
+ ),
55
+ }
56
+
57
+ export const SetTypes: Story = {
58
+ name: 'Set Types',
59
+ render: () => (
60
+ <Sheet width={700}>
61
+ <Note>The set-type vocabulary at wall scale, each type paired single above dual.</Note>
62
+ <SetTypeBoard view="hero" />
63
+ </Sheet>
64
+ ),
65
+ }
66
+
67
+ export const InProgress: Story = {
68
+ name: 'In Progress',
69
+ render: () => (
70
+ <Sheet width={700}>
71
+ <Note>
72
+ 4 of 8 done, newest bar live, the remaining four drawn as dashed placeholders. Fixed scale,
73
+ so nothing reflows as reps land.
74
+ </Note>
75
+ <ScenarioPair
76
+ view="hero"
77
+ title="Mid set"
78
+ single={IN_PROGRESS_SET}
79
+ left={IN_PROGRESS_SET}
80
+ right={IN_PROGRESS_LAGGING}
81
+ scale="fixed"
82
+ targetReps={8}
83
+ liveRepIndex={3}
84
+ />
85
+ </Sheet>
86
+ ),
87
+ }
88
+
89
+ export const FatigueDecline: Story = {
90
+ name: 'Fatigue Decline',
91
+ render: () => (
92
+ <Sheet width={700}>
93
+ <Note>
94
+ A hard decline with loss colouring and the VL bands — the reading the wall exists to make
95
+ obvious from across the room.
96
+ </Note>
97
+ <ScenarioPair
98
+ view="hero"
99
+ title="Fatigue decline"
100
+ single={FATIGUE_SET}
101
+ left={FATIGUE_SET}
102
+ right={FATIGUE_SET_LAGGING}
103
+ scale="fixed"
104
+ barColor="loss"
105
+ />
106
+ </Sheet>
107
+ ),
108
+ }
109
+
110
+ export const EmptyColdBoot: Story = {
111
+ name: 'Empty / Cold Boot',
112
+ render: () => (
113
+ <Sheet width={700}>
114
+ <Note>
115
+ Cold boot: the set is planned but no rep has landed. Placeholders carry the shape so the
116
+ wall is never blank mid-session.
117
+ </Note>
118
+ <ScenarioPair
119
+ view="hero"
120
+ title="Zero reps · 8 planned"
121
+ single={[]}
122
+ left={[]}
123
+ right={[]}
124
+ scale="fixed"
125
+ targetReps={8}
126
+ />
127
+ </Sheet>
128
+ ),
129
+ }
130
+
131
+ export const DualLaggingSide: Story = {
132
+ name: 'Dual · Lagging Side',
133
+ render: () => (
134
+ <Sheet width={700}>
135
+ <Note>
136
+ Index-locked empties at wall scale — the lagging slot&apos;s gaps sit directly under the
137
+ leading slot&apos;s reps, so the imbalance is the thing you see.
138
+ </Note>
139
+ <ScenarioPair
140
+ view="hero"
141
+ title="Lagging right"
142
+ single={REP_SET}
143
+ left={REP_SET}
144
+ right={REP_SET_LAGGING.slice(0, 2)}
145
+ scale="fixed"
146
+ />
147
+ </Sheet>
148
+ ),
149
+ }
150
+
151
+ export const Responsive: Story = {
152
+ name: 'Responsive',
153
+ render: () => (
154
+ <Sheet width={760}>
155
+ <Note>
156
+ HEIGHT first. The side labels are sized to the WING, not the chart, so the collapse
157
+ threshold is per-wing: below 70px of wing extent a slot name degrades to its initial. A dual
158
+ splits its height into two wings, so the ladder below crosses that boundary between 160 and
159
+ 120 — at 120 the names are &quot;L&quot; / &quot;R&quot;. Dashed VL lines and washes always
160
+ survive; only their labels go.
161
+ </Note>
162
+ {[220, 160, 140, 120, 90].map((h) => (
163
+ <View key={h} style={{ gap: 8 }}>
164
+ <ViewLabel text={`${h}px · wings ${Math.round((h - 2) / 2)}px each`} />
165
+ <DualVelocityStrip
166
+ left={{ velocities: REP_SET, label: 'Left' }}
167
+ right={{ velocities: REP_SET_LAGGING, label: 'Right' }}
168
+ variant="hero"
169
+ height={h}
170
+ scale="fixed"
171
+ />
172
+ </View>
173
+ ))}
174
+
175
+ <Note>
176
+ Then WIDTH. Bars and gaps come from the shared layout maths, so they thin together rather
177
+ than the gaps collapsing first; the per-bar value labels drop out once a column can no
178
+ longer seat one.
179
+ </Note>
180
+ {[700, 460, 300, 190].map((w) => (
181
+ <View key={w} style={{ gap: 8, width: w }}>
182
+ <ViewLabel text={`${w}px`} />
183
+ <VelocityStrip
184
+ velocities={REP_SET}
185
+ variant="hero"
186
+ label="Set"
187
+ height={180}
188
+ scale="fixed"
189
+ />
190
+ <DualVelocityStrip
191
+ left={{ velocities: REP_SET, label: 'Left' }}
192
+ right={{ velocities: REP_SET_LAGGING, label: 'Right' }}
193
+ variant="hero"
194
+ height={200}
195
+ scale="fixed"
196
+ />
197
+ </View>
198
+ ))}
199
+ </Sheet>
200
+ ),
201
+ }
202
+
203
+ export const RepTypes: Story = {
204
+ name: 'Rep Types',
205
+ render: () => (
206
+ <Sheet width={700}>
207
+ <Note>
208
+ Every state a rep column can be in at wall scale — where there is room for all of it to be
209
+ unambiguous, and therefore the reference the smaller views are judged against.
210
+ </Note>
211
+ <RepTypeBoard view="hero" />
212
+ </Sheet>
213
+ ),
214
+ }
215
+
216
+ export const EdgeCases: Story = {
217
+ name: 'Edge Cases',
218
+ decorators: [wallDecorator],
219
+ render: () => (
220
+ <View style={{ gap: 26 }}>
221
+ <View style={{ gap: 8 }}>
222
+ <ViewLabel text="near complete · 7 of 8" />
223
+ <VelocityStrip
224
+ velocities={[0.82, 0.79, 0.81, 0.76, 0.74, 0.71, 0.68]}
225
+ variant="hero"
226
+ label="Set"
227
+ targetReps={8}
228
+ scale="fixed"
229
+ />
230
+ </View>
231
+
232
+ <View style={{ gap: 8 }}>
233
+ <ViewLabel text="ends on the best rep · reference line sits on the last bar" />
234
+ <VelocityStrip
235
+ velocities={[0.7, 0.74, 0.78, 0.86]}
236
+ variant="hero"
237
+ label="Set"
238
+ scale="fixed"
239
+ />
240
+ </View>
241
+
242
+ <View style={{ gap: 8 }}>
243
+ <ViewLabel text="exceeds target · more reps performed than planned" />
244
+ <VelocityStrip
245
+ velocities={[0.9, 0.88, 0.85, 0.83, 0.8, 0.78, 0.75]}
246
+ variant="hero"
247
+ label="Set"
248
+ targetReps={5}
249
+ scale="fixed"
250
+ />
251
+ </View>
252
+
253
+ <View style={{ gap: 8 }}>
254
+ <ViewLabel text="single rep · no decline to draw" />
255
+ <VelocityStrip velocities={[0.88]} variant="hero" label="Set" scale="fixed" />
256
+ </View>
257
+ </View>
258
+ ),
259
+ }