@tastic/hud 0.1.0 → 0.1.1

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.
@@ -100,7 +100,15 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
100
100
  return path;
101
101
  }, [segments, litIndicesKey, transitionFromKey, singleSelect, step, startDeg, dashAngleDeg, totalDurationMs, oval.x, oval.y, oval.width, oval.height]);
102
102
  if (segments < 2) return null;
103
- return /* @__PURE__ */ jsx(View, { style: [styles.container, { height: size, width: size }], pointerEvents: "none", children: /* @__PURE__ */ jsxs(Canvas, { style: { height: canvasSize, width: canvasSize }, children: [
103
+ const gaugeSizeStyle = {
104
+ height: size,
105
+ width: size
106
+ };
107
+ const canvasSizeStyle = {
108
+ height: canvasSize,
109
+ width: canvasSize
110
+ };
111
+ return /* @__PURE__ */ jsx(View, { style: [styles.container, gaugeSizeStyle], pointerEvents: "none", children: /* @__PURE__ */ jsxs(Canvas, { style: canvasSizeStyle, children: [
104
112
  /* @__PURE__ */ jsx(Path, { path: unlitPath, style: "stroke", strokeWidth: UNLIT_THICKNESS, strokeCap: "round", color: mutedColor, opacity: 0.35 }),
105
113
  /* @__PURE__ */ jsx(Path, { path: litPath, style: "stroke", strokeWidth: LIT_THICKNESS, strokeCap: "round", color: accentColor, opacity: 1 })
106
114
  ] }) });
package/dist/index.js CHANGED
@@ -122,7 +122,15 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
122
122
  return path;
123
123
  }, [segments, litIndicesKey, transitionFromKey, singleSelect, step, startDeg, dashAngleDeg, totalDurationMs, oval.x, oval.y, oval.width, oval.height]);
124
124
  if (segments < 2) return null;
125
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native8.View, { style: [styles4.container, { height: size, width: size }], pointerEvents: "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native_skia.Canvas, { style: { height: canvasSize, width: canvasSize }, children: [
125
+ const gaugeSizeStyle = {
126
+ height: size,
127
+ width: size
128
+ };
129
+ const canvasSizeStyle = {
130
+ height: canvasSize,
131
+ width: canvasSize
132
+ };
133
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native8.View, { style: [styles4.container, gaugeSizeStyle], pointerEvents: "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native_skia.Canvas, { style: canvasSizeStyle, children: [
126
134
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native_skia.Path, { path: unlitPath, style: "stroke", strokeWidth: UNLIT_THICKNESS, strokeCap: "round", color: mutedColor, opacity: 0.35 }),
127
135
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native_skia.Path, { path: litPath, style: "stroke", strokeWidth: LIT_THICKNESS, strokeCap: "round", color: accentColor, opacity: 1 })
128
136
  ] }) });
@@ -418,7 +426,10 @@ var import_react_native7 = require("react-native");
418
426
  var import_react_native_paper2 = require("react-native-paper");
419
427
  var import_jsx_runtime4 = require("react/jsx-runtime");
420
428
  function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
421
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_feedback_press2.TouchableRipple, { onPress: onToggleReady, borderless: true, style: [styles3.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style], children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_paper2.Text, { variant: "labelLarge", style: [{ fontFamily: labelFontFamily, fontWeight: "bold" }, { color: ready ? "#000000" : color }], children: ready ? "READY \u2713" : "READY?" }) });
429
+ const readyButtonStyle = [styles3.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
430
+ const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
431
+ const labelColorStyle = { color: ready ? "#000000" : color };
432
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_feedback_press2.TouchableRipple, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_paper2.Text, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
422
433
  }
