@tastic/hud 0.7.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -8
- package/dist/SkiaGate.d.mts +13 -0
- package/dist/SkiaGate.d.ts +13 -0
- package/dist/SkiaGate.js +45 -0
- package/dist/SkiaGate.mjs +6 -0
- package/dist/chunk-XEOFR236.mjs +21 -0
- package/dist/index.d.mts +20 -17
- package/dist/index.d.ts +20 -17
- package/dist/index.js +250 -214
- package/dist/index.mjs +166 -145
- package/package.json +13 -6
- package/src/BaseSettingsDialog.tsx +9 -6
- package/src/BaseStatsScreen.tsx +54 -93
- package/src/ConfirmDialog.tsx +29 -3
- package/src/InlineColorPicker.tsx +10 -4
- package/src/SectionedDropdown.tsx +17 -3
- package/src/SkiaGate.tsx +45 -0
- package/src/SkiaGate.web.tsx +9 -0
- package/src/TriggerGaugeHost.tsx +12 -20
- package/src/index.ts +8 -7
- package/src/useAutoAlign.ts +58 -16
package/dist/index.js
CHANGED
|
@@ -28,22 +28,22 @@ __export(TriggerGauge_exports, {
|
|
|
28
28
|
function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, dashWidth, startDeg = DEFAULT_START_DEG, endDeg = startDeg }) {
|
|
29
29
|
const totalDurationMs = MOUNT_DURATION_MS + Math.max(0, segments - 1) * MOUNT_STAGGER_MS;
|
|
30
30
|
const mountProgress = (0, import_react_native_reanimated.useSharedValue)(0);
|
|
31
|
-
(0,
|
|
31
|
+
(0, import_react4.useLayoutEffect)(() => {
|
|
32
32
|
mountProgress.value = (0, import_react_native_reanimated.withTiming)(1, { duration: totalDurationMs, easing: import_react_native_reanimated.Easing.out(import_react_native_reanimated.Easing.cubic) });
|
|
33
33
|
}, []);
|
|
34
34
|
const rawSweepDeg = ((endDeg - startDeg) % 360 + 360) % 360;
|
|
35
35
|
const totalSweepDeg = rawSweepDeg === 0 ? 360 : rawSweepDeg;
|
|
36
36
|
const step = segments > 0 ? totalSweepDeg / segments : 0;
|
|
37
|
-
const centerDeg = (0,
|
|
37
|
+
const centerDeg = (0, import_react4.useCallback)((i) => startDeg + (i + 0.5) * step, [startDeg, step]);
|
|
38
38
|
const singleSelect = litIndices.length === 1;
|
|
39
39
|
const angleDeg = (0, import_react_native_reanimated.useSharedValue)(centerDeg(litIndices[0] ?? 0));
|
|
40
40
|
const litIndicesKey = [...litIndices].sort((a, b) => a - b).join(",");
|
|
41
|
-
const [transitionFrom, setTransitionFrom] = (0,
|
|
41
|
+
const [transitionFrom, setTransitionFrom] = (0, import_react4.useState)(litIndices);
|
|
42
42
|
const transitionFromKey = [...transitionFrom].sort((a, b) => a - b).join(",");
|
|
43
|
-
const lastKeyRef = (0,
|
|
44
|
-
const lastIndicesRef = (0,
|
|
43
|
+
const lastKeyRef = (0, import_react4.useRef)(litIndicesKey);
|
|
44
|
+
const lastIndicesRef = (0, import_react4.useRef)(litIndices);
|
|
45
45
|
const selectionProgress = (0, import_react_native_reanimated.useSharedValue)(1);
|
|
46
|
-
(0,
|
|
46
|
+
(0, import_react4.useLayoutEffect)(() => {
|
|
47
47
|
if (litIndicesKey !== lastKeyRef.current) {
|
|
48
48
|
if (singleSelect && lastIndicesRef.current.length === 1) {
|
|
49
49
|
angleDeg.value = (0, import_react_native_reanimated.withTiming)(centerDeg(litIndices[0]), { duration: SELECTION_TRANSITION_DURATION_MS, easing: import_react_native_reanimated.Easing.out(import_react_native_reanimated.Easing.cubic) });
|
|
@@ -72,7 +72,7 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
|
|
|
72
72
|
if (mountProgress.value < 1) {
|
|
73
73
|
const startFrac = i * MOUNT_STAGGER_MS / totalDurationMs;
|
|
74
74
|
const endFrac = startFrac + MOUNT_DURATION_MS / totalDurationMs;
|
|
75
|
-
local = (0,
|
|
75
|
+
local = (0, import_core4.clamp)((mountProgress.value - startFrac) / (endFrac - startFrac), 0, 1);
|
|
76
76
|
}
|
|
77
77
|
const sweep = dashAngleDeg * local;
|
|
78
78
|
if (sweep <= 0) continue;
|
|
@@ -96,7 +96,7 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
|
|
|
96
96
|
if (!isLitNow) continue;
|
|
97
97
|
const startFrac = i * MOUNT_STAGGER_MS / totalDurationMs;
|
|
98
98
|
const endFrac = startFrac + MOUNT_DURATION_MS / totalDurationMs;
|
|
99
|
-
local = (0,
|
|
99
|
+
local = (0, import_core4.clamp)((mountProgress.value - startFrac) / (endFrac - startFrac), 0, 1);
|
|
100
100
|
} else if (isLitNow === wasLit) {
|
|
101
101
|
local = 1;
|
|
102
102
|
} else if (isLitNow) {
|
|
@@ -120,21 +120,21 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
|
|
|
120
120
|
height: canvasSize,
|
|
121
121
|
width: canvasSize
|
|
122
122
|
};
|
|
123
|
-
return /* @__PURE__ */ (0,
|
|
124
|
-
/* @__PURE__ */ (0,
|
|
125
|
-
/* @__PURE__ */ (0,
|
|
123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native8.View, { style: [styles7.container, gaugeSizeStyle], pointerEvents: "none", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native_skia.Canvas, { style: canvasSizeStyle, children: [
|
|
124
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_skia.Path, { path: unlitPath, style: "stroke", strokeWidth: UNLIT_THICKNESS, strokeCap: "round", color: mutedColor, opacity: 0.35 }),
|
|
125
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_skia.Path, { path: litPath, style: "stroke", strokeWidth: LIT_THICKNESS, strokeCap: "round", color: accentColor, opacity: 1 })
|
|
126
126
|
] }) });
|
|
127
127
|
}
|
|
128
|
-
var import_react_native_skia,
|
|
128
|
+
var import_react_native_skia, import_core4, import_react4, import_react_native8, import_react_native_reanimated, import_jsx_runtime8, UNLIT_THICKNESS, LIT_THICKNESS, DASH_GAP_PX, ARC_GAP, DEFAULT_START_DEG, MIN_DASH_ANGLE_DEG, MOUNT_DURATION_MS, MOUNT_STAGGER_MS, SELECTION_TRANSITION_DURATION_MS, styles7;
|
|
129
129
|
var init_TriggerGauge = __esm({
|
|
130
130
|
"src/TriggerGauge.tsx"() {
|
|
131
131
|
"use strict";
|
|
132
132
|
import_react_native_skia = require("@shopify/react-native-skia");
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
import_core4 = require("@tastic/core");
|
|
134
|
+
import_react4 = require("react");
|
|
135
135
|
import_react_native8 = require("react-native");
|
|
136
136
|
import_react_native_reanimated = require("react-native-reanimated");
|
|
137
|
-
|
|
137
|
+
import_jsx_runtime8 = require("react/jsx-runtime");
|
|
138
138
|
UNLIT_THICKNESS = 3;
|
|
139
139
|
LIT_THICKNESS = 7;
|
|
140
140
|
DASH_GAP_PX = 9;
|
|
@@ -175,6 +175,7 @@ __export(index_exports, {
|
|
|
175
175
|
ReadyButton: () => ReadyButton,
|
|
176
176
|
SectionedDropdown: () => SectionedDropdown,
|
|
177
177
|
SharedActionBand: () => SharedActionBand,
|
|
178
|
+
SkiaGate: () => SkiaGate,
|
|
178
179
|
StatRow: () => StatRow,
|
|
179
180
|
StatSection: () => StatSection,
|
|
180
181
|
TriggerGaugeHost: () => TriggerGaugeHost,
|
|
@@ -265,8 +266,10 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
265
266
|
function SettingIcon({ source, color, containerColor }) {
|
|
266
267
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native2.View, { style: [styles2.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.Icon, { source, size: 18, color }) });
|
|
267
268
|
}
|
|
268
|
-
function BaseSettingsDialog({ visible, onDismiss, rotation
|
|
269
|
+
function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, children }) {
|
|
269
270
|
const { dark, colors } = (0, import_auto_paper2.useAutoPaperTheme)();
|
|
271
|
+
const ambientRotation = (0, import_core.useRotation)();
|
|
272
|
+
const rotation = rotationOverride ?? ambientRotation;
|
|
270
273
|
const isTouchPrimary = (0, import_core.useIsTouchPrimaryDevice)();
|
|
271
274
|
const { settings: hapticSettings, set: setHapticSettings } = (0, import_feedback_press.useHapticSettings)();
|
|
272
275
|
const { settings: soundSettings, set: setSoundSettings } = (0, import_feedback_press.useSoundSettings)();
|
|
@@ -456,136 +459,56 @@ var styles2 = import_react_native2.StyleSheet.create({
|
|
|
456
459
|
});
|
|
457
460
|
|
|
458
461
|
// src/BaseStatsScreen.tsx
|
|
462
|
+
var import_auto_paper4 = require("@rific/auto-paper");
|
|
463
|
+
var import_feedback_press3 = require("@rific/feedback-press");
|
|
464
|
+
var import_core2 = require("@tastic/core");
|
|
465
|
+
var import_react2 = require("react");
|
|
466
|
+
var import_react_native4 = require("react-native");
|
|
467
|
+
var import_react_native_paper4 = require("react-native-paper");
|
|
468
|
+
|
|
469
|
+
// src/ConfirmDialog.tsx
|
|
459
470
|
var import_auto_paper3 = require("@rific/auto-paper");
|
|
460
471
|
var import_feedback_press2 = require("@rific/feedback-press");
|
|
461
|
-
var import_react2 = require("react");
|
|
462
472
|
var import_react_native3 = require("react-native");
|
|
463
473
|
var import_react_native_paper3 = require("react-native-paper");
|
|
464
474
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
465
|
-
function BaseStatsScreen({ rotation = 0, title = "Achievements", titleVariant = "headlineSmall", onBack, insets, onReset, resetLabel = "Reset All Stats", resetConfirmTitle = "Reset Everything?", resetConfirmBody = "This permanently erases all stats and achievements. This cannot be undone.", fg: fgOverride, bg: bgOverride, cardBg: cardBgOverride, accentColor: accentColorOverride, children }) {
|
|
466
|
-
const { dark, colors } = (0, import_auto_paper3.useAutoPaperTheme)();
|
|
467
|
-
const [confirmResetVisible, setConfirmResetVisible] = (0, import_react2.useState)(false);
|
|
468
|
-
const showReset = !!onReset;
|
|
469
|
-
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
470
|
-
const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
|
|
471
|
-
const cardBg = cardBgOverride ?? (dark ? "#111111" : "#F2F2F2");
|
|
472
|
-
const cardBorder = dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)";
|
|
473
|
-
const accentColor = accentColorOverride ?? colors.secondary;
|
|
474
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: [styles3.container, { backgroundColor: bg }], children: [
|
|
475
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: [styles3.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
|
|
476
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_feedback_press2.IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
|
|
477
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Text, { variant: titleVariant, style: [styles3.title, { color: fg }], children: title })
|
|
478
|
-
] }),
|
|
479
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.ScrollView, { style: styles3.scrollView, contentContainerStyle: [styles3.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
|
|
480
|
-
children,
|
|
481
|
-
showReset && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_feedback_press2.Button, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.secondary, textColor: colors.onSecondary, style: styles3.resetButton, children: resetLabel })
|
|
482
|
-
] }),
|
|
483
|
-
confirmResetVisible && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [styles3.overlay, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: [styles3.overlayCard, { backgroundColor: cardBg, borderColor: cardBorder }], children: [
|
|
484
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Icon, { source: "alert-outline", size: 64, color: accentColor }),
|
|
485
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Text, { variant: "headlineLarge", style: [styles3.overlayTitle, { color: accentColor }], children: resetConfirmTitle }),
|
|
486
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Text, { variant: "bodyLarge", style: [styles3.overlayBody, { color: fg }], children: resetConfirmBody }),
|
|
487
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_feedback_press2.Button, { mode: "contained", onPress: () => setConfirmResetVisible(false), style: styles3.overlayButton, children: "Cancel" }),
|
|
488
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
489
|
-
import_feedback_press2.Button,
|
|
490
|
-
{
|
|
491
|
-
mode: "contained",
|
|
492
|
-
onPress: () => {
|
|
493
|
-
onReset?.();
|
|
494
|
-
setConfirmResetVisible(false);
|
|
495
|
-
},
|
|
496
|
-
style: styles3.overlayButton,
|
|
497
|
-
buttonColor: colors.secondary,
|
|
498
|
-
textColor: colors.onSecondary,
|
|
499
|
-
children: "Reset"
|
|
500
|
-
}
|
|
501
|
-
)
|
|
502
|
-
] }) }) })
|
|
503
|
-
] });
|
|
504
|
-
}
|
|
505
|
-
var styles3 = import_react_native3.StyleSheet.create({
|
|
506
|
-
container: {
|
|
507
|
-
flex: 1
|
|
508
|
-
},
|
|
509
|
-
content: {
|
|
510
|
-
gap: 12,
|
|
511
|
-
paddingHorizontal: 20
|
|
512
|
-
},
|
|
513
|
-
header: {
|
|
514
|
-
alignItems: "center",
|
|
515
|
-
flexDirection: "row",
|
|
516
|
-
gap: 4,
|
|
517
|
-
paddingBottom: 8
|
|
518
|
-
},
|
|
519
|
-
// Same overlay shape BaseSettingsDialog's own info overlay uses (backdrop + centered card),
|
|
520
|
-
// rotated in place the same way rather than via Portal-root transform for the same reason — see
|
|
521
|
-
// that component's own identical styles for the full rationale.
|
|
522
|
-
overlay: {
|
|
523
|
-
alignItems: "center",
|
|
524
|
-
backgroundColor: "rgba(0,0,0,0.72)",
|
|
525
|
-
bottom: 0,
|
|
526
|
-
justifyContent: "center",
|
|
527
|
-
left: 0,
|
|
528
|
-
position: "absolute",
|
|
529
|
-
right: 0,
|
|
530
|
-
top: 0
|
|
531
|
-
},
|
|
532
|
-
overlayBody: { textAlign: "center" },
|
|
533
|
-
overlayButton: { width: 160 },
|
|
534
|
-
overlayCard: {
|
|
535
|
-
alignItems: "center",
|
|
536
|
-
borderRadius: 20,
|
|
537
|
-
borderWidth: 1,
|
|
538
|
-
gap: 16,
|
|
539
|
-
maxWidth: 360,
|
|
540
|
-
padding: 32
|
|
541
|
-
},
|
|
542
|
-
overlayTitle: { fontWeight: "bold", marginBottom: -8 },
|
|
543
|
-
resetButton: {
|
|
544
|
-
marginTop: 16
|
|
545
|
-
},
|
|
546
|
-
// Bounds the ScrollView to the space `container`'s flex:1 actually gives it — without this, a
|
|
547
|
-
// ScrollView with only a contentContainerStyle isn't reliably height-constrained on native (it
|
|
548
|
-
// can render at its full unclipped content height instead of the screen's), which leaves the
|
|
549
|
-
// header's back button touch target unreliable underneath it.
|
|
550
|
-
scrollView: {
|
|
551
|
-
flex: 1
|
|
552
|
-
},
|
|
553
|
-
title: {
|
|
554
|
-
flexShrink: 1,
|
|
555
|
-
fontWeight: "bold"
|
|
556
|
-
}
|
|
557
|
-
});
|
|
558
|
-
|
|
559
|
-
// src/ConfirmDialog.tsx
|
|
560
|
-
var import_auto_paper4 = require("@rific/auto-paper");
|
|
561
|
-
var import_feedback_press3 = require("@rific/feedback-press");
|
|
562
|
-
var import_react_native4 = require("react-native");
|
|
563
|
-
var import_react_native_paper4 = require("react-native-paper");
|
|
564
|
-
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
565
475
|
function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
|
|
566
|
-
const { dark, colors } = (0,
|
|
476
|
+
const { dark, colors } = (0, import_auto_paper3.useAutoPaperTheme)();
|
|
567
477
|
if (!visible) return null;
|
|
568
478
|
const fg = dark ? "#FFFFFF" : "#000000";
|
|
569
479
|
const cardBg = dark ? "#111111" : "#F2F2F2";
|
|
570
480
|
const cardBorder = dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)";
|
|
571
481
|
const accent = destructive ? colors.danger : colors.primary;
|
|
572
482
|
const onAccent = destructive ? colors.onDanger : colors.onPrimary;
|
|
573
|
-
return /* @__PURE__ */ (0,
|
|
574
|
-
/* @__PURE__ */ (0,
|
|
575
|
-
/* @__PURE__ */ (0,
|
|
576
|
-
/* @__PURE__ */ (0,
|
|
577
|
-
/* @__PURE__ */ (0,
|
|
578
|
-
/* @__PURE__ */ (0,
|
|
579
|
-
/* @__PURE__ */ (0,
|
|
483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: styles3.overlay, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: [styles3.card, { backgroundColor: cardBg, borderColor: cardBorder }, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: [
|
|
484
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Icon, { source: icon, size: 64, color: accent }),
|
|
485
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Text, { variant: "headlineLarge", style: [styles3.title, { color: accent }], children: title }),
|
|
486
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Text, { variant: "bodyLarge", style: [styles3.body, { color: fg }], children: message }),
|
|
487
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: styles3.actions, children: [
|
|
488
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_feedback_press2.Button, { mode: "outlined", onPress: onCancel, style: styles3.actionButton, children: cancelLabel }),
|
|
489
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_feedback_press2.Button, { mode: "contained", onPress: onConfirm, style: styles3.actionButton, buttonColor: accent, textColor: onAccent, children: confirmLabel })
|
|
580
490
|
] })
|
|
581
491
|
] }) }) });
|
|
582
492
|
}
|
|
583
|
-
var
|
|
493
|
+
var styles3 = import_react_native3.StyleSheet.create({
|
|
494
|
+
// flexBasis (not flex: 1's own 0%) is each button's real floor: whenever both fit side by side,
|
|
495
|
+
// flexGrow still splits any leftover width evenly beyond that floor, same visual result as the
|
|
496
|
+
// old flex: 1 on a roomy screen - but a button can never be squeezed narrower than 128, only
|
|
497
|
+
// wrap to its own row instead (see actions' flexWrap below). react-native-paper's Button
|
|
498
|
+
// hardcodes numberOfLines={1} on its label with no override, so a button squeezed under its
|
|
499
|
+
// label's natural width silently ellipsizes ("Cancel" -> "Can...") instead of wrapping - assumed
|
|
500
|
+
// fixable by just giving the row more width, until confirmed live that these two-word labels
|
|
501
|
+
// (Cancel/Reset/New Game) can still lose the truncation fight even with the extra room card's own
|
|
502
|
+
// width fix below provides, on a narrow enough screen. flexBasis is the real fix: past a certain
|
|
503
|
+
// width there's no side-by-side arrangement that fits both buttons at their natural label size,
|
|
504
|
+
// so the layout has to give (stack) rather than the label (truncate).
|
|
584
505
|
actionButton: {
|
|
585
|
-
|
|
506
|
+
flexBasis: 128,
|
|
507
|
+
flexGrow: 1
|
|
586
508
|
},
|
|
587
509
|
actions: {
|
|
588
510
|
flexDirection: "row",
|
|
511
|
+
flexWrap: "wrap",
|
|
589
512
|
gap: 12,
|
|
590
513
|
width: "100%"
|
|
591
514
|
},
|
|
@@ -598,7 +521,12 @@ var styles4 = import_react_native4.StyleSheet.create({
|
|
|
598
521
|
borderWidth: 1,
|
|
599
522
|
gap: 16,
|
|
600
523
|
maxWidth: 360,
|
|
601
|
-
padding: 32
|
|
524
|
+
padding: 32,
|
|
525
|
+
// Claims its full allowance instead of just maxWidth alone, which only caps how wide the card
|
|
526
|
+
// is allowed to get - without an explicit width, a flex-centered child sizes to its own content
|
|
527
|
+
// instead of stretching, so the card (and therefore actions below) can end up narrower than the
|
|
528
|
+
// screen actually has room for, needlessly forcing the action row to wrap sooner than it has to.
|
|
529
|
+
width: "100%"
|
|
602
530
|
},
|
|
603
531
|
overlay: {
|
|
604
532
|
alignItems: "center",
|
|
@@ -606,22 +534,99 @@ var styles4 = import_react_native4.StyleSheet.create({
|
|
|
606
534
|
bottom: 0,
|
|
607
535
|
justifyContent: "center",
|
|
608
536
|
left: 0,
|
|
537
|
+
// Gives the card room to breathe from the screen edges now that it reliably stretches to fill
|
|
538
|
+
// its full width allowance (see card's own width comment) - without this, width: '100%' would
|
|
539
|
+
// run the card edge-to-edge on a screen narrower than maxWidth's own 360.
|
|
540
|
+
paddingHorizontal: 24,
|
|
609
541
|
position: "absolute",
|
|
610
542
|
right: 0,
|
|
611
543
|
top: 0
|
|
612
544
|
},
|
|
545
|
+
// textAlign is load-bearing, not decorative, once `title` wraps to more than one line - centered
|
|
546
|
+
// within card's own alignItems: 'center' only centers the Text's block as a whole; each wrapped
|
|
547
|
+
// line inside that block still defaults to left-aligned without this.
|
|
548
|
+
title: {
|
|
549
|
+
fontWeight: "bold",
|
|
550
|
+
textAlign: "center"
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
// src/BaseStatsScreen.tsx
|
|
555
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
556
|
+
function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", titleVariant = "headlineSmall", onBack, insets, onReset, resetLabel = "Reset All Stats", resetConfirmTitle = "Reset Everything?", resetConfirmBody = "This permanently erases all stats and achievements. This cannot be undone.", fg: fgOverride, bg: bgOverride, children }) {
|
|
557
|
+
const { dark, colors } = (0, import_auto_paper4.useAutoPaperTheme)();
|
|
558
|
+
const ambientRotation = (0, import_core2.useRotation)();
|
|
559
|
+
const rotation = rotationOverride ?? ambientRotation;
|
|
560
|
+
const [confirmResetVisible, setConfirmResetVisible] = (0, import_react2.useState)(false);
|
|
561
|
+
const showReset = !!onReset;
|
|
562
|
+
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
563
|
+
const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
|
|
564
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native4.View, { style: [styles4.container, { backgroundColor: bg }], children: [
|
|
565
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native4.View, { style: [styles4.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
|
|
566
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_feedback_press3.IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
|
|
567
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_paper4.Text, { variant: titleVariant, style: [styles4.title, { color: fg }], children: title })
|
|
568
|
+
] }),
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native4.ScrollView, { style: styles4.scrollView, contentContainerStyle: [styles4.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
|
|
570
|
+
children,
|
|
571
|
+
showReset && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_feedback_press3.Button, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles4.resetButton, children: resetLabel })
|
|
572
|
+
] }),
|
|
573
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
574
|
+
ConfirmDialog,
|
|
575
|
+
{
|
|
576
|
+
visible: confirmResetVisible,
|
|
577
|
+
title: resetConfirmTitle,
|
|
578
|
+
message: resetConfirmBody,
|
|
579
|
+
confirmLabel: "Reset",
|
|
580
|
+
cancelLabel: "Cancel",
|
|
581
|
+
icon: "alert-outline",
|
|
582
|
+
destructive: true,
|
|
583
|
+
rotation,
|
|
584
|
+
onCancel: () => setConfirmResetVisible(false),
|
|
585
|
+
onConfirm: () => {
|
|
586
|
+
onReset?.();
|
|
587
|
+
setConfirmResetVisible(false);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
)
|
|
591
|
+
] });
|
|
592
|
+
}
|
|
593
|
+
var styles4 = import_react_native4.StyleSheet.create({
|
|
594
|
+
container: {
|
|
595
|
+
flex: 1
|
|
596
|
+
},
|
|
597
|
+
content: {
|
|
598
|
+
gap: 12,
|
|
599
|
+
paddingHorizontal: 20
|
|
600
|
+
},
|
|
601
|
+
header: {
|
|
602
|
+
alignItems: "center",
|
|
603
|
+
flexDirection: "row",
|
|
604
|
+
gap: 4,
|
|
605
|
+
paddingBottom: 8
|
|
606
|
+
},
|
|
607
|
+
resetButton: {
|
|
608
|
+
marginTop: 16
|
|
609
|
+
},
|
|
610
|
+
// Bounds the ScrollView to the space `container`'s flex:1 actually gives it — without this, a
|
|
611
|
+
// ScrollView with only a contentContainerStyle isn't reliably height-constrained on native (it
|
|
612
|
+
// can render at its full unclipped content height instead of the screen's), which leaves the
|
|
613
|
+
// header's back button touch target unreliable underneath it.
|
|
614
|
+
scrollView: {
|
|
615
|
+
flex: 1
|
|
616
|
+
},
|
|
613
617
|
title: {
|
|
618
|
+
flexShrink: 1,
|
|
614
619
|
fontWeight: "bold"
|
|
615
620
|
}
|
|
616
621
|
});
|
|
617
622
|
|
|
618
623
|
// src/ContentGutter.tsx
|
|
619
|
-
var
|
|
624
|
+
var import_core3 = require("@tastic/core");
|
|
620
625
|
var import_react_native5 = require("react-native");
|
|
621
626
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
622
627
|
function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
|
|
623
628
|
const { width: windowWidth } = (0, import_react_native5.useWindowDimensions)();
|
|
624
|
-
const { contentWidth, gutterWidth } = (0,
|
|
629
|
+
const { contentWidth, gutterWidth } = (0, import_core3.computeContentBounds)(windowWidth, maxContentWidth ?? Infinity);
|
|
625
630
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: [styles5.row, style], children: [
|
|
626
631
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.View, { style: [styles5.gutter, { width: gutterWidth }], children: leftGutter }),
|
|
627
632
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.View, { style: { width: contentWidth }, children }),
|
|
@@ -640,12 +645,13 @@ var styles5 = import_react_native5.StyleSheet.create({
|
|
|
640
645
|
});
|
|
641
646
|
|
|
642
647
|
// src/ControlSchemePicker.tsx
|
|
643
|
-
var
|
|
648
|
+
var import_core6 = require("@tastic/core");
|
|
644
649
|
var import_react_native11 = require("react-native");
|
|
645
650
|
|
|
646
651
|
// src/SectionedDropdown.tsx
|
|
647
652
|
var import_auto_paper5 = require("@rific/auto-paper");
|
|
648
653
|
var import_feedback_press4 = require("@rific/feedback-press");
|
|
654
|
+
var import_core5 = require("@tastic/core");
|
|
649
655
|
var import_react_native10 = require("react-native");
|
|
650
656
|
var import_react_native_paper5 = require("react-native-paper");
|
|
651
657
|
|
|
@@ -719,26 +725,45 @@ var styles6 = import_react_native7.StyleSheet.create({
|
|
|
719
725
|
}
|
|
720
726
|
});
|
|
721
727
|
|
|
722
|
-
// src/
|
|
723
|
-
var
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
+
// src/SkiaGate.tsx
|
|
729
|
+
var import_react3 = require("react");
|
|
730
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
731
|
+
function SkiaGate({ getComponent, componentProps, fallback = null }) {
|
|
732
|
+
const [Component, setComponent] = (0, import_react3.useState)(null);
|
|
733
|
+
(0, import_react3.useEffect)(() => {
|
|
734
|
+
let cancelled = false;
|
|
735
|
+
getComponent().then((mod) => {
|
|
736
|
+
if (!cancelled) setComponent(() => mod.default);
|
|
737
|
+
});
|
|
738
|
+
return () => {
|
|
739
|
+
cancelled = true;
|
|
740
|
+
};
|
|
741
|
+
}, [getComponent]);
|
|
742
|
+
if (!Component) return fallback;
|
|
743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Component, { ...componentProps });
|
|
728
744
|
}
|
|
729
745
|
|
|
730
746
|
// src/TriggerGaugeHost.tsx
|
|
731
|
-
var
|
|
732
|
-
var
|
|
747
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
748
|
+
var getTriggerGauge = () => Promise.resolve().then(() => (init_TriggerGauge(), TriggerGauge_exports)).then((mod) => ({ default: mod.TriggerGauge }));
|
|
733
749
|
function TriggerGaugeHost(props) {
|
|
734
|
-
return /* @__PURE__ */ (0,
|
|
750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
|
|
735
751
|
}
|
|
736
752
|
|
|
737
753
|
// src/useAutoAlign.ts
|
|
738
754
|
var import_react5 = require("react");
|
|
739
755
|
var import_react_native9 = require("react-native");
|
|
740
756
|
var EDGE_MARGIN = 12;
|
|
741
|
-
function
|
|
757
|
+
function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
|
|
758
|
+
if (rotation === 0) return { x, y, width, height };
|
|
759
|
+
const cx = windowWidth / 2;
|
|
760
|
+
const cy = windowHeight / 2;
|
|
761
|
+
const dx = x + width / 2 - cx;
|
|
762
|
+
const dy = y + height / 2 - cy;
|
|
763
|
+
const [newDx, newDy, newWidth, newHeight] = rotation === 180 ? [-dx, -dy, width, height] : rotation === 90 ? [-dy, dx, height, width] : [dy, -dx, height, width];
|
|
764
|
+
return { x: cx + newDx - newWidth / 2, y: cy + newDy - newHeight / 2, width: newWidth, height: newHeight };
|
|
765
|
+
}
|
|
766
|
+
function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
742
767
|
const triggerRef = (0, import_react5.useRef)(null);
|
|
743
768
|
const { width: windowWidth, height: windowHeight } = (0, import_react_native9.useWindowDimensions)();
|
|
744
769
|
const [align, setAlign] = (0, import_react5.useState)("center");
|
|
@@ -751,7 +776,8 @@ function useAutoAlign(open, contentWidth, contentHeight) {
|
|
|
751
776
|
if (open) setMeasured(false);
|
|
752
777
|
}
|
|
753
778
|
const measure = (0, import_react5.useCallback)(() => {
|
|
754
|
-
triggerRef.current?.measureInWindow((
|
|
779
|
+
triggerRef.current?.measureInWindow((rawX, rawY, rawWidth, rawHeight) => {
|
|
780
|
+
const { x, y, width: triggerWidth, height: triggerHeight } = rotateRect(rawX, rawY, rawWidth, rawHeight, rotation, windowWidth, windowHeight);
|
|
755
781
|
const centerX = x + triggerWidth / 2;
|
|
756
782
|
const overflowsRight = centerX + contentWidth / 2 > windowWidth - EDGE_MARGIN;
|
|
757
783
|
const overflowsLeft = centerX - contentWidth / 2 < EDGE_MARGIN;
|
|
@@ -765,7 +791,7 @@ function useAutoAlign(open, contentWidth, contentHeight) {
|
|
|
765
791
|
setMaxHeight(Math.max(above ? roomAbove : roomBelow, 0));
|
|
766
792
|
setMeasured(true);
|
|
767
793
|
});
|
|
768
|
-
}, [contentWidth, contentHeight, windowWidth, windowHeight]);
|
|
794
|
+
}, [contentWidth, contentHeight, windowWidth, windowHeight, rotation]);
|
|
769
795
|
(0, import_react5.useEffect)(() => {
|
|
770
796
|
if (open) measure();
|
|
771
797
|
}, [open, measure]);
|
|
@@ -773,7 +799,7 @@ function useAutoAlign(open, contentWidth, contentHeight) {
|
|
|
773
799
|
}
|
|
774
800
|
|
|
775
801
|
// src/SectionedDropdown.tsx
|
|
776
|
-
var
|
|
802
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
777
803
|
var MENU_BORDER_WIDTH = 1;
|
|
778
804
|
var TRIGGER_SIZE = 44;
|
|
779
805
|
var MENU_MIN_WIDTH = 200;
|
|
@@ -784,7 +810,9 @@ var MENU_ITEM_HEIGHT = 40;
|
|
|
784
810
|
var MENU_ITEM_HEIGHT_WITH_DESCRIPTION = 58;
|
|
785
811
|
var MENU_DIVIDER_HEIGHT = 9;
|
|
786
812
|
var MENU_VERTICAL_PADDING = 12;
|
|
787
|
-
function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accentColor, mutedColor, onAccentColor, dark, align: alignOverride, autoDismiss = true, labelFontFamily = MONO_FONT, allClearLabels = { all: "All", clear: "Clear" } }) {
|
|
813
|
+
function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accentColor, mutedColor, onAccentColor, dark, align: alignOverride, rotation: rotationOverride, autoDismiss = true, labelFontFamily = MONO_FONT, allClearLabels = { all: "All", clear: "Clear" } }) {
|
|
814
|
+
const ambientRotation = (0, import_core5.useRotation)();
|
|
815
|
+
const rotation = rotationOverride ?? ambientRotation;
|
|
788
816
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
789
817
|
const menuBorderColor = (0, import_auto_paper5.getBlendedColor)(mutedColor, menuBg, 0.5);
|
|
790
818
|
const resolvedOnAccentColor = onAccentColor ?? (0, import_auto_paper5.getColorRoles)(accentColor, menuBg).onColor;
|
|
@@ -796,7 +824,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
796
824
|
const divider = sectionIndex > 0 ? MENU_DIVIDER_HEIGHT : 0;
|
|
797
825
|
return sum + rows + footer + divider;
|
|
798
826
|
}, 0);
|
|
799
|
-
const { align: autoAlign, maxHeight, measured, triggerRef, verticalAlign } = useAutoAlign(open, MENU_MAX_WIDTH, estimatedHeight);
|
|
827
|
+
const { align: autoAlign, maxHeight, measured, triggerRef, verticalAlign } = useAutoAlign(open, MENU_MAX_WIDTH, estimatedHeight, rotation);
|
|
800
828
|
const align = alignOverride ?? autoAlign;
|
|
801
829
|
const onlySection = sections.length === 1 ? sections[0] : null;
|
|
802
830
|
const selectedOption = onlySection?.kind === "single" ? onlySection.options.find((o) => o.value === onlySection.value) : void 0;
|
|
@@ -822,14 +850,14 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
822
850
|
const anchorStyle = [styles8.anchor, open && styles8.anchorOpen];
|
|
823
851
|
const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
|
|
824
852
|
const dividerStyle = { backgroundColor: menuBorderColor };
|
|
825
|
-
return /* @__PURE__ */ (0,
|
|
826
|
-
/* @__PURE__ */ (0,
|
|
827
|
-
/* @__PURE__ */ (0,
|
|
828
|
-
/* @__PURE__ */ (0,
|
|
853
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native10.View, { style: anchorStyle, children: [
|
|
854
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native10.View, { ref: triggerRef, collapsable: false, style: styles8.triggerBox, children: [
|
|
855
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
|
|
856
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press4.IconButton, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
|
|
829
857
|
] }),
|
|
830
|
-
/* @__PURE__ */ (0,
|
|
831
|
-
sectionIndex > 0 && /* @__PURE__ */ (0,
|
|
832
|
-
section.kind === "single" ? /* @__PURE__ */ (0,
|
|
858
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native10.ScrollView, { style: [styles8.menu, menuStyle], contentContainerStyle: styles8.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native10.View, { children: [
|
|
859
|
+
sectionIndex > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native10.View, { style: [styles8.divider, dividerStyle] }),
|
|
860
|
+
section.kind === "single" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
833
861
|
SingleSection,
|
|
834
862
|
{
|
|
835
863
|
section,
|
|
@@ -842,7 +870,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
842
870
|
if (autoDismiss) host.close();
|
|
843
871
|
}
|
|
844
872
|
}
|
|
845
|
-
) : /* @__PURE__ */ (0,
|
|
873
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
|
|
846
874
|
] }, section.id)) }) })
|
|
847
875
|
] });
|
|
848
876
|
}
|
|
@@ -854,18 +882,18 @@ function SingleSection({
|
|
|
854
882
|
labelFontFamily,
|
|
855
883
|
onSelect
|
|
856
884
|
}) {
|
|
857
|
-
return /* @__PURE__ */ (0,
|
|
885
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: section.options.map((option) => {
|
|
858
886
|
const selected = option.value === section.value;
|
|
859
887
|
const taken = !selected && option.value === section.takenValue;
|
|
860
888
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
861
889
|
const itemStyle = [styles8.item, selected && { backgroundColor: accentColor }, taken && styles8.itemTaken];
|
|
862
890
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
863
891
|
const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
|
|
864
|
-
return /* @__PURE__ */ (0,
|
|
865
|
-
option.icon && /* @__PURE__ */ (0,
|
|
866
|
-
/* @__PURE__ */ (0,
|
|
867
|
-
/* @__PURE__ */ (0,
|
|
868
|
-
option.description && /* @__PURE__ */ (0,
|
|
892
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press4.TouchableRipple, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native10.View, { style: styles8.itemRow, children: [
|
|
893
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper5.Icon, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
894
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native10.View, { style: styles8.itemLabelColumn, children: [
|
|
895
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper5.Text, { variant: "labelLarge", style: labelStyle, children: option.label }),
|
|
896
|
+
option.description && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper5.Text, { variant: "labelSmall", style: descriptionStyle, children: option.description })
|
|
869
897
|
] })
|
|
870
898
|
] }) }, option.value);
|
|
871
899
|
}) });
|
|
@@ -879,7 +907,7 @@ function MultiSection({
|
|
|
879
907
|
allClearLabels
|
|
880
908
|
}) {
|
|
881
909
|
const allSelected = section.value.length === section.options.length;
|
|
882
|
-
return /* @__PURE__ */ (0,
|
|
910
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
883
911
|
section.options.map((option, i) => {
|
|
884
912
|
const selected = section.value.includes(option.value);
|
|
885
913
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
@@ -887,12 +915,12 @@ function MultiSection({
|
|
|
887
915
|
const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
|
|
888
916
|
const itemStyle = [styles8.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
|
|
889
917
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
890
|
-
return /* @__PURE__ */ (0,
|
|
891
|
-
option.icon && /* @__PURE__ */ (0,
|
|
892
|
-
/* @__PURE__ */ (0,
|
|
918
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press4.TouchableRipple, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native10.View, { style: styles8.itemRow, children: [
|
|
919
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper5.Icon, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
920
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper5.Text, { variant: "labelLarge", style: [styles8.itemLabelFlex, labelStyle], children: option.label })
|
|
893
921
|
] }) }, option.value);
|
|
894
922
|
}),
|
|
895
|
-
section.allClear && /* @__PURE__ */ (0,
|
|
923
|
+
section.allClear && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press4.TouchableRipple, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles8.item, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper5.Text, { variant: "labelLarge", style: [styles8.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
|
|
896
924
|
] });
|
|
897
925
|
}
|
|
898
926
|
var styles8 = import_react_native10.StyleSheet.create({
|
|
@@ -965,21 +993,21 @@ var styles8 = import_react_native10.StyleSheet.create({
|
|
|
965
993
|
});
|
|
966
994
|
|
|
967
995
|
// src/ControlSchemePicker.tsx
|
|
968
|
-
var
|
|
996
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
969
997
|
function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, labelFontFamily }) {
|
|
970
|
-
const isTouchPrimary = (0,
|
|
998
|
+
const isTouchPrimary = (0, import_core6.useIsTouchPrimaryDevice)();
|
|
971
999
|
if (import_react_native11.Platform.OS !== "web" || isTouchPrimary) return null;
|
|
972
|
-
return /* @__PURE__ */ (0,
|
|
1000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SectionedDropdown, { id, host, icon: "keyboard-outline", accessibilityLabel: "Control scheme", sections: [{ kind: "single", id: "controls", options, value, onChange, takenValue }], accentColor, mutedColor, onAccentColor, dark, align, labelFontFamily });
|
|
973
1001
|
}
|
|
974
1002
|
|
|
975
1003
|
// src/CornerActionButtons.tsx
|
|
976
1004
|
var import_feedback_press5 = require("@rific/feedback-press");
|
|
977
1005
|
var import_react_native12 = require("react-native");
|
|
978
|
-
var
|
|
1006
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
979
1007
|
function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back" }) {
|
|
980
|
-
return /* @__PURE__ */ (0,
|
|
981
|
-
/* @__PURE__ */ (0,
|
|
982
|
-
/* @__PURE__ */ (0,
|
|
1008
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1009
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_feedback_press5.IconButton, { icon: backIcon, iconColor: fg, size: 24, style: [styles9.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: backLabel }),
|
|
1010
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_feedback_press5.IconButton, { icon: "cog", iconColor: fg, size: 24, style: [styles9.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
|
|
983
1011
|
] });
|
|
984
1012
|
}
|
|
985
1013
|
var styles9 = import_react_native12.StyleSheet.create({
|
|
@@ -994,17 +1022,17 @@ var styles9 = import_react_native12.StyleSheet.create({
|
|
|
994
1022
|
// src/CornerStatusBadges.tsx
|
|
995
1023
|
var import_react_native13 = require("react-native");
|
|
996
1024
|
var import_react_native_paper6 = require("react-native-paper");
|
|
997
|
-
var
|
|
1025
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
998
1026
|
var BADGE_SIZE = 30;
|
|
999
1027
|
function StatusBadge({ icon }) {
|
|
1000
|
-
return /* @__PURE__ */ (0,
|
|
1028
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.View, { style: styles10.badge, children: icon && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_paper6.Icon, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
|
|
1001
1029
|
}
|
|
1002
1030
|
function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
|
|
1003
1031
|
const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
|
|
1004
1032
|
const p2OnLeftSide = orientationMode === "sideBySide" && !p1OnRight;
|
|
1005
|
-
return /* @__PURE__ */ (0,
|
|
1006
|
-
p1 && /* @__PURE__ */ (0,
|
|
1007
|
-
p2 && /* @__PURE__ */ (0,
|
|
1033
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
1034
|
+
p1 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.View, { pointerEvents: "none", style: p1OnRightSide ? styles10.bottomRight : styles10.bottomLeft, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatusBadge, { icon: p1.icon }) }),
|
|
1035
|
+
p2 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.View, { pointerEvents: "none", style: p2OnLeftSide ? styles10.topLeft : styles10.topRight, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatusBadge, { icon: p2.icon }) })
|
|
1008
1036
|
] });
|
|
1009
1037
|
}
|
|
1010
1038
|
var styles10 = import_react_native13.StyleSheet.create({
|
|
@@ -1028,10 +1056,10 @@ var styles10 = import_react_native13.StyleSheet.create({
|
|
|
1028
1056
|
// src/InlineColorPicker.tsx
|
|
1029
1057
|
var import_auto_paper6 = require("@rific/auto-paper");
|
|
1030
1058
|
var import_feedback_press6 = require("@rific/feedback-press");
|
|
1031
|
-
var
|
|
1059
|
+
var import_core7 = require("@tastic/core");
|
|
1032
1060
|
var import_react_native14 = require("react-native");
|
|
1033
1061
|
var import_react_native_paper7 = require("react-native-paper");
|
|
1034
|
-
var
|
|
1062
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1035
1063
|
var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
|
|
1036
1064
|
var DEFAULT_SIZE = 48;
|
|
1037
1065
|
var SWATCH_SIZE = 28;
|
|
@@ -1044,29 +1072,31 @@ var SCREEN_MARGIN = 40;
|
|
|
1044
1072
|
function widthForColumns(columns) {
|
|
1045
1073
|
return SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * columns + SWATCHES_GAP * (columns - 1);
|
|
1046
1074
|
}
|
|
1047
|
-
function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = import_auto_paper6.defaultColors, takenValue, allowSwapTaken, dark, align: alignOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
|
|
1075
|
+
function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = import_auto_paper6.defaultColors, takenValue, allowSwapTaken, dark, align: alignOverride, rotation: rotationOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
|
|
1076
|
+
const ambientRotation = (0, import_core7.useRotation)();
|
|
1077
|
+
const rotation = rotationOverride ?? ambientRotation;
|
|
1048
1078
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
1049
1079
|
const { width: windowWidth } = (0, import_react_native14.useWindowDimensions)();
|
|
1050
|
-
const autoColumns = (0,
|
|
1080
|
+
const autoColumns = (0, import_core7.clamp)(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS);
|
|
1051
1081
|
const resolvedColumns = columns ?? autoColumns;
|
|
1052
1082
|
const swatchesWidth = widthForColumns(resolvedColumns);
|
|
1053
1083
|
const swatchRows = Math.ceil(swatches.length / resolvedColumns);
|
|
1054
1084
|
const swatchesHeight = SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * swatchRows + SWATCHES_GAP * (swatchRows - 1);
|
|
1055
1085
|
const open = host.openId === id;
|
|
1056
|
-
const { align: autoAlign, maxHeight, measured, triggerRef, verticalAlign } = useAutoAlign(open, swatchesWidth, swatchesHeight);
|
|
1086
|
+
const { align: autoAlign, maxHeight, measured, triggerRef, verticalAlign } = useAutoAlign(open, swatchesWidth, swatchesHeight, rotation);
|
|
1057
1087
|
const align = alignOverride ?? autoAlign;
|
|
1058
1088
|
const displayFor = previewValue ?? ((hex) => hex);
|
|
1059
1089
|
const displayValue = displayFor(value);
|
|
1060
1090
|
const contrastColor = (0, import_auto_paper6.getContrastColor)(displayValue);
|
|
1061
1091
|
const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
|
|
1062
|
-
return /* @__PURE__ */ (0,
|
|
1063
|
-
/* @__PURE__ */ (0,
|
|
1064
|
-
/* @__PURE__ */ (0,
|
|
1092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { style: [styles11.anchor, open && styles11.anchorOpen], children: [
|
|
1093
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_feedback_press6.TouchableRipple, { onPress: () => host.toggle(id), borderless: true, style: [styles11.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.View, { ref: triggerRef, collapsable: false, style: styles11.triggerMeasure, children: tag ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper7.Text, { style: [styles11.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper7.Icon, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
|
|
1094
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.ScrollView, { style: [styles11.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles11.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
|
|
1065
1095
|
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
1066
1096
|
const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
|
|
1067
1097
|
const swappable = taken && allowSwapTaken;
|
|
1068
1098
|
const swatchDisplay = displayFor(swatch.value);
|
|
1069
|
-
return /* @__PURE__ */ (0,
|
|
1099
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1070
1100
|
import_feedback_press6.TouchableRipple,
|
|
1071
1101
|
{
|
|
1072
1102
|
disabled: taken && !swappable,
|
|
@@ -1076,7 +1106,7 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
|
|
|
1076
1106
|
},
|
|
1077
1107
|
borderless: true,
|
|
1078
1108
|
style: [styles11.swatch, { backgroundColor: swatchDisplay }, selected && styles11.swatchSelected, taken && !swappable && styles11.swatchTaken],
|
|
1079
|
-
children: selected ? /* @__PURE__ */ (0,
|
|
1109
|
+
children: selected ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper7.Icon, { source: "check", size: 16, color: (0, import_auto_paper6.getContrastColor)(swatchDisplay) }) : swappable ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper7.Icon, { source: "swap-horizontal", size: 16, color: (0, import_auto_paper6.getContrastColor)(swatchDisplay) }) : taken ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper7.Icon, { source: "close", size: 16, color: (0, import_auto_paper6.getContrastColor)(swatchDisplay) }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.View, {})
|
|
1080
1110
|
},
|
|
1081
1111
|
swatch.value
|
|
1082
1112
|
);
|
|
@@ -1159,7 +1189,7 @@ var import_auto_paper7 = require("@rific/auto-paper");
|
|
|
1159
1189
|
var import_feedback_press7 = require("@rific/feedback-press");
|
|
1160
1190
|
var import_react_native15 = require("react-native");
|
|
1161
1191
|
var import_react_native_paper8 = require("react-native-paper");
|
|
1162
|
-
var
|
|
1192
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1163
1193
|
var TRIGGER_HEIGHT = 28;
|
|
1164
1194
|
var POPOVER_WIDTH = 180;
|
|
1165
1195
|
var ROW_HEIGHT = 36;
|
|
@@ -1182,17 +1212,17 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
|
|
|
1182
1212
|
onChange(option.value);
|
|
1183
1213
|
host.close();
|
|
1184
1214
|
};
|
|
1185
|
-
return /* @__PURE__ */ (0,
|
|
1186
|
-
/* @__PURE__ */ (0,
|
|
1187
|
-
/* @__PURE__ */ (0,
|
|
1188
|
-
/* @__PURE__ */ (0,
|
|
1215
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { style: [styles12.anchor, open && styles12.anchorOpen], children: [
|
|
1216
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_feedback_press7.TouchableRipple, { onPress: () => host.toggle(id), style: styles12.trigger, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { ref: triggerRef, collapsable: false, style: styles12.triggerInner, children: [
|
|
1217
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper8.Text, { style: [styles12.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
|
|
1218
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper8.Icon, { source: "menu-down", size: 16, color })
|
|
1189
1219
|
] }) }),
|
|
1190
|
-
/* @__PURE__ */ (0,
|
|
1220
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.ScrollView, { style: [styles12.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles12.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
|
|
1191
1221
|
const isSelected = option.value === value;
|
|
1192
1222
|
const onColor = (0, import_auto_paper7.getContrastColor)(color);
|
|
1193
|
-
return /* @__PURE__ */ (0,
|
|
1194
|
-
option.icon && /* @__PURE__ */ (0,
|
|
1195
|
-
/* @__PURE__ */ (0,
|
|
1223
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_feedback_press7.TouchableRipple, { onPress: () => handleSelect(option), style: [styles12.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { style: styles12.rowInner, children: [
|
|
1224
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper8.Icon, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
|
|
1225
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper8.Text, { style: [styles12.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
|
|
1196
1226
|
] }) }, option.value);
|
|
1197
1227
|
}) }) })
|
|
1198
1228
|
] });
|
|
@@ -1249,24 +1279,29 @@ var styles12 = import_react_native15.StyleSheet.create({
|
|
|
1249
1279
|
}
|
|
1250
1280
|
});
|
|
1251
1281
|
|
|
1282
|
+
// src/loadSkiaWeb.ts
|
|
1283
|
+
function loadSkiaWeb() {
|
|
1284
|
+
return Promise.resolve();
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1252
1287
|
// src/PressAwayOverlay.tsx
|
|
1253
1288
|
var import_react_native16 = require("react-native");
|
|
1254
|
-
var
|
|
1289
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1255
1290
|
function PressAwayOverlay({ active, onPress, style }) {
|
|
1256
1291
|
if (!active) return null;
|
|
1257
|
-
return /* @__PURE__ */ (0,
|
|
1292
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native16.Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [import_react_native16.StyleSheet.absoluteFill, style] });
|
|
1258
1293
|
}
|
|
1259
1294
|
|
|
1260
1295
|
// src/ReadyButton.tsx
|
|
1261
1296
|
var import_feedback_press8 = require("@rific/feedback-press");
|
|
1262
1297
|
var import_react_native17 = require("react-native");
|
|
1263
1298
|
var import_react_native_paper9 = require("react-native-paper");
|
|
1264
|
-
var
|
|
1299
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1265
1300
|
function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
|
|
1266
1301
|
const readyButtonStyle = [styles13.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
|
|
1267
1302
|
const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
|
|
1268
1303
|
const labelColorStyle = { color: ready ? "#000000" : color };
|
|
1269
|
-
return /* @__PURE__ */ (0,
|
|
1304
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_feedback_press8.TouchableRipple, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native_paper9.Text, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
|
|
1270
1305
|
}
|
|
1271
1306
|
var styles13 = import_react_native17.StyleSheet.create({
|
|
1272
1307
|
readyButton: {
|
|
@@ -1283,14 +1318,14 @@ var styles13 = import_react_native17.StyleSheet.create({
|
|
|
1283
1318
|
// src/SharedActionBand.tsx
|
|
1284
1319
|
var import_feedback_press9 = require("@rific/feedback-press");
|
|
1285
1320
|
var import_react_native18 = require("react-native");
|
|
1286
|
-
var
|
|
1321
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1287
1322
|
function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
|
|
1288
|
-
return /* @__PURE__ */ (0,
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1291
|
-
onRandomize && /* @__PURE__ */ (0,
|
|
1292
|
-
onReset && /* @__PURE__ */ (0,
|
|
1293
|
-
/* @__PURE__ */ (0,
|
|
1323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native18.View, { style: [styles14.column, popoverOpen && styles14.columnOpen], children: [
|
|
1324
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native18.View, { style: styles14.actionsRow, children: [
|
|
1325
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_feedback_press9.IconButton, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
|
|
1326
|
+
onRandomize && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_feedback_press9.IconButton, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
|
|
1327
|
+
onReset && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_feedback_press9.IconButton, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
|
|
1328
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_feedback_press9.IconButton, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
|
|
1294
1329
|
] }),
|
|
1295
1330
|
children
|
|
1296
1331
|
] });
|
|
@@ -1314,14 +1349,14 @@ var styles14 = import_react_native18.StyleSheet.create({
|
|
|
1314
1349
|
var import_auto_paper8 = require("@rific/auto-paper");
|
|
1315
1350
|
var import_react_native19 = require("react-native");
|
|
1316
1351
|
var import_react_native_paper10 = require("react-native-paper");
|
|
1317
|
-
var
|
|
1352
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1318
1353
|
function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
|
|
1319
1354
|
const { dark } = (0, import_auto_paper8.useAutoPaperTheme)();
|
|
1320
1355
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
1321
1356
|
const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
|
|
1322
|
-
return /* @__PURE__ */ (0,
|
|
1323
|
-
/* @__PURE__ */ (0,
|
|
1324
|
-
/* @__PURE__ */ (0,
|
|
1357
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native19.View, { style: styles15.row, children: [
|
|
1358
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper10.Text, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
|
|
1359
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper10.Text, { variant: "bodyMedium", style: [styles15.value, { color: fg }], children: value })
|
|
1325
1360
|
] });
|
|
1326
1361
|
}
|
|
1327
1362
|
var styles15 = import_react_native19.StyleSheet.create({
|
|
@@ -1339,13 +1374,13 @@ var styles15 = import_react_native19.StyleSheet.create({
|
|
|
1339
1374
|
var import_auto_paper9 = require("@rific/auto-paper");
|
|
1340
1375
|
var import_react_native20 = require("react-native");
|
|
1341
1376
|
var import_react_native_paper11 = require("react-native-paper");
|
|
1342
|
-
var
|
|
1377
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1343
1378
|
function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
|
|
1344
1379
|
const { dark } = (0, import_auto_paper9.useAutoPaperTheme)();
|
|
1345
1380
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
1346
1381
|
const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
|
|
1347
|
-
return /* @__PURE__ */ (0,
|
|
1348
|
-
/* @__PURE__ */ (0,
|
|
1382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native20.View, { style: [styles16.section, { backgroundColor: sectionBg }], children: [
|
|
1383
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_paper11.Text, { variant: "labelMedium", style: [styles16.label, { color: fg }], children: label }),
|
|
1349
1384
|
children
|
|
1350
1385
|
] });
|
|
1351
1386
|
}
|
|
@@ -1395,6 +1430,7 @@ function usePopoverHost() {
|
|
|
1395
1430
|
ReadyButton,
|
|
1396
1431
|
SectionedDropdown,
|
|
1397
1432
|
SharedActionBand,
|
|
1433
|
+
SkiaGate,
|
|
1398
1434
|
StatRow,
|
|
1399
1435
|
StatSection,
|
|
1400
1436
|
TriggerGaugeHost,
|