@titan-design/react-ui 0.7.0 → 0.9.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/index.d.mts +112 -55
- package/dist/index.d.ts +112 -55
- package/dist/index.js +795 -501
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +795 -498
- package/dist/index.mjs.map +1 -1
- package/dist/{pages-8u_4WbL-.d.mts → pages-D7hOD4Vj.d.mts} +17 -8
- package/dist/{pages-DaWiBOGa.d.ts → pages-DyEx-lBf.d.ts} +17 -8
- package/dist/pages.d.mts +1 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +691 -250
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +692 -251
- package/dist/pages.mjs.map +1 -1
- package/package.json +1 -1
- 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/Workout/ExerciseIndicator.tsx +1 -1
- package/src/components/custom/Workout/FatigueMeter.stories.tsx +2 -2
- package/src/components/custom/Workout/FatigueMeter.test.tsx +12 -0
- package/src/components/custom/Workout/FatigueMeter.tsx +7 -3
- package/src/components/custom/Workout/README.md +70 -3
- package/src/components/custom/Workout/RestTimer.stories.tsx +132 -2
- package/src/components/custom/Workout/RestTimer.test.tsx +73 -0
- package/src/components/custom/Workout/RestTimer.tsx +141 -50
- package/src/components/custom/Workout/SetsRepsLoad.test.tsx +6 -0
- package/src/components/custom/Workout/SetsRepsLoad.tsx +15 -6
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +240 -65
- package/src/components/custom/Workout/TempoDisplay.test.tsx +61 -16
- package/src/components/custom/Workout/TempoDisplay.tsx +173 -60
- package/src/components/custom/Workout/VelocityStrip.stories.tsx +152 -9
- package/src/components/custom/Workout/VelocityStrip.test.tsx +67 -3
- package/src/components/custom/Workout/VelocityStrip.tsx +323 -42
- package/src/components/custom/Workout/ZoneTrack.stories.tsx +2 -3
- package/src/components/custom/Workout/ZoneTrack.test.tsx +34 -0
- package/src/components/custom/Workout/ZoneTrack.tsx +91 -19
- package/src/components/custom/Workout/index.ts +1 -9
- package/src/components/custom/index.ts +1 -0
- package/src/components/ui/alert/Alert.stories.tsx +85 -2
- package/src/components/ui/alert/Alert.test.tsx +52 -0
- package/src/components/ui/alert/Alert.tsx +54 -20
- package/src/components/ui/progress/Progress.tsx +47 -22
- package/src/lab/north-star/LivePage.tsx +101 -0
- package/src/lab/north-star/LiveView.tsx +409 -0
- package/src/lab/north-star/LiveWallDashboard.stories.tsx +129 -0
- package/src/lab/north-star/RestView.tsx +140 -0
- package/src/lab/north-star/fixtures.ts +224 -0
- package/src/components/custom/Workout/TempoBar.stories.tsx +0 -95
- package/src/components/custom/Workout/TempoBar.test.tsx +0 -103
- package/src/components/custom/Workout/TempoBar.tsx +0 -215
package/dist/index.js
CHANGED
|
@@ -158,6 +158,7 @@ var statusColors = {
|
|
|
158
158
|
subtle: "bg-status-success-subtle",
|
|
159
159
|
outline: "border-2 border-status-success bg-transparent",
|
|
160
160
|
solid: "bg-status-success",
|
|
161
|
+
border: "border-status-success",
|
|
161
162
|
icon: "text-status-success",
|
|
162
163
|
text: "text-status-success"
|
|
163
164
|
},
|
|
@@ -165,6 +166,7 @@ var statusColors = {
|
|
|
165
166
|
subtle: "bg-status-info-subtle",
|
|
166
167
|
outline: "border-2 border-status-info bg-transparent",
|
|
167
168
|
solid: "bg-status-info",
|
|
169
|
+
border: "border-status-info",
|
|
168
170
|
icon: "text-status-info",
|
|
169
171
|
text: "text-status-info"
|
|
170
172
|
},
|
|
@@ -172,6 +174,7 @@ var statusColors = {
|
|
|
172
174
|
subtle: "bg-status-warning-subtle",
|
|
173
175
|
outline: "border-2 border-status-warning bg-transparent",
|
|
174
176
|
solid: "bg-status-warning",
|
|
177
|
+
border: "border-status-warning",
|
|
175
178
|
icon: "text-status-warning",
|
|
176
179
|
text: "text-status-warning"
|
|
177
180
|
},
|
|
@@ -179,6 +182,7 @@ var statusColors = {
|
|
|
179
182
|
subtle: "bg-status-error-subtle",
|
|
180
183
|
outline: "border-2 border-status-error bg-transparent",
|
|
181
184
|
solid: "bg-status-error",
|
|
185
|
+
border: "border-status-error",
|
|
182
186
|
icon: "text-status-error",
|
|
183
187
|
text: "text-status-error"
|
|
184
188
|
}
|
|
@@ -192,6 +196,8 @@ var defaultIcons = {
|
|
|
192
196
|
function Alert({
|
|
193
197
|
status = "info",
|
|
194
198
|
variant = "subtle",
|
|
199
|
+
size = "default",
|
|
200
|
+
message,
|
|
195
201
|
icon,
|
|
196
202
|
showIcon = true,
|
|
197
203
|
onClose,
|
|
@@ -201,28 +207,43 @@ function Alert({
|
|
|
201
207
|
}) {
|
|
202
208
|
const colors = statusColors[status];
|
|
203
209
|
const isSolid = variant === "solid";
|
|
210
|
+
const isCompact = size === "compact";
|
|
204
211
|
return /* @__PURE__ */ jsxs(
|
|
205
212
|
reactNative.View,
|
|
206
213
|
{
|
|
207
214
|
accessibilityRole: "alert",
|
|
208
215
|
className: cn(
|
|
209
|
-
"flex-row items-start p-4 rounded-lg",
|
|
216
|
+
isCompact ? "flex-row items-center px-3 py-2 rounded-lg" : "flex-row items-start p-4 rounded-lg",
|
|
210
217
|
colors[variant],
|
|
218
|
+
// A compact `subtle` pill gets a hairline status border so it reads as a
|
|
219
|
+
// defined cue on a dark wall (the CueFlag look); other variants carry their own.
|
|
220
|
+
isCompact && variant === "subtle" && cn("border", colors.border),
|
|
211
221
|
className
|
|
212
222
|
),
|
|
213
223
|
...props,
|
|
214
224
|
children: [
|
|
215
|
-
showIcon && /* @__PURE__ */ jsx(reactNative.View, { className: "mr-3 mt-0.5", children: icon || /* @__PURE__ */ jsx(
|
|
225
|
+
showIcon && /* @__PURE__ */ jsx(reactNative.View, { className: isCompact ? "mr-2" : "mr-3 mt-0.5", children: icon || /* @__PURE__ */ jsx(
|
|
216
226
|
reactNative.Text,
|
|
217
227
|
{
|
|
218
228
|
className: cn(
|
|
219
|
-
"
|
|
229
|
+
"font-bold",
|
|
230
|
+
isCompact ? "text-base" : "text-lg",
|
|
220
231
|
isSolid ? "text-white" : colors.icon
|
|
221
232
|
),
|
|
222
233
|
children: defaultIcons[status]
|
|
223
234
|
}
|
|
224
235
|
) }),
|
|
225
|
-
/* @__PURE__ */
|
|
236
|
+
/* @__PURE__ */ jsxs(reactNative.View, { className: "flex-1", children: [
|
|
237
|
+
message != null && /* @__PURE__ */ jsx(
|
|
238
|
+
reactNative.Text,
|
|
239
|
+
{
|
|
240
|
+
className: cn("text-sm font-semibold", isSolid ? "text-white" : colors.text),
|
|
241
|
+
testID: "alert-message",
|
|
242
|
+
children: message
|
|
243
|
+
}
|
|
244
|
+
),
|
|
245
|
+
children
|
|
246
|
+
] }),
|
|
226
247
|
onClose && /* @__PURE__ */ jsx(
|
|
227
248
|
reactNative.Pressable,
|
|
228
249
|
{
|
|
@@ -5072,6 +5093,8 @@ function CircularProgress({
|
|
|
5072
5093
|
color = "primary",
|
|
5073
5094
|
showValue = false,
|
|
5074
5095
|
formatValue: formatValue3 = (v, m) => `${Math.round(v / m * 100)}%`,
|
|
5096
|
+
children,
|
|
5097
|
+
fill = false,
|
|
5075
5098
|
className,
|
|
5076
5099
|
...props
|
|
5077
5100
|
}) {
|
|
@@ -5080,11 +5103,12 @@ function CircularProgress({
|
|
|
5080
5103
|
const circumference = 2 * Math.PI * radius;
|
|
5081
5104
|
const strokeDashoffset = circumference - percentage / 100 * circumference;
|
|
5082
5105
|
const center = size / 2;
|
|
5106
|
+
const boxStyle = fill ? { width: "100%", aspectRatio: 1 } : { width: size, height: size };
|
|
5083
5107
|
return /* @__PURE__ */ jsxs(
|
|
5084
5108
|
reactNative.View,
|
|
5085
5109
|
{
|
|
5086
5110
|
className: cn("items-center justify-center", className),
|
|
5087
|
-
style:
|
|
5111
|
+
style: boxStyle,
|
|
5088
5112
|
accessibilityRole: "progressbar",
|
|
5089
5113
|
accessibilityValue: {
|
|
5090
5114
|
min: 0,
|
|
@@ -5093,52 +5117,56 @@ function CircularProgress({
|
|
|
5093
5117
|
},
|
|
5094
5118
|
...props,
|
|
5095
5119
|
children: [
|
|
5096
|
-
/* @__PURE__ */ jsx(
|
|
5120
|
+
/* @__PURE__ */ jsx(reactNative.View, { className: cn(isIndeterminate && "animate-spin"), style: boxStyle, children: /* @__PURE__ */ jsxs(
|
|
5121
|
+
"svg",
|
|
5122
|
+
{
|
|
5123
|
+
width: "100%",
|
|
5124
|
+
height: "100%",
|
|
5125
|
+
viewBox: `0 0 ${size} ${size}`,
|
|
5126
|
+
style: { position: "absolute" },
|
|
5127
|
+
children: [
|
|
5128
|
+
/* @__PURE__ */ jsx(
|
|
5129
|
+
"circle",
|
|
5130
|
+
{
|
|
5131
|
+
cx: center,
|
|
5132
|
+
cy: center,
|
|
5133
|
+
r: radius,
|
|
5134
|
+
fill: "none",
|
|
5135
|
+
stroke: "var(--color-border-default)",
|
|
5136
|
+
strokeWidth
|
|
5137
|
+
}
|
|
5138
|
+
),
|
|
5139
|
+
/* @__PURE__ */ jsx(
|
|
5140
|
+
"circle",
|
|
5141
|
+
{
|
|
5142
|
+
cx: center,
|
|
5143
|
+
cy: center,
|
|
5144
|
+
r: radius,
|
|
5145
|
+
fill: "none",
|
|
5146
|
+
stroke: colorVarMap[color],
|
|
5147
|
+
strokeWidth,
|
|
5148
|
+
strokeLinecap: "round",
|
|
5149
|
+
strokeDasharray: circumference,
|
|
5150
|
+
strokeDashoffset: isIndeterminate ? circumference * 0.75 : strokeDashoffset,
|
|
5151
|
+
transform: `rotate(-90 ${center} ${center})`,
|
|
5152
|
+
style: { transition: "stroke-dashoffset 300ms cubic-bezier(0.22, 1, 0.36, 1)" }
|
|
5153
|
+
}
|
|
5154
|
+
)
|
|
5155
|
+
]
|
|
5156
|
+
}
|
|
5157
|
+
) }),
|
|
5158
|
+
children != null ? /* @__PURE__ */ jsx(
|
|
5097
5159
|
reactNative.View,
|
|
5098
5160
|
{
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
"
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
viewBox: `0 0 ${size} ${size}`,
|
|
5107
|
-
style: { position: "absolute" },
|
|
5108
|
-
children: [
|
|
5109
|
-
/* @__PURE__ */ jsx(
|
|
5110
|
-
"circle",
|
|
5111
|
-
{
|
|
5112
|
-
cx: center,
|
|
5113
|
-
cy: center,
|
|
5114
|
-
r: radius,
|
|
5115
|
-
fill: "none",
|
|
5116
|
-
stroke: "var(--color-border-default)",
|
|
5117
|
-
strokeWidth
|
|
5118
|
-
}
|
|
5119
|
-
),
|
|
5120
|
-
/* @__PURE__ */ jsx(
|
|
5121
|
-
"circle",
|
|
5122
|
-
{
|
|
5123
|
-
cx: center,
|
|
5124
|
-
cy: center,
|
|
5125
|
-
r: radius,
|
|
5126
|
-
fill: "none",
|
|
5127
|
-
stroke: colorVarMap[color],
|
|
5128
|
-
strokeWidth,
|
|
5129
|
-
strokeLinecap: "round",
|
|
5130
|
-
strokeDasharray: circumference,
|
|
5131
|
-
strokeDashoffset: isIndeterminate ? circumference * 0.75 : strokeDashoffset,
|
|
5132
|
-
transform: `rotate(-90 ${center} ${center})`,
|
|
5133
|
-
style: { transition: "stroke-dashoffset 300ms cubic-bezier(0.22, 1, 0.36, 1)" }
|
|
5134
|
-
}
|
|
5135
|
-
)
|
|
5136
|
-
]
|
|
5137
|
-
}
|
|
5138
|
-
)
|
|
5161
|
+
style: {
|
|
5162
|
+
position: "absolute",
|
|
5163
|
+
alignItems: "center",
|
|
5164
|
+
justifyContent: "center",
|
|
5165
|
+
pointerEvents: "none"
|
|
5166
|
+
},
|
|
5167
|
+
children
|
|
5139
5168
|
}
|
|
5140
|
-
)
|
|
5141
|
-
showValue && !isIndeterminate && /* @__PURE__ */ jsx(
|
|
5169
|
+
) : showValue && !isIndeterminate && /* @__PURE__ */ jsx(
|
|
5142
5170
|
reactNative.Text,
|
|
5143
5171
|
{
|
|
5144
5172
|
className: "text-xs font-semibold text-text-primary absolute",
|
|
@@ -5234,7 +5262,7 @@ function ToastProvider({
|
|
|
5234
5262
|
return id;
|
|
5235
5263
|
}, [defaultDuration, maxToasts]);
|
|
5236
5264
|
const removeToast = React24.useCallback((id) => {
|
|
5237
|
-
setToasts((prev) => prev.filter((
|
|
5265
|
+
setToasts((prev) => prev.filter((t17) => t17.id !== id));
|
|
5238
5266
|
}, []);
|
|
5239
5267
|
const removeAllToasts = React24.useCallback(() => {
|
|
5240
5268
|
setToasts([]);
|
|
@@ -7079,6 +7107,70 @@ function TimerReadout({
|
|
|
7079
7107
|
}
|
|
7080
7108
|
);
|
|
7081
7109
|
}
|
|
7110
|
+
function CircularTimer({
|
|
7111
|
+
durationMs,
|
|
7112
|
+
elapsedMs,
|
|
7113
|
+
mode = "down",
|
|
7114
|
+
size = 160,
|
|
7115
|
+
strokeWidth = 8,
|
|
7116
|
+
fill = false,
|
|
7117
|
+
color = "primary",
|
|
7118
|
+
doneLabel,
|
|
7119
|
+
doneColor = "success",
|
|
7120
|
+
controls,
|
|
7121
|
+
accessibilityLabel: accessibilityLabel2,
|
|
7122
|
+
testID
|
|
7123
|
+
}) {
|
|
7124
|
+
const { remainingMs, progress, label, done } = useTimer({ mode, durationMs, elapsedMs });
|
|
7125
|
+
const isDone = done && mode === "down";
|
|
7126
|
+
const showDone = isDone && doneLabel != null;
|
|
7127
|
+
const remainingFrac = durationMs > 0 ? Math.max(0, Math.min(1, remainingMs / durationMs)) : 0;
|
|
7128
|
+
const arc = mode === "down" ? showDone ? 1 : remainingFrac : progress;
|
|
7129
|
+
const ringColor = showDone ? doneColor : color;
|
|
7130
|
+
const remainingSec = Math.ceil(Math.max(0, remainingMs) / 1e3);
|
|
7131
|
+
const a11y = accessibilityLabel2 ?? (isDone ? "Timer complete" : `${remainingSec} seconds remaining`);
|
|
7132
|
+
return /* @__PURE__ */ jsxs(
|
|
7133
|
+
reactNative.View,
|
|
7134
|
+
{
|
|
7135
|
+
style: { alignItems: "center", gap: 16 },
|
|
7136
|
+
accessibilityRole: "timer",
|
|
7137
|
+
accessibilityLabel: a11y,
|
|
7138
|
+
testID: testID ?? "circular-timer",
|
|
7139
|
+
children: [
|
|
7140
|
+
/* @__PURE__ */ jsx(
|
|
7141
|
+
CircularProgress,
|
|
7142
|
+
{
|
|
7143
|
+
value: arc,
|
|
7144
|
+
max: 1,
|
|
7145
|
+
size,
|
|
7146
|
+
strokeWidth,
|
|
7147
|
+
fill,
|
|
7148
|
+
color: ringColor,
|
|
7149
|
+
accessibilityLabel: "Timer ring",
|
|
7150
|
+
testID: "circular-timer-ring",
|
|
7151
|
+
children: /* @__PURE__ */ jsx(
|
|
7152
|
+
reactNative.Text,
|
|
7153
|
+
{
|
|
7154
|
+
className: showDone ? void 0 : "text-text-primary",
|
|
7155
|
+
style: {
|
|
7156
|
+
fontSize: Math.round(size * (showDone ? 0.28 : 0.24)),
|
|
7157
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
7158
|
+
fontWeight: "800",
|
|
7159
|
+
fontVariant: ["tabular-nums"],
|
|
7160
|
+
letterSpacing: showDone ? 1 : -1,
|
|
7161
|
+
...showDone ? { color: colorVarMap[doneColor] } : null
|
|
7162
|
+
},
|
|
7163
|
+
testID: "circular-timer-label",
|
|
7164
|
+
children: showDone ? doneLabel : label
|
|
7165
|
+
}
|
|
7166
|
+
)
|
|
7167
|
+
}
|
|
7168
|
+
),
|
|
7169
|
+
controls
|
|
7170
|
+
]
|
|
7171
|
+
}
|
|
7172
|
+
);
|
|
7173
|
+
}
|
|
7082
7174
|
var sizeConfig2 = {
|
|
7083
7175
|
sm: { value: "text-lg font-bold", label: "text-xs", unit: "text-xs" },
|
|
7084
7176
|
md: { value: "text-2xl font-bold", label: "text-xs", unit: "text-sm" },
|
|
@@ -7724,137 +7816,6 @@ function getLuminance(color) {
|
|
|
7724
7816
|
function getContrastText(backgroundColor) {
|
|
7725
7817
|
return getLuminance(backgroundColor) === "light" ? "#000000" : "#FFFFFF";
|
|
7726
7818
|
}
|
|
7727
|
-
var t2 = getSemanticColors("dark");
|
|
7728
|
-
var TEMPO_PACING = {
|
|
7729
|
-
behindThresholdPct: 0.15,
|
|
7730
|
-
minPhaseDurationMs: 500
|
|
7731
|
-
};
|
|
7732
|
-
function getTempoPacingState(elapsedMs, targetMs) {
|
|
7733
|
-
if (!targetMs || targetMs < TEMPO_PACING.minPhaseDurationMs) return "none";
|
|
7734
|
-
const ratio = elapsedMs / targetMs;
|
|
7735
|
-
if (ratio > 1 + TEMPO_PACING.behindThresholdPct) return "behind";
|
|
7736
|
-
return "on-pace";
|
|
7737
|
-
}
|
|
7738
|
-
function getTempoFillPct(elapsedMs, targetMs) {
|
|
7739
|
-
if (!targetMs) return 100;
|
|
7740
|
-
return Math.min(100, elapsedMs / targetMs * 100);
|
|
7741
|
-
}
|
|
7742
|
-
var PHASE_ORDER = ["concentric", "hold", "eccentric"];
|
|
7743
|
-
var PHASE_CONFIG = {
|
|
7744
|
-
concentric: { label: "Con", color: t2["status-success"], flex: 2 },
|
|
7745
|
-
hold: { label: "Hold", color: t2["brand-primary"], flex: 1 },
|
|
7746
|
-
eccentric: { label: "Ecc", color: t2["status-warning"], flex: 3 }
|
|
7747
|
-
};
|
|
7748
|
-
function TempoBar({
|
|
7749
|
-
activePhase,
|
|
7750
|
-
phaseElapsedMs,
|
|
7751
|
-
completed,
|
|
7752
|
-
target,
|
|
7753
|
-
className,
|
|
7754
|
-
...props
|
|
7755
|
-
}) {
|
|
7756
|
-
return /* @__PURE__ */ jsxs(reactNative.View, { className, testID: "tempo-bar", ...props, children: [
|
|
7757
|
-
/* @__PURE__ */ jsx(reactNative.View, { style: { flexDirection: "row", marginBottom: 4 }, children: PHASE_ORDER.map((phase) => {
|
|
7758
|
-
const config = PHASE_CONFIG[phase];
|
|
7759
|
-
return /* @__PURE__ */ jsx(reactNative.View, { style: { flex: config.flex, alignItems: "center" }, children: /* @__PURE__ */ jsx(reactNative.Text, { style: { fontSize: 10, color: t2["text-disabled"] }, children: config.label }) }, phase);
|
|
7760
|
-
}) }),
|
|
7761
|
-
/* @__PURE__ */ jsx(reactNative.View, { style: { flexDirection: "row", gap: 2, height: 20 }, children: PHASE_ORDER.map((phase) => {
|
|
7762
|
-
const config = PHASE_CONFIG[phase];
|
|
7763
|
-
const isActive = activePhase === phase;
|
|
7764
|
-
const completedMs = completed?.[phase];
|
|
7765
|
-
const targetSec = target?.[phase];
|
|
7766
|
-
const targetMs = targetSec != null ? targetSec * 1e3 : null;
|
|
7767
|
-
return /* @__PURE__ */ jsx(
|
|
7768
|
-
reactNative.View,
|
|
7769
|
-
{
|
|
7770
|
-
style: {
|
|
7771
|
-
flex: config.flex,
|
|
7772
|
-
backgroundColor: alpha("#ffffff", 0.06),
|
|
7773
|
-
borderRadius: 4,
|
|
7774
|
-
overflow: "hidden"
|
|
7775
|
-
},
|
|
7776
|
-
children: isActive ? /* @__PURE__ */ jsx(
|
|
7777
|
-
ActiveSegment,
|
|
7778
|
-
{
|
|
7779
|
-
config,
|
|
7780
|
-
phaseElapsedMs,
|
|
7781
|
-
targetMs
|
|
7782
|
-
}
|
|
7783
|
-
) : completedMs != null ? /* @__PURE__ */ jsx(CompletedSegment, { config, completedMs, targetMs }) : null
|
|
7784
|
-
},
|
|
7785
|
-
phase
|
|
7786
|
-
);
|
|
7787
|
-
}) })
|
|
7788
|
-
] });
|
|
7789
|
-
}
|
|
7790
|
-
function ActiveSegment({
|
|
7791
|
-
config,
|
|
7792
|
-
phaseElapsedMs,
|
|
7793
|
-
targetMs
|
|
7794
|
-
}) {
|
|
7795
|
-
const pacing = getTempoPacingState(phaseElapsedMs, targetMs);
|
|
7796
|
-
const barColor = pacing === "behind" ? t2["status-error"] : config.color;
|
|
7797
|
-
const fillPct = getTempoFillPct(phaseElapsedMs, targetMs);
|
|
7798
|
-
const label = targetMs ? `${formatDuration2(phaseElapsedMs)} / ${formatDuration2(targetMs)}` : formatDuration2(phaseElapsedMs);
|
|
7799
|
-
return /* @__PURE__ */ jsxs(reactNative.View, { style: { height: "100%", position: "relative" }, testID: `tempo-segment-active-${config.label}`, children: [
|
|
7800
|
-
/* @__PURE__ */ jsx(
|
|
7801
|
-
reactNative.View,
|
|
7802
|
-
{
|
|
7803
|
-
style: {
|
|
7804
|
-
position: "absolute",
|
|
7805
|
-
left: 0,
|
|
7806
|
-
top: 0,
|
|
7807
|
-
bottom: 0,
|
|
7808
|
-
width: `${fillPct}%`,
|
|
7809
|
-
backgroundColor: alpha(barColor, 0.3),
|
|
7810
|
-
borderRadius: 4
|
|
7811
|
-
}
|
|
7812
|
-
}
|
|
7813
|
-
),
|
|
7814
|
-
/* @__PURE__ */ jsx(
|
|
7815
|
-
reactNative.View,
|
|
7816
|
-
{
|
|
7817
|
-
style: {
|
|
7818
|
-
height: "100%",
|
|
7819
|
-
flexDirection: "row",
|
|
7820
|
-
alignItems: "center",
|
|
7821
|
-
justifyContent: "center"
|
|
7822
|
-
},
|
|
7823
|
-
children: /* @__PURE__ */ jsx(reactNative.Text, { style: { fontSize: 12, fontWeight: "700", color: barColor }, children: label })
|
|
7824
|
-
}
|
|
7825
|
-
)
|
|
7826
|
-
] });
|
|
7827
|
-
}
|
|
7828
|
-
function CompletedSegment({
|
|
7829
|
-
config,
|
|
7830
|
-
completedMs,
|
|
7831
|
-
targetMs
|
|
7832
|
-
}) {
|
|
7833
|
-
const pacing = getTempoPacingState(completedMs, targetMs);
|
|
7834
|
-
const hitTarget = pacing !== "behind";
|
|
7835
|
-
const indicator = targetMs && targetMs >= TEMPO_PACING.minPhaseDurationMs ? hitTarget ? " \u2713" : " \u2717" : "";
|
|
7836
|
-
return /* @__PURE__ */ jsx(
|
|
7837
|
-
reactNative.View,
|
|
7838
|
-
{
|
|
7839
|
-
style: {
|
|
7840
|
-
height: "100%",
|
|
7841
|
-
flexDirection: "row",
|
|
7842
|
-
alignItems: "center",
|
|
7843
|
-
justifyContent: "center",
|
|
7844
|
-
backgroundColor: alpha(config.color, 0.15)
|
|
7845
|
-
},
|
|
7846
|
-
testID: `tempo-segment-completed-${config.label}`,
|
|
7847
|
-
children: /* @__PURE__ */ jsxs(reactNative.Text, { style: { fontSize: 12, fontWeight: "500", color: alpha(config.color, 0.7) }, children: [
|
|
7848
|
-
formatDuration2(completedMs),
|
|
7849
|
-
indicator
|
|
7850
|
-
] })
|
|
7851
|
-
}
|
|
7852
|
-
);
|
|
7853
|
-
}
|
|
7854
|
-
function formatDuration2(ms) {
|
|
7855
|
-
const s = ms / 1e3;
|
|
7856
|
-
return s < 10 ? s.toFixed(1) : Math.round(s).toString();
|
|
7857
|
-
}
|
|
7858
7819
|
var METRIC_FONT = "Inter, sans-serif";
|
|
7859
7820
|
function MetricCell({ children, color, fontSize = 11 }) {
|
|
7860
7821
|
return /* @__PURE__ */ jsx(
|
|
@@ -7873,14 +7834,32 @@ function MetricCell({ children, color, fontSize = 11 }) {
|
|
|
7873
7834
|
}
|
|
7874
7835
|
|
|
7875
7836
|
// src/components/custom/Workout/TempoDisplay.tsx
|
|
7876
|
-
var
|
|
7837
|
+
var t2 = getSemanticColors("dark");
|
|
7877
7838
|
var INTER = "Inter, sans-serif";
|
|
7878
7839
|
var TEXT_TERTIARY = "#6B7280";
|
|
7879
|
-
var STATUS_ERROR =
|
|
7840
|
+
var STATUS_ERROR = t2["status-error"];
|
|
7841
|
+
var STATUS_SUCCESS = t2["status-success"];
|
|
7842
|
+
var STATUS_WARNING = t2["status-warning"];
|
|
7843
|
+
var ON_TARGET_MS = 100;
|
|
7844
|
+
function getTempoFillPct(elapsedMs, targetMs) {
|
|
7845
|
+
if (!targetMs) return 100;
|
|
7846
|
+
return Math.min(100, elapsedMs / targetMs * 100);
|
|
7847
|
+
}
|
|
7848
|
+
function activeNumberTone(elapsedMs, targetMs) {
|
|
7849
|
+
if (targetMs == null) return t2["text-primary"];
|
|
7850
|
+
const remainingMs = targetMs - elapsedMs;
|
|
7851
|
+
if (remainingMs > ON_TARGET_MS) return STATUS_WARNING;
|
|
7852
|
+
if (remainingMs >= -ON_TARGET_MS) return STATUS_SUCCESS;
|
|
7853
|
+
return STATUS_ERROR;
|
|
7854
|
+
}
|
|
7855
|
+
function liveReadoutText(elapsedMs, targetMs, readout) {
|
|
7856
|
+
const seconds = readout === "countup" ? elapsedMs / 1e3 : (targetMs - elapsedMs) / 1e3;
|
|
7857
|
+
return seconds.toFixed(1);
|
|
7858
|
+
}
|
|
7880
7859
|
var phaseColors = {
|
|
7881
|
-
eccentric:
|
|
7860
|
+
eccentric: primitiveRamps.magenta[400],
|
|
7882
7861
|
pauseBottom: TEXT_TERTIARY,
|
|
7883
|
-
concentric:
|
|
7862
|
+
concentric: primitiveRamps.cyan[300],
|
|
7884
7863
|
pauseTop: TEXT_TERTIARY,
|
|
7885
7864
|
dash: TEXT_TERTIARY
|
|
7886
7865
|
};
|
|
@@ -7900,63 +7879,98 @@ var LIVE_PHASES = [
|
|
|
7900
7879
|
{ key: "concentric", color: phaseColors.concentric },
|
|
7901
7880
|
{ key: "pauseTop", color: phaseColors.pauseTop }
|
|
7902
7881
|
];
|
|
7882
|
+
function CellFill({ color, pct: pct2 }) {
|
|
7883
|
+
return /* @__PURE__ */ jsx(
|
|
7884
|
+
reactNative.View,
|
|
7885
|
+
{
|
|
7886
|
+
style: {
|
|
7887
|
+
position: "absolute",
|
|
7888
|
+
left: 2,
|
|
7889
|
+
right: 2,
|
|
7890
|
+
bottom: 0,
|
|
7891
|
+
height: `${pct2}%`,
|
|
7892
|
+
backgroundColor: alpha(color, 0.28),
|
|
7893
|
+
borderRadius: 3
|
|
7894
|
+
}
|
|
7895
|
+
}
|
|
7896
|
+
);
|
|
7897
|
+
}
|
|
7898
|
+
var MONO = "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
|
|
7899
|
+
var READOUT_MAX_CHARS = 5;
|
|
7903
7900
|
function LiveTempoCell({
|
|
7904
7901
|
value,
|
|
7905
7902
|
color,
|
|
7906
|
-
|
|
7903
|
+
status,
|
|
7907
7904
|
phaseElapsedMs,
|
|
7908
|
-
|
|
7905
|
+
completedMs,
|
|
7906
|
+
fontSize,
|
|
7907
|
+
readout
|
|
7909
7908
|
}) {
|
|
7910
|
-
if (!isActive) {
|
|
7911
|
-
return /* @__PURE__ */ jsx(TempoValue, { value, color: alpha(color, 0.35), fontSize });
|
|
7912
|
-
}
|
|
7913
7909
|
const targetMs = value > 0 ? value * 1e3 : null;
|
|
7914
|
-
const
|
|
7910
|
+
const cellW = Math.ceil(fontSize * 0.62 * READOUT_MAX_CHARS);
|
|
7911
|
+
const wrap = {
|
|
7912
|
+
position: "relative",
|
|
7913
|
+
width: cellW,
|
|
7914
|
+
minHeight: Math.round(fontSize * 1.25),
|
|
7915
|
+
alignItems: "center",
|
|
7916
|
+
justifyContent: "center"
|
|
7917
|
+
};
|
|
7918
|
+
const num = (c, text) => /* @__PURE__ */ jsx(reactNative.Text, { style: { fontFamily: MONO, fontSize, color: c, fontWeight: "700" }, children: text });
|
|
7919
|
+
if (status === "upcoming") {
|
|
7920
|
+
const targetText = targetMs != null ? (targetMs / 1e3).toFixed(1) : String(value);
|
|
7921
|
+
return /* @__PURE__ */ jsx(reactNative.View, { style: wrap, children: num(color, targetText) });
|
|
7922
|
+
}
|
|
7923
|
+
if (status === "done") {
|
|
7924
|
+
const finalMs = completedMs ?? targetMs ?? 0;
|
|
7925
|
+
const finalText = targetMs != null ? liveReadoutText(finalMs, targetMs, readout) : String(value);
|
|
7926
|
+
const finalTone = targetMs != null ? activeNumberTone(finalMs, targetMs) : color;
|
|
7927
|
+
return /* @__PURE__ */ jsxs(reactNative.View, { style: wrap, testID: "tempo-live-done", children: [
|
|
7928
|
+
/* @__PURE__ */ jsx(CellFill, { color, pct: 100 }),
|
|
7929
|
+
num(finalTone, finalText)
|
|
7930
|
+
] });
|
|
7931
|
+
}
|
|
7932
|
+
const numberTone = activeNumberTone(phaseElapsedMs, targetMs);
|
|
7915
7933
|
const fillPct = getTempoFillPct(phaseElapsedMs, targetMs);
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
style: {
|
|
7921
|
-
position: "absolute",
|
|
7922
|
-
left: 0,
|
|
7923
|
-
top: 0,
|
|
7924
|
-
bottom: 0,
|
|
7925
|
-
width: `${fillPct}%`,
|
|
7926
|
-
backgroundColor: alpha(barColor, 0.3),
|
|
7927
|
-
borderRadius: 2
|
|
7928
|
-
}
|
|
7929
|
-
}
|
|
7930
|
-
),
|
|
7931
|
-
/* @__PURE__ */ jsx(TempoValue, { value, color: barColor, fontSize })
|
|
7934
|
+
const activeText = targetMs != null ? liveReadoutText(phaseElapsedMs, targetMs, readout) : String(value);
|
|
7935
|
+
return /* @__PURE__ */ jsxs(reactNative.View, { style: wrap, testID: "tempo-live-active", children: [
|
|
7936
|
+
/* @__PURE__ */ jsx(CellFill, { color, pct: fillPct }),
|
|
7937
|
+
num(numberTone, activeText)
|
|
7932
7938
|
] });
|
|
7933
7939
|
}
|
|
7934
7940
|
function LiveTempoRow({
|
|
7935
7941
|
values,
|
|
7936
7942
|
live,
|
|
7937
|
-
fontSize
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
|
|
7951
|
-
|
|
7943
|
+
fontSize,
|
|
7944
|
+
readout
|
|
7945
|
+
}) {
|
|
7946
|
+
const activeIndex = live.activePhase ? LIVE_PHASES.findIndex((p) => p.key === live.activePhase) : -1;
|
|
7947
|
+
return /* @__PURE__ */ jsx(jsxRuntime.Fragment, { children: LIVE_PHASES.map((phase, i) => {
|
|
7948
|
+
const status = activeIndex < 0 || i > activeIndex ? "upcoming" : i < activeIndex ? "done" : "active";
|
|
7949
|
+
return /* @__PURE__ */ jsxs(reactNative.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
7950
|
+
i > 0 && /* @__PURE__ */ jsx(TempoSeparator, { color: phaseColors.dash, fontSize }),
|
|
7951
|
+
/* @__PURE__ */ jsx(
|
|
7952
|
+
LiveTempoCell,
|
|
7953
|
+
{
|
|
7954
|
+
value: values[i],
|
|
7955
|
+
color: phase.color,
|
|
7956
|
+
status,
|
|
7957
|
+
phaseElapsedMs: live.phaseElapsedMs,
|
|
7958
|
+
completedMs: live.completed?.[phase.key],
|
|
7959
|
+
fontSize,
|
|
7960
|
+
readout
|
|
7961
|
+
}
|
|
7962
|
+
)
|
|
7963
|
+
] }, phase.key);
|
|
7964
|
+
}) });
|
|
7952
7965
|
}
|
|
7953
7966
|
function TempoDisplay({
|
|
7954
7967
|
tempo,
|
|
7955
7968
|
size = "md",
|
|
7956
|
-
|
|
7969
|
+
fontSize: fontSizeProp,
|
|
7957
7970
|
showLabel = true,
|
|
7958
7971
|
showInfo = true,
|
|
7959
7972
|
live,
|
|
7973
|
+
liveReadout = "countdown",
|
|
7960
7974
|
onPress,
|
|
7961
7975
|
className,
|
|
7962
7976
|
...props
|
|
@@ -7964,8 +7978,11 @@ function TempoDisplay({
|
|
|
7964
7978
|
const [showTooltip, setShowTooltip] = React24.useState(false);
|
|
7965
7979
|
const [eccentric, pauseBottom, concentric, pauseTop] = roundTempo(tempo);
|
|
7966
7980
|
const isSm = size === "sm";
|
|
7967
|
-
const fontSize = isSm ? 9 : 11;
|
|
7968
|
-
const
|
|
7981
|
+
const fontSize = fontSizeProp ?? (isSm ? 9 : 11);
|
|
7982
|
+
const chromePadX = Math.round(fontSize * 0.6);
|
|
7983
|
+
const chromePadY = Math.round(fontSize * 0.3);
|
|
7984
|
+
const chromeRadius = Math.round(fontSize * 0.4);
|
|
7985
|
+
const labelFont = Math.max(9, Math.round(fontSize * 0.5));
|
|
7969
7986
|
const handlePress = React24.useCallback(() => {
|
|
7970
7987
|
if (onPress) {
|
|
7971
7988
|
onPress();
|
|
@@ -7982,9 +7999,9 @@ function TempoDisplay({
|
|
|
7982
7999
|
flexDirection: "row",
|
|
7983
8000
|
alignItems: "center",
|
|
7984
8001
|
backgroundColor: "#1C1C1C",
|
|
7985
|
-
paddingHorizontal:
|
|
7986
|
-
paddingVertical:
|
|
7987
|
-
borderRadius:
|
|
8002
|
+
paddingHorizontal: chromePadX,
|
|
8003
|
+
paddingVertical: chromePadY,
|
|
8004
|
+
borderRadius: chromeRadius
|
|
7988
8005
|
},
|
|
7989
8006
|
...props,
|
|
7990
8007
|
children: [
|
|
@@ -7993,12 +8010,13 @@ function TempoDisplay({
|
|
|
7993
8010
|
{
|
|
7994
8011
|
style: {
|
|
7995
8012
|
fontFamily: INTER,
|
|
7996
|
-
fontSize:
|
|
8013
|
+
fontSize: labelFont,
|
|
7997
8014
|
fontWeight: "500",
|
|
7998
|
-
|
|
8015
|
+
// Live-muted green while a rep is running, tertiary at rest.
|
|
8016
|
+
color: live ? t2["status-live-muted"] : TEXT_TERTIARY,
|
|
7999
8017
|
letterSpacing: 0.5,
|
|
8000
8018
|
textTransform: "uppercase",
|
|
8001
|
-
marginRight:
|
|
8019
|
+
marginRight: Math.round(fontSize * 0.5)
|
|
8002
8020
|
},
|
|
8003
8021
|
children: "TEMPO"
|
|
8004
8022
|
}
|
|
@@ -8008,36 +8026,20 @@ function TempoDisplay({
|
|
|
8008
8026
|
{
|
|
8009
8027
|
values: [eccentric, pauseBottom, concentric, pauseTop],
|
|
8010
8028
|
live,
|
|
8011
|
-
fontSize
|
|
8012
|
-
|
|
8013
|
-
) : colored ? /* @__PURE__ */ jsxs(jsxRuntime.Fragment, { children: [
|
|
8014
|
-
/* @__PURE__ */ jsx(TempoValue, { value: eccentric, color: phaseColors.eccentric, fontSize }),
|
|
8015
|
-
/* @__PURE__ */ jsx(TempoSeparator, { color: phaseColors.dash, fontSize }),
|
|
8016
|
-
/* @__PURE__ */ jsx(TempoValue, { value: pauseBottom, color: phaseColors.pauseBottom, fontSize }),
|
|
8017
|
-
/* @__PURE__ */ jsx(TempoSeparator, { color: phaseColors.dash, fontSize }),
|
|
8018
|
-
/* @__PURE__ */ jsx(TempoValue, { value: concentric, color: phaseColors.concentric, fontSize }),
|
|
8019
|
-
/* @__PURE__ */ jsx(TempoSeparator, { color: phaseColors.dash, fontSize }),
|
|
8020
|
-
/* @__PURE__ */ jsx(TempoValue, { value: pauseTop, color: phaseColors.pauseTop, fontSize })
|
|
8021
|
-
] }) : /* @__PURE__ */ jsxs(
|
|
8022
|
-
reactNative.Text,
|
|
8023
|
-
{
|
|
8024
|
-
style: {
|
|
8025
|
-
fontFamily: INTER,
|
|
8026
|
-
fontSize,
|
|
8027
|
-
color: monoColor,
|
|
8028
|
-
fontWeight: "600",
|
|
8029
|
-
letterSpacing: 1
|
|
8030
|
-
},
|
|
8031
|
-
children: [
|
|
8032
|
-
eccentric,
|
|
8033
|
-
"-",
|
|
8034
|
-
pauseBottom,
|
|
8035
|
-
"-",
|
|
8036
|
-
concentric,
|
|
8037
|
-
"-",
|
|
8038
|
-
pauseTop
|
|
8039
|
-
]
|
|
8029
|
+
fontSize,
|
|
8030
|
+
readout: liveReadout
|
|
8040
8031
|
}
|
|
8032
|
+
) : (
|
|
8033
|
+
// Static prescription: the phase-coloured lockup (the same colours the live row rests at).
|
|
8034
|
+
/* @__PURE__ */ jsxs(jsxRuntime.Fragment, { children: [
|
|
8035
|
+
/* @__PURE__ */ jsx(TempoValue, { value: eccentric, color: phaseColors.eccentric, fontSize }),
|
|
8036
|
+
/* @__PURE__ */ jsx(TempoSeparator, { color: phaseColors.dash, fontSize }),
|
|
8037
|
+
/* @__PURE__ */ jsx(TempoValue, { value: pauseBottom, color: phaseColors.pauseBottom, fontSize }),
|
|
8038
|
+
/* @__PURE__ */ jsx(TempoSeparator, { color: phaseColors.dash, fontSize }),
|
|
8039
|
+
/* @__PURE__ */ jsx(TempoValue, { value: concentric, color: phaseColors.concentric, fontSize }),
|
|
8040
|
+
/* @__PURE__ */ jsx(TempoSeparator, { color: phaseColors.dash, fontSize }),
|
|
8041
|
+
/* @__PURE__ */ jsx(TempoValue, { value: pauseTop, color: phaseColors.pauseTop, fontSize })
|
|
8042
|
+
] })
|
|
8041
8043
|
) })
|
|
8042
8044
|
]
|
|
8043
8045
|
}
|
|
@@ -8122,13 +8124,13 @@ function TempoDisplay({
|
|
|
8122
8124
|
}
|
|
8123
8125
|
);
|
|
8124
8126
|
}
|
|
8125
|
-
var
|
|
8127
|
+
var t3 = getSemanticColors("dark");
|
|
8126
8128
|
function getDotColor(deviation) {
|
|
8127
8129
|
const abs = Math.abs(deviation);
|
|
8128
|
-
if (deviation < -0.3) return
|
|
8130
|
+
if (deviation < -0.3) return t3["status-success"];
|
|
8129
8131
|
if (abs <= 0.3) return "#6B7280";
|
|
8130
|
-
if (abs <= 0.7) return
|
|
8131
|
-
return
|
|
8132
|
+
if (abs <= 0.7) return t3["status-warning"];
|
|
8133
|
+
return t3["status-error"];
|
|
8132
8134
|
}
|
|
8133
8135
|
function getDeviationDescription(deviation) {
|
|
8134
8136
|
if (deviation < -0.3) return "lighter than planned";
|
|
@@ -8196,19 +8198,19 @@ function DeviationBar({
|
|
|
8196
8198
|
}
|
|
8197
8199
|
);
|
|
8198
8200
|
}
|
|
8199
|
-
var
|
|
8201
|
+
var t4 = getSemanticColors("dark");
|
|
8200
8202
|
var TRACK_BG = "#333333";
|
|
8201
8203
|
var LABEL_COLOR = "#6B7280";
|
|
8202
8204
|
var TARGET_LINE_COLOR = "rgba(33, 150, 243, 0.5)";
|
|
8203
8205
|
var AT_TARGET_GLOW = "0 0 5px 1px rgba(33, 150, 243, 0.35), 0 0 10px 3px rgba(33, 150, 243, 0.15)";
|
|
8204
8206
|
var ZONE = {
|
|
8205
|
-
building:
|
|
8207
|
+
building: t4["status-success"],
|
|
8206
8208
|
// below target ramp-up
|
|
8207
|
-
approaching:
|
|
8209
|
+
approaching: t4["status-warning"],
|
|
8208
8210
|
// nearing target
|
|
8209
|
-
target:
|
|
8211
|
+
target: t4["brand-primary"],
|
|
8210
8212
|
// exactly at target
|
|
8211
|
-
over1:
|
|
8213
|
+
over1: t4["status-error"],
|
|
8212
8214
|
// mild over-target
|
|
8213
8215
|
over2: WORKOUT_TOKENS.intensity.over2,
|
|
8214
8216
|
// moderate over-target
|
|
@@ -8377,7 +8379,7 @@ var MESO_ACCENT_GRADIENT_LIGHT = primitiveRamps.orange[300];
|
|
|
8377
8379
|
var WORKOUT_PILL_DELOAD = primitiveRamps.magenta[600];
|
|
8378
8380
|
|
|
8379
8381
|
// src/components/custom/Workout/WorkoutPill.tsx
|
|
8380
|
-
var
|
|
8382
|
+
var t5 = getSemanticColors("dark");
|
|
8381
8383
|
var statusBgColors = {
|
|
8382
8384
|
completed: "rgba(46,213,115,0.15)",
|
|
8383
8385
|
current: "rgba(255,121,0,0.15)",
|
|
@@ -8395,9 +8397,9 @@ var statusBorderStyles = {
|
|
|
8395
8397
|
deload: { borderWidth: 1, borderColor: "rgba(186,41,150,0.3)" }
|
|
8396
8398
|
};
|
|
8397
8399
|
var textColors = {
|
|
8398
|
-
completed:
|
|
8399
|
-
current:
|
|
8400
|
-
next:
|
|
8400
|
+
completed: t5["status-success"],
|
|
8401
|
+
current: t5["brand-primary"],
|
|
8402
|
+
next: t5["brand-primary"],
|
|
8401
8403
|
upcoming: "#6B7280",
|
|
8402
8404
|
missed: "rgba(209,67,67,0.7)",
|
|
8403
8405
|
deload: WORKOUT_PILL_DELOAD
|
|
@@ -8937,8 +8939,18 @@ var EXPANDED_ENCODED_PCT = 45;
|
|
|
8937
8939
|
var EXPANDED_HEIGHT = 60;
|
|
8938
8940
|
var FIXED_MAX_VELOCITY = 1.15;
|
|
8939
8941
|
var BARE_STUB_HEIGHT = 3;
|
|
8942
|
+
var HERO_HEIGHT = 220;
|
|
8943
|
+
var HERO_LABEL_HEADROOM = 20;
|
|
8944
|
+
var HERO_BAR_GAP = 8;
|
|
8945
|
+
var HERO_BAR_MAX_WIDTH = 120;
|
|
8946
|
+
var HERO_LABEL_MIN_BAR_WIDTH = 30;
|
|
8947
|
+
var HERO_BAR_RADIUS = 5;
|
|
8948
|
+
var HERO_MIN_BAR_HEIGHT = 4;
|
|
8949
|
+
var HERO_PENDING_COLOR = primitiveColors.charcoal[100];
|
|
8950
|
+
var HERO_REFERENCE_COLOR = primitiveColors.charcoal[0];
|
|
8951
|
+
var PEAK_HEADROOM = 1.06;
|
|
8940
8952
|
function scaleDenominator(scale, maxVelocity) {
|
|
8941
|
-
return scale === "fixed" ? FIXED_MAX_VELOCITY : maxVelocity *
|
|
8953
|
+
return scale === "fixed" ? FIXED_MAX_VELOCITY : maxVelocity * PEAK_HEADROOM;
|
|
8942
8954
|
}
|
|
8943
8955
|
function bareSlotHeight(slot, height, denom) {
|
|
8944
8956
|
if (slot.kind !== "rep" || denom <= 0) return BARE_STUB_HEIGHT;
|
|
@@ -8964,6 +8976,195 @@ function usePrefersReducedMotion() {
|
|
|
8964
8976
|
var ANIMATION_DURATION = 400;
|
|
8965
8977
|
var ANIMATION_EASING = reactNative.Easing.bezier(0.22, 1, 0.36, 1);
|
|
8966
8978
|
var POP_EASING = reactNative.Easing.bezier(0.34, 1.56, 0.64, 1);
|
|
8979
|
+
function useLiveRepPop(active, liveRepIndex, liveVelocity, isNewPeak) {
|
|
8980
|
+
const prefersReducedMotion = usePrefersReducedMotion();
|
|
8981
|
+
const [liveScale] = React24.useState(() => new reactNative.Animated.Value(1));
|
|
8982
|
+
React24.useEffect(() => {
|
|
8983
|
+
if (!active || liveRepIndex == null || liveVelocity == null) return;
|
|
8984
|
+
if (prefersReducedMotion) {
|
|
8985
|
+
liveScale.setValue(1);
|
|
8986
|
+
return;
|
|
8987
|
+
}
|
|
8988
|
+
if (isNewPeak) {
|
|
8989
|
+
liveScale.setValue(1);
|
|
8990
|
+
reactNative.Animated.sequence([
|
|
8991
|
+
reactNative.Animated.timing(liveScale, {
|
|
8992
|
+
toValue: 1.25,
|
|
8993
|
+
duration: 150,
|
|
8994
|
+
easing: reactNative.Easing.out(reactNative.Easing.quad),
|
|
8995
|
+
useNativeDriver: true
|
|
8996
|
+
}),
|
|
8997
|
+
reactNative.Animated.spring(liveScale, {
|
|
8998
|
+
toValue: 1,
|
|
8999
|
+
friction: 3,
|
|
9000
|
+
tension: 140,
|
|
9001
|
+
useNativeDriver: true
|
|
9002
|
+
})
|
|
9003
|
+
]).start();
|
|
9004
|
+
} else {
|
|
9005
|
+
liveScale.setValue(0.8);
|
|
9006
|
+
reactNative.Animated.timing(liveScale, {
|
|
9007
|
+
toValue: 1,
|
|
9008
|
+
duration: 300,
|
|
9009
|
+
easing: POP_EASING,
|
|
9010
|
+
useNativeDriver: true
|
|
9011
|
+
}).start();
|
|
9012
|
+
}
|
|
9013
|
+
}, [active, liveRepIndex, liveVelocity, isNewPeak, prefersReducedMotion, liveScale]);
|
|
9014
|
+
return liveScale;
|
|
9015
|
+
}
|
|
9016
|
+
function HeroVelocityChart({
|
|
9017
|
+
doneVelocities,
|
|
9018
|
+
barColorFor,
|
|
9019
|
+
scaleDenom,
|
|
9020
|
+
referenceVelocity,
|
|
9021
|
+
liveRepIndex,
|
|
9022
|
+
isNewPeak,
|
|
9023
|
+
targetReps,
|
|
9024
|
+
height,
|
|
9025
|
+
className,
|
|
9026
|
+
viewProps
|
|
9027
|
+
}) {
|
|
9028
|
+
const liveVelocity = liveRepIndex != null ? doneVelocities[liveRepIndex] : void 0;
|
|
9029
|
+
const liveScale = useLiveRepPop(true, liveRepIndex, liveVelocity, isNewPeak);
|
|
9030
|
+
const [plotW, setPlotW] = React24.useState(0);
|
|
9031
|
+
const onPlotLayout = (e) => setPlotW(e.nativeEvent.layout.width);
|
|
9032
|
+
const plotHeight = Math.max(0, height - HERO_LABEL_HEADROOM);
|
|
9033
|
+
const barHeight = (velocity) => scaleDenom > 0 ? Math.max(HERO_MIN_BAR_HEIGHT, Math.min(1, velocity / scaleDenom) * plotHeight) : HERO_MIN_BAR_HEIGHT;
|
|
9034
|
+
const pendingCount = Math.max(0, (targetReps ?? 0) - doneVelocities.length);
|
|
9035
|
+
const referencePx = referenceVelocity > 0 && scaleDenom > 0 ? Math.min(plotHeight, referenceVelocity / scaleDenom * plotHeight) : 0;
|
|
9036
|
+
const totalSlots = doneVelocities.length + pendingCount;
|
|
9037
|
+
const barWidth = plotW > 0 && totalSlots > 0 ? Math.min(HERO_BAR_MAX_WIDTH, (plotW - HERO_BAR_GAP * (totalSlots - 1)) / totalSlots) : HERO_BAR_MAX_WIDTH;
|
|
9038
|
+
const labelsCrowded = plotW > 0 && barWidth < HERO_LABEL_MIN_BAR_WIDTH;
|
|
9039
|
+
const heroGap = plotW === 0 ? HERO_BAR_GAP : barWidth < 16 ? 2 : barWidth < 28 ? 4 : HERO_BAR_GAP;
|
|
9040
|
+
const peakIndex = doneVelocities.reduce(
|
|
9041
|
+
(best, v, i) => v > doneVelocities[best] ? i : best,
|
|
9042
|
+
0
|
|
9043
|
+
);
|
|
9044
|
+
const showBarLabel = (i) => !labelsCrowded || i === peakIndex || i === liveRepIndex;
|
|
9045
|
+
const repCount = doneVelocities.length;
|
|
9046
|
+
const total = Math.max(repCount, targetReps ?? repCount);
|
|
9047
|
+
const label = referenceVelocity > 0 ? `Velocity chart, ${repCount} of ${total} reps, best ${formatVelocity(referenceVelocity)} meters per second` : `Velocity chart, ${repCount} of ${total} reps`;
|
|
9048
|
+
const { style: externalStyle, ...restProps } = viewProps;
|
|
9049
|
+
return /* @__PURE__ */ jsx(
|
|
9050
|
+
reactNative.View,
|
|
9051
|
+
{
|
|
9052
|
+
className,
|
|
9053
|
+
style: [{ height }, externalStyle],
|
|
9054
|
+
accessibilityRole: "image",
|
|
9055
|
+
accessibilityLabel: label,
|
|
9056
|
+
testID: "velocity-strip-hero",
|
|
9057
|
+
...restProps,
|
|
9058
|
+
children: /* @__PURE__ */ jsxs(
|
|
9059
|
+
reactNative.View,
|
|
9060
|
+
{
|
|
9061
|
+
onLayout: onPlotLayout,
|
|
9062
|
+
style: {
|
|
9063
|
+
flex: 1,
|
|
9064
|
+
flexDirection: "row",
|
|
9065
|
+
alignItems: "flex-end",
|
|
9066
|
+
gap: heroGap,
|
|
9067
|
+
position: "relative",
|
|
9068
|
+
borderBottomWidth: 2,
|
|
9069
|
+
borderBottomColor: HERO_PENDING_COLOR
|
|
9070
|
+
},
|
|
9071
|
+
children: [
|
|
9072
|
+
referencePx > 0 && /* @__PURE__ */ jsx(
|
|
9073
|
+
reactNative.View,
|
|
9074
|
+
{
|
|
9075
|
+
accessibilityElementsHidden: true,
|
|
9076
|
+
style: {
|
|
9077
|
+
position: "absolute",
|
|
9078
|
+
left: 0,
|
|
9079
|
+
right: 0,
|
|
9080
|
+
bottom: referencePx,
|
|
9081
|
+
borderTopWidth: 1,
|
|
9082
|
+
borderStyle: "dashed",
|
|
9083
|
+
borderColor: HERO_REFERENCE_COLOR,
|
|
9084
|
+
pointerEvents: "none"
|
|
9085
|
+
},
|
|
9086
|
+
testID: "velocity-hero-reference"
|
|
9087
|
+
}
|
|
9088
|
+
),
|
|
9089
|
+
doneVelocities.map((velocity, i) => {
|
|
9090
|
+
const isLive = liveRepIndex === i;
|
|
9091
|
+
return /* @__PURE__ */ jsxs(
|
|
9092
|
+
reactNative.View,
|
|
9093
|
+
{
|
|
9094
|
+
accessibilityElementsHidden: true,
|
|
9095
|
+
style: {
|
|
9096
|
+
flex: 1,
|
|
9097
|
+
maxWidth: HERO_BAR_MAX_WIDTH,
|
|
9098
|
+
height: "100%",
|
|
9099
|
+
alignItems: "center",
|
|
9100
|
+
justifyContent: "flex-end"
|
|
9101
|
+
},
|
|
9102
|
+
children: [
|
|
9103
|
+
showBarLabel(i) && /* @__PURE__ */ jsx(
|
|
9104
|
+
reactNative.Text,
|
|
9105
|
+
{
|
|
9106
|
+
className: "text-text-primary",
|
|
9107
|
+
style: { fontSize: 12, fontWeight: "800", marginBottom: 4 },
|
|
9108
|
+
testID: `velocity-label-${i}`,
|
|
9109
|
+
children: formatVelocity(velocity)
|
|
9110
|
+
}
|
|
9111
|
+
),
|
|
9112
|
+
/* @__PURE__ */ jsx(
|
|
9113
|
+
reactNative.Animated.View,
|
|
9114
|
+
{
|
|
9115
|
+
style: [
|
|
9116
|
+
{
|
|
9117
|
+
width: "100%",
|
|
9118
|
+
height: barHeight(velocity),
|
|
9119
|
+
borderTopLeftRadius: HERO_BAR_RADIUS,
|
|
9120
|
+
borderTopRightRadius: HERO_BAR_RADIUS,
|
|
9121
|
+
backgroundColor: barColorFor(velocity)
|
|
9122
|
+
},
|
|
9123
|
+
isLive ? { transform: [{ scale: liveScale }] } : null
|
|
9124
|
+
],
|
|
9125
|
+
testID: `velocity-bar-${i}`
|
|
9126
|
+
}
|
|
9127
|
+
)
|
|
9128
|
+
]
|
|
9129
|
+
},
|
|
9130
|
+
i
|
|
9131
|
+
);
|
|
9132
|
+
}),
|
|
9133
|
+
Array.from({ length: pendingCount }, (_, i) => /* @__PURE__ */ jsx(
|
|
9134
|
+
reactNative.View,
|
|
9135
|
+
{
|
|
9136
|
+
accessibilityElementsHidden: true,
|
|
9137
|
+
style: {
|
|
9138
|
+
flex: 1,
|
|
9139
|
+
maxWidth: HERO_BAR_MAX_WIDTH,
|
|
9140
|
+
height: "100%",
|
|
9141
|
+
alignItems: "center",
|
|
9142
|
+
justifyContent: "flex-end"
|
|
9143
|
+
},
|
|
9144
|
+
children: /* @__PURE__ */ jsx(
|
|
9145
|
+
reactNative.View,
|
|
9146
|
+
{
|
|
9147
|
+
style: {
|
|
9148
|
+
width: "100%",
|
|
9149
|
+
height: HERO_MIN_BAR_HEIGHT * 3,
|
|
9150
|
+
borderWidth: 1,
|
|
9151
|
+
borderStyle: "dashed",
|
|
9152
|
+
borderColor: HERO_PENDING_COLOR,
|
|
9153
|
+
borderTopLeftRadius: HERO_BAR_RADIUS,
|
|
9154
|
+
borderTopRightRadius: HERO_BAR_RADIUS
|
|
9155
|
+
},
|
|
9156
|
+
testID: "velocity-slot-todo"
|
|
9157
|
+
}
|
|
9158
|
+
)
|
|
9159
|
+
},
|
|
9160
|
+
`pending-${i}`
|
|
9161
|
+
))
|
|
9162
|
+
]
|
|
9163
|
+
}
|
|
9164
|
+
)
|
|
9165
|
+
}
|
|
9166
|
+
);
|
|
9167
|
+
}
|
|
8967
9168
|
function VelocityStrip({
|
|
8968
9169
|
velocities,
|
|
8969
9170
|
set,
|
|
@@ -8974,6 +9175,7 @@ function VelocityStrip({
|
|
|
8974
9175
|
onRepPress,
|
|
8975
9176
|
variant = "expanded",
|
|
8976
9177
|
height = EXPANDED_HEIGHT,
|
|
9178
|
+
targetReps,
|
|
8977
9179
|
scale = "peak",
|
|
8978
9180
|
showNumbers = true,
|
|
8979
9181
|
showInfo = true,
|
|
@@ -8999,45 +9201,17 @@ function VelocityStrip({
|
|
|
8999
9201
|
return SET_STRIP_VARIABLE_COLOR;
|
|
9000
9202
|
};
|
|
9001
9203
|
const meanZone = hasZones ? classifyBand(meanVelocity, zones)?.label ?? "" : getVelocityZoneName(meanVelocity);
|
|
9002
|
-
const prefersReducedMotion = usePrefersReducedMotion();
|
|
9003
9204
|
const [heightAnim] = React24.useState(() => new reactNative.Animated.Value(expanded ? height : 3));
|
|
9004
9205
|
const [labelOpacity] = React24.useState(() => new reactNative.Animated.Value(expanded ? 1 : 0));
|
|
9005
9206
|
const [infoOpacity] = React24.useState(() => new reactNative.Animated.Value(expanded ? 1 : 0));
|
|
9006
|
-
const [liveScale] = React24.useState(() => new reactNative.Animated.Value(1));
|
|
9007
9207
|
const liveVelocity = liveRepIndex != null ? doneVelocities[liveRepIndex] : void 0;
|
|
9008
9208
|
const isNewPeak = liveVelocity != null && maxVelocity > 0 && liveVelocity === maxVelocity;
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
if (isNewPeak) {
|
|
9016
|
-
liveScale.setValue(1);
|
|
9017
|
-
reactNative.Animated.sequence([
|
|
9018
|
-
reactNative.Animated.timing(liveScale, {
|
|
9019
|
-
toValue: 1.25,
|
|
9020
|
-
duration: 150,
|
|
9021
|
-
easing: reactNative.Easing.out(reactNative.Easing.quad),
|
|
9022
|
-
useNativeDriver: true
|
|
9023
|
-
}),
|
|
9024
|
-
reactNative.Animated.spring(liveScale, {
|
|
9025
|
-
toValue: 1,
|
|
9026
|
-
friction: 3,
|
|
9027
|
-
tension: 140,
|
|
9028
|
-
useNativeDriver: true
|
|
9029
|
-
})
|
|
9030
|
-
]).start();
|
|
9031
|
-
} else {
|
|
9032
|
-
liveScale.setValue(0.8);
|
|
9033
|
-
reactNative.Animated.timing(liveScale, {
|
|
9034
|
-
toValue: 1,
|
|
9035
|
-
duration: 300,
|
|
9036
|
-
easing: POP_EASING,
|
|
9037
|
-
useNativeDriver: true
|
|
9038
|
-
}).start();
|
|
9039
|
-
}
|
|
9040
|
-
}, [variant, framed, liveRepIndex, liveVelocity, isNewPeak, prefersReducedMotion, liveScale]);
|
|
9209
|
+
const liveScale = useLiveRepPop(
|
|
9210
|
+
variant === "expanded" && framed,
|
|
9211
|
+
liveRepIndex,
|
|
9212
|
+
liveVelocity,
|
|
9213
|
+
isNewPeak
|
|
9214
|
+
);
|
|
9041
9215
|
React24.useEffect(() => {
|
|
9042
9216
|
if (variant !== "expanded" || !framed) return;
|
|
9043
9217
|
reactNative.Animated.parallel([
|
|
@@ -9064,6 +9238,24 @@ function VelocityStrip({
|
|
|
9064
9238
|
if (set == null && velocities == null) return null;
|
|
9065
9239
|
const repCount = doneVelocities.length;
|
|
9066
9240
|
const miniLabel = set ? setAccessibilityLabel(set, repCount) : `Velocity strip, ${repCount} reps`;
|
|
9241
|
+
if (variant === "hero") {
|
|
9242
|
+
const heroHeight = height === EXPANDED_HEIGHT ? HERO_HEIGHT : height;
|
|
9243
|
+
return /* @__PURE__ */ jsx(
|
|
9244
|
+
HeroVelocityChart,
|
|
9245
|
+
{
|
|
9246
|
+
doneVelocities,
|
|
9247
|
+
barColorFor,
|
|
9248
|
+
scaleDenom,
|
|
9249
|
+
referenceVelocity: maxVelocity,
|
|
9250
|
+
liveRepIndex,
|
|
9251
|
+
isNewPeak,
|
|
9252
|
+
targetReps,
|
|
9253
|
+
height: heroHeight,
|
|
9254
|
+
className,
|
|
9255
|
+
viewProps: props
|
|
9256
|
+
}
|
|
9257
|
+
);
|
|
9258
|
+
}
|
|
9067
9259
|
if (variant === "mini") {
|
|
9068
9260
|
const { style: externalStyle, ...restProps } = props;
|
|
9069
9261
|
return /* @__PURE__ */ jsx(
|
|
@@ -9354,13 +9546,13 @@ function VelocityStrip({
|
|
|
9354
9546
|
}
|
|
9355
9547
|
return stripContent;
|
|
9356
9548
|
}
|
|
9357
|
-
var
|
|
9549
|
+
var t6 = getSemanticColors("dark");
|
|
9358
9550
|
var dotColorMap = {
|
|
9359
9551
|
untrained: "#2C2C2C",
|
|
9360
|
-
behind:
|
|
9361
|
-
ontrack:
|
|
9362
|
-
target:
|
|
9363
|
-
over:
|
|
9552
|
+
behind: t6["brand-secondary"],
|
|
9553
|
+
ontrack: t6["status-success"],
|
|
9554
|
+
target: t6["brand-primary"],
|
|
9555
|
+
over: t6["status-error"]
|
|
9364
9556
|
};
|
|
9365
9557
|
function MuscleGroupChip({
|
|
9366
9558
|
name,
|
|
@@ -9828,6 +10020,99 @@ function InputBar({
|
|
|
9828
10020
|
);
|
|
9829
10021
|
}
|
|
9830
10022
|
var BRAND_PRIMARY4 = getSemanticColors("dark")["brand-primary"];
|
|
10023
|
+
var RING_DEFAULT_SIZE = 180;
|
|
10024
|
+
function RestActions({ onAddTime, onSkip }) {
|
|
10025
|
+
return /* @__PURE__ */ jsxs(reactNative.View, { style: { flexDirection: "row", gap: 8 }, children: [
|
|
10026
|
+
/* @__PURE__ */ jsx(
|
|
10027
|
+
reactNative.Pressable,
|
|
10028
|
+
{
|
|
10029
|
+
onPress: onAddTime,
|
|
10030
|
+
style: {
|
|
10031
|
+
backgroundColor: "rgba(255,255,255,0.06)",
|
|
10032
|
+
paddingVertical: 8,
|
|
10033
|
+
paddingHorizontal: 20,
|
|
10034
|
+
borderRadius: 8
|
|
10035
|
+
},
|
|
10036
|
+
accessibilityRole: "button",
|
|
10037
|
+
accessibilityLabel: "Add 30 seconds",
|
|
10038
|
+
testID: "rest-timer-add-time",
|
|
10039
|
+
children: /* @__PURE__ */ jsx(
|
|
10040
|
+
reactNative.Text,
|
|
10041
|
+
{
|
|
10042
|
+
className: "text-text-secondary",
|
|
10043
|
+
style: { fontSize: 11, fontFamily: "Inter, sans-serif", fontWeight: "600" },
|
|
10044
|
+
children: "+30s"
|
|
10045
|
+
}
|
|
10046
|
+
)
|
|
10047
|
+
}
|
|
10048
|
+
),
|
|
10049
|
+
/* @__PURE__ */ jsx(
|
|
10050
|
+
reactNative.Pressable,
|
|
10051
|
+
{
|
|
10052
|
+
onPress: onSkip,
|
|
10053
|
+
style: {
|
|
10054
|
+
backgroundColor: "rgba(255,121,0,0.12)",
|
|
10055
|
+
paddingVertical: 8,
|
|
10056
|
+
paddingHorizontal: 20,
|
|
10057
|
+
borderRadius: 8
|
|
10058
|
+
},
|
|
10059
|
+
accessibilityRole: "button",
|
|
10060
|
+
accessibilityLabel: "Skip rest",
|
|
10061
|
+
testID: "rest-timer-skip",
|
|
10062
|
+
children: /* @__PURE__ */ jsx(
|
|
10063
|
+
reactNative.Text,
|
|
10064
|
+
{
|
|
10065
|
+
style: {
|
|
10066
|
+
fontSize: 11,
|
|
10067
|
+
fontFamily: "Inter, sans-serif",
|
|
10068
|
+
fontWeight: "600",
|
|
10069
|
+
color: BRAND_PRIMARY4
|
|
10070
|
+
},
|
|
10071
|
+
children: "Skip"
|
|
10072
|
+
}
|
|
10073
|
+
)
|
|
10074
|
+
}
|
|
10075
|
+
)
|
|
10076
|
+
] });
|
|
10077
|
+
}
|
|
10078
|
+
function RestTimerRing({
|
|
10079
|
+
totalSeconds,
|
|
10080
|
+
elapsedMs,
|
|
10081
|
+
remainingSec,
|
|
10082
|
+
done,
|
|
10083
|
+
size,
|
|
10084
|
+
nextSetInfo,
|
|
10085
|
+
displayOnly,
|
|
10086
|
+
onSkip,
|
|
10087
|
+
onAddTime
|
|
10088
|
+
}) {
|
|
10089
|
+
const a11yLabel = done ? "Rest complete, next set ready" : `Rest timer, ${Math.max(0, remainingSec)} seconds remaining`;
|
|
10090
|
+
return /* @__PURE__ */ jsxs(reactNative.View, { style: { alignItems: "center", gap: 16 }, testID: "rest-timer", children: [
|
|
10091
|
+
/* @__PURE__ */ jsx(
|
|
10092
|
+
CircularTimer,
|
|
10093
|
+
{
|
|
10094
|
+
durationMs: totalSeconds * 1e3,
|
|
10095
|
+
elapsedMs,
|
|
10096
|
+
mode: "down",
|
|
10097
|
+
size,
|
|
10098
|
+
doneLabel: "GO",
|
|
10099
|
+
doneColor: "success",
|
|
10100
|
+
accessibilityLabel: a11yLabel,
|
|
10101
|
+
controls: !displayOnly ? /* @__PURE__ */ jsx(RestActions, { onAddTime, onSkip }) : void 0,
|
|
10102
|
+
testID: "rest-timer-ring"
|
|
10103
|
+
}
|
|
10104
|
+
),
|
|
10105
|
+
nextSetInfo != null && /* @__PURE__ */ jsx(
|
|
10106
|
+
reactNative.Text,
|
|
10107
|
+
{
|
|
10108
|
+
className: "text-text-tertiary",
|
|
10109
|
+
style: { fontSize: 13, fontFamily: "Inter, sans-serif" },
|
|
10110
|
+
testID: "rest-timer-next-set",
|
|
10111
|
+
children: nextSetInfo
|
|
10112
|
+
}
|
|
10113
|
+
)
|
|
10114
|
+
] });
|
|
10115
|
+
}
|
|
9831
10116
|
function RestTimer({
|
|
9832
10117
|
totalSeconds,
|
|
9833
10118
|
elapsedMs,
|
|
@@ -9835,12 +10120,15 @@ function RestTimer({
|
|
|
9835
10120
|
onAddTime,
|
|
9836
10121
|
nextSetInfo,
|
|
9837
10122
|
visible,
|
|
9838
|
-
displayOnly = false
|
|
10123
|
+
displayOnly = false,
|
|
10124
|
+
variant = "bar",
|
|
10125
|
+
size = RING_DEFAULT_SIZE
|
|
9839
10126
|
}) {
|
|
9840
10127
|
const {
|
|
9841
10128
|
remainingMs,
|
|
9842
10129
|
progress,
|
|
9843
|
-
label: timeDisplay
|
|
10130
|
+
label: timeDisplay,
|
|
10131
|
+
done
|
|
9844
10132
|
} = useTimer({
|
|
9845
10133
|
mode: "down",
|
|
9846
10134
|
durationMs: totalSeconds * 1e3,
|
|
@@ -9849,6 +10137,22 @@ function RestTimer({
|
|
|
9849
10137
|
const remainingSec = Math.ceil(remainingMs / 1e3);
|
|
9850
10138
|
const progressPct = progress * 100;
|
|
9851
10139
|
if (!visible) return null;
|
|
10140
|
+
if (variant === "ring") {
|
|
10141
|
+
return /* @__PURE__ */ jsx(
|
|
10142
|
+
RestTimerRing,
|
|
10143
|
+
{
|
|
10144
|
+
totalSeconds,
|
|
10145
|
+
elapsedMs,
|
|
10146
|
+
remainingSec,
|
|
10147
|
+
done,
|
|
10148
|
+
size,
|
|
10149
|
+
nextSetInfo,
|
|
10150
|
+
displayOnly,
|
|
10151
|
+
onSkip,
|
|
10152
|
+
onAddTime
|
|
10153
|
+
}
|
|
10154
|
+
);
|
|
10155
|
+
}
|
|
9852
10156
|
return /* @__PURE__ */ jsxs(
|
|
9853
10157
|
reactNative.View,
|
|
9854
10158
|
{
|
|
@@ -9946,67 +10250,12 @@ function RestTimer({
|
|
|
9946
10250
|
)
|
|
9947
10251
|
}
|
|
9948
10252
|
),
|
|
9949
|
-
!displayOnly && /* @__PURE__ */
|
|
9950
|
-
/* @__PURE__ */ jsx(
|
|
9951
|
-
reactNative.Pressable,
|
|
9952
|
-
{
|
|
9953
|
-
onPress: onAddTime,
|
|
9954
|
-
style: {
|
|
9955
|
-
backgroundColor: "rgba(255,255,255,0.06)",
|
|
9956
|
-
paddingVertical: 8,
|
|
9957
|
-
paddingHorizontal: 20,
|
|
9958
|
-
borderRadius: 8
|
|
9959
|
-
},
|
|
9960
|
-
accessibilityRole: "button",
|
|
9961
|
-
accessibilityLabel: "Add 30 seconds",
|
|
9962
|
-
testID: "rest-timer-add-time",
|
|
9963
|
-
children: /* @__PURE__ */ jsx(
|
|
9964
|
-
reactNative.Text,
|
|
9965
|
-
{
|
|
9966
|
-
className: "text-text-secondary",
|
|
9967
|
-
style: {
|
|
9968
|
-
fontSize: 11,
|
|
9969
|
-
fontFamily: "Inter, sans-serif",
|
|
9970
|
-
fontWeight: "600"
|
|
9971
|
-
},
|
|
9972
|
-
children: "+30s"
|
|
9973
|
-
}
|
|
9974
|
-
)
|
|
9975
|
-
}
|
|
9976
|
-
),
|
|
9977
|
-
/* @__PURE__ */ jsx(
|
|
9978
|
-
reactNative.Pressable,
|
|
9979
|
-
{
|
|
9980
|
-
onPress: onSkip,
|
|
9981
|
-
style: {
|
|
9982
|
-
backgroundColor: "rgba(255,121,0,0.12)",
|
|
9983
|
-
paddingVertical: 8,
|
|
9984
|
-
paddingHorizontal: 20,
|
|
9985
|
-
borderRadius: 8
|
|
9986
|
-
},
|
|
9987
|
-
accessibilityRole: "button",
|
|
9988
|
-
accessibilityLabel: "Skip rest",
|
|
9989
|
-
testID: "rest-timer-skip",
|
|
9990
|
-
children: /* @__PURE__ */ jsx(
|
|
9991
|
-
reactNative.Text,
|
|
9992
|
-
{
|
|
9993
|
-
style: {
|
|
9994
|
-
fontSize: 11,
|
|
9995
|
-
fontFamily: "Inter, sans-serif",
|
|
9996
|
-
fontWeight: "600",
|
|
9997
|
-
color: BRAND_PRIMARY4
|
|
9998
|
-
},
|
|
9999
|
-
children: "Skip"
|
|
10000
|
-
}
|
|
10001
|
-
)
|
|
10002
|
-
}
|
|
10003
|
-
)
|
|
10004
|
-
] })
|
|
10253
|
+
!displayOnly && /* @__PURE__ */ jsx(RestActions, { onAddTime, onSkip })
|
|
10005
10254
|
]
|
|
10006
10255
|
}
|
|
10007
10256
|
);
|
|
10008
10257
|
}
|
|
10009
|
-
var
|
|
10258
|
+
var t7 = getSemanticColors("dark");
|
|
10010
10259
|
var TIMES = "\xD7";
|
|
10011
10260
|
var AT = "@";
|
|
10012
10261
|
function SetsRepsLoad({
|
|
@@ -10014,11 +10263,12 @@ function SetsRepsLoad({
|
|
|
10014
10263
|
reps,
|
|
10015
10264
|
load,
|
|
10016
10265
|
unit = "lb",
|
|
10266
|
+
fontSize,
|
|
10017
10267
|
className,
|
|
10018
10268
|
...props
|
|
10019
10269
|
}) {
|
|
10020
|
-
const value =
|
|
10021
|
-
const sep =
|
|
10270
|
+
const value = t7["text-primary"];
|
|
10271
|
+
const sep = t7["text-tertiary"];
|
|
10022
10272
|
return /* @__PURE__ */ jsxs(
|
|
10023
10273
|
reactNative.View,
|
|
10024
10274
|
{
|
|
@@ -10028,12 +10278,12 @@ function SetsRepsLoad({
|
|
|
10028
10278
|
testID: "sets-reps-load",
|
|
10029
10279
|
...props,
|
|
10030
10280
|
children: [
|
|
10031
|
-
/* @__PURE__ */ jsx(MetricCell, { color: value, children: sets }),
|
|
10032
|
-
/* @__PURE__ */ jsx(MetricCell, { color: sep, children: ` ${TIMES} ` }),
|
|
10033
|
-
/* @__PURE__ */ jsx(MetricCell, { color: value, children: reps }),
|
|
10034
|
-
/* @__PURE__ */ jsx(MetricCell, { color: sep, children: ` ${AT} ` }),
|
|
10035
|
-
/* @__PURE__ */ jsx(MetricCell, { color: value, children: load }),
|
|
10036
|
-
/* @__PURE__ */ jsx(MetricCell, { color: sep, children: ` ${unit}` })
|
|
10281
|
+
/* @__PURE__ */ jsx(MetricCell, { color: value, fontSize, children: sets }),
|
|
10282
|
+
/* @__PURE__ */ jsx(MetricCell, { color: sep, fontSize, children: ` ${TIMES} ` }),
|
|
10283
|
+
/* @__PURE__ */ jsx(MetricCell, { color: value, fontSize, children: reps }),
|
|
10284
|
+
/* @__PURE__ */ jsx(MetricCell, { color: sep, fontSize, children: ` ${AT} ` }),
|
|
10285
|
+
/* @__PURE__ */ jsx(MetricCell, { color: value, fontSize, children: load }),
|
|
10286
|
+
/* @__PURE__ */ jsx(MetricCell, { color: sep, fontSize, children: ` ${unit}` })
|
|
10037
10287
|
]
|
|
10038
10288
|
}
|
|
10039
10289
|
);
|
|
@@ -10131,14 +10381,14 @@ function ScheduleTiles({ when, now, gap = 1, ...props }) {
|
|
|
10131
10381
|
)
|
|
10132
10382
|
] });
|
|
10133
10383
|
}
|
|
10134
|
-
var
|
|
10384
|
+
var t8 = getSemanticColors("dark");
|
|
10135
10385
|
var INDICATOR_CONFIG = {
|
|
10136
|
-
imbalance: { Icon: ScaleIcon, color:
|
|
10137
|
-
overshoot: { Icon: AlertTriangleIcon, color:
|
|
10138
|
-
"velocity-loss": { Icon: TrendingDownIcon, color:
|
|
10139
|
-
"missed-reps": { Icon: CircleSlashIcon, color:
|
|
10140
|
-
pr: { Icon: AwardIcon, color:
|
|
10141
|
-
info: { Icon: InfoIcon, color:
|
|
10386
|
+
imbalance: { Icon: ScaleIcon, color: t8["status-error"], label: "Left/right imbalance" },
|
|
10387
|
+
overshoot: { Icon: AlertTriangleIcon, color: t8["status-error"], label: "Load overshoot" },
|
|
10388
|
+
"velocity-loss": { Icon: TrendingDownIcon, color: t8["status-warning"], label: "Velocity loss" },
|
|
10389
|
+
"missed-reps": { Icon: CircleSlashIcon, color: t8["status-warning"], label: "Missed reps" },
|
|
10390
|
+
pr: { Icon: AwardIcon, color: t8["status-success"], label: "Personal record" },
|
|
10391
|
+
info: { Icon: InfoIcon, color: t8["status-info"], label: "More info" }
|
|
10142
10392
|
};
|
|
10143
10393
|
var INDICATOR_PRECEDENCE = [
|
|
10144
10394
|
"imbalance",
|
|
@@ -10613,7 +10863,7 @@ function ExerciseCard({
|
|
|
10613
10863
|
if (upcoming) return /* @__PURE__ */ jsx(UpcomingCard, { ...rest, onToggle });
|
|
10614
10864
|
return isExpanded ? /* @__PURE__ */ jsx(ExpandedCard, { ...rest, onToggle }) : /* @__PURE__ */ jsx(CollapsedCard, { ...rest, onToggle });
|
|
10615
10865
|
}
|
|
10616
|
-
var
|
|
10866
|
+
var t9 = getSemanticColors("dark");
|
|
10617
10867
|
var RAISED = primitiveColors.charcoal[400];
|
|
10618
10868
|
var BAR_HEIGHT = 9;
|
|
10619
10869
|
var BAR_GAP = 3;
|
|
@@ -10635,7 +10885,7 @@ function SessionHeader({
|
|
|
10635
10885
|
const hasPace = !upcoming && budgetMs != null && elapsedMs != null;
|
|
10636
10886
|
const target = hasPace ? elapsedMs / budgetMs : void 0;
|
|
10637
10887
|
const setsLabel = upcoming ? `${totalSets} sets` : `${Math.floor(setsDone)}/${totalSets} sets`;
|
|
10638
|
-
const setsLabelColor = upcoming ?
|
|
10888
|
+
const setsLabelColor = upcoming ? t9["text-secondary"] : paceToneColor(paceTone(totalSets > 0 ? setsDone / totalSets : 0, target));
|
|
10639
10889
|
return /* @__PURE__ */ jsxs(
|
|
10640
10890
|
reactNative.View,
|
|
10641
10891
|
{
|
|
@@ -10663,7 +10913,7 @@ function SessionHeader({
|
|
|
10663
10913
|
lineHeight: 18,
|
|
10664
10914
|
fontWeight: "700",
|
|
10665
10915
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
10666
|
-
color:
|
|
10916
|
+
color: t9["text-primary"],
|
|
10667
10917
|
marginBottom: 10
|
|
10668
10918
|
},
|
|
10669
10919
|
testID: "session-rail-title",
|
|
@@ -11058,10 +11308,10 @@ function WeekRow({
|
|
|
11058
11308
|
}
|
|
11059
11309
|
);
|
|
11060
11310
|
}
|
|
11061
|
-
var
|
|
11311
|
+
var t10 = getSemanticColors("dark");
|
|
11062
11312
|
var COLORS = {
|
|
11063
|
-
statusSuccess:
|
|
11064
|
-
brandPrimary:
|
|
11313
|
+
statusSuccess: t10["status-success"],
|
|
11314
|
+
brandPrimary: t10["brand-primary"],
|
|
11065
11315
|
borderDefault: "#1F1F1F",
|
|
11066
11316
|
brandPrimarySubtle: "rgba(255,121,0,0.06)"
|
|
11067
11317
|
};
|
|
@@ -11545,12 +11795,12 @@ function PrHistoryModal({
|
|
|
11545
11795
|
}
|
|
11546
11796
|
);
|
|
11547
11797
|
}
|
|
11548
|
-
var
|
|
11549
|
-
var BRAND_PRIMARY9 =
|
|
11798
|
+
var t11 = getSemanticColors("dark");
|
|
11799
|
+
var BRAND_PRIMARY9 = t11["brand-primary"];
|
|
11550
11800
|
var BRAND_PRIMARY_SUBTLE = "rgba(255,121,0,0.12)";
|
|
11551
|
-
var
|
|
11552
|
-
var
|
|
11553
|
-
var STATUS_ERROR2 =
|
|
11801
|
+
var STATUS_SUCCESS2 = t11["status-success"];
|
|
11802
|
+
var STATUS_WARNING2 = t11["status-warning"];
|
|
11803
|
+
var STATUS_ERROR2 = t11["status-error"];
|
|
11554
11804
|
var EMOJI_SETS = {
|
|
11555
11805
|
sleep: ["\u{1F634}", "\u{1F610}", "\u{1F642}", "\u{1F60A}", "\u{1F929}"],
|
|
11556
11806
|
soreness: ["\u{1F635}", "\u{1F623}", "\u{1F610}", "\u{1F642}", "\u{1F4AA}"],
|
|
@@ -11560,8 +11810,8 @@ var EMOJI_SETS = {
|
|
|
11560
11810
|
var DEFAULT_EMOJI_SET = ["\u{1F61E}", "\u{1F615}", "\u{1F610}", "\u{1F642}", "\u{1F604}"];
|
|
11561
11811
|
function scoreColor(score) {
|
|
11562
11812
|
if (score < 40) return STATUS_ERROR2;
|
|
11563
|
-
if (score < 70) return
|
|
11564
|
-
return
|
|
11813
|
+
if (score < 70) return STATUS_WARNING2;
|
|
11814
|
+
return STATUS_SUCCESS2;
|
|
11565
11815
|
}
|
|
11566
11816
|
var WARMUP_BADGE = {
|
|
11567
11817
|
good: { color: "success", label: "Good" },
|
|
@@ -11740,13 +11990,13 @@ function ReadinessCheck({
|
|
|
11740
11990
|
)
|
|
11741
11991
|
] }) });
|
|
11742
11992
|
}
|
|
11743
|
-
var
|
|
11744
|
-
var BRAND_PRIMARY10 =
|
|
11993
|
+
var t12 = getSemanticColors("dark");
|
|
11994
|
+
var BRAND_PRIMARY10 = t12["brand-primary"];
|
|
11745
11995
|
var BRAND_PRIMARY_DARK2 = MESO_ACCENT_GRADIENT_DARK;
|
|
11746
11996
|
var BRAND_PRIMARY_LIGHT2 = MESO_ACCENT_GRADIENT_LIGHT;
|
|
11747
|
-
var SUCCESS =
|
|
11748
|
-
var WARNING =
|
|
11749
|
-
var ERROR =
|
|
11997
|
+
var SUCCESS = t12["status-success"];
|
|
11998
|
+
var WARNING = t12["status-warning"];
|
|
11999
|
+
var ERROR = t12["status-error"];
|
|
11750
12000
|
var ACCENT_STOPS2 = [BRAND_PRIMARY_DARK2, BRAND_PRIMARY10, BRAND_PRIMARY_LIGHT2];
|
|
11751
12001
|
var CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor("surface-elevated")} 0%, ${resolveColor("surface-raised")} 100%)`;
|
|
11752
12002
|
var GAUGE_GRADIENT = "linear-gradient(90deg, rgba(46,213,115,0.25) 0%, rgba(249,180,21,0.25) 50%, rgba(209,67,67,0.25) 100%)";
|
|
@@ -12106,9 +12356,9 @@ function MesoStatusCard({
|
|
|
12106
12356
|
var sem = getSemanticColors("dark");
|
|
12107
12357
|
var BRAND_PRIMARY11 = sem["brand-primary"];
|
|
12108
12358
|
var PROJECTION_LINE_COLOR = resolveColor("text-tertiary");
|
|
12109
|
-
var
|
|
12359
|
+
var STATUS_SUCCESS3 = sem["status-success"];
|
|
12110
12360
|
var STATUS_ERROR3 = sem["status-error"];
|
|
12111
|
-
var
|
|
12361
|
+
var STATUS_WARNING3 = sem["status-warning"];
|
|
12112
12362
|
var GRID_LINE = "rgba(255,255,255,0.06)";
|
|
12113
12363
|
var SUCCESS_PILL_BG = "rgba(46,213,115,0.10)";
|
|
12114
12364
|
var SUCCESS_PILL_BORDER = "rgba(46,213,115,0.20)";
|
|
@@ -12117,8 +12367,8 @@ var ERROR_PILL_BORDER = "rgba(209,67,67,0.20)";
|
|
|
12117
12367
|
var PLOT_LEFT = 26;
|
|
12118
12368
|
var TOOLTIP_WIDTH = 124;
|
|
12119
12369
|
function timeOf(dateStr) {
|
|
12120
|
-
const
|
|
12121
|
-
return Number.isNaN(
|
|
12370
|
+
const t17 = Date.parse(dateStr);
|
|
12371
|
+
return Number.isNaN(t17) ? 0 : t17;
|
|
12122
12372
|
}
|
|
12123
12373
|
function formatValue(value) {
|
|
12124
12374
|
return `${Math.round(value)}`;
|
|
@@ -12414,7 +12664,7 @@ function StrengthTrendChart({
|
|
|
12414
12664
|
left: c.x - 7,
|
|
12415
12665
|
top: c.y - 20,
|
|
12416
12666
|
fontSize: 12,
|
|
12417
|
-
color:
|
|
12667
|
+
color: STATUS_WARNING3
|
|
12418
12668
|
},
|
|
12419
12669
|
children: "\u2605"
|
|
12420
12670
|
},
|
|
@@ -12507,7 +12757,7 @@ function StrengthTrendChart({
|
|
|
12507
12757
|
marginTop: 1,
|
|
12508
12758
|
fontSize: 10,
|
|
12509
12759
|
fontFamily: "Inter, sans-serif",
|
|
12510
|
-
color: selectedCoord.point.e1rm - geometry.actual[selected - 1].point.e1rm >= 0 ?
|
|
12760
|
+
color: selectedCoord.point.e1rm - geometry.actual[selected - 1].point.e1rm >= 0 ? STATUS_SUCCESS3 : STATUS_ERROR3
|
|
12511
12761
|
},
|
|
12512
12762
|
children: `${selectedCoord.point.e1rm - geometry.actual[selected - 1].point.e1rm >= 0 ? "+" : "-"}${Math.abs(
|
|
12513
12763
|
selectedCoord.point.e1rm - geometry.actual[selected - 1].point.e1rm
|
|
@@ -12563,7 +12813,7 @@ function StrengthTrendChart({
|
|
|
12563
12813
|
fontSize: 11,
|
|
12564
12814
|
fontFamily: "Inter, sans-serif",
|
|
12565
12815
|
fontWeight: "600",
|
|
12566
|
-
color: trend.positive ?
|
|
12816
|
+
color: trend.positive ? STATUS_SUCCESS3 : STATUS_ERROR3
|
|
12567
12817
|
},
|
|
12568
12818
|
children: trendText
|
|
12569
12819
|
}
|
|
@@ -12597,7 +12847,7 @@ function StrengthTrendChart({
|
|
|
12597
12847
|
/* @__PURE__ */ jsx(reactNative.Text, { className: "text-text-secondary", style: { fontSize: 10, fontFamily: "Inter, sans-serif" }, children: "Projected" })
|
|
12598
12848
|
] }),
|
|
12599
12849
|
/* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-center", style: { gap: 5 }, children: [
|
|
12600
|
-
/* @__PURE__ */ jsx(reactNative.Text, { style: { fontSize: 12, color:
|
|
12850
|
+
/* @__PURE__ */ jsx(reactNative.Text, { style: { fontSize: 12, color: STATUS_WARNING3 }, children: "\u2605" }),
|
|
12601
12851
|
/* @__PURE__ */ jsx(reactNative.Text, { className: "text-text-secondary", style: { fontSize: 10, fontFamily: "Inter, sans-serif" }, children: "PR" })
|
|
12602
12852
|
] })
|
|
12603
12853
|
]
|
|
@@ -12607,10 +12857,10 @@ function StrengthTrendChart({
|
|
|
12607
12857
|
}
|
|
12608
12858
|
);
|
|
12609
12859
|
}
|
|
12610
|
-
var
|
|
12611
|
-
var
|
|
12612
|
-
var
|
|
12613
|
-
var STATUS_INFO =
|
|
12860
|
+
var t13 = getSemanticColors("dark");
|
|
12861
|
+
var STATUS_SUCCESS4 = t13["status-success"];
|
|
12862
|
+
var STATUS_WARNING4 = t13["status-warning"];
|
|
12863
|
+
var STATUS_INFO = t13["status-info"];
|
|
12614
12864
|
var DOT_BORDER = "#F3F4F6";
|
|
12615
12865
|
var BAND_FILL = "rgba(46,213,115,0.1)";
|
|
12616
12866
|
var BAND_EDGE = "rgba(46,213,115,0.45)";
|
|
@@ -12622,8 +12872,8 @@ var PADDING_BOTTOM = 16;
|
|
|
12622
12872
|
var COLUMN_STEP = 4;
|
|
12623
12873
|
var DOT_SIZE = 8;
|
|
12624
12874
|
var DOT_COLORS = {
|
|
12625
|
-
within:
|
|
12626
|
-
above:
|
|
12875
|
+
within: STATUS_SUCCESS4,
|
|
12876
|
+
above: STATUS_WARNING4,
|
|
12627
12877
|
below: STATUS_INFO
|
|
12628
12878
|
};
|
|
12629
12879
|
var STATUS_PHRASES = {
|
|
@@ -12653,8 +12903,8 @@ function interpEdge(pixels, x, key) {
|
|
|
12653
12903
|
const a = pixels[i];
|
|
12654
12904
|
const b = pixels[i + 1];
|
|
12655
12905
|
if (x >= a.x && x <= b.x) {
|
|
12656
|
-
const
|
|
12657
|
-
return a[key] +
|
|
12906
|
+
const t17 = b.x === a.x ? 0 : (x - a.x) / (b.x - a.x);
|
|
12907
|
+
return a[key] + t17 * (b[key] - a[key]);
|
|
12658
12908
|
}
|
|
12659
12909
|
}
|
|
12660
12910
|
return pixels[pixels.length - 1][key];
|
|
@@ -12848,8 +13098,8 @@ function CapacityBandChart({
|
|
|
12848
13098
|
projection && /* @__PURE__ */ jsxs(reactNative.View, { testID: "capacity-band-chart-projection", children: [
|
|
12849
13099
|
renderColumns(buildColumns2(trainingPixels, COLUMN_STEP), PROJECTION_FILL, "capacity-band-chart-projection-fill"),
|
|
12850
13100
|
renderColumns(buildColumns2(restPixels, COLUMN_STEP), PROJECTION_FILL, "capacity-band-chart-projection-fill"),
|
|
12851
|
-
renderEdges(buildEdges(trainingPixels, "yHigh"),
|
|
12852
|
-
renderEdges(buildEdges(trainingPixels, "yLow"),
|
|
13101
|
+
renderEdges(buildEdges(trainingPixels, "yHigh"), STATUS_SUCCESS4, true, "capacity-band-chart-projection-training"),
|
|
13102
|
+
renderEdges(buildEdges(trainingPixels, "yLow"), STATUS_SUCCESS4, true, "capacity-band-chart-projection-training"),
|
|
12853
13103
|
renderEdges(buildEdges(restPixels, "yHigh"), STATUS_INFO, true, "capacity-band-chart-projection-rest"),
|
|
12854
13104
|
renderEdges(buildEdges(restPixels, "yLow"), STATUS_INFO, true, "capacity-band-chart-projection-rest"),
|
|
12855
13105
|
/* @__PURE__ */ jsx(
|
|
@@ -12861,7 +13111,7 @@ function CapacityBandChart({
|
|
|
12861
13111
|
top: trainingPixels[trainingPixels.length - 1]?.yHigh - 12,
|
|
12862
13112
|
fontSize: 9,
|
|
12863
13113
|
fontFamily: "Inter, sans-serif",
|
|
12864
|
-
color:
|
|
13114
|
+
color: STATUS_SUCCESS4
|
|
12865
13115
|
},
|
|
12866
13116
|
testID: "capacity-band-chart-projection-training-label",
|
|
12867
13117
|
children: "Training"
|
|
@@ -12984,16 +13234,43 @@ function CapacityBandChart({
|
|
|
12984
13234
|
}
|
|
12985
13235
|
);
|
|
12986
13236
|
}
|
|
12987
|
-
var
|
|
13237
|
+
var t14 = getSemanticColors("dark");
|
|
12988
13238
|
function glowShadow(color) {
|
|
12989
13239
|
return `0 0 5px 1px ${alpha(color, 0.3)}, 0 0 10px 3px ${alpha(color, 0.12)}`;
|
|
12990
13240
|
}
|
|
12991
13241
|
var DEFAULT_TRACK_COLOR = primitiveColors.charcoal[200];
|
|
12992
13242
|
var DEFAULT_MARKER_COLOR2 = primitiveColors.white;
|
|
12993
|
-
var TICK_COLOR =
|
|
12994
|
-
var
|
|
12995
|
-
|
|
12996
|
-
|
|
13243
|
+
var TICK_COLOR = t14["text-tertiary"];
|
|
13244
|
+
var ZONE_SIZES = {
|
|
13245
|
+
default: {
|
|
13246
|
+
trackHeight: 14,
|
|
13247
|
+
needleOverhang: 6,
|
|
13248
|
+
needleWidth: 4,
|
|
13249
|
+
tickLineNormal: 1.5,
|
|
13250
|
+
tickLineEmphasized: 2,
|
|
13251
|
+
tickLineHeightPad: 4,
|
|
13252
|
+
tickLineTopPad: 2,
|
|
13253
|
+
labelRowHeight: 16,
|
|
13254
|
+
labelMarginTop: 5,
|
|
13255
|
+
tickFont: 9,
|
|
13256
|
+
tickLetterSpacing: 0.5,
|
|
13257
|
+
tickCellWidth: 28
|
|
13258
|
+
},
|
|
13259
|
+
wall: {
|
|
13260
|
+
trackHeight: 24,
|
|
13261
|
+
needleOverhang: 9,
|
|
13262
|
+
needleWidth: 7,
|
|
13263
|
+
tickLineNormal: 2.5,
|
|
13264
|
+
tickLineEmphasized: 3.5,
|
|
13265
|
+
tickLineHeightPad: 6,
|
|
13266
|
+
tickLineTopPad: 3,
|
|
13267
|
+
labelRowHeight: 24,
|
|
13268
|
+
labelMarginTop: 8,
|
|
13269
|
+
tickFont: 14,
|
|
13270
|
+
tickLetterSpacing: 0.5,
|
|
13271
|
+
tickCellWidth: 48
|
|
13272
|
+
}
|
|
13273
|
+
};
|
|
12997
13274
|
function fraction(value, min, max) {
|
|
12998
13275
|
if (max <= min) return 0;
|
|
12999
13276
|
return Math.max(0, Math.min(1, (value - min) / (max - min)));
|
|
@@ -13008,14 +13285,24 @@ function ZoneTrack({
|
|
|
13008
13285
|
marker = null,
|
|
13009
13286
|
ticks,
|
|
13010
13287
|
band = null,
|
|
13011
|
-
|
|
13012
|
-
|
|
13288
|
+
size = "default",
|
|
13289
|
+
trackHeight: trackHeightProp,
|
|
13290
|
+
needleOverhang: needleOverhangProp,
|
|
13013
13291
|
trackColor = DEFAULT_TRACK_COLOR,
|
|
13014
13292
|
className,
|
|
13015
13293
|
style,
|
|
13016
13294
|
accessibilityLabel: accessibilityLabel2,
|
|
13017
13295
|
...props
|
|
13018
13296
|
}) {
|
|
13297
|
+
const s = ZONE_SIZES[size];
|
|
13298
|
+
const trackHeight = trackHeightProp ?? s.trackHeight;
|
|
13299
|
+
const needleOverhang = needleOverhangProp ?? s.needleOverhang;
|
|
13300
|
+
const [trackW, setTrackW] = React24.useState(0);
|
|
13301
|
+
const onTrackLayout = (e) => setTrackW(e.nativeEvent.layout.width);
|
|
13302
|
+
const tickCount = ticks?.length ?? 0;
|
|
13303
|
+
const tickSpacing = trackW > 0 && tickCount > 0 ? trackW / tickCount : Infinity;
|
|
13304
|
+
const tickStep = tickSpacing < s.tickCellWidth ? Math.ceil(s.tickCellWidth / tickSpacing) : 1;
|
|
13305
|
+
const showTickLabel = (i, emphasized) => tickStep <= 1 || i === 0 || i === tickCount - 1 || i % tickStep === 0 || emphasized;
|
|
13019
13306
|
const isNeedle = marker?.type === "needle";
|
|
13020
13307
|
const markerHeight = isNeedle ? trackHeight + needleOverhang * 2 : trackHeight;
|
|
13021
13308
|
const markerFrac = marker != null ? fraction(marker.value, min, max) : 0;
|
|
@@ -13034,6 +13321,7 @@ function ZoneTrack({
|
|
|
13034
13321
|
accessibilityValue: marker != null ? { min, max, now: marker.value } : { min, max, now: min },
|
|
13035
13322
|
accessibilityLabel: accessibilityLabel2 ?? `Zone track: ${marker?.value ?? min}`,
|
|
13036
13323
|
testID: "zone-track",
|
|
13324
|
+
onLayout: onTrackLayout,
|
|
13037
13325
|
...props,
|
|
13038
13326
|
children: [
|
|
13039
13327
|
/* @__PURE__ */ jsxs(reactNative.View, { style: { position: "relative", height: markerHeight }, children: [
|
|
@@ -13125,18 +13413,18 @@ function ZoneTrack({
|
|
|
13125
13413
|
position: "absolute",
|
|
13126
13414
|
top: 0,
|
|
13127
13415
|
left: pct(markerFrac),
|
|
13128
|
-
width:
|
|
13416
|
+
width: s.needleWidth,
|
|
13129
13417
|
height: markerHeight,
|
|
13130
|
-
borderRadius:
|
|
13418
|
+
borderRadius: s.needleWidth / 2,
|
|
13131
13419
|
backgroundColor: marker.color ?? DEFAULT_MARKER_COLOR2,
|
|
13132
|
-
transform: [{ translateX: -
|
|
13420
|
+
transform: [{ translateX: -s.needleWidth / 2 }]
|
|
13133
13421
|
}
|
|
13134
13422
|
}
|
|
13135
13423
|
),
|
|
13136
13424
|
ticks?.map((tick, i) => {
|
|
13137
13425
|
const emphasized = tick.emphasized === true;
|
|
13138
|
-
const lineColor = tick.color ?? (emphasized ?
|
|
13139
|
-
const lineWidth = emphasized ?
|
|
13426
|
+
const lineColor = tick.color ?? (emphasized ? t14["brand-primary"] : TICK_COLOR);
|
|
13427
|
+
const lineWidth = emphasized ? s.tickLineEmphasized : s.tickLineNormal;
|
|
13140
13428
|
return /* @__PURE__ */ jsx(
|
|
13141
13429
|
reactNative.View,
|
|
13142
13430
|
{
|
|
@@ -13144,10 +13432,10 @@ function ZoneTrack({
|
|
|
13144
13432
|
accessibilityElementsHidden: true,
|
|
13145
13433
|
style: {
|
|
13146
13434
|
position: "absolute",
|
|
13147
|
-
top: (markerHeight - trackHeight) / 2 -
|
|
13435
|
+
top: (markerHeight - trackHeight) / 2 - s.tickLineTopPad,
|
|
13148
13436
|
left: pct(fraction(tick.value, min, max)),
|
|
13149
13437
|
width: lineWidth,
|
|
13150
|
-
height: trackHeight +
|
|
13438
|
+
height: trackHeight + s.tickLineHeightPad,
|
|
13151
13439
|
borderRadius: lineWidth / 2,
|
|
13152
13440
|
backgroundColor: lineColor,
|
|
13153
13441
|
transform: [{ translateX: -lineWidth / 2 }],
|
|
@@ -13158,40 +13446,47 @@ function ZoneTrack({
|
|
|
13158
13446
|
);
|
|
13159
13447
|
})
|
|
13160
13448
|
] }),
|
|
13161
|
-
ticks != null && ticks.length > 0 && /* @__PURE__ */ jsx(
|
|
13162
|
-
|
|
13163
|
-
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13167
|
-
|
|
13168
|
-
|
|
13169
|
-
|
|
13170
|
-
|
|
13171
|
-
|
|
13172
|
-
|
|
13173
|
-
|
|
13174
|
-
|
|
13175
|
-
|
|
13176
|
-
|
|
13177
|
-
|
|
13178
|
-
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13449
|
+
ticks != null && ticks.length > 0 && /* @__PURE__ */ jsx(
|
|
13450
|
+
reactNative.View,
|
|
13451
|
+
{
|
|
13452
|
+
style: { position: "relative", height: s.labelRowHeight, marginTop: s.labelMarginTop },
|
|
13453
|
+
children: ticks.map((tick, i) => {
|
|
13454
|
+
if (tick.label == null) return null;
|
|
13455
|
+
const emphasized = tick.emphasized === true;
|
|
13456
|
+
if (!showTickLabel(i, emphasized)) return null;
|
|
13457
|
+
const labelColor = tick.color ?? (emphasized ? t14["brand-primary"] : TICK_COLOR);
|
|
13458
|
+
const labelNode = /* @__PURE__ */ jsx(
|
|
13459
|
+
reactNative.Text,
|
|
13460
|
+
{
|
|
13461
|
+
testID: "zone-track-tick-label",
|
|
13462
|
+
style: {
|
|
13463
|
+
fontSize: s.tickFont,
|
|
13464
|
+
letterSpacing: s.tickLetterSpacing,
|
|
13465
|
+
color: labelColor,
|
|
13466
|
+
fontFamily: "monospace",
|
|
13467
|
+
fontWeight: emphasized ? "700" : "400"
|
|
13468
|
+
},
|
|
13469
|
+
children: tick.label
|
|
13470
|
+
}
|
|
13471
|
+
);
|
|
13472
|
+
return /* @__PURE__ */ jsx(
|
|
13473
|
+
reactNative.View,
|
|
13474
|
+
{
|
|
13475
|
+
testID: "zone-track-tick",
|
|
13476
|
+
style: {
|
|
13477
|
+
position: "absolute",
|
|
13478
|
+
left: pct(fraction(tick.value, min, max)),
|
|
13479
|
+
transform: [{ translateX: -s.tickCellWidth / 2 }],
|
|
13480
|
+
width: s.tickCellWidth,
|
|
13481
|
+
alignItems: "center"
|
|
13482
|
+
},
|
|
13483
|
+
children: tick.tooltip != null ? /* @__PURE__ */ jsx(Tooltip, { label: tick.tooltip, placement: "top", children: labelNode }) : labelNode
|
|
13484
|
+
},
|
|
13485
|
+
`label-${i}`
|
|
13486
|
+
);
|
|
13487
|
+
})
|
|
13488
|
+
}
|
|
13489
|
+
)
|
|
13195
13490
|
]
|
|
13196
13491
|
}
|
|
13197
13492
|
);
|
|
@@ -13209,7 +13504,8 @@ function FatigueMeter({
|
|
|
13209
13504
|
thresholds = DEFAULT_THRESHOLDS,
|
|
13210
13505
|
zoneColors = DEFAULT_ZONE_COLORS,
|
|
13211
13506
|
labels = DEFAULT_LABELS,
|
|
13212
|
-
|
|
13507
|
+
size = "default",
|
|
13508
|
+
trackHeight,
|
|
13213
13509
|
needleColor,
|
|
13214
13510
|
className,
|
|
13215
13511
|
...props
|
|
@@ -13230,6 +13526,7 @@ function FatigueMeter({
|
|
|
13230
13526
|
zones,
|
|
13231
13527
|
min: 0,
|
|
13232
13528
|
max,
|
|
13529
|
+
size,
|
|
13233
13530
|
trackHeight,
|
|
13234
13531
|
ticks,
|
|
13235
13532
|
marker: { type: "needle", value, color: needleColor },
|
|
@@ -13241,7 +13538,7 @@ function FatigueMeter({
|
|
|
13241
13538
|
}
|
|
13242
13539
|
var HEAT = WORKOUT_TOKENS.heatmap;
|
|
13243
13540
|
var NEUTRAL_TRACK = primitiveColors.charcoal[200];
|
|
13244
|
-
var
|
|
13541
|
+
var MONO2 = "monospace";
|
|
13245
13542
|
var HEAT_BY_ZONE = {
|
|
13246
13543
|
under: HEAT.under,
|
|
13247
13544
|
maintenance: HEAT.maintenance,
|
|
@@ -13300,7 +13597,7 @@ function VolumeLandmarkBar({
|
|
|
13300
13597
|
reactNative.Text,
|
|
13301
13598
|
{
|
|
13302
13599
|
testID: "volume-landmark-pct",
|
|
13303
|
-
style: { fontSize: 14, fontWeight: "700", fontFamily:
|
|
13600
|
+
style: { fontSize: 14, fontWeight: "700", fontFamily: MONO2, color: fillColor },
|
|
13304
13601
|
children: [
|
|
13305
13602
|
pct2,
|
|
13306
13603
|
"%"
|
|
@@ -13343,7 +13640,7 @@ function VolumeLandmarkBar({
|
|
|
13343
13640
|
}
|
|
13344
13641
|
);
|
|
13345
13642
|
}
|
|
13346
|
-
var
|
|
13643
|
+
var t15 = getSemanticColors("dark");
|
|
13347
13644
|
var statusToken = {
|
|
13348
13645
|
productive: "status-success",
|
|
13349
13646
|
threshold: "status-warning",
|
|
@@ -13360,7 +13657,7 @@ var defaultLabel = {
|
|
|
13360
13657
|
stop: "Stop"
|
|
13361
13658
|
};
|
|
13362
13659
|
function statusPillColor(status) {
|
|
13363
|
-
return
|
|
13660
|
+
return t15[statusToken[status]];
|
|
13364
13661
|
}
|
|
13365
13662
|
function StatusPill2({ status, label, className, style, ...props }) {
|
|
13366
13663
|
const color = statusPillColor(status);
|
|
@@ -13393,7 +13690,7 @@ function StatusPill2({ status, label, className, style, ...props }) {
|
|
|
13393
13690
|
}
|
|
13394
13691
|
);
|
|
13395
13692
|
}
|
|
13396
|
-
var
|
|
13693
|
+
var t16 = getSemanticColors("dark");
|
|
13397
13694
|
var categoryToken = {
|
|
13398
13695
|
productive: null,
|
|
13399
13696
|
threshold: "status-warning",
|
|
@@ -13406,7 +13703,7 @@ var floodOpacity = {
|
|
|
13406
13703
|
};
|
|
13407
13704
|
function liveAuraColor(category) {
|
|
13408
13705
|
const token = categoryToken[category];
|
|
13409
|
-
return token ?
|
|
13706
|
+
return token ? t16[token] : null;
|
|
13410
13707
|
}
|
|
13411
13708
|
function LiveAuraFrame({
|
|
13412
13709
|
category,
|
|
@@ -13435,9 +13732,9 @@ function LiveAuraFrame({
|
|
|
13435
13732
|
position: "relative",
|
|
13436
13733
|
overflow: "hidden",
|
|
13437
13734
|
borderRadius: 10,
|
|
13438
|
-
backgroundColor:
|
|
13735
|
+
backgroundColor: t16["background-base"],
|
|
13439
13736
|
borderWidth: 1,
|
|
13440
|
-
borderColor:
|
|
13737
|
+
borderColor: t16["border-default"]
|
|
13441
13738
|
},
|
|
13442
13739
|
style
|
|
13443
13740
|
],
|
|
@@ -13664,28 +13961,28 @@ function Scatter({
|
|
|
13664
13961
|
testID: "scatter-canvas",
|
|
13665
13962
|
style: { position: "absolute", top: 0, left: 0, width, height, overflow: "hidden" },
|
|
13666
13963
|
children: [
|
|
13667
|
-
ticksOf(yd, TICK_COUNT).map((
|
|
13668
|
-
const y = toY(
|
|
13964
|
+
ticksOf(yd, TICK_COUNT).map((t17, i) => {
|
|
13965
|
+
const y = toY(t17);
|
|
13669
13966
|
return /* @__PURE__ */ jsx(
|
|
13670
13967
|
reactNative.View,
|
|
13671
13968
|
{
|
|
13672
13969
|
accessibilityElementsHidden: true,
|
|
13673
13970
|
testID: "scatter-gridline-y",
|
|
13674
13971
|
style: { position: "absolute", left: PLOT_LEFT2, width: innerW, top: y, height: 1, backgroundColor: GRID_LINE2 },
|
|
13675
|
-
children: /* @__PURE__ */ jsx(reactNative.Text, { className: "text-[9px] text-text-tertiary", style: { position: "absolute", left: -PLOT_LEFT2, top: -6, width: PLOT_LEFT2 - 6, textAlign: "right" }, children: formatTick(
|
|
13972
|
+
children: /* @__PURE__ */ jsx(reactNative.Text, { className: "text-[9px] text-text-tertiary", style: { position: "absolute", left: -PLOT_LEFT2, top: -6, width: PLOT_LEFT2 - 6, textAlign: "right" }, children: formatTick(t17) })
|
|
13676
13973
|
},
|
|
13677
13974
|
`y-${i}`
|
|
13678
13975
|
);
|
|
13679
13976
|
}),
|
|
13680
|
-
ticksOf(xd, TICK_COUNT).map((
|
|
13681
|
-
const x = toX(
|
|
13977
|
+
ticksOf(xd, TICK_COUNT).map((t17, i) => {
|
|
13978
|
+
const x = toX(t17);
|
|
13682
13979
|
return /* @__PURE__ */ jsx(
|
|
13683
13980
|
reactNative.View,
|
|
13684
13981
|
{
|
|
13685
13982
|
accessibilityElementsHidden: true,
|
|
13686
13983
|
testID: "scatter-gridline-x",
|
|
13687
13984
|
style: { position: "absolute", top: PLOT_TOP, height: innerH, left: x, width: 1, backgroundColor: GRID_LINE2 },
|
|
13688
|
-
children: /* @__PURE__ */ jsx(reactNative.Text, { className: "text-[9px] text-text-tertiary", style: { position: "absolute", top: innerH + 4, left: -16, width: 32, textAlign: "center" }, children: formatTick(
|
|
13985
|
+
children: /* @__PURE__ */ jsx(reactNative.Text, { className: "text-[9px] text-text-tertiary", style: { position: "absolute", top: innerH + 4, left: -16, width: 32, textAlign: "center" }, children: formatTick(t17) })
|
|
13689
13986
|
},
|
|
13690
13987
|
`x-${i}`
|
|
13691
13988
|
);
|
|
@@ -13746,14 +14043,14 @@ function Scatter({
|
|
|
13746
14043
|
] });
|
|
13747
14044
|
}
|
|
13748
14045
|
var sem2 = getSemanticColors("dark");
|
|
13749
|
-
var
|
|
13750
|
-
var
|
|
14046
|
+
var STATUS_SUCCESS5 = sem2["status-success"];
|
|
14047
|
+
var STATUS_WARNING5 = sem2["status-warning"];
|
|
13751
14048
|
var STATUS_ERROR4 = sem2["status-error"];
|
|
13752
14049
|
var TRACK = "rgba(255,255,255,0.08)";
|
|
13753
14050
|
var DEFAULT_THRESHOLDS2 = [
|
|
13754
14051
|
{ value: 0, color: STATUS_ERROR4 },
|
|
13755
|
-
{ value: 60, color:
|
|
13756
|
-
{ value: 80, color:
|
|
14052
|
+
{ value: 60, color: STATUS_WARNING5 },
|
|
14053
|
+
{ value: 80, color: STATUS_SUCCESS5 }
|
|
13757
14054
|
];
|
|
13758
14055
|
var ARC_START = 135;
|
|
13759
14056
|
var ARC_SWEEP = 270;
|
|
@@ -13768,7 +14065,7 @@ function formatValue2(v) {
|
|
|
13768
14065
|
function bandColor2(fraction2, bands, min, max) {
|
|
13769
14066
|
const value = min + fraction2 * (max - min);
|
|
13770
14067
|
const sorted = [...bands].sort((a, b) => a.value - b.value);
|
|
13771
|
-
let color = sorted[0]?.color ??
|
|
14068
|
+
let color = sorted[0]?.color ?? STATUS_SUCCESS5;
|
|
13772
14069
|
for (const band of sorted) {
|
|
13773
14070
|
if (value >= band.value) color = band.color;
|
|
13774
14071
|
}
|
|
@@ -13820,23 +14117,23 @@ function Gauge2({
|
|
|
13820
14117
|
testID: "gauge",
|
|
13821
14118
|
...props,
|
|
13822
14119
|
children: [
|
|
13823
|
-
ticks.map((
|
|
14120
|
+
ticks.map((t17) => /* @__PURE__ */ jsx(
|
|
13824
14121
|
reactNative.View,
|
|
13825
14122
|
{
|
|
13826
14123
|
accessibilityElementsHidden: true,
|
|
13827
14124
|
testID: "gauge-segment",
|
|
13828
14125
|
style: {
|
|
13829
14126
|
position: "absolute",
|
|
13830
|
-
left:
|
|
13831
|
-
top:
|
|
14127
|
+
left: t17.left - tickThickness / 2,
|
|
14128
|
+
top: t17.top - tickLength / 2,
|
|
13832
14129
|
width: tickThickness,
|
|
13833
14130
|
height: tickLength,
|
|
13834
14131
|
borderRadius: tickThickness / 2,
|
|
13835
|
-
backgroundColor:
|
|
13836
|
-
transform: [{ rotate:
|
|
14132
|
+
backgroundColor: t17.color,
|
|
14133
|
+
transform: [{ rotate: t17.rotate }]
|
|
13837
14134
|
}
|
|
13838
14135
|
},
|
|
13839
|
-
|
|
14136
|
+
t17.key
|
|
13840
14137
|
)),
|
|
13841
14138
|
/* @__PURE__ */ jsxs(reactNative.View, { style: { position: "absolute", top: 0, left: 0, width: size, height: size }, className: "items-center justify-center", children: [
|
|
13842
14139
|
/* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-baseline gap-0.5", children: [
|
|
@@ -14296,6 +14593,7 @@ exports.CheckboxGroup = CheckboxGroup;
|
|
|
14296
14593
|
exports.Chip = Chip;
|
|
14297
14594
|
exports.CircleSlashIcon = CircleSlashIcon;
|
|
14298
14595
|
exports.CircularProgress = CircularProgress;
|
|
14596
|
+
exports.CircularTimer = CircularTimer;
|
|
14299
14597
|
exports.Collapse = Collapse;
|
|
14300
14598
|
exports.CollapseButton = CollapseButton;
|
|
14301
14599
|
exports.CollapseContent = CollapseContent;
|
|
@@ -14434,7 +14732,6 @@ exports.SupersetWrapper = SupersetWrapper;
|
|
|
14434
14732
|
exports.Surface = Surface;
|
|
14435
14733
|
exports.SvgIcon = SvgIcon;
|
|
14436
14734
|
exports.Switch = Switch;
|
|
14437
|
-
exports.TEMPO_PACING = TEMPO_PACING;
|
|
14438
14735
|
exports.Tab = Tab;
|
|
14439
14736
|
exports.TabList = TabList;
|
|
14440
14737
|
exports.TabPanel = TabPanel;
|
|
@@ -14447,7 +14744,6 @@ exports.TableHeaderCell = TableHeaderCell;
|
|
|
14447
14744
|
exports.TablePagination = TablePagination;
|
|
14448
14745
|
exports.TableRow = TableRow;
|
|
14449
14746
|
exports.Tabs = Tabs;
|
|
14450
|
-
exports.TempoBar = TempoBar;
|
|
14451
14747
|
exports.TempoDisplay = TempoDisplay;
|
|
14452
14748
|
exports.Tile = Tile;
|
|
14453
14749
|
exports.TimerReadout = TimerReadout;
|
|
@@ -14513,8 +14809,6 @@ exports.getLuminance = getLuminance;
|
|
|
14513
14809
|
exports.getResultColor = getResultColor;
|
|
14514
14810
|
exports.getSemanticColors = getSemanticColors;
|
|
14515
14811
|
exports.getStatusColor = getStatusColor;
|
|
14516
|
-
exports.getTempoFillPct = getTempoFillPct;
|
|
14517
|
-
exports.getTempoPacingState = getTempoPacingState;
|
|
14518
14812
|
exports.getThemeCSSVars = getThemeCSSVars;
|
|
14519
14813
|
exports.getValidatedElevation = getValidatedElevation;
|
|
14520
14814
|
exports.getVelocityZoneColor = getVelocityZoneColor;
|