@tastic/hud 0.5.0 → 0.6.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 +18 -7
- package/dist/index.d.ts +18 -7
- package/dist/index.js +161 -126
- package/dist/index.mjs +146 -112
- package/package.json +4 -4
- package/src/BaseSettingsDialog.tsx +12 -12
- package/src/ContentGutter.tsx +55 -0
- package/src/InlineColorPicker.tsx +21 -11
- package/src/SectionedDropdown.tsx +14 -2
- package/src/index.ts +1 -0
package/dist/index.mjs
CHANGED
|
@@ -232,25 +232,25 @@ var styles2 = StyleSheet2.create({
|
|
|
232
232
|
sectionLabel: {
|
|
233
233
|
letterSpacing: 2
|
|
234
234
|
},
|
|
235
|
-
//
|
|
236
|
-
// HAPTICS below, while the ripple/hover highlight
|
|
237
|
-
//
|
|
238
|
-
//
|
|
235
|
+
// Used to carry marginHorizontal: -12 + paddingHorizontal: 12 (netting to the same inset as
|
|
236
|
+
// APPEARANCE/SOUND & HAPTICS below, while giving the ripple/hover highlight room to breathe
|
|
237
|
+
// into the dialog's own gutter beyond that). Removed: this dialog scrolls (Dialog.ScrollArea +
|
|
238
|
+
// ScrollView above), and on web a ScrollView's own content wrapper clips to its own bounds
|
|
239
|
+
// regardless of a child's negative margin - confirmed live, the icon's own rounded-square badge
|
|
240
|
+
// was getting its left edge sliced off by exactly that overhang. No horizontal inset of its own
|
|
241
|
+
// now - it relies purely on the same dialog padding APPEARANCE/every other row already does,
|
|
242
|
+
// which can never overflow because it's never negative.
|
|
239
243
|
toggleButton: {
|
|
240
244
|
borderRadius: 12,
|
|
241
|
-
marginHorizontal: -12,
|
|
242
245
|
overflow: "hidden",
|
|
243
|
-
paddingHorizontal: 12,
|
|
244
246
|
paddingVertical: 10
|
|
245
247
|
},
|
|
246
|
-
// Same shape as toggleButton
|
|
247
|
-
//
|
|
248
|
-
// toggleRow carries that edge-alignment margin once, for the row as a whole, instead.
|
|
248
|
+
// Same shape as toggleButton, `flex: 1` instead of its own width - two of these side by side in
|
|
249
|
+
// toggleRow share the row's own edge alignment instead of each carrying their own.
|
|
249
250
|
toggleButtonInRow: {
|
|
250
251
|
borderRadius: 12,
|
|
251
252
|
flex: 1,
|
|
252
253
|
overflow: "hidden",
|
|
253
|
-
paddingHorizontal: 12,
|
|
254
254
|
paddingVertical: 10
|
|
255
255
|
},
|
|
256
256
|
toggleContent: {
|
|
@@ -261,10 +261,10 @@ var styles2 = StyleSheet2.create({
|
|
|
261
261
|
toggleGroup: {
|
|
262
262
|
gap: 4
|
|
263
263
|
},
|
|
264
|
+
// No horizontal margin of its own now either - see toggleButton's identical note.
|
|
264
265
|
toggleRow: {
|
|
265
266
|
flexDirection: "row",
|
|
266
|
-
gap: 4
|
|
267
|
-
marginHorizontal: -12
|
|
267
|
+
gap: 4
|
|
268
268
|
}
|
|
269
269
|
});
|
|
270
270
|
|
|
@@ -369,17 +369,41 @@ var styles3 = StyleSheet3.create({
|
|
|
369
369
|
}
|
|
370
370
|
});
|
|
371
371
|
|
|
372
|
+
// src/ContentGutter.tsx
|
|
373
|
+
import { computeContentBounds } from "@tastic/core";
|
|
374
|
+
import { StyleSheet as StyleSheet4, useWindowDimensions, View as View4 } from "react-native";
|
|
375
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
376
|
+
function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
|
|
377
|
+
const { width: windowWidth } = useWindowDimensions();
|
|
378
|
+
const { contentWidth, gutterWidth } = computeContentBounds(windowWidth, maxContentWidth ?? Infinity);
|
|
379
|
+
return /* @__PURE__ */ jsxs4(View4, { style: [styles4.row, style], children: [
|
|
380
|
+
/* @__PURE__ */ jsx4(View4, { style: [styles4.gutter, { width: gutterWidth }], children: leftGutter }),
|
|
381
|
+
/* @__PURE__ */ jsx4(View4, { style: { width: contentWidth }, children }),
|
|
382
|
+
/* @__PURE__ */ jsx4(View4, { style: [styles4.gutter, { width: gutterWidth }], children: rightGutter })
|
|
383
|
+
] });
|
|
384
|
+
}
|
|
385
|
+
var styles4 = StyleSheet4.create({
|
|
386
|
+
// overflow:'hidden' keeps an oversized leftGutter/rightGutter from bleeding into the content
|
|
387
|
+
// column instead of clipping cleanly at its own real width.
|
|
388
|
+
gutter: {
|
|
389
|
+
overflow: "hidden"
|
|
390
|
+
},
|
|
391
|
+
row: {
|
|
392
|
+
flexDirection: "row"
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
|
|
372
396
|
// src/CornerActionButtons.tsx
|
|
373
397
|
import { IconButton as IconButton2 } from "@rific/feedback-press";
|
|
374
|
-
import { StyleSheet as
|
|
375
|
-
import { Fragment as Fragment2, jsx as
|
|
398
|
+
import { StyleSheet as StyleSheet5 } from "react-native";
|
|
399
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
376
400
|
function CornerActionButtons({ onBack, onSettings, fg, insets }) {
|
|
377
|
-
return /* @__PURE__ */
|
|
378
|
-
/* @__PURE__ */
|
|
379
|
-
/* @__PURE__ */
|
|
401
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
402
|
+
/* @__PURE__ */ jsx5(IconButton2, { icon: "arrow-left", iconColor: fg, size: 24, style: [styles5.back, { top: 8 + insets.top, left: 8 + insets.left }], onPress: onBack, accessibilityLabel: "Back" }),
|
|
403
|
+
/* @__PURE__ */ jsx5(IconButton2, { icon: "cog", iconColor: fg, size: 24, style: [styles5.topRight, { top: 8 + insets.top, right: 8 + insets.right }], onPress: onSettings, accessibilityLabel: "Settings" })
|
|
380
404
|
] });
|
|
381
405
|
}
|
|
382
|
-
var
|
|
406
|
+
var styles5 = StyleSheet5.create({
|
|
383
407
|
back: {
|
|
384
408
|
position: "absolute"
|
|
385
409
|
},
|
|
@@ -396,34 +420,34 @@ var MONO_FONT = Platform2.select({ ios: "Menlo", android: "monospace", default:
|
|
|
396
420
|
import { defaultColors, getContrastColor } from "@rific/auto-paper";
|
|
397
421
|
import { TouchableRipple as TouchableRipple2 } from "@rific/feedback-press";
|
|
398
422
|
import { clamp } from "@tastic/core";
|
|
399
|
-
import { ScrollView as ScrollView3, StyleSheet as
|
|
423
|
+
import { ScrollView as ScrollView3, StyleSheet as StyleSheet7, useWindowDimensions as useWindowDimensions3, View as View7 } from "react-native";
|
|
400
424
|
import { Icon as Icon4, Text as Text4 } from "react-native-paper";
|
|
401
425
|
|
|
402
426
|
// src/PopoverBody.tsx
|
|
403
|
-
import { StyleSheet as
|
|
404
|
-
import { Fragment as Fragment3, jsx as
|
|
427
|
+
import { StyleSheet as StyleSheet6, View as View5 } from "react-native";
|
|
428
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
405
429
|
var CARET_SIZE = 7;
|
|
406
430
|
var CARET_RING_OFFSET = 2;
|
|
407
431
|
var CARET_DIP = 1;
|
|
408
432
|
function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
|
|
409
433
|
if (!visible) return null;
|
|
410
434
|
const above = verticalAlign === "above";
|
|
411
|
-
const alignStyle = align === "left" ?
|
|
412
|
-
const verticalStyle = above ?
|
|
435
|
+
const alignStyle = align === "left" ? styles6.contentLeft : align === "right" ? styles6.contentRight : styles6.contentCenter;
|
|
436
|
+
const verticalStyle = above ? styles6.contentAbove : styles6.contentBelow;
|
|
413
437
|
const ringSize = CARET_SIZE + caretBorderWidth;
|
|
414
438
|
const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
|
|
415
439
|
const caretFill = above ? "borderTopColor" : "borderBottomColor";
|
|
416
440
|
const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
|
|
417
441
|
const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
|
|
418
|
-
return /* @__PURE__ */
|
|
442
|
+
return /* @__PURE__ */ jsxs6(View5, { style: [styles6.content, alignStyle, verticalStyle], children: [
|
|
419
443
|
children,
|
|
420
|
-
caretColor && /* @__PURE__ */
|
|
421
|
-
/* @__PURE__ */
|
|
422
|
-
/* @__PURE__ */
|
|
444
|
+
caretColor && /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
445
|
+
/* @__PURE__ */ jsx6(View5, { style: [styles6.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
|
|
446
|
+
/* @__PURE__ */ jsx6(View5, { style: [styles6.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
|
|
423
447
|
] })
|
|
424
448
|
] });
|
|
425
449
|
}
|
|
426
|
-
var
|
|
450
|
+
var styles6 = StyleSheet6.create({
|
|
427
451
|
caret: {
|
|
428
452
|
borderLeftColor: "transparent",
|
|
429
453
|
borderRightColor: "transparent",
|
|
@@ -467,11 +491,11 @@ var styles5 = StyleSheet5.create({
|
|
|
467
491
|
|
|
468
492
|
// src/useAutoAlign.ts
|
|
469
493
|
import { useCallback, useEffect, useRef, useState as useState3 } from "react";
|
|
470
|
-
import { useWindowDimensions } from "react-native";
|
|
494
|
+
import { useWindowDimensions as useWindowDimensions2 } from "react-native";
|
|
471
495
|
var EDGE_MARGIN = 12;
|
|
472
496
|
function useAutoAlign(open, contentWidth, contentHeight) {
|
|
473
497
|
const triggerRef = useRef(null);
|
|
474
|
-
const { width: windowWidth, height: windowHeight } =
|
|
498
|
+
const { width: windowWidth, height: windowHeight } = useWindowDimensions2();
|
|
475
499
|
const [align, setAlign] = useState3("center");
|
|
476
500
|
const [verticalAlign, setVerticalAlign] = useState3("below");
|
|
477
501
|
const [maxHeight, setMaxHeight] = useState3(contentHeight);
|
|
@@ -504,7 +528,7 @@ function useAutoAlign(open, contentWidth, contentHeight) {
|
|
|
504
528
|
}
|
|
505
529
|
|
|
506
530
|
// src/InlineColorPicker.tsx
|
|
507
|
-
import { jsx as
|
|
531
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
508
532
|
var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
|
|
509
533
|
var DEFAULT_SIZE = 48;
|
|
510
534
|
var SWATCH_SIZE = 28;
|
|
@@ -517,9 +541,9 @@ var SCREEN_MARGIN = 40;
|
|
|
517
541
|
function widthForColumns(columns) {
|
|
518
542
|
return SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * columns + SWATCHES_GAP * (columns - 1);
|
|
519
543
|
}
|
|
520
|
-
function InlineColorPicker({ id, host, value, onChange, swatches = defaultColors, takenValue, allowSwapTaken, dark, align: alignOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
|
|
544
|
+
function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = defaultColors, takenValue, allowSwapTaken, dark, align: alignOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
|
|
521
545
|
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
522
|
-
const { width: windowWidth } =
|
|
546
|
+
const { width: windowWidth } = useWindowDimensions3();
|
|
523
547
|
const autoColumns = clamp(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS);
|
|
524
548
|
const resolvedColumns = columns ?? autoColumns;
|
|
525
549
|
const swatchesWidth = widthForColumns(resolvedColumns);
|
|
@@ -528,15 +552,18 @@ function InlineColorPicker({ id, host, value, onChange, swatches = defaultColors
|
|
|
528
552
|
const open = host.openId === id;
|
|
529
553
|
const { align: autoAlign, maxHeight, measured, triggerRef, verticalAlign } = useAutoAlign(open, swatchesWidth, swatchesHeight);
|
|
530
554
|
const align = alignOverride ?? autoAlign;
|
|
531
|
-
const
|
|
555
|
+
const displayFor = previewValue ?? ((hex) => hex);
|
|
556
|
+
const displayValue = displayFor(value);
|
|
557
|
+
const contrastColor = getContrastColor(displayValue);
|
|
532
558
|
const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
|
|
533
|
-
return /* @__PURE__ */
|
|
534
|
-
/* @__PURE__ */
|
|
535
|
-
/* @__PURE__ */
|
|
559
|
+
return /* @__PURE__ */ jsxs7(View7, { style: [styles7.anchor, open && styles7.anchorOpen], children: [
|
|
560
|
+
/* @__PURE__ */ jsx7(TouchableRipple2, { onPress: () => host.toggle(id), borderless: true, style: [styles7.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ jsx7(View7, { ref: triggerRef, collapsable: false, style: styles7.triggerMeasure, children: tag ? /* @__PURE__ */ jsx7(Text4, { style: [styles7.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ jsx7(Icon4, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
|
|
561
|
+
/* @__PURE__ */ jsx7(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ jsx7(ScrollView3, { style: [styles7.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles7.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
|
|
536
562
|
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
537
563
|
const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
|
|
538
564
|
const swappable = taken && allowSwapTaken;
|
|
539
|
-
|
|
565
|
+
const swatchDisplay = displayFor(swatch.value);
|
|
566
|
+
return /* @__PURE__ */ jsx7(
|
|
540
567
|
TouchableRipple2,
|
|
541
568
|
{
|
|
542
569
|
disabled: taken && !swappable,
|
|
@@ -545,15 +572,15 @@ function InlineColorPicker({ id, host, value, onChange, swatches = defaultColors
|
|
|
545
572
|
if (autoDismiss) host.close();
|
|
546
573
|
},
|
|
547
574
|
borderless: true,
|
|
548
|
-
style: [
|
|
549
|
-
children: selected ? /* @__PURE__ */
|
|
575
|
+
style: [styles7.swatch, { backgroundColor: swatchDisplay }, selected && styles7.swatchSelected, taken && !swappable && styles7.swatchTaken],
|
|
576
|
+
children: selected ? /* @__PURE__ */ jsx7(Icon4, { source: "check", size: 16, color: getContrastColor(swatchDisplay) }) : swappable ? /* @__PURE__ */ jsx7(Icon4, { source: "swap-horizontal", size: 16, color: getContrastColor(swatchDisplay) }) : taken ? /* @__PURE__ */ jsx7(Icon4, { source: "close", size: 16, color: getContrastColor(swatchDisplay) }) : /* @__PURE__ */ jsx7(View7, {})
|
|
550
577
|
},
|
|
551
578
|
swatch.value
|
|
552
579
|
);
|
|
553
580
|
}) }) })
|
|
554
581
|
] });
|
|
555
582
|
}
|
|
556
|
-
var
|
|
583
|
+
var styles7 = StyleSheet7.create({
|
|
557
584
|
anchor: {
|
|
558
585
|
position: "relative"
|
|
559
586
|
},
|
|
@@ -599,6 +626,10 @@ var styles6 = StyleSheet6.create({
|
|
|
599
626
|
gap: SWATCHES_GAP,
|
|
600
627
|
padding: SWATCHES_PADDING
|
|
601
628
|
},
|
|
629
|
+
tagLabel: {
|
|
630
|
+
fontWeight: "700",
|
|
631
|
+
letterSpacing: 0.5
|
|
632
|
+
},
|
|
602
633
|
// borderRadius/height/width come from the `size` prop instead (see render-site override) — no
|
|
603
634
|
// fixed default here, since this style object is shared by every caller regardless of size.
|
|
604
635
|
trigger: {
|
|
@@ -617,19 +648,15 @@ var styles6 = StyleSheet6.create({
|
|
|
617
648
|
justifyContent: "center",
|
|
618
649
|
paddingHorizontal: 4,
|
|
619
650
|
width: "100%"
|
|
620
|
-
},
|
|
621
|
-
tagLabel: {
|
|
622
|
-
fontWeight: "700",
|
|
623
|
-
letterSpacing: 0.5
|
|
624
651
|
}
|
|
625
652
|
});
|
|
626
653
|
|
|
627
654
|
// src/LabeledDropdown.tsx
|
|
628
655
|
import { getContrastColor as getContrastColor2 } from "@rific/auto-paper";
|
|
629
656
|
import { TouchableRipple as TouchableRipple3 } from "@rific/feedback-press";
|
|
630
|
-
import { ScrollView as ScrollView4, StyleSheet as
|
|
657
|
+
import { ScrollView as ScrollView4, StyleSheet as StyleSheet8, View as View8 } from "react-native";
|
|
631
658
|
import { Icon as Icon5, Text as Text5 } from "react-native-paper";
|
|
632
|
-
import { jsx as
|
|
659
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
633
660
|
var TRIGGER_HEIGHT = 28;
|
|
634
661
|
var POPOVER_WIDTH = 180;
|
|
635
662
|
var ROW_HEIGHT = 36;
|
|
@@ -652,22 +679,22 @@ function LabeledDropdown({ id, host, options, value, onChange, color, dark, alig
|
|
|
652
679
|
onChange(option.value);
|
|
653
680
|
host.close();
|
|
654
681
|
};
|
|
655
|
-
return /* @__PURE__ */
|
|
656
|
-
/* @__PURE__ */
|
|
657
|
-
/* @__PURE__ */
|
|
658
|
-
/* @__PURE__ */
|
|
682
|
+
return /* @__PURE__ */ jsxs8(View8, { style: [styles8.anchor, open && styles8.anchorOpen], children: [
|
|
683
|
+
/* @__PURE__ */ jsx8(TouchableRipple3, { onPress: () => host.toggle(id), style: styles8.trigger, children: /* @__PURE__ */ jsxs8(View8, { ref: triggerRef, collapsable: false, style: styles8.triggerInner, children: [
|
|
684
|
+
/* @__PURE__ */ jsx8(Text5, { style: [styles8.triggerLabel, { color }], numberOfLines: 1, children: (selected?.label ?? "").toUpperCase() }),
|
|
685
|
+
/* @__PURE__ */ jsx8(Icon5, { source: "menu-down", size: 16, color })
|
|
659
686
|
] }) }),
|
|
660
|
-
/* @__PURE__ */
|
|
687
|
+
/* @__PURE__ */ jsx8(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: color, caretBorderWidth: 2, triggerSize: TRIGGER_HEIGHT, children: /* @__PURE__ */ jsx8(ScrollView4, { style: [styles8.menu, { backgroundColor: menuBg, borderColor: color, width: POPOVER_WIDTH, maxHeight }], contentContainerStyle: styles8.menuContent, showsVerticalScrollIndicator: false, children: options.map((option) => {
|
|
661
688
|
const isSelected = option.value === value;
|
|
662
689
|
const onColor = getContrastColor2(color);
|
|
663
|
-
return /* @__PURE__ */
|
|
664
|
-
option.icon && /* @__PURE__ */
|
|
665
|
-
/* @__PURE__ */
|
|
690
|
+
return /* @__PURE__ */ jsx8(TouchableRipple3, { onPress: () => handleSelect(option), style: [styles8.row, isSelected && { backgroundColor: color }], children: /* @__PURE__ */ jsxs8(View8, { style: styles8.rowInner, children: [
|
|
691
|
+
option.icon && /* @__PURE__ */ jsx8(Icon5, { source: option.icon, size: 18, color: isSelected ? onColor : fg }),
|
|
692
|
+
/* @__PURE__ */ jsx8(Text5, { style: [styles8.rowLabel, { color: isSelected ? onColor : fg }], numberOfLines: 1, children: option.label })
|
|
666
693
|
] }) }, option.value);
|
|
667
694
|
}) }) })
|
|
668
695
|
] });
|
|
669
696
|
}
|
|
670
|
-
var
|
|
697
|
+
var styles8 = StyleSheet8.create({
|
|
671
698
|
anchor: {
|
|
672
699
|
position: "relative"
|
|
673
700
|
},
|
|
@@ -725,25 +752,25 @@ function loadSkiaWeb() {
|
|
|
725
752
|
}
|
|
726
753
|
|
|
727
754
|
// src/PressAwayOverlay.tsx
|
|
728
|
-
import { Pressable, StyleSheet as
|
|
729
|
-
import { jsx as
|
|
755
|
+
import { Pressable, StyleSheet as StyleSheet9 } from "react-native";
|
|
756
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
730
757
|
function PressAwayOverlay({ active, onPress, style }) {
|
|
731
758
|
if (!active) return null;
|
|
732
|
-
return /* @__PURE__ */
|
|
759
|
+
return /* @__PURE__ */ jsx9(Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [StyleSheet9.absoluteFill, style] });
|
|
733
760
|
}
|
|
734
761
|
|
|
735
762
|
// src/ReadyButton.tsx
|
|
736
763
|
import { TouchableRipple as TouchableRipple4 } from "@rific/feedback-press";
|
|
737
|
-
import { StyleSheet as
|
|
764
|
+
import { StyleSheet as StyleSheet10 } from "react-native";
|
|
738
765
|
import { Text as Text6 } from "react-native-paper";
|
|
739
|
-
import { jsx as
|
|
766
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
740
767
|
function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
|
|
741
|
-
const readyButtonStyle = [
|
|
768
|
+
const readyButtonStyle = [styles9.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
|
|
742
769
|
const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
|
|
743
770
|
const labelColorStyle = { color: ready ? "#000000" : color };
|
|
744
|
-
return /* @__PURE__ */
|
|
771
|
+
return /* @__PURE__ */ jsx10(TouchableRipple4, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx10(Text6, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
|
|
745
772
|
}
|
|
746
|
-
var
|
|
773
|
+
var styles9 = StyleSheet10.create({
|
|
747
774
|
readyButton: {
|
|
748
775
|
alignItems: "center",
|
|
749
776
|
borderRadius: 12,
|
|
@@ -758,19 +785,19 @@ var styles8 = StyleSheet9.create({
|
|
|
758
785
|
// src/SectionedDropdown.tsx
|
|
759
786
|
import { getBlendedColor, getColorRoles } from "@rific/auto-paper";
|
|
760
787
|
import { IconButton as IconButton3, TouchableRipple as TouchableRipple5 } from "@rific/feedback-press";
|
|
761
|
-
import { ScrollView as ScrollView5, StyleSheet as
|
|
788
|
+
import { ScrollView as ScrollView5, StyleSheet as StyleSheet11, View as View9 } from "react-native";
|
|
762
789
|
import { Icon as Icon6, Text as Text7 } from "react-native-paper";
|
|
763
790
|
|
|
764
791
|
// src/TriggerGaugeHost.tsx
|
|
765
792
|
import { lazy, Suspense } from "react";
|
|
766
|
-
import { jsx as
|
|
793
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
767
794
|
var LazyTriggerGauge = lazy(() => loadSkiaWeb().then(() => import("./TriggerGauge-2OJOOF6I.mjs").then((m) => ({ default: m.TriggerGauge }))));
|
|
768
795
|
function TriggerGaugeHost(props) {
|
|
769
|
-
return /* @__PURE__ */
|
|
796
|
+
return /* @__PURE__ */ jsx11(Suspense, { fallback: null, children: /* @__PURE__ */ jsx11(LazyTriggerGauge, { ...props }) });
|
|
770
797
|
}
|
|
771
798
|
|
|
772
799
|
// src/SectionedDropdown.tsx
|
|
773
|
-
import { Fragment as Fragment4, jsx as
|
|
800
|
+
import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
774
801
|
var MENU_BORDER_WIDTH = 1;
|
|
775
802
|
var TRIGGER_SIZE = 44;
|
|
776
803
|
var MENU_MIN_WIDTH = 200;
|
|
@@ -816,17 +843,17 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
816
843
|
}
|
|
817
844
|
gaugeOffset += section.options.length;
|
|
818
845
|
}
|
|
819
|
-
const anchorStyle = [
|
|
846
|
+
const anchorStyle = [styles10.anchor, open && styles10.anchorOpen];
|
|
820
847
|
const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
|
|
821
848
|
const dividerStyle = { backgroundColor: menuBorderColor };
|
|
822
|
-
return /* @__PURE__ */
|
|
823
|
-
/* @__PURE__ */
|
|
824
|
-
/* @__PURE__ */
|
|
825
|
-
/* @__PURE__ */
|
|
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) })
|
|
826
853
|
] }),
|
|
827
|
-
/* @__PURE__ */
|
|
828
|
-
sectionIndex > 0 && /* @__PURE__ */
|
|
829
|
-
section.kind === "single" ? /* @__PURE__ */
|
|
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(
|
|
830
857
|
SingleSection,
|
|
831
858
|
{
|
|
832
859
|
section,
|
|
@@ -839,7 +866,7 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
|
|
|
839
866
|
if (autoDismiss) host.close();
|
|
840
867
|
}
|
|
841
868
|
}
|
|
842
|
-
) : /* @__PURE__ */
|
|
869
|
+
) : /* @__PURE__ */ jsx12(MultiSection, { section, accentColor, onAccentColor: resolvedOnAccentColor, mutedColor, labelFontFamily, allClearLabels })
|
|
843
870
|
] }, section.id)) }) })
|
|
844
871
|
] });
|
|
845
872
|
}
|
|
@@ -851,17 +878,18 @@ function SingleSection({
|
|
|
851
878
|
labelFontFamily,
|
|
852
879
|
onSelect
|
|
853
880
|
}) {
|
|
854
|
-
return /* @__PURE__ */
|
|
881
|
+
return /* @__PURE__ */ jsx12(Fragment4, { children: section.options.map((option) => {
|
|
855
882
|
const selected = option.value === section.value;
|
|
883
|
+
const taken = !selected && option.value === section.takenValue;
|
|
856
884
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
857
|
-
const itemStyle = [
|
|
885
|
+
const itemStyle = [styles10.item, selected && { backgroundColor: accentColor }, taken && styles10.itemTaken];
|
|
858
886
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
859
887
|
const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
|
|
860
|
-
return /* @__PURE__ */
|
|
861
|
-
option.icon && /* @__PURE__ */
|
|
862
|
-
/* @__PURE__ */
|
|
863
|
-
/* @__PURE__ */
|
|
864
|
-
option.description && /* @__PURE__ */
|
|
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 })
|
|
865
893
|
] })
|
|
866
894
|
] }) }, option.value);
|
|
867
895
|
}) });
|
|
@@ -875,23 +903,23 @@ function MultiSection({
|
|
|
875
903
|
allClearLabels
|
|
876
904
|
}) {
|
|
877
905
|
const allSelected = section.value.length === section.options.length;
|
|
878
|
-
return /* @__PURE__ */
|
|
906
|
+
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
879
907
|
section.options.map((option, i) => {
|
|
880
908
|
const selected = section.value.includes(option.value);
|
|
881
909
|
const rowColor = selected ? onAccentColor : mutedColor;
|
|
882
910
|
const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
|
|
883
911
|
const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
|
|
884
|
-
const itemStyle = [
|
|
912
|
+
const itemStyle = [styles10.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
|
|
885
913
|
const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
|
|
886
|
-
return /* @__PURE__ */
|
|
887
|
-
option.icon && /* @__PURE__ */
|
|
888
|
-
/* @__PURE__ */
|
|
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 })
|
|
889
917
|
] }) }, option.value);
|
|
890
918
|
}),
|
|
891
|
-
section.allClear && /* @__PURE__ */
|
|
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 }) })
|
|
892
920
|
] });
|
|
893
921
|
}
|
|
894
|
-
var
|
|
922
|
+
var styles10 = StyleSheet11.create({
|
|
895
923
|
allClearLabel: {
|
|
896
924
|
fontWeight: "bold",
|
|
897
925
|
textAlign: "center"
|
|
@@ -908,7 +936,7 @@ var styles9 = StyleSheet10.create({
|
|
|
908
936
|
zIndex: 100
|
|
909
937
|
},
|
|
910
938
|
divider: {
|
|
911
|
-
height:
|
|
939
|
+
height: StyleSheet11.hairlineWidth,
|
|
912
940
|
marginVertical: 4
|
|
913
941
|
},
|
|
914
942
|
item: {
|
|
@@ -927,6 +955,11 @@ var styles9 = StyleSheet10.create({
|
|
|
927
955
|
flexDirection: "row",
|
|
928
956
|
gap: 8
|
|
929
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
|
+
},
|
|
930
963
|
menu: {
|
|
931
964
|
borderRadius: 12,
|
|
932
965
|
borderWidth: MENU_BORDER_WIDTH,
|
|
@@ -957,20 +990,20 @@ var styles9 = StyleSheet10.create({
|
|
|
957
990
|
|
|
958
991
|
// src/SharedActionBand.tsx
|
|
959
992
|
import { IconButton as IconButton4 } from "@rific/feedback-press";
|
|
960
|
-
import { StyleSheet as
|
|
961
|
-
import { jsx as
|
|
993
|
+
import { StyleSheet as StyleSheet12, View as View10 } from "react-native";
|
|
994
|
+
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
962
995
|
function SharedActionBand({ onBack, onSettings, onRandomize, onReset, fg, popoverOpen, children }) {
|
|
963
|
-
return /* @__PURE__ */
|
|
964
|
-
/* @__PURE__ */
|
|
965
|
-
/* @__PURE__ */
|
|
966
|
-
onRandomize && /* @__PURE__ */
|
|
967
|
-
onReset && /* @__PURE__ */
|
|
968
|
-
/* @__PURE__ */
|
|
996
|
+
return /* @__PURE__ */ jsxs10(View10, { style: [styles11.column, popoverOpen && styles11.columnOpen], children: [
|
|
997
|
+
/* @__PURE__ */ jsxs10(View10, { style: styles11.actionsRow, children: [
|
|
998
|
+
/* @__PURE__ */ jsx13(IconButton4, { icon: "arrow-left", iconColor: fg, size: 20, onPress: onBack, accessibilityLabel: "Back" }),
|
|
999
|
+
onRandomize && /* @__PURE__ */ jsx13(IconButton4, { icon: "dice-multiple", iconColor: fg, size: 18, onPress: onRandomize, accessibilityLabel: "Randomize match settings" }),
|
|
1000
|
+
onReset && /* @__PURE__ */ jsx13(IconButton4, { icon: "restore", iconColor: fg, size: 18, onPress: onReset, accessibilityLabel: "Reset match settings to defaults" }),
|
|
1001
|
+
/* @__PURE__ */ jsx13(IconButton4, { icon: "cog", iconColor: fg, size: 20, onPress: onSettings, accessibilityLabel: "Settings" })
|
|
969
1002
|
] }),
|
|
970
1003
|
children
|
|
971
1004
|
] });
|
|
972
1005
|
}
|
|
973
|
-
var
|
|
1006
|
+
var styles11 = StyleSheet12.create({
|
|
974
1007
|
actionsRow: {
|
|
975
1008
|
alignItems: "center",
|
|
976
1009
|
flexDirection: "row",
|
|
@@ -987,19 +1020,19 @@ var styles10 = StyleSheet11.create({
|
|
|
987
1020
|
|
|
988
1021
|
// src/StatRow.tsx
|
|
989
1022
|
import { useAutoPaperTheme as useAutoPaperTheme4 } from "@rific/auto-paper";
|
|
990
|
-
import { StyleSheet as
|
|
1023
|
+
import { StyleSheet as StyleSheet13, View as View11 } from "react-native";
|
|
991
1024
|
import { Text as Text8 } from "react-native-paper";
|
|
992
|
-
import { jsx as
|
|
1025
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
993
1026
|
function StatRow({ label, value, fg: fgOverride, fgMuted: fgMutedOverride }) {
|
|
994
1027
|
const { dark } = useAutoPaperTheme4();
|
|
995
1028
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
996
1029
|
const fgMuted = fgMutedOverride ?? (dark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)");
|
|
997
|
-
return /* @__PURE__ */
|
|
998
|
-
/* @__PURE__ */
|
|
999
|
-
/* @__PURE__ */
|
|
1030
|
+
return /* @__PURE__ */ jsxs11(View11, { style: styles12.row, children: [
|
|
1031
|
+
/* @__PURE__ */ jsx14(Text8, { variant: "bodyMedium", style: { color: fgMuted }, children: label }),
|
|
1032
|
+
/* @__PURE__ */ jsx14(Text8, { variant: "bodyMedium", style: [styles12.value, { color: fg }], children: value })
|
|
1000
1033
|
] });
|
|
1001
1034
|
}
|
|
1002
|
-
var
|
|
1035
|
+
var styles12 = StyleSheet13.create({
|
|
1003
1036
|
row: {
|
|
1004
1037
|
alignItems: "center",
|
|
1005
1038
|
flexDirection: "row",
|
|
@@ -1012,19 +1045,19 @@ var styles11 = StyleSheet12.create({
|
|
|
1012
1045
|
|
|
1013
1046
|
// src/StatSection.tsx
|
|
1014
1047
|
import { useAutoPaperTheme as useAutoPaperTheme5 } from "@rific/auto-paper";
|
|
1015
|
-
import { StyleSheet as
|
|
1048
|
+
import { StyleSheet as StyleSheet14, View as View12 } from "react-native";
|
|
1016
1049
|
import { Text as Text9 } from "react-native-paper";
|
|
1017
|
-
import { jsx as
|
|
1050
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1018
1051
|
function StatSection({ label, fg: fgOverride, sectionBg: sectionBgOverride, children }) {
|
|
1019
1052
|
const { dark } = useAutoPaperTheme5();
|
|
1020
1053
|
const fg = fgOverride ?? (dark ? "#FFFFFF" : "#000000");
|
|
1021
1054
|
const sectionBg = sectionBgOverride ?? (dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)");
|
|
1022
|
-
return /* @__PURE__ */
|
|
1023
|
-
/* @__PURE__ */
|
|
1055
|
+
return /* @__PURE__ */ jsxs12(View12, { style: [styles13.section, { backgroundColor: sectionBg }], children: [
|
|
1056
|
+
/* @__PURE__ */ jsx15(Text9, { variant: "labelMedium", style: [styles13.label, { color: fg }], children: label }),
|
|
1024
1057
|
children
|
|
1025
1058
|
] });
|
|
1026
1059
|
}
|
|
1027
|
-
var
|
|
1060
|
+
var styles13 = StyleSheet14.create({
|
|
1028
1061
|
// Bold and full-contrast (fg), not the original fontless/fgMuted treatment — that read at the
|
|
1029
1062
|
// same visual weight as StatRow's own row labels below it (both used the identical muted color;
|
|
1030
1063
|
// letterSpacing/variant alone didn't separate them enough to read as "this is the group header"
|
|
@@ -1054,6 +1087,7 @@ export {
|
|
|
1054
1087
|
AchievementRow,
|
|
1055
1088
|
BaseSettingsDialog,
|
|
1056
1089
|
BaseStatsScreen,
|
|
1090
|
+
ContentGutter,
|
|
1057
1091
|
CornerActionButtons,
|
|
1058
1092
|
InlineColorPicker,
|
|
1059
1093
|
LABELED_DROPDOWN_POPOVER_WIDTH,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tastic/hud",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Visual component kit for local-multiplayer React Native games: inline (non-modal) popovers, dropdowns, color pickers, gauges, ready buttons, and dialogs, built to stay scoped to one player's own zone on a shared screen",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -63,14 +63,14 @@
|
|
|
63
63
|
},
|
|
64
64
|
"prettier": "@infinitetoken/eslint-config/prettier",
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@infinitetoken/eslint-config": "
|
|
66
|
+
"@infinitetoken/eslint-config": "0.2.0",
|
|
67
67
|
"@infinitetoken/jest-config": "^0.2.0",
|
|
68
|
-
"@infinitetoken/tsconfig": "^0.
|
|
68
|
+
"@infinitetoken/tsconfig": "^0.4.1",
|
|
69
69
|
"@rific/auto-paper": "^0.10.3",
|
|
70
70
|
"@rific/feedback-press": "^0.10.8",
|
|
71
71
|
"@rific/updater": "^0.4.2",
|
|
72
72
|
"@shopify/react-native-skia": "^2.6.2",
|
|
73
|
-
"@tastic/core": "^0.
|
|
73
|
+
"@tastic/core": "^0.2.0",
|
|
74
74
|
"@testing-library/dom": "^10.4.1",
|
|
75
75
|
"@testing-library/react": "^16.3.2",
|
|
76
76
|
"@types/jest": "^30.0.0",
|