@tastic/hud 0.8.2 → 0.8.4
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 +44 -8
- package/dist/index.d.ts +44 -8
- package/dist/index.js +308 -277
- package/dist/index.mjs +228 -200
- package/package.json +5 -4
- package/src/BaseSettingsDialog.tsx +16 -51
- package/src/BaseStatsScreen.tsx +2 -2
- package/src/ConfirmDialog.tsx +27 -37
- package/src/UpdateDialog.tsx +28 -0
- package/src/index.ts +2 -0
- package/src/overlayCard.ts +48 -0
- package/src/useUpdateConfirmBridge.ts +30 -0
package/dist/index.mjs
CHANGED
|
@@ -71,19 +71,146 @@ var styles = StyleSheet.create({
|
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
// src/BaseSettingsDialog.tsx
|
|
74
|
-
import { AutoAppearancePicker, Dialog, useAutoPaperTheme as
|
|
75
|
-
import { Button, SoundContext, TouchableRipple, useHapticSettings, useSoundSettings, useVibration } from "@rific/feedback-press";
|
|
74
|
+
import { AutoAppearancePicker, Dialog, useAutoPaperTheme as useAutoPaperTheme3 } from "@rific/auto-paper";
|
|
75
|
+
import { Button as Button2, SoundContext, TouchableRipple, useHapticSettings, useSoundSettings, useVibration } from "@rific/feedback-press";
|
|
76
76
|
import { useUpdater } from "@rific/updater";
|
|
77
|
-
import { useIsTouchPrimaryDevice, useRotation } from "@tastic/core";
|
|
78
|
-
import { useContext, useState } from "react";
|
|
79
|
-
import { Platform, ScrollView, StyleSheet as
|
|
77
|
+
import { toRotationStyle as toRotationStyle2, useIsTouchPrimaryDevice, useRotation } from "@tastic/core";
|
|
78
|
+
import { useContext, useState as useState2 } from "react";
|
|
79
|
+
import { Platform, ScrollView, StyleSheet as StyleSheet4, View as View3 } from "react-native";
|
|
80
|
+
import { Icon as Icon3, Text as Text3 } from "react-native-paper";
|
|
81
|
+
|
|
82
|
+
// src/ConfirmDialog.tsx
|
|
83
|
+
import { useAutoPaperTheme as useAutoPaperTheme2 } from "@rific/auto-paper";
|
|
84
|
+
import { Button } from "@rific/feedback-press";
|
|
85
|
+
import { toRotationStyle } from "@tastic/core";
|
|
86
|
+
import { StyleSheet as StyleSheet3, View as View2 } from "react-native";
|
|
80
87
|
import { Icon as Icon2, Portal, Text as Text2 } from "react-native-paper";
|
|
81
|
-
|
|
88
|
+
|
|
89
|
+
// src/overlayCard.ts
|
|
90
|
+
import { StyleSheet as StyleSheet2 } from "react-native";
|
|
91
|
+
function getOverlayCardColors(dark) {
|
|
92
|
+
return {
|
|
93
|
+
fg: dark ? "#FFFFFF" : "#000000",
|
|
94
|
+
fgMuted: dark ? "rgba(255,255,255,0.4)" : "rgba(0,0,0,0.4)",
|
|
95
|
+
cardBg: dark ? "#111111" : "#F2F2F2",
|
|
96
|
+
cardBorder: dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)"
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
var overlayStyles = StyleSheet2.create({
|
|
100
|
+
card: {
|
|
101
|
+
alignItems: "center",
|
|
102
|
+
borderRadius: 20,
|
|
103
|
+
borderWidth: 1,
|
|
104
|
+
gap: 16,
|
|
105
|
+
maxWidth: 360,
|
|
106
|
+
padding: 32
|
|
107
|
+
},
|
|
108
|
+
overlay: {
|
|
109
|
+
alignItems: "center",
|
|
110
|
+
backgroundColor: "rgba(0,0,0,0.72)",
|
|
111
|
+
bottom: 0,
|
|
112
|
+
justifyContent: "center",
|
|
113
|
+
left: 0,
|
|
114
|
+
position: "absolute",
|
|
115
|
+
right: 0,
|
|
116
|
+
top: 0
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// src/ConfirmDialog.tsx
|
|
121
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
122
|
+
function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
|
|
123
|
+
const { dark, colors } = useAutoPaperTheme2();
|
|
124
|
+
if (!visible) return null;
|
|
125
|
+
const { fg, cardBg, cardBorder } = getOverlayCardColors(dark);
|
|
126
|
+
const accent = destructive ? colors.danger : colors.primary;
|
|
127
|
+
const onAccent = destructive ? colors.onDanger : colors.onPrimary;
|
|
128
|
+
return /* @__PURE__ */ jsx2(Portal, { children: /* @__PURE__ */ jsx2(View2, { style: [overlayStyles.overlay, styles2.overlay], children: /* @__PURE__ */ jsxs2(View2, { style: [overlayStyles.card, styles2.card, { backgroundColor: cardBg, borderColor: cardBorder }, toRotationStyle(rotation)], children: [
|
|
129
|
+
/* @__PURE__ */ jsx2(Icon2, { source: icon, size: 64, color: accent }),
|
|
130
|
+
/* @__PURE__ */ jsx2(Text2, { variant: "headlineLarge", style: [styles2.title, { color: accent }], children: title }),
|
|
131
|
+
/* @__PURE__ */ jsx2(Text2, { variant: "bodyLarge", style: [styles2.body, { color: fg }], children: message }),
|
|
132
|
+
/* @__PURE__ */ jsxs2(View2, { style: styles2.actions, children: [
|
|
133
|
+
cancelLabel !== void 0 && onCancel !== void 0 && /* @__PURE__ */ jsx2(Button, { mode: "outlined", onPress: onCancel, style: styles2.actionButton, children: cancelLabel }),
|
|
134
|
+
/* @__PURE__ */ jsx2(Button, { mode: "contained", onPress: onConfirm, style: styles2.actionButton, buttonColor: accent, textColor: onAccent, children: confirmLabel })
|
|
135
|
+
] })
|
|
136
|
+
] }) }) });
|
|
137
|
+
}
|
|
138
|
+
var styles2 = StyleSheet3.create({
|
|
139
|
+
// flexBasis (not flex: 1's own 0%) is each button's real floor: whenever both fit side by side,
|
|
140
|
+
// flexGrow still splits any leftover width evenly beyond that floor, same visual result as the
|
|
141
|
+
// old flex: 1 on a roomy screen - but a button can never be squeezed narrower than 128, only
|
|
142
|
+
// wrap to its own row instead (see actions' flexWrap below). react-native-paper's Button
|
|
143
|
+
// hardcodes numberOfLines={1} on its label with no override, so a button squeezed under its
|
|
144
|
+
// label's natural width silently ellipsizes ("Cancel" -> "Can...") instead of wrapping - assumed
|
|
145
|
+
// fixable by just giving the row more width, until confirmed live that these two-word labels
|
|
146
|
+
// (Cancel/Reset/New Game) can still lose the truncation fight even with the extra room card's own
|
|
147
|
+
// width fix below provides, on a narrow enough screen. flexBasis is the real fix: past a certain
|
|
148
|
+
// width there's no side-by-side arrangement that fits both buttons at their natural label size,
|
|
149
|
+
// so the layout has to give (stack) rather than the label (truncate).
|
|
150
|
+
actionButton: {
|
|
151
|
+
flexBasis: 128,
|
|
152
|
+
flexGrow: 1
|
|
153
|
+
},
|
|
154
|
+
actions: {
|
|
155
|
+
flexDirection: "row",
|
|
156
|
+
flexWrap: "wrap",
|
|
157
|
+
gap: 12,
|
|
158
|
+
width: "100%"
|
|
159
|
+
},
|
|
160
|
+
body: {
|
|
161
|
+
textAlign: "center"
|
|
162
|
+
},
|
|
163
|
+
// Additive on top of overlayCard's own shared `card` shape (borderRadius/borderWidth/gap/maxWidth/
|
|
164
|
+
// padding) — claims its full allowance instead of just maxWidth alone, which only caps how wide the
|
|
165
|
+
// card is allowed to get - without an explicit width, a flex-centered child sizes to its own content
|
|
166
|
+
// instead of stretching, so the card (and therefore actions below) can end up narrower than the
|
|
167
|
+
// screen actually has room for, needlessly forcing the action row to wrap sooner than it has to.
|
|
168
|
+
card: {
|
|
169
|
+
width: "100%"
|
|
170
|
+
},
|
|
171
|
+
// Additive on top of overlayCard's own shared `overlay` backdrop — gives the card room to breathe
|
|
172
|
+
// from the screen edges now that it reliably stretches to fill its full width allowance (see
|
|
173
|
+
// card's own width comment) - without this, width: '100%' would run the card edge-to-edge on a
|
|
174
|
+
// screen narrower than maxWidth's own 360.
|
|
175
|
+
overlay: {
|
|
176
|
+
paddingHorizontal: 24
|
|
177
|
+
},
|
|
178
|
+
// textAlign is load-bearing, not decorative, once `title` wraps to more than one line - centered
|
|
179
|
+
// within card's own alignItems: 'center' only centers the Text's block as a whole; each wrapped
|
|
180
|
+
// line inside that block still defaults to left-aligned without this.
|
|
181
|
+
title: {
|
|
182
|
+
fontWeight: "bold",
|
|
183
|
+
textAlign: "center"
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// src/useUpdateConfirmBridge.ts
|
|
188
|
+
import { useCallback, useRef, useState } from "react";
|
|
189
|
+
function useUpdateConfirmBridge() {
|
|
190
|
+
const [manifest, setManifest] = useState(null);
|
|
191
|
+
const resolveRef = useRef(null);
|
|
192
|
+
const onConfirm = useCallback(
|
|
193
|
+
(next) => new Promise((resolve) => {
|
|
194
|
+
resolveRef.current = resolve;
|
|
195
|
+
setManifest(next);
|
|
196
|
+
}),
|
|
197
|
+
[]
|
|
198
|
+
);
|
|
199
|
+
const respond = useCallback((confirmed) => {
|
|
200
|
+
setManifest(null);
|
|
201
|
+
resolveRef.current?.(confirmed);
|
|
202
|
+
resolveRef.current = null;
|
|
203
|
+
}, []);
|
|
204
|
+
return { manifest, onConfirm, respond };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/BaseSettingsDialog.tsx
|
|
208
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
82
209
|
function SettingIcon({ source, color, containerColor }) {
|
|
83
|
-
return /* @__PURE__ */
|
|
210
|
+
return /* @__PURE__ */ jsx3(View3, { style: [styles3.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ jsx3(Icon3, { source, size: 18, color }) });
|
|
84
211
|
}
|
|
85
212
|
function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, children }) {
|
|
86
|
-
const {
|
|
213
|
+
const { colors } = useAutoPaperTheme3();
|
|
87
214
|
const ambientRotation = useRotation();
|
|
88
215
|
const rotation = rotationOverride ?? ambientRotation;
|
|
89
216
|
const isTouchPrimary = useIsTouchPrimaryDevice();
|
|
@@ -91,43 +218,43 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
91
218
|
const { settings: soundSettings, set: setSoundSettings } = useSoundSettings();
|
|
92
219
|
const sound = useContext(SoundContext);
|
|
93
220
|
const { forceShort: forceHapticFeedback } = useVibration();
|
|
94
|
-
const [infoMessage, setInfoMessage] =
|
|
221
|
+
const [infoMessage, setInfoMessage] = useState2(null);
|
|
222
|
+
const { manifest: updateManifest, onConfirm: onUpdateConfirm, respond: respondToUpdateConfirm } = useUpdateConfirmBridge();
|
|
95
223
|
const { check, checking, updateReady } = useUpdater({
|
|
96
224
|
autoCheck: false,
|
|
97
225
|
autoPrompt: false,
|
|
226
|
+
onConfirm: onUpdateConfirm,
|
|
98
227
|
onError: onUpdateError,
|
|
99
228
|
onInfo: (title, message) => setInfoMessage({ title, message })
|
|
100
229
|
});
|
|
230
|
+
const updateManifestDate = updateManifest ? new Date(updateManifest.createdAt) : null;
|
|
101
231
|
const showLockOrientation = isTouchPrimary && lockOrientation !== void 0 && onLockOrientationChange !== void 0;
|
|
102
232
|
const showEdgeGuard = Platform.OS === "ios" && deferBottomEdgeGestures !== void 0 && onDeferBottomEdgeGestures !== void 0;
|
|
103
233
|
const showHaptics = Platform.OS !== "web" && !hideHaptics;
|
|
104
234
|
const showSound = !hideSound;
|
|
105
235
|
const showAppearance = !hideAppearance;
|
|
106
236
|
const showUpdateCheck = Platform.OS !== "web" && !hideUpdateCheck;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
/* @__PURE__ */ jsxs2(View2, { style: styles2.flexShrink, children: [
|
|
118
|
-
/* @__PURE__ */ jsx2(Text2, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
|
|
119
|
-
/* @__PURE__ */ jsx2(Text2, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pins the current layout" })
|
|
237
|
+
return /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
238
|
+
/* @__PURE__ */ jsxs3(Dialog, { visible, onDismiss, style: [styles3.dialog, toRotationStyle2(rotation)], children: [
|
|
239
|
+
/* @__PURE__ */ jsx3(Dialog.Title, { children: "Settings" }),
|
|
240
|
+
/* @__PURE__ */ jsx3(Dialog.ScrollArea, { style: styles3.scrollArea, children: /* @__PURE__ */ jsxs3(ScrollView, { contentContainerStyle: styles3.content, showsVerticalScrollIndicator: false, children: [
|
|
241
|
+
/* @__PURE__ */ jsxs3(View3, { style: styles3.toggleGroup, children: [
|
|
242
|
+
showLockOrientation && /* @__PURE__ */ jsx3(TouchableRipple, { onPress: () => onLockOrientationChange(!lockOrientation), style: styles3.toggleButton, accessibilityLabel: `Lock orientation ${lockOrientation ? "on" : "off"}`, children: /* @__PURE__ */ jsxs3(View3, { style: styles3.toggleContent, children: [
|
|
243
|
+
/* @__PURE__ */ jsx3(SettingIcon, { source: lockOrientation ? "lock" : "lock-open-variant-outline", color: lockOrientation ? colors.secondary : colors.onSurfaceVariant, containerColor: lockOrientation ? colors.secondaryContainer : colors.surfaceVariant }),
|
|
244
|
+
/* @__PURE__ */ jsxs3(View3, { style: styles3.flexShrink, children: [
|
|
245
|
+
/* @__PURE__ */ jsx3(Text3, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
|
|
246
|
+
/* @__PURE__ */ jsx3(Text3, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pins the current layout" })
|
|
120
247
|
] })
|
|
121
248
|
] }) }),
|
|
122
|
-
showEdgeGuard && /* @__PURE__ */
|
|
123
|
-
/* @__PURE__ */
|
|
124
|
-
/* @__PURE__ */
|
|
125
|
-
/* @__PURE__ */
|
|
126
|
-
/* @__PURE__ */
|
|
249
|
+
showEdgeGuard && /* @__PURE__ */ jsx3(TouchableRipple, { onPress: () => onDeferBottomEdgeGestures(!deferBottomEdgeGestures), style: styles3.toggleButton, accessibilityLabel: `Edge guard ${deferBottomEdgeGestures ? "on" : "off"}`, children: /* @__PURE__ */ jsxs3(View3, { style: styles3.toggleContent, children: [
|
|
250
|
+
/* @__PURE__ */ jsx3(SettingIcon, { source: deferBottomEdgeGestures ? "shield-check-outline" : "shield-off-outline", color: deferBottomEdgeGestures ? colors.secondary : colors.onSurfaceVariant, containerColor: deferBottomEdgeGestures ? colors.secondaryContainer : colors.surfaceVariant }),
|
|
251
|
+
/* @__PURE__ */ jsxs3(View3, { style: styles3.flexShrink, children: [
|
|
252
|
+
/* @__PURE__ */ jsx3(Text3, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Edge Guard" }),
|
|
253
|
+
/* @__PURE__ */ jsx3(Text3, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Requires a second swipe" })
|
|
127
254
|
] })
|
|
128
255
|
] }) }),
|
|
129
|
-
(showSound || showHaptics) && /* @__PURE__ */
|
|
130
|
-
showSound && /* @__PURE__ */
|
|
256
|
+
(showSound || showHaptics) && /* @__PURE__ */ jsxs3(View3, { style: styles3.toggleRow, children: [
|
|
257
|
+
showSound && /* @__PURE__ */ jsx3(
|
|
131
258
|
TouchableRipple,
|
|
132
259
|
{
|
|
133
260
|
soundDisabled: true,
|
|
@@ -136,15 +263,15 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
136
263
|
setSoundSettings({ enabled });
|
|
137
264
|
if (enabled) sound.selection?.();
|
|
138
265
|
},
|
|
139
|
-
style:
|
|
266
|
+
style: styles3.toggleButtonInRow,
|
|
140
267
|
accessibilityLabel: `Sound ${soundSettings.enabled ? "on" : "off"}`,
|
|
141
|
-
children: /* @__PURE__ */
|
|
142
|
-
/* @__PURE__ */
|
|
143
|
-
/* @__PURE__ */
|
|
268
|
+
children: /* @__PURE__ */ jsxs3(View3, { style: styles3.toggleContent, children: [
|
|
269
|
+
/* @__PURE__ */ jsx3(SettingIcon, { source: soundSettings.enabled ? "volume-high" : "volume-off", color: soundSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: soundSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
270
|
+
/* @__PURE__ */ jsx3(Text3, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Sound" })
|
|
144
271
|
] })
|
|
145
272
|
}
|
|
146
273
|
),
|
|
147
|
-
showHaptics && /* @__PURE__ */
|
|
274
|
+
showHaptics && /* @__PURE__ */ jsx3(
|
|
148
275
|
TouchableRipple,
|
|
149
276
|
{
|
|
150
277
|
hapticDisabled: true,
|
|
@@ -153,40 +280,36 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
153
280
|
setHapticSettings({ vibrate });
|
|
154
281
|
if (vibrate) forceHapticFeedback();
|
|
155
282
|
},
|
|
156
|
-
style:
|
|
283
|
+
style: styles3.toggleButtonInRow,
|
|
157
284
|
accessibilityLabel: `Haptics ${hapticSettings.vibrate ? "on" : "off"}`,
|
|
158
|
-
children: /* @__PURE__ */
|
|
159
|
-
/* @__PURE__ */
|
|
160
|
-
/* @__PURE__ */
|
|
285
|
+
children: /* @__PURE__ */ jsxs3(View3, { style: styles3.toggleContent, children: [
|
|
286
|
+
/* @__PURE__ */ jsx3(SettingIcon, { source: hapticSettings.vibrate ? "vibrate" : "vibrate-off", color: hapticSettings.vibrate ? colors.tertiary : colors.onSurfaceVariant, containerColor: hapticSettings.vibrate ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
287
|
+
/* @__PURE__ */ jsx3(Text3, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Haptics" })
|
|
161
288
|
] })
|
|
162
289
|
}
|
|
163
290
|
)
|
|
164
291
|
] })
|
|
165
292
|
] }),
|
|
166
|
-
showAppearance && /* @__PURE__ */
|
|
167
|
-
/* @__PURE__ */
|
|
168
|
-
/* @__PURE__ */
|
|
293
|
+
showAppearance && /* @__PURE__ */ jsxs3(View3, { style: styles3.section, children: [
|
|
294
|
+
/* @__PURE__ */ jsx3(Text3, { variant: "labelMedium", style: [styles3.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
|
|
295
|
+
/* @__PURE__ */ jsx3(AutoAppearancePicker, { showLabels: false })
|
|
169
296
|
] }),
|
|
170
297
|
children,
|
|
171
|
-
showUpdateCheck && /* @__PURE__ */
|
|
172
|
-
/* @__PURE__ */
|
|
298
|
+
showUpdateCheck && /* @__PURE__ */ jsxs3(View3, { style: styles3.section, children: [
|
|
299
|
+
/* @__PURE__ */ jsxs3(Text3, { variant: "labelSmall", style: [styles3.sectionLabel, { color: colors.onSurfaceVariant }], children: [
|
|
173
300
|
"VERSION ",
|
|
174
301
|
version,
|
|
175
302
|
updateReady ? " \xB7 UPDATE READY" : ""
|
|
176
303
|
] }),
|
|
177
|
-
/* @__PURE__ */
|
|
304
|
+
/* @__PURE__ */ jsx3(Button2, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
|
|
178
305
|
] })
|
|
179
306
|
] }) })
|
|
180
307
|
] }),
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
/* @__PURE__ */ jsx2(Text2, { variant: "headlineLarge", style: [styles2.overlayTitle, { color: colors.secondary }], children: infoMessage.title }),
|
|
184
|
-
/* @__PURE__ */ jsx2(Text2, { variant: "bodyLarge", style: [styles2.overlayBody, { color: fg }], children: infoMessage.message }),
|
|
185
|
-
/* @__PURE__ */ jsx2(Button, { mode: "contained", onPress: () => setInfoMessage(null), style: styles2.overlayButton, buttonColor: colors.primary, textColor: colors.onPrimary, children: "OK" })
|
|
186
|
-
] }) }) })
|
|
308
|
+
/* @__PURE__ */ jsx3(ConfirmDialog, { visible: !!updateManifest, title: "Update Available", message: updateManifestDate ? `Released ${updateManifestDate.toLocaleDateString()} at ${updateManifestDate.toLocaleTimeString()}` : "", confirmLabel: "Restart", cancelLabel: "Later", icon: "update", rotation, onConfirm: () => respondToUpdateConfirm(true), onCancel: () => respondToUpdateConfirm(false) }),
|
|
309
|
+
/* @__PURE__ */ jsx3(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation, onConfirm: () => setInfoMessage(null) })
|
|
187
310
|
] });
|
|
188
311
|
}
|
|
189
|
-
var
|
|
312
|
+
var styles3 = StyleSheet4.create({
|
|
190
313
|
content: {
|
|
191
314
|
gap: 24,
|
|
192
315
|
paddingVertical: 20
|
|
@@ -208,27 +331,6 @@ var styles2 = StyleSheet2.create({
|
|
|
208
331
|
justifyContent: "center",
|
|
209
332
|
width: 36
|
|
210
333
|
},
|
|
211
|
-
overlay: {
|
|
212
|
-
alignItems: "center",
|
|
213
|
-
backgroundColor: "rgba(0,0,0,0.72)",
|
|
214
|
-
bottom: 0,
|
|
215
|
-
justifyContent: "center",
|
|
216
|
-
left: 0,
|
|
217
|
-
position: "absolute",
|
|
218
|
-
right: 0,
|
|
219
|
-
top: 0
|
|
220
|
-
},
|
|
221
|
-
overlayBody: { textAlign: "center" },
|
|
222
|
-
overlayButton: { width: 160 },
|
|
223
|
-
overlayCard: {
|
|
224
|
-
alignItems: "center",
|
|
225
|
-
borderRadius: 20,
|
|
226
|
-
borderWidth: 1,
|
|
227
|
-
gap: 16,
|
|
228
|
-
maxWidth: 360,
|
|
229
|
-
padding: 32
|
|
230
|
-
},
|
|
231
|
-
overlayTitle: { fontWeight: "bold" },
|
|
232
334
|
scrollArea: {
|
|
233
335
|
marginBottom: 0
|
|
234
336
|
},
|
|
@@ -278,102 +380,15 @@ var styles2 = StyleSheet2.create({
|
|
|
278
380
|
import { useAutoPaperTheme as useAutoPaperTheme4 } from "@rific/auto-paper";
|
|
279
381
|
import { Button as Button3, IconButton } from "@rific/feedback-press";
|
|
280
382
|
import { useRotation as useRotation2 } from "@tastic/core";
|
|
281
|
-
import { useState as
|
|
282
|
-
import { ScrollView as ScrollView2, StyleSheet as
|
|
383
|
+
import { useState as useState3 } from "react";
|
|
384
|
+
import { ScrollView as ScrollView2, StyleSheet as StyleSheet5, View as View4 } from "react-native";
|
|
283
385
|
import { Text as Text4 } from "react-native-paper";
|
|
284
|
-
|
|
285
|
-
// src/ConfirmDialog.tsx
|
|
286
|
-
import { useAutoPaperTheme as useAutoPaperTheme3 } from "@rific/auto-paper";
|
|
287
|
-
import { Button as Button2 } from "@rific/feedback-press";
|
|
288
|
-
import { StyleSheet as StyleSheet3, View as View3 } from "react-native";
|
|
289
|
-
import { Icon as Icon3, Portal as Portal2, Text as Text3 } from "react-native-paper";
|
|
290
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
291
|
-
function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
|
|
292
|
-
const { dark, colors } = useAutoPaperTheme3();
|
|
293
|
-
if (!visible) return null;
|
|
294
|
-
const fg = dark ? "#FFFFFF" : "#000000";
|
|
295
|
-
const cardBg = dark ? "#111111" : "#F2F2F2";
|
|
296
|
-
const cardBorder = dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)";
|
|
297
|
-
const accent = destructive ? colors.danger : colors.primary;
|
|
298
|
-
const onAccent = destructive ? colors.onDanger : colors.onPrimary;
|
|
299
|
-
return /* @__PURE__ */ jsx3(Portal2, { children: /* @__PURE__ */ jsx3(View3, { style: styles3.overlay, children: /* @__PURE__ */ jsxs3(View3, { style: [styles3.card, { backgroundColor: cardBg, borderColor: cardBorder }, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: [
|
|
300
|
-
/* @__PURE__ */ jsx3(Icon3, { source: icon, size: 64, color: accent }),
|
|
301
|
-
/* @__PURE__ */ jsx3(Text3, { variant: "headlineLarge", style: [styles3.title, { color: accent }], children: title }),
|
|
302
|
-
/* @__PURE__ */ jsx3(Text3, { variant: "bodyLarge", style: [styles3.body, { color: fg }], children: message }),
|
|
303
|
-
/* @__PURE__ */ jsxs3(View3, { style: styles3.actions, children: [
|
|
304
|
-
/* @__PURE__ */ jsx3(Button2, { mode: "outlined", onPress: onCancel, style: styles3.actionButton, children: cancelLabel }),
|
|
305
|
-
/* @__PURE__ */ jsx3(Button2, { mode: "contained", onPress: onConfirm, style: styles3.actionButton, buttonColor: accent, textColor: onAccent, children: confirmLabel })
|
|
306
|
-
] })
|
|
307
|
-
] }) }) });
|
|
308
|
-
}
|
|
309
|
-
var styles3 = StyleSheet3.create({
|
|
310
|
-
// flexBasis (not flex: 1's own 0%) is each button's real floor: whenever both fit side by side,
|
|
311
|
-
// flexGrow still splits any leftover width evenly beyond that floor, same visual result as the
|
|
312
|
-
// old flex: 1 on a roomy screen - but a button can never be squeezed narrower than 128, only
|
|
313
|
-
// wrap to its own row instead (see actions' flexWrap below). react-native-paper's Button
|
|
314
|
-
// hardcodes numberOfLines={1} on its label with no override, so a button squeezed under its
|
|
315
|
-
// label's natural width silently ellipsizes ("Cancel" -> "Can...") instead of wrapping - assumed
|
|
316
|
-
// fixable by just giving the row more width, until confirmed live that these two-word labels
|
|
317
|
-
// (Cancel/Reset/New Game) can still lose the truncation fight even with the extra room card's own
|
|
318
|
-
// width fix below provides, on a narrow enough screen. flexBasis is the real fix: past a certain
|
|
319
|
-
// width there's no side-by-side arrangement that fits both buttons at their natural label size,
|
|
320
|
-
// so the layout has to give (stack) rather than the label (truncate).
|
|
321
|
-
actionButton: {
|
|
322
|
-
flexBasis: 128,
|
|
323
|
-
flexGrow: 1
|
|
324
|
-
},
|
|
325
|
-
actions: {
|
|
326
|
-
flexDirection: "row",
|
|
327
|
-
flexWrap: "wrap",
|
|
328
|
-
gap: 12,
|
|
329
|
-
width: "100%"
|
|
330
|
-
},
|
|
331
|
-
body: {
|
|
332
|
-
textAlign: "center"
|
|
333
|
-
},
|
|
334
|
-
card: {
|
|
335
|
-
alignItems: "center",
|
|
336
|
-
borderRadius: 20,
|
|
337
|
-
borderWidth: 1,
|
|
338
|
-
gap: 16,
|
|
339
|
-
maxWidth: 360,
|
|
340
|
-
padding: 32,
|
|
341
|
-
// Claims its full allowance instead of just maxWidth alone, which only caps how wide the card
|
|
342
|
-
// is allowed to get - without an explicit width, a flex-centered child sizes to its own content
|
|
343
|
-
// instead of stretching, so the card (and therefore actions below) can end up narrower than the
|
|
344
|
-
// screen actually has room for, needlessly forcing the action row to wrap sooner than it has to.
|
|
345
|
-
width: "100%"
|
|
346
|
-
},
|
|
347
|
-
overlay: {
|
|
348
|
-
alignItems: "center",
|
|
349
|
-
backgroundColor: "rgba(0,0,0,0.72)",
|
|
350
|
-
bottom: 0,
|
|
351
|
-
justifyContent: "center",
|
|
352
|
-
left: 0,
|
|
353
|
-
// Gives the card room to breathe from the screen edges now that it reliably stretches to fill
|
|
354
|
-
// its full width allowance (see card's own width comment) - without this, width: '100%' would
|
|
355
|
-
// run the card edge-to-edge on a screen narrower than maxWidth's own 360.
|
|
356
|
-
paddingHorizontal: 24,
|
|
357
|
-
position: "absolute",
|
|
358
|
-
right: 0,
|
|
359
|
-
top: 0
|
|
360
|
-
},
|
|
361
|
-
// textAlign is load-bearing, not decorative, once `title` wraps to more than one line - centered
|
|
362
|
-
// within card's own alignItems: 'center' only centers the Text's block as a whole; each wrapped
|
|
363
|
-
// line inside that block still defaults to left-aligned without this.
|
|
364
|
-
title: {
|
|
365
|
-
fontWeight: "bold",
|
|
366
|
-
textAlign: "center"
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
// src/BaseStatsScreen.tsx
|
|
371
386
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
372
387
|
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 }) {
|
|
373
388
|
const { dark, colors } = useAutoPaperTheme4();
|
|
374
389
|
const ambientRotation = useRotation2();
|
|
375
390
|
const rotation = rotationOverride ?? ambientRotation;
|
|
376
|
-
const [confirmResetVisible, setConfirmResetVisible] =
|
|
391
|
+
const [confirmResetVisible, setConfirmResetVisible] = useState3(false);
|
|
377
392
|
const showReset = !!onReset;
|
|
378
393
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
379
394
|
const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
|
|
@@ -406,7 +421,7 @@ function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", t
|
|
|
406
421
|
)
|
|
407
422
|
] });
|
|
408
423
|
}
|
|
409
|
-
var styles4 =
|
|
424
|
+
var styles4 = StyleSheet5.create({
|
|
410
425
|
container: {
|
|
411
426
|
flex: 1
|
|
412
427
|
},
|
|
@@ -438,7 +453,7 @@ var styles4 = StyleSheet4.create({
|
|
|
438
453
|
|
|
439
454
|
// src/ContentGutter.tsx
|
|
440
455
|
import { computeContentBounds } from "@tastic/core";
|
|
441
|
-
import { StyleSheet as
|
|
456
|
+
import { StyleSheet as StyleSheet6, useWindowDimensions, View as View5 } from "react-native";
|
|
442
457
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
443
458
|
function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
|
|
444
459
|
const { width: windowWidth } = useWindowDimensions();
|
|
@@ -449,7 +464,7 @@ function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, childr
|
|
|
449
464
|
/* @__PURE__ */ jsx5(View5, { style: [styles5.gutter, { width: gutterWidth }], children: rightGutter })
|
|
450
465
|
] });
|
|
451
466
|
}
|
|
452
|
-
var styles5 =
|
|
467
|
+
var styles5 = StyleSheet6.create({
|
|
453
468
|
// overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
|
|
454
469
|
// column instead of clipping cleanly at its own real width.
|
|
455
470
|
gutter: {
|
|
@@ -468,7 +483,7 @@ import { Platform as Platform3 } from "react-native";
|
|
|
468
483
|
import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
|
|
469
484
|
import { IconButton as IconButton2, TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
|
|
470
485
|
import { useRotation as useRotation3 } from "@tastic/core";
|
|
471
|
-
import { ScrollView as ScrollView3, StyleSheet as
|
|
486
|
+
import { ScrollView as ScrollView3, StyleSheet as StyleSheet8, View as View8 } from "react-native";
|
|
472
487
|
import { Icon as Icon4, Text as Text5 } from "react-native-paper";
|
|
473
488
|
|
|
474
489
|
// src/fonts.ts
|
|
@@ -476,7 +491,7 @@ import { Platform as Platform2 } from "react-native";
|
|
|
476
491
|
var MONO_FONT = Platform2.select({ ios: "Menlo", android: "monospace", default: "monospace" });
|
|
477
492
|
|
|
478
493
|
// src/PopoverBody.tsx
|
|
479
|
-
import { StyleSheet as
|
|
494
|
+
import { StyleSheet as StyleSheet7, View as View6 } from "react-native";
|
|
480
495
|
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
481
496
|
var CARET_SIZE = 7;
|
|
482
497
|
var CARET_RING_OFFSET = 2;
|
|
@@ -499,7 +514,7 @@ function PopoverBody({ visible, children, align = "center", verticalAlign = "bel
|
|
|
499
514
|
] })
|
|
500
515
|
] });
|
|
501
516
|
}
|
|
502
|
-
var styles6 =
|
|
517
|
+
var styles6 = StyleSheet7.create({
|
|
503
518
|
caret: {
|
|
504
519
|
borderLeftColor: "transparent",
|
|
505
520
|
borderRightColor: "transparent",
|
|
@@ -549,7 +564,7 @@ function TriggerGaugeHost(props) {
|
|
|
549
564
|
}
|
|
550
565
|
|
|
551
566
|
// src/useAutoAlign.ts
|
|
552
|
-
import { useCallback, useEffect, useRef, useState as
|
|
567
|
+
import { useCallback as useCallback2, useEffect, useRef as useRef2, useState as useState4 } from "react";
|
|
553
568
|
import { useWindowDimensions as useWindowDimensions2 } from "react-native";
|
|
554
569
|
var EDGE_MARGIN = 12;
|
|
555
570
|
function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
|
|
@@ -562,18 +577,18 @@ function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
|
|
|
562
577
|
return { x: cx + newDx - newWidth / 2, y: cy + newDy - newHeight / 2, width: newWidth, height: newHeight };
|
|
563
578
|
}
|
|
564
579
|
function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
565
|
-
const triggerRef =
|
|
580
|
+
const triggerRef = useRef2(null);
|
|
566
581
|
const { width: windowWidth, height: windowHeight } = useWindowDimensions2();
|
|
567
|
-
const [align, setAlign] =
|
|
568
|
-
const [verticalAlign, setVerticalAlign] =
|
|
569
|
-
const [maxHeight, setMaxHeight] =
|
|
570
|
-
const [measured, setMeasured] =
|
|
571
|
-
const [prevOpen, setPrevOpen] =
|
|
582
|
+
const [align, setAlign] = useState4("center");
|
|
583
|
+
const [verticalAlign, setVerticalAlign] = useState4("below");
|
|
584
|
+
const [maxHeight, setMaxHeight] = useState4(contentHeight);
|
|
585
|
+
const [measured, setMeasured] = useState4(false);
|
|
586
|
+
const [prevOpen, setPrevOpen] = useState4(open);
|
|
572
587
|
if (open !== prevOpen) {
|
|
573
588
|
setPrevOpen(open);
|
|
574
589
|
if (open) setMeasured(false);
|
|
575
590
|
}
|
|
576
|
-
const measure =
|
|
591
|
+
const measure = useCallback2(() => {
|
|
577
592
|
triggerRef.current?.measureInWindow((rawX, rawY, rawWidth, rawHeight) => {
|
|
578
593
|
const { x, y, width: triggerWidth, height: triggerHeight } = rotateRect(rawX, rawY, rawWidth, rawHeight, rotation, windowWidth, windowHeight);
|
|
579
594
|
const centerX = x + triggerWidth / 2;
|
|
@@ -721,7 +736,7 @@ function MultiSection({
|
|
|
721
736
|
section.allClear && /* @__PURE__ */ jsx8(TouchableRipple2, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles7.item, children: /* @__PURE__ */ jsx8(Text5, { variant: "labelLarge", style: [styles7.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
|
|
722
737
|
] });
|
|
723
738
|
}
|
|
724
|
-
var styles7 =
|
|
739
|
+
var styles7 = StyleSheet8.create({
|
|
725
740
|
allClearLabel: {
|
|
726
741
|
fontWeight: "bold",
|
|
727
742
|
textAlign: "center"
|
|
@@ -738,7 +753,7 @@ var styles7 = StyleSheet7.create({
|
|
|
738
753
|
zIndex: 100
|
|
739
754
|
},
|
|
740
755
|
divider: {
|
|
741
|
-
height:
|
|
756
|
+
height: StyleSheet8.hairlineWidth,
|
|
742
757
|
marginVertical: 4
|
|
743
758
|
},
|
|
744
759
|
item: {
|
|
@@ -800,7 +815,7 @@ function ControlSchemePicker({ id, host, value, onChange, options, takenValue, a
|
|
|
800
815
|
|
|
801
816
|
// src/CornerActionButtons.tsx
|
|
802
817
|
import { IconButton as IconButton3 } from "@rific/feedback-press";
|
|
803
|
-
import { StyleSheet as
|
|
818
|
+
import { StyleSheet as StyleSheet9 } from "react-native";
|
|
804
819
|
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
805
820
|
function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back" }) {
|
|
806
821
|
return /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
@@ -808,7 +823,7 @@ function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow
|
|
|
808
823
|
/* @__PURE__ */ jsx10(IconButton3, { icon: "cog", iconColor: fg, size: 24, style: [styles8.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
|
|
809
824
|
] });
|
|
810
825
|
}
|
|
811
|
-
var styles8 =
|
|
826
|
+
var styles8 = StyleSheet9.create({
|
|
812
827
|
back: {
|
|
813
828
|
position: "absolute"
|
|
814
829
|
},
|
|
@@ -818,7 +833,7 @@ var styles8 = StyleSheet8.create({
|
|
|
818
833
|
});
|
|
819
834
|
|
|
820
835
|
// src/CornerStatusBadges.tsx
|
|
821
|
-
import { StyleSheet as
|
|
836
|
+
import { StyleSheet as StyleSheet10, View as View9 } from "react-native";
|
|
822
837
|
import { Icon as Icon5 } from "react-native-paper";
|
|
823
838
|
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
824
839
|
var BADGE_SIZE = 30;
|
|
@@ -833,7 +848,7 @@ function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
|
|
|
833
848
|
p2 && /* @__PURE__ */ jsx11(View9, { pointerEvents: "none", style: p2OnLeftSide ? styles9.topLeft : styles9.topRight, children: /* @__PURE__ */ jsx11(StatusBadge, { icon: p2.icon }) })
|
|
834
849
|
] });
|
|
835
850
|
}
|
|
836
|
-
var styles9 =
|
|
851
|
+
var styles9 = StyleSheet10.create({
|
|
837
852
|
badge: {
|
|
838
853
|
alignItems: "center",
|
|
839
854
|
backgroundColor: "rgba(0,0,0,0.28)",
|
|
@@ -855,7 +870,7 @@ var styles9 = StyleSheet9.create({
|
|
|
855
870
|
import { defaultColors, getContrastColor } from "@rific/auto-paper";
|
|
856
871
|
import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
|
|
857
872
|
import { clamp, useRotation as useRotation4 } from "@tastic/core";
|
|
858
|
-
import { ScrollView as ScrollView4, StyleSheet as
|
|
873
|
+
import { ScrollView as ScrollView4, StyleSheet as StyleSheet11, useWindowDimensions as useWindowDimensions3, View as View10 } from "react-native";
|
|
859
874
|
import { Icon as Icon6, Text as Text6 } from "react-native-paper";
|
|
860
875
|
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
861
876
|
var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
|
|
@@ -911,7 +926,7 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
|
|
|
911
926
|
}) }) })
|
|
912
927
|
] });
|
|
913
928
|
}
|
|
914
|
-
var styles10 =
|
|
929
|
+
var styles10 = StyleSheet11.create({
|
|
915
930
|
anchor: {
|
|
916
931
|
position: "relative"
|
|
917
932
|
},
|
|
@@ -985,7 +1000,7 @@ var styles10 = StyleSheet10.create({
|
|
|
985
1000
|
// src/LabeledDropdown.tsx
|
|
986
1001
|
import { getContrastColor as getContrastColor2 } from "@rific/auto-paper";
|
|
987
1002
|
import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
|
|
988
|
-
import { ScrollView as ScrollView5, StyleSheet as
|
|
1003
|
+
import { ScrollView as ScrollView5, StyleSheet as StyleSheet12, View as View11 } from "react-native";
|
|
989
1004
|
import { Icon as Icon7, Text as Text7 } from "react-native-paper";
|
|
990
1005
|
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
991
1006
|
var TRIGGER_HEIGHT = 28;
|
|
@@ -1025,7 +1040,7 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
|
|
|
1025
1040
|
}) }) })
|
|
1026
1041
|
] });
|
|
1027
1042
|
}
|
|
1028
|
-
var styles11 =
|
|
1043
|
+
var styles11 = StyleSheet12.create({
|
|
1029
1044
|
anchor: {
|
|
1030
1045
|
position: "relative"
|
|
1031
1046
|
},
|
|
@@ -1083,16 +1098,16 @@ function loadSkiaWeb() {
|
|
|
1083
1098
|
}
|
|
1084
1099
|
|
|
1085
1100
|
// src/PressAwayOverlay.tsx
|
|
1086
|
-
import { Pressable, StyleSheet as
|
|
1101
|
+
import { Pressable, StyleSheet as StyleSheet13 } from "react-native";
|
|
1087
1102
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
1088
1103
|
function PressAwayOverlay({ active, onPress, style }) {
|
|
1089
1104
|
if (!active) return null;
|
|
1090
|
-
return /* @__PURE__ */ jsx14(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [
|
|
1105
|
+
return /* @__PURE__ */ jsx14(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet13.absoluteFill, style] });
|
|
1091
1106
|
}
|
|
1092
1107
|
|
|
1093
1108
|
// src/ReadyButton.tsx
|
|
1094
1109
|
import { TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
|
|
1095
|
-
import { StyleSheet as
|
|
1110
|
+
import { StyleSheet as StyleSheet14 } from "react-native";
|
|
1096
1111
|
import { Text as Text8 } from "react-native-paper";
|
|
1097
1112
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1098
1113
|
function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
|
|
@@ -1101,7 +1116,7 @@ function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MON
|
|
|
1101
1116
|
const labelColorStyle = { color: ready ? "#000000" : color };
|
|
1102
1117
|
return /* @__PURE__ */ jsx15(TouchableRipple5, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx15(Text8, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
|
|
1103
1118
|
}
|
|
1104
|
-
var styles12 =
|
|
1119
|
+
var styles12 = StyleSheet14.create({
|
|
1105
1120
|
readyButton: {
|
|
1106
1121
|
alignItems: "center",
|
|
1107
1122
|
borderRadius: 12,
|
|
@@ -1115,7 +1130,7 @@ var styles12 = StyleSheet13.create({
|
|
|
1115
1130
|
|
|
1116
1131
|
// src/SharedActionBand.tsx
|
|
1117
1132
|
import { IconButton as IconButton4 } from "@rific/feedback-press";
|
|
1118
|
-
import { StyleSheet as
|
|
1133
|
+
import { StyleSheet as StyleSheet15, View as View12 } from "react-native";
|
|
1119
1134
|
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1120
1135
|
function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
|
|
1121
1136
|
return /* @__PURE__ */ jsxs12(View12, { style: [styles13.column, popoverOpen && styles13.columnOpen], children: [
|
|
@@ -1128,7 +1143,7 @@ function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popove
|
|
|
1128
1143
|
children
|
|
1129
1144
|
] });
|
|
1130
1145
|
}
|
|
1131
|
-
var styles13 =
|
|
1146
|
+
var styles13 = StyleSheet15.create({
|
|
1132
1147
|
actionsRow: {
|
|
1133
1148
|
alignItems: "center",
|
|
1134
1149
|
flexDirection: "row",
|
|
@@ -1145,7 +1160,7 @@ var styles13 = StyleSheet14.create({
|
|
|
1145
1160
|
|
|
1146
1161
|
// src/StatRow.tsx
|
|
1147
1162
|
import { useAutoPaperTheme as useAutoPaperTheme5 } from "@rific/auto-paper";
|
|
1148
|
-
import { StyleSheet as
|
|
1163
|
+
import { StyleSheet as StyleSheet16, View as View13 } from "react-native";
|
|
1149
1164
|
import { Text as Text9 } from "react-native-paper";
|
|
1150
1165
|
import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1151
1166
|
function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
|
|
@@ -1157,7 +1172,7 @@ function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
|
|
|
1157
1172
|
/* @__PURE__ */ jsx17(Text9, { variant: "bodyMedium", style: [styles14.value, { color: fg }], children: value })
|
|
1158
1173
|
] });
|
|
1159
1174
|
}
|
|
1160
|
-
var styles14 =
|
|
1175
|
+
var styles14 = StyleSheet16.create({
|
|
1161
1176
|
row: {
|
|
1162
1177
|
alignItems: "center",
|
|
1163
1178
|
flexDirection: "row",
|
|
@@ -1170,7 +1185,7 @@ var styles14 = StyleSheet15.create({
|
|
|
1170
1185
|
|
|
1171
1186
|
// src/StatSection.tsx
|
|
1172
1187
|
import { useAutoPaperTheme as useAutoPaperTheme6 } from "@rific/auto-paper";
|
|
1173
|
-
import { StyleSheet as
|
|
1188
|
+
import { StyleSheet as StyleSheet17, View as View14 } from "react-native";
|
|
1174
1189
|
import { Text as Text10 } from "react-native-paper";
|
|
1175
1190
|
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1176
1191
|
function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
|
|
@@ -1182,7 +1197,7 @@ function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, chil
|
|
|
1182
1197
|
children
|
|
1183
1198
|
] });
|
|
1184
1199
|
}
|
|
1185
|
-
var styles15 =
|
|
1200
|
+
var styles15 = StyleSheet17.create({
|
|
1186
1201
|
// Bold and full-contrast (fg), not the original fontless/fgMuted treatment — that read at the
|
|
1187
1202
|
// same visual weight as StatRow's own row labels below it (both used the identical muted color;
|
|
1188
1203
|
// letterSpacing/variant alone didn't separate them enough to read as "this is the group header"
|
|
@@ -1198,14 +1213,24 @@ var styles15 = StyleSheet16.create({
|
|
|
1198
1213
|
}
|
|
1199
1214
|
});
|
|
1200
1215
|
|
|
1216
|
+
// src/UpdateDialog.tsx
|
|
1217
|
+
import { useUpdater as useUpdater2 } from "@rific/updater";
|
|
1218
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
1219
|
+
function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onError }) {
|
|
1220
|
+
const { manifest, onConfirm, respond } = useUpdateConfirmBridge();
|
|
1221
|
+
useUpdater2({ autoCheck, autoPrompt, onConfirm, onError });
|
|
1222
|
+
const date = manifest ? new Date(manifest.createdAt) : null;
|
|
1223
|
+
return /* @__PURE__ */ jsx19(ConfirmDialog, { visible: !!manifest, title: "Update Available", message: date ? `Released ${date.toLocaleDateString()} at ${date.toLocaleTimeString()}` : "", confirmLabel: "Restart", cancelLabel: "Later", icon: "update", rotation, onConfirm: () => respond(true), onCancel: () => respond(false) });
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1201
1226
|
// src/usePopoverHost.ts
|
|
1202
|
-
import { useCallback as
|
|
1227
|
+
import { useCallback as useCallback3, useState as useState5 } from "react";
|
|
1203
1228
|
function usePopoverHost() {
|
|
1204
|
-
const [openId, setOpenId] =
|
|
1205
|
-
const toggle =
|
|
1229
|
+
const [openId, setOpenId] = useState5(null);
|
|
1230
|
+
const toggle = useCallback3((id) => {
|
|
1206
1231
|
setOpenId((prev) => prev === id ? null : id);
|
|
1207
1232
|
}, []);
|
|
1208
|
-
const close =
|
|
1233
|
+
const close = useCallback3(() => setOpenId(null), []);
|
|
1209
1234
|
return { openId, toggle, close };
|
|
1210
1235
|
}
|
|
1211
1236
|
export {
|
|
@@ -1231,8 +1256,11 @@ export {
|
|
|
1231
1256
|
StatRow,
|
|
1232
1257
|
StatSection,
|
|
1233
1258
|
TriggerGaugeHost,
|
|
1259
|
+
UpdateDialog,
|
|
1234
1260
|
getLabeledDropdownContentHeight,
|
|
1261
|
+
getOverlayCardColors,
|
|
1235
1262
|
loadSkiaWeb,
|
|
1263
|
+
overlayStyles,
|
|
1236
1264
|
useAutoAlign,
|
|
1237
1265
|
usePopoverHost
|
|
1238
1266
|
};
|