423
434
  var styles3 = import_react_native7.StyleSheet.create({
424
435
  readyButton: {
@@ -493,13 +504,16 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
493
504
  }
494
505
  gaugeOffset += section.options.length;
495
506
  }
496
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native9.View, { style: [styles5.anchor, open && styles5.anchorOpen], children: [
507
+ const anchorStyle = [styles5.anchor, open && styles5.anchorOpen];
508
+ const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
509
+ const dividerStyle = { backgroundColor: menuBorderColor };
510
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native9.View, { style: anchorStyle, children: [
497
511
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native9.View, { ref: triggerRef, collapsable: false, style: styles5.triggerBox, children: [
498
512
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
499
513
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press3.IconButton, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
500
514
  ] }),
501
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native9.ScrollView, { style: [styles5.menu, { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight }], contentContainerStyle: styles5.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native9.View, { children: [
502
- sectionIndex > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native9.View, { style: [styles5.divider, { backgroundColor: menuBorderColor }] }),
515
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native9.ScrollView, { style: [styles5.menu, menuStyle], contentContainerStyle: styles5.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native9.View, { children: [
516
+ sectionIndex > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native9.View, { style: [styles5.divider, dividerStyle] }),
503
517
  section.kind === "single" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
504
518
  SingleSection,
505
519
  {
@@ -528,11 +542,14 @@ function SingleSection({
528
542
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: section.options.map((option) => {
529
543
  const selected = option.value === section.value;
530
544
  const rowColor = selected ? onAccentColor : mutedColor;
531
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press3.TouchableRipple, { onPress: () => onSelect(option.value), style: [styles5.item, selected && { backgroundColor: accentColor }], children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native9.View, { style: styles5.itemRow, children: [
545
+ const itemStyle = [styles5.item, selected && { backgroundColor: accentColor }];
546
+ const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
547
+ const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
548
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press3.TouchableRipple, { onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native9.View, { style: styles5.itemRow, children: [
532
549
  option.icon && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper3.Icon, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
533
550
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native9.View, { style: styles5.itemLabelColumn, children: [
534
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper3.Text, { variant: "labelLarge", style: [{ fontFamily: labelFontFamily }, { color: rowColor, fontWeight: selected ? "bold" : "normal" }], children: option.label }),
535
- option.description && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper3.Text, { variant: "labelSmall", style: [{ fontFamily: labelFontFamily }, { color: rowColor }], children: option.description })
551
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper3.Text, { variant: "labelLarge", style: labelStyle, children: option.label }),
552
+ option.description && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper3.Text, { variant: "labelSmall", style: descriptionStyle, children: option.description })
536
553
  ] })
537
554
  ] }) }, option.value);
538
555
  }) });
@@ -552,9 +569,11 @@ function MultiSection({
552
569
  const rowColor = selected ? onAccentColor : mutedColor;
553
570
  const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
554
571
  const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
555
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press3.TouchableRipple, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: [styles5.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }], children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native9.View, { style: styles5.itemRow, children: [
572
+ const itemStyle = [styles5.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
573
+ const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
574
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press3.TouchableRipple, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native9.View, { style: styles5.itemRow, children: [
556
575
  option.icon && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper3.Icon, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
557
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper3.Text, { variant: "labelLarge", style: [styles5.itemLabelFlex, { fontFamily: labelFontFamily }, { color: rowColor, fontWeight: selected ? "bold" : "normal" }], children: option.label })
576
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper3.Text, { variant: "labelLarge", style: [styles5.itemLabelFlex, labelStyle], children: option.label })
558
577
  ] }) }, option.value);
559
578
  }),
560
579
  section.allClear && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_feedback_press3.TouchableRipple, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles5.item, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_paper3.Text, { variant: "labelLarge", style: [styles5.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
package/dist/index.mjs CHANGED
@@ -245,7 +245,10 @@ import { StyleSheet as StyleSheet4 } from "react-native";
245
245
  import { Text } from "react-native-paper";
246
246
  import { jsx as jsx4 } from "react/jsx-runtime";
247
247
  function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }) {
248
- return /* @__PURE__ */ jsx4(TouchableRipple2, { onPress: onToggleReady, borderless: true, style: [styles3.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style], children: /* @__PURE__ */ jsx4(Text, { variant: "labelLarge", style: [{ fontFamily: labelFontFamily, fontWeight: "bold" }, { color: ready ? "#000000" : color }], children: ready ? "READY \u2713" : "READY?" }) });
248
+ const readyButtonStyle = [styles3.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style];
249
+ const labelTextStyle = { fontFamily: labelFontFamily, fontWeight: "bold" };
250
+ const labelColorStyle = { color: ready ? "#000000" : color };
251
+ return /* @__PURE__ */ jsx4(TouchableRipple2, { onPress: onToggleReady, borderless: true, style: readyButtonStyle, children: /* @__PURE__ */ jsx4(Text, { variant: "labelLarge", style: [labelTextStyle, labelColorStyle], children: ready ? "READY \u2713" : "READY?" }) });
249
252
  }
250
253
  var styles3 = StyleSheet4.create({
251
254
  readyButton: {
@@ -268,7 +271,7 @@ import { Icon as Icon2, Text as Text2 } from "react-native-paper";
268
271
  // src/TriggerGaugeHost.tsx
269
272
  import { lazy, Suspense } from "react";
270
273
  import { jsx as jsx5 } from "react/jsx-runtime";
271
- var LazyTriggerGauge = lazy(() => loadSkiaWeb().then(() => import("./TriggerGauge-HIPRGEWJ.mjs").then((m) => ({ default: m.TriggerGauge }))));
274
+ var LazyTriggerGauge = lazy(() => loadSkiaWeb().then(() => import("./TriggerGauge-XBKZ3KER.mjs").then((m) => ({ default: m.TriggerGauge }))));
272
275
  function TriggerGaugeHost(props) {
273
276
  return /* @__PURE__ */ jsx5(Suspense, { fallback: null, children: /* @__PURE__ */ jsx5(LazyTriggerGauge, { ...props }) });
274
277
  }
@@ -320,13 +323,16 @@ function SectionedDropdown({ id, host, icon, accessibilityLabel, sections, accen
320
323
  }
321
324
  gaugeOffset += section.options.length;
322
325
  }
323
- return /* @__PURE__ */ jsxs3(View4, { style: [styles4.anchor, open && styles4.anchorOpen], children: [
326
+ const anchorStyle = [styles4.anchor, open && styles4.anchorOpen];
327
+ const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight };
328
+ const dividerStyle = { backgroundColor: menuBorderColor };
329
+ return /* @__PURE__ */ jsxs3(View4, { style: anchorStyle, children: [
324
330
  /* @__PURE__ */ jsxs3(View4, { ref: triggerRef, collapsable: false, style: styles4.triggerBox, children: [
325
331
  /* @__PURE__ */ jsx6(TriggerGaugeHost, { segments: gaugeSegments, litIndices: gaugeLitIndices, size: TRIGGER_SIZE, accentColor, mutedColor }),
326
332
  /* @__PURE__ */ jsx6(IconButton, { icon: triggerIcon, iconColor: triggerIconColor, size: triggerIconSize, accessibilityLabel, onPress: () => host.toggle(id) })
327
333
  ] }),
328
- /* @__PURE__ */ jsx6(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx6(ScrollView2, { style: [styles4.menu, { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight }], contentContainerStyle: styles4.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs3(View4, { children: [
329
- sectionIndex > 0 && /* @__PURE__ */ jsx6(View4, { style: [styles4.divider, { backgroundColor: menuBorderColor }] }),
334
+ /* @__PURE__ */ jsx6(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: menuBorderColor, caretBorderWidth: MENU_BORDER_WIDTH, triggerSize: TRIGGER_SIZE, children: /* @__PURE__ */ jsx6(ScrollView2, { style: [styles4.menu, menuStyle], contentContainerStyle: styles4.menuContent, showsVerticalScrollIndicator: false, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs3(View4, { children: [
335
+ sectionIndex > 0 && /* @__PURE__ */ jsx6(View4, { style: [styles4.divider, dividerStyle] }),
330
336
  section.kind === "single" ? /* @__PURE__ */ jsx6(
331
337
  SingleSection,
332
338
  {
@@ -355,11 +361,14 @@ function SingleSection({
355
361
  return /* @__PURE__ */ jsx6(Fragment2, { children: section.options.map((option) => {
356
362
  const selected = option.value === section.value;
357
363
  const rowColor = selected ? onAccentColor : mutedColor;
358
- return /* @__PURE__ */ jsx6(TouchableRipple3, { onPress: () => onSelect(option.value), style: [styles4.item, selected && { backgroundColor: accentColor }], children: /* @__PURE__ */ jsxs3(View4, { style: styles4.itemRow, children: [
364
+ const itemStyle = [styles4.item, selected && { backgroundColor: accentColor }];
365
+ const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
366
+ const descriptionStyle = { fontFamily: labelFontFamily, color: rowColor };
367
+ return /* @__PURE__ */ jsx6(TouchableRipple3, { onPress: () => onSelect(option.value), style: itemStyle, children: /* @__PURE__ */ jsxs3(View4, { style: styles4.itemRow, children: [
359
368
  option.icon && /* @__PURE__ */ jsx6(Icon2, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
360
369
  /* @__PURE__ */ jsxs3(View4, { style: styles4.itemLabelColumn, children: [
361
- /* @__PURE__ */ jsx6(Text2, { variant: "labelLarge", style: [{ fontFamily: labelFontFamily }, { color: rowColor, fontWeight: selected ? "bold" : "normal" }], children: option.label }),
362
- option.description && /* @__PURE__ */ jsx6(Text2, { variant: "labelSmall", style: [{ fontFamily: labelFontFamily }, { color: rowColor }], children: option.description })
370
+ /* @__PURE__ */ jsx6(Text2, { variant: "labelLarge", style: labelStyle, children: option.label }),
371
+ option.description && /* @__PURE__ */ jsx6(Text2, { variant: "labelSmall", style: descriptionStyle, children: option.description })
363
372
  ] })
364
373
  ] }) }, option.value);
365
374
  }) });
@@ -379,9 +388,11 @@ function MultiSection({
379
388
  const rowColor = selected ? onAccentColor : mutedColor;
380
389
  const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value);
381
390
  const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value);
382
- return /* @__PURE__ */ jsx6(TouchableRipple3, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: [styles4.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }], children: /* @__PURE__ */ jsxs3(View4, { style: styles4.itemRow, children: [
391
+ const itemStyle = [styles4.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }];
392
+ const labelStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? "bold" : "normal" };
393
+ return /* @__PURE__ */ jsx6(TouchableRipple3, { onPress: () => section.onChange(selected ? section.value.filter((v) => v !== option.value) : [...section.value, option.value]), style: itemStyle, children: /* @__PURE__ */ jsxs3(View4, { style: styles4.itemRow, children: [
383
394
  option.icon && /* @__PURE__ */ jsx6(Icon2, { source: option.icon, size: MENU_ITEM_ICON_SIZE, color: rowColor }),
384
- /* @__PURE__ */ jsx6(Text2, { variant: "labelLarge", style: [styles4.itemLabelFlex, { fontFamily: labelFontFamily }, { color: rowColor, fontWeight: selected ? "bold" : "normal" }], children: option.label })
395
+ /* @__PURE__ */ jsx6(Text2, { variant: "labelLarge", style: [styles4.itemLabelFlex, labelStyle], children: option.label })
385
396
  ] }) }, option.value);
386
397
  }),
387
398
  section.allClear && /* @__PURE__ */ jsx6(TouchableRipple3, { onPress: () => section.onChange(allSelected ? [] : section.options.map((o) => o.value)), style: styles4.item, children: /* @__PURE__ */ jsx6(Text2, { variant: "labelLarge", style: [styles4.allClearLabel, { fontFamily: labelFontFamily, color: accentColor }], children: allSelected ? allClearLabels.clear : allClearLabels.all }) })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tastic/hud",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
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",
@@ -1,5 +1,5 @@
1
1
  import { TouchableRipple } from '@rific/feedback-press'
2
- import { StyleProp, StyleSheet, ViewStyle } from 'react-native'
2
+ import { StyleProp, StyleSheet, TextStyle, ViewStyle } from 'react-native'
3
3
  import { Text } from 'react-native-paper'
4
4
 
5
5
  import { MONO_FONT } from './fonts'
@@ -21,9 +21,13 @@ interface Props {
21
21
  // below a shared row — e.g. a vs-CPU mode with only one human player needs just one Ready toggle,
22
22
  // not one tucked under each slot.
23
23
  export function ReadyButton({ color, ready, onToggleReady, style, labelFontFamily = MONO_FONT }: Props) {
24
+ const readyButtonStyle = [styles.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style]
25
+ const labelTextStyle: TextStyle = { fontFamily: labelFontFamily, fontWeight: 'bold' }
26
+ const labelColorStyle = { color: ready ? '#000000' : color }
27
+
24
28
  return (
25
- <TouchableRipple onPress={onToggleReady} borderless style={[styles.readyButton, { borderColor: color }, ready && { backgroundColor: color }, style]}>
26
- <Text variant='labelLarge' style={[{ fontFamily: labelFontFamily, fontWeight: 'bold' }, { color: ready ? '#000000' : color }]}>
29
+ <TouchableRipple onPress={onToggleReady} borderless style={readyButtonStyle}>
30
+ <Text variant='labelLarge' style={[labelTextStyle, labelColorStyle]}>
27
31
  {ready ? 'READY ✓' : 'READY?'}
28
32
  </Text>
29
33
  </TouchableRipple>
@@ -1,6 +1,6 @@
1
1
  import { getBlendedColor, getColorRoles } from '@rific/auto-paper'
2
2
  import { IconButton, TouchableRipple } from '@rific/feedback-press'
3
- import { ScrollView, StyleSheet, View } from 'react-native'
3
+ import { ScrollView, StyleSheet, TextStyle, View } from 'react-native'
4
4
  import { Icon, Text } from 'react-native-paper'
5
5
 
6
6
  import { MONO_FONT } from './fonts'
@@ -177,8 +177,12 @@ export function SectionedDropdown({ id, host, icon, accessibilityLabel, sections
177
177
  gaugeOffset += section.options.length
178
178
  }
179
179
 
180
+ const anchorStyle = [styles.anchor, open && styles.anchorOpen]
181
+ const menuStyle = { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight }
182
+ const dividerStyle = { backgroundColor: menuBorderColor }
183
+
180
184
  return (
181
- <View style={[styles.anchor, open && styles.anchorOpen]}>
185
+ <View style={anchorStyle}>
182
186
  <View ref={triggerRef} collapsable={false} style={styles.triggerBox}>
183
187
  <TriggerGaugeHost segments={gaugeSegments} litIndices={gaugeLitIndices} size={TRIGGER_SIZE} accentColor={accentColor} mutedColor={mutedColor} />
184
188
  <IconButton icon={triggerIcon} iconColor={triggerIconColor} size={triggerIconSize} accessibilityLabel={accessibilityLabel} onPress={() => host.toggle(id)} />
@@ -194,13 +198,13 @@ export function SectionedDropdown({ id, host, icon, accessibilityLabel, sections
194
198
  is always <= maxHeight then, so nothing scrolls); on a short landscape screen where neither
195
199
  direction has enough room, this is what keeps the menu from just running off the screen
196
200
  edge instead of flipping only made it run off a *smaller* amount. */}
197
- <ScrollView style={[styles.menu, { backgroundColor: menuBg, borderColor: menuBorderColor, maxHeight }]} contentContainerStyle={styles.menuContent} showsVerticalScrollIndicator={false}>
201
+ <ScrollView style={[styles.menu, menuStyle]} contentContainerStyle={styles.menuContent} showsVerticalScrollIndicator={false}>
198
202
  {sections.map((section, sectionIndex) => (
199
203
  <View key={section.id}>
200
204
  {/* Every section after the first gets a rule above it — the divider belongs to the
201
205
  boundary between sections, not to either section itself, so it's keyed off position
202
206
  rather than each section carrying its own "divider below me" flag. */}
203
- {sectionIndex > 0 && <View style={[styles.divider, { backgroundColor: menuBorderColor }]} />}
207
+ {sectionIndex > 0 && <View style={[styles.divider, dividerStyle]} />}
204
208
 
205
209
  {section.kind === 'single' ? (
206
210
  <SingleSection
@@ -247,16 +251,19 @@ function SingleSection({
247
251
  {section.options.map((option) => {
248
252
  const selected = option.value === section.value
249
253
  const rowColor = selected ? onAccentColor : mutedColor
254
+ const itemStyle = [styles.item, selected && { backgroundColor: accentColor }]
255
+ const labelStyle: TextStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? 'bold' : 'normal' }
256
+ const descriptionStyle: TextStyle = { fontFamily: labelFontFamily, color: rowColor }
250
257
  return (
251
- <TouchableRipple key={option.value} onPress={() => onSelect(option.value)} style={[styles.item, selected && { backgroundColor: accentColor }]}>
258
+ <TouchableRipple key={option.value} onPress={() => onSelect(option.value)} style={itemStyle}>
252
259
  <View style={styles.itemRow}>
253
260
  {option.icon && <Icon source={option.icon} size={MENU_ITEM_ICON_SIZE} color={rowColor} />}
254
261
  <View style={styles.itemLabelColumn}>
255
- <Text variant='labelLarge' style={[{ fontFamily: labelFontFamily }, { color: rowColor, fontWeight: selected ? 'bold' : 'normal' }]}>
262
+ <Text variant='labelLarge' style={labelStyle}>
256
263
  {option.label}
257
264
  </Text>
258
265
  {option.description && (
259
- <Text variant='labelSmall' style={[{ fontFamily: labelFontFamily }, { color: rowColor }]}>
266
+ <Text variant='labelSmall' style={descriptionStyle}>
260
267
  {option.description}
261
268
  </Text>
262
269
  )}
@@ -299,11 +306,13 @@ function MultiSection({
299
306
  // separately-rounded pills.
300
307
  const prevSelected = selected && i > 0 && section.value.includes(section.options[i - 1].value)
301
308
  const nextSelected = selected && i < section.options.length - 1 && section.value.includes(section.options[i + 1].value)
309
+ const itemStyle = [styles.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }]
310
+ const labelStyle: TextStyle = { fontFamily: labelFontFamily, color: rowColor, fontWeight: selected ? 'bold' : 'normal' }
302
311
  return (
303
- <TouchableRipple key={option.value} onPress={() => section.onChange(selected ? section.value.filter((v: unknown) => v !== option.value) : [...section.value, option.value])} style={[styles.item, selected && { backgroundColor: accentColor }, prevSelected && { borderTopLeftRadius: 0, borderTopRightRadius: 0 }, nextSelected && { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }]}>
312
+ <TouchableRipple key={option.value} onPress={() => section.onChange(selected ? section.value.filter((v: unknown) => v !== option.value) : [...section.value, option.value])} style={itemStyle}>
304
313
  <View style={styles.itemRow}>
305
314
  {option.icon && <Icon source={option.icon} size={MENU_ITEM_ICON_SIZE} color={rowColor} />}
306
- <Text variant='labelLarge' style={[styles.itemLabelFlex, { fontFamily: labelFontFamily }, { color: rowColor, fontWeight: selected ? 'bold' : 'normal' }]}>
315
+ <Text variant='labelLarge' style={[styles.itemLabelFlex, labelStyle]}>
307
316
  {option.label}
308
317
  </Text>
309
318
  </View>
@@ -266,9 +266,18 @@ export function TriggerGauge({ segments, litIndices, size, accentColor, mutedCol
266
266
 
267
267
  if (segments < 2) return null
268
268
 
269
+ const gaugeSizeStyle = {
270
+ height: size,
271
+ width: size
272
+ }
273
+ const canvasSizeStyle = {
274
+ height: canvasSize,
275
+ width: canvasSize
276
+ }
277
+
269
278
  return (
270
- <View style={[styles.container, { height: size, width: size }]} pointerEvents='none'>
271
- <Canvas style={{ height: canvasSize, width: canvasSize }}>
279
+ <View style={[styles.container, gaugeSizeStyle]} pointerEvents='none'>
280
+ <Canvas style={canvasSizeStyle}>
272
281
  <Path path={unlitPath} style='stroke' strokeWidth={UNLIT_THICKNESS} strokeCap='round' color={mutedColor} opacity={0.35} />
273
282
  <Path path={litPath} style='stroke' strokeWidth={LIT_THICKNESS} strokeCap='round' color={accentColor} opacity={1} />
274
283
  </Canvas>