@tastic/hud 0.6.0 → 0.7.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.d.mts +107 -63
- package/dist/index.d.ts +107 -63
- package/dist/index.js +448 -337
- package/dist/index.mjs +415 -307
- package/package.json +1 -1
- package/src/ConfirmDialog.tsx +104 -0
- package/src/ControlSchemePicker.tsx +53 -0
- package/src/CornerActionButtons.tsx +10 -2
- package/src/CornerStatusBadges.tsx +87 -0
- package/src/index.ts +3 -0
package/dist/index.mjs
CHANGED
|
@@ -369,20 +369,79 @@ var styles3 = StyleSheet3.create({
|
|
|
369
369
|
}
|
|
370
370
|
});
|
|
371
371
|
|
|
372
|
+
// src/ConfirmDialog.tsx
|
|
373
|
+
import { useAutoPaperTheme as useAutoPaperTheme4 } from "@rific/auto-paper";
|
|
374
|
+
import { Button as Button3 } from "@rific/feedback-press";
|
|
375
|
+
import { StyleSheet as StyleSheet4, View as View4 } from "react-native";
|
|
376
|
+
import { Icon as Icon4, Portal as Portal3, Text as Text4 } from "react-native-paper";
|
|
377
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
378
|
+
function ConfirmDialog({ visible, title, message, confirmLabel, cancelLabel, onConfirm, onCancel, rotation = 0, icon = "help-circle-outline", destructive = false }) {
|
|
379
|
+
const { dark, colors } = useAutoPaperTheme4();
|
|
380
|
+
if (!visible) return null;
|
|
381
|
+
const fg = dark ? "#FFFFFF" : "#000000";
|
|
382
|
+
const cardBg = dark ? "#111111" : "#F2F2F2";
|
|
383
|
+
const cardBorder = dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)";
|
|
384
|
+
const accent = destructive ? colors.danger : colors.primary;
|
|
385
|
+
const onAccent = destructive ? colors.onDanger : colors.onPrimary;
|
|
386
|
+
return /* @__PURE__ */ jsx4(Portal3, { children: /* @__PURE__ */ jsx4(View4, { style: styles4.overlay, children: /* @__PURE__ */ jsxs4(View4, { style: [styles4.card, { backgroundColor: cardBg, borderColor: cardBorder }, rotation % 360 !== 0 && { transform: [{ rotate: `${rotation}deg` }] }], children: [
|
|
387
|
+
/* @__PURE__ */ jsx4(Icon4, { source: icon, size: 64, color: accent }),
|
|
388
|
+
/* @__PURE__ */ jsx4(Text4, { variant: "headlineLarge", style: [styles4.title, { color: accent }], children: title }),
|
|
389
|
+
/* @__PURE__ */ jsx4(Text4, { variant: "bodyLarge", style: [styles4.body, { color: fg }], children: message }),
|
|
390
|
+
/* @__PURE__ */ jsxs4(View4, { style: styles4.actions, children: [
|
|
391
|
+
/* @__PURE__ */ jsx4(Button3, { mode: "outlined", onPress: onCancel, style: styles4.actionButton, children: cancelLabel }),
|
|
392
|
+
/* @__PURE__ */ jsx4(Button3, { mode: "contained", onPress: onConfirm, style: styles4.actionButton, buttonColor: accent, textColor: onAccent, children: confirmLabel })
|
|
393
|
+
] })
|
|
394
|
+
] }) }) });
|
|
395
|
+
}
|
|
396
|
+
var styles4 = StyleSheet4.create({
|
|
397
|
+
actionButton: {
|
|
398
|
+
flex: 1
|
|
399
|
+
},
|
|
400
|
+
actions: {
|
|
401
|
+
flexDirection: "row",
|
|
402
|
+
gap: 12,
|
|
403
|
+
width: "100%"
|
|
404
|
+
},
|
|
405
|
+
body: {
|
|
406
|
+
textAlign: "center"
|
|
407
|
+
},
|
|
408
|
+
card: {
|
|
409
|
+
alignItems: "center",
|
|
410
|
+
borderRadius: 20,
|
|
411
|
+
borderWidth: 1,
|
|
412
|
+
gap: 16,
|
|
413
|
+
maxWidth: 360,
|
|
414
|
+
padding: 32
|
|
415
|
+
},
|
|
416
|
+
overlay: {
|
|
417
|
+
alignItems: "center",
|
|
418
|
+
backgroundColor: "rgba(0,0,0,0.72)",
|
|
419
|
+
bottom: 0,
|
|
420
|
+
justifyContent: "center",
|
|
421
|
+
left: 0,
|
|
422
|
+
position: "absolute",
|
|
423
|
+
right: 0,
|
|
424
|
+
top: 0
|
|
425
|
+
},
|
|
426
|
+
title: {
|
|
427
|
+
fontWeight: "bold"
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
|
|
372
431
|
// src/ContentGutter.tsx
|
|
373
432
|
import { computeContentBounds } from "@tastic/core";
|
|
374
|
-
import { StyleSheet as
|
|
375
|
-
import { jsx as
|
|
433
|
+
import { StyleSheet as StyleSheet5, useWindowDimensions, View as View5 } from "react-native";
|
|
434
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
376
435
|
function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
|
|
377
436
|
const { width: windowWidth } = useWindowDimensions();
|
|
378
437
|
const { contentWidth, gutterWidth } = computeContentBounds(windowWidth, maxContentWidth ?? Infinity);
|
|
379
|
-
return /* @__PURE__ */
|
|
380
|
-
/* @__PURE__ */
|
|
381
|
-
/* @__PURE__ */
|
|
382
|
-
/* @__PURE__ */
|
|
438
|
+
return /* @__PURE__ */ jsxs5(View5, { style: [styles5.row, style], children: [
|
|
439
|
+
/* @__PURE__ */ jsx5(View5, { style: [styles5.gutter, { width: gutterWidth }], children: leftGutter }),
|
|
440
|
+
/* @__PURE__ */ jsx5(View5, { style: { width: contentWidth }, children }),
|
|
441
|
+
/* @__PURE__ */ jsx5(View5, { style: [styles5.gutter, { width: gutterWidth }], children: rightGutter })
|
|
383
442
|
] });
|
|
384
443
|
}
|
|
385
|
-
var
|
|
444
|
+
var styles5 = StyleSheet5.create({
|
|
386
445
|
// overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
|
|
387
446
|
// column instead of clipping cleanly at its own real width.
|
|
388
447
|
gutter: {
|
|
@@ -393,39 +452,23 @@ var styles4 = StyleSheet4.create({
|
|
|
393
452
|
}
|
|
394
453
|
});
|
|
395
454
|
|
|
396
|
-
// src/
|
|
397
|
-
import {
|
|
398
|
-
import {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
406
|
-
var styles5 = StyleSheet5.create({
|
|
407
|
-
back: {
|
|
408
|
-
position: "absolute"
|
|
409
|
-
},
|
|
410
|
-
topRight: {
|
|
411
|
-
position: "absolute"
|
|
412
|
-
}
|
|
413
|
-
});
|
|
455
|
+
// src/ControlSchemePicker.tsx
|
|
456
|
+
import { useIsTouchPrimaryDevice as useIsTouchPrimaryDevice2 } from "@tastic/core";
|
|
457
|
+
import { Platform as Platform3 } from "react-native";
|
|
458
|
+
|
|
459
|
+
// src/SectionedDropdown.tsx
|
|
460
|
+
import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
|
|
461
|
+
import { IconButton as IconButton2, TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
|
|
462
|
+
import { ScrollView as ScrollView3, StyleSheet as StyleSheet7, View as View8 } from "react-native";
|
|
463
|
+
import { Icon as Icon5, Text as Text5 } from "react-native-paper";
|
|
414
464
|
|
|
415
465
|
// src/fonts.ts
|
|
416
466
|
import { Platform as Platform2 } from "react-native";
|
|
417
467
|
var MONO_FONT = Platform2.select({ ios: "Menlo", android: "monospace", default: "monospace" });
|
|
418
468
|
|
|
419
|
-
// src/InlineColorPicker.tsx
|
|
420
|
-
import { defaultColors, getContrastColor } from "@rific/auto-paper";
|
|
421
|
-
import { TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
|
|
422
|
-
import { clamp } from "@tastic/core";
|
|
423
|
-
import { ScrollView as ScrollView3, StyleSheet as StyleSheet7, useWindowDimensions as useWindowDimensions3, View as View7 } from "react-native";
|
|
424
|
-
import { Icon as Icon4, Text as Text4 } from "react-native-paper";
|
|
425
|
-
|
|
426
469
|
// src/PopoverBody.tsx
|
|
427
|
-
import { StyleSheet as StyleSheet6, View as
|
|
428
|
-
import { Fragment as
|
|
470
|
+
import { StyleSheet as StyleSheet6, View as View6 } from "react-native";
|
|
471
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
429
472
|
var CARET_SIZE = 7;
|
|
430
473
|
var CARET_RING_OFFSET = 2;
|
|
431
474
|
var CARET_DIP = 1;
|
|
@@ -439,11 +482,11 @@ function PopoverBody({ visible, children, align = "center", verticalAlign = "bel
|
|
|
439
482
|
const caretFill = above ? "borderTopColor" : "borderBottomColor";
|
|
440
483
|
const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
|
|
441
484
|
const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
|
|
442
|
-
return /* @__PURE__ */ jsxs6(
|
|
485
|
+
return /* @__PURE__ */ jsxs6(View6, { style: [styles6.content, alignStyle, verticalStyle], children: [
|
|
443
486
|
children,
|
|
444
|
-
caretColor && /* @__PURE__ */ jsxs6(
|
|
445
|
-
/* @__PURE__ */ jsx6(
|
|
446
|
-
/* @__PURE__ */ jsx6(
|
|
487
|
+
caretColor && /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
488
|
+
/* @__PURE__ */ jsx6(View6, { style: [styles6.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
|
|
489
|
+
/* @__PURE__ */ jsx6(View6, { style: [styles6.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
|
|
447
490
|
] })
|
|
448
491
|
] });
|
|
449
492
|
}
|
|
@@ -489,6 +532,21 @@ var styles6 = StyleSheet6.create({
|
|
|
489
532
|
}
|
|
490
533
|
});
|
|
491
534
|
|
|
535
|
+
// src/TriggerGaugeHost.tsx
|
|
536
|
+
import { lazy, Suspense } from "react";
|
|
537
|
+
|
|
538
|
+
// src/loadSkiaWeb.ts
|
|
539
|
+
function loadSkiaWeb() {
|
|
540
|
+
return Promise.resolve();
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// src/TriggerGaugeHost.tsx
|
|
544
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
545
|
+
var LazyTriggerGauge = lazy(() => loadSkiaWeb().then(() => import("./TriggerGauge-2OJOOF6I.mjs").then((m) => ({ default: m.TriggerGauge }))));
|
|
546
|
+
function TriggerGaugeHost(props) {
|
|
547
|
+
return /* @__PURE__ */ jsx7(Suspense, { fallback: null, children: /* @__PURE__ */ jsx7(LazyTriggerGauge, { ...props }) });
|
|
548
|
+
}
|
|
549
|
+
|
|
492
550
|
// src/useAutoAlign.ts
|
|
493
551
|
import { useCallback, useEffect, useRef, useState as useState3 } from "react";
|
|
494
552
|
import { useWindowDimensions as useWindowDimensions2 } from "react-native";
|
|
@@ -527,8 +585,266 @@ function useAutoAlign(open, contentWidth, contentHeight) {
|
|
|
527
585
|
return { align, maxHeight, measured, triggerRef, verticalAlign };
|
|
528
586
|
}
|
|
529
587
|
|
|
588
|
+
// src/SectionedDropdown.tsx
|
|
589
|
+
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
590
|
+
var MENU_BORDER_WIDTH = 1;
|
|
591
|
+
var TRIGGER_SIZE = 44;
|
|
592
|
+
var MENU_MIN_WIDTH = 200;
|
|
593
|
+
var MENU_MAX_WIDTH = 220;
|
|
594
|
+
var MENU_ITEM_ICON_SIZE = 18;
|
|
595
|
+
var MENU_ITEM_LABEL_MAX_WIDTH = 150;
|
|
596
|
+
var MENU_ITEM_HEIGHT = 40;
|
|
597
|
+
var MENU_ITEM_HEIGHT_WITH_DESCRIPTION = 58;
|
|
598
|
+
var MENU_DIVIDER_HEIGHT = 9;
|
|
599
|
+
var MENU_VERTICAL_PADDING = 12;
|
|
600
|
+
function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accentColor, mutedColor, onAccentColor, dark, align: alignOverride, autoDismiss = true, labelFontFamily = MONO_FONT, allClearLabels = { all: "All", clear: "Clear" } }) {
|
|
601
|
+
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
602
|
+
const menuBorderColor = getBlendedColor(mutedColor, menuBg, 0.5);
|
|
603
|
+
const resolvedOnAccentColor = onAccentColor ?? getColorRoles(accentColor, menuBg).onColor;
|
|
604
|
+
const fg = dark ? "#FFFFFF" : "#000000";
|
|
605
|
+
const open = host.openId === id;
|
|
606
|
+
const estimatedHeight = MENU_VERTICAL_PADDING + sections.reduce((sum, section, sectionIndex) => {
|
|
607
|
+
const rows = section.options.reduce((rowSum, option) => rowSum + (option.description ? MENU_ITEM_HEIGHT_WITH_DESCRIPTION : MENU_ITEM_HEIGHT), 0);
|
|
608
|
+
const footer = section.kind === "multi" && section.allClear ? MENU_ITEM_HEIGHT : 0;
|
|
609
|
+
const divider = sectionIndex > 0 ? MENU_DIVIDER_HEIGHT : 0;
|
|
610
|
+
return sum + rows + footer + divider;
|
|
611
|
+
}, 0);
|
|
612
|
+
const { align: autoAlign, maxHeight, measured, triggerRef, verticalAlign } = useAutoAlign(open, MENU_MAX_WIDTH, estimatedHeight);
|
|
613
|
+
const align = alignOverride ?? autoAlign;
|
|
614
|
+
const onlySection = sections.length === 1 ? sections[0] : null;
|
|
615
|
+
const selectedOption = onlySection?.kind === "single" ? onlySection.options.find((o) => o.value === onlySection.value) : void 0;
|
|
616
|
+
const triggerIcon = selectedOption?.icon ?? icon;
|
|
617
|
+
const triggerIconSize = selectedOption?.iconSize ?? 22;
|
|
618
|
+
const hasMultiSection = sections.some((s) => s.kind === "multi");
|
|
619
|
+
const anyMultiSelected = sections.some((s) => s.kind === "multi" && s.value.length > 0);
|
|
620
|
+
const triggerIconColor = hasMultiSection ? anyMultiSelected ? accentColor : fg : fg;
|
|
621
|
+
const gaugeSegments = sections.reduce((sum, section) => sum + section.options.length, 0);
|
|
622
|
+
const gaugeLitIndices = [];
|
|
623
|
+
let gaugeOffset = 0;
|
|
624
|
+
for (const section of sections) {
|
|
625
|
+
if (section.kind === "single") {
|
|
626
|
+
const index = section.options.findIndex((o) => o.value === section.value);
|
|
627
|
+
if (index >= 0) gaugeLitIndices.push(gaugeOffset + index);
|
|
628
|
+
} else {
|
|
629
|
+
section.options.forEach((o, i) => {
|
|
630
|
+
if (section.value.includes(o.value)) gaugeLitIndices.push(gaugeOffset + i);
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
gaugeOffset += section.options.length;
|
|
634
|
+
}
|
|
635
|
+
const anchorStyle = [styles7.anchor, open && styles7.anchorOpen];
|
|
636
|
+
const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
|
|
637
|
+
const dividerStyle = { backgroundColor: menuBorderColor };
|
|
638
|
+
return /* @__PURE__ */ jsxs7(View8, { style: anchorStyle, children: [
|
|
639
|
+
/* @__PURE__ */ jsxs7(View8, { ref: triggerRef, collapsable: false, style: styles7.triggerBox, children: [
|
|
640
|
+
/* @__PURE__ */ jsx8(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
|
|
641
|
+
/* @__PURE__ */ jsx8(IconButton2, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
|
|
642
|
+
] }),
|
|
643
|
+
/* @__PURE__ */ jsx8(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx8(ScrollView3, { style: [styles7.menu, menuStyle], contentContainerStyle: styles7.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs7(View8, { children: [
|
|
644
|
+
sectionIndex > 0 && /* @__PURE__ */ jsx8(View8, { style: [styles7.divider, dividerStyle] }),
|
|
645
|
+
section.kind === "single" ? /* @__PURE__ */ jsx8(
|
|
646
|
+
SingleSection,
|
|
647
|
+
{
|
|
648
|
+
section,
|
|
649
|
+
accentColor,
|
|
650
|
+
onAccentColor: resolvedOnAccentColor,
|
|
651
|
+
mutedColor,
|
|
652
|
+
labelFontFamily,
|
|
653
|
+
onSelect: (value) => {
|
|
654
|
+
section.onChange(value);
|
|
655
|
+
if (autoDismiss) host.close();
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
) : /* @__PURE__ */ jsx8(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
|
|
659
|
+
] }, section.id)) }) })
|
|
660
|
+
] });
|
|
661
|
+
}
|
|
662
|
+
function SingleSection({
|
|
663
|
+
section,
|
|
664
|
+
accentColor,
|
|
665
|
+
onAccentColor,
|
|
666
|
+
mutedColor,
|
|
667
|
+
labelFontFamily,
|
|
668
|
+
onSelect
|
|
669
|
+
}) {
|
|
670
|
+
return /* @__PURE__ */ jsx8(Fragment3, { children: section.options.map((option) => {
|
|
671
|
+
const selected = option.value === section.value;
|
|
672
|
+
const taken = !selected && option.value === section.takenValue;
|
|
673
|
+
const rowColor = selected ? onAccentColor : mutedColor;
|
|
674
|
+
const itemStyle = [styles7.item, selected && { backgroundColor: accentColor }, taken && styles7.itemTaken];
|
|
675
|
+
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
676
|
+
const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
|
|
677
|
+
return /* @__PURE__ */ jsx8(TouchableRipple2, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs7(View8, { style: styles7.itemRow, children: [
|
|
678
|
+
option.icon && /* @__PURE__ */ jsx8(Icon5, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
679
|
+
/* @__PURE__ */ jsxs7(View8, { style: styles7.itemLabelColumn, children: [
|
|
680
|
+
/* @__PURE__ */ jsx8(Text5, { variant: "labelLarge", style: labelStyle, children: option.label }),
|
|
681
|
+
option.description && /* @__PURE__ */ jsx8(Text5, { variant: "labelSmall", style: descriptionStyle, children: option.description })
|
|
682
|
+
] })
|
|
683
|
+
] }) }, option.value);
|
|
684
|
+
}) });
|
|
685
|
+
}
|
|
686
|
+
function MultiSection({
|
|
687
|
+
section,
|
|
688
|
+
accentColor,
|
|
689
|
+
onAccentColor,
|
|
690
|
+
mutedColor,
|
|
691
|
+
labelFontFamily,
|
|
692
|
+
allClearLabels
|
|
693
|
+
}) {
|
|
694
|
+
const allSelected = section.value.length === section.options.length;
|
|
695
|
+
return /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
696
|
+
section.options.map((option, i) => {
|
|
697
|
+
const selected = section.value.includes(option.value);
|
|
698
|
+
const rowColor = selected ? onAccentColor : mutedColor;
|
|
699
|
+
const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
|
|
700
|
+
const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
|
|
701
|
+
const itemStyle = [styles7.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
|
|
702
|
+
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
703
|
+
return /* @__PURE__ */ jsx8(TouchableRipple2, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs7(View8, { style: styles7.itemRow, children: [
|
|
704
|
+
option.icon && /* @__PURE__ */ jsx8(Icon5, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
705
|
+
/* @__PURE__ */ jsx8(Text5, { variant: "labelLarge", style: [styles7.itemLabelFlex, labelStyle], children: option.label })
|
|
706
|
+
] }) }, option.value);
|
|
707
|
+
}),
|
|
708
|
+
section.allClear && /* @__PURE__ */ jsx8(TouchableRipple2, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles7.item, children: /* @__PURE__ */ jsx8(Text5, { variant: "labelLarge", style: [styles7.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
|
|
709
|
+
] });
|
|
710
|
+
}
|
|
711
|
+
var styles7 = StyleSheet7.create({
|
|
712
|
+
allClearLabel: {
|
|
713
|
+
fontWeight: "bold",
|
|
714
|
+
textAlign: "center"
|
|
715
|
+
},
|
|
716
|
+
anchor: {
|
|
717
|
+
position: "relative"
|
|
718
|
+
},
|
|
719
|
+
// React Native Web gives every position:'relative' view an explicit zIndex (0, not 'auto'),
|
|
720
|
+
// which makes each one its own stacking context — so a zIndex set only on the popover content
|
|
721
|
+
// below only wins comparisons within this anchor's own box, not against this anchor's own later
|
|
722
|
+
// siblings (e.g. a Ready button), which are otherwise painted on top by DOM-order tiebreak.
|
|
723
|
+
// Elevating the anchor itself, only while its popover is open, fixes that at the right level.
|
|
724
|
+
anchorOpen: {
|
|
725
|
+
zIndex: 100
|
|
726
|
+
},
|
|
727
|
+
divider: {
|
|
728
|
+
height: StyleSheet7.hairlineWidth,
|
|
729
|
+
marginVertical: 4
|
|
730
|
+
},
|
|
731
|
+
item: {
|
|
732
|
+
borderRadius: 8,
|
|
733
|
+
paddingHorizontal: 12,
|
|
734
|
+
paddingVertical: 8
|
|
735
|
+
},
|
|
736
|
+
itemLabelColumn: {
|
|
737
|
+
maxWidth: MENU_ITEM_LABEL_MAX_WIDTH
|
|
738
|
+
},
|
|
739
|
+
itemLabelFlex: {
|
|
740
|
+
flex: 1
|
|
741
|
+
},
|
|
742
|
+
itemRow: {
|
|
743
|
+
alignItems: "center",
|
|
744
|
+
flexDirection: "row",
|
|
745
|
+
gap: 8
|
|
746
|
+
},
|
|
747
|
+
// Same opacity as ProfilePicker's rowDisabled / InlineColorPicker's swatchTaken — the fleet's
|
|
748
|
+
// established "shown, not removed" treatment for another seat's own current pick.
|
|
749
|
+
itemTaken: {
|
|
750
|
+
opacity: 0.35
|
|
751
|
+
},
|
|
752
|
+
menu: {
|
|
753
|
+
borderRadius: 12,
|
|
754
|
+
borderWidth: MENU_BORDER_WIDTH,
|
|
755
|
+
elevation: 8,
|
|
756
|
+
maxWidth: MENU_MAX_WIDTH,
|
|
757
|
+
minWidth: MENU_MIN_WIDTH,
|
|
758
|
+
shadowColor: "#000000",
|
|
759
|
+
shadowOffset: { height: 2, width: 0 },
|
|
760
|
+
shadowOpacity: 0.3,
|
|
761
|
+
shadowRadius: 8
|
|
762
|
+
},
|
|
763
|
+
// Separate from `menu` itself — a ScrollView's own style sets the scrolling frame's bounds
|
|
764
|
+
// (including the maxHeight that actually caps it), while padding/gap belong to its
|
|
765
|
+
// contentContainerStyle, which sizes to the *unclamped* content instead of the frame.
|
|
766
|
+
menuContent: {
|
|
767
|
+
gap: 4,
|
|
768
|
+
padding: 6
|
|
769
|
+
},
|
|
770
|
+
// Fixed hit-area regardless of the current option's iconSize, so a small-vs-large trigger icon
|
|
771
|
+
// doesn't shift this picker's position within its row.
|
|
772
|
+
triggerBox: {
|
|
773
|
+
alignItems: "center",
|
|
774
|
+
height: TRIGGER_SIZE,
|
|
775
|
+
justifyContent: "center",
|
|
776
|
+
width: TRIGGER_SIZE
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
// src/ControlSchemePicker.tsx
|
|
781
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
782
|
+
function ControlSchemePicker({ id, host, value, onChange, options, takenValue, accentColor, mutedColor, onAccentColor, dark, align, labelFontFamily }) {
|
|
783
|
+
const isTouchPrimary = useIsTouchPrimaryDevice2();
|
|
784
|
+
if (Platform3.OS !== "web" || isTouchPrimary) return null;
|
|
785
|
+
return /* @__PURE__ */ jsx9(SectionedDropdown, { id, host, icon: "keyboard-outline", accessibilityLabel: "Control scheme", sections: [{ kind: "single", id: "controls", options, value, onChange, takenValue }], accentColor, mutedColor, onAccentColor, dark, align, labelFontFamily });
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// src/CornerActionButtons.tsx
|
|
789
|
+
import { IconButton as IconButton3 } from "@rific/feedback-press";
|
|
790
|
+
import { StyleSheet as StyleSheet8 } from "react-native";
|
|
791
|
+
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
792
|
+
function CornerActionButtons({ onBack, onSettings, fg, insets, backIcon = "arrow-left", backLabel = "Back" }) {
|
|
793
|
+
return /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
794
|
+
/* @__PURE__ */ jsx10(IconButton3, { icon: backIcon, iconColor: fg, size: 24, style: [styles8.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: backLabel }),
|
|
795
|
+
/* @__PURE__ */ jsx10(IconButton3, { icon: "cog", iconColor: fg, size: 24, style: [styles8.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
|
|
796
|
+
] });
|
|
797
|
+
}
|
|
798
|
+
var styles8 = StyleSheet8.create({
|
|
799
|
+
back: {
|
|
800
|
+
position: "absolute"
|
|
801
|
+
},
|
|
802
|
+
topRight: {
|
|
803
|
+
position: "absolute"
|
|
804
|
+
}
|
|
805
|
+
});
|
|
806
|
+
|
|
807
|
+
// src/CornerStatusBadges.tsx
|
|
808
|
+
import { StyleSheet as StyleSheet9, View as View9 } from "react-native";
|
|
809
|
+
import { Icon as Icon6 } from "react-native-paper";
|
|
810
|
+
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
811
|
+
var BADGE_SIZE = 30;
|
|
812
|
+
function StatusBadge({ icon }) {
|
|
813
|
+
return /* @__PURE__ */ jsx11(View9, { style: styles9.badge, children: icon && /* @__PURE__ */ jsx11(Icon6, { source: icon, size: 16, color: "rgba(255,255,255,0.85)" }) });
|
|
814
|
+
}
|
|
815
|
+
function CornerStatusBadges({ orientationMode, p1OnRight, p1, p2 }) {
|
|
816
|
+
const p1OnRightSide = orientationMode === "sideBySide" && p1OnRight;
|
|
817
|
+
const p2OnLeftSide = orientationMode === "sideBySide" && !p1OnRight;
|
|
818
|
+
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
819
|
+
p1 && /* @__PURE__ */ jsx11(View9, { pointerEvents: "none", style: p1OnRightSide ? styles9.bottomRight : styles9.bottomLeft, children: /* @__PURE__ */ jsx11(StatusBadge, { icon: p1.icon }) }),
|
|
820
|
+
p2 && /* @__PURE__ */ jsx11(View9, { pointerEvents: "none", style: p2OnLeftSide ? styles9.topLeft : styles9.topRight, children: /* @__PURE__ */ jsx11(StatusBadge, { icon: p2.icon }) })
|
|
821
|
+
] });
|
|
822
|
+
}
|
|
823
|
+
var styles9 = StyleSheet9.create({
|
|
824
|
+
badge: {
|
|
825
|
+
alignItems: "center",
|
|
826
|
+
backgroundColor: "rgba(0,0,0,0.28)",
|
|
827
|
+
borderColor: "rgba(255,255,255,0.18)",
|
|
828
|
+
borderRadius: BADGE_SIZE / 2,
|
|
829
|
+
borderWidth: 1,
|
|
830
|
+
height: BADGE_SIZE,
|
|
831
|
+
justifyContent: "center",
|
|
832
|
+
opacity: 0.7,
|
|
833
|
+
width: BADGE_SIZE
|
|
834
|
+
},
|
|
835
|
+
bottomLeft: { bottom: 12, left: 12, position: "absolute" },
|
|
836
|
+
bottomRight: { bottom: 12, position: "absolute", right: 12 },
|
|
837
|
+
topLeft: { left: 12, position: "absolute", top: 12 },
|
|
838
|
+
topRight: { position: "absolute", right: 12, top: 12 }
|
|
839
|
+
});
|
|
840
|
+
|
|
530
841
|
// src/InlineColorPicker.tsx
|
|
531
|
-
import {
|
|
842
|
+
import { defaultColors, getContrastColor } from "@rific/auto-paper";
|
|
843
|
+
import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
|
|
844
|
+
import { clamp } from "@tastic/core";
|
|
845
|
+
import { ScrollView as ScrollView4, StyleSheet as StyleSheet10, useWindowDimensions as useWindowDimensions3, View as View10 } from "react-native";
|
|
846
|
+
import { Icon as Icon7, Text as Text6 } from "react-native-paper";
|
|
847
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
532
848
|
var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
|
|
533
849
|
var DEFAULT_SIZE = 48;
|
|
534
850
|
var SWATCH_SIZE = 28;
|
|
@@ -556,15 +872,15 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
|
|
|
556
872
|
const displayValue = displayFor(value);
|
|
557
873
|
const contrastColor = getContrastColor(displayValue);
|
|
558
874
|
const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
|
|
559
|
-
return /* @__PURE__ */
|
|
560
|
-
/* @__PURE__ */
|
|
561
|
-
/* @__PURE__ */
|
|
875
|
+
return /* @__PURE__ */ jsxs10(View10, { style: [styles10.anchor, open && styles10.anchorOpen], children: [
|
|
876
|
+
/* @__PURE__ */ jsx12(TouchableRipple3, { onPress: () => host.toggle(id), borderless: true, style: [styles10.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx12(View10, { ref: triggerRef, collapsable: false, style: styles10.triggerMeasure, children: tag ? /* @__PURE__ */ jsx12(Text6, { style: [styles10.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx12(Icon7, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
|
|
877
|
+
/* @__PURE__ */ jsx12(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ jsx12(ScrollView4, { style: [styles10.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles10.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
|
|
562
878
|
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
563
879
|
const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
|
|
564
880
|
const swappable = taken && allowSwapTaken;
|
|
565
881
|
const swatchDisplay = displayFor(swatch.value);
|
|
566
|
-
return /* @__PURE__ */
|
|
567
|
-
|
|
882
|
+
return /* @__PURE__ */ jsx12(
|
|
883
|
+
TouchableRipple3,
|
|
568
884
|
{
|
|
569
885
|
disabled: taken && !swappable,
|
|
570
886
|
onPress: () => {
|
|
@@ -572,15 +888,15 @@ function InlineColorPicker({ id, host, value, onChange, previewValue, swatches =
|
|
|
572
888
|
if (autoDismiss) host.close();
|
|
573
889
|
},
|
|
574
890
|
borderless: true,
|
|
575
|
-
style: [
|
|
576
|
-
children: selected ? /* @__PURE__ */
|
|
891
|
+
style: [styles10.swatch, { backgroundColor: swatchDisplay }, selected && styles10.swatchSelected, taken && !swappable && styles10.swatchTaken],
|
|
892
|
+
children: selected ? /* @__PURE__ */ jsx12(Icon7, { source: "check", size: 16, color: getContrastColor(swatchDisplay) }) : swappable ? /* @__PURE__ */ jsx12(Icon7, { source: "swap-horizontal", size: 16, color: getContrastColor(swatchDisplay) }) : taken ? /* @__PURE__ */ jsx12(Icon7, { source: "close", size: 16, color: getContrastColor(swatchDisplay) }) : /* @__PURE__ */ jsx12(View10, {})
|
|
577
893
|
},
|
|
578
894
|
swatch.value
|
|
579
895
|
);
|
|
580
896
|
}) }) })
|
|
581
897
|
] });
|
|
582
898
|
}
|
|
583
|
-
var
|
|
899
|
+
var styles10 = StyleSheet10.create({
|
|
584
900
|
anchor: {
|
|
585
901
|
position: "relative"
|
|
586
902
|
},
|
|
@@ -653,10 +969,10 @@ var styles7 = StyleSheet7.create({
|
|
|
653
969
|
|
|
654
970
|
// src/LabeledDropdown.tsx
|
|
655
971
|
import { getContrastColor as getContrastColor2 } from "@rific/auto-paper";
|
|
656
|
-
import { TouchableRipple as
|
|
657
|
-
import { ScrollView as
|
|
658
|
-
import { Icon as
|
|
659
|
-
import { jsx as
|
|
972
|
+
import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
|
|
973
|
+
import { ScrollView as ScrollView5, StyleSheet as StyleSheet11, View as View11 } from "react-native";
|
|
974
|
+
import { Icon as Icon8, Text as Text7 } from "react-native-paper";
|
|
975
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
660
976
|
var TRIGGER_HEIGHT = 28;
|
|
661
977
|
var POPOVER_WIDTH = 180;
|
|
662
978
|
var ROW_HEIGHT = 36;
|
|
@@ -679,22 +995,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
|
|
|
679
995
|
onChange(option.value);
|
|
680
996
|
host.close();
|
|
681
997
|
};
|
|
682
|
-
return /* @__PURE__ */
|
|
683
|
-
/* @__PURE__ */
|
|
684
|
-
/* @__PURE__ */
|
|
685
|
-
/* @__PURE__ */
|
|
998
|
+
return /* @__PURE__ */ jsxs11(View11, { style: [styles11.anchor, open && styles11.anchorOpen], children: [
|
|
999
|
+
/* @__PURE__ */ jsx13(TouchableRipple4, { onPress: () => host.toggle(id), style: styles11.trigger, children: /* @__PURE__ */ jsxs11(View11, { ref: triggerRef, collapsable: false, style: styles11.triggerInner, children: [
|
|
1000
|
+
/* @__PURE__ */ jsx13(Text7, { style: [styles11.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
|
|
1001
|
+
/* @__PURE__ */ jsx13(Icon8, { source: "menu-down", size: 16, color })
|
|
686
1002
|
] }) }),
|
|
687
|
-
/* @__PURE__ */
|
|
1003
|
+
/* @__PURE__ */ jsx13(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx13(ScrollView5, { style: [styles11.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles11.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
|
|
688
1004
|
const isSelected = option.value === value;
|
|
689
1005
|
const onColor = getContrastColor2(color);
|
|
690
|
-
return /* @__PURE__ */
|
|
691
|
-
option.icon && /* @__PURE__ */
|
|
692
|
-
/* @__PURE__ */
|
|
1006
|
+
return /* @__PURE__ */ jsx13(TouchableRipple4, { onPress: () => handleSelect(option), style: [styles11.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs11(View11, { style: styles11.rowInner, children: [
|
|
1007
|
+
option.icon && /* @__PURE__ */ jsx13(Icon8, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
|
|
1008
|
+
/* @__PURE__ */ jsx13(Text7, { style: [styles11.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
|
|
693
1009
|
] }) }, option.value);
|
|
694
1010
|
}) }) })
|
|
695
1011
|
] });
|
|
696
1012
|
}
|
|
697
|
-
var
|
|
1013
|
+
var styles11 = StyleSheet11.create({
|
|
698
1014
|
anchor: {
|
|
699
1015
|
position: "relative"
|
|
700
1016
|
},
|
|
@@ -746,31 +1062,26 @@ var styles8 = StyleSheet8.create({
|
|
|
746
1062
|
}
|
|
747
1063
|
});
|
|
748
1064
|
|
|
749
|
-
// src/loadSkiaWeb.ts
|
|
750
|
-
function loadSkiaWeb() {
|
|
751
|
-
return Promise.resolve();
|
|
752
|
-
}
|
|
753
|
-
|
|
754
1065
|
// src/PressAwayOverlay.tsx
|
|
755
|
-
import { Pressable, StyleSheet as
|
|
756
|
-
import { jsx as
|
|
1066
|
+
import { Pressable, StyleSheet as StyleSheet12 } from "react-native";
|
|
1067
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
757
1068
|
function PressAwayOverlay({ active, onPress, style }) {
|
|
758
1069
|
if (!active) return null;
|
|
759
|
-
return /* @__PURE__ */
|
|
1070
|
+
return /* @__PURE__ */ jsx14(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet12.absoluteFill, style] });
|
|
760
1071
|
}
|
|
761
1072
|
|
|
762
1073
|
// src/ReadyButton.tsx
|
|
763
|
-
import { TouchableRipple as
|
|
764
|
-
import { StyleSheet as
|
|
765
|
-
import { Text as
|
|
766
|
-
import { jsx as
|
|
1074
|
+
import { TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
|
|
1075
|
+
import { StyleSheet as StyleSheet13 } from "react-native";
|
|
1076
|
+
import { Text as Text8 } from "react-native-paper";
|
|
1077
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
767
1078
|
function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
|
|
768
|
-
const readyButtonStyle = [
|
|
1079
|
+
const readyButtonStyle = [styles12.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
|
|
769
1080
|
const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
|
|
770
1081
|
const labelColorStyle = { color: ready ? "#000000" : color };
|
|
771
|
-
return /* @__PURE__ */
|
|
1082
|
+
return /* @__PURE__ */ jsx15(TouchableRipple5, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx15(Text8, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
|
|
772
1083
|
}
|
|
773
|
-
var
|
|
1084
|
+
var styles12 = StyleSheet13.create({
|
|
774
1085
|
readyButton: {
|
|
775
1086
|
alignItems: "center",
|
|
776
1087
|
borderRadius: 12,
|
|
@@ -782,228 +1093,22 @@ var styles9 = StyleSheet10.create({
|
|
|
782
1093
|
}
|
|
783
1094
|
});
|
|
784
1095
|
|
|
785
|
-
// src/SectionedDropdown.tsx
|
|
786
|
-
import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
|
|
787
|
-
import { IconButton as IconButton3, TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
|
|
788
|
-
import { ScrollView as ScrollView5, StyleSheet as StyleSheet11, View as View9 } from "react-native";
|
|
789
|
-
import { Icon as Icon6, Text as Text7 } from "react-native-paper";
|
|
790
|
-
|
|
791
|
-
// src/TriggerGaugeHost.tsx
|
|
792
|
-
import { lazy, Suspense } from "react";
|
|
793
|
-
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
794
|
-
var LazyTriggerGauge = lazy(() => loadSkiaWeb().then(() => import("./TriggerGauge-2OJOOF6I.mjs").then((m) => ({ default: m.TriggerGauge }))));
|
|
795
|
-
function TriggerGaugeHost(props) {
|
|
796
|
-
return /* @__PURE__ */ jsx11(Suspense, { fallback: null, children: /* @__PURE__ */ jsx11(LazyTriggerGauge, { ...props }) });
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
// src/SectionedDropdown.tsx
|
|
800
|
-
import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
801
|
-
var MENU_BORDER_WIDTH = 1;
|
|
802
|
-
var TRIGGER_SIZE = 44;
|
|
803
|
-
var MENU_MIN_WIDTH = 200;
|
|
804
|
-
var MENU_MAX_WIDTH = 220;
|
|
805
|
-
var MENU_ITEM_ICON_SIZE = 18;
|
|
806
|
-
var MENU_ITEM_LABEL_MAX_WIDTH = 150;
|
|
807
|
-
var MENU_ITEM_HEIGHT = 40;
|
|
808
|
-
var MENU_ITEM_HEIGHT_WITH_DESCRIPTION = 58;
|
|
809
|
-
var MENU_DIVIDER_HEIGHT = 9;
|
|
810
|
-
var MENU_VERTICAL_PADDING = 12;
|
|
811
|
-
function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accentColor, mutedColor, onAccentColor, dark, align: alignOverride, autoDismiss = true, labelFontFamily = MONO_FONT, allClearLabels = { all: "All", clear: "Clear" } }) {
|
|
812
|
-
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
813
|
-
const menuBorderColor = getBlendedColor(mutedColor, menuBg, 0.5);
|
|
814
|
-
const resolvedOnAccentColor = onAccentColor ?? getColorRoles(accentColor, menuBg).onColor;
|
|
815
|
-
const fg = dark ? "#FFFFFF" : "#000000";
|
|
816
|
-
const open = host.openId === id;
|
|
817
|
-
const estimatedHeight = MENU_VERTICAL_PADDING + sections.reduce((sum, section, sectionIndex) => {
|
|
818
|
-
const rows = section.options.reduce((rowSum, option) => rowSum + (option.description ? MENU_ITEM_HEIGHT_WITH_DESCRIPTION : MENU_ITEM_HEIGHT), 0);
|
|
819
|
-
const footer = section.kind === "multi" && section.allClear ? MENU_ITEM_HEIGHT : 0;
|
|
820
|
-
const divider = sectionIndex > 0 ? MENU_DIVIDER_HEIGHT : 0;
|
|
821
|
-
return sum + rows + footer + divider;
|
|
822
|
-
}, 0);
|
|
823
|
-
const { align: autoAlign, maxHeight, measured, triggerRef, verticalAlign } = useAutoAlign(open, MENU_MAX_WIDTH, estimatedHeight);
|
|
824
|
-
const align = alignOverride ?? autoAlign;
|
|
825
|
-
const onlySection = sections.length === 1 ? sections[0] : null;
|
|
826
|
-
const selectedOption = onlySection?.kind === "single" ? onlySection.options.find((o) => o.value === onlySection.value) : void 0;
|
|
827
|
-
const triggerIcon = selectedOption?.icon ?? icon;
|
|
828
|
-
const triggerIconSize = selectedOption?.iconSize ?? 22;
|
|
829
|
-
const hasMultiSection = sections.some((s) => s.kind === "multi");
|
|
830
|
-
const anyMultiSelected = sections.some((s) => s.kind === "multi" && s.value.length > 0);
|
|
831
|
-
const triggerIconColor = hasMultiSection ? anyMultiSelected ? accentColor : fg : fg;
|
|
832
|
-
const gaugeSegments = sections.reduce((sum, section) => sum + section.options.length, 0);
|
|
833
|
-
const gaugeLitIndices = [];
|
|
834
|
-
let gaugeOffset = 0;
|
|
835
|
-
for (const section of sections) {
|
|
836
|
-
if (section.kind === "single") {
|
|
837
|
-
const index = section.options.findIndex((o) => o.value === section.value);
|
|
838
|
-
if (index >= 0) gaugeLitIndices.push(gaugeOffset + index);
|
|
839
|
-
} else {
|
|
840
|
-
section.options.forEach((o, i) => {
|
|
841
|
-
if (section.value.includes(o.value)) gaugeLitIndices.push(gaugeOffset + i);
|
|
842
|
-
});
|
|
843
|
-
}
|
|
844
|
-
gaugeOffset += section.options.length;
|
|
845
|
-
}
|
|
846
|
-
const anchorStyle = [styles10.anchor, open && styles10.anchorOpen];
|
|
847
|
-
const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
|
|
848
|
-
const dividerStyle = { backgroundColor: menuBorderColor };
|
|
849
|
-
return /* @__PURE__ */ jsxs9(View9, { style: anchorStyle, children: [
|
|
850
|
-
/* @__PURE__ */ jsxs9(View9, { ref: triggerRef, collapsable: false, style: styles10.triggerBox, children: [
|
|
851
|
-
/* @__PURE__ */ jsx12(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
|
|
852
|
-
/* @__PURE__ */ jsx12(IconButton3, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
|
|
853
|
-
] }),
|
|
854
|
-
/* @__PURE__ */ jsx12(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx12(ScrollView5, { style: [styles10.menu, menuStyle], contentContainerStyle: styles10.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs9(View9, { children: [
|
|
855
|
-
sectionIndex > 0 && /* @__PURE__ */ jsx12(View9, { style: [styles10.divider, dividerStyle] }),
|
|
856
|
-
section.kind === "single" ? /* @__PURE__ */ jsx12(
|
|
857
|
-
SingleSection,
|
|
858
|
-
{
|
|
859
|
-
section,
|
|
860
|
-
accentColor,
|
|
861
|
-
onAccentColor: resolvedOnAccentColor,
|
|
862
|
-
mutedColor,
|
|
863
|
-
labelFontFamily,
|
|
864
|
-
onSelect: (value) => {
|
|
865
|
-
section.onChange(value);
|
|
866
|
-
if (autoDismiss) host.close();
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
) : /* @__PURE__ */ jsx12(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
|
|
870
|
-
] }, section.id)) }) })
|
|
871
|
-
] });
|
|
872
|
-
}
|
|
873
|
-
function SingleSection({
|
|
874
|
-
section,
|
|
875
|
-
accentColor,
|
|
876
|
-
onAccentColor,
|
|
877
|
-
mutedColor,
|
|
878
|
-
labelFontFamily,
|
|
879
|
-
onSelect
|
|
880
|
-
}) {
|
|
881
|
-
return /* @__PURE__ */ jsx12(Fragment4, { children: section.options.map((option) => {
|
|
882
|
-
const selected = option.value === section.value;
|
|
883
|
-
const taken = !selected && option.value === section.takenValue;
|
|
884
|
-
const rowColor = selected ? onAccentColor : mutedColor;
|
|
885
|
-
const itemStyle = [styles10.item, selected && { backgroundColor: accentColor }, taken && styles10.itemTaken];
|
|
886
|
-
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
887
|
-
const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
|
|
888
|
-
return /* @__PURE__ */ jsx12(TouchableRipple5, { disabled: taken, onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs9(View9, { style: styles10.itemRow, children: [
|
|
889
|
-
option.icon && /* @__PURE__ */ jsx12(Icon6, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
890
|
-
/* @__PURE__ */ jsxs9(View9, { style: styles10.itemLabelColumn, children: [
|
|
891
|
-
/* @__PURE__ */ jsx12(Text7, { variant: "labelLarge", style: labelStyle, children: option.label }),
|
|
892
|
-
option.description && /* @__PURE__ */ jsx12(Text7, { variant: "labelSmall", style: descriptionStyle, children: option.description })
|
|
893
|
-
] })
|
|
894
|
-
] }) }, option.value);
|
|
895
|
-
}) });
|
|
896
|
-
}
|
|
897
|
-
function MultiSection({
|
|
898
|
-
section,
|
|
899
|
-
accentColor,
|
|
900
|
-
onAccentColor,
|
|
901
|
-
mutedColor,
|
|
902
|
-
labelFontFamily,
|
|
903
|
-
allClearLabels
|
|
904
|
-
}) {
|
|
905
|
-
const allSelected = section.value.length === section.options.length;
|
|
906
|
-
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
907
|
-
section.options.map((option, i) => {
|
|
908
|
-
const selected = section.value.includes(option.value);
|
|
909
|
-
const rowColor = selected ? onAccentColor : mutedColor;
|
|
910
|
-
const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
|
|
911
|
-
const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
|
|
912
|
-
const itemStyle = [styles10.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
|
|
913
|
-
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
914
|
-
return /* @__PURE__ */ jsx12(TouchableRipple5, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs9(View9, { style: styles10.itemRow, children: [
|
|
915
|
-
option.icon && /* @__PURE__ */ jsx12(Icon6, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
|
|
916
|
-
/* @__PURE__ */ jsx12(Text7, { variant: "labelLarge", style: [styles10.itemLabelFlex, labelStyle], children: option.label })
|
|
917
|
-
] }) }, option.value);
|
|
918
|
-
}),
|
|
919
|
-
section.allClear && /* @__PURE__ */ jsx12(TouchableRipple5, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles10.item, children: /* @__PURE__ */ jsx12(Text7, { variant: "labelLarge", style: [styles10.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
|
|
920
|
-
] });
|
|
921
|
-
}
|
|
922
|
-
var styles10 = StyleSheet11.create({
|
|
923
|
-
allClearLabel: {
|
|
924
|
-
fontWeight: "bold",
|
|
925
|
-
textAlign: "center"
|
|
926
|
-
},
|
|
927
|
-
anchor: {
|
|
928
|
-
position: "relative"
|
|
929
|
-
},
|
|
930
|
-
// React Native Web gives every position:'relative' view an explicit zIndex (0, not 'auto'),
|
|
931
|
-
// which makes each one its own stacking context — so a zIndex set only on the popover content
|
|
932
|
-
// below only wins comparisons within this anchor's own box, not against this anchor's own later
|
|
933
|
-
// siblings (e.g. a Ready button), which are otherwise painted on top by DOM-order tiebreak.
|
|
934
|
-
// Elevating the anchor itself, only while its popover is open, fixes that at the right level.
|
|
935
|
-
anchorOpen: {
|
|
936
|
-
zIndex: 100
|
|
937
|
-
},
|
|
938
|
-
divider: {
|
|
939
|
-
height: StyleSheet11.hairlineWidth,
|
|
940
|
-
marginVertical: 4
|
|
941
|
-
},
|
|
942
|
-
item: {
|
|
943
|
-
borderRadius: 8,
|
|
944
|
-
paddingHorizontal: 12,
|
|
945
|
-
paddingVertical: 8
|
|
946
|
-
},
|
|
947
|
-
itemLabelColumn: {
|
|
948
|
-
maxWidth: MENU_ITEM_LABEL_MAX_WIDTH
|
|
949
|
-
},
|
|
950
|
-
itemLabelFlex: {
|
|
951
|
-
flex: 1
|
|
952
|
-
},
|
|
953
|
-
itemRow: {
|
|
954
|
-
alignItems: "center",
|
|
955
|
-
flexDirection: "row",
|
|
956
|
-
gap: 8
|
|
957
|
-
},
|
|
958
|
-
// Same opacity as ProfilePicker's rowDisabled / InlineColorPicker's swatchTaken — the fleet's
|
|
959
|
-
// established "shown, not removed" treatment for another seat's own current pick.
|
|
960
|
-
itemTaken: {
|
|
961
|
-
opacity: 0.35
|
|
962
|
-
},
|
|
963
|
-
menu: {
|
|
964
|
-
borderRadius: 12,
|
|
965
|
-
borderWidth: MENU_BORDER_WIDTH,
|
|
966
|
-
elevation: 8,
|
|
967
|
-
maxWidth: MENU_MAX_WIDTH,
|
|
968
|
-
minWidth: MENU_MIN_WIDTH,
|
|
969
|
-
shadowColor: "#000000",
|
|
970
|
-
shadowOffset: { height: 2, width: 0 },
|
|
971
|
-
shadowOpacity: 0.3,
|
|
972
|
-
shadowRadius: 8
|
|
973
|
-
},
|
|
974
|
-
// Separate from `menu` itself — a ScrollView's own style sets the scrolling frame's bounds
|
|
975
|
-
// (including the maxHeight that actually caps it), while padding/gap belong to its
|
|
976
|
-
// contentContainerStyle, which sizes to the *unclamped* content instead of the frame.
|
|
977
|
-
menuContent: {
|
|
978
|
-
gap: 4,
|
|
979
|
-
padding: 6
|
|
980
|
-
},
|
|
981
|
-
// Fixed hit-area regardless of the current option's iconSize, so a small-vs-large trigger icon
|
|
982
|
-
// doesn't shift this picker's position within its row.
|
|
983
|
-
triggerBox: {
|
|
984
|
-
alignItems: "center",
|
|
985
|
-
height: TRIGGER_SIZE,
|
|
986
|
-
justifyContent: "center",
|
|
987
|
-
width: TRIGGER_SIZE
|
|
988
|
-
}
|
|
989
|
-
});
|
|
990
|
-
|
|
991
1096
|
// src/SharedActionBand.tsx
|
|
992
1097
|
import { IconButton as IconButton4 } from "@rific/feedback-press";
|
|
993
|
-
import { StyleSheet as
|
|
994
|
-
import { jsx as
|
|
1098
|
+
import { StyleSheet as StyleSheet14, View as View12 } from "react-native";
|
|
1099
|
+
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
995
1100
|
function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
|
|
996
|
-
return /* @__PURE__ */
|
|
997
|
-
/* @__PURE__ */
|
|
998
|
-
/* @__PURE__ */
|
|
999
|
-
onRandomize && /* @__PURE__ */
|
|
1000
|
-
onReset && /* @__PURE__ */
|
|
1001
|
-
/* @__PURE__ */
|
|
1101
|
+
return /* @__PURE__ */ jsxs12(View12, { style: [styles13.column, popoverOpen && styles13.columnOpen], children: [
|
|
1102
|
+
/* @__PURE__ */ jsxs12(View12, { style: styles13.actionsRow, children: [
|
|
1103
|
+
/* @__PURE__ */ jsx16(IconButton4, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
|
|
1104
|
+
onRandomize && /* @__PURE__ */ jsx16(IconButton4, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
|
|
1105
|
+
onReset && /* @__PURE__ */ jsx16(IconButton4, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
|
|
1106
|
+
/* @__PURE__ */ jsx16(IconButton4, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
|
|
1002
1107
|
] }),
|
|
1003
1108
|
children
|
|
1004
1109
|
] });
|
|
1005
1110
|
}
|
|
1006
|
-
var
|
|
1111
|
+
var styles13 = StyleSheet14.create({
|
|
1007
1112
|
actionsRow: {
|
|
1008
1113
|
alignItems: "center",
|
|
1009
1114
|
flexDirection: "row",
|
|
@@ -1019,20 +1124,20 @@ var styles11 = StyleSheet12.create({
|
|
|
1019
1124
|
});
|
|
1020
1125
|
|
|
1021
1126
|
// src/StatRow.tsx
|
|
1022
|
-
import { useAutoPaperTheme as
|
|
1023
|
-
import { StyleSheet as
|
|
1024
|
-
import { Text as
|
|
1025
|
-
import { jsx as
|
|
1127
|
+
import { useAutoPaperTheme as useAutoPaperTheme5 } from "@rific/auto-paper";
|
|
1128
|
+
import { StyleSheet as StyleSheet15, View as View13 } from "react-native";
|
|
1129
|
+
import { Text as Text9 } from "react-native-paper";
|
|
1130
|
+
import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1026
1131
|
function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
|
|
1027
|
-
const { dark } =
|
|
1132
|
+
const { dark } = useAutoPaperTheme5();
|
|
1028
1133
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
1029
1134
|
const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
|
|
1030
|
-
return /* @__PURE__ */
|
|
1031
|
-
/* @__PURE__ */
|
|
1032
|
-
/* @__PURE__ */
|
|
1135
|
+
return /* @__PURE__ */ jsxs13(View13, { style: styles14.row, children: [
|
|
1136
|
+
/* @__PURE__ */ jsx17(Text9, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
|
|
1137
|
+
/* @__PURE__ */ jsx17(Text9, { variant: "bodyMedium", style: [styles14.value, { color: fg }], children: value })
|
|
1033
1138
|
] });
|
|
1034
1139
|
}
|
|
1035
|
-
var
|
|
1140
|
+
var styles14 = StyleSheet15.create({
|
|
1036
1141
|
row: {
|
|
1037
1142
|
alignItems: "center",
|
|
1038
1143
|
flexDirection: "row",
|
|
@@ -1044,20 +1149,20 @@ var styles12 = StyleSheet13.create({
|
|
|
1044
1149
|
});
|
|
1045
1150
|
|
|
1046
1151
|
// src/StatSection.tsx
|
|
1047
|
-
import { useAutoPaperTheme as
|
|
1048
|
-
import { StyleSheet as
|
|
1049
|
-
import { Text as
|
|
1050
|
-
import { jsx as
|
|
1152
|
+
import { useAutoPaperTheme as useAutoPaperTheme6 } from "@rific/auto-paper";
|
|
1153
|
+
import { StyleSheet as StyleSheet16, View as View14 } from "react-native";
|
|
1154
|
+
import { Text as Text10 } from "react-native-paper";
|
|
1155
|
+
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1051
1156
|
function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
|
|
1052
|
-
const { dark } =
|
|
1157
|
+
const { dark } = useAutoPaperTheme6();
|
|
1053
1158
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
1054
1159
|
const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
|
|
1055
|
-
return /* @__PURE__ */
|
|
1056
|
-
/* @__PURE__ */
|
|
1160
|
+
return /* @__PURE__ */ jsxs14(View14, { style: [styles15.section, { backgroundColor: sectionBg }], children: [
|
|
1161
|
+
/* @__PURE__ */ jsx18(Text10, { variant: "labelMedium", style: [styles15.label, { color: fg }], children: label }),
|
|
1057
1162
|
children
|
|
1058
1163
|
] });
|
|
1059
1164
|
}
|
|
1060
|
-
var
|
|
1165
|
+
var styles15 = StyleSheet16.create({
|
|
1061
1166
|
// Bold and full-contrast (fg), not the original fontless/fgMuted treatment — that read at the
|
|
1062
1167
|
// same visual weight as StatRow's own row labels below it (both used the identical muted color;
|
|
1063
1168
|
// letterSpacing/variant alone didn't separate them enough to read as "this is the group header"
|
|
@@ -1087,8 +1192,11 @@ export {
|
|
|
1087
1192
|
AchievementRow,
|
|
1088
1193
|
BaseSettingsDialog,
|
|
1089
1194
|
BaseStatsScreen,
|
|
1195
|
+
ConfirmDialog,
|
|
1090
1196
|
ContentGutter,
|
|
1197
|
+
ControlSchemePicker,
|
|
1091
1198
|
CornerActionButtons,
|
|
1199
|
+
CornerStatusBadges,
|
|
1092
1200
|
InlineColorPicker,
|
|
1093
1201
|
LABELED_DROPDOWN_POPOVER_WIDTH,
|
|
1094
1202
|
LOCKED_BADGE_COLOR,
|