@tastic/hud 0.8.5 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +425 -23
- package/dist/chunk-32U2OIRW.mjs +77 -0
- package/dist/guide/index.d.mts +118 -0
- package/dist/guide/index.d.ts +118 -0
- package/dist/guide/index.js +543 -0
- package/dist/guide/index.mjs +428 -0
- package/dist/index.d.mts +145 -16
- package/dist/index.d.ts +145 -16
- package/dist/index.js +612 -322
- package/dist/index.mjs +533 -334
- package/package.json +46 -11
- package/src/AchievementCatalogSection.tsx +60 -0
- package/src/AchievementUnlockList.tsx +98 -0
- package/src/ActivityStatSection.tsx +29 -0
- package/src/BaseSettingsDialog.tsx +32 -1
- package/src/ConfirmDialog.tsx +4 -43
- package/src/ContentGutter.tsx +12 -5
- package/src/ControlSchemePicker.tsx +11 -2
- package/src/InlineColorPicker.tsx +38 -11
- package/src/LabeledDropdown.tsx +5 -17
- package/src/PlayerSetupPanel.tsx +196 -0
- package/src/SectionedDropdown.tsx +18 -7
- package/src/StaggeredWord.tsx +114 -0
- package/src/guide/DirectionKeysHint.tsx +96 -0
- package/src/guide/GuideProvider.tsx +87 -0
- package/src/guide/HowToPlayDialog.tsx +224 -0
- package/src/guide/SeatDevicesHint.tsx +52 -0
- package/src/guide/SeatDiagram.tsx +72 -0
- package/src/guide/SwipeHint.tsx +115 -0
- package/src/guide/guideSlice.ts +131 -0
- package/src/guide/index.ts +14 -0
- package/src/guide/types.ts +16 -0
- package/src/index.ts +10 -3
- package/src/overlayCard.ts +51 -4
- package/src/useAutoAlign.ts +17 -1
- package/src/useQuitConfirmation.ts +61 -0
- package/src/useZoneClampedAlign.ts +135 -0
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __esm = (fn, res) => function __init() {
|
|
7
9
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -18,6 +20,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
20
|
}
|
|
19
21
|
return to;
|
|
20
22
|
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
21
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
32
|
|
|
23
33
|
// src/TriggerGauge.tsx
|
|
@@ -28,22 +38,22 @@ __export(TriggerGauge_exports, {
|
|
|
28
38
|
function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, dashWidth, startDeg = DEFAULT_START_DEG, endDeg = startDeg }) {
|
|
29
39
|
const totalDurationMs = MOUNT_DURATION_MS + Math.max(0, segments - 1) * MOUNT_STAGGER_MS;
|
|
30
40
|
const mountProgress = (0, import_react_native_reanimated.useSharedValue)(0);
|
|
31
|
-
(0,
|
|
41
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
32
42
|
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
43
|
}, []);
|
|
34
44
|
const rawSweepDeg = ((endDeg - startDeg) % 360 + 360) % 360;
|
|
35
45
|
const totalSweepDeg = rawSweepDeg === 0 ? 360 : rawSweepDeg;
|
|
36
46
|
const step = segments > 0 ? totalSweepDeg / segments : 0;
|
|
37
|
-
const centerDeg = (0,
|
|
47
|
+
const centerDeg = (0, import_react6.useCallback)((i) => startDeg + (i + 0.5) * step, [startDeg, step]);
|
|
38
48
|
const singleSelect = litIndices.length === 1;
|
|
39
49
|
const angleDeg = (0, import_react_native_reanimated.useSharedValue)(centerDeg(litIndices[0] ?? 0));
|
|
40
50
|
const litIndicesKey = [...litIndices].sort((a, b) => a - b).join(",");
|
|
41
|
-
const [transitionFrom, setTransitionFrom] = (0,
|
|
51
|
+
const [transitionFrom, setTransitionFrom] = (0, import_react6.useState)(litIndices);
|
|
42
52
|
const transitionFromKey = [...transitionFrom].sort((a, b) => a - b).join(",");
|
|
43
|
-
const lastKeyRef = (0,
|
|
44
|
-
const lastIndicesRef = (0,
|
|
53
|
+
const lastKeyRef = (0, import_react6.useRef)(litIndicesKey);
|
|
54
|
+
const lastIndicesRef = (0, import_react6.useRef)(litIndices);
|
|
45
55
|
const selectionProgress = (0, import_react_native_reanimated.useSharedValue)(1);
|
|
46
|
-
(0,
|
|
56
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
47
57
|
if (litIndicesKey !== lastKeyRef.current) {
|
|
48
58
|
if (singleSelect && lastIndicesRef.current.length === 1) {
|
|
49
59
|
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) });
|
|
@@ -120,21 +130,21 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
|
|
|
120
130
|
height: canvasSize,
|
|
121
131
|
width: canvasSize
|
|
122
132
|
};
|
|
123
|
-
return /* @__PURE__ */ (0,
|
|
124
|
-
/* @__PURE__ */ (0,
|
|
125
|
-
/* @__PURE__ */ (0,
|
|
133
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.View, { style: [styles11.container, gaugeSizeStyle], pointerEvents: "none", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native_skia.Canvas, { style: canvasSizeStyle, children: [
|
|
134
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_skia.Path, { path: unlitPath, style: "stroke", strokeWidth: UNLIT_THICKNESS, strokeCap: "round", color: mutedColor, opacity: 0.35 }),
|
|
135
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native_skia.Path, { path: litPath, style: "stroke", strokeWidth: LIT_THICKNESS, strokeCap: "round", color: accentColor, opacity: 1 })
|
|
126
136
|
] }) });
|
|
127
137
|
}
|
|
128
|
-
var import_react_native_skia, import_core5,
|
|
138
|
+
var import_react_native_skia, import_core5, import_react6, import_react_native13, import_react_native_reanimated, import_jsx_runtime13, 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, styles11;
|
|
129
139
|
var init_TriggerGauge = __esm({
|
|
130
140
|
"src/TriggerGauge.tsx"() {
|
|
131
141
|
"use strict";
|
|
132
142
|
import_react_native_skia = require("@shopify/react-native-skia");
|
|
133
143
|
import_core5 = require("@tastic/core");
|
|
134
|
-
|
|
135
|
-
|
|
144
|
+
import_react6 = require("react");
|
|
145
|
+
import_react_native13 = require("react-native");
|
|
136
146
|
import_react_native_reanimated = require("react-native-reanimated");
|
|
137
|
-
|
|
147
|
+
import_jsx_runtime13 = require("react/jsx-runtime");
|
|
138
148
|
UNLIT_THICKNESS = 3;
|
|
139
149
|
LIT_THICKNESS = 7;
|
|
140
150
|
DASH_GAP_PX = 9;
|
|
@@ -144,7 +154,7 @@ var init_TriggerGauge = __esm({
|
|
|
144
154
|
MOUNT_DURATION_MS = 450;
|
|
145
155
|
MOUNT_STAGGER_MS = 40;
|
|
146
156
|
SELECTION_TRANSITION_DURATION_MS = 260;
|
|
147
|
-
|
|
157
|
+
styles11 = import_react_native13.StyleSheet.create({
|
|
148
158
|
container: {
|
|
149
159
|
alignItems: "center",
|
|
150
160
|
justifyContent: "center",
|
|
@@ -157,7 +167,10 @@ var init_TriggerGauge = __esm({
|
|
|
157
167
|
// src/index.ts
|
|
158
168
|
var index_exports = {};
|
|
159
169
|
__export(index_exports, {
|
|
170
|
+
AchievementCatalogSection: () => AchievementCatalogSection,
|
|
160
171
|
AchievementRow: () => AchievementRow,
|
|
172
|
+
AchievementUnlockList: () => AchievementUnlockList,
|
|
173
|
+
ActivityStatSection: () => ActivityStatSection,
|
|
161
174
|
BaseSettingsDialog: () => BaseSettingsDialog,
|
|
162
175
|
BaseStatsScreen: () => BaseStatsScreen,
|
|
163
176
|
ConfirmDialog: () => ConfirmDialog,
|
|
@@ -170,25 +183,40 @@ __export(index_exports, {
|
|
|
170
183
|
LOCKED_BADGE_COLOR: () => LOCKED_BADGE_COLOR,
|
|
171
184
|
LabeledDropdown: () => LabeledDropdown,
|
|
172
185
|
MONO_FONT: () => MONO_FONT,
|
|
186
|
+
PlayerSetupPanel: () => PlayerSetupPanel,
|
|
173
187
|
PopoverBody: () => PopoverBody,
|
|
174
188
|
PressAwayOverlay: () => PressAwayOverlay,
|
|
175
189
|
ReadyButton: () => ReadyButton,
|
|
176
190
|
SectionedDropdown: () => SectionedDropdown,
|
|
177
191
|
SharedActionBand: () => SharedActionBand,
|
|
178
192
|
SkiaGate: () => SkiaGate,
|
|
193
|
+
StaggeredWord: () => StaggeredWord,
|
|
179
194
|
StatRow: () => StatRow,
|
|
180
195
|
StatSection: () => StatSection,
|
|
181
196
|
TriggerGaugeHost: () => TriggerGaugeHost,
|
|
182
197
|
UpdateDialog: () => UpdateDialog,
|
|
198
|
+
getColorPopoverId: () => getColorPopoverId,
|
|
199
|
+
getCpuDifficultyPopoverId: () => getCpuDifficultyPopoverId,
|
|
200
|
+
getInlineColorPickerContentSize: () => getInlineColorPickerContentSize,
|
|
183
201
|
getLabeledDropdownContentHeight: () => getLabeledDropdownContentHeight,
|
|
184
202
|
getOverlayCardColors: () => getOverlayCardColors,
|
|
203
|
+
getStaggeredWordDuration: () => getStaggeredWordDuration,
|
|
185
204
|
loadSkiaWeb: () => loadSkiaWeb,
|
|
205
|
+
overlayActionStyles: () => overlayActionStyles,
|
|
186
206
|
overlayStyles: () => overlayStyles,
|
|
187
207
|
useAutoAlign: () => useAutoAlign,
|
|
188
|
-
usePopoverHost: () => usePopoverHost
|
|
208
|
+
usePopoverHost: () => usePopoverHost,
|
|
209
|
+
useQuitConfirmation: () => useQuitConfirmation,
|
|
210
|
+
useZoneClampedAlign: () => useZoneClampedAlign
|
|
189
211
|
});
|
|
190
212
|
module.exports = __toCommonJS(index_exports);
|
|
191
213
|
|
|
214
|
+
// src/AchievementCatalogSection.tsx
|
|
215
|
+
var import_auto_paper2 = require("@rific/auto-paper");
|
|
216
|
+
var import_react = require("react");
|
|
217
|
+
var import_react_native3 = require("react-native");
|
|
218
|
+
var import_react_native_paper2 = require("react-native-paper");
|
|
219
|
+
|
|
192
220
|
// src/AchievementRow.tsx
|
|
193
221
|
var import_auto_paper = require("@rific/auto-paper");
|
|
194
222
|
var import_react_native = require("react-native");
|
|
@@ -257,24 +285,154 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
257
285
|
}
|
|
258
286
|
});
|
|
259
287
|
|
|
260
|
-
// src/
|
|
288
|
+
// src/fonts.ts
|
|
289
|
+
var import_react_native2 = require("react-native");
|
|
290
|
+
var MONO_FONT = import_react_native2.Platform.select({ ios: "Menlo", android: "monospace", default: "monospace" });
|
|
291
|
+
|
|
292
|
+
// src/AchievementCatalogSection.tsx
|
|
293
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
294
|
+
function AchievementCatalogSection({ rows, label = "ALL ACHIEVEMENTS", fg, fgMuted: fgMutedOverride }) {
|
|
295
|
+
const { dark } = (0, import_auto_paper2.useAutoPaperTheme)();
|
|
296
|
+
const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
|
|
297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react.Fragment, { children: [
|
|
298
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.Text, { variant: "labelMedium", style: [styles2.label, { color: fgMuted, fontFamily: MONO_FONT }], children: label }),
|
|
299
|
+
rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AchievementRow, { icon: row.icon, title: row.title, description: row.description, badgeColor: row.unlockedAt !== void 0 ? row.tierColor : LOCKED_BADGE_COLOR, checkColor: row.tierColor, unlockedLabel: row.unlockedLabel, progress: row.progress, deviceMarker: row.deviceMarker, fg, fgMuted: fgMutedOverride }, row.id))
|
|
300
|
+
] });
|
|
301
|
+
}
|
|
302
|
+
var styles2 = import_react_native3.StyleSheet.create({
|
|
303
|
+
label: {
|
|
304
|
+
letterSpacing: 2,
|
|
305
|
+
marginTop: 8
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// src/AchievementUnlockList.tsx
|
|
261
310
|
var import_auto_paper3 = require("@rific/auto-paper");
|
|
311
|
+
var import_profile = require("@tastic/profile");
|
|
312
|
+
var import_react_native4 = require("react-native");
|
|
313
|
+
var import_react_native_paper3 = require("react-native-paper");
|
|
314
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
315
|
+
var AVATAR_SIZE = 18;
|
|
316
|
+
function AchievementUnlockList({ unlocks, seats, owners, tierColors, fg: fgOverride, style }) {
|
|
317
|
+
const { dark } = (0, import_auto_paper3.useAutoPaperTheme)();
|
|
318
|
+
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
319
|
+
const rows = seats.flatMap((seat) => (unlocks[seat] ?? []).map((achievement) => ({ seat, achievement })));
|
|
320
|
+
if (rows.length === 0) return null;
|
|
321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.View, { style: [styles3.list, style], children: rows.map(({ seat, achievement }) => {
|
|
322
|
+
const owner = owners[seat];
|
|
323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.View, { style: styles3.row, children: [
|
|
324
|
+
owner.profile ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_profile.ProfileChip, { profile: owner.profile, size: AVATAR_SIZE }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.View, { style: [styles3.circle, { backgroundColor: owner.color }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Icon, { source: "account", size: 10, color: (0, import_auto_paper3.getContrastColor)(owner.color) }) }),
|
|
325
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.View, { style: [styles3.circle, { backgroundColor: tierColors[achievement.tier] }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Icon, { source: achievement.icon, size: 12, color: "#000000" }) }),
|
|
326
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Text, { style: [styles3.label, { color: fg }], numberOfLines: 1, children: achievement.title })
|
|
327
|
+
] }, `${seat}-${achievement.id}`);
|
|
328
|
+
}) });
|
|
329
|
+
}
|
|
330
|
+
var styles3 = import_react_native4.StyleSheet.create({
|
|
331
|
+
circle: {
|
|
332
|
+
alignItems: "center",
|
|
333
|
+
borderRadius: AVATAR_SIZE / 2,
|
|
334
|
+
height: AVATAR_SIZE,
|
|
335
|
+
justifyContent: "center",
|
|
336
|
+
width: AVATAR_SIZE
|
|
337
|
+
},
|
|
338
|
+
label: {
|
|
339
|
+
flexShrink: 1,
|
|
340
|
+
fontSize: 12,
|
|
341
|
+
fontWeight: "700"
|
|
342
|
+
},
|
|
343
|
+
list: {
|
|
344
|
+
gap: 6
|
|
345
|
+
},
|
|
346
|
+
row: {
|
|
347
|
+
alignItems: "center",
|
|
348
|
+
flexDirection: "row",
|
|
349
|
+
gap: 6
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
// src/StatRow.tsx
|
|
354
|
+
var import_auto_paper4 = require("@rific/auto-paper");
|
|
355
|
+
var import_react_native5 = require("react-native");
|
|
356
|
+
var import_react_native_paper4 = require("react-native-paper");
|
|
357
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
358
|
+
function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
|
|
359
|
+
const { dark } = (0, import_auto_paper4.useAutoPaperTheme)();
|
|
360
|
+
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
361
|
+
const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
|
|
362
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native5.View, { style: styles4.row, children: [
|
|
363
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_paper4.Text, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
|
|
364
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_paper4.Text, { variant: "bodyMedium", style: [styles4.value, { color: fg }], children: value })
|
|
365
|
+
] });
|
|
366
|
+
}
|
|
367
|
+
var styles4 = import_react_native5.StyleSheet.create({
|
|
368
|
+
row: {
|
|
369
|
+
alignItems: "center",
|
|
370
|
+
flexDirection: "row",
|
|
371
|
+
justifyContent: "space-between"
|
|
372
|
+
},
|
|
373
|
+
value: {
|
|
374
|
+
fontWeight: "bold"
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// src/StatSection.tsx
|
|
379
|
+
var import_auto_paper5 = require("@rific/auto-paper");
|
|
380
|
+
var import_react_native6 = require("react-native");
|
|
381
|
+
var import_react_native_paper5 = require("react-native-paper");
|
|
382
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
383
|
+
function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
|
|
384
|
+
const { dark } = (0, import_auto_paper5.useAutoPaperTheme)();
|
|
385
|
+
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
386
|
+
const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
|
|
387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native6.View, { style: [styles5.section, { backgroundColor: sectionBg }], children: [
|
|
388
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native_paper5.Text, { variant: "labelMedium", style: [styles5.label, { color: fg }], children: label }),
|
|
389
|
+
children
|
|
390
|
+
] });
|
|
391
|
+
}
|
|
392
|
+
var styles5 = import_react_native6.StyleSheet.create({
|
|
393
|
+
// Bold and full-contrast (fg), not the original fontless/fgMuted treatment — that read at the
|
|
394
|
+
// same visual weight as StatRow's own row labels below it (both used the identical muted color;
|
|
395
|
+
// letterSpacing/variant alone didn't separate them enough to read as "this is the group header"
|
|
396
|
+
// at a glance). Matches AchievementRow's own title styling (bold + fg) below it in the same list.
|
|
397
|
+
label: {
|
|
398
|
+
fontWeight: "bold",
|
|
399
|
+
letterSpacing: 2
|
|
400
|
+
},
|
|
401
|
+
section: {
|
|
402
|
+
borderRadius: 12,
|
|
403
|
+
gap: 8,
|
|
404
|
+
padding: 16
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// src/ActivityStatSection.tsx
|
|
409
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
410
|
+
function ActivityStatSection({ stats }) {
|
|
411
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(StatSection, { label: "ACTIVITY", children: [
|
|
412
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatRow, { label: "Days Played", value: String(stats.distinctDaysPlayed) }),
|
|
413
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatRow, { label: "Day Streak", value: String(stats.currentDayStreak) }),
|
|
414
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatRow, { label: "Best Day Streak", value: String(stats.bestDayStreak) })
|
|
415
|
+
] });
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// src/BaseSettingsDialog.tsx
|
|
419
|
+
var import_auto_paper7 = require("@rific/auto-paper");
|
|
262
420
|
var import_feedback_press2 = require("@rific/feedback-press");
|
|
263
421
|
var import_updater = require("@rific/updater");
|
|
264
422
|
var import_core2 = require("@tastic/core");
|
|
265
|
-
var
|
|
266
|
-
var
|
|
267
|
-
var
|
|
423
|
+
var import_react3 = require("react");
|
|
424
|
+
var import_react_native9 = require("react-native");
|
|
425
|
+
var import_react_native_paper7 = require("react-native-paper");
|
|
268
426
|
|
|
269
427
|
// src/ConfirmDialog.tsx
|
|
270
|
-
var
|
|
428
|
+
var import_auto_paper6 = require("@rific/auto-paper");
|
|
271
429
|
var import_feedback_press = require("@rific/feedback-press");
|
|
272
430
|
var import_core = require("@tastic/core");
|
|
273
|
-
var
|
|
274
|
-
var
|
|
431
|
+
var import_react_native8 = require("react-native");
|
|
432
|
+
var import_react_native_paper6 = require("react-native-paper");
|
|
275
433
|
|
|
276
434
|
// src/overlayCard.ts
|
|
277
|
-
var
|
|
435
|
+
var import_react_native7 = require("react-native");
|
|
278
436
|
function getOverlayCardColors(dark) {
|
|
279
437
|
return {
|
|
280
438
|
fg: dark ? "#FFFFFF" : "#000000",
|
|
@@ -283,7 +441,7 @@ function getOverlayCardColors(dark) {
|
|
|
283
441
|
cardBorder: dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)"
|
|
284
442
|
};
|
|
285
443
|
}
|
|
286
|
-
var overlayStyles =
|
|
444
|
+
var overlayStyles = import_react_native7.StyleSheet.create({
|
|
287
445
|
card: {
|
|
288
446
|
alignItems: "center",
|
|
289
447
|
borderRadius: 20,
|
|
@@ -303,27 +461,7 @@ var overlayStyles = import_react_native2.StyleSheet.create({
|
|
|
303
461
|
top: 0
|
|
304
462
|
}
|
|
305
463
|
});
|
|
306
|
-
|
|
307
|
-
// src/ConfirmDialog.tsx
|
|
308
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
309
|
-
function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
|
|
310
|
-
const { dark, colors } = (0, import_auto_paper2.useAutoPaperTheme)();
|
|
311
|
-
if (!visible) return null;
|
|
312
|
-
const { fg, cardBg, cardBorder } = getOverlayCardColors(dark);
|
|
313
|
-
const accent = destructive ? colors.danger : colors.primary;
|
|
314
|
-
const onAccent = destructive ? colors.onDanger : colors.onPrimary;
|
|
315
|
-
const showCancel = cancelLabel !== void 0 && onCancel !== void 0;
|
|
316
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.View, { style: [overlayStyles.overlay, styles2.overlay], children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native3.View, { style: [overlayStyles.card, styles2.card, { backgroundColor: cardBg, borderColor: cardBorder }, (0, import_core.toRotationStyle)(rotation)], children: [
|
|
317
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.Icon, { source: icon, size: 64, color: accent }),
|
|
318
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.Text, { variant: "headlineLarge", style: [styles2.title, { color: accent }], children: title }),
|
|
319
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.Text, { variant: "bodyLarge", style: [styles2.body, { color: fg }], children: message }),
|
|
320
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native3.View, { style: styles2.actions, children: [
|
|
321
|
-
showCancel && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_feedback_press.Button, { mode: "outlined", onPress: onCancel, style: styles2.actionButton, children: cancelLabel }),
|
|
322
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_feedback_press.Button, { mode: "contained", onPress: onConfirm, style: showCancel ? styles2.actionButton : styles2.actionButtonSingle, buttonColor: accent, textColor: onAccent, children: confirmLabel })
|
|
323
|
-
] })
|
|
324
|
-
] }) }) });
|
|
325
|
-
}
|
|
326
|
-
var styles2 = import_react_native3.StyleSheet.create({
|
|
464
|
+
var overlayActionStyles = import_react_native7.StyleSheet.create({
|
|
327
465
|
// minWidth (not flexBasis) is each button's real floor - whenever both fit side by side, flexGrow
|
|
328
466
|
// still splits any leftover width evenly beyond that floor, same visual result as a plain flex: 1
|
|
329
467
|
// on a roomy screen, but a button can never be squeezed narrower than 128, only wrap to its own
|
|
@@ -342,8 +480,8 @@ var styles2 = import_react_native3.StyleSheet.create({
|
|
|
342
480
|
// hardcodes numberOfLines={1} on its label with no override, so a button squeezed under its
|
|
343
481
|
// label's natural width silently ellipsizes ("Cancel" -> "Can...") instead of wrapping - assumed
|
|
344
482
|
// fixable by just giving the row more width, until confirmed live that these two-word labels
|
|
345
|
-
// (Cancel/Reset/New Game) can still lose the truncation fight even with the extra room
|
|
346
|
-
// width fix
|
|
483
|
+
// (Cancel/Reset/New Game) can still lose the truncation fight even with the extra room ConfirmDialog's own
|
|
484
|
+
// card width fix provides, on a narrow enough screen.
|
|
347
485
|
actionButton: {
|
|
348
486
|
flexGrow: 1,
|
|
349
487
|
minWidth: 128
|
|
@@ -362,7 +500,29 @@ var styles2 = import_react_native3.StyleSheet.create({
|
|
|
362
500
|
gap: 12,
|
|
363
501
|
justifyContent: "center",
|
|
364
502
|
width: "100%"
|
|
365
|
-
}
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
// src/ConfirmDialog.tsx
|
|
507
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
508
|
+
function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
|
|
509
|
+
const { dark, colors } = (0, import_auto_paper6.useAutoPaperTheme)();
|
|
510
|
+
if (!visible) return null;
|
|
511
|
+
const { fg, cardBg, cardBorder } = getOverlayCardColors(dark);
|
|
512
|
+
const accent = destructive ? colors.danger : colors.primary;
|
|
513
|
+
const onAccent = destructive ? colors.onDanger : colors.onPrimary;
|
|
514
|
+
const showCancel = cancelLabel !== void 0 && onCancel !== void 0;
|
|
515
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native8.View, { style: [overlayStyles.overlay, styles6.overlay], children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: [overlayStyles.card, styles6.card, { backgroundColor: cardBg, borderColor: cardBorder }, (0, import_core.toRotationStyle)(rotation)], children: [
|
|
516
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Icon, { source: icon, size: 64, color: accent }),
|
|
517
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Text, { variant: "headlineLarge", style: [styles6.title, { color: accent }], children: title }),
|
|
518
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Text, { variant: "bodyLarge", style: [styles6.body, { color: fg }], children: message }),
|
|
519
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: overlayActionStyles.actions, children: [
|
|
520
|
+
showCancel && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press.Button, { mode: "outlined", onPress: onCancel, style: overlayActionStyles.actionButton, children: cancelLabel }),
|
|
521
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press.Button, { mode: "contained", onPress: onConfirm, style: showCancel ? overlayActionStyles.actionButton : overlayActionStyles.actionButtonSingle, buttonColor: accent, textColor: onAccent, children: confirmLabel })
|
|
522
|
+
] })
|
|
523
|
+
] }) }) });
|
|
524
|
+
}
|
|
525
|
+
var styles6 = import_react_native8.StyleSheet.create({
|
|
366
526
|
body: {
|
|
367
527
|
textAlign: "center"
|
|
368
528
|
},
|
|
@@ -391,18 +551,18 @@ var styles2 = import_react_native3.StyleSheet.create({
|
|
|
391
551
|
});
|
|
392
552
|
|
|
393
553
|
// src/useUpdateConfirmBridge.ts
|
|
394
|
-
var
|
|
554
|
+
var import_react2 = require("react");
|
|
395
555
|
function useUpdateConfirmBridge() {
|
|
396
|
-
const [manifest, setManifest] = (0,
|
|
397
|
-
const resolveRef = (0,
|
|
398
|
-
const onConfirm = (0,
|
|
556
|
+
const [manifest, setManifest] = (0, import_react2.useState)(null);
|
|
557
|
+
const resolveRef = (0, import_react2.useRef)(null);
|
|
558
|
+
const onConfirm = (0, import_react2.useCallback)(
|
|
399
559
|
(next) => new Promise((resolve) => {
|
|
400
560
|
resolveRef.current = resolve;
|
|
401
561
|
setManifest(next);
|
|
402
562
|
}),
|
|
403
563
|
[]
|
|
404
564
|
);
|
|
405
|
-
const respond = (0,
|
|
565
|
+
const respond = (0, import_react2.useCallback)((confirmed) => {
|
|
406
566
|
setManifest(null);
|
|
407
567
|
resolveRef.current?.(confirmed);
|
|
408
568
|
resolveRef.current = null;
|
|
@@ -411,20 +571,20 @@ function useUpdateConfirmBridge() {
|
|
|
411
571
|
}
|
|
412
572
|
|
|
413
573
|
// src/BaseSettingsDialog.tsx
|
|
414
|
-
var
|
|
574
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
415
575
|
function SettingIcon({ source, color, containerColor }) {
|
|
416
|
-
return /* @__PURE__ */ (0,
|
|
576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, { style: [styles7.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Icon, { source, size: 18, color }) });
|
|
417
577
|
}
|
|
418
|
-
function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, children }) {
|
|
419
|
-
const { colors } = (0,
|
|
578
|
+
function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, onShowHowToPlay, children }) {
|
|
579
|
+
const { colors } = (0, import_auto_paper7.useAutoPaperTheme)();
|
|
420
580
|
const ambientRotation = (0, import_core2.useRotation)();
|
|
421
581
|
const rotation = rotationOverride ?? ambientRotation;
|
|
422
582
|
const isTouchPrimary = (0, import_core2.useIsTouchPrimaryDevice)();
|
|
423
583
|
const { settings: hapticSettings, set: setHapticSettings } = (0, import_feedback_press2.useHapticSettings)();
|
|
424
584
|
const { settings: soundSettings, set: setSoundSettings } = (0, import_feedback_press2.useSoundSettings)();
|
|
425
|
-
const sound = (0,
|
|
585
|
+
const sound = (0, import_react3.useContext)(import_feedback_press2.SoundContext);
|
|
426
586
|
const { forceShort: forceHapticFeedback } = (0, import_feedback_press2.useVibration)();
|
|
427
|
-
const [infoMessage, setInfoMessage] = (0,
|
|
587
|
+
const [infoMessage, setInfoMessage] = (0, import_react3.useState)(null);
|
|
428
588
|
const { manifest: updateManifest, onConfirm: onUpdateConfirm, respond: respondToUpdateConfirm } = useUpdateConfirmBridge();
|
|
429
589
|
const { check, checking, updateReady } = (0, import_updater.useUpdater)({
|
|
430
590
|
autoCheck: false,
|
|
@@ -435,32 +595,32 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
435
595
|
});
|
|
436
596
|
const updateManifestDate = updateManifest ? new Date(updateManifest.createdAt) : null;
|
|
437
597
|
const showLockOrientation = isTouchPrimary && lockOrientation !== void 0 && onLockOrientationChange !== void 0;
|
|
438
|
-
const showEdgeGuard =
|
|
439
|
-
const showHaptics =
|
|
598
|
+
const showEdgeGuard = import_react_native9.Platform.OS === "ios" && deferBottomEdgeGestures !== void 0 && onDeferBottomEdgeGestures !== void 0;
|
|
599
|
+
const showHaptics = import_react_native9.Platform.OS !== "web" && !hideHaptics;
|
|
440
600
|
const showSound = !hideSound;
|
|
441
601
|
const showAppearance = !hideAppearance;
|
|
442
|
-
const showUpdateCheck =
|
|
443
|
-
return /* @__PURE__ */ (0,
|
|
444
|
-
/* @__PURE__ */ (0,
|
|
445
|
-
/* @__PURE__ */ (0,
|
|
446
|
-
/* @__PURE__ */ (0,
|
|
447
|
-
/* @__PURE__ */ (0,
|
|
448
|
-
showLockOrientation && /* @__PURE__ */ (0,
|
|
449
|
-
/* @__PURE__ */ (0,
|
|
450
|
-
/* @__PURE__ */ (0,
|
|
451
|
-
/* @__PURE__ */ (0,
|
|
452
|
-
/* @__PURE__ */ (0,
|
|
602
|
+
const showUpdateCheck = import_react_native9.Platform.OS !== "web" && !hideUpdateCheck;
|
|
603
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
604
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_auto_paper7.Dialog, { visible, onDismiss, style: [styles7.dialog, (0, import_core2.toRotationStyle)(rotation)], children: [
|
|
605
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_auto_paper7.Dialog.Title, { children: "Settings" }),
|
|
606
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_auto_paper7.Dialog.ScrollArea, { style: styles7.scrollArea, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.ScrollView, { contentContainerStyle: styles7.content, showsVerticalScrollIndicator: false, children: [
|
|
607
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.toggleGroup, children: [
|
|
608
|
+
showLockOrientation && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => onLockOrientationChange(!lockOrientation), style: styles7.toggleButton, accessibilityLabel: `Lock orientation ${lockOrientation ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.toggleContent, children: [
|
|
609
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SettingIcon, { source: lockOrientation ? "lock" : "lock-open-variant-outline", color: lockOrientation ? colors.secondary : colors.onSurfaceVariant, containerColor: lockOrientation ? colors.secondaryContainer : colors.surfaceVariant }),
|
|
610
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.flexShrink, children: [
|
|
611
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
|
|
612
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pins the current layout" })
|
|
453
613
|
] })
|
|
454
614
|
] }) }),
|
|
455
|
-
showEdgeGuard && /* @__PURE__ */ (0,
|
|
456
|
-
/* @__PURE__ */ (0,
|
|
457
|
-
/* @__PURE__ */ (0,
|
|
458
|
-
/* @__PURE__ */ (0,
|
|
459
|
-
/* @__PURE__ */ (0,
|
|
615
|
+
showEdgeGuard && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => onDeferBottomEdgeGestures(!deferBottomEdgeGestures), style: styles7.toggleButton, accessibilityLabel: `Edge guard ${deferBottomEdgeGestures ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.toggleContent, children: [
|
|
616
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SettingIcon, { source: deferBottomEdgeGestures ? "shield-check-outline" : "shield-off-outline", color: deferBottomEdgeGestures ? colors.secondary : colors.onSurfaceVariant, containerColor: deferBottomEdgeGestures ? colors.secondaryContainer : colors.surfaceVariant }),
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.flexShrink, children: [
|
|
618
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Edge Guard" }),
|
|
619
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Requires a second swipe" })
|
|
460
620
|
] })
|
|
461
621
|
] }) }),
|
|
462
|
-
(showSound || showHaptics) && /* @__PURE__ */ (0,
|
|
463
|
-
showSound && /* @__PURE__ */ (0,
|
|
622
|
+
(showSound || showHaptics) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.toggleRow, children: [
|
|
623
|
+
showSound && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
464
624
|
import_feedback_press2.TouchableRipple,
|
|
465
625
|
{
|
|
466
626
|
soundDisabled: true,
|
|
@@ -469,15 +629,15 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
469
629
|
setSoundSettings({ enabled });
|
|
470
630
|
if (enabled) sound.selection?.();
|
|
471
631
|
},
|
|
472
|
-
style:
|
|
632
|
+
style: styles7.toggleButtonInRow,
|
|
473
633
|
accessibilityLabel: `Sound ${soundSettings.enabled ? "on" : "off"}`,
|
|
474
|
-
children: /* @__PURE__ */ (0,
|
|
475
|
-
/* @__PURE__ */ (0,
|
|
476
|
-
/* @__PURE__ */ (0,
|
|
634
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.toggleContent, children: [
|
|
635
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SettingIcon, { source: soundSettings.enabled ? "volume-high" : "volume-off", color: soundSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: soundSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
636
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Sound" })
|
|
477
637
|
] })
|
|
478
638
|
}
|
|
479
639
|
),
|
|
480
|
-
showHaptics && /* @__PURE__ */ (0,
|
|
640
|
+
showHaptics && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
481
641
|
import_feedback_press2.TouchableRipple,
|
|
482
642
|
{
|
|
483
643
|
hapticDisabled: true,
|
|
@@ -486,36 +646,54 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
486
646
|
setHapticSettings({ vibrate });
|
|
487
647
|
if (vibrate) forceHapticFeedback();
|
|
488
648
|
},
|
|
489
|
-
style:
|
|
649
|
+
style: styles7.toggleButtonInRow,
|
|
490
650
|
accessibilityLabel: `Haptics ${hapticSettings.vibrate ? "on" : "off"}`,
|
|
491
|
-
children: /* @__PURE__ */ (0,
|
|
492
|
-
/* @__PURE__ */ (0,
|
|
493
|
-
/* @__PURE__ */ (0,
|
|
651
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.toggleContent, children: [
|
|
652
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SettingIcon, { source: hapticSettings.vibrate ? "vibrate" : "vibrate-off", color: hapticSettings.vibrate ? colors.tertiary : colors.onSurfaceVariant, containerColor: hapticSettings.vibrate ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
653
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Haptics" })
|
|
494
654
|
] })
|
|
495
655
|
}
|
|
496
656
|
)
|
|
497
|
-
] })
|
|
657
|
+
] }),
|
|
658
|
+
onShowHowToPlay && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
659
|
+
import_feedback_press2.TouchableRipple,
|
|
660
|
+
{
|
|
661
|
+
onPress: () => {
|
|
662
|
+
onDismiss();
|
|
663
|
+
onShowHowToPlay();
|
|
664
|
+
},
|
|
665
|
+
style: styles7.toggleButton,
|
|
666
|
+
accessibilityLabel: "How to Play",
|
|
667
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.toggleContent, children: [
|
|
668
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SettingIcon, { source: "help-circle-outline", color: colors.secondary, containerColor: colors.secondaryContainer }),
|
|
669
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.flexShrink, children: [
|
|
670
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "How to Play" }),
|
|
671
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Replay the quick intro" })
|
|
672
|
+
] })
|
|
673
|
+
] })
|
|
674
|
+
}
|
|
675
|
+
)
|
|
498
676
|
] }),
|
|
499
|
-
showAppearance && /* @__PURE__ */ (0,
|
|
500
|
-
/* @__PURE__ */ (0,
|
|
501
|
-
/* @__PURE__ */ (0,
|
|
677
|
+
showAppearance && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.section, children: [
|
|
678
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Text, { variant: "labelMedium", style: [styles7.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
|
|
679
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_auto_paper7.AutoAppearancePicker, { showLabels: false })
|
|
502
680
|
] }),
|
|
503
681
|
children,
|
|
504
|
-
showUpdateCheck && /* @__PURE__ */ (0,
|
|
505
|
-
/* @__PURE__ */ (0,
|
|
682
|
+
showUpdateCheck && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: styles7.section, children: [
|
|
683
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native_paper7.Text, { variant: "labelSmall", style: [styles7.sectionLabel, { color: colors.onSurfaceVariant }], children: [
|
|
506
684
|
"VERSION ",
|
|
507
685
|
version,
|
|
508
686
|
updateReady ? " \xB7 UPDATE READY" : ""
|
|
509
687
|
] }),
|
|
510
|
-
/* @__PURE__ */ (0,
|
|
688
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_feedback_press2.Button, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
|
|
511
689
|
] })
|
|
512
690
|
] }) })
|
|
513
691
|
] }),
|
|
514
|
-
/* @__PURE__ */ (0,
|
|
515
|
-
/* @__PURE__ */ (0,
|
|
692
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(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) }),
|
|
693
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation, onConfirm: () => setInfoMessage(null) })
|
|
516
694
|
] });
|
|
517
695
|
}
|
|
518
|
-
var
|
|
696
|
+
var styles7 = import_react_native9.StyleSheet.create({
|
|
519
697
|
content: {
|
|
520
698
|
gap: 24,
|
|
521
699
|
paddingVertical: 20
|
|
@@ -583,31 +761,31 @@ var styles3 = import_react_native4.StyleSheet.create({
|
|
|
583
761
|
});
|
|
584
762
|
|
|
585
763
|
// src/BaseStatsScreen.tsx
|
|
586
|
-
var
|
|
764
|
+
var import_auto_paper8 = require("@rific/auto-paper");
|
|
587
765
|
var import_feedback_press3 = require("@rific/feedback-press");
|
|
588
766
|
var import_core3 = require("@tastic/core");
|
|
589
|
-
var
|
|
590
|
-
var
|
|
591
|
-
var
|
|
592
|
-
var
|
|
767
|
+
var import_react4 = require("react");
|
|
768
|
+
var import_react_native10 = require("react-native");
|
|
769
|
+
var import_react_native_paper8 = require("react-native-paper");
|
|
770
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
593
771
|
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 }) {
|
|
594
|
-
const { dark, colors } = (0,
|
|
772
|
+
const { dark, colors } = (0, import_auto_paper8.useAutoPaperTheme)();
|
|
595
773
|
const ambientRotation = (0, import_core3.useRotation)();
|
|
596
774
|
const rotation = rotationOverride ?? ambientRotation;
|
|
597
|
-
const [confirmResetVisible, setConfirmResetVisible] = (0,
|
|
775
|
+
const [confirmResetVisible, setConfirmResetVisible] = (0, import_react4.useState)(false);
|
|
598
776
|
const showReset = !!onReset;
|
|
599
777
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
600
778
|
const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
|
|
601
|
-
return /* @__PURE__ */ (0,
|
|
602
|
-
/* @__PURE__ */ (0,
|
|
603
|
-
/* @__PURE__ */ (0,
|
|
604
|
-
/* @__PURE__ */ (0,
|
|
779
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: [styles8.container, { backgroundColor: bg }], children: [
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: [styles8.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_feedback_press3.IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
|
|
782
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper8.Text, { variant: titleVariant, style: [styles8.title, { color: fg }], children: title })
|
|
605
783
|
] }),
|
|
606
|
-
/* @__PURE__ */ (0,
|
|
784
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.ScrollView, { style: styles8.scrollView, contentContainerStyle: [styles8.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
|
|
607
785
|
children,
|
|
608
|
-
showReset && /* @__PURE__ */ (0,
|
|
786
|
+
showReset && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_feedback_press3.Button, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles8.resetButton, children: resetLabel })
|
|
609
787
|
] }),
|
|
610
|
-
/* @__PURE__ */ (0,
|
|
788
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
611
789
|
ConfirmDialog,
|
|
612
790
|
{
|
|
613
791
|
visible: confirmResetVisible,
|
|
@@ -627,7 +805,7 @@ function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", t
|
|
|
627
805
|
)
|
|
628
806
|
] });
|
|
629
807
|
}
|
|
630
|
-
var
|
|
808
|
+
var styles8 = import_react_native10.StyleSheet.create({
|
|
631
809
|
container: {
|
|
632
810
|
flex: 1
|
|
633
811
|
},
|
|
@@ -659,18 +837,18 @@ var styles4 = import_react_native5.StyleSheet.create({
|
|
|
659
837
|
|
|
660
838
|
// src/ContentGutter.tsx
|
|
661
839
|
var import_core4 = require("@tastic/core");
|
|
662
|
-
var
|
|
663
|
-
var
|
|
840
|
+
var import_react_native11 = require("react-native");
|
|
841
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
664
842
|
function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
|
|
665
|
-
const { width: windowWidth } = (0,
|
|
843
|
+
const { width: windowWidth } = (0, import_core4.useRotatedWindowDimensions)();
|
|
666
844
|
const { contentWidth, gutterWidth } = (0, import_core4.computeContentBounds)(windowWidth, maxContentWidth ?? Infinity);
|
|
667
|
-
return /* @__PURE__ */ (0,
|
|
668
|
-
/* @__PURE__ */ (0,
|
|
669
|
-
/* @__PURE__ */ (0,
|
|
670
|
-
/* @__PURE__ */ (0,
|
|
845
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native11.View, { style: [styles9.row, style], children: [
|
|
846
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native11.View, { style: [styles9.gutter, { width: gutterWidth }], children: leftGutter }),
|
|
847
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native11.View, { style: { width: contentWidth }, children }),
|
|
848
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native11.View, { style: [styles9.gutter, { width: gutterWidth }], children: rightGutter })
|
|
671
849
|
] });
|
|
672
850
|
}
|
|
673
|
-
var
|
|
851
|
+
var styles9 = import_react_native11.StyleSheet.create({
|
|
674
852
|
// overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
|
|
675
853
|
// column instead of clipping cleanly at its own real width.
|
|
676
854
|
gutter: {
|
|
@@ -683,44 +861,40 @@ var styles5 = import_react_native6.StyleSheet.create({
|
|
|
683
861
|
|
|
684
862
|
// src/ControlSchemePicker.tsx
|
|
685
863
|
var import_core7 = require("@tastic/core");
|
|
686
|
-
var
|
|
864
|
+
var import_react_native16 = require("react-native");
|
|
687
865
|
|
|
688
866
|
// src/SectionedDropdown.tsx
|
|
689
|
-
var
|
|
867
|
+
var import_auto_paper9 = require("@rific/auto-paper");
|
|
690
868
|
var import_feedback_press4 = require("@rific/feedback-press");
|
|
691
869
|
var import_core6 = require("@tastic/core");
|
|
692
|
-
var
|
|
693
|
-
var
|
|
694
|
-
|
|
695
|
-
// src/fonts.ts
|
|
696
|
-
var import_react_native7 = require("react-native");
|
|
697
|
-
var MONO_FONT = import_react_native7.Platform.select({ ios: "Menlo", android: "monospace", default: "monospace" });
|
|
870
|
+
var import_react_native15 = require("react-native");
|
|
871
|
+
var import_react_native_paper9 = require("react-native-paper");
|
|
698
872
|
|
|
699
873
|
// src/PopoverBody.tsx
|
|
700
|
-
var
|
|
701
|
-
var
|
|
874
|
+
var import_react_native12 = require("react-native");
|
|
875
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
702
876
|
var CARET_SIZE = 7;
|
|
703
877
|
var CARET_RING_OFFSET = 2;
|
|
704
878
|
var CARET_DIP = 1;
|
|
705
879
|
function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
|
|
706
880
|
if (!visible) return null;
|
|
707
881
|
const above = verticalAlign === "above";
|
|
708
|
-
const alignStyle = align === "left" ?
|
|
709
|
-
const verticalStyle = above ?
|
|
882
|
+
const alignStyle = align === "left" ? styles10.contentLeft : align === "right" ? styles10.contentRight : styles10.contentCenter;
|
|
883
|
+
const verticalStyle = above ? styles10.contentAbove : styles10.contentBelow;
|
|
710
884
|
const ringSize = CARET_SIZE + caretBorderWidth;
|
|
711
885
|
const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
|
|
712
886
|
const caretFill = above ? "borderTopColor" : "borderBottomColor";
|
|
713
887
|
const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
|
|
714
888
|
const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
|
|
715
|
-
return /* @__PURE__ */ (0,
|
|
889
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.View, { style: [styles10.content, alignStyle, verticalStyle], children: [
|
|
716
890
|
children,
|
|
717
|
-
caretColor && /* @__PURE__ */ (0,
|
|
718
|
-
/* @__PURE__ */ (0,
|
|
719
|
-
/* @__PURE__ */ (0,
|
|
891
|
+
caretColor && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
892
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.View, { style: [styles10.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
|
|
893
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.View, { style: [styles10.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
|
|
720
894
|
] })
|
|
721
895
|
] });
|
|
722
896
|
}
|
|
723
|
-
var
|
|
897
|
+
var styles10 = import_react_native12.StyleSheet.create({
|
|
724
898
|
caret: {
|
|
725
899
|
borderLeftColor: "transparent",
|
|
726
900
|
borderRightColor: "transparent",
|
|
@@ -763,11 +937,11 @@ var styles6 = import_react_native8.StyleSheet.create({
|
|
|
763
937
|
});
|
|
764
938
|
|
|
765
939
|
// src/SkiaGate.tsx
|
|
766
|
-
var
|
|
767
|
-
var
|
|
940
|
+
var import_react5 = require("react");
|
|
941
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
768
942
|
function SkiaGate({ getComponent, componentProps, fallback = null }) {
|
|
769
|
-
const [Component, setComponent] = (0,
|
|
770
|
-
(0,
|
|
943
|
+
const [Component, setComponent] = (0, import_react5.useState)(null);
|
|
944
|
+
(0, import_react5.useEffect)(() => {
|
|
771
945
|
let cancelled = false;
|
|
772
946
|
getComponent().then((mod) => {
|
|
773
947
|
if (!cancelled) setComponent(() => mod.default);
|
|
@@ -777,19 +951,19 @@ function SkiaGate({ getComponent, componentProps, fallback = null }) {
|
|
|
777
951
|
};
|
|
778
952
|
}, [getComponent]);
|
|
779
953
|
if (!Component) return fallback;
|
|
780
|
-
return /* @__PURE__ */ (0,
|
|
954
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Component, { ...componentProps });
|
|
781
955
|
}
|
|
782
956
|
|
|
783
957
|
// src/TriggerGaugeHost.tsx
|
|
784
|
-
var
|
|
958
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
785
959
|
var getTriggerGauge = () => Promise.resolve().then(() => (init_TriggerGauge(), TriggerGauge_exports)).then((mod) => ({ default: mod.TriggerGauge }));
|
|
786
960
|
function TriggerGaugeHost(props) {
|
|
787
|
-
return /* @__PURE__ */ (0,
|
|
961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
|
|
788
962
|
}
|
|
789
963
|
|
|
790
964
|
// src/useAutoAlign.ts
|
|
791
|
-
var
|
|
792
|
-
var
|
|
965
|
+
var import_react7 = require("react");
|
|
966
|
+
var import_react_native14 = require("react-native");
|
|
793
967
|
var EDGE_MARGIN = 12;
|
|
794
968
|
function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
|
|
795
969
|
if (rotation === 0) return { x, y, width, height };
|
|
@@ -801,18 +975,18 @@ function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
|
|
|
801
975
|
return { x: cx + newDx - newWidth / 2, y: cy + newDy - newHeight / 2, width: newWidth, height: newHeight };
|
|
802
976
|
}
|
|
803
977
|
function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
804
|
-
const triggerRef = (0,
|
|
805
|
-
const { width: windowWidth, height: windowHeight } = (0,
|
|
806
|
-
const [align, setAlign] = (0,
|
|
807
|
-
const [verticalAlign, setVerticalAlign] = (0,
|
|
808
|
-
const [maxHeight, setMaxHeight] = (0,
|
|
809
|
-
const [measured, setMeasured] = (0,
|
|
810
|
-
const [prevOpen, setPrevOpen] = (0,
|
|
978
|
+
const triggerRef = (0, import_react7.useRef)(null);
|
|
979
|
+
const { width: windowWidth, height: windowHeight } = (0, import_react_native14.useWindowDimensions)();
|
|
980
|
+
const [align, setAlign] = (0, import_react7.useState)("center");
|
|
981
|
+
const [verticalAlign, setVerticalAlign] = (0, import_react7.useState)("below");
|
|
982
|
+
const [maxHeight, setMaxHeight] = (0, import_react7.useState)(contentHeight);
|
|
983
|
+
const [measured, setMeasured] = (0, import_react7.useState)(false);
|
|
984
|
+
const [prevOpen, setPrevOpen] = (0, import_react7.useState)(open);
|
|
811
985
|
if (open !== prevOpen) {
|
|
812
986
|
setPrevOpen(open);
|
|
813
987
|
if (open) setMeasured(false);
|
|
814
988
|
}
|
|
815
|
-
const measure = (0,
|
|
989
|
+
const measure = (0, import_react7.useCallback)(() => {
|
|
816
990
|
triggerRef.current?.measureInWindow((rawX, rawY, rawWidth, rawHeight) => {
|
|
817
991
|
const { x, y, width: triggerWidth, height: triggerHeight } = rotateRect(rawX, rawY, rawWidth, rawHeight, rotation, windowWidth, windowHeight);
|
|
818
992
|
const centerX = x + triggerWidth / 2;
|
|
@@ -829,14 +1003,14 @@ function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
|
829
1003
|
setMeasured(true);
|
|
830
1004
|
});
|
|
831
1005
|
}, [contentWidth, contentHeight, windowWidth, windowHeight, rotation]);
|
|
832
|
-
(0,
|
|
1006
|
+
(0, import_react7.useEffect)(() => {
|
|
833
1007
|
if (open) measure();
|
|
834
1008
|
}, [open, measure]);
|
|
835
1009
|
return { align, maxHeight, measured, triggerRef, verticalAlign };
|
|
836
1010
|
}
|
|
837
1011
|
|
|
838
1012
|
// src/SectionedDropdown.tsx
|
|
839
|
-
var
|
|
1013
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
840
1014
|
var MENU_BORDER_WIDTH = 1;
|
|
841
1015
|
var TRIGGER_SIZE = 44;
|
|
842
1016
|
var MENU_MIN_WIDTH = 200;
|
|
@@ -847,12 +1021,12 @@ var MENU_ITEM_HEIGHT = 40;
|
|
|
847
1021
|
var MENU_ITEM_HEIGHT_WITH_DESCRIPTION = 58;
|
|
848
1022
|
var MENU_DIVIDER_HEIGHT = 9;
|
|
849
1023
|
var MENU_VERTICAL_PADDING = 12;
|
|
850
|
-
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" } }) {
|
|
1024
|
+
function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accentColor, mutedColor, onAccentColor, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, autoDismiss = true, labelFontFamily = MONO_FONT, allClearLabels = { all: "All", clear: "Clear" } }) {
|
|
851
1025
|
const ambientRotation = (0, import_core6.useRotation)();
|
|
852
1026
|
const rotation = rotationOverride ?? ambientRotation;
|
|
853
1027
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
854
|
-
const menuBorderColor = (0,
|
|
855
|
-
const resolvedOnAccentColor = onAccentColor ?? (0,
|
|
1028
|
+
const menuBorderColor = (0, import_auto_paper9.getBlendedColor)(mutedColor, menuBg, 0.5);
|
|
1029
|
+
const resolvedOnAccentColor = onAccentColor ?? (0, import_auto_paper9.getColorRoles)(accentColor, menuBg).onColor;
|
|
856
1030
|
const fg = dark ? "#FFFFFF" : "#000000";
|
|
857
1031
|
const open = host.openId === id;
|
|
858
1032
|
const estimatedHeight = MENU_VERTICAL_PADDING + sections.reduce((sum, section, sectionIndex) => {
|
|
@@ -861,8 +1035,10 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
861
1035
|
const divider = sectionIndex > 0 ? MENU_DIVIDER_HEIGHT : 0;
|
|
862
1036
|
return sum + rows + footer + divider;
|
|
863
1037
|
}, 0);
|
|
864
|
-
const
|
|
865
|
-
const
|
|
1038
|
+
const auto = useAutoAlign(open, MENU_MAX_WIDTH, estimatedHeight, rotation);
|
|
1039
|
+
const placement = alignOverride ?? auto;
|
|
1040
|
+
const { maxHeight, measured, triggerRef, verticalAlign } = placement;
|
|
1041
|
+
const align = forcedAlign ?? placement.align;
|
|
866
1042
|
const onlySection = sections.length === 1 ? sections[0] : null;
|
|
867
1043
|
const selectedOption = onlySection?.kind === "single" ? onlySection.options.find((o) => o.value === onlySection.value) : void 0;
|
|
868
1044
|
const triggerIcon = selectedOption?.icon ?? icon;
|
|
@@ -884,17 +1060,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
884
1060
|
}
|
|
885
1061
|
gaugeOffset += section.options.length;
|
|
886
1062
|
}
|
|
887
|
-
const anchorStyle = [
|
|
1063
|
+
const anchorStyle = [styles12.anchor, open && styles12.anchorOpen];
|
|
888
1064
|
const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
|
|
889
1065
|
const dividerStyle = { backgroundColor: menuBorderColor };
|
|
890
|
-
return /* @__PURE__ */ (0,
|
|
891
|
-
/* @__PURE__ */ (0,
|
|
892
|
-
/* @__PURE__ */ (0,
|
|
893
|
-
/* @__PURE__ */ (0,
|
|
1066
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { style: anchorStyle, children: [
|
|
1067
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { ref: triggerRef, collapsable: false, style: styles12.triggerBox, children: [
|
|
1068
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
|
|
1069
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_feedback_press4.IconButton, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
|
|
894
1070
|
] }),
|
|
895
|
-
/* @__PURE__ */ (0,
|
|
896
|
-
sectionIndex > 0 && /* @__PURE__ */ (0,
|
|
897
|
-
section.kind === "single" ? /* @__PURE__ */ (0,
|
|
1071
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.ScrollView, { style: [styles12.menu, menuStyle], contentContainerStyle: styles12.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { children: [
|
|
1072
|
+
sectionIndex > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.View, { style: [styles12.divider, dividerStyle] }),
|
|
1073
|
+
section.kind === "single" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
898
1074
|
SingleSection,
|
|
899
1075
|
{
|
|
900
1076
|
section,
|
|
@@ -907,7 +1083,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
907
1083
|
if (autoDismiss) host.close();
|
|
908
1084
|
}
|
|
909
1085
|
}
|
|
910
|
-
) : /* @__PURE__ */ (0,
|
|
1086
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
|
|
911
1087
|
] }, section.id)) }) })
|
|
912
1088
|
] });
|
|
913
1089
|
}
|
|
@@ -919,18 +1095,18 @@ function SingleSection({
|
|
|
919
1095
|
labelFontFamily,
|
|
920
1096
|
onSelect
|
|
921
1097
|
}) {
|
|
922
|
-
return /* @__PURE__ */ (0,
|
|
1098
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children: section.options.map((option) => {
|
|
923
1099
|
const selected = option.value === section.value;
|
|
924
1100
|
const taken = !selected && option.value === section.takenValue;
|
|
925
1101
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
926
|
-
const itemStyle = [
|
|
1102
|
+
const itemStyle = [styles12.item, selected && { backgroundColor: accentColor }, taken && styles12.itemTaken];
|
|
927
1103
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
928
1104
|
const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
|
|
929
|
-
return /* @__PURE__ */ (0,
|
|
930
|
-
option.icon && /* @__PURE__ */ (0,
|
|
931
|
-
/* @__PURE__ */ (0,
|
|
932
|
-
/* @__PURE__ */ (0,
|
|
933
|
-
option.description && /* @__PURE__ */ (0,
|
|
1105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_feedback_press4.TouchableRipple, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { style: styles12.itemRow, children: [
|
|
1106
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper9.Icon, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
1107
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { style: styles12.itemLabelColumn, children: [
|
|
1108
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper9.Text, { variant: "labelLarge", style: labelStyle, children: option.label }),
|
|
1109
|
+
option.description && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper9.Text, { variant: "labelSmall", style: descriptionStyle, children: option.description })
|
|
934
1110
|
] })
|
|
935
1111
|
] }) }, option.value);
|
|
936
1112
|
}) });
|
|
@@ -944,23 +1120,23 @@ function MultiSection({
|
|
|
944
1120
|
allClearLabels
|
|
945
1121
|
}) {
|
|
946
1122
|
const allSelected = section.value.length === section.options.length;
|
|
947
|
-
return /* @__PURE__ */ (0,
|
|
1123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
948
1124
|
section.options.map((option, i) => {
|
|
949
1125
|
const selected = section.value.includes(option.value);
|
|
950
1126
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
951
1127
|
const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
|
|
952
1128
|
const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
|
|
953
|
-
const itemStyle = [
|
|
1129
|
+
const itemStyle = [styles12.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
|
|
954
1130
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
955
|
-
return /* @__PURE__ */ (0,
|
|
956
|
-
option.icon && /* @__PURE__ */ (0,
|
|
957
|
-
/* @__PURE__ */ (0,
|
|
1131
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.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_runtime15.jsxs)(import_react_native15.View, { style: styles12.itemRow, children: [
|
|
1132
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper9.Icon, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
1133
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper9.Text, { variant: "labelLarge", style: [styles12.itemLabelFlex, labelStyle], children: option.label })
|
|
958
1134
|
] }) }, option.value);
|
|
959
1135
|
}),
|
|
960
|
-
section.allClear && /* @__PURE__ */ (0,
|
|
1136
|
+
section.allClear && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_feedback_press4.TouchableRipple, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles12.item, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper9.Text, { variant: "labelLarge", style: [styles12.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
|
|
961
1137
|
] });
|
|
962
1138
|
}
|
|
963
|
-
var
|
|
1139
|
+
var styles12 = import_react_native15.StyleSheet.create({
|
|
964
1140
|
allClearLabel: {
|
|
965
1141
|
fontWeight: "bold",
|
|
966
1142
|
textAlign: "center"
|
|
@@ -977,7 +1153,7 @@ var styles8 = import_react_native11.StyleSheet.create({
|
|
|
977
1153
|
zIndex: 100
|
|
978
1154
|
},
|
|
979
1155
|
divider: {
|
|
980
|
-
height:
|
|
1156
|
+
height: import_react_native15.StyleSheet.hairlineWidth,
|
|
981
1157
|
marginVertical: 4
|
|
982
1158
|
},
|
|
983
1159
|
item: {
|
|
@@ -1030,24 +1206,24 @@ var styles8 = import_react_native11.StyleSheet.create({
|
|
|
1030
1206
|
});
|
|
1031
1207
|
|
|
1032
1208
|
// src/ControlSchemePicker.tsx
|
|
1033
|
-
var
|
|
1034
|
-
function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, labelFontFamily }) {
|
|
1209
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1210
|
+
function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, alignOverride, rotation, labelFontFamily }) {
|
|
1035
1211
|
const isTouchPrimary = (0, import_core7.useIsTouchPrimaryDevice)();
|
|
1036
|
-
if (
|
|
1037
|
-
return /* @__PURE__ */ (0,
|
|
1212
|
+
if (import_react_native16.Platform.OS !== "web" || isTouchPrimary) return null;
|
|
1213
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SectionedDropdown, { id, host, icon: "keyboard-outline", accessibilityLabel: "Control scheme", sections: [{ kind: "single", id: "controls", options, value, onChange, takenValue }], accentColor, mutedColor, onAccentColor, dark, align, alignOverride, rotation, labelFontFamily });
|
|
1038
1214
|
}
|
|
1039
1215
|
|
|
1040
1216
|
// src/CornerActionButtons.tsx
|
|
1041
1217
|
var import_feedback_press5 = require("@rific/feedback-press");
|
|
1042
|
-
var
|
|
1043
|
-
var
|
|
1218
|
+
var import_react_native17 = require("react-native");
|
|
1219
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1044
1220
|
function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back" }) {
|
|
1045
|
-
return /* @__PURE__ */ (0,
|
|
1046
|
-
/* @__PURE__ */ (0,
|
|
1047
|
-
/* @__PURE__ */ (0,
|
|
1221
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
1222
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_feedback_press5.IconButton, { icon: backIcon, iconColor: fg, size: 24, style: [styles13.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: backLabel }),
|
|
1223
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_feedback_press5.IconButton, { icon: "cog", iconColor: fg, size: 24, style: [styles13.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
|
|
1048
1224
|
] });
|
|
1049
1225
|
}
|
|
1050
|
-
var
|
|
1226
|
+
var styles13 = import_react_native17.StyleSheet.create({
|
|
1051
1227
|
back: {
|
|
1052
1228
|
position: "absolute"
|
|
1053
1229
|
},
|
|
@@ -1057,22 +1233,22 @@ var styles9 = import_react_native13.StyleSheet.create({
|
|
|
1057
1233
|
});
|
|
1058
1234
|
|
|
1059
1235
|
// src/CornerStatusBadges.tsx
|
|
1060
|
-
var
|
|
1061
|
-
var
|
|
1062
|
-
var
|
|
1236
|
+
var import_react_native18 = require("react-native");
|
|
1237
|
+
var import_react_native_paper10 = require("react-native-paper");
|
|
1238
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1063
1239
|
var BADGE_SIZE = 30;
|
|
1064
1240
|
function StatusBadge({ icon }) {
|
|
1065
|
-
return /* @__PURE__ */ (0,
|
|
1241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native18.View, { style: styles14.badge, children: icon && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native_paper10.Icon, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
|
|
1066
1242
|
}
|
|
1067
1243
|
function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
|
|
1068
1244
|
const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
|
|
1069
1245
|
const p2OnLeftSide = orientationMode === "sideBySide" && !p1OnRight;
|
|
1070
|
-
return /* @__PURE__ */ (0,
|
|
1071
|
-
p1 && /* @__PURE__ */ (0,
|
|
1072
|
-
p2 && /* @__PURE__ */ (0,
|
|
1246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
1247
|
+
p1 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native18.View, { pointerEvents: "none", style: p1OnRightSide ? styles14.bottomRight : styles14.bottomLeft, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StatusBadge, { icon: p1.icon }) }),
|
|
1248
|
+
p2 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native18.View, { pointerEvents: "none", style: p2OnLeftSide ? styles14.topLeft : styles14.topRight, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StatusBadge, { icon: p2.icon }) })
|
|
1073
1249
|
] });
|
|
1074
1250
|
}
|
|
1075
|
-
var
|
|
1251
|
+
var styles14 = import_react_native18.StyleSheet.create({
|
|
1076
1252
|
badge: {
|
|
1077
1253
|
alignItems: "center",
|
|
1078
1254
|
backgroundColor: "rgba(0,0,0,0.28)",
|
|
@@ -1091,12 +1267,12 @@ var styles10 = import_react_native14.StyleSheet.create({
|
|
|
1091
1267
|
});
|
|
1092
1268
|
|
|
1093
1269
|
// src/InlineColorPicker.tsx
|
|
1094
|
-
var
|
|
1270
|
+
var import_auto_paper10 = require("@rific/auto-paper");
|
|
1095
1271
|
var import_feedback_press6 = require("@rific/feedback-press");
|
|
1096
1272
|
var import_core8 = require("@tastic/core");
|
|
1097
|
-
var
|
|
1098
|
-
var
|
|
1099
|
-
var
|
|
1273
|
+
var import_react_native19 = require("react-native");
|
|
1274
|
+
var import_react_native_paper11 = require("react-native-paper");
|
|
1275
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1100
1276
|
var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
|
|
1101
1277
|
var DEFAULT_SIZE = 48;
|
|
1102
1278
|
var SWATCH_SIZE = 28;
|
|
@@ -1109,31 +1285,37 @@ var SCREEN_MARGIN = 40;
|
|
|
1109
1285
|
function widthForColumns(columns) {
|
|
1110
1286
|
return SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * columns + SWATCHES_GAP * (columns - 1);
|
|
1111
1287
|
}
|
|
1112
|
-
function
|
|
1288
|
+
function getInlineColorPickerContentSize(swatchCount, windowWidth, columns) {
|
|
1289
|
+
const autoColumns = (0, import_core8.clamp)(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS);
|
|
1290
|
+
const resolvedColumns = columns ?? autoColumns;
|
|
1291
|
+
const width = widthForColumns(resolvedColumns);
|
|
1292
|
+
const rows = Math.ceil(swatchCount / resolvedColumns);
|
|
1293
|
+
const height = SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * rows + SWATCHES_GAP * (rows - 1);
|
|
1294
|
+
return { width, height };
|
|
1295
|
+
}
|
|
1296
|
+
function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = import_auto_paper10.defaultColors, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
|
|
1113
1297
|
const ambientRotation = (0, import_core8.useRotation)();
|
|
1114
1298
|
const rotation = rotationOverride ?? ambientRotation;
|
|
1115
1299
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
1116
|
-
const { width: windowWidth } = (0,
|
|
1117
|
-
const
|
|
1118
|
-
const resolvedColumns = columns ?? autoColumns;
|
|
1119
|
-
const swatchesWidth = widthForColumns(resolvedColumns);
|
|
1120
|
-
const swatchRows = Math.ceil(swatches.length / resolvedColumns);
|
|
1121
|
-
const swatchesHeight = SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * swatchRows + SWATCHES_GAP * (swatchRows - 1);
|
|
1300
|
+
const { width: windowWidth } = (0, import_react_native19.useWindowDimensions)();
|
|
1301
|
+
const { width: swatchesWidth, height: swatchesHeight } = getInlineColorPickerContentSize(swatches.length, windowWidth, columns);
|
|
1122
1302
|
const open = host.openId === id;
|
|
1123
|
-
const
|
|
1124
|
-
const
|
|
1303
|
+
const auto = useAutoAlign(open, swatchesWidth, swatchesHeight, rotation);
|
|
1304
|
+
const placement = alignOverride ?? auto;
|
|
1305
|
+
const { maxHeight, measured, triggerRef, verticalAlign } = placement;
|
|
1306
|
+
const align = forcedAlign ?? placement.align;
|
|
1125
1307
|
const displayFor = previewValue ?? ((hex) => hex);
|
|
1126
1308
|
const displayValue = displayFor(value);
|
|
1127
|
-
const contrastColor = (0,
|
|
1309
|
+
const contrastColor = (0, import_auto_paper10.getContrastColor)(displayValue);
|
|
1128
1310
|
const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
|
|
1129
|
-
return /* @__PURE__ */ (0,
|
|
1130
|
-
/* @__PURE__ */ (0,
|
|
1131
|
-
/* @__PURE__ */ (0,
|
|
1311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native19.View, { style: [styles15.anchor, open && styles15.anchorOpen], children: [
|
|
1312
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_feedback_press6.TouchableRipple, { onPress: () => host.toggle(id), borderless: true, style: [styles15.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native19.View, { ref: triggerRef, collapsable: false, style: styles15.triggerMeasure, children: tag ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper11.Text, { style: [styles15.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper11.Icon, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
|
|
1313
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native19.ScrollView, { style: [styles15.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles15.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
|
|
1132
1314
|
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
1133
1315
|
const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
|
|
1134
1316
|
const swappable = taken && allowSwapTaken;
|
|
1135
1317
|
const swatchDisplay = displayFor(swatch.value);
|
|
1136
|
-
return /* @__PURE__ */ (0,
|
|
1318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1137
1319
|
import_feedback_press6.TouchableRipple,
|
|
1138
1320
|
{
|
|
1139
1321
|
disabled: taken && !swappable,
|
|
@@ -1142,15 +1324,15 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
|
|
|
1142
1324
|
if (autoDismiss) host.close();
|
|
1143
1325
|
},
|
|
1144
1326
|
borderless: true,
|
|
1145
|
-
style: [
|
|
1146
|
-
children: selected ? /* @__PURE__ */ (0,
|
|
1327
|
+
style: [styles15.swatch, { backgroundColor: swatchDisplay }, selected && styles15.swatchSelected, taken && !swappable && styles15.swatchTaken],
|
|
1328
|
+
children: selected ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper11.Icon, { source: "check", size: 16, color: (0, import_auto_paper10.getContrastColor)(swatchDisplay) }) : swappable ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper11.Icon, { source: "swap-horizontal", size: 16, color: (0, import_auto_paper10.getContrastColor)(swatchDisplay) }) : taken ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper11.Icon, { source: "close", size: 16, color: (0, import_auto_paper10.getContrastColor)(swatchDisplay) }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native19.View, {})
|
|
1147
1329
|
},
|
|
1148
1330
|
swatch.value
|
|
1149
1331
|
);
|
|
1150
1332
|
}) }) })
|
|
1151
1333
|
] });
|
|
1152
1334
|
}
|
|
1153
|
-
var
|
|
1335
|
+
var styles15 = import_react_native19.StyleSheet.create({
|
|
1154
1336
|
anchor: {
|
|
1155
1337
|
position: "relative"
|
|
1156
1338
|
},
|
|
@@ -1222,11 +1404,11 @@ var styles11 = import_react_native15.StyleSheet.create({
|
|
|
1222
1404
|
});
|
|
1223
1405
|
|
|
1224
1406
|
// src/LabeledDropdown.tsx
|
|
1225
|
-
var
|
|
1407
|
+
var import_auto_paper11 = require("@rific/auto-paper");
|
|
1226
1408
|
var import_feedback_press7 = require("@rific/feedback-press");
|
|
1227
|
-
var
|
|
1228
|
-
var
|
|
1229
|
-
var
|
|
1409
|
+
var import_react_native20 = require("react-native");
|
|
1410
|
+
var import_react_native_paper12 = require("react-native-paper");
|
|
1411
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1230
1412
|
var TRIGGER_HEIGHT = 28;
|
|
1231
1413
|
var POPOVER_WIDTH = 180;
|
|
1232
1414
|
var ROW_HEIGHT = 36;
|
|
@@ -1249,22 +1431,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
|
|
|
1249
1431
|
onChange(option.value);
|
|
1250
1432
|
host.close();
|
|
1251
1433
|
};
|
|
1252
|
-
return /* @__PURE__ */ (0,
|
|
1253
|
-
/* @__PURE__ */ (0,
|
|
1254
|
-
/* @__PURE__ */ (0,
|
|
1255
|
-
/* @__PURE__ */ (0,
|
|
1434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native20.View, { style: [styles16.anchor, open && styles16.anchorOpen], children: [
|
|
1435
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_feedback_press7.TouchableRipple, { onPress: () => host.toggle(id), style: styles16.trigger, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native20.View, { ref: triggerRef, collapsable: false, style: styles16.triggerInner, children: [
|
|
1436
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_paper12.Text, { style: [styles16.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
|
|
1437
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_paper12.Icon, { source: "menu-down", size: 16, color })
|
|
1256
1438
|
] }) }),
|
|
1257
|
-
/* @__PURE__ */ (0,
|
|
1439
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native20.ScrollView, { style: [styles16.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles16.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
|
|
1258
1440
|
const isSelected = option.value === value;
|
|
1259
|
-
const onColor = (0,
|
|
1260
|
-
return /* @__PURE__ */ (0,
|
|
1261
|
-
option.icon && /* @__PURE__ */ (0,
|
|
1262
|
-
/* @__PURE__ */ (0,
|
|
1441
|
+
const onColor = (0, import_auto_paper11.getContrastColor)(color);
|
|
1442
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_feedback_press7.TouchableRipple, { onPress: () => handleSelect(option), style: [styles16.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native20.View, { style: styles16.rowInner, children: [
|
|
1443
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_paper12.Icon, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
|
|
1444
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_paper12.Text, { style: [styles16.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
|
|
1263
1445
|
] }) }, option.value);
|
|
1264
1446
|
}) }) })
|
|
1265
1447
|
] });
|
|
1266
1448
|
}
|
|
1267
|
-
var
|
|
1449
|
+
var styles16 = import_react_native20.StyleSheet.create({
|
|
1268
1450
|
anchor: {
|
|
1269
1451
|
position: "relative"
|
|
1270
1452
|
},
|
|
@@ -1321,26 +1503,23 @@ function loadSkiaWeb() {
|
|
|
1321
1503
|
return Promise.resolve();
|
|
1322
1504
|
}
|
|
1323
1505
|
|
|
1324
|
-
// src/
|
|
1325
|
-
var
|
|
1326
|
-
var
|
|
1327
|
-
|
|
1328
|
-
if (!active) return null;
|
|
1329
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native17.Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [import_react_native17.StyleSheet.absoluteFill, style] });
|
|
1330
|
-
}
|
|
1506
|
+
// src/PlayerSetupPanel.tsx
|
|
1507
|
+
var import_profile2 = require("@tastic/profile");
|
|
1508
|
+
var import_react_native22 = require("react-native");
|
|
1509
|
+
var import_react_native_paper14 = require("react-native-paper");
|
|
1331
1510
|
|
|
1332
1511
|
// src/ReadyButton.tsx
|
|
1333
1512
|
var import_feedback_press8 = require("@rific/feedback-press");
|
|
1334
|
-
var
|
|
1335
|
-
var
|
|
1336
|
-
var
|
|
1513
|
+
var import_react_native21 = require("react-native");
|
|
1514
|
+
var import_react_native_paper13 = require("react-native-paper");
|
|
1515
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1337
1516
|
function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
|
|
1338
|
-
const readyButtonStyle = [
|
|
1517
|
+
const readyButtonStyle = [styles17.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
|
|
1339
1518
|
const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
|
|
1340
1519
|
const labelColorStyle = { color: ready ? "#000000" : color };
|
|
1341
|
-
return /* @__PURE__ */ (0,
|
|
1520
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_feedback_press8.TouchableRipple, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native_paper13.Text, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
|
|
1342
1521
|
}
|
|
1343
|
-
var
|
|
1522
|
+
var styles17 = import_react_native21.StyleSheet.create({
|
|
1344
1523
|
readyButton: {
|
|
1345
1524
|
alignItems: "center",
|
|
1346
1525
|
borderRadius: 12,
|
|
@@ -1352,22 +1531,97 @@ var styles13 = import_react_native18.StyleSheet.create({
|
|
|
1352
1531
|
}
|
|
1353
1532
|
});
|
|
1354
1533
|
|
|
1534
|
+
// src/usePopoverHost.ts
|
|
1535
|
+
var import_react8 = require("react");
|
|
1536
|
+
function usePopoverHost() {
|
|
1537
|
+
const [openId, setOpenId] = (0, import_react8.useState)(null);
|
|
1538
|
+
const toggle = (0, import_react8.useCallback)((id) => {
|
|
1539
|
+
setOpenId((prev) => prev === id ? null : id);
|
|
1540
|
+
}, []);
|
|
1541
|
+
const close = (0, import_react8.useCallback)(() => setOpenId(null), []);
|
|
1542
|
+
return { openId, toggle, close };
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
// src/PlayerSetupPanel.tsx
|
|
1546
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1547
|
+
function getColorPopoverId(idPrefix) {
|
|
1548
|
+
return `${idPrefix}-color`;
|
|
1549
|
+
}
|
|
1550
|
+
function getCpuDifficultyPopoverId(idPrefix) {
|
|
1551
|
+
return `${idPrefix}-difficulty`;
|
|
1552
|
+
}
|
|
1553
|
+
function PlayerSetupPanel({ idPrefix, host, label, labelFontFamily, color, onColorChange, swatches, takenColor, allowSwapTaken, colorAlignOverride, colorRotation, isHuman, secondPicker, secondPickerId, ready, onToggleReady, dark, showReadyButton = true, profiles, selectedProfileId, takenProfileId, guestLabel, onProfileSelect, onManageProfiles, cpuDifficulty, cpuDifficultyOptions, onCpuDifficultyChange, cpuDifficultyAlignOverride, humanIcon = "face-man", cpuIcon = "robot" }) {
|
|
1554
|
+
const ownHost = usePopoverHost();
|
|
1555
|
+
const popover = host ?? ownHost;
|
|
1556
|
+
const ownPopoverOpen = popover.openId?.startsWith(`${idPrefix}-`) ?? false;
|
|
1557
|
+
const pickerRowPopoverOpen = popover.openId === getColorPopoverId(idPrefix) || secondPickerId !== void 0 && popover.openId === secondPickerId;
|
|
1558
|
+
const showProfilePicker = isHuman && profiles !== void 0 && !!onProfileSelect;
|
|
1559
|
+
const showCpuDifficulty = !isHuman && cpuDifficulty !== void 0 && cpuDifficultyOptions !== void 0 && !!onCpuDifficultyChange;
|
|
1560
|
+
const selectedProfile = profiles?.find((p) => p.id === selectedProfileId) ?? null;
|
|
1561
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native22.View, { style: [styles18.panel, ownPopoverOpen && styles18.panelOpen], children: [
|
|
1562
|
+
showProfilePicker ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_profile2.ProfilePicker, { idPrefix, host: popover, profiles, selectedId: selectedProfileId ?? null, takenId: takenProfileId, color, dark, guestLabel: guestLabel ?? "GUEST", onSelect: (profile) => onProfileSelect?.(profile), onManage: onManageProfiles }) : showCpuDifficulty ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(LabeledDropdown, { id: getCpuDifficultyPopoverId(idPrefix), host: popover, options: cpuDifficultyOptions, value: cpuDifficulty, onChange: onCpuDifficultyChange, color, dark, alignOverride: cpuDifficultyAlignOverride }) : label && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native_paper14.Text, { variant: "labelSmall", style: { color, fontFamily: labelFontFamily }, children: label }),
|
|
1563
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native22.View, { style: [styles18.pickerRow, pickerRowPopoverOpen && styles18.pickerRowOpen], children: [
|
|
1564
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(InlineColorPicker, { id: getColorPopoverId(idPrefix), host: popover, value: color, onChange: onColorChange, swatches, takenValue: takenColor, allowSwapTaken, alignOverride: colorAlignOverride, rotation: colorRotation, dark, tag: isHuman ? selectedProfile?.tag : void 0, icon: isHuman ? humanIcon : cpuIcon }),
|
|
1565
|
+
secondPicker
|
|
1566
|
+
] }),
|
|
1567
|
+
isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ReadyButton, { color, ready: ready ?? false, onToggleReady })
|
|
1568
|
+
] });
|
|
1569
|
+
}
|
|
1570
|
+
var styles18 = import_react_native22.StyleSheet.create({
|
|
1571
|
+
panel: {
|
|
1572
|
+
alignItems: "center",
|
|
1573
|
+
gap: 12
|
|
1574
|
+
},
|
|
1575
|
+
// See SectionedDropdown's anchorOpen comment — this panel is typically a sibling of another
|
|
1576
|
+
// panel (and/or a shared-controls row), so a popover escaping this panel's bounds needs the panel
|
|
1577
|
+
// itself elevated, not just the popover content, to paint above a later sibling.
|
|
1578
|
+
panelOpen: {
|
|
1579
|
+
zIndex: 100
|
|
1580
|
+
},
|
|
1581
|
+
// Same gap as `panel`'s own vertical rhythm, reused horizontally — the color picker and (when
|
|
1582
|
+
// present) secondPicker sit side by side within this row instead of stacked in the panel's own
|
|
1583
|
+
// column.
|
|
1584
|
+
pickerRow: {
|
|
1585
|
+
alignItems: "center",
|
|
1586
|
+
flexDirection: "row",
|
|
1587
|
+
gap: 12
|
|
1588
|
+
},
|
|
1589
|
+
// A popover is an absolutely-positioned sibling of its own trigger — so a tall one (the color
|
|
1590
|
+
// swatch grid) can extend down far enough to overlap the ReadyButton below, which paints on top of
|
|
1591
|
+
// it by default DOM order since it's a later sibling within `panel`. `panel`'s own panelOpen
|
|
1592
|
+
// elevation only helps this panel paint above OTHER panels (see its own comment) — it does nothing
|
|
1593
|
+
// for stacking *within* this panel, since React Native Web gives each View its own stacking
|
|
1594
|
+
// context. This is what actually fixes that: elevate pickerRow itself above its own later sibling
|
|
1595
|
+
// whenever one of its own popovers is open.
|
|
1596
|
+
pickerRowOpen: {
|
|
1597
|
+
zIndex: 100
|
|
1598
|
+
}
|
|
1599
|
+
});
|
|
1600
|
+
|
|
1601
|
+
// src/PressAwayOverlay.tsx
|
|
1602
|
+
var import_react_native23 = require("react-native");
|
|
1603
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1604
|
+
function PressAwayOverlay({ active, onPress, style }) {
|
|
1605
|
+
if (!active) return null;
|
|
1606
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native23.Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [import_react_native23.StyleSheet.absoluteFill, style] });
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1355
1609
|
// src/SharedActionBand.tsx
|
|
1356
1610
|
var import_feedback_press9 = require("@rific/feedback-press");
|
|
1357
|
-
var
|
|
1358
|
-
var
|
|
1611
|
+
var import_react_native24 = require("react-native");
|
|
1612
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1359
1613
|
function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
|
|
1360
|
-
return /* @__PURE__ */ (0,
|
|
1361
|
-
/* @__PURE__ */ (0,
|
|
1362
|
-
/* @__PURE__ */ (0,
|
|
1363
|
-
onRandomize && /* @__PURE__ */ (0,
|
|
1364
|
-
onReset && /* @__PURE__ */ (0,
|
|
1365
|
-
/* @__PURE__ */ (0,
|
|
1614
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native24.View, { style: [styles19.column, popoverOpen && styles19.columnOpen], children: [
|
|
1615
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native24.View, { style: styles19.actionsRow, children: [
|
|
1616
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_feedback_press9.IconButton, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
|
|
1617
|
+
onRandomize && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_feedback_press9.IconButton, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
|
|
1618
|
+
onReset && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_feedback_press9.IconButton, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
|
|
1619
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_feedback_press9.IconButton, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
|
|
1366
1620
|
] }),
|
|
1367
1621
|
children
|
|
1368
1622
|
] });
|
|
1369
1623
|
}
|
|
1370
|
-
var
|
|
1624
|
+
var styles19 = import_react_native24.StyleSheet.create({
|
|
1371
1625
|
actionsRow: {
|
|
1372
1626
|
alignItems: "center",
|
|
1373
1627
|
flexDirection: "row",
|
|
@@ -1382,84 +1636,111 @@ var styles14 = import_react_native19.StyleSheet.create({
|
|
|
1382
1636
|
}
|
|
1383
1637
|
});
|
|
1384
1638
|
|
|
1385
|
-
// src/
|
|
1386
|
-
var
|
|
1387
|
-
var
|
|
1388
|
-
var
|
|
1389
|
-
var
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native20.View, { style: styles15.row, children: [
|
|
1395
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper10.Text, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
|
|
1396
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper10.Text, { variant: "bodyMedium", style: [styles15.value, { color: fg }], children: value })
|
|
1397
|
-
] });
|
|
1639
|
+
// src/StaggeredWord.tsx
|
|
1640
|
+
var import_react9 = require("react");
|
|
1641
|
+
var import_react_native25 = require("react-native");
|
|
1642
|
+
var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
|
|
1643
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1644
|
+
var STAGGER_MS = 45;
|
|
1645
|
+
var LETTER_DURATION_MS = 320;
|
|
1646
|
+
function getStaggeredWordDuration(letterCount) {
|
|
1647
|
+
return (letterCount - 1) * STAGGER_MS + LETTER_DURATION_MS;
|
|
1398
1648
|
}
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
},
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
});
|
|
1409
|
-
|
|
1410
|
-
// src/StatSection.tsx
|
|
1411
|
-
var import_auto_paper9 = require("@rific/auto-paper");
|
|
1412
|
-
var import_react_native21 = require("react-native");
|
|
1413
|
-
var import_react_native_paper11 = require("react-native-paper");
|
|
1414
|
-
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1415
|
-
function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
|
|
1416
|
-
const { dark } = (0, import_auto_paper9.useAutoPaperTheme)();
|
|
1417
|
-
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
1418
|
-
const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
|
|
1419
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native21.View, { style: [styles16.section, { backgroundColor: sectionBg }], children: [
|
|
1420
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_paper11.Text, { variant: "labelMedium", style: [styles16.label, { color: fg }], children: label }),
|
|
1421
|
-
children
|
|
1422
|
-
] });
|
|
1649
|
+
function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }) {
|
|
1650
|
+
const progress = (0, import_react_native_reanimated2.useSharedValue)(reducedMotion ? 1 : 0);
|
|
1651
|
+
(0, import_react9.useEffect)(() => {
|
|
1652
|
+
if (reducedMotion) return;
|
|
1653
|
+
progress.value = (0, import_react_native_reanimated2.withDelay)(index * STAGGER_MS, (0, import_react_native_reanimated2.withTiming)(1, { duration: LETTER_DURATION_MS, easing: import_react_native_reanimated2.Easing.out(import_react_native_reanimated2.Easing.back(1.5)) }));
|
|
1654
|
+
}, [reducedMotion]);
|
|
1655
|
+
const style = (0, import_react_native_reanimated2.useAnimatedStyle)(() => ({
|
|
1656
|
+
opacity: progress.value,
|
|
1657
|
+
transform: [{ translateY: (1 - progress.value) * 12 }, { scale: 0.85 + progress.value * 0.15 }]
|
|
1658
|
+
}));
|
|
1659
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native_reanimated2.default.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
|
|
1423
1660
|
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
fontWeight: "bold",
|
|
1431
|
-
letterSpacing: 2
|
|
1432
|
-
},
|
|
1433
|
-
section: {
|
|
1434
|
-
borderRadius: 12,
|
|
1435
|
-
gap: 8,
|
|
1436
|
-
padding: 16
|
|
1661
|
+
function StaggeredWord({ word, color, fontFamily, fontSize, lineHeight, reducedMotion, startIndex = 0, fontWeight = "bold", letterSpacing, style, onLayout }) {
|
|
1662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native25.View, { style: [styles20.row, style], onLayout, children: word.split("").map((char, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AnimatedLetter, { char, index: startIndex + i, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, i)) });
|
|
1663
|
+
}
|
|
1664
|
+
var styles20 = import_react_native25.StyleSheet.create({
|
|
1665
|
+
row: {
|
|
1666
|
+
flexDirection: "row"
|
|
1437
1667
|
}
|
|
1438
1668
|
});
|
|
1439
1669
|
|
|
1440
1670
|
// src/UpdateDialog.tsx
|
|
1441
1671
|
var import_updater2 = require("@rific/updater");
|
|
1442
|
-
var
|
|
1672
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1443
1673
|
function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onError }) {
|
|
1444
1674
|
const { manifest, onConfirm, respond } = useUpdateConfirmBridge();
|
|
1445
1675
|
(0, import_updater2.useUpdater)({ autoCheck, autoPrompt, onConfirm, onError });
|
|
1446
1676
|
const date = manifest ? new Date(manifest.createdAt) : null;
|
|
1447
|
-
return /* @__PURE__ */ (0,
|
|
1677
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(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) });
|
|
1448
1678
|
}
|
|
1449
1679
|
|
|
1450
|
-
// src/
|
|
1451
|
-
var
|
|
1452
|
-
function
|
|
1453
|
-
const [
|
|
1454
|
-
const
|
|
1455
|
-
|
|
1680
|
+
// src/useQuitConfirmation.ts
|
|
1681
|
+
var import_react10 = require("react");
|
|
1682
|
+
function useQuitConfirmation(hasProgress, onConfirmedBack) {
|
|
1683
|
+
const [confirmVisible, setConfirmVisible] = (0, import_react10.useState)(false);
|
|
1684
|
+
const hasProgressRef = (0, import_react10.useRef)(hasProgress);
|
|
1685
|
+
(0, import_react10.useEffect)(() => {
|
|
1686
|
+
hasProgressRef.current = hasProgress;
|
|
1687
|
+
});
|
|
1688
|
+
const onConfirmedBackRef = (0, import_react10.useRef)(onConfirmedBack);
|
|
1689
|
+
(0, import_react10.useEffect)(() => {
|
|
1690
|
+
onConfirmedBackRef.current = onConfirmedBack;
|
|
1691
|
+
});
|
|
1692
|
+
const requestBack = (0, import_react10.useCallback)(() => {
|
|
1693
|
+
if (hasProgressRef.current()) setConfirmVisible(true);
|
|
1694
|
+
else onConfirmedBackRef.current();
|
|
1456
1695
|
}, []);
|
|
1457
|
-
const
|
|
1458
|
-
return {
|
|
1696
|
+
const cancelBack = (0, import_react10.useCallback)(() => setConfirmVisible(false), []);
|
|
1697
|
+
return { confirmVisible, requestBack, cancelBack };
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
// src/useZoneClampedAlign.ts
|
|
1701
|
+
var import_split_screen = require("@tastic/split-screen");
|
|
1702
|
+
var import_react11 = require("react");
|
|
1703
|
+
var import_react_native26 = require("react-native");
|
|
1704
|
+
var import_react_native_safe_area_context = require("react-native-safe-area-context");
|
|
1705
|
+
var EDGE_MARGIN2 = 12;
|
|
1706
|
+
function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
1707
|
+
const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
|
|
1708
|
+
const zone = (0, import_split_screen.useZoneBounds)();
|
|
1709
|
+
const { height: windowHeight } = (0, import_react_native26.useWindowDimensions)();
|
|
1710
|
+
const insets = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
|
|
1711
|
+
const shouldMeasure = open && auto.measured && zone !== null;
|
|
1712
|
+
const [ownBounds, setOwnBounds] = (0, import_react11.useState)(null);
|
|
1713
|
+
const [prevShouldMeasure, setPrevShouldMeasure] = (0, import_react11.useState)(shouldMeasure);
|
|
1714
|
+
if (shouldMeasure !== prevShouldMeasure) {
|
|
1715
|
+
setPrevShouldMeasure(shouldMeasure);
|
|
1716
|
+
setOwnBounds(null);
|
|
1717
|
+
}
|
|
1718
|
+
(0, import_react11.useEffect)(() => {
|
|
1719
|
+
if (!shouldMeasure) return;
|
|
1720
|
+
auto.triggerRef.current?.measureInWindow((_x, y, _width, height) => {
|
|
1721
|
+
const belowShared = zone.zoneSide === "belowShared";
|
|
1722
|
+
const awayRoom = belowShared ? windowHeight - insets.bottom - (y + height) - EDGE_MARGIN2 : y - insets.top - EDGE_MARGIN2;
|
|
1723
|
+
const towardRoom = belowShared ? y - zone.sharedEdgeY - EDGE_MARGIN2 : zone.sharedEdgeY - (y + height) - EDGE_MARGIN2;
|
|
1724
|
+
const useToward = contentHeight > awayRoom && towardRoom > awayRoom;
|
|
1725
|
+
let awaySide = belowShared ? "below" : "above";
|
|
1726
|
+
let towardSide = belowShared ? "above" : "below";
|
|
1727
|
+
if (zone.rotated) {
|
|
1728
|
+
awaySide = awaySide === "above" ? "below" : "above";
|
|
1729
|
+
towardSide = towardSide === "above" ? "below" : "above";
|
|
1730
|
+
}
|
|
1731
|
+
setOwnBounds({ maxHeight: Math.max(useToward ? towardRoom : awayRoom, 0), verticalAlign: useToward ? towardSide : awaySide });
|
|
1732
|
+
});
|
|
1733
|
+
}, [shouldMeasure, zone, auto.triggerRef, contentHeight, windowHeight, insets.top, insets.bottom]);
|
|
1734
|
+
if (!zone) return auto;
|
|
1735
|
+
if (!ownBounds) return { ...auto, measured: false };
|
|
1736
|
+
return { ...auto, maxHeight: ownBounds.maxHeight, measured: auto.measured, verticalAlign: ownBounds.verticalAlign };
|
|
1459
1737
|
}
|
|
1460
1738
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1461
1739
|
0 && (module.exports = {
|
|
1740
|
+
AchievementCatalogSection,
|
|
1462
1741
|
AchievementRow,
|
|
1742
|
+
AchievementUnlockList,
|
|
1743
|
+
ActivityStatSection,
|
|
1463
1744
|
BaseSettingsDialog,
|
|
1464
1745
|
BaseStatsScreen,
|
|
1465
1746
|
ConfirmDialog,
|
|
@@ -1472,20 +1753,29 @@ function usePopoverHost() {
|
|
|
1472
1753
|
LOCKED_BADGE_COLOR,
|
|
1473
1754
|
LabeledDropdown,
|
|
1474
1755
|
MONO_FONT,
|
|
1756
|
+
PlayerSetupPanel,
|
|
1475
1757
|
PopoverBody,
|
|
1476
1758
|
PressAwayOverlay,
|
|
1477
1759
|
ReadyButton,
|
|
1478
1760
|
SectionedDropdown,
|
|
1479
1761
|
SharedActionBand,
|
|
1480
1762
|
SkiaGate,
|
|
1763
|
+
StaggeredWord,
|
|
1481
1764
|
StatRow,
|
|
1482
1765
|
StatSection,
|
|
1483
1766
|
TriggerGaugeHost,
|
|
1484
1767
|
UpdateDialog,
|
|
1768
|
+
getColorPopoverId,
|
|
1769
|
+
getCpuDifficultyPopoverId,
|
|
1770
|
+
getInlineColorPickerContentSize,
|
|
1485
1771
|
getLabeledDropdownContentHeight,
|
|
1486
1772
|
getOverlayCardColors,
|
|
1773
|
+
getStaggeredWordDuration,
|
|
1487
1774
|
loadSkiaWeb,
|
|
1775
|
+
overlayActionStyles,
|
|
1488
1776
|
overlayStyles,
|
|
1489
1777
|
useAutoAlign,
|
|
1490
|
-
usePopoverHost
|
|
1778
|
+
usePopoverHost,
|
|
1779
|
+
useQuitConfirmation,
|
|
1780
|
+
useZoneClampedAlign
|
|
1491
1781
|
});
|