@tastic/hud 0.1.2 → 0.1.3

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.
@@ -1,5 +1,6 @@
1
1
  // src/TriggerGauge.tsx
2
2
  import { Canvas, Path, Skia } from "@shopify/react-native-skia";
3
+ import { clamp } from "@tastic/core";
3
4
  import { useCallback, useLayoutEffect, useRef, useState } from "react";
4
5
  import { StyleSheet, View } from "react-native";
5
6
  import { Easing, useDerivedValue, useSharedValue, withTiming } from "react-native-reanimated";
@@ -60,7 +61,7 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
60
61
  if (mountProgress.value < 1) {
61
62
  const startFrac = i * MOUNT_STAGGER_MS / totalDurationMs;
62
63
  const endFrac = startFrac + MOUNT_DURATION_MS / totalDurationMs;
63
- local = Math.min(1, Math.max(0, (mountProgress.value - startFrac) / (endFrac - startFrac)));
64
+ local = clamp((mountProgress.value - startFrac) / (endFrac - startFrac), 0, 1);
64
65
  }
65
66
  const sweep = dashAngleDeg * local;
66
67
  if (sweep <= 0) continue;
@@ -84,7 +85,7 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
84
85
  if (!isLitNow) continue;
85
86
  const startFrac = i * MOUNT_STAGGER_MS / totalDurationMs;
86
87
  const endFrac = startFrac + MOUNT_DURATION_MS / totalDurationMs;
87
- local = Math.min(1, Math.max(0, (mountProgress.value - startFrac) / (endFrac - startFrac)));
88
+ local = clamp((mountProgress.value - startFrac) / (endFrac - startFrac), 0, 1);
88
89
  } else if (isLitNow === wasLit) {
89
90
  local = 1;
90
91
  } else if (isLitNow) {
package/dist/index.js CHANGED
@@ -72,7 +72,7 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
72
72
  if (mountProgress.value < 1) {
73
73
  const startFrac = i * MOUNT_STAGGER_MS / totalDurationMs;
74
74
  const endFrac = startFrac + MOUNT_DURATION_MS / totalDurationMs;
75
- local = Math.min(1, Math.max(0, (mountProgress.value - startFrac) / (endFrac - startFrac)));
75
+ local = (0, import_core2.clamp)((mountProgress.value - startFrac) / (endFrac - startFrac), 0, 1);
76
76
  }
77
77
  const sweep = dashAngleDeg * local;
78
78
  if (sweep <= 0) continue;
@@ -96,7 +96,7 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
96
96
  if (!isLitNow) continue;
97
97
  const startFrac = i * MOUNT_STAGGER_MS / totalDurationMs;
98
98
  const endFrac = startFrac + MOUNT_DURATION_MS / totalDurationMs;
99
- local = Math.min(1, Math.max(0, (mountProgress.value - startFrac) / (endFrac - startFrac)));
99
+ local = (0, import_core2.clamp)((mountProgress.value - startFrac) / (endFrac - startFrac), 0, 1);
100
100
  } else if (isLitNow === wasLit) {
101
101
  local = 1;
102
102
  } else if (isLitNow) {
@@ -125,11 +125,12 @@ function TriggerGauge({ segments, litIndices, size, accentColor, mutedColor, das
125
125
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native_skia.Path, { path: litPath, style: "stroke", strokeWidth: LIT_THICKNESS, strokeCap: "round", color: accentColor, opacity: 1 })
126
126
  ] }) });
127
127
  }
