@tastic/hud 0.22.0 → 0.24.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/dist/index.mjs CHANGED
@@ -1,6 +1,3 @@
1
- import {
2
- SkiaGate
3
- } from "./chunk-XEOFR236.mjs";
4
1
  import {
5
2
  AchievementCatalogSection,
6
3
  AchievementRow,
@@ -10,18 +7,24 @@ import {
10
7
  ConfirmDialog,
11
8
  ContentGutter,
12
9
  CornerActionButtons,
10
+ InlineColorPicker,
13
11
  LOCKED_BADGE_COLOR,
14
12
  MONO_FONT,
13
+ PopoverBody,
14
+ PressAwayOverlay,
15
15
  RotatedFrame,
16
16
  StaggeredWord,
17
17
  StatRow,
18
18
  StatSection,
19
19
  UpdateDialog,
20
20
  WELL_SHADOW,
21
+ getInlineColorPickerContentSize,
21
22
  getStaggeredWordDuration,
23
+ useAutoAlign,
22
24
  useCompactDialog,
25
+ usePopoverHost,
23
26
  useWellColors
24
- } from "./chunk-N7A7W72S.mjs";
27
+ } from "./chunk-BXG44LIA.mjs";
25
28
  import {
26
29
  COMPACT_DIALOG_HEIGHT,
27
30
  DialogHeader,
@@ -32,6 +35,10 @@ import {
32
35
  overlayStyles,
33
36
  useOverlayCardColors
34
37
  } from "./chunk-PUF6TABL.mjs";
38
+ import {
39
+ loadSkiaWeb,
40
+ locateSkiaWebFile
41
+ } from "./chunk-3TCJHMJP.mjs";
35
42
 
36
43
  // src/AchievementUnlockList.tsx
37
44
  import { getContrastColor, useAutoPaperTheme } from "@rific/auto-paper";
@@ -85,132 +92,19 @@ import { Platform } from "react-native";
85
92
  import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
86
93
  import { IconButton, TouchableRipple } from "@rific/feedback-press";
87
94
  import { useRotation } from "@tastic/core";
88
- import { ScrollView, StyleSheet as StyleSheet3, View as View4 } from "react-native";
95
+ import { ScrollView, StyleSheet as StyleSheet2, View as View2 } from "react-native";
89
96
  import { Icon as Icon2, Text as Text2 } from "react-native-paper";
90
97
 
91
- // src/PopoverBody.tsx
92
- import { StyleSheet as StyleSheet2, View as View2 } from "react-native";
93
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
94
- var CARET_SIZE = 7;
95
- var CARET_RING_OFFSET = 2;
96
- var CARET_DIP = 1;
97
- function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
98
- if (!visible) return null;
99
- const above = verticalAlign === "above";
100
- const alignStyle = align === "left" ? styles2.contentLeft : align === "right" ? styles2.contentRight : styles2.contentCenter;
101
- const verticalStyle = above ? styles2.contentAbove : styles2.contentBelow;
102
- const ringSize = CARET_SIZE + caretBorderWidth;
103
- const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
104
- const caretFill = above ? "borderTopColor" : "borderBottomColor";
105
- const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
106
- const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
107
- return /* @__PURE__ */ jsxs2(View2, { style: [styles2.content, alignStyle, verticalStyle], children: [
108
- children,
109
- caretColor && /* @__PURE__ */ jsxs2(Fragment, { children: [
110
- /* @__PURE__ */ jsx2(View2, { style: [styles2.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
111
- /* @__PURE__ */ jsx2(View2, { style: [styles2.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
112
- ] })
113
- ] });
114
- }
115
- var styles2 = StyleSheet2.create({
116
- caret: {
117
- borderLeftColor: "transparent",
118
- borderRightColor: "transparent",
119
- height: 0,
120
- position: "absolute",
121
- width: 0,
122
- // Explicit, not left to DOM order - the box it dips into is itself a position:'relative' view,
123
- // which React Native Web always gives an implicit zIndex:0 (see PopoverBody's stacking-context
124
- // notes elsewhere in this codebase), so painting on top needs a real zIndex to beat that
125
- // reliably rather than relying on being the later sibling.
126
- zIndex: 1
127
- },
128
- content: {
129
- position: "absolute",
130
- zIndex: 50
131
- },
132
- contentAbove: {
133
- bottom: "100%",
134
- marginBottom: 8
135
- },
136
- contentBelow: {
137
- marginTop: 8,
138
- top: "100%"
139
- },
140
- // Stretched to the anchor's own (trigger) width, with alignItems centering the actual (usually
141
- // much wider) popover box inside via plain flexbox - not `left:'50%'` plus a percentage
142
- // `transform`, which depends on native resolving the box's own auto width before applying the
143
- // transform and has proven unreliable there, visibly shifting the box off-center.
144
- contentCenter: {
145
- alignItems: "center",
146
- left: 0,
147
- right: 0
148
- },
149
- contentLeft: {
150
- left: 0
151
- },
152
- contentRight: {
153
- right: 0
154
- }
155
- });
156
-
157
98
  // src/TriggerGaugeHost.tsx
158
- import { jsx as jsx3 } from "react/jsx-runtime";
159
- var getTriggerGauge = () => import("./TriggerGauge-GIHKGAZE.mjs").then((mod) => ({ default: mod.TriggerGauge }));
99
+ import { lazy, Suspense } from "react";
100
+ import { jsx as jsx2 } from "react/jsx-runtime";
101
+ var LazyTriggerGauge = lazy(() => loadSkiaWeb().then(() => import("./TriggerGauge-GIHKGAZE.mjs").then((mod) => ({ default: mod.TriggerGauge }))));
160
102
  function TriggerGaugeHost(props) {
161
- return /* @__PURE__ */ jsx3(SkiaGate, { getComponent: getTriggerGauge, componentProps: props });
162
- }
163
-
164
- // src/useAutoAlign.ts
165
- import { useCallback, useEffect, useRef, useState } from "react";
166
- import { useWindowDimensions } from "react-native";
167
- var EDGE_MARGIN = 12;
168
- function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
169
- if (rotation === 0) return { x, y, width, height };
170
- const cx = windowWidth / 2;
171
- const cy = windowHeight / 2;
172
- const dx = x + width / 2 - cx;
173
- const dy = y + height / 2 - cy;
174
- const [newDx, newDy, newWidth, newHeight] = rotation === 180 ? [-dx, -dy, width, height] : rotation === 90 ? [-dy, dx, height, width] : [dy, -dx, height, width];
175
- return { x: cx + newDx - newWidth / 2, y: cy + newDy - newHeight / 2, width: newWidth, height: newHeight };
176
- }
177
- function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
178
- const triggerRef = useRef(null);
179
- const { width: windowWidth, height: windowHeight } = useWindowDimensions();
180
- const [align, setAlign] = useState("center");
181
- const [verticalAlign, setVerticalAlign] = useState("below");
182
- const [maxHeight, setMaxHeight] = useState(contentHeight);
183
- const [measured, setMeasured] = useState(false);
184
- const [prevOpen, setPrevOpen] = useState(open);
185
- if (open !== prevOpen) {
186
- setPrevOpen(open);
187
- if (open) setMeasured(false);
188
- }
189
- const measure = useCallback(() => {
190
- triggerRef.current?.measureInWindow((rawX, rawY, rawWidth, rawHeight) => {
191
- const { x, y, width: triggerWidth, height: triggerHeight } = rotateRect(rawX, rawY, rawWidth, rawHeight, rotation, windowWidth, windowHeight);
192
- const centerX = x + triggerWidth / 2;
193
- const overflowsRight = centerX + contentWidth / 2 > windowWidth - EDGE_MARGIN;
194
- const overflowsLeft = centerX - contentWidth / 2 < EDGE_MARGIN;
195
- if (overflowsRight && !overflowsLeft) setAlign("right");
196
- else if (overflowsLeft && !overflowsRight) setAlign("left");
197
- else setAlign("center");
198
- const roomBelow = windowHeight - (y + triggerHeight) - EDGE_MARGIN;
199
- const roomAbove = y - EDGE_MARGIN;
200
- const above = contentHeight > roomBelow && roomAbove > roomBelow;
201
- setVerticalAlign(above ? "above" : "below");
202
- setMaxHeight(Math.max(above ? roomAbove : roomBelow, 0));
203
- setMeasured(true);
204
- });
205
- }, [contentWidth, contentHeight, windowWidth, windowHeight, rotation]);
206
- useEffect(() => {
207
- if (open) measure();
208
- }, [open, measure]);
209
- return { align, maxHeight, measured, triggerRef, verticalAlign };
103
+ return /* @__PURE__ */ jsx2(Suspense, { fallback: null, children: /* @__PURE__ */ jsx2(LazyTriggerGauge, { ...props }) });
210
104
  }
211
105
 
212
106
  // src/SectionedDropdown.tsx
213
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
107
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
214
108
  var MENU_BORDER_WIDTH = 1;
215
109
  var TRIGGER_SIZE = 44;
216
110
  var MENU_MIN_WIDTH = 200;
@@ -260,17 +154,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
260
154
  }
261
155
  gaugeOffset += section.options.length;
262
156
  }
263
- const anchorStyle = [styles3.anchor, open && styles3.anchorOpen];
157
+ const anchorStyle = [styles2.anchor, open && styles2.anchorOpen];
264
158
  const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
265
159
  const dividerStyle = { backgroundColor: menuBorderColor };
266
- return /* @__PURE__ */ jsxs3(View4, { style: anchorStyle, children: [
267
- /* @__PURE__ */ jsxs3(View4, { ref: triggerRef, collapsable: false, style: styles3.triggerBox, children: [
268
- /* @__PURE__ */ jsx4(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
269
- /* @__PURE__ */ jsx4(IconButton, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
160
+ return /* @__PURE__ */ jsxs2(View2, { style: anchorStyle, children: [
161
+ /* @__PURE__ */ jsxs2(View2, { ref: triggerRef, collapsable: false, style: styles2.triggerBox, children: [
162
+ /* @__PURE__ */ jsx3(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
163
+ /* @__PURE__ */ jsx3(IconButton, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
270
164
  ] }),
271
- /* @__PURE__ */ jsx4(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx4(ScrollView, { style: [styles3.menu, menuStyle], contentContainerStyle: styles3.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs3(View4, { children: [
272
- sectionIndex > 0 && /* @__PURE__ */ jsx4(View4, { style: [styles3.divider, dividerStyle] }),
273
- section.kind === "single" ? /* @__PURE__ */ jsx4(
165
+ /* @__PURE__ */ jsx3(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx3(ScrollView, { style: [styles2.menu, menuStyle], contentContainerStyle: styles2.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs2(View2, { children: [
166
+ sectionIndex > 0 && /* @__PURE__ */ jsx3(View2, { style: [styles2.divider, dividerStyle] }),
167
+ section.kind === "single" ? /* @__PURE__ */ jsx3(
274
168
  SingleSection,
275
169
  {
276
170
  section,
@@ -283,7 +177,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
283
177
  if (autoDismiss) host.close();
284
178
  }
285
179
  }
286
- ) : /* @__PURE__ */ jsx4(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
180
+ ) : /* @__PURE__ */ jsx3(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
287
181
  ] }, section.id)) }) })
288
182
  ] });
289
183
  }
@@ -295,18 +189,18 @@ function SingleSection({
295
189
  labelFontFamily,
296
190
  onSelect
297
191
  }) {
298
- return /* @__PURE__ */ jsx4(Fragment2, { children: section.options.map((option) => {
192
+ return /* @__PURE__ */ jsx3(Fragment, { children: section.options.map((option) => {
299
193
  const selected = option.value === section.value;
300
194
  const taken = !selected && option.value === section.takenValue;
301
195
  const rowColor = selected ? onAccentColor : mutedColor;
302
- const itemStyle = [styles3.item, selected && { backgroundColor: accentColor }, taken && styles3.itemTaken];
196
+ const itemStyle = [styles2.item, selected && { backgroundColor: accentColor }, taken && styles2.itemTaken];
303
197
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
304
198
  const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
305
- return /* @__PURE__ */ jsx4(TouchableRipple, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs3(View4, { style: styles3.itemRow, children: [
306
- option.icon && /* @__PURE__ */ jsx4(Icon2, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
307
- /* @__PURE__ */ jsxs3(View4, { style: styles3.itemLabelColumn, children: [
308
- /* @__PURE__ */ jsx4(Text2, { variant: "labelLarge", style: labelStyle, children: option.label }),
309
- option.description && /* @__PURE__ */ jsx4(Text2, { variant: "labelSmall", style: descriptionStyle, children: option.description })
199
+ return /* @__PURE__ */ jsx3(TouchableRipple, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs2(View2, { style: styles2.itemRow, children: [
200
+ option.icon && /* @__PURE__ */ jsx3(Icon2, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
201
+ /* @__PURE__ */ jsxs2(View2, { style: styles2.itemLabelColumn, children: [
202
+ /* @__PURE__ */ jsx3(Text2, { variant: "labelLarge", style: labelStyle, children: option.label }),
203
+ option.description && /* @__PURE__ */ jsx3(Text2, { variant: "labelSmall", style: descriptionStyle, children: option.description })
310
204
  ] })
311
205
  ] }) }, option.value);
312
206
  }) });
@@ -320,23 +214,23 @@ function MultiSection({
320
214
  allClearLabels
321
215
  }) {
322
216
  const allSelected = section.value.length === section.options.length;
323
- return /* @__PURE__ */ jsxs3(Fragment2, { children: [
217
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
324
218
  section.options.map((option, i) => {
325
219
  const selected = section.value.includes(option.value);
326
220
  const rowColor = selected ? onAccentColor : mutedColor;
327
221
  const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
328
222
  const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
329
- const itemStyle = [styles3.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
223
+ const itemStyle = [styles2.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
330
224
  const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
331
- return /* @__PURE__ */ jsx4(TouchableRipple, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs3(View4, { style: styles3.itemRow, children: [
332
- option.icon && /* @__PURE__ */ jsx4(Icon2, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
333
- /* @__PURE__ */ jsx4(Text2, { variant: "labelLarge", style: [styles3.itemLabelFlex, labelStyle], children: option.label })
225
+ return /* @__PURE__ */ jsx3(TouchableRipple, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs2(View2, { style: styles2.itemRow, children: [
226
+ option.icon && /* @__PURE__ */ jsx3(Icon2, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
227
+ /* @__PURE__ */ jsx3(Text2, { variant: "labelLarge", style: [styles2.itemLabelFlex, labelStyle], children: option.label })
334
228
  ] }) }, option.value);
335
229
  }),
336
- section.allClear && /* @__PURE__ */ jsx4(TouchableRipple, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles3.item, children: /* @__PURE__ */ jsx4(Text2, { variant: "labelLarge", style: [styles3.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
230
+ section.allClear && /* @__PURE__ */ jsx3(TouchableRipple, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles2.item, children: /* @__PURE__ */ jsx3(Text2, { variant: "labelLarge", style: [styles2.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
337
231
  ] });
338
232
  }
339
- var styles3 = StyleSheet3.create({
233
+ var styles2 = StyleSheet2.create({
340
234
  allClearLabel: {
341
235
  fontWeight: "bold",
342
236
  textAlign: "center"
@@ -353,7 +247,7 @@ var styles3 = StyleSheet3.create({
353
247
  zIndex: 100
354
248
  },
355
249
  divider: {
356
- height: StyleSheet3.hairlineWidth,
250
+ height: StyleSheet2.hairlineWidth,
357
251
  marginVertical: 4
358
252
  },
359
253
  item: {
@@ -406,30 +300,30 @@ var styles3 = StyleSheet3.create({
406
300
  });
407
301
 
408
302
  // src/ControlSchemePicker.tsx
409
- import { jsx as jsx5 } from "react/jsx-runtime";
303
+ import { jsx as jsx4 } from "react/jsx-runtime";
410
304
  function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, alignOverride, rotation, labelFontFamily }) {
411
305
  const isTouchPrimary = useIsTouchPrimaryDevice();
412
306
  if (Platform.OS !== "web" || isTouchPrimary) return null;
413
- return /* @__PURE__ */ jsx5(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 });
307
+ return /* @__PURE__ */ jsx4(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 });
414
308
  }
415
309
 
416
310
  // src/CornerStatusBadges.tsx
417
- import { StyleSheet as StyleSheet4, View as View5 } from "react-native";
311
+ import { StyleSheet as StyleSheet3, View as View3 } from "react-native";
418
312
  import { Icon as Icon3 } from "react-native-paper";
419
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
313
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
420
314
  var BADGE_SIZE = 30;
421
315
  function StatusBadge({ icon }) {
422
- return /* @__PURE__ */ jsx6(View5, { style: styles4.badge, children: icon && /* @__PURE__ */ jsx6(Icon3, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
316
+ return /* @__PURE__ */ jsx5(View3, { style: styles3.badge, children: icon && /* @__PURE__ */ jsx5(Icon3, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
423
317
  }
424
318
  function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
425
319
  const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
426
320
  const p2OnLeftSide = orientationMode === "sideBySide" && !p1OnRight;
427
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
428
- p1 && /* @__PURE__ */ jsx6(View5, { pointerEvents: "none", style: p1OnRightSide ? styles4.bottomRight : styles4.bottomLeft, children: /* @__PURE__ */ jsx6(StatusBadge, { icon: p1.icon }) }),
429
- p2 && /* @__PURE__ */ jsx6(View5, { pointerEvents: "none", style: p2OnLeftSide ? styles4.topLeft : styles4.topRight, children: /* @__PURE__ */ jsx6(StatusBadge, { icon: p2.icon }) })
321
+ return /* @__PURE__ */ jsxs3(Fragment2, { children: [
322
+ p1 && /* @__PURE__ */ jsx5(View3, { pointerEvents: "none", style: p1OnRightSide ? styles3.bottomRight : styles3.bottomLeft, children: /* @__PURE__ */ jsx5(StatusBadge, { icon: p1.icon }) }),
323
+ p2 && /* @__PURE__ */ jsx5(View3, { pointerEvents: "none", style: p2OnLeftSide ? styles3.topLeft : styles3.topRight, children: /* @__PURE__ */ jsx5(StatusBadge, { icon: p2.icon }) })
430
324
  ] });
431
325
  }
432
- var styles4 = StyleSheet4.create({
326
+ var styles3 = StyleSheet3.create({
433
327
  badge: {
434
328
  alignItems: "center",
435
329
  backgroundColor: "rgba(0,0,0,0.28)",
@@ -447,149 +341,12 @@ var styles4 = StyleSheet4.create({
447
341
  topRight: { position: "absolute", right: 12, top: 12 }
448
342
  });
449
343
 
450
- // src/InlineColorPicker.tsx
451
- import { defaultColors, getContrastColor as getContrastColor2 } from "@rific/auto-paper";
344
+ // src/LabeledDropdown.tsx
345
+ import { getContrastColor as getContrastColor2 } from "@rific/auto-paper";
452
346
  import { TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
453
- import { clamp, useRotation as useRotation2 } from "@tastic/core";
454
- import { ScrollView as ScrollView2, StyleSheet as StyleSheet5, useWindowDimensions as useWindowDimensions2, View as View6 } from "react-native";
347
+ import { ScrollView as ScrollView2, StyleSheet as StyleSheet4, View as View4 } from "react-native";
455
348
  import { Icon as Icon4, Text as Text3 } from "react-native-paper";
456
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
457
- var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
458
- var DEFAULT_SIZE = 48;
459
- var SWATCH_SIZE = 28;
460
- var SWATCHES_PADDING = 8;
461
- var SWATCHES_GAP = 6;
462
- var SWATCHES_BORDER_WIDTH = 2;
463
- var MIN_COLUMNS = 4;
464
- var MAX_COLUMNS = 5;
465
- var SCREEN_MARGIN = 40;
466
- function widthForColumns(columns) {
467
- return SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * columns + SWATCHES_GAP * (columns - 1);
468
- }
469
- function getInlineColorPickerContentSize(swatchCount, windowWidth, columns) {
470
- const autoColumns = clamp(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS);
471
- const resolvedColumns = columns ?? autoColumns;
472
- const width = widthForColumns(resolvedColumns);
473
- const rows = Math.ceil(swatchCount / resolvedColumns);
474
- const height = SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * rows + SWATCHES_GAP * (rows - 1);
475
- return { width, height };
476
- }
477
- function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = defaultColors, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
478
- const ambientRotation = useRotation2();
479
- const rotation = rotationOverride ?? ambientRotation;
480
- const menuBg = dark ? "#000000" : "#FFFFFF";
481
- const { width: windowWidth } = useWindowDimensions2();
482
- const { width: swatchesWidth, height: swatchesHeight } = getInlineColorPickerContentSize(swatches.length, windowWidth, columns);
483
- const open = host.openId === id;
484
- const auto = useAutoAlign(open, swatchesWidth, swatchesHeight, rotation);
485
- const placement = alignOverride ?? auto;
486
- const { maxHeight, measured, triggerRef, verticalAlign } = placement;
487
- const align = forcedAlign ?? placement.align;
488
- const displayFor = previewValue ?? ((hex) => hex);
489
- const displayValue = displayFor(value);
490
- const contrastColor = getContrastColor2(displayValue);
491
- const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
492
- return /* @__PURE__ */ jsxs5(View6, { style: [styles5.anchor, open && styles5.anchorOpen], children: [
493
- /* @__PURE__ */ jsx7(TouchableRipple2, { onPress: () => host.toggle(id), borderless: true, style: [styles5.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx7(View6, { ref: triggerRef, collapsable: false, style: styles5.triggerMeasure, children: tag ? /* @__PURE__ */ jsx7(Text3, { style: [styles5.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx7(Icon4, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
494
- /* @__PURE__ */ jsx7(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ jsx7(ScrollView2, { style: [styles5.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles5.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
495
- const selected = swatch.value.toLowerCase() === value.toLowerCase();
496
- const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
497
- const swappable = taken && allowSwapTaken;
498
- const swatchDisplay = displayFor(swatch.value);
499
- return /* @__PURE__ */ jsx7(
500
- TouchableRipple2,
501
- {
502
- disabled: taken && !swappable,
503
- onPress: () => {
504
- onChange(swatch.value);
505
- if (autoDismiss) host.close();
506
- },
507
- borderless: true,
508
- style: [styles5.swatch, { backgroundColor: swatchDisplay }, selected && styles5.swatchSelected, taken && !swappable && styles5.swatchTaken],
509
- children: selected ? /* @__PURE__ */ jsx7(Icon4, { source: "check", size: 16, color: getContrastColor2(swatchDisplay) }) : swappable ? /* @__PURE__ */ jsx7(Icon4, { source: "swap-horizontal", size: 16, color: getContrastColor2(swatchDisplay) }) : taken ? /* @__PURE__ */ jsx7(Icon4, { source: "close", size: 16, color: getContrastColor2(swatchDisplay) }) : /* @__PURE__ */ jsx7(View6, {})
510
- },
511
- swatch.value
512
- );
513
- }) }) })
514
- ] });
515
- }
516
- var styles5 = StyleSheet5.create({
517
- anchor: {
518
- position: "relative"
519
- },
520
- // See SectionedDropdown's identical comment - React Native Web gives every position:'relative' view
521
- // its own stacking context, so the elevation has to live on the anchor itself, not just the
522
- // popover content nested inside it, to correctly paint above this anchor's own later siblings.
523
- anchorOpen: {
524
- zIndex: 100
525
- },
526
- swatch: {
527
- alignItems: "center",
528
- borderRadius: SWATCH_SIZE / 2,
529
- height: SWATCH_SIZE,
530
- justifyContent: "center",
531
- width: SWATCH_SIZE
532
- },
533
- swatchSelected: {
534
- borderColor: "#ffffff",
535
- borderWidth: 2
536
- },
537
- swatchTaken: {
538
- opacity: 0.35
539
- },
540
- swatches: {
541
- borderRadius: 12,
542
- borderWidth: SWATCHES_BORDER_WIDTH,
543
- elevation: 8,
544
- shadowColor: "#000000",
545
- shadowOffset: { height: 2, width: 0 },
546
- shadowOpacity: 0.3,
547
- shadowRadius: 8
548
- // width is set inline above - border-box sizing means it has to include the border too
549
- // (2*SWATCHES_BORDER_WIDTH), not just padding+content, or exactly enough room goes missing that
550
- // the last column silently wraps to a new row. Anything wider than the exact sum just shows as
551
- // dead space on the right edge of each row instead.
552
- },
553
- // Separate from `swatches` itself - see SectionedDropdown's identical menu/menuContent split.
554
- // The scroll frame's own bounds (including maxHeight) live on the ScrollView; the actual grid
555
- // wrapping belongs to its contentContainerStyle, which sizes to the unclamped content instead.
556
- swatchesContent: {
557
- flexDirection: "row",
558
- flexWrap: "wrap",
559
- gap: SWATCHES_GAP,
560
- padding: SWATCHES_PADDING
561
- },
562
- tagLabel: {
563
- fontWeight: "700",
564
- letterSpacing: 0.5
565
- },
566
- // borderRadius/height/width come from the `size` prop instead (see render-site override) - no
567
- // fixed default here, since this style object is shared by every caller regardless of size.
568
- trigger: {
569
- alignItems: "center",
570
- alignSelf: "flex-start",
571
- justifyContent: "center"
572
- },
573
- // Wraps just the icon/tag, inside the TouchableRipple, purely so useAutoAlign has a plain View
574
- // to attach its measurement ref to - TouchableRipple itself doesn't forward a ref to a
575
- // measurable native node. Padded horizontally so a multi-character tag doesn't butt right up
576
- // against the trigger's own circular edge (an icon alone doesn't need it, but this style is
577
- // shared by both).
578
- triggerMeasure: {
579
- alignItems: "center",
580
- height: "100%",
581
- justifyContent: "center",
582
- paddingHorizontal: 4,
583
- width: "100%"
584
- }
585
- });
586
-
587
- // src/LabeledDropdown.tsx
588
- import { getContrastColor as getContrastColor3 } from "@rific/auto-paper";
589
- import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
590
- import { ScrollView as ScrollView3, StyleSheet as StyleSheet6, View as View7 } from "react-native";
591
- import { Icon as Icon5, Text as Text4 } from "react-native-paper";
592
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
349
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
593
350
  var TRIGGER_HEIGHT = 28;
594
351
  var POPOVER_WIDTH = 180;
595
352
  var ROW_HEIGHT = 36;
@@ -612,22 +369,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
612
369
  onChange(option.value);
613
370
  host.close();
614
371
  };
615
- return /* @__PURE__ */ jsxs6(View7, { style: [styles6.anchor, open && styles6.anchorOpen], children: [
616
- /* @__PURE__ */ jsx8(TouchableRipple3, { onPress: () => host.toggle(id), style: styles6.trigger, children: /* @__PURE__ */ jsxs6(View7, { ref: triggerRef, collapsable: false, style: styles6.triggerInner, children: [
617
- /* @__PURE__ */ jsx8(Text4, { style: [styles6.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
618
- /* @__PURE__ */ jsx8(Icon5, { source: "menu-down", size: 16, color })
372
+ return /* @__PURE__ */ jsxs4(View4, { style: [styles4.anchor, open && styles4.anchorOpen], children: [
373
+ /* @__PURE__ */ jsx6(TouchableRipple2, { onPress: () => host.toggle(id), style: styles4.trigger, children: /* @__PURE__ */ jsxs4(View4, { ref: triggerRef, collapsable: false, style: styles4.triggerInner, children: [
374
+ /* @__PURE__ */ jsx6(Text3, { style: [styles4.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
375
+ /* @__PURE__ */ jsx6(Icon4, { source: "menu-down", size: 16, color })
619
376
  ] }) }),
620
- /* @__PURE__ */ jsx8(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx8(ScrollView3, { style: [styles6.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles6.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
377
+ /* @__PURE__ */ jsx6(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx6(ScrollView2, { style: [styles4.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles4.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
621
378
  const isSelected = option.value === value;
622
- const onColor = getContrastColor3(color);
623
- return /* @__PURE__ */ jsx8(TouchableRipple3, { onPress: () => handleSelect(option), style: [styles6.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs6(View7, { style: styles6.rowInner, children: [
624
- option.icon && /* @__PURE__ */ jsx8(Icon5, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
625
- /* @__PURE__ */ jsx8(Text4, { style: [styles6.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
379
+ const onColor = getContrastColor2(color);
380
+ return /* @__PURE__ */ jsx6(TouchableRipple2, { onPress: () => handleSelect(option), style: [styles4.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs4(View4, { style: styles4.rowInner, children: [
381
+ option.icon && /* @__PURE__ */ jsx6(Icon4, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
382
+ /* @__PURE__ */ jsx6(Text3, { style: [styles4.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
626
383
  ] }) }, option.value);
627
384
  }) }) })
628
385
  ] });
629
386
  }
630
- var styles6 = StyleSheet6.create({
387
+ var styles4 = StyleSheet4.create({
631
388
  anchor: {
632
389
  position: "relative"
633
390
  },
@@ -679,28 +436,23 @@ var styles6 = StyleSheet6.create({
679
436
  }
680
437
  });
681
438
 
682
- // src/loadSkiaWeb.ts
683
- function loadSkiaWeb() {
684
- return Promise.resolve();
685
- }
686
-
687
439
  // src/PlayerSetupPanel.tsx
688
440
  import { getOptionPickerContentSize, getProfilePickerContentSize, OptionPicker, ProfilePicker } from "@tastic/profile";
689
- import { StyleSheet as StyleSheet8, View as View8 } from "react-native";
690
- import { Text as Text6 } from "react-native-paper";
441
+ import { StyleSheet as StyleSheet6, View as View5 } from "react-native";
442
+ import { Text as Text5 } from "react-native-paper";
691
443
 
692
444
  // src/ReadyButton.tsx
693
- import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
694
- import { StyleSheet as StyleSheet7 } from "react-native";
695
- import { Text as Text5 } from "react-native-paper";
696
- import { jsx as jsx9 } from "react/jsx-runtime";
445
+ import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
446
+ import { StyleSheet as StyleSheet5 } from "react-native";
447
+ import { Text as Text4 } from "react-native-paper";
448
+ import { jsx as jsx7 } from "react/jsx-runtime";
697
449
  function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
698
- const readyButtonStyle = [styles7.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
450
+ const readyButtonStyle = [styles5.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
699
451
  const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
700
452
  const labelColorStyle = { color: ready ? "#000000" : color };
701
- return /* @__PURE__ */ jsx9(TouchableRipple4, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx9(Text5, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
453
+ return /* @__PURE__ */ jsx7(TouchableRipple3, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx7(Text4, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
702
454
  }
703
- var styles7 = StyleSheet7.create({
455
+ var styles5 = StyleSheet5.create({
704
456
  readyButton: {
705
457
  alignItems: "center",
706
458
  borderRadius: 12,
@@ -712,41 +464,30 @@ var styles7 = StyleSheet7.create({
712
464
  }
713
465
  });
714
466
 
715
- // src/usePopoverHost.ts
716
- import { useCallback as useCallback2, useState as useState2 } from "react";
717
- function usePopoverHost() {
718
- const [openId, setOpenId] = useState2(null);
719
- const toggle = useCallback2((id) => {
720
- setOpenId((prev) => prev === id ? null : id);
721
- }, []);
722
- const close = useCallback2(() => setOpenId(null), []);
723
- return { openId, toggle, close };
724
- }
725
-
726
467
  // src/useZoneClampedAlign.ts
727
468
  import { useZoneBounds } from "@tastic/split-screen";
728
- import { useEffect as useEffect2, useState as useState3 } from "react";
729
- import { useWindowDimensions as useWindowDimensions3 } from "react-native";
469
+ import { useEffect, useState } from "react";
470
+ import { useWindowDimensions } from "react-native";
730
471
  import { useSafeAreaInsets } from "react-native-safe-area-context";
731
- var EDGE_MARGIN2 = 12;
472
+ var EDGE_MARGIN = 12;
732
473
  function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
733
474
  const auto = useAutoAlign(open, contentWidth, contentHeight, rotation);
734
475
  const zone = useZoneBounds();
735
- const { height: windowHeight } = useWindowDimensions3();
476
+ const { height: windowHeight } = useWindowDimensions();
736
477
  const insets = useSafeAreaInsets();
737
478
  const shouldMeasure = open && auto.measured && zone !== null;
738
- const [ownBounds, setOwnBounds] = useState3(null);
739
- const [prevShouldMeasure, setPrevShouldMeasure] = useState3(shouldMeasure);
479
+ const [ownBounds, setOwnBounds] = useState(null);
480
+ const [prevShouldMeasure, setPrevShouldMeasure] = useState(shouldMeasure);
740
481
  if (shouldMeasure !== prevShouldMeasure) {
741
482
  setPrevShouldMeasure(shouldMeasure);
742
483
  setOwnBounds(null);
743
484
  }
744
- useEffect2(() => {
485
+ useEffect(() => {
745
486
  if (!shouldMeasure) return;
746
487
  auto.triggerRef.current?.measureInWindow((_x, y, _width, height) => {
747
488
  const belowShared = zone.zoneSide === "belowShared";
748
- const awayRoom = belowShared ? windowHeight - insets.bottom - (y + height) - EDGE_MARGIN2 : y - insets.top - EDGE_MARGIN2;
749
- const towardRoom = belowShared ? y - zone.sharedEdgeY - EDGE_MARGIN2 : zone.sharedEdgeY - (y + height) - EDGE_MARGIN2;
489
+ const awayRoom = belowShared ? windowHeight - insets.bottom - (y + height) - EDGE_MARGIN : y - insets.top - EDGE_MARGIN;
490
+ const towardRoom = belowShared ? y - zone.sharedEdgeY - EDGE_MARGIN : zone.sharedEdgeY - (y + height) - EDGE_MARGIN;
750
491
  const useToward = contentHeight > awayRoom && towardRoom > awayRoom;
751
492
  let awaySide = belowShared ? "below" : "above";
752
493
  let towardSide = belowShared ? "above" : "below";
@@ -763,7 +504,7 @@ function useZoneClampedAlign(open, contentWidth, contentHeight, rotation = 0) {
763
504
  }
764
505
 
765
506
  // src/PlayerSetupPanel.tsx
766
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
507
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
767
508
  function getColorPopoverId(idPrefix) {
768
509
  return `${idPrefix}-color`;
769
510
  }
@@ -786,16 +527,16 @@ function PlayerSetupPanel({ idPrefix, host, label, labelFontFamily, color, onCol
786
527
  const seatPickerId = showProfilePicker ? getProfilePopoverId(idPrefix) : getCpuDifficultyPopoverId(idPrefix);
787
528
  const seatPickerSize = showProfilePicker ? getProfilePickerContentSize(profiles.length, !!onManageProfiles, colorSection) : getOptionPickerContentSize(cpuDifficultyOptions?.length ?? 0, colorSection);
788
529
  const seatPickerAlign = useZoneClampedAlign(seatButton && popover.openId === seatPickerId, seatPickerSize.width, seatPickerSize.height);
789
- return /* @__PURE__ */ jsxs7(View8, { style: [styles8.panel, ownPopoverOpen && styles8.panelOpen], children: [
790
- showProfilePicker ? /* @__PURE__ */ jsx10(ProfilePicker, { idPrefix, host: popover, profiles, selectedId: selectedProfileId ?? null, takenId: takenProfileId, color, dark, guestLabel: guestLabel ?? "GUEST", onSelect: (profile) => onProfileSelect?.(profile), onManage: onManageProfiles, colorSection, alignOverride: seatPickerAlign }) : showCpuDifficulty ? /* @__PURE__ */ jsx10(OptionPicker, { id: getCpuDifficultyPopoverId(idPrefix), host: popover, options: cpuDifficultyOptions, value: cpuDifficulty, onChange: onCpuDifficultyChange, color, dark, icon: cpuIcon, colorSection, alignOverride: seatPickerAlign }) : label && /* @__PURE__ */ jsx10(Text6, { variant: "labelSmall", style: { color, fontFamily: labelFontFamily }, children: label }),
791
- (!seatButton || secondPicker) && /* @__PURE__ */ jsxs7(View8, { style: [styles8.pickerRow, pickerRowPopoverOpen && styles8.pickerRowOpen], children: [
792
- !seatButton && /* @__PURE__ */ jsx10(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 }),
530
+ return /* @__PURE__ */ jsxs5(View5, { style: [styles6.panel, ownPopoverOpen && styles6.panelOpen], children: [
531
+ showProfilePicker ? /* @__PURE__ */ jsx8(ProfilePicker, { idPrefix, host: popover, profiles, selectedId: selectedProfileId ?? null, takenId: takenProfileId, color, dark, guestLabel: guestLabel ?? "GUEST", onSelect: (profile) => onProfileSelect?.(profile), onManage: onManageProfiles, colorSection, alignOverride: seatPickerAlign }) : showCpuDifficulty ? /* @__PURE__ */ jsx8(OptionPicker, { id: getCpuDifficultyPopoverId(idPrefix), host: popover, options: cpuDifficultyOptions, value: cpuDifficulty, onChange: onCpuDifficultyChange, color, dark, icon: cpuIcon, colorSection, alignOverride: seatPickerAlign }) : label && /* @__PURE__ */ jsx8(Text5, { variant: "labelSmall", style: { color, fontFamily: labelFontFamily }, children: label }),
532
+ (!seatButton || secondPicker) && /* @__PURE__ */ jsxs5(View5, { style: [styles6.pickerRow, pickerRowPopoverOpen && styles6.pickerRowOpen], children: [
533
+ !seatButton && /* @__PURE__ */ jsx8(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 }),
793
534
  secondPicker
794
535
  ] }),
795
- isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ jsx10(ReadyButton, { color, ready: ready ?? false, onToggleReady })
536
+ isHuman && showReadyButton && onToggleReady && /* @__PURE__ */ jsx8(ReadyButton, { color, ready: ready ?? false, onToggleReady })
796
537
  ] });
797
538
  }
798
- var styles8 = StyleSheet8.create({
539
+ var styles6 = StyleSheet6.create({
799
540
  panel: {
800
541
  alignItems: "center",
801
542
  gap: 12
@@ -826,30 +567,22 @@ var styles8 = StyleSheet8.create({
826
567
  }
827
568
  });
828
569
 
829
- // src/PressAwayOverlay.tsx
830
- import { Pressable, StyleSheet as StyleSheet9 } from "react-native";
831
- import { jsx as jsx11 } from "react/jsx-runtime";
832
- function PressAwayOverlay({ active, onPress, style }) {
833
- if (!active) return null;
834
- return /* @__PURE__ */ jsx11(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet9.absoluteFill, style] });
835
- }
836
-
837
570
  // src/SharedActionBand.tsx
838
571
  import { IconButton as IconButton2 } from "@rific/feedback-press";
839
- import { StyleSheet as StyleSheet10, View as View9 } from "react-native";
840
- import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
572
+ import { StyleSheet as StyleSheet7, View as View6 } from "react-native";
573
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
841
574
  function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
842
- return /* @__PURE__ */ jsxs8(View9, { style: [styles9.column, popoverOpen && styles9.columnOpen], children: [
843
- /* @__PURE__ */ jsxs8(View9, { style: styles9.actionsRow, children: [
844
- /* @__PURE__ */ jsx12(IconButton2, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
845
- onRandomize && /* @__PURE__ */ jsx12(IconButton2, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
846
- onReset && /* @__PURE__ */ jsx12(IconButton2, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
847
- /* @__PURE__ */ jsx12(IconButton2, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
575
+ return /* @__PURE__ */ jsxs6(View6, { style: [styles7.column, popoverOpen && styles7.columnOpen], children: [
576
+ /* @__PURE__ */ jsxs6(View6, { style: styles7.actionsRow, children: [
577
+ /* @__PURE__ */ jsx9(IconButton2, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
578
+ onRandomize && /* @__PURE__ */ jsx9(IconButton2, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
579
+ onReset && /* @__PURE__ */ jsx9(IconButton2, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
580
+ /* @__PURE__ */ jsx9(IconButton2, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
848
581
  ] }),
849
582
  children
850
583
  ] });
851
584
  }
852
- var styles9 = StyleSheet10.create({
585
+ var styles7 = StyleSheet7.create({
853
586
  actionsRow: {
854
587
  alignItems: "center",
855
588
  flexDirection: "row",
@@ -865,22 +598,22 @@ var styles9 = StyleSheet10.create({
865
598
  });
866
599
 
867
600
  // src/useQuitConfirmation.ts
868
- import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
601
+ import { useCallback, useEffect as useEffect2, useRef, useState as useState2 } from "react";
869
602
  function useQuitConfirmation(hasProgress, onConfirmedBack) {
870
- const [confirmVisible, setConfirmVisible] = useState4(false);
871
- const hasProgressRef = useRef2(hasProgress);
872
- useEffect3(() => {
603
+ const [confirmVisible, setConfirmVisible] = useState2(false);
604
+ const hasProgressRef = useRef(hasProgress);
605
+ useEffect2(() => {
873
606
  hasProgressRef.current = hasProgress;
874
607
  });
875
- const onConfirmedBackRef = useRef2(onConfirmedBack);
876
- useEffect3(() => {
608
+ const onConfirmedBackRef = useRef(onConfirmedBack);
609
+ useEffect2(() => {
877
610
  onConfirmedBackRef.current = onConfirmedBack;
878
611
  });
879
- const requestBack = useCallback3(() => {
612
+ const requestBack = useCallback(() => {
880
613
  if (hasProgressRef.current()) setConfirmVisible(true);
881
614
  else onConfirmedBackRef.current();
882
615
  }, []);
883
- const cancelBack = useCallback3(() => setConfirmVisible(false), []);
616
+ const cancelBack = useCallback(() => setConfirmVisible(false), []);
884
617
  return { confirmVisible, requestBack, cancelBack };
885
618
  }
886
619
  export {
@@ -911,7 +644,6 @@ export {
911
644
  RotatedFrame,
912
645
  SectionedDropdown,
913
646
  SharedActionBand,
914
- SkiaGate,
915
647
  StaggeredWord,
916
648
  StatRow,
917
649
  StatSection,
@@ -926,6 +658,7 @@ export {
926
658
  getStaggeredWordDuration,
927
659
  isCompactDialogHeight,
928
660
  loadSkiaWeb,
661
+ locateSkiaWebFile,
929
662
  overlayActionStyles,
930
663
  overlayStyles,
931
664
  useAutoAlign,