@tastic/hud 0.8.5 → 0.12.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 +301 -20
- package/dist/index.d.mts +107 -15
- package/dist/index.d.ts +107 -15
- package/dist/index.js +528 -306
- package/dist/index.mjs +455 -253
- package/package.json +16 -8
- package/src/AchievementCatalogSection.tsx +60 -0
- package/src/ActivityStatSection.tsx +29 -0
- 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/index.ts +8 -2
- 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_runtime12.jsx)(import_react_native12.View, { style: [styles10.container, gaugeSizeStyle], pointerEvents: "none", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native_skia.Canvas, { style: canvasSizeStyle, children: [
|
|
134
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.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_runtime12.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_native12, import_react_native_reanimated, import_jsx_runtime12, 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, styles10;
|
|
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_native12 = require("react-native");
|
|
136
146
|
import_react_native_reanimated = require("react-native-reanimated");
|
|
137
|
-
|
|
147
|
+
import_jsx_runtime12 = 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
|
+
styles10 = import_react_native12.StyleSheet.create({
|
|
148
158
|
container: {
|
|
149
159
|
alignItems: "center",
|
|
150
160
|
justifyContent: "center",
|
|
@@ -157,7 +167,9 @@ 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
|
+
ActivityStatSection: () => ActivityStatSection,
|
|
161
173
|
BaseSettingsDialog: () => BaseSettingsDialog,
|
|
162
174
|
BaseStatsScreen: () => BaseStatsScreen,
|
|
163
175
|
ConfirmDialog: () => ConfirmDialog,
|
|
@@ -170,25 +182,39 @@ __export(index_exports, {
|
|
|
170
182
|
LOCKED_BADGE_COLOR: () => LOCKED_BADGE_COLOR,
|
|
171
183
|
LabeledDropdown: () => LabeledDropdown,
|
|
172
184
|
MONO_FONT: () => MONO_FONT,
|
|
185
|
+
PlayerSetupPanel: () => PlayerSetupPanel,
|
|
173
186
|
PopoverBody: () => PopoverBody,
|
|
174
187
|
PressAwayOverlay: () => PressAwayOverlay,
|
|
175
188
|
ReadyButton: () => ReadyButton,
|
|
176
189
|
SectionedDropdown: () => SectionedDropdown,
|
|
177
190
|
SharedActionBand: () => SharedActionBand,
|
|
178
191
|
SkiaGate: () => SkiaGate,
|
|
192
|
+
StaggeredWord: () => StaggeredWord,
|
|
179
193
|
StatRow: () => StatRow,
|
|
180
194
|
StatSection: () => StatSection,
|
|
181
195
|
TriggerGaugeHost: () => TriggerGaugeHost,
|
|
182
196
|
UpdateDialog: () => UpdateDialog,
|
|
197
|
+
getColorPopoverId: () => getColorPopoverId,
|
|
198
|
+
getCpuDifficultyPopoverId: () => getCpuDifficultyPopoverId,
|
|
199
|
+
getInlineColorPickerContentSize: () => getInlineColorPickerContentSize,
|
|
183
200
|
getLabeledDropdownContentHeight: () => getLabeledDropdownContentHeight,
|
|
184
201
|
getOverlayCardColors: () => getOverlayCardColors,
|
|
202
|
+
getStaggeredWordDuration: () => getStaggeredWordDuration,
|
|
185
203
|
loadSkiaWeb: () => loadSkiaWeb,
|
|
186
204
|
overlayStyles: () => overlayStyles,
|
|
187
205
|
useAutoAlign: () => useAutoAlign,
|
|
188
|
-
usePopoverHost: () => usePopoverHost
|
|
206
|
+
usePopoverHost: () => usePopoverHost,
|
|
207
|
+
useQuitConfirmation: () => useQuitConfirmation,
|
|
208
|
+
useZoneClampedAlign: () => useZoneClampedAlign
|
|
189
209
|
});
|
|
190
210
|
module.exports = __toCommonJS(index_exports);
|
|
191
211
|
|
|
212
|
+
// src/AchievementCatalogSection.tsx
|
|
213
|
+
var import_auto_paper2 = require("@rific/auto-paper");
|
|
214
|
+
var import_react = require("react");
|
|
215
|
+
var import_react_native3 = require("react-native");
|
|
216
|
+
var import_react_native_paper2 = require("react-native-paper");
|
|
217
|
+
|
|
192
218
|
// src/AchievementRow.tsx
|
|
193
219
|
var import_auto_paper = require("@rific/auto-paper");
|
|
194
220
|
var import_react_native = require("react-native");
|
|
@@ -257,24 +283,110 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
257
283
|
}
|
|
258
284
|
});
|
|
259
285
|
|
|
260
|
-
// src/
|
|
286
|
+
// src/fonts.ts
|
|
287
|
+
var import_react_native2 = require("react-native");
|
|
288
|
+
var MONO_FONT = import_react_native2.Platform.select({ ios: "Menlo", android: "monospace", default: "monospace" });
|
|
289
|
+
|
|
290
|
+
// src/AchievementCatalogSection.tsx
|
|
291
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
292
|
+
function AchievementCatalogSection({ rows, label = "ALL ACHIEVEMENTS", fg, fgMuted: fgMutedOverride }) {
|
|
293
|
+
const { dark } = (0, import_auto_paper2.useAutoPaperTheme)();
|
|
294
|
+
const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
|
|
295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react.Fragment, { children: [
|
|
296
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper2.Text, { variant: "labelMedium", style: [styles2.label, { color: fgMuted, fontFamily: MONO_FONT }], children: label }),
|
|
297
|
+
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))
|
|
298
|
+
] });
|
|
299
|
+
}
|
|
300
|
+
var styles2 = import_react_native3.StyleSheet.create({
|
|
301
|
+
label: {
|
|
302
|
+
letterSpacing: 2,
|
|
303
|
+
marginTop: 8
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// src/StatRow.tsx
|
|
261
308
|
var import_auto_paper3 = require("@rific/auto-paper");
|
|
309
|
+
var import_react_native4 = require("react-native");
|
|
310
|
+
var import_react_native_paper3 = require("react-native-paper");
|
|
311
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
312
|
+
function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
|
|
313
|
+
const { dark } = (0, import_auto_paper3.useAutoPaperTheme)();
|
|
314
|
+
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
315
|
+
const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
|
|
316
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.View, { style: styles3.row, children: [
|
|
317
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Text, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
|
|
318
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_paper3.Text, { variant: "bodyMedium", style: [styles3.value, { color: fg }], children: value })
|
|
319
|
+
] });
|
|
320
|
+
}
|
|
321
|
+
var styles3 = import_react_native4.StyleSheet.create({
|
|
322
|
+
row: {
|
|
323
|
+
alignItems: "center",
|
|
324
|
+
flexDirection: "row",
|
|
325
|
+
justifyContent: "space-between"
|
|
326
|
+
},
|
|
327
|
+
value: {
|
|
328
|
+
fontWeight: "bold"
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// src/StatSection.tsx
|
|
333
|
+
var import_auto_paper4 = require("@rific/auto-paper");
|
|
334
|
+
var import_react_native5 = require("react-native");
|
|
335
|
+
var import_react_native_paper4 = require("react-native-paper");
|
|
336
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
337
|
+
function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
|
|
338
|
+
const { dark } = (0, import_auto_paper4.useAutoPaperTheme)();
|
|
339
|
+
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
340
|
+
const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
|
|
341
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native5.View, { style: [styles4.section, { backgroundColor: sectionBg }], children: [
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_paper4.Text, { variant: "labelMedium", style: [styles4.label, { color: fg }], children: label }),
|
|
343
|
+
children
|
|
344
|
+
] });
|
|
345
|
+
}
|
|
346
|
+
var styles4 = import_react_native5.StyleSheet.create({
|
|
347
|
+
// Bold and full-contrast (fg), not the original fontless/fgMuted treatment — that read at the
|
|
348
|
+
// same visual weight as StatRow's own row labels below it (both used the identical muted color;
|
|
349
|
+
// letterSpacing/variant alone didn't separate them enough to read as "this is the group header"
|
|
350
|
+
// at a glance). Matches AchievementRow's own title styling (bold + fg) below it in the same list.
|
|
351
|
+
label: {
|
|
352
|
+
fontWeight: "bold",
|
|
353
|
+
letterSpacing: 2
|
|
354
|
+
},
|
|
355
|
+
section: {
|
|
356
|
+
borderRadius: 12,
|
|
357
|
+
gap: 8,
|
|
358
|
+
padding: 16
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
// src/ActivityStatSection.tsx
|
|
363
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
364
|
+
function ActivityStatSection({ stats }) {
|
|
365
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(StatSection, { label: "ACTIVITY", children: [
|
|
366
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatRow, { label: "Days Played", value: String(stats.distinctDaysPlayed) }),
|
|
367
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatRow, { label: "Day Streak", value: String(stats.currentDayStreak) }),
|
|
368
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatRow, { label: "Best Day Streak", value: String(stats.bestDayStreak) })
|
|
369
|
+
] });
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// src/BaseSettingsDialog.tsx
|
|
373
|
+
var import_auto_paper6 = require("@rific/auto-paper");
|
|
262
374
|
var import_feedback_press2 = require("@rific/feedback-press");
|
|
263
375
|
var import_updater = require("@rific/updater");
|
|
264
376
|
var import_core2 = require("@tastic/core");
|
|
265
|
-
var
|
|
266
|
-
var
|
|
267
|
-
var
|
|
377
|
+
var import_react3 = require("react");
|
|
378
|
+
var import_react_native8 = require("react-native");
|
|
379
|
+
var import_react_native_paper6 = require("react-native-paper");
|
|
268
380
|
|
|
269
381
|
// src/ConfirmDialog.tsx
|
|
270
|
-
var
|
|
382
|
+
var import_auto_paper5 = require("@rific/auto-paper");
|
|
271
383
|
var import_feedback_press = require("@rific/feedback-press");
|
|
272
384
|
var import_core = require("@tastic/core");
|
|
273
|
-
var
|
|
274
|
-
var
|
|
385
|
+
var import_react_native7 = require("react-native");
|
|
386
|
+
var import_react_native_paper5 = require("react-native-paper");
|
|
275
387
|
|
|
276
388
|
// src/overlayCard.ts
|
|
277
|
-
var
|
|
389
|
+
var import_react_native6 = require("react-native");
|
|
278
390
|
function getOverlayCardColors(dark) {
|
|
279
391
|
return {
|
|
280
392
|
fg: dark ? "#FFFFFF" : "#000000",
|
|
@@ -283,7 +395,7 @@ function getOverlayCardColors(dark) {
|
|
|
283
395
|
cardBorder: dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)"
|
|
284
396
|
};
|
|
285
397
|
}
|
|
286
|
-
var overlayStyles =
|
|
398
|
+
var overlayStyles = import_react_native6.StyleSheet.create({
|
|
287
399
|
card: {
|
|
288
400
|
alignItems: "center",
|
|
289
401
|
borderRadius: 20,
|
|
@@ -305,25 +417,25 @@ var overlayStyles = import_react_native2.StyleSheet.create({
|
|
|
305
417
|
});
|
|
306
418
|
|
|
307
419
|
// src/ConfirmDialog.tsx
|
|
308
|
-
var
|
|
420
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
309
421
|
function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
|
|
310
|
-
const { dark, colors } = (0,
|
|
422
|
+
const { dark, colors } = (0, import_auto_paper5.useAutoPaperTheme)();
|
|
311
423
|
if (!visible) return null;
|
|
312
424
|
const { fg, cardBg, cardBorder } = getOverlayCardColors(dark);
|
|
313
425
|
const accent = destructive ? colors.danger : colors.primary;
|
|
314
426
|
const onAccent = destructive ? colors.onDanger : colors.onPrimary;
|
|
315
427
|
const showCancel = cancelLabel !== void 0 && onCancel !== void 0;
|
|
316
|
-
return /* @__PURE__ */ (0,
|
|
317
|
-
/* @__PURE__ */ (0,
|
|
318
|
-
/* @__PURE__ */ (0,
|
|
319
|
-
/* @__PURE__ */ (0,
|
|
320
|
-
/* @__PURE__ */ (0,
|
|
321
|
-
showCancel && /* @__PURE__ */ (0,
|
|
322
|
-
/* @__PURE__ */ (0,
|
|
428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper5.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.View, { style: [overlayStyles.overlay, styles5.overlay], children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native7.View, { style: [overlayStyles.card, styles5.card, { backgroundColor: cardBg, borderColor: cardBorder }, (0, import_core.toRotationStyle)(rotation)], children: [
|
|
429
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper5.Icon, { source: icon, size: 64, color: accent }),
|
|
430
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper5.Text, { variant: "headlineLarge", style: [styles5.title, { color: accent }], children: title }),
|
|
431
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper5.Text, { variant: "bodyLarge", style: [styles5.body, { color: fg }], children: message }),
|
|
432
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native7.View, { style: styles5.actions, children: [
|
|
433
|
+
showCancel && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_feedback_press.Button, { mode: "outlined", onPress: onCancel, style: styles5.actionButton, children: cancelLabel }),
|
|
434
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_feedback_press.Button, { mode: "contained", onPress: onConfirm, style: showCancel ? styles5.actionButton : styles5.actionButtonSingle, buttonColor: accent, textColor: onAccent, children: confirmLabel })
|
|
323
435
|
] })
|
|
324
436
|
] }) }) });
|
|
325
437
|
}
|
|
326
|
-
var
|
|
438
|
+
var styles5 = import_react_native7.StyleSheet.create({
|
|
327
439
|
// minWidth (not flexBasis) is each button's real floor - whenever both fit side by side, flexGrow
|
|
328
440
|
// still splits any leftover width evenly beyond that floor, same visual result as a plain flex: 1
|
|
329
441
|
// on a roomy screen, but a button can never be squeezed narrower than 128, only wrap to its own
|
|
@@ -391,18 +503,18 @@ var styles2 = import_react_native3.StyleSheet.create({
|
|
|
391
503
|
});
|
|
392
504
|
|
|
393
505
|
// src/useUpdateConfirmBridge.ts
|
|
394
|
-
var
|
|
506
|
+
var import_react2 = require("react");
|
|
395
507
|
function useUpdateConfirmBridge() {
|
|
396
|
-
const [manifest, setManifest] = (0,
|
|
397
|
-
const resolveRef = (0,
|
|
398
|
-
const onConfirm = (0,
|
|
508
|
+
const [manifest, setManifest] = (0, import_react2.useState)(null);
|
|
509
|
+
const resolveRef = (0, import_react2.useRef)(null);
|
|
510
|
+
const onConfirm = (0, import_react2.useCallback)(
|
|
399
511
|
(next) => new Promise((resolve) => {
|
|
400
512
|
resolveRef.current = resolve;
|
|
401
513
|
setManifest(next);
|
|
402
514
|
}),
|
|
403
515
|
[]
|
|
404
516
|
);
|
|
405
|
-
const respond = (0,
|
|
517
|
+
const respond = (0, import_react2.useCallback)((confirmed) => {
|
|
406
518
|
setManifest(null);
|
|
407
519
|
resolveRef.current?.(confirmed);
|
|
408
520
|
resolveRef.current = null;
|
|
@@ -411,20 +523,20 @@ function useUpdateConfirmBridge() {
|
|
|
411
523
|
}
|
|
412
524
|
|
|
413
525
|
// src/BaseSettingsDialog.tsx
|
|
414
|
-
var
|
|
526
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
415
527
|
function SettingIcon({ source, color, containerColor }) {
|
|
416
|
-
return /* @__PURE__ */ (0,
|
|
528
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native8.View, { style: [styles6.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Icon, { source, size: 18, color }) });
|
|
417
529
|
}
|
|
418
530
|
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,
|
|
531
|
+
const { colors } = (0, import_auto_paper6.useAutoPaperTheme)();
|
|
420
532
|
const ambientRotation = (0, import_core2.useRotation)();
|
|
421
533
|
const rotation = rotationOverride ?? ambientRotation;
|
|
422
534
|
const isTouchPrimary = (0, import_core2.useIsTouchPrimaryDevice)();
|
|
423
535
|
const { settings: hapticSettings, set: setHapticSettings } = (0, import_feedback_press2.useHapticSettings)();
|
|
424
536
|
const { settings: soundSettings, set: setSoundSettings } = (0, import_feedback_press2.useSoundSettings)();
|
|
425
|
-
const sound = (0,
|
|
537
|
+
const sound = (0, import_react3.useContext)(import_feedback_press2.SoundContext);
|
|
426
538
|
const { forceShort: forceHapticFeedback } = (0, import_feedback_press2.useVibration)();
|
|
427
|
-
const [infoMessage, setInfoMessage] = (0,
|
|
539
|
+
const [infoMessage, setInfoMessage] = (0, import_react3.useState)(null);
|
|
428
540
|
const { manifest: updateManifest, onConfirm: onUpdateConfirm, respond: respondToUpdateConfirm } = useUpdateConfirmBridge();
|
|
429
541
|
const { check, checking, updateReady } = (0, import_updater.useUpdater)({
|
|
430
542
|
autoCheck: false,
|
|
@@ -435,32 +547,32 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
435
547
|
});
|
|
436
548
|
const updateManifestDate = updateManifest ? new Date(updateManifest.createdAt) : null;
|
|
437
549
|
const showLockOrientation = isTouchPrimary && lockOrientation !== void 0 && onLockOrientationChange !== void 0;
|
|
438
|
-
const showEdgeGuard =
|
|
439
|
-
const showHaptics =
|
|
550
|
+
const showEdgeGuard = import_react_native8.Platform.OS === "ios" && deferBottomEdgeGestures !== void 0 && onDeferBottomEdgeGestures !== void 0;
|
|
551
|
+
const showHaptics = import_react_native8.Platform.OS !== "web" && !hideHaptics;
|
|
440
552
|
const showSound = !hideSound;
|
|
441
553
|
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,
|
|
554
|
+
const showUpdateCheck = import_react_native8.Platform.OS !== "web" && !hideUpdateCheck;
|
|
555
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
556
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_auto_paper6.Dialog, { visible, onDismiss, style: [styles6.dialog, (0, import_core2.toRotationStyle)(rotation)], children: [
|
|
557
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_auto_paper6.Dialog.Title, { children: "Settings" }),
|
|
558
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_auto_paper6.Dialog.ScrollArea, { style: styles6.scrollArea, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.ScrollView, { contentContainerStyle: styles6.content, showsVerticalScrollIndicator: false, children: [
|
|
559
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: styles6.toggleGroup, children: [
|
|
560
|
+
showLockOrientation && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => onLockOrientationChange(!lockOrientation), style: styles6.toggleButton, accessibilityLabel: `Lock orientation ${lockOrientation ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: styles6.toggleContent, children: [
|
|
561
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SettingIcon, { source: lockOrientation ? "lock" : "lock-open-variant-outline", color: lockOrientation ? colors.secondary : colors.onSurfaceVariant, containerColor: lockOrientation ? colors.secondaryContainer : colors.surfaceVariant }),
|
|
562
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: styles6.flexShrink, children: [
|
|
563
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Lock Orientation" }),
|
|
564
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Pins the current layout" })
|
|
453
565
|
] })
|
|
454
566
|
] }) }),
|
|
455
|
-
showEdgeGuard && /* @__PURE__ */ (0,
|
|
456
|
-
/* @__PURE__ */ (0,
|
|
457
|
-
/* @__PURE__ */ (0,
|
|
458
|
-
/* @__PURE__ */ (0,
|
|
459
|
-
/* @__PURE__ */ (0,
|
|
567
|
+
showEdgeGuard && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => onDeferBottomEdgeGestures(!deferBottomEdgeGestures), style: styles6.toggleButton, accessibilityLabel: `Edge guard ${deferBottomEdgeGestures ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: styles6.toggleContent, children: [
|
|
568
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SettingIcon, { source: deferBottomEdgeGestures ? "shield-check-outline" : "shield-off-outline", color: deferBottomEdgeGestures ? colors.secondary : colors.onSurfaceVariant, containerColor: deferBottomEdgeGestures ? colors.secondaryContainer : colors.surfaceVariant }),
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: styles6.flexShrink, children: [
|
|
570
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Edge Guard" }),
|
|
571
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Requires a second swipe" })
|
|
460
572
|
] })
|
|
461
573
|
] }) }),
|
|
462
|
-
(showSound || showHaptics) && /* @__PURE__ */ (0,
|
|
463
|
-
showSound && /* @__PURE__ */ (0,
|
|
574
|
+
(showSound || showHaptics) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: styles6.toggleRow, children: [
|
|
575
|
+
showSound && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
464
576
|
import_feedback_press2.TouchableRipple,
|
|
465
577
|
{
|
|
466
578
|
soundDisabled: true,
|
|
@@ -469,15 +581,15 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
469
581
|
setSoundSettings({ enabled });
|
|
470
582
|
if (enabled) sound.selection?.();
|
|
471
583
|
},
|
|
472
|
-
style:
|
|
584
|
+
style: styles6.toggleButtonInRow,
|
|
473
585
|
accessibilityLabel: `Sound ${soundSettings.enabled ? "on" : "off"}`,
|
|
474
|
-
children: /* @__PURE__ */ (0,
|
|
475
|
-
/* @__PURE__ */ (0,
|
|
476
|
-
/* @__PURE__ */ (0,
|
|
586
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: styles6.toggleContent, children: [
|
|
587
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SettingIcon, { source: soundSettings.enabled ? "volume-high" : "volume-off", color: soundSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: soundSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
588
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Sound" })
|
|
477
589
|
] })
|
|
478
590
|
}
|
|
479
591
|
),
|
|
480
|
-
showHaptics && /* @__PURE__ */ (0,
|
|
592
|
+
showHaptics && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
481
593
|
import_feedback_press2.TouchableRipple,
|
|
482
594
|
{
|
|
483
595
|
hapticDisabled: true,
|
|
@@ -486,36 +598,36 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
486
598
|
setHapticSettings({ vibrate });
|
|
487
599
|
if (vibrate) forceHapticFeedback();
|
|
488
600
|
},
|
|
489
|
-
style:
|
|
601
|
+
style: styles6.toggleButtonInRow,
|
|
490
602
|
accessibilityLabel: `Haptics ${hapticSettings.vibrate ? "on" : "off"}`,
|
|
491
|
-
children: /* @__PURE__ */ (0,
|
|
492
|
-
/* @__PURE__ */ (0,
|
|
493
|
-
/* @__PURE__ */ (0,
|
|
603
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: styles6.toggleContent, children: [
|
|
604
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SettingIcon, { source: hapticSettings.vibrate ? "vibrate" : "vibrate-off", color: hapticSettings.vibrate ? colors.tertiary : colors.onSurfaceVariant, containerColor: hapticSettings.vibrate ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
605
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Haptics" })
|
|
494
606
|
] })
|
|
495
607
|
}
|
|
496
608
|
)
|
|
497
609
|
] })
|
|
498
610
|
] }),
|
|
499
|
-
showAppearance && /* @__PURE__ */ (0,
|
|
500
|
-
/* @__PURE__ */ (0,
|
|
501
|
-
/* @__PURE__ */ (0,
|
|
611
|
+
showAppearance && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: styles6.section, children: [
|
|
612
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper6.Text, { variant: "labelMedium", style: [styles6.sectionLabel, { color: colors.onSurfaceVariant }], children: "APPEARANCE" }),
|
|
613
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_auto_paper6.AutoAppearancePicker, { showLabels: false })
|
|
502
614
|
] }),
|
|
503
615
|
children,
|
|
504
|
-
showUpdateCheck && /* @__PURE__ */ (0,
|
|
505
|
-
/* @__PURE__ */ (0,
|
|
616
|
+
showUpdateCheck && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: styles6.section, children: [
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native_paper6.Text, { variant: "labelSmall", style: [styles6.sectionLabel, { color: colors.onSurfaceVariant }], children: [
|
|
506
618
|
"VERSION ",
|
|
507
619
|
version,
|
|
508
620
|
updateReady ? " \xB7 UPDATE READY" : ""
|
|
509
621
|
] }),
|
|
510
|
-
/* @__PURE__ */ (0,
|
|
622
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press2.Button, { mode: "outlined", onPress: check, loading: checking, disabled: checking, children: "Check for Updates" })
|
|
511
623
|
] })
|
|
512
624
|
] }) })
|
|
513
625
|
] }),
|
|
514
|
-
/* @__PURE__ */ (0,
|
|
515
|
-
/* @__PURE__ */ (0,
|
|
626
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.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) }),
|
|
627
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ConfirmDialog, { visible: !!infoMessage, title: infoMessage?.title ?? "", message: infoMessage?.message ?? "", confirmLabel: "OK", icon: "information-outline", rotation, onConfirm: () => setInfoMessage(null) })
|
|
516
628
|
] });
|
|
517
629
|
}
|
|
518
|
-
var
|
|
630
|
+
var styles6 = import_react_native8.StyleSheet.create({
|
|
519
631
|
content: {
|
|
520
632
|
gap: 24,
|
|
521
633
|
paddingVertical: 20
|
|
@@ -583,31 +695,31 @@ var styles3 = import_react_native4.StyleSheet.create({
|
|
|
583
695
|
});
|
|
584
696
|
|
|
585
697
|
// src/BaseStatsScreen.tsx
|
|
586
|
-
var
|
|
698
|
+
var import_auto_paper7 = require("@rific/auto-paper");
|
|
587
699
|
var import_feedback_press3 = require("@rific/feedback-press");
|
|
588
700
|
var import_core3 = require("@tastic/core");
|
|
589
|
-
var
|
|
590
|
-
var
|
|
591
|
-
var
|
|
592
|
-
var
|
|
701
|
+
var import_react4 = require("react");
|
|
702
|
+
var import_react_native9 = require("react-native");
|
|
703
|
+
var import_react_native_paper7 = require("react-native-paper");
|
|
704
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
593
705
|
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,
|
|
706
|
+
const { dark, colors } = (0, import_auto_paper7.useAutoPaperTheme)();
|
|
595
707
|
const ambientRotation = (0, import_core3.useRotation)();
|
|
596
708
|
const rotation = rotationOverride ?? ambientRotation;
|
|
597
|
-
const [confirmResetVisible, setConfirmResetVisible] = (0,
|
|
709
|
+
const [confirmResetVisible, setConfirmResetVisible] = (0, import_react4.useState)(false);
|
|
598
710
|
const showReset = !!onReset;
|
|
599
711
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
600
712
|
const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
|
|
601
|
-
return /* @__PURE__ */ (0,
|
|
602
|
-
/* @__PURE__ */ (0,
|
|
603
|
-
/* @__PURE__ */ (0,
|
|
604
|
-
/* @__PURE__ */ (0,
|
|
713
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: [styles7.container, { backgroundColor: bg }], children: [
|
|
714
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: [styles7.header, { paddingTop: 8 + insets.top, paddingLeft: 8 + insets.left }], children: [
|
|
715
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_feedback_press3.IconButton, { icon: "arrow-left", iconColor: fg, size: 24, onPress: onBack }),
|
|
716
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native_paper7.Text, { variant: titleVariant, style: [styles7.title, { color: fg }], children: title })
|
|
605
717
|
] }),
|
|
606
|
-
/* @__PURE__ */ (0,
|
|
718
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.ScrollView, { style: styles7.scrollView, contentContainerStyle: [styles7.content, { paddingBottom: 32 + insets.bottom }], showsVerticalScrollIndicator: false, children: [
|
|
607
719
|
children,
|
|
608
|
-
showReset && /* @__PURE__ */ (0,
|
|
720
|
+
showReset && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_feedback_press3.Button, { mode: "contained", onPress: () => setConfirmResetVisible(true), buttonColor: colors.danger, textColor: colors.onDanger, style: styles7.resetButton, children: resetLabel })
|
|
609
721
|
] }),
|
|
610
|
-
/* @__PURE__ */ (0,
|
|
722
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
611
723
|
ConfirmDialog,
|
|
612
724
|
{
|
|
613
725
|
visible: confirmResetVisible,
|
|
@@ -627,7 +739,7 @@ function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", t
|
|
|
627
739
|
)
|
|
628
740
|
] });
|
|
629
741
|
}
|
|
630
|
-
var
|
|
742
|
+
var styles7 = import_react_native9.StyleSheet.create({
|
|
631
743
|
container: {
|
|
632
744
|
flex: 1
|
|
633
745
|
},
|
|
@@ -659,18 +771,18 @@ var styles4 = import_react_native5.StyleSheet.create({
|
|
|
659
771
|
|
|
660
772
|
// src/ContentGutter.tsx
|
|
661
773
|
var import_core4 = require("@tastic/core");
|
|
662
|
-
var
|
|
663
|
-
var
|
|
774
|
+
var import_react_native10 = require("react-native");
|
|
775
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
664
776
|
function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
|
|
665
|
-
const { width: windowWidth } = (0,
|
|
777
|
+
const { width: windowWidth } = (0, import_react_native10.useWindowDimensions)();
|
|
666
778
|
const { contentWidth, gutterWidth } = (0, import_core4.computeContentBounds)(windowWidth, maxContentWidth ?? Infinity);
|
|
667
|
-
return /* @__PURE__ */ (0,
|
|
668
|
-
/* @__PURE__ */ (0,
|
|
669
|
-
/* @__PURE__ */ (0,
|
|
670
|
-
/* @__PURE__ */ (0,
|
|
779
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: [styles8.row, style], children: [
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: [styles8.gutter, { width: gutterWidth }], children: leftGutter }),
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: { width: contentWidth }, children }),
|
|
782
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: [styles8.gutter, { width: gutterWidth }], children: rightGutter })
|
|
671
783
|
] });
|
|
672
784
|
}
|
|
673
|
-
var
|
|
785
|
+
var styles8 = import_react_native10.StyleSheet.create({
|
|
674
786
|
// overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
|
|
675
787
|
// column instead of clipping cleanly at its own real width.
|
|
676
788
|
gutter: {
|
|
@@ -683,44 +795,40 @@ var styles5 = import_react_native6.StyleSheet.create({
|
|
|
683
795
|
|
|
684
796
|
// src/ControlSchemePicker.tsx
|
|
685
797
|
var import_core7 = require("@tastic/core");
|
|
686
|
-
var
|
|
798
|
+
var import_react_native15 = require("react-native");
|
|
687
799
|
|
|
688
800
|
// src/SectionedDropdown.tsx
|
|
689
|
-
var
|
|
801
|
+
var import_auto_paper8 = require("@rific/auto-paper");
|
|
690
802
|
var import_feedback_press4 = require("@rific/feedback-press");
|
|
691
803
|
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" });
|
|
804
|
+
var import_react_native14 = require("react-native");
|
|
805
|
+
var import_react_native_paper8 = require("react-native-paper");
|
|
698
806
|
|
|
699
807
|
// src/PopoverBody.tsx
|
|
700
|
-
var
|
|
701
|
-
var
|
|
808
|
+
var import_react_native11 = require("react-native");
|
|
809
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
702
810
|
var CARET_SIZE = 7;
|
|
703
811
|
var CARET_RING_OFFSET = 2;
|
|
704
812
|
var CARET_DIP = 1;
|
|
705
813
|
function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
|
|
706
814
|
if (!visible) return null;
|
|
707
815
|
const above = verticalAlign === "above";
|
|
708
|
-
const alignStyle = align === "left" ?
|
|
709
|
-
const verticalStyle = above ?
|
|
816
|
+
const alignStyle = align === "left" ? styles9.contentLeft : align === "right" ? styles9.contentRight : styles9.contentCenter;
|
|
817
|
+
const verticalStyle = above ? styles9.contentAbove : styles9.contentBelow;
|
|
710
818
|
const ringSize = CARET_SIZE + caretBorderWidth;
|
|
711
819
|
const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
|
|
712
820
|
const caretFill = above ? "borderTopColor" : "borderBottomColor";
|
|
713
821
|
const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
|
|
714
822
|
const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
|
|
715
|
-
return /* @__PURE__ */ (0,
|
|
823
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native11.View, { style: [styles9.content, alignStyle, verticalStyle], children: [
|
|
716
824
|
children,
|
|
717
|
-
caretColor && /* @__PURE__ */ (0,
|
|
718
|
-
/* @__PURE__ */ (0,
|
|
719
|
-
/* @__PURE__ */ (0,
|
|
825
|
+
caretColor && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
826
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native11.View, { style: [styles9.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
|
|
827
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native11.View, { style: [styles9.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
|
|
720
828
|
] })
|
|
721
829
|
] });
|
|
722
830
|
}
|
|
723
|
-
var
|
|
831
|
+
var styles9 = import_react_native11.StyleSheet.create({
|
|
724
832
|
caret: {
|
|
725
833
|
borderLeftColor: "transparent",
|
|
726
834
|
borderRightColor: "transparent",
|
|
@@ -763,11 +871,11 @@ var styles6 = import_react_native8.StyleSheet.create({
|
|
|
763
871
|
});
|
|
764
872
|
|
|
765
873
|
// src/SkiaGate.tsx
|
|
766
|
-
var
|
|
767
|
-
var
|
|
874
|
+
var import_react5 = require("react");
|
|
875
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
768
876
|
function SkiaGate({ getComponent, componentProps, fallback = null }) {
|
|
769
|
-
const [Component, setComponent] = (0,
|
|
770
|
-
(0,
|
|
877
|
+
const [Component, setComponent] = (0, import_react5.useState)(null);
|
|
878
|
+
(0, import_react5.useEffect)(() => {
|
|
771
879
|
let cancelled = false;
|
|
772
880
|
getComponent().then((mod) => {
|
|
773
881
|
if (!cancelled) setComponent(() => mod.default);
|
|
@@ -777,19 +885,19 @@ function SkiaGate({ getComponent, componentProps, fallback = null }) {
|
|
|
777
885
|
};
|
|
778
886
|
}, [getComponent]);
|
|
779
887
|
if (!Component) return fallback;
|
|
780
|
-
return /* @__PURE__ */ (0,
|
|
888
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Component, { ...componentProps });
|
|
781
889
|
}
|
|
782
890
|
|
|
783
891
|
// src/TriggerGaugeHost.tsx
|
|
784
|
-
var
|
|
892
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
785
893
|
var getTriggerGauge = () => Promise.resolve().then(() => (init_TriggerGauge(), TriggerGauge_exports)).then((mod) => ({ default: mod.TriggerGauge }));
|
|
786
894
|
function TriggerGaugeHost(props) {
|
|
787
|
-
return /* @__PURE__ */ (0,
|
|
895
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
|
|
788
896
|
}
|
|
789
897
|
|
|
790
898
|
// src/useAutoAlign.ts
|
|
791
|
-
var
|
|
792
|
-
var
|
|
899
|
+
var import_react7 = require("react");
|
|
900
|
+
var import_react_native13 = require("react-native");
|
|
793
901
|
var EDGE_MARGIN = 12;
|
|
794
902
|
function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
|
|
795
903
|
if (rotation === 0) return { x, y, width, height };
|
|
@@ -801,18 +909,18 @@ function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
|
|
|
801
909
|
return { x: cx + newDx - newWidth / 2, y: cy + newDy - newHeight / 2, width: newWidth, height: newHeight };
|
|
802
910
|
}
|
|
803
911
|
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,
|
|
912
|
+
const triggerRef = (0, import_react7.useRef)(null);
|
|
913
|
+
const { width: windowWidth, height: windowHeight } = (0, import_react_native13.useWindowDimensions)();
|
|
914
|
+
const [align, setAlign] = (0, import_react7.useState)("center");
|
|
915
|
+
const [verticalAlign, setVerticalAlign] = (0, import_react7.useState)("below");
|
|
916
|
+
const [maxHeight, setMaxHeight] = (0, import_react7.useState)(contentHeight);
|
|
917
|
+
const [measured, setMeasured] = (0, import_react7.useState)(false);
|
|
918
|
+
const [prevOpen, setPrevOpen] = (0, import_react7.useState)(open);
|
|
811
919
|
if (open !== prevOpen) {
|
|
812
920
|
setPrevOpen(open);
|
|
813
921
|
if (open) setMeasured(false);
|
|
814
922
|
}
|
|
815
|
-
const measure = (0,
|
|
923
|
+
const measure = (0, import_react7.useCallback)(() => {
|
|
816
924
|
triggerRef.current?.measureInWindow((rawX, rawY, rawWidth, rawHeight) => {
|
|
817
925
|
const { x, y, width: triggerWidth, height: triggerHeight } = rotateRect(rawX, rawY, rawWidth, rawHeight, rotation, windowWidth, windowHeight);
|
|
818
926
|
const centerX = x + triggerWidth / 2;
|
|
@@ -829,14 +937,14 @@ function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
|
829
937
|
setMeasured(true);
|
|
830
938
|
});
|
|
831
939
|
}, [contentWidth, contentHeight, windowWidth, windowHeight, rotation]);
|
|
832
|
-
(0,
|
|
940
|
+
(0, import_react7.useEffect)(() => {
|
|
833
941
|
if (open) measure();
|
|
834
942
|
}, [open, measure]);
|
|
835
943
|
return { align, maxHeight, measured, triggerRef, verticalAlign };
|
|
836
944
|
}
|
|
837
945
|
|
|
838
946
|
// src/SectionedDropdown.tsx
|
|
839
|
-
var
|
|
947
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
840
948
|
var MENU_BORDER_WIDTH = 1;
|
|
841
949
|
var TRIGGER_SIZE = 44;
|
|
842
950
|
var MENU_MIN_WIDTH = 200;
|
|
@@ -847,12 +955,12 @@ var MENU_ITEM_HEIGHT = 40;
|
|
|
847
955
|
var MENU_ITEM_HEIGHT_WITH_DESCRIPTION = 58;
|
|
848
956
|
var MENU_DIVIDER_HEIGHT = 9;
|
|
849
957
|
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" } }) {
|
|
958
|
+
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
959
|
const ambientRotation = (0, import_core6.useRotation)();
|
|
852
960
|
const rotation = rotationOverride ?? ambientRotation;
|
|
853
961
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
854
|
-
const menuBorderColor = (0,
|
|
855
|
-
const resolvedOnAccentColor = onAccentColor ?? (0,
|
|
962
|
+
const menuBorderColor = (0, import_auto_paper8.getBlendedColor)(mutedColor, menuBg, 0.5);
|
|
963
|
+
const resolvedOnAccentColor = onAccentColor ?? (0, import_auto_paper8.getColorRoles)(accentColor, menuBg).onColor;
|
|
856
964
|
const fg = dark ? "#FFFFFF" : "#000000";
|
|
857
965
|
const open = host.openId === id;
|
|
858
966
|
const estimatedHeight = MENU_VERTICAL_PADDING + sections.reduce((sum, section, sectionIndex) => {
|
|
@@ -861,8 +969,10 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
861
969
|
const divider = sectionIndex > 0 ? MENU_DIVIDER_HEIGHT : 0;
|
|
862
970
|
return sum + rows + footer + divider;
|
|
863
971
|
}, 0);
|
|
864
|
-
const
|
|
865
|
-
const
|
|
972
|
+
const auto = useAutoAlign(open, MENU_MAX_WIDTH, estimatedHeight, rotation);
|
|
973
|
+
const placement = alignOverride ?? auto;
|
|
974
|
+
const { maxHeight, measured, triggerRef, verticalAlign } = placement;
|
|
975
|
+
const align = forcedAlign ?? placement.align;
|
|
866
976
|
const onlySection = sections.length === 1 ? sections[0] : null;
|
|
867
977
|
const selectedOption = onlySection?.kind === "single" ? onlySection.options.find((o) => o.value === onlySection.value) : void 0;
|
|
868
978
|
const triggerIcon = selectedOption?.icon ?? icon;
|
|
@@ -884,17 +994,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
884
994
|
}
|
|
885
995
|
gaugeOffset += section.options.length;
|
|
886
996
|
}
|
|
887
|
-
const anchorStyle = [
|
|
997
|
+
const anchorStyle = [styles11.anchor, open && styles11.anchorOpen];
|
|
888
998
|
const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
|
|
889
999
|
const dividerStyle = { backgroundColor: menuBorderColor };
|
|
890
|
-
return /* @__PURE__ */ (0,
|
|
891
|
-
/* @__PURE__ */ (0,
|
|
892
|
-
/* @__PURE__ */ (0,
|
|
893
|
-
/* @__PURE__ */ (0,
|
|
1000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { style: anchorStyle, children: [
|
|
1001
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { ref: triggerRef, collapsable: false, style: styles11.triggerBox, children: [
|
|
1002
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
|
|
1003
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_feedback_press4.IconButton, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
|
|
894
1004
|
] }),
|
|
895
|
-
/* @__PURE__ */ (0,
|
|
896
|
-
sectionIndex > 0 && /* @__PURE__ */ (0,
|
|
897
|
-
section.kind === "single" ? /* @__PURE__ */ (0,
|
|
1005
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.ScrollView, { style: [styles11.menu, menuStyle], contentContainerStyle: styles11.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { children: [
|
|
1006
|
+
sectionIndex > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.View, { style: [styles11.divider, dividerStyle] }),
|
|
1007
|
+
section.kind === "single" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
898
1008
|
SingleSection,
|
|
899
1009
|
{
|
|
900
1010
|
section,
|
|
@@ -907,7 +1017,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
907
1017
|
if (autoDismiss) host.close();
|
|
908
1018
|
}
|
|
909
1019
|
}
|
|
910
|
-
) : /* @__PURE__ */ (0,
|
|
1020
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
|
|
911
1021
|
] }, section.id)) }) })
|
|
912
1022
|
] });
|
|
913
1023
|
}
|
|
@@ -919,18 +1029,18 @@ function SingleSection({
|
|
|
919
1029
|
labelFontFamily,
|
|
920
1030
|
onSelect
|
|
921
1031
|
}) {
|
|
922
|
-
return /* @__PURE__ */ (0,
|
|
1032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: section.options.map((option) => {
|
|
923
1033
|
const selected = option.value === section.value;
|
|
924
1034
|
const taken = !selected && option.value === section.takenValue;
|
|
925
1035
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
926
|
-
const itemStyle = [
|
|
1036
|
+
const itemStyle = [styles11.item, selected && { backgroundColor: accentColor }, taken && styles11.itemTaken];
|
|
927
1037
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
928
1038
|
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,
|
|
1039
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_feedback_press4.TouchableRipple, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { style: styles11.itemRow, children: [
|
|
1040
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper8.Icon, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
1041
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { style: styles11.itemLabelColumn, children: [
|
|
1042
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper8.Text, { variant: "labelLarge", style: labelStyle, children: option.label }),
|
|
1043
|
+
option.description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper8.Text, { variant: "labelSmall", style: descriptionStyle, children: option.description })
|
|
934
1044
|
] })
|
|
935
1045
|
] }) }, option.value);
|
|
936
1046
|
}) });
|
|
@@ -944,23 +1054,23 @@ function MultiSection({
|
|
|
944
1054
|
allClearLabels
|
|
945
1055
|
}) {
|
|
946
1056
|
const allSelected = section.value.length === section.options.length;
|
|
947
|
-
return /* @__PURE__ */ (0,
|
|
1057
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
948
1058
|
section.options.map((option, i) => {
|
|
949
1059
|
const selected = section.value.includes(option.value);
|
|
950
1060
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
951
1061
|
const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
|
|
952
1062
|
const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
|
|
953
|
-
const itemStyle = [
|
|
1063
|
+
const itemStyle = [styles11.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
|
|
954
1064
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
955
|
-
return /* @__PURE__ */ (0,
|
|
956
|
-
option.icon && /* @__PURE__ */ (0,
|
|
957
|
-
/* @__PURE__ */ (0,
|
|
1065
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.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_runtime14.jsxs)(import_react_native14.View, { style: styles11.itemRow, children: [
|
|
1066
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper8.Icon, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
1067
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper8.Text, { variant: "labelLarge", style: [styles11.itemLabelFlex, labelStyle], children: option.label })
|
|
958
1068
|
] }) }, option.value);
|
|
959
1069
|
}),
|
|
960
|
-
section.allClear && /* @__PURE__ */ (0,
|
|
1070
|
+
section.allClear && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_feedback_press4.TouchableRipple, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles11.item, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper8.Text, { variant: "labelLarge", style: [styles11.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
|
|
961
1071
|
] });
|
|
962
1072
|
}
|
|
963
|
-
var
|
|
1073
|
+
var styles11 = import_react_native14.StyleSheet.create({
|
|
964
1074
|
allClearLabel: {
|
|
965
1075
|
fontWeight: "bold",
|
|
966
1076
|
textAlign: "center"
|
|
@@ -977,7 +1087,7 @@ var styles8 = import_react_native11.StyleSheet.create({
|
|
|
977
1087
|
zIndex: 100
|
|
978
1088
|
},
|
|
979
1089
|
divider: {
|
|
980
|
-
height:
|
|
1090
|
+
height: import_react_native14.StyleSheet.hairlineWidth,
|
|
981
1091
|
marginVertical: 4
|
|
982
1092
|
},
|
|
983
1093
|
item: {
|
|
@@ -1030,24 +1140,24 @@ var styles8 = import_react_native11.StyleSheet.create({
|
|
|
1030
1140
|
});
|
|
1031
1141
|
|
|
1032
1142
|
// src/ControlSchemePicker.tsx
|
|
1033
|
-
var
|
|
1034
|
-
function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, labelFontFamily }) {
|
|
1143
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1144
|
+
function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, alignOverride, rotation, labelFontFamily }) {
|
|
1035
1145
|
const isTouchPrimary = (0, import_core7.useIsTouchPrimaryDevice)();
|
|
1036
|
-
if (
|
|
1037
|
-
return /* @__PURE__ */ (0,
|
|
1146
|
+
if (import_react_native15.Platform.OS !== "web" || isTouchPrimary) return null;
|
|
1147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.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
1148
|
}
|
|
1039
1149
|
|
|
1040
1150
|
// src/CornerActionButtons.tsx
|
|
1041
1151
|
var import_feedback_press5 = require("@rific/feedback-press");
|
|
1042
|
-
var
|
|
1043
|
-
var
|
|
1152
|
+
var import_react_native16 = require("react-native");
|
|
1153
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1044
1154
|
function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back" }) {
|
|
1045
|
-
return /* @__PURE__ */ (0,
|
|
1046
|
-
/* @__PURE__ */ (0,
|
|
1047
|
-
/* @__PURE__ */ (0,
|
|
1155
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
1156
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_feedback_press5.IconButton, { icon: backIcon, iconColor: fg, size: 24, style: [styles12.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: backLabel }),
|
|
1157
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_feedback_press5.IconButton, { icon: "cog", iconColor: fg, size: 24, style: [styles12.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
|
|
1048
1158
|
] });
|
|
1049
1159
|
}
|
|
1050
|
-
var
|
|
1160
|
+
var styles12 = import_react_native16.StyleSheet.create({
|
|
1051
1161
|
back: {
|
|
1052
1162
|
position: "absolute"
|
|
1053
1163
|
},
|
|
@@ -1057,22 +1167,22 @@ var styles9 = import_react_native13.StyleSheet.create({
|
|
|
1057
1167
|
});
|
|
1058
1168
|
|
|
1059
1169
|
// src/CornerStatusBadges.tsx
|
|
1060
|
-
var
|
|
1061
|
-
var
|
|
1062
|
-
var
|
|
1170
|
+
var import_react_native17 = require("react-native");
|
|
1171
|
+
var import_react_native_paper9 = require("react-native-paper");
|
|
1172
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1063
1173
|
var BADGE_SIZE = 30;
|
|
1064
1174
|
function StatusBadge({ icon }) {
|
|
1065
|
-
return /* @__PURE__ */ (0,
|
|
1175
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native17.View, { style: styles13.badge, children: icon && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native_paper9.Icon, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
|
|
1066
1176
|
}
|
|
1067
1177
|
function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
|
|
1068
1178
|
const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
|
|
1069
1179
|
const p2OnLeftSide = orientationMode === "sideBySide" && !p1OnRight;
|
|
1070
|
-
return /* @__PURE__ */ (0,
|
|
1071
|
-
p1 && /* @__PURE__ */ (0,
|
|
1072
|
-
p2 && /* @__PURE__ */ (0,
|
|
1180
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
1181
|
+
p1 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native17.View, { pointerEvents: "none", style: p1OnRightSide ? styles13.bottomRight : styles13.bottomLeft, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(StatusBadge, { icon: p1.icon }) }),
|
|
1182
|
+
p2 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native17.View, { pointerEvents: "none", style: p2OnLeftSide ? styles13.topLeft : styles13.topRight, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(StatusBadge, { icon: p2.icon }) })
|
|
1073
1183
|
] });
|
|
1074
1184
|
}
|
|
1075
|
-
var
|
|
1185
|
+
var styles13 = import_react_native17.StyleSheet.create({
|
|
1076
1186
|
badge: {
|
|
1077
1187
|
alignItems: "center",
|
|
1078
1188
|
backgroundColor: "rgba(0,0,0,0.28)",
|
|
@@ -1091,12 +1201,12 @@ var styles10 = import_react_native14.StyleSheet.create({
|
|
|
1091
1201
|
});
|
|
1092
1202
|
|
|
1093
1203
|
// src/InlineColorPicker.tsx
|
|
1094
|
-
var
|
|
1204
|
+
var import_auto_paper9 = require("@rific/auto-paper");
|
|
1095
1205
|
var import_feedback_press6 = require("@rific/feedback-press");
|
|
1096
1206
|
var import_core8 = require("@tastic/core");
|
|
1097
|
-
var
|
|
1098
|
-
var
|
|
1099
|
-
var
|
|
1207
|
+
var import_react_native18 = require("react-native");
|
|
1208
|
+
var import_react_native_paper10 = require("react-native-paper");
|
|
1209
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1100
1210
|
var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
|
|
1101
1211
|
var DEFAULT_SIZE = 48;
|
|
1102
1212
|
var SWATCH_SIZE = 28;
|
|
@@ -1109,31 +1219,37 @@ var SCREEN_MARGIN = 40;
|
|
|
1109
1219
|
function widthForColumns(columns) {
|
|
1110
1220
|
return SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * columns + SWATCHES_GAP * (columns - 1);
|
|
1111
1221
|
}
|
|
1112
|
-
function
|
|
1222
|
+
function getInlineColorPickerContentSize(swatchCount, windowWidth, columns) {
|
|
1223
|
+
const autoColumns = (0, import_core8.clamp)(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS);
|
|
1224
|
+
const resolvedColumns = columns ?? autoColumns;
|
|
1225
|
+
const width = widthForColumns(resolvedColumns);
|
|
1226
|
+
const rows = Math.ceil(swatchCount / resolvedColumns);
|
|
1227
|
+
const height = SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * rows + SWATCHES_GAP * (rows - 1);
|
|
1228
|
+
return { width, height };
|
|
1229
|
+
}
|
|
1230
|
+
function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = import_auto_paper9.defaultColors, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
|
|
1113
1231
|
const ambientRotation = (0, import_core8.useRotation)();
|
|
1114
1232
|
const rotation = rotationOverride ?? ambientRotation;
|
|
1115
1233
|
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);
|
|
1234
|
+
const { width: windowWidth } = (0, import_react_native18.useWindowDimensions)();
|
|
1235
|
+
const { width: swatchesWidth, height: swatchesHeight } = getInlineColorPickerContentSize(swatches.length, windowWidth, columns);
|
|
1122
1236
|
const open = host.openId === id;
|
|
1123
|
-
const
|
|
1124
|
-
const
|
|
1237
|
+
const auto = useAutoAlign(open, swatchesWidth, swatchesHeight, rotation);
|
|
1238
|
+
const placement = alignOverride ?? auto;
|
|
1239
|
+
const { maxHeight, measured, triggerRef, verticalAlign } = placement;
|
|
1240
|
+
const align = forcedAlign ?? placement.align;
|
|
1125
1241
|
const displayFor = previewValue ?? ((hex) => hex);
|
|
1126
1242
|
const displayValue = displayFor(value);
|
|
1127
|
-
const contrastColor = (0,
|
|
1243
|
+
const contrastColor = (0, import_auto_paper9.getContrastColor)(displayValue);
|
|
1128
1244
|
const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
|
|
1129
|
-
return /* @__PURE__ */ (0,
|
|
1130
|
-
/* @__PURE__ */ (0,
|
|
1131
|
-
/* @__PURE__ */ (0,
|
|
1245
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native18.View, { style: [styles14.anchor, open && styles14.anchorOpen], children: [
|
|
1246
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_feedback_press6.TouchableRipple, { onPress: () => host.toggle(id), borderless: true, style: [styles14.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native18.View, { ref: triggerRef, collapsable: false, style: styles14.triggerMeasure, children: tag ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native_paper10.Text, { style: [styles14.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native_paper10.Icon, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
|
|
1247
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native18.ScrollView, { style: [styles14.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles14.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
|
|
1132
1248
|
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
1133
1249
|
const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
|
|
1134
1250
|
const swappable = taken && allowSwapTaken;
|
|
1135
1251
|
const swatchDisplay = displayFor(swatch.value);
|
|
1136
|
-
return /* @__PURE__ */ (0,
|
|
1252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1137
1253
|
import_feedback_press6.TouchableRipple,
|
|
1138
1254
|
{
|
|
1139
1255
|
disabled: taken && !swappable,
|
|
@@ -1142,15 +1258,15 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
|
|
|
1142
1258
|
if (autoDismiss) host.close();
|
|
1143
1259
|
},
|
|
1144
1260
|
borderless: true,
|
|
1145
|
-
style: [
|
|
1146
|
-
children: selected ? /* @__PURE__ */ (0,
|
|
1261
|
+
style: [styles14.swatch, { backgroundColor: swatchDisplay }, selected && styles14.swatchSelected, taken && !swappable && styles14.swatchTaken],
|
|
1262
|
+
children: selected ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native_paper10.Icon, { source: "check", size: 16, color: (0, import_auto_paper9.getContrastColor)(swatchDisplay) }) : swappable ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native_paper10.Icon, { source: "swap-horizontal", size: 16, color: (0, import_auto_paper9.getContrastColor)(swatchDisplay) }) : taken ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native_paper10.Icon, { source: "close", size: 16, color: (0, import_auto_paper9.getContrastColor)(swatchDisplay) }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native18.View, {})
|
|
1147
1263
|
},
|
|
1148
1264
|
swatch.value
|
|
1149
1265
|
);
|
|
1150
1266
|
}) }) })
|
|
1151
1267
|
] });
|
|
1152
1268
|
}
|
|
1153
|
-
var
|
|
1269
|
+
var styles14 = import_react_native18.StyleSheet.create({
|
|
1154
1270
|
anchor: {
|
|
1155
1271
|
position: "relative"
|
|
1156
1272
|
},
|
|
@@ -1222,11 +1338,11 @@ var styles11 = import_react_native15.StyleSheet.create({
|
|
|
1222
1338
|
});
|
|
1223
1339
|
|
|
1224
1340
|
// src/LabeledDropdown.tsx
|
|
1225
|
-
var
|
|
1341
|
+
var import_auto_paper10 = require("@rific/auto-paper");
|
|
1226
1342
|
var import_feedback_press7 = require("@rific/feedback-press");
|
|
1227
|
-
var
|
|
1228
|
-
var
|
|
1229
|
-
var
|
|
1343
|
+
var import_react_native19 = require("react-native");
|
|
1344
|
+
var import_react_native_paper11 = require("react-native-paper");
|
|
1345
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1230
1346
|
var TRIGGER_HEIGHT = 28;
|
|
1231
1347
|
var POPOVER_WIDTH = 180;
|
|
1232
1348
|
var ROW_HEIGHT = 36;
|
|
@@ -1249,22 +1365,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
|
|
|
1249
1365
|
onChange(option.value);
|
|
1250
1366
|
host.close();
|
|
1251
1367
|
};
|
|
1252
|
-
return /* @__PURE__ */ (0,
|
|
1253
|
-
/* @__PURE__ */ (0,
|
|
1254
|
-
/* @__PURE__ */ (0,
|
|
1255
|
-
/* @__PURE__ */ (0,
|
|
1368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native19.View, { style: [styles15.anchor, open && styles15.anchorOpen], children: [
|
|
1369
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_feedback_press7.TouchableRipple, { onPress: () => host.toggle(id), style: styles15.trigger, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native19.View, { ref: triggerRef, collapsable: false, style: styles15.triggerInner, children: [
|
|
1370
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper11.Text, { style: [styles15.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
|
|
1371
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper11.Icon, { source: "menu-down", size: 16, color })
|
|
1256
1372
|
] }) }),
|
|
1257
|
-
/* @__PURE__ */ (0,
|
|
1373
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native19.ScrollView, { style: [styles15.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles15.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
|
|
1258
1374
|
const isSelected = option.value === value;
|
|
1259
|
-
const onColor = (0,
|
|
1260
|
-
return /* @__PURE__ */ (0,
|
|
1261
|
-
option.icon && /* @__PURE__ */ (0,
|
|
1262
|
-
/* @__PURE__ */ (0,
|
|
1375
|
+
const onColor = (0, import_auto_paper10.getContrastColor)(color);
|
|
1376
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_feedback_press7.TouchableRipple, { onPress: () => handleSelect(option), style: [styles15.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native19.View, { style: styles15.rowInner, children: [
|
|
1377
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper11.Icon, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
|
|
1378
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper11.Text, { style: [styles15.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
|
|
1263
1379
|
] }) }, option.value);
|
|
1264
1380
|
}) }) })
|
|
1265
1381
|
] });
|
|
1266
1382
|
}
|
|
1267
|
-
var
|
|
1383
|
+
var styles15 = import_react_native19.StyleSheet.create({
|
|
1268
1384
|
anchor: {
|
|
1269
1385
|
position: "relative"
|
|
1270
1386
|
},
|
|
@@ -1321,26 +1437,23 @@ function loadSkiaWeb() {
|
|
|
1321
1437
|
return Promise.resolve();
|
|
1322
1438
|
}
|
|
1323
1439
|
|
|
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
|
-
}
|
|
1440
|
+
// src/PlayerSetupPanel.tsx
|
|
1441
|
+
var import_profile = require("@tastic/profile");
|
|
1442
|
+
var import_react_native21 = require("react-native");
|
|
1443
|
+
var import_react_native_paper13 = require("react-native-paper");
|
|
1331
1444
|
|
|
1332
1445
|
// src/ReadyButton.tsx
|
|
1333
1446
|
var import_feedback_press8 = require("@rific/feedback-press");
|
|
1334
|
-
var
|
|
1335
|
-
var
|
|
1336
|
-
var
|
|
1447
|
+
var import_react_native20 = require("react-native");
|
|
1448
|
+
var import_react_native_paper12 = require("react-native-paper");
|
|
1449
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1337
1450
|
function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
|
|
1338
|
-
const readyButtonStyle = [
|
|
1451
|
+
const readyButtonStyle = [styles16.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
|
|
1339
1452
|
const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
|
|
1340
1453
|
const labelColorStyle = { color: ready ? "#000000" : color };
|
|
1341
|
-
return /* @__PURE__ */ (0,
|
|
1454
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_feedback_press8.TouchableRipple, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_paper12.Text, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
|
|
1342
1455
|
}
|
|
1343
|
-
var
|
|
1456
|
+
var styles16 = import_react_native20.StyleSheet.create({
|
|
1344
1457
|
readyButton: {
|
|
1345
1458
|
alignItems: "center",
|
|
1346
1459
|
borderRadius: 12,
|
|
@@ -1352,22 +1465,97 @@ var styles13 = import_react_native18.StyleSheet.create({
|
|
|
1352
1465
|
}
|
|
1353
1466
|
});
|
|
1354
1467
|
|
|
1468
|
+
// src/usePopoverHost.ts
|
|
1469
|
+
var import_react8 = require("react");
|
|
1470
|
+
function usePopoverHost() {
|
|
1471
|
+
const [openId, setOpenId] = (0, import_react8.useState)(null);
|
|
1472
|
+
const toggle = (0, import_react8.useCallback)((id) => {
|
|
1473
|
+
setOpenId((prev) => prev === id ? null : id);
|
|
1474
|
+
}, []);
|
|
1475
|
+
const close = (0, import_react8.useCallback)(() => setOpenId(null), []);
|
|
1476
|
+
return { openId, toggle, close };
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
// src/PlayerSetupPanel.tsx
|
|
1480
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1481
|
+
function getColorPopoverId(idPrefix) {
|
|
1482
|
+
return `${idPrefix}-color`;
|
|
1483
|
+
}
|
|
1484
|
+
function getCpuDifficultyPopoverId(idPrefix) {
|
|
1485
|
+
return `${idPrefix}-difficulty`;
|
|
1486
|
+
}
|
|
1487
|
+
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" }) {
|
|
1488
|
+
const ownHost = usePopoverHost();
|
|
1489
|
+
const popover = host ?? ownHost;
|
|
1490
|
+
const ownPopoverOpen = popover.openId?.startsWith(`${idPrefix}-`) ?? false;
|
|
1491
|
+
const pickerRowPopoverOpen = popover.openId === getColorPopoverId(idPrefix) || secondPickerId !== void 0 && popover.openId === secondPickerId;
|
|
1492
|
+
const showProfilePicker = isHuman && profiles !== void 0 && !!onProfileSelect;
|
|
1493
|
+
const showCpuDifficulty = !isHuman && cpuDifficulty !== void 0 && cpuDifficultyOptions !== void 0 && !!onCpuDifficultyChange;
|
|
1494
|
+
const selectedProfile = profiles?.find((p) => p.id === selectedProfileId) ?? null;
|
|
1495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native21.View, { style: [styles17.panel, ownPopoverOpen && styles17.panelOpen], children: [
|
|
1496
|
+
showProfilePicker ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_profile.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_runtime21.jsx)(LabeledDropdown, { id: getCpuDifficultyPopoverId(idPrefix), host: popover, options: cpuDifficultyOptions, value: cpuDifficulty, onChange: onCpuDifficultyChange, color, dark, alignOverride: cpuDifficultyAlignOverride }) : label && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native_paper13.Text, { variant: "labelSmall", style: { color, fontFamily: labelFontFamily }, children: label }),
|
|
1497
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native21.View, { style: [styles17.pickerRow, pickerRowPopoverOpen && styles17.pickerRowOpen], children: [
|
|
1498
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.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 }),
|
|
1499
|
+
secondPicker
|
|
1500
|
+
] }),
|
|
1501
|
+
isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ReadyButton, { color, ready: ready ?? false, onToggleReady })
|
|
1502
|
+
] });
|
|
1503
|
+
}
|
|
1504
|
+
var styles17 = import_react_native21.StyleSheet.create({
|
|
1505
|
+
panel: {
|
|
1506
|
+
alignItems: "center",
|
|
1507
|
+
gap: 12
|
|
1508
|
+
},
|
|
1509
|
+
// See SectionedDropdown's anchorOpen comment — this panel is typically a sibling of another
|
|
1510
|
+
// panel (and/or a shared-controls row), so a popover escaping this panel's bounds needs the panel
|
|
1511
|
+
// itself elevated, not just the popover content, to paint above a later sibling.
|
|
1512
|
+
panelOpen: {
|
|
1513
|
+
zIndex: 100
|
|
1514
|
+
},
|
|
1515
|
+
// Same gap as `panel`'s own vertical rhythm, reused horizontally — the color picker and (when
|
|
1516
|
+
// present) secondPicker sit side by side within this row instead of stacked in the panel's own
|
|
1517
|
+
// column.
|
|
1518
|
+
pickerRow: {
|
|
1519
|
+
alignItems: "center",
|
|
1520
|
+
flexDirection: "row",
|
|
1521
|
+
gap: 12
|
|
1522
|
+
},
|
|
1523
|
+
// A popover is an absolutely-positioned sibling of its own trigger — so a tall one (the color
|
|
1524
|
+
// swatch grid) can extend down far enough to overlap the ReadyButton below, which paints on top of
|
|
1525
|
+
// it by default DOM order since it's a later sibling within `panel`. `panel`'s own panelOpen
|
|
1526
|
+
// elevation only helps this panel paint above OTHER panels (see its own comment) — it does nothing
|
|
1527
|
+
// for stacking *within* this panel, since React Native Web gives each View its own stacking
|
|
1528
|
+
// context. This is what actually fixes that: elevate pickerRow itself above its own later sibling
|
|
1529
|
+
// whenever one of its own popovers is open.
|
|
1530
|
+
pickerRowOpen: {
|
|
1531
|
+
zIndex: 100
|
|
1532
|
+
}
|
|
1533
|
+
});
|
|
1534
|
+
|
|
1535
|
+
// src/PressAwayOverlay.tsx
|
|
1536
|
+
var import_react_native22 = require("react-native");
|
|
1537
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1538
|
+
function PressAwayOverlay({ active, onPress, style }) {
|
|
1539
|
+
if (!active) return null;
|
|
1540
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native22.Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [import_react_native22.StyleSheet.absoluteFill, style] });
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1355
1543
|
// src/SharedActionBand.tsx
|
|
1356
1544
|
var import_feedback_press9 = require("@rific/feedback-press");
|
|
1357
|
-
var
|
|
1358
|
-
var
|
|
1545
|
+
var import_react_native23 = require("react-native");
|
|
1546
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1359
1547
|
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,
|
|
1548
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react_native23.View, { style: [styles18.column, popoverOpen && styles18.columnOpen], children: [
|
|
1549
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react_native23.View, { style: styles18.actionsRow, children: [
|
|
1550
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_feedback_press9.IconButton, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
|
|
1551
|
+
onRandomize && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_feedback_press9.IconButton, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
|
|
1552
|
+
onReset && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_feedback_press9.IconButton, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
|
|
1553
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_feedback_press9.IconButton, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
|
|
1366
1554
|
] }),
|
|
1367
1555
|
children
|
|
1368
1556
|
] });
|
|
1369
1557
|
}
|
|
1370
|
-
var
|
|
1558
|
+
var styles18 = import_react_native23.StyleSheet.create({
|
|
1371
1559
|
actionsRow: {
|
|
1372
1560
|
alignItems: "center",
|
|
1373
1561
|
flexDirection: "row",
|
|
@@ -1382,84 +1570,110 @@ var styles14 = import_react_native19.StyleSheet.create({
|
|
|
1382
1570
|
}
|
|
1383
1571
|
});
|
|
1384
1572
|
|
|
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
|
-
] });
|
|
1573
|
+
// src/StaggeredWord.tsx
|
|
1574
|
+
var import_react9 = require("react");
|
|
1575
|
+
var import_react_native24 = require("react-native");
|
|
1576
|
+
var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
|
|
1577
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1578
|
+
var STAGGER_MS = 45;
|
|
1579
|
+
var LETTER_DURATION_MS = 320;
|
|
1580
|
+
function getStaggeredWordDuration(letterCount) {
|
|
1581
|
+
return (letterCount - 1) * STAGGER_MS + LETTER_DURATION_MS;
|
|
1398
1582
|
}
|
|
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
|
-
] });
|
|
1583
|
+
function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }) {
|
|
1584
|
+
const progress = (0, import_react_native_reanimated2.useSharedValue)(reducedMotion ? 1 : 0);
|
|
1585
|
+
(0, import_react9.useEffect)(() => {
|
|
1586
|
+
if (reducedMotion) return;
|
|
1587
|
+
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)) }));
|
|
1588
|
+
}, [reducedMotion]);
|
|
1589
|
+
const style = (0, import_react_native_reanimated2.useAnimatedStyle)(() => ({
|
|
1590
|
+
opacity: progress.value,
|
|
1591
|
+
transform: [{ translateY: (1 - progress.value) * 12 }, { scale: 0.85 + progress.value * 0.15 }]
|
|
1592
|
+
}));
|
|
1593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native_reanimated2.default.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
|
|
1423
1594
|
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
fontWeight: "bold",
|
|
1431
|
-
letterSpacing: 2
|
|
1432
|
-
},
|
|
1433
|
-
section: {
|
|
1434
|
-
borderRadius: 12,
|
|
1435
|
-
gap: 8,
|
|
1436
|
-
padding: 16
|
|
1595
|
+
function StaggeredWord({ word, color, fontFamily, fontSize, lineHeight, reducedMotion, startIndex = 0, fontWeight = "bold", letterSpacing, style, onLayout }) {
|
|
1596
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_native24.View, { style: [styles19.row, style], onLayout, children: word.split("").map((char, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AnimatedLetter, { char, index: startIndex + i, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, i)) });
|
|
1597
|
+
}
|
|
1598
|
+
var styles19 = import_react_native24.StyleSheet.create({
|
|
1599
|
+
row: {
|
|
1600
|
+
flexDirection: "row"
|
|
1437
1601
|
}
|
|
1438
1602
|
});
|
|
1439
1603
|
|
|
1440
1604
|
// src/UpdateDialog.tsx
|
|
1441
1605
|
var import_updater2 = require("@rific/updater");
|
|
1442
|
-
var
|
|
1606
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1443
1607
|
function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onError }) {
|
|
1444
1608
|
const { manifest, onConfirm, respond } = useUpdateConfirmBridge();
|
|
1445
1609
|
(0, import_updater2.useUpdater)({ autoCheck, autoPrompt, onConfirm, onError });
|
|
1446
1610
|
const date = manifest ? new Date(manifest.createdAt) : null;
|
|
1447
|
-
return /* @__PURE__ */ (0,
|
|
1611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.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
1612
|
}
|
|
1449
1613
|
|
|
1450
|
-
// src/
|
|
1451
|
-
var
|
|
1452
|
-
function
|
|
1453
|
-
const [
|
|
1454
|
-
const
|
|
1455
|
-
|
|
1614
|
+
// src/useQuitConfirmation.ts
|
|
1615
|
+
var import_react10 = require("react");
|
|
1616
|
+
function useQuitConfirmation(hasProgress, onConfirmedBack) {
|
|
1617
|
+
const [confirmVisible, setConfirmVisible] = (0, import_react10.useState)(false);
|
|
1618
|
+
const hasProgressRef = (0, import_react10.useRef)(hasProgress);
|
|
1619
|
+
(0, import_react10.useEffect)(() => {
|
|
1620
|
+
hasProgressRef.current = hasProgress;
|
|
1621
|
+
});
|
|
1622
|
+
const onConfirmedBackRef = (0, import_react10.useRef)(onConfirmedBack);
|
|
1623
|
+
(0, import_react10.useEffect)(() => {
|
|
1624
|
+
onConfirmedBackRef.current = onConfirmedBack;
|
|
1625
|
+
});
|
|
1626
|
+
const requestBack = (0, import_react10.useCallback)(() => {
|
|
1627
|
+
if (hasProgressRef.current()) setConfirmVisible(true);
|
|
1628
|
+
else onConfirmedBackRef.current();
|
|
1456
1629
|
}, []);
|
|
1457
|
-
const
|
|
1458
|
-
return {
|
|
1630
|
+
const cancelBack = (0, import_react10.useCallback)(() => setConfirmVisible(false), []);
|
|
1631
|
+
return { confirmVisible, requestBack, cancelBack };
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
// src/useZoneClampedAlign.ts
|
|
1635
|
+
var import_split_screen = require("@tastic/split-screen");
|
|
1636
|
+
var import_react11 = require("react");
|
|
1637
|
+
var import_react_native25 = require("react-native");
|
|
1638
|
+
var import_react_native_safe_area_context = require("react-native-safe-area-context");
|
|
1639
|
+
var EDGE_MARGIN2 = 12;
|
|
1640
|
+
function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
1641
|
+
const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
|
|
1642
|
+
const zone = (0, import_split_screen.useZoneBounds)();
|
|
1643
|
+
const { height: windowHeight } = (0, import_react_native25.useWindowDimensions)();
|
|
1644
|
+
const insets = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
|
|
1645
|
+
const shouldMeasure = open && auto.measured && zone !== null;
|
|
1646
|
+
const [ownBounds, setOwnBounds] = (0, import_react11.useState)(null);
|
|
1647
|
+
const [prevShouldMeasure, setPrevShouldMeasure] = (0, import_react11.useState)(shouldMeasure);
|
|
1648
|
+
if (shouldMeasure !== prevShouldMeasure) {
|
|
1649
|
+
setPrevShouldMeasure(shouldMeasure);
|
|
1650
|
+
setOwnBounds(null);
|
|
1651
|
+
}
|
|
1652
|
+
(0, import_react11.useEffect)(() => {
|
|
1653
|
+
if (!shouldMeasure) return;
|
|
1654
|
+
auto.triggerRef.current?.measureInWindow((_x, y, _width, height) => {
|
|
1655
|
+
const belowShared = zone.zoneSide === "belowShared";
|
|
1656
|
+
const awayRoom = belowShared ? windowHeight - insets.bottom - (y + height) - EDGE_MARGIN2 : y - insets.top - EDGE_MARGIN2;
|
|
1657
|
+
const towardRoom = belowShared ? y - zone.sharedEdgeY - EDGE_MARGIN2 : zone.sharedEdgeY - (y + height) - EDGE_MARGIN2;
|
|
1658
|
+
const useToward = contentHeight > awayRoom && towardRoom > awayRoom;
|
|
1659
|
+
let awaySide = belowShared ? "below" : "above";
|
|
1660
|
+
let towardSide = belowShared ? "above" : "below";
|
|
1661
|
+
if (zone.rotated) {
|
|
1662
|
+
awaySide = awaySide === "above" ? "below" : "above";
|
|
1663
|
+
towardSide = towardSide === "above" ? "below" : "above";
|
|
1664
|
+
}
|
|
1665
|
+
setOwnBounds({ maxHeight: Math.max(useToward ? towardRoom : awayRoom, 0), verticalAlign: useToward ? towardSide : awaySide });
|
|
1666
|
+
});
|
|
1667
|
+
}, [shouldMeasure, zone, auto.triggerRef, contentHeight, windowHeight, insets.top, insets.bottom]);
|
|
1668
|
+
if (!zone) return auto;
|
|
1669
|
+
if (!ownBounds) return { ...auto, measured: false };
|
|
1670
|
+
return { ...auto, maxHeight: ownBounds.maxHeight, measured: auto.measured, verticalAlign: ownBounds.verticalAlign };
|
|
1459
1671
|
}
|
|
1460
1672
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1461
1673
|
0 && (module.exports = {
|
|
1674
|
+
AchievementCatalogSection,
|
|
1462
1675
|
AchievementRow,
|
|
1676
|
+
ActivityStatSection,
|
|
1463
1677
|
BaseSettingsDialog,
|
|
1464
1678
|
BaseStatsScreen,
|
|
1465
1679
|
ConfirmDialog,
|
|
@@ -1472,20 +1686,28 @@ function usePopoverHost() {
|
|
|
1472
1686
|
LOCKED_BADGE_COLOR,
|
|
1473
1687
|
LabeledDropdown,
|
|
1474
1688
|
MONO_FONT,
|
|
1689
|
+
PlayerSetupPanel,
|
|
1475
1690
|
PopoverBody,
|
|
1476
1691
|
PressAwayOverlay,
|
|
1477
1692
|
ReadyButton,
|
|
1478
1693
|
SectionedDropdown,
|
|
1479
1694
|
SharedActionBand,
|
|
1480
1695
|
SkiaGate,
|
|
1696
|
+
StaggeredWord,
|
|
1481
1697
|
StatRow,
|
|
1482
1698
|
StatSection,
|
|
1483
1699
|
TriggerGaugeHost,
|
|
1484
1700
|
UpdateDialog,
|
|
1701
|
+
getColorPopoverId,
|
|
1702
|
+
getCpuDifficultyPopoverId,
|
|
1703
|
+
getInlineColorPickerContentSize,
|
|
1485
1704
|
getLabeledDropdownContentHeight,
|
|
1486
1705
|
getOverlayCardColors,
|
|
1706
|
+
getStaggeredWordDuration,
|
|
1487
1707
|
loadSkiaWeb,
|
|
1488
1708
|
overlayStyles,
|
|
1489
1709
|
useAutoAlign,
|
|
1490
|
-
usePopoverHost
|
|
1710
|
+
usePopoverHost,
|
|
1711
|
+
useQuitConfirmation,
|
|
1712
|
+
useZoneClampedAlign
|
|
1491
1713
|
});
|