@tastic/hud 0.8.4 → 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 +556 -315
- package/dist/index.mjs +483 -262
- package/package.json +16 -8
- package/src/AchievementCatalogSection.tsx +60 -0
- package/src/ActivityStatSection.tsx +29 -0
- package/src/ConfirmDialog.tsx +30 -11
- 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,43 +417,62 @@ 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
|
-
|
|
316
|
-
|
|
317
|
-
/* @__PURE__ */ (0,
|
|
318
|
-
/* @__PURE__ */ (0,
|
|
319
|
-
/* @__PURE__ */ (0,
|
|
320
|
-
|
|
321
|
-
/* @__PURE__ */ (0,
|
|
427
|
+
const showCancel = cancelLabel !== void 0 && onCancel !== void 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 })
|
|
322
435
|
] })
|
|
323
436
|
] }) }) });
|
|
324
437
|
}
|
|
325
|
-
var
|
|
326
|
-
//
|
|
327
|
-
//
|
|
328
|
-
//
|
|
329
|
-
//
|
|
438
|
+
var styles5 = import_react_native7.StyleSheet.create({
|
|
439
|
+
// minWidth (not flexBasis) is each button's real floor - whenever both fit side by side, flexGrow
|
|
440
|
+
// still splits any leftover width evenly beyond that floor, same visual result as a plain flex: 1
|
|
441
|
+
// on a roomy screen, but a button can never be squeezed narrower than 128, only wrap to its own
|
|
442
|
+
// row instead (see actions' flexWrap below). This used to be flexBasis: 128, which measured
|
|
443
|
+
// correctly on web but rendered every button roughly SQUARE on iOS - confirmed live (see the
|
|
444
|
+
// "Quit Match?" Cancel/Quit buttons and the single-button "OK" dialogs both coming out ~128pt
|
|
445
|
+
// tall instead of wide). Root cause: react-native-paper's Button renders its Surface as two
|
|
446
|
+
// nested views on iOS only (Surface.tsx's SurfaceIOS, for shadow rendering) - only a curated
|
|
447
|
+
// allowlist of style keys (flex/flexGrow/flexShrink/width/height/position/... - notably NOT
|
|
448
|
+
// flexBasis) reaches the outer view, which is the real flex item inside this row; every other
|
|
449
|
+
// key, flexBasis included, falls through to an inner view whose own unspecified flexDirection
|
|
450
|
+
// defaults to column. flexGrow: 1 landed on the (row-context) outer view and grew width
|
|
451
|
+
// correctly; flexBasis: 128 landed on the (column-context) inner view instead, where a flexBasis
|
|
452
|
+
// sets HEIGHT, not width. minWidth isn't axis-relative like flexBasis, so it constrains width
|
|
453
|
+
// correctly regardless of which of the two views it ends up on. react-native-paper's Button also
|
|
330
454
|
// hardcodes numberOfLines={1} on its label with no override, so a button squeezed under its
|
|
331
455
|
// label's natural width silently ellipsizes ("Cancel" -> "Can...") instead of wrapping - assumed
|
|
332
456
|
// fixable by just giving the row more width, until confirmed live that these two-word labels
|
|
333
457
|
// (Cancel/Reset/New Game) can still lose the truncation fight even with the extra room card's own
|
|
334
|
-
// width fix below provides, on a narrow enough screen.
|
|
335
|
-
// width there's no side-by-side arrangement that fits both buttons at their natural label size,
|
|
336
|
-
// so the layout has to give (stack) rather than the label (truncate).
|
|
458
|
+
// width fix below provides, on a narrow enough screen.
|
|
337
459
|
actionButton: {
|
|
338
|
-
|
|
339
|
-
|
|
460
|
+
flexGrow: 1,
|
|
461
|
+
minWidth: 128
|
|
462
|
+
},
|
|
463
|
+
// A lone confirm button (no cancel - BaseSettingsDialog's info-only "OK" dialogs, e.g. the
|
|
464
|
+
// update-check "no update found" message) has nothing left to share actions' width with, so
|
|
465
|
+
// actionButton's own flexGrow: 1 would stretch it across the entire row instead of reading as a
|
|
466
|
+
// normal button. Same 128 floor, no flexGrow, so it stays at that natural size instead of filling
|
|
467
|
+
// the card - centered by actions' own justifyContent below.
|
|
468
|
+
actionButtonSingle: {
|
|
469
|
+
minWidth: 128
|
|
340
470
|
},
|
|
341
471
|
actions: {
|
|
342
472
|
flexDirection: "row",
|
|
343
473
|
flexWrap: "wrap",
|
|
344
474
|
gap: 12,
|
|
475
|
+
justifyContent: "center",
|
|
345
476
|
width: "100%"
|
|
346
477
|
},
|
|
347
478
|
body: {
|
|
@@ -372,18 +503,18 @@ var styles2 = import_react_native3.StyleSheet.create({
|
|
|
372
503
|
});
|
|
373
504
|
|
|
374
505
|
// src/useUpdateConfirmBridge.ts
|
|
375
|
-
var
|
|
506
|
+
var import_react2 = require("react");
|
|
376
507
|
function useUpdateConfirmBridge() {
|
|
377
|
-
const [manifest, setManifest] = (0,
|
|
378
|
-
const resolveRef = (0,
|
|
379
|
-
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)(
|
|
380
511
|
(next) => new Promise((resolve) => {
|
|
381
512
|
resolveRef.current = resolve;
|
|
382
513
|
setManifest(next);
|
|
383
514
|
}),
|
|
384
515
|
[]
|
|
385
516
|
);
|
|
386
|
-
const respond = (0,
|
|
517
|
+
const respond = (0, import_react2.useCallback)((confirmed) => {
|
|
387
518
|
setManifest(null);
|
|
388
519
|
resolveRef.current?.(confirmed);
|
|
389
520
|
resolveRef.current = null;
|
|
@@ -392,20 +523,20 @@ function useUpdateConfirmBridge() {
|
|
|
392
523
|
}
|
|
393
524
|
|
|
394
525
|
// src/BaseSettingsDialog.tsx
|
|
395
|
-
var
|
|
526
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
396
527
|
function SettingIcon({ source, color, containerColor }) {
|
|
397
|
-
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 }) });
|
|
398
529
|
}
|
|
399
530
|
function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, children }) {
|
|
400
|
-
const { colors } = (0,
|
|
531
|
+
const { colors } = (0, import_auto_paper6.useAutoPaperTheme)();
|
|
401
532
|
const ambientRotation = (0, import_core2.useRotation)();
|
|
402
533
|
const rotation = rotationOverride ?? ambientRotation;
|
|
403
534
|
const isTouchPrimary = (0, import_core2.useIsTouchPrimaryDevice)();
|
|
404
535
|
const { settings: hapticSettings, set: setHapticSettings } = (0, import_feedback_press2.useHapticSettings)();
|
|
405
536
|
const { settings: soundSettings, set: setSoundSettings } = (0, import_feedback_press2.useSoundSettings)();
|
|
406
|
-
const sound = (0,
|
|
537
|
+
const sound = (0, import_react3.useContext)(import_feedback_press2.SoundContext);
|
|
407
538
|
const { forceShort: forceHapticFeedback } = (0, import_feedback_press2.useVibration)();
|
|
408
|
-
const [infoMessage, setInfoMessage] = (0,
|
|
539
|
+
const [infoMessage, setInfoMessage] = (0, import_react3.useState)(null);
|
|
409
540
|
const { manifest: updateManifest, onConfirm: onUpdateConfirm, respond: respondToUpdateConfirm } = useUpdateConfirmBridge();
|
|
410
541
|
const { check, checking, updateReady } = (0, import_updater.useUpdater)({
|
|
411
542
|
autoCheck: false,
|
|
@@ -416,32 +547,32 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
416
547
|
});
|
|
417
548
|
const updateManifestDate = updateManifest ? new Date(updateManifest.createdAt) : null;
|
|
418
549
|
const showLockOrientation = isTouchPrimary && lockOrientation !== void 0 && onLockOrientationChange !== void 0;
|
|
419
|
-
const showEdgeGuard =
|
|
420
|
-
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;
|
|
421
552
|
const showSound = !hideSound;
|
|
422
553
|
const showAppearance = !hideAppearance;
|
|
423
|
-
const showUpdateCheck =
|
|
424
|
-
return /* @__PURE__ */ (0,
|
|
425
|
-
/* @__PURE__ */ (0,
|
|
426
|
-
/* @__PURE__ */ (0,
|
|
427
|
-
/* @__PURE__ */ (0,
|
|
428
|
-
/* @__PURE__ */ (0,
|
|
429
|
-
showLockOrientation && /* @__PURE__ */ (0,
|
|
430
|
-
/* @__PURE__ */ (0,
|
|
431
|
-
/* @__PURE__ */ (0,
|
|
432
|
-
/* @__PURE__ */ (0,
|
|
433
|
-
/* @__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" })
|
|
434
565
|
] })
|
|
435
566
|
] }) }),
|
|
436
|
-
showEdgeGuard && /* @__PURE__ */ (0,
|
|
437
|
-
/* @__PURE__ */ (0,
|
|
438
|
-
/* @__PURE__ */ (0,
|
|
439
|
-
/* @__PURE__ */ (0,
|
|
440
|
-
/* @__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" })
|
|
441
572
|
] })
|
|
442
573
|
] }) }),
|
|
443
|
-
(showSound || showHaptics) && /* @__PURE__ */ (0,
|
|
444
|
-
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)(
|
|
445
576
|
import_feedback_press2.TouchableRipple,
|
|
446
577
|
{
|
|
447
578
|
soundDisabled: true,
|
|
@@ -450,15 +581,15 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
450
581
|
setSoundSettings({ enabled });
|
|
451
582
|
if (enabled) sound.selection?.();
|
|
452
583
|
},
|
|
453
|
-
style:
|
|
584
|
+
style: styles6.toggleButtonInRow,
|
|
454
585
|
accessibilityLabel: `Sound ${soundSettings.enabled ? "on" : "off"}`,
|
|
455
|
-
children: /* @__PURE__ */ (0,
|
|
456
|
-
/* @__PURE__ */ (0,
|
|
457
|
-
/* @__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" })
|
|
458
589
|
] })
|
|
459
590
|
}
|
|
460
591
|
),
|
|
461
|
-
showHaptics && /* @__PURE__ */ (0,
|
|
592
|
+
showHaptics && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
462
593
|
import_feedback_press2.TouchableRipple,
|
|
463
594
|
{
|
|
464
595
|
hapticDisabled: true,
|
|
@@ -467,36 +598,36 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
467
598
|
setHapticSettings({ vibrate });
|
|
468
599
|
if (vibrate) forceHapticFeedback();
|
|
469
600
|
},
|
|
470
|
-
style:
|
|
601
|
+
style: styles6.toggleButtonInRow,
|
|
471
602
|
accessibilityLabel: `Haptics ${hapticSettings.vibrate ? "on" : "off"}`,
|
|
472
|
-
children: /* @__PURE__ */ (0,
|
|
473
|
-
/* @__PURE__ */ (0,
|
|
474
|
-
/* @__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" })
|
|
475
606
|
] })
|
|
476
607
|
}
|
|
477
608
|
)
|
|
478
609
|
] })
|
|
479
610
|
] }),
|
|
480
|
-
showAppearance && /* @__PURE__ */ (0,
|
|
481
|
-
/* @__PURE__ */ (0,
|
|
482
|
-
/* @__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 })
|
|
483
614
|
] }),
|
|
484
615
|
children,
|
|
485
|
-
showUpdateCheck && /* @__PURE__ */ (0,
|
|
486
|
-
/* @__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: [
|
|
487
618
|
"VERSION ",
|
|
488
619
|
version,
|
|
489
620
|
updateReady ? " \xB7 UPDATE READY" : ""
|
|
490
621
|
] }),
|
|
491
|
-
/* @__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" })
|
|
492
623
|
] })
|
|
493
624
|
] }) })
|
|
494
625
|
] }),
|
|
495
|
-
/* @__PURE__ */ (0,
|
|
496
|
-
/* @__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) })
|
|
497
628
|
] });
|
|
498
629
|
}
|
|
499
|
-
var
|
|
630
|
+
var styles6 = import_react_native8.StyleSheet.create({
|
|
500
631
|
content: {
|
|
501
632
|
gap: 24,
|
|
502
633
|
paddingVertical: 20
|
|
@@ -564,31 +695,31 @@ var styles3 = import_react_native4.StyleSheet.create({
|
|
|
564
695
|
});
|
|
565
696
|
|
|
566
697
|
// src/BaseStatsScreen.tsx
|
|
567
|
-
var
|
|
698
|
+
var import_auto_paper7 = require("@rific/auto-paper");
|
|
568
699
|
var import_feedback_press3 = require("@rific/feedback-press");
|
|
569
700
|
var import_core3 = require("@tastic/core");
|
|
570
|
-
var
|
|
571
|
-
var
|
|
572
|
-
var
|
|
573
|
-
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");
|
|
574
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 }) {
|
|
575
|
-
const { dark, colors } = (0,
|
|
706
|
+
const { dark, colors } = (0, import_auto_paper7.useAutoPaperTheme)();
|
|
576
707
|
const ambientRotation = (0, import_core3.useRotation)();
|
|
577
708
|
const rotation = rotationOverride ?? ambientRotation;
|
|
578
|
-
const [confirmResetVisible, setConfirmResetVisible] = (0,
|
|
709
|
+
const [confirmResetVisible, setConfirmResetVisible] = (0, import_react4.useState)(false);
|
|
579
710
|
const showReset = !!onReset;
|
|
580
711
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
581
712
|
const bg = bgOverride ?? (dark ? "#000000" : "#FFFFFF");
|
|
582
|
-
return /* @__PURE__ */ (0,
|
|
583
|
-
/* @__PURE__ */ (0,
|
|
584
|
-
/* @__PURE__ */ (0,
|
|
585
|
-
/* @__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 })
|
|
586
717
|
] }),
|
|
587
|
-
/* @__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: [
|
|
588
719
|
children,
|
|
589
|
-
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 })
|
|
590
721
|
] }),
|
|
591
|
-
/* @__PURE__ */ (0,
|
|
722
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
592
723
|
ConfirmDialog,
|
|
593
724
|
{
|
|
594
725
|
visible: confirmResetVisible,
|
|
@@ -608,7 +739,7 @@ function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", t
|
|
|
608
739
|
)
|
|
609
740
|
] });
|
|
610
741
|
}
|
|
611
|
-
var
|
|
742
|
+
var styles7 = import_react_native9.StyleSheet.create({
|
|
612
743
|
container: {
|
|
613
744
|
flex: 1
|
|
614
745
|
},
|
|
@@ -640,18 +771,18 @@ var styles4 = import_react_native5.StyleSheet.create({
|
|
|
640
771
|
|
|
641
772
|
// src/ContentGutter.tsx
|
|
642
773
|
var import_core4 = require("@tastic/core");
|
|
643
|
-
var
|
|
644
|
-
var
|
|
774
|
+
var import_react_native10 = require("react-native");
|
|
775
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
645
776
|
function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
|
|
646
|
-
const { width: windowWidth } = (0,
|
|
777
|
+
const { width: windowWidth } = (0, import_react_native10.useWindowDimensions)();
|
|
647
778
|
const { contentWidth, gutterWidth } = (0, import_core4.computeContentBounds)(windowWidth, maxContentWidth ?? Infinity);
|
|
648
|
-
return /* @__PURE__ */ (0,
|
|
649
|
-
/* @__PURE__ */ (0,
|
|
650
|
-
/* @__PURE__ */ (0,
|
|
651
|
-
/* @__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 })
|
|
652
783
|
] });
|
|
653
784
|
}
|
|
654
|
-
var
|
|
785
|
+
var styles8 = import_react_native10.StyleSheet.create({
|
|
655
786
|
// overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
|
|
656
787
|
// column instead of clipping cleanly at its own real width.
|
|
657
788
|
gutter: {
|
|
@@ -664,44 +795,40 @@ var styles5 = import_react_native6.StyleSheet.create({
|
|
|
664
795
|
|
|
665
796
|
// src/ControlSchemePicker.tsx
|
|
666
797
|
var import_core7 = require("@tastic/core");
|
|
667
|
-
var
|
|
798
|
+
var import_react_native15 = require("react-native");
|
|
668
799
|
|
|
669
800
|
// src/SectionedDropdown.tsx
|
|
670
|
-
var
|
|
801
|
+
var import_auto_paper8 = require("@rific/auto-paper");
|
|
671
802
|
var import_feedback_press4 = require("@rific/feedback-press");
|
|
672
803
|
var import_core6 = require("@tastic/core");
|
|
673
|
-
var
|
|
674
|
-
var
|
|
675
|
-
|
|
676
|
-
// src/fonts.ts
|
|
677
|
-
var import_react_native7 = require("react-native");
|
|
678
|
-
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");
|
|
679
806
|
|
|
680
807
|
// src/PopoverBody.tsx
|
|
681
|
-
var
|
|
682
|
-
var
|
|
808
|
+
var import_react_native11 = require("react-native");
|
|
809
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
683
810
|
var CARET_SIZE = 7;
|
|
684
811
|
var CARET_RING_OFFSET = 2;
|
|
685
812
|
var CARET_DIP = 1;
|
|
686
813
|
function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
|
|
687
814
|
if (!visible) return null;
|
|
688
815
|
const above = verticalAlign === "above";
|
|
689
|
-
const alignStyle = align === "left" ?
|
|
690
|
-
const verticalStyle = above ?
|
|
816
|
+
const alignStyle = align === "left" ? styles9.contentLeft : align === "right" ? styles9.contentRight : styles9.contentCenter;
|
|
817
|
+
const verticalStyle = above ? styles9.contentAbove : styles9.contentBelow;
|
|
691
818
|
const ringSize = CARET_SIZE + caretBorderWidth;
|
|
692
819
|
const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
|
|
693
820
|
const caretFill = above ? "borderTopColor" : "borderBottomColor";
|
|
694
821
|
const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
|
|
695
822
|
const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
|
|
696
|
-
return /* @__PURE__ */ (0,
|
|
823
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native11.View, { style: [styles9.content, alignStyle, verticalStyle], children: [
|
|
697
824
|
children,
|
|
698
|
-
caretColor && /* @__PURE__ */ (0,
|
|
699
|
-
/* @__PURE__ */ (0,
|
|
700
|
-
/* @__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 }] })
|
|
701
828
|
] })
|
|
702
829
|
] });
|
|
703
830
|
}
|
|
704
|
-
var
|
|
831
|
+
var styles9 = import_react_native11.StyleSheet.create({
|
|
705
832
|
caret: {
|
|
706
833
|
borderLeftColor: "transparent",
|
|
707
834
|
borderRightColor: "transparent",
|
|
@@ -744,11 +871,11 @@ var styles6 = import_react_native8.StyleSheet.create({
|
|
|
744
871
|
});
|
|
745
872
|
|
|
746
873
|
// src/SkiaGate.tsx
|
|
747
|
-
var
|
|
748
|
-
var
|
|
874
|
+
var import_react5 = require("react");
|
|
875
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
749
876
|
function SkiaGate({ getComponent, componentProps, fallback = null }) {
|
|
750
|
-
const [Component, setComponent] = (0,
|
|
751
|
-
(0,
|
|
877
|
+
const [Component, setComponent] = (0, import_react5.useState)(null);
|
|
878
|
+
(0, import_react5.useEffect)(() => {
|
|
752
879
|
let cancelled = false;
|
|
753
880
|
getComponent().then((mod) => {
|
|
754
881
|
if (!cancelled) setComponent(() => mod.default);
|
|
@@ -758,19 +885,19 @@ function SkiaGate({ getComponent, componentProps, fallback = null }) {
|
|
|
758
885
|
};
|
|
759
886
|
}, [getComponent]);
|
|
760
887
|
if (!Component) return fallback;
|
|
761
|
-
return /* @__PURE__ */ (0,
|
|
888
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Component, { ...componentProps });
|
|
762
889
|
}
|
|
763
890
|
|
|
764
891
|
// src/TriggerGaugeHost.tsx
|
|
765
|
-
var
|
|
892
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
766
893
|
var getTriggerGauge = () => Promise.resolve().then(() => (init_TriggerGauge(), TriggerGauge_exports)).then((mod) => ({ default: mod.TriggerGauge }));
|
|
767
894
|
function TriggerGaugeHost(props) {
|
|
768
|
-
return /* @__PURE__ */ (0,
|
|
895
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
|
|
769
896
|
}
|
|
770
897
|
|
|
771
898
|
// src/useAutoAlign.ts
|
|
772
|
-
var
|
|
773
|
-
var
|
|
899
|
+
var import_react7 = require("react");
|
|
900
|
+
var import_react_native13 = require("react-native");
|
|
774
901
|
var EDGE_MARGIN = 12;
|
|
775
902
|
function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
|
|
776
903
|
if (rotation === 0) return { x, y, width, height };
|
|
@@ -782,18 +909,18 @@ function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
|
|
|
782
909
|
return { x: cx + newDx - newWidth / 2, y: cy + newDy - newHeight / 2, width: newWidth, height: newHeight };
|
|
783
910
|
}
|
|
784
911
|
function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
785
|
-
const triggerRef = (0,
|
|
786
|
-
const { width: windowWidth, height: windowHeight } = (0,
|
|
787
|
-
const [align, setAlign] = (0,
|
|
788
|
-
const [verticalAlign, setVerticalAlign] = (0,
|
|
789
|
-
const [maxHeight, setMaxHeight] = (0,
|
|
790
|
-
const [measured, setMeasured] = (0,
|
|
791
|
-
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);
|
|
792
919
|
if (open !== prevOpen) {
|
|
793
920
|
setPrevOpen(open);
|
|
794
921
|
if (open) setMeasured(false);
|
|
795
922
|
}
|
|
796
|
-
const measure = (0,
|
|
923
|
+
const measure = (0, import_react7.useCallback)(() => {
|
|
797
924
|
triggerRef.current?.measureInWindow((rawX, rawY, rawWidth, rawHeight) => {
|
|
798
925
|
const { x, y, width: triggerWidth, height: triggerHeight } = rotateRect(rawX, rawY, rawWidth, rawHeight, rotation, windowWidth, windowHeight);
|
|
799
926
|
const centerX = x + triggerWidth / 2;
|
|
@@ -810,14 +937,14 @@ function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
|
810
937
|
setMeasured(true);
|
|
811
938
|
});
|
|
812
939
|
}, [contentWidth, contentHeight, windowWidth, windowHeight, rotation]);
|
|
813
|
-
(0,
|
|
940
|
+
(0, import_react7.useEffect)(() => {
|
|
814
941
|
if (open) measure();
|
|
815
942
|
}, [open, measure]);
|
|
816
943
|
return { align, maxHeight, measured, triggerRef, verticalAlign };
|
|
817
944
|
}
|
|
818
945
|
|
|
819
946
|
// src/SectionedDropdown.tsx
|
|
820
|
-
var
|
|
947
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
821
948
|
var MENU_BORDER_WIDTH = 1;
|
|
822
949
|
var TRIGGER_SIZE = 44;
|
|
823
950
|
var MENU_MIN_WIDTH = 200;
|
|
@@ -828,12 +955,12 @@ var MENU_ITEM_HEIGHT = 40;
|
|
|
828
955
|
var MENU_ITEM_HEIGHT_WITH_DESCRIPTION = 58;
|
|
829
956
|
var MENU_DIVIDER_HEIGHT = 9;
|
|
830
957
|
var MENU_VERTICAL_PADDING = 12;
|
|
831
|
-
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" } }) {
|
|
832
959
|
const ambientRotation = (0, import_core6.useRotation)();
|
|
833
960
|
const rotation = rotationOverride ?? ambientRotation;
|
|
834
961
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
835
|
-
const menuBorderColor = (0,
|
|
836
|
-
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;
|
|
837
964
|
const fg = dark ? "#FFFFFF" : "#000000";
|
|
838
965
|
const open = host.openId === id;
|
|
839
966
|
const estimatedHeight = MENU_VERTICAL_PADDING + sections.reduce((sum, section, sectionIndex) => {
|
|
@@ -842,8 +969,10 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
842
969
|
const divider = sectionIndex > 0 ? MENU_DIVIDER_HEIGHT : 0;
|
|
843
970
|
return sum + rows + footer + divider;
|
|
844
971
|
}, 0);
|
|
845
|
-
const
|
|
846
|
-
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;
|
|
847
976
|
const onlySection = sections.length === 1 ? sections[0] : null;
|
|
848
977
|
const selectedOption = onlySection?.kind === "single" ? onlySection.options.find((o) => o.value === onlySection.value) : void 0;
|
|
849
978
|
const triggerIcon = selectedOption?.icon ?? icon;
|
|
@@ -865,17 +994,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
865
994
|
}
|
|
866
995
|
gaugeOffset += section.options.length;
|
|
867
996
|
}
|
|
868
|
-
const anchorStyle = [
|
|
997
|
+
const anchorStyle = [styles11.anchor, open && styles11.anchorOpen];
|
|
869
998
|
const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
|
|
870
999
|
const dividerStyle = { backgroundColor: menuBorderColor };
|
|
871
|
-
return /* @__PURE__ */ (0,
|
|
872
|
-
/* @__PURE__ */ (0,
|
|
873
|
-
/* @__PURE__ */ (0,
|
|
874
|
-
/* @__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) })
|
|
875
1004
|
] }),
|
|
876
|
-
/* @__PURE__ */ (0,
|
|
877
|
-
sectionIndex > 0 && /* @__PURE__ */ (0,
|
|
878
|
-
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)(
|
|
879
1008
|
SingleSection,
|
|
880
1009
|
{
|
|
881
1010
|
section,
|
|
@@ -888,7 +1017,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
888
1017
|
if (autoDismiss) host.close();
|
|
889
1018
|
}
|
|
890
1019
|
}
|
|
891
|
-
) : /* @__PURE__ */ (0,
|
|
1020
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
|
|
892
1021
|
] }, section.id)) }) })
|
|
893
1022
|
] });
|
|
894
1023
|
}
|
|
@@ -900,18 +1029,18 @@ function SingleSection({
|
|
|
900
1029
|
labelFontFamily,
|
|
901
1030
|
onSelect
|
|
902
1031
|
}) {
|
|
903
|
-
return /* @__PURE__ */ (0,
|
|
1032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: section.options.map((option) => {
|
|
904
1033
|
const selected = option.value === section.value;
|
|
905
1034
|
const taken = !selected && option.value === section.takenValue;
|
|
906
1035
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
907
|
-
const itemStyle = [
|
|
1036
|
+
const itemStyle = [styles11.item, selected && { backgroundColor: accentColor }, taken && styles11.itemTaken];
|
|
908
1037
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
909
1038
|
const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
|
|
910
|
-
return /* @__PURE__ */ (0,
|
|
911
|
-
option.icon && /* @__PURE__ */ (0,
|
|
912
|
-
/* @__PURE__ */ (0,
|
|
913
|
-
/* @__PURE__ */ (0,
|
|
914
|
-
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 })
|
|
915
1044
|
] })
|
|
916
1045
|
] }) }, option.value);
|
|
917
1046
|
}) });
|
|
@@ -925,23 +1054,23 @@ function MultiSection({
|
|
|
925
1054
|
allClearLabels
|
|
926
1055
|
}) {
|
|
927
1056
|
const allSelected = section.value.length === section.options.length;
|
|
928
|
-
return /* @__PURE__ */ (0,
|
|
1057
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
929
1058
|
section.options.map((option, i) => {
|
|
930
1059
|
const selected = section.value.includes(option.value);
|
|
931
1060
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
932
1061
|
const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
|
|
933
1062
|
const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
|
|
934
|
-
const itemStyle = [
|
|
1063
|
+
const itemStyle = [styles11.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
|
|
935
1064
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
936
|
-
return /* @__PURE__ */ (0,
|
|
937
|
-
option.icon && /* @__PURE__ */ (0,
|
|
938
|
-
/* @__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 })
|
|
939
1068
|
] }) }, option.value);
|
|
940
1069
|
}),
|
|
941
|
-
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 }) })
|
|
942
1071
|
] });
|
|
943
1072
|
}
|
|
944
|
-
var
|
|
1073
|
+
var styles11 = import_react_native14.StyleSheet.create({
|
|
945
1074
|
allClearLabel: {
|
|
946
1075
|
fontWeight: "bold",
|
|
947
1076
|
textAlign: "center"
|
|
@@ -958,7 +1087,7 @@ var styles8 = import_react_native11.StyleSheet.create({
|
|
|
958
1087
|
zIndex: 100
|
|
959
1088
|
},
|
|
960
1089
|
divider: {
|
|
961
|
-
height:
|
|
1090
|
+
height: import_react_native14.StyleSheet.hairlineWidth,
|
|
962
1091
|
marginVertical: 4
|
|
963
1092
|
},
|
|
964
1093
|
item: {
|
|
@@ -1011,24 +1140,24 @@ var styles8 = import_react_native11.StyleSheet.create({
|
|
|
1011
1140
|
});
|
|
1012
1141
|
|
|
1013
1142
|
// src/ControlSchemePicker.tsx
|
|
1014
|
-
var
|
|
1015
|
-
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 }) {
|
|
1016
1145
|
const isTouchPrimary = (0, import_core7.useIsTouchPrimaryDevice)();
|
|
1017
|
-
if (
|
|
1018
|
-
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 });
|
|
1019
1148
|
}
|
|
1020
1149
|
|
|
1021
1150
|
// src/CornerActionButtons.tsx
|
|
1022
1151
|
var import_feedback_press5 = require("@rific/feedback-press");
|
|
1023
|
-
var
|
|
1024
|
-
var
|
|
1152
|
+
var import_react_native16 = require("react-native");
|
|
1153
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1025
1154
|
function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back" }) {
|
|
1026
|
-
return /* @__PURE__ */ (0,
|
|
1027
|
-
/* @__PURE__ */ (0,
|
|
1028
|
-
/* @__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" })
|
|
1029
1158
|
] });
|
|
1030
1159
|
}
|
|
1031
|
-
var
|
|
1160
|
+
var styles12 = import_react_native16.StyleSheet.create({
|
|
1032
1161
|
back: {
|
|
1033
1162
|
position: "absolute"
|
|
1034
1163
|
},
|
|
@@ -1038,22 +1167,22 @@ var styles9 = import_react_native13.StyleSheet.create({
|
|
|
1038
1167
|
});
|
|
1039
1168
|
|
|
1040
1169
|
// src/CornerStatusBadges.tsx
|
|
1041
|
-
var
|
|
1042
|
-
var
|
|
1043
|
-
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");
|
|
1044
1173
|
var BADGE_SIZE = 30;
|
|
1045
1174
|
function StatusBadge({ icon }) {
|
|
1046
|
-
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)" }) });
|
|
1047
1176
|
}
|
|
1048
1177
|
function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
|
|
1049
1178
|
const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
|
|
1050
1179
|
const p2OnLeftSide = orientationMode === "sideBySide" && !p1OnRight;
|
|
1051
|
-
return /* @__PURE__ */ (0,
|
|
1052
|
-
p1 && /* @__PURE__ */ (0,
|
|
1053
|
-
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 }) })
|
|
1054
1183
|
] });
|
|
1055
1184
|
}
|
|
1056
|
-
var
|
|
1185
|
+
var styles13 = import_react_native17.StyleSheet.create({
|
|
1057
1186
|
badge: {
|
|
1058
1187
|
alignItems: "center",
|
|
1059
1188
|
backgroundColor: "rgba(0,0,0,0.28)",
|
|
@@ -1072,12 +1201,12 @@ var styles10 = import_react_native14.StyleSheet.create({
|
|
|
1072
1201
|
});
|
|
1073
1202
|
|
|
1074
1203
|
// src/InlineColorPicker.tsx
|
|
1075
|
-
var
|
|
1204
|
+
var import_auto_paper9 = require("@rific/auto-paper");
|
|
1076
1205
|
var import_feedback_press6 = require("@rific/feedback-press");
|
|
1077
1206
|
var import_core8 = require("@tastic/core");
|
|
1078
|
-
var
|
|
1079
|
-
var
|
|
1080
|
-
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");
|
|
1081
1210
|
var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
|
|
1082
1211
|
var DEFAULT_SIZE = 48;
|
|
1083
1212
|
var SWATCH_SIZE = 28;
|
|
@@ -1090,31 +1219,37 @@ var SCREEN_MARGIN = 40;
|
|
|
1090
1219
|
function widthForColumns(columns) {
|
|
1091
1220
|
return SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * columns + SWATCHES_GAP * (columns - 1);
|
|
1092
1221
|
}
|
|
1093
|
-
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 }) {
|
|
1094
1231
|
const ambientRotation = (0, import_core8.useRotation)();
|
|
1095
1232
|
const rotation = rotationOverride ?? ambientRotation;
|
|
1096
1233
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
1097
|
-
const { width: windowWidth } = (0,
|
|
1098
|
-
const
|
|
1099
|
-
const resolvedColumns = columns ?? autoColumns;
|
|
1100
|
-
const swatchesWidth = widthForColumns(resolvedColumns);
|
|
1101
|
-
const swatchRows = Math.ceil(swatches.length / resolvedColumns);
|
|
1102
|
-
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);
|
|
1103
1236
|
const open = host.openId === id;
|
|
1104
|
-
const
|
|
1105
|
-
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;
|
|
1106
1241
|
const displayFor = previewValue ?? ((hex) => hex);
|
|
1107
1242
|
const displayValue = displayFor(value);
|
|
1108
|
-
const contrastColor = (0,
|
|
1243
|
+
const contrastColor = (0, import_auto_paper9.getContrastColor)(displayValue);
|
|
1109
1244
|
const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
|
|
1110
|
-
return /* @__PURE__ */ (0,
|
|
1111
|
-
/* @__PURE__ */ (0,
|
|
1112
|
-
/* @__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) => {
|
|
1113
1248
|
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
1114
1249
|
const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
|
|
1115
1250
|
const swappable = taken && allowSwapTaken;
|
|
1116
1251
|
const swatchDisplay = displayFor(swatch.value);
|
|
1117
|
-
return /* @__PURE__ */ (0,
|
|
1252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1118
1253
|
import_feedback_press6.TouchableRipple,
|
|
1119
1254
|
{
|
|
1120
1255
|
disabled: taken && !swappable,
|
|
@@ -1123,15 +1258,15 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
|
|
|
1123
1258
|
if (autoDismiss) host.close();
|
|
1124
1259
|
},
|
|
1125
1260
|
borderless: true,
|
|
1126
|
-
style: [
|
|
1127
|
-
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, {})
|
|
1128
1263
|
},
|
|
1129
1264
|
swatch.value
|
|
1130
1265
|
);
|
|
1131
1266
|
}) }) })
|
|
1132
1267
|
] });
|
|
1133
1268
|
}
|
|
1134
|
-
var
|
|
1269
|
+
var styles14 = import_react_native18.StyleSheet.create({
|
|
1135
1270
|
anchor: {
|
|
1136
1271
|
position: "relative"
|
|
1137
1272
|
},
|
|
@@ -1203,11 +1338,11 @@ var styles11 = import_react_native15.StyleSheet.create({
|
|
|
1203
1338
|
});
|
|
1204
1339
|
|
|
1205
1340
|
// src/LabeledDropdown.tsx
|
|
1206
|
-
var
|
|
1341
|
+
var import_auto_paper10 = require("@rific/auto-paper");
|
|
1207
1342
|
var import_feedback_press7 = require("@rific/feedback-press");
|
|
1208
|
-
var
|
|
1209
|
-
var
|
|
1210
|
-
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");
|
|
1211
1346
|
var TRIGGER_HEIGHT = 28;
|
|
1212
1347
|
var POPOVER_WIDTH = 180;
|
|
1213
1348
|
var ROW_HEIGHT = 36;
|
|
@@ -1230,22 +1365,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
|
|
|
1230
1365
|
onChange(option.value);
|
|
1231
1366
|
host.close();
|
|
1232
1367
|
};
|
|
1233
|
-
return /* @__PURE__ */ (0,
|
|
1234
|
-
/* @__PURE__ */ (0,
|
|
1235
|
-
/* @__PURE__ */ (0,
|
|
1236
|
-
/* @__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 })
|
|
1237
1372
|
] }) }),
|
|
1238
|
-
/* @__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) => {
|
|
1239
1374
|
const isSelected = option.value === value;
|
|
1240
|
-
const onColor = (0,
|
|
1241
|
-
return /* @__PURE__ */ (0,
|
|
1242
|
-
option.icon && /* @__PURE__ */ (0,
|
|
1243
|
-
/* @__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 })
|
|
1244
1379
|
] }) }, option.value);
|
|
1245
1380
|
}) }) })
|
|
1246
1381
|
] });
|
|
1247
1382
|
}
|
|
1248
|
-
var
|
|
1383
|
+
var styles15 = import_react_native19.StyleSheet.create({
|
|
1249
1384
|
anchor: {
|
|
1250
1385
|
position: "relative"
|
|
1251
1386
|
},
|
|
@@ -1302,26 +1437,23 @@ function loadSkiaWeb() {
|
|
|
1302
1437
|
return Promise.resolve();
|
|
1303
1438
|
}
|
|
1304
1439
|
|
|
1305
|
-
// src/
|
|
1306
|
-
var
|
|
1307
|
-
var
|
|
1308
|
-
|
|
1309
|
-
if (!active) return null;
|
|
1310
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native17.Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [import_react_native17.StyleSheet.absoluteFill, style] });
|
|
1311
|
-
}
|
|
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");
|
|
1312
1444
|
|
|
1313
1445
|
// src/ReadyButton.tsx
|
|
1314
1446
|
var import_feedback_press8 = require("@rific/feedback-press");
|
|
1315
|
-
var
|
|
1316
|
-
var
|
|
1317
|
-
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");
|
|
1318
1450
|
function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
|
|
1319
|
-
const readyButtonStyle = [
|
|
1451
|
+
const readyButtonStyle = [styles16.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
|
|
1320
1452
|
const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
|
|
1321
1453
|
const labelColorStyle = { color: ready ? "#000000" : color };
|
|
1322
|
-
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?" }) });
|
|
1323
1455
|
}
|
|
1324
|
-
var
|
|
1456
|
+
var styles16 = import_react_native20.StyleSheet.create({
|
|
1325
1457
|
readyButton: {
|
|
1326
1458
|
alignItems: "center",
|
|
1327
1459
|
borderRadius: 12,
|
|
@@ -1333,22 +1465,97 @@ var styles13 = import_react_native18.StyleSheet.create({
|
|
|
1333
1465
|
}
|
|
1334
1466
|
});
|
|
1335
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
|
+
|
|
1336
1543
|
// src/SharedActionBand.tsx
|
|
1337
1544
|
var import_feedback_press9 = require("@rific/feedback-press");
|
|
1338
|
-
var
|
|
1339
|
-
var
|
|
1545
|
+
var import_react_native23 = require("react-native");
|
|
1546
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1340
1547
|
function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
|
|
1341
|
-
return /* @__PURE__ */ (0,
|
|
1342
|
-
/* @__PURE__ */ (0,
|
|
1343
|
-
/* @__PURE__ */ (0,
|
|
1344
|
-
onRandomize && /* @__PURE__ */ (0,
|
|
1345
|
-
onReset && /* @__PURE__ */ (0,
|
|
1346
|
-
/* @__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" })
|
|
1347
1554
|
] }),
|
|
1348
1555
|
children
|
|
1349
1556
|
] });
|
|
1350
1557
|
}
|
|
1351
|
-
var
|
|
1558
|
+
var styles18 = import_react_native23.StyleSheet.create({
|
|
1352
1559
|
actionsRow: {
|
|
1353
1560
|
alignItems: "center",
|
|
1354
1561
|
flexDirection: "row",
|
|
@@ -1363,84 +1570,110 @@ var styles14 = import_react_native19.StyleSheet.create({
|
|
|
1363
1570
|
}
|
|
1364
1571
|
});
|
|
1365
1572
|
|
|
1366
|
-
// src/
|
|
1367
|
-
var
|
|
1368
|
-
var
|
|
1369
|
-
var
|
|
1370
|
-
var
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native20.View, { style: styles15.row, children: [
|
|
1376
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper10.Text, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
|
|
1377
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native_paper10.Text, { variant: "bodyMedium", style: [styles15.value, { color: fg }], children: value })
|
|
1378
|
-
] });
|
|
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;
|
|
1379
1582
|
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
},
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
});
|
|
1390
|
-
|
|
1391
|
-
// src/StatSection.tsx
|
|
1392
|
-
var import_auto_paper9 = require("@rific/auto-paper");
|
|
1393
|
-
var import_react_native21 = require("react-native");
|
|
1394
|
-
var import_react_native_paper11 = require("react-native-paper");
|
|
1395
|
-
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1396
|
-
function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
|
|
1397
|
-
const { dark } = (0, import_auto_paper9.useAutoPaperTheme)();
|
|
1398
|
-
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
1399
|
-
const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
|
|
1400
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native21.View, { style: [styles16.section, { backgroundColor: sectionBg }], children: [
|
|
1401
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_paper11.Text, { variant: "labelMedium", style: [styles16.label, { color: fg }], children: label }),
|
|
1402
|
-
children
|
|
1403
|
-
] });
|
|
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 });
|
|
1404
1594
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
fontWeight: "bold",
|
|
1412
|
-
letterSpacing: 2
|
|
1413
|
-
},
|
|
1414
|
-
section: {
|
|
1415
|
-
borderRadius: 12,
|
|
1416
|
-
gap: 8,
|
|
1417
|
-
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"
|
|
1418
1601
|
}
|
|
1419
1602
|
});
|
|
1420
1603
|
|
|
1421
1604
|
// src/UpdateDialog.tsx
|
|
1422
1605
|
var import_updater2 = require("@rific/updater");
|
|
1423
|
-
var
|
|
1606
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1424
1607
|
function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onError }) {
|
|
1425
1608
|
const { manifest, onConfirm, respond } = useUpdateConfirmBridge();
|
|
1426
1609
|
(0, import_updater2.useUpdater)({ autoCheck, autoPrompt, onConfirm, onError });
|
|
1427
1610
|
const date = manifest ? new Date(manifest.createdAt) : null;
|
|
1428
|
-
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) });
|
|
1429
1612
|
}
|
|
1430
1613
|
|
|
1431
|
-
// src/
|
|
1432
|
-
var
|
|
1433
|
-
function
|
|
1434
|
-
const [
|
|
1435
|
-
const
|
|
1436
|
-
|
|
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();
|
|
1437
1629
|
}, []);
|
|
1438
|
-
const
|
|
1439
|
-
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 };
|
|
1440
1671
|
}
|
|
1441
1672
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1442
1673
|
0 && (module.exports = {
|
|
1674
|
+
AchievementCatalogSection,
|
|
1443
1675
|
AchievementRow,
|
|
1676
|
+
ActivityStatSection,
|
|
1444
1677
|
BaseSettingsDialog,
|
|
1445
1678
|
BaseStatsScreen,
|
|
1446
1679
|
ConfirmDialog,
|
|
@@ -1453,20 +1686,28 @@ function usePopoverHost() {
|
|
|
1453
1686
|
LOCKED_BADGE_COLOR,
|
|
1454
1687
|
LabeledDropdown,
|
|
1455
1688
|
MONO_FONT,
|
|
1689
|
+
PlayerSetupPanel,
|
|
1456
1690
|
PopoverBody,
|
|
1457
1691
|
PressAwayOverlay,
|
|
1458
1692
|
ReadyButton,
|
|
1459
1693
|
SectionedDropdown,
|
|
1460
1694
|
SharedActionBand,
|
|
1461
1695
|
SkiaGate,
|
|
1696
|
+
StaggeredWord,
|
|
1462
1697
|
StatRow,
|
|
1463
1698
|
StatSection,
|
|
1464
1699
|
TriggerGaugeHost,
|
|
1465
1700
|
UpdateDialog,
|
|
1701
|
+
getColorPopoverId,
|
|
1702
|
+
getCpuDifficultyPopoverId,
|
|
1703
|
+
getInlineColorPickerContentSize,
|
|
1466
1704
|
getLabeledDropdownContentHeight,
|
|
1467
1705
|
getOverlayCardColors,
|
|
1706
|
+
getStaggeredWordDuration,
|
|
1468
1707
|
loadSkiaWeb,
|
|
1469
1708
|
overlayStyles,
|
|
1470
1709
|
useAutoAlign,
|
|
1471
|
-
usePopoverHost
|
|
1710
|
+
usePopoverHost,
|
|
1711
|
+
useQuitConfirmation,
|
|
1712
|
+
useZoneClampedAlign
|
|
1472
1713
|
});
|