128
- var import_react_native_skia, import_react2, import_react_native7, import_react_native_reanimated, import_jsx_runtime5, UNLIT_THICKNESS, LIT_THICKNESS, DASH_GAP_PX, ARC_GAP, DEFAULT_START_DEG, MIN_DASH_ANGLE_DEG, MOUNT_DURATION_MS, MOUNT_STAGGER_MS, SELECTION_TRANSITION_DURATION_MS, styles4;
128
+ var import_react_native_skia, import_core2, import_react2, import_react_native7, import_react_native_reanimated, import_jsx_runtime5, UNLIT_THICKNESS, LIT_THICKNESS, DASH_GAP_PX, ARC_GAP, DEFAULT_START_DEG, MIN_DASH_ANGLE_DEG, MOUNT_DURATION_MS, MOUNT_STAGGER_MS, SELECTION_TRANSITION_DURATION_MS, styles4;
129
129
  var init_TriggerGauge = __esm({
130
130
  "src/TriggerGauge.tsx"() {
131
131
  "use strict";
132
132
  import_react_native_skia = require("@shopify/react-native-skia");
133
+ import_core2 = require("@tastic/core");
133
134
  import_react2 = require("react");
134
135
  import_react_native7 = require("react-native");
135
136
  import_react_native_reanimated = require("react-native-reanimated");
@@ -176,6 +177,7 @@ var MONO_FONT = import_react_native.Platform.select({ ios: "Menlo", android: "mo
176
177
  // src/InlineColorPicker.tsx
177
178
  var import_auto_paper = require("@rific/auto-paper");
178
179
  var import_feedback_press = require("@rific/feedback-press");
180
+ var import_core = require("@tastic/core");
179
181
  var import_react_native4 = require("react-native");
180
182
  var import_react_native_paper = require("react-native-paper");
181
183
 
@@ -299,7 +301,7 @@ function widthForColumns(columns) {
299
301
  function InlineColorPicker({ id, host, value, onChange, swatches = import_auto_paper.defaultColors, takenValue, allowSwapTaken, dark, align: alignOverride, icon = "palette", autoDismiss = true, columns }) {
300
302
  const menuBg = dark ? "#000000" : "#FFFFFF";
301
303
  const { width: windowWidth } = (0, import_react_native4.useWindowDimensions)();
302
- const autoColumns = Math.min(MAX_COLUMNS, Math.max(MIN_COLUMNS, Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP))));
304
+ const autoColumns = (0, import_core.clamp)(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS);
303
305
  const resolvedColumns = columns ?? autoColumns;
304
306
  const swatchesWidth = widthForColumns(resolvedColumns);
305
307
  const swatchRows = Math.ceil(swatches.length / resolvedColumns);
package/dist/index.mjs CHANGED
@@ -5,6 +5,7 @@ var MONO_FONT = Platform.select({ ios: "Menlo", android: "monospace", default: "
5
5
  // src/InlineColorPicker.tsx
6
6
  import { defaultColors, getContrastColor } from "@rific/auto-paper";
7
7
  import { TouchableRipple } from "@rific/feedback-press";
8
+ import { clamp } from "@tastic/core";
8
9
  import { ScrollView, StyleSheet as StyleSheet2, useWindowDimensions as useWindowDimensions2, View as View3 } from "react-native";
9
10
  import { Icon } from "react-native-paper";
10
11
 
@@ -128,7 +129,7 @@ function widthForColumns(columns) {
128
129
  function InlineColorPicker({ id, host, value, onChange, swatches = defaultColors, takenValue, allowSwapTaken, dark, align: alignOverride, icon = "palette", autoDismiss = true, columns }) {
129
130
  const menuBg = dark ? "#000000" : "#FFFFFF";
130
131
  const { width: windowWidth } = useWindowDimensions2();
131
- const autoColumns = Math.min(MAX_COLUMNS, Math.max(MIN_COLUMNS, Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP))));
132
+ const autoColumns = clamp(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS);
132
133
  const resolvedColumns = columns ?? autoColumns;
133
134
  const swatchesWidth = widthForColumns(resolvedColumns);
134
135
  const swatchRows = Math.ceil(swatches.length / resolvedColumns);
@@ -269,7 +270,7 @@ import { Icon as Icon2, Text as Text2 } from "react-native-paper";
269
270
  // src/TriggerGaugeHost.tsx
270
271
  import { lazy, Suspense } from "react";
271
272
  import { jsx as jsx5 } from "react/jsx-runtime";
272
- var LazyTriggerGauge = lazy(() => loadSkiaWeb().then(() => import("./TriggerGauge-XBKZ3KER.mjs").then((m) => ({ default: m.TriggerGauge }))));
273
+ var LazyTriggerGauge = lazy(() => loadSkiaWeb().then(() => import("./TriggerGauge-2OJOOF6I.mjs").then((m) => ({ default: m.TriggerGauge }))));
273
274
  function TriggerGaugeHost(props) {
274
275
  return /* @__PURE__ */ jsx5(Suspense, { fallback: null, children: /* @__PURE__ */ jsx5(LazyTriggerGauge, { ...props }) });
275
276
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tastic/hud",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
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",
@@ -29,6 +29,7 @@
29
29
  "exports": {
30
30
  ".": {
31
31
  "react-native": "./src/index.ts",
32
+ "browser": "./src/index.ts",
32
33
  "types": "./dist/index.d.ts",
33
34
  "import": "./dist/index.mjs",
34
35
  "require": "./dist/index.js"
@@ -63,6 +64,7 @@
63
64
  "@rific/auto-paper": "^0.9.4",
64
65
  "@rific/feedback-press": "^0.10.4",
65
66
  "@shopify/react-native-skia": "^2.6.2",
67
+ "@tastic/core": "^0.1.2",
66
68
  "@testing-library/dom": "^10.4.1",
67
69
  "@testing-library/react": "^16.3.2",
68
70
  "@types/jest": "^30.0.0",
@@ -92,6 +94,7 @@
92
94
  "@rific/auto-paper": ">=0.9.0",
93
95
  "@rific/feedback-press": ">=0.10.0",
94
96
  "@shopify/react-native-skia": ">=1.5.0",
97
+ "@tastic/core": ">=0.1.0",
95
98
  "react": ">=19.0.0",
96
99
  "react-native": ">=0.76.0",
97
100
  "react-native-paper": ">=5.0.0",
@@ -1,5 +1,6 @@
1
1
  import { defaultColors, getContrastColor, SeedColor } from '@rific/auto-paper'
2
2
  import { TouchableRipple } from '@rific/feedback-press'
3
+ import { clamp } from '@tastic/core'
3
4
  import { ScrollView, StyleSheet, useWindowDimensions, View } from 'react-native'
4
5
  import { Icon } from 'react-native-paper'
5
6
 
@@ -63,7 +64,7 @@ interface Props {
63
64
  export function InlineColorPicker({ id, host, value, onChange, swatches = defaultColors, takenValue, allowSwapTaken, dark, align: alignOverride, icon = 'palette', autoDismiss = true, columns }: Props) {
64
65
  const menuBg = dark ? '#000000' : '#FFFFFF'
65
66
  const { width: windowWidth } = useWindowDimensions()
66
- const autoColumns = Math.min(MAX_COLUMNS, Math.max(MIN_COLUMNS, Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP))))
67
+ const autoColumns = clamp(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS)
67
68
  const resolvedColumns = columns ?? autoColumns
68
69
  const swatchesWidth = widthForColumns(resolvedColumns)
69
70
  const swatchRows = Math.ceil(swatches.length / resolvedColumns)
@@ -1,4 +1,5 @@
1
1
  import { Canvas, Path, Skia } from '@shopify/react-native-skia'
2
+ import { clamp } from '@tastic/core'
2
3
  import { useCallback, useLayoutEffect, useRef, useState } from 'react'
3
4
  import { StyleSheet, View } from 'react-native'
4
5
  import { Easing, useDerivedValue, useSharedValue, withTiming } from 'react-native-reanimated'
@@ -207,7 +208,7 @@ export function TriggerGauge({ segments, litIndices, size, accentColor, mutedCol
207
208
  if (mountProgress.value < 1) {
208
209
  const startFrac = (i * MOUNT_STAGGER_MS) / totalDurationMs
209
210
  const endFrac = startFrac + MOUNT_DURATION_MS / totalDurationMs
210
- local = Math.min(1, Math.max(0, (mountProgress.value - startFrac) / (endFrac - startFrac)))
211
+ local = clamp((mountProgress.value - startFrac) / (endFrac - startFrac), 0, 1)
211
212
  }
212
213
  const sweep = dashAngleDeg * local
213
214
  if (sweep <= 0) continue
@@ -245,7 +246,7 @@ export function TriggerGauge({ segments, litIndices, size, accentColor, mutedCol
245
246
  if (!isLitNow) continue
246
247
  const startFrac = (i * MOUNT_STAGGER_MS) / totalDurationMs
247
248
  const endFrac = startFrac + MOUNT_DURATION_MS / totalDurationMs
248
- local = Math.min(1, Math.max(0, (mountProgress.value - startFrac) / (endFrac - startFrac)))
249
+ local = clamp((mountProgress.value - startFrac) / (endFrac - startFrac), 0, 1)
249
250
  } else if (isLitNow === wasLit) {
250
251
  local = 1 // steady — lit before and after (or the mount-only branch above already handled unlit)
251
252
  } else if (isLitNow) {