@tastic/hud 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -15
- package/dist/chrome/index.d.mts +87 -18
- package/dist/chrome/index.d.ts +87 -18
- package/dist/chrome/index.js +309 -22
- package/dist/chrome/index.mjs +13 -1
- package/dist/chunk-3TCJHMJP.mjs +14 -0
- package/dist/{chunk-N7A7W72S.mjs → chunk-BXG44LIA.mjs} +298 -19
- package/dist/index.d.mts +13 -84
- package/dist/index.d.ts +13 -84
- package/dist/index.js +120 -127
- package/dist/index.mjs +107 -374
- package/dist/skia/index.d.mts +5 -0
- package/dist/skia/index.d.ts +5 -0
- package/dist/{SkiaGate.js → skia/index.js} +17 -21
- package/dist/skia/index.mjs +8 -0
- package/package.json +9 -8
- package/src/BaseSettingsDialog.tsx +13 -13
- package/src/TriggerGaugeHost.tsx +20 -14
- package/src/chrome/index.ts +12 -4
- package/src/guide/index.ts +1 -1
- package/src/index.ts +2 -2
- package/src/loadSkiaWeb.web.ts +7 -4
- package/src/locateSkiaWebFile.ts +16 -0
- package/src/skia/index.ts +12 -0
- package/dist/SkiaGate.d.mts +0 -13
- package/dist/SkiaGate.d.ts +0 -13
- package/dist/SkiaGate.mjs +0 -6
- package/dist/chunk-XEOFR236.mjs +0 -21
- package/src/SkiaGate.tsx +0 -45
- package/src/SkiaGate.web.tsx +0 -9
package/dist/chrome/index.js
CHANGED
|
@@ -40,22 +40,28 @@ __export(chrome_exports, {
|
|
|
40
40
|
ContentGutter: () => ContentGutter,
|
|
41
41
|
CornerActionButtons: () => CornerActionButtons,
|
|
42
42
|
DialogHeader: () => DialogHeader,
|
|
43
|
+
InlineColorPicker: () => InlineColorPicker,
|
|
43
44
|
LOCKED_BADGE_COLOR: () => LOCKED_BADGE_COLOR,
|
|
44
45
|
MONO_FONT: () => MONO_FONT,
|
|
45
46
|
OverlayBackdrop: () => OverlayBackdrop,
|
|
46
47
|
OverlayCard: () => OverlayCard,
|
|
48
|
+
PopoverBody: () => PopoverBody,
|
|
49
|
+
PressAwayOverlay: () => PressAwayOverlay,
|
|
47
50
|
RotatedFrame: () => RotatedFrame,
|
|
48
51
|
StaggeredWord: () => StaggeredWord,
|
|
49
52
|
StatRow: () => StatRow,
|
|
50
53
|
StatSection: () => StatSection,
|
|
51
54
|
UpdateDialog: () => UpdateDialog,
|
|
52
55
|
WELL_SHADOW: () => WELL_SHADOW,
|
|
56
|
+
getInlineColorPickerContentSize: () => getInlineColorPickerContentSize,
|
|
53
57
|
getStaggeredWordDuration: () => getStaggeredWordDuration,
|
|
54
58
|
isCompactDialogHeight: () => isCompactDialogHeight,
|
|
55
59
|
overlayActionStyles: () => overlayActionStyles,
|
|
56
60
|
overlayStyles: () => overlayStyles,
|
|
61
|
+
useAutoAlign: () => useAutoAlign,
|
|
57
62
|
useCompactDialog: () => useCompactDialog,
|
|
58
63
|
useOverlayCardColors: () => useOverlayCardColors,
|
|
64
|
+
usePopoverHost: () => usePopoverHost,
|
|
59
65
|
useWellColors: () => useWellColors
|
|
60
66
|
});
|
|
61
67
|
module.exports = __toCommonJS(chrome_exports);
|
|
@@ -232,9 +238,10 @@ function ActivityStatSection({ stats, fg, fgMuted, sectionBg }) {
|
|
|
232
238
|
|
|
233
239
|
// src/BaseSettingsDialog.tsx
|
|
234
240
|
var import_auto_paper6 = require("@rific/auto-paper");
|
|
241
|
+
var import_core4 = require("@rific/core");
|
|
235
242
|
var import_feedback_press2 = require("@rific/feedback-press");
|
|
236
243
|
var import_updater = require("@rific/updater");
|
|
237
|
-
var
|
|
244
|
+
var import_core5 = require("@tastic/core");
|
|
238
245
|
var import_react6 = require("react");
|
|
239
246
|
var import_react_native12 = require("react-native");
|
|
240
247
|
var import_react_native_paper8 = require("react-native-paper");
|
|
@@ -499,18 +506,20 @@ var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
|
499
506
|
function SettingIcon({ source, color, containerColor }) {
|
|
500
507
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: [styles9.iconBadge, { backgroundColor: containerColor }], children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Icon, { source, size: 18, color }) });
|
|
501
508
|
}
|
|
502
|
-
function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures,
|
|
509
|
+
function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, version, lockOrientation, onLockOrientationChange, deferBottomEdgeGestures, onDeferBottomEdgeGestures, hideSound = false, hideHaptics = false, hideAppearance = false, hideUpdateCheck = false, onUpdateError, onShowHowToPlay, children }) {
|
|
503
510
|
const { colors } = (0, import_auto_paper6.useAutoPaperTheme)();
|
|
504
|
-
const ambientRotation = (0,
|
|
511
|
+
const ambientRotation = (0, import_core5.useRotation)();
|
|
505
512
|
const rotation = rotationOverride ?? ambientRotation;
|
|
506
513
|
const window = (0, import_react_native12.useWindowDimensions)();
|
|
507
514
|
const turned = rotation === 90 || rotation === -90;
|
|
508
515
|
const compactHeader = isCompactDialogHeight(turned ? window.width : window.height);
|
|
509
|
-
const insets = (0,
|
|
516
|
+
const insets = (0, import_core5.rotateInsets)((0, import_react_native_safe_area_context2.useSafeAreaInsets)(), rotation);
|
|
510
517
|
const sheetWidth = Math.min(overlayStyles.card.maxWidth, (turned ? window.height : window.width) - 2 * Math.max(insets.left, insets.right, SHEET_GUTTER));
|
|
511
|
-
const isTouchPrimary = (0,
|
|
518
|
+
const isTouchPrimary = (0, import_core5.useIsTouchPrimaryDevice)();
|
|
512
519
|
const { settings: hapticSettings, set: setHapticSettings } = (0, import_feedback_press2.useHapticSettings)();
|
|
513
520
|
const { settings: soundSettings, set: setSoundSettings } = (0, import_feedback_press2.useSoundSettings)();
|
|
521
|
+
const { settings: keepAwakeSettings, set: setKeepAwakeSettings } = (0, import_core4.useKeepAwakeSettings)();
|
|
522
|
+
const expoKeepAwake = (0, import_core4.useExpoKeepAwake)();
|
|
514
523
|
const sound = (0, import_react6.useContext)(import_feedback_press2.SoundContext);
|
|
515
524
|
const { forceShort: forceHapticFeedback } = (0, import_feedback_press2.useVibration)();
|
|
516
525
|
const { settings: themeSettings, set: setThemeSettings } = (0, import_auto_paper6.useThemeSettings)();
|
|
@@ -529,7 +538,7 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
529
538
|
if (visible && !opened) setOpened(true);
|
|
530
539
|
const showLockOrientation = isTouchPrimary && lockOrientation !== void 0 && onLockOrientationChange !== void 0;
|
|
531
540
|
const showEdgeGuard = import_react_native12.Platform.OS === "ios" && deferBottomEdgeGestures !== void 0 && onDeferBottomEdgeGestures !== void 0;
|
|
532
|
-
const showKeepAwake = isTouchPrimary &&
|
|
541
|
+
const showKeepAwake = isTouchPrimary && expoKeepAwake !== void 0;
|
|
533
542
|
const showHaptics = import_react_native12.Platform.OS !== "web" && !hideHaptics;
|
|
534
543
|
const showSound = !hideSound;
|
|
535
544
|
const showAppearance = !hideAppearance;
|
|
@@ -556,8 +565,8 @@ function BaseSettingsDialog({ visible, onDismiss, rotation: rotationOverride, ve
|
|
|
556
565
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Require second swipe" })
|
|
557
566
|
] })
|
|
558
567
|
] }) }),
|
|
559
|
-
showKeepAwake && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press2.TouchableRipple, { onPress: () =>
|
|
560
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SettingIcon, { source:
|
|
568
|
+
showKeepAwake && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_feedback_press2.TouchableRipple, { onPress: () => setKeepAwakeSettings({ enabled: !keepAwakeSettings.enabled }), style: styles9.toggleButton, accessibilityLabel: `Keep awake ${keepAwakeSettings.enabled ? "on" : "off"}`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.toggleContent, children: [
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SettingIcon, { source: keepAwakeSettings.enabled ? "eye" : "eye-closed", color: keepAwakeSettings.enabled ? colors.tertiary : colors.onSurfaceVariant, containerColor: keepAwakeSettings.enabled ? colors.tertiaryContainer : colors.surfaceVariant }),
|
|
561
570
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.View, { style: styles9.flexShrink, children: [
|
|
562
571
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodyLarge", style: { color: colors.onSurface }, children: "Keep Awake" }),
|
|
563
572
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native_paper8.Text, { variant: "bodySmall", numberOfLines: 1, style: { color: colors.onSurfaceVariant }, children: "Stop auto-lock mid-match" })
|
|
@@ -733,14 +742,14 @@ var styles9 = import_react_native12.StyleSheet.create({
|
|
|
733
742
|
// src/BaseStatsScreen.tsx
|
|
734
743
|
var import_auto_paper7 = require("@rific/auto-paper");
|
|
735
744
|
var import_feedback_press3 = require("@rific/feedback-press");
|
|
736
|
-
var
|
|
745
|
+
var import_core6 = require("@tastic/core");
|
|
737
746
|
var import_react7 = require("react");
|
|
738
747
|
var import_react_native13 = require("react-native");
|
|
739
748
|
var import_react_native_paper9 = require("react-native-paper");
|
|
740
749
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
741
750
|
function BaseStatsScreen({ rotation: rotationOverride, title = "Achievements", titleVariant = "headlineSmall", onBack, backLabel = "Back", hitSlop, insets, onReset, resetLabel = "Reset All Stats", resetConfirmTitle = "Reset Everything?", resetConfirmBody = "This permanently erases all stats and achievements. This cannot be undone.", fg: fgOverride, bg: bgOverride, children }) {
|
|
742
751
|
const { dark, colors } = (0, import_auto_paper7.useAutoPaperTheme)();
|
|
743
|
-
const ambientRotation = (0,
|
|
752
|
+
const ambientRotation = (0, import_core6.useRotation)();
|
|
744
753
|
const rotation = rotationOverride ?? ambientRotation;
|
|
745
754
|
const [confirmResetVisible, setConfirmResetVisible] = (0, import_react7.useState)(false);
|
|
746
755
|
const showReset = !!onReset;
|
|
@@ -806,12 +815,12 @@ var styles10 = import_react_native13.StyleSheet.create({
|
|
|
806
815
|
});
|
|
807
816
|
|
|
808
817
|
// src/ContentGutter.tsx
|
|
809
|
-
var
|
|
818
|
+
var import_core7 = require("@tastic/core");
|
|
810
819
|
var import_react_native14 = require("react-native");
|
|
811
820
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
812
821
|
function ContentGutter({ maxContentWidth, leftGutter, rightGutter, style, children }) {
|
|
813
|
-
const { width: windowWidth } = (0,
|
|
814
|
-
const { contentWidth, gutterWidth } = (0,
|
|
822
|
+
const { width: windowWidth } = (0, import_core7.useRotatedWindowDimensions)();
|
|
823
|
+
const { contentWidth, gutterWidth } = (0, import_core7.computeContentBounds)(windowWidth, maxContentWidth ?? Infinity);
|
|
815
824
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native14.View, { style: [styles11.row, style], children: [
|
|
816
825
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native14.View, { style: [styles11.gutter, { width: gutterWidth }], children: leftGutter }),
|
|
817
826
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native14.View, { style: { width: contentWidth }, children }),
|
|
@@ -848,11 +857,272 @@ var styles12 = import_react_native15.StyleSheet.create({
|
|
|
848
857
|
}
|
|
849
858
|
});
|
|
850
859
|
|
|
851
|
-
// src/
|
|
852
|
-
var
|
|
860
|
+
// src/InlineColorPicker.tsx
|
|
861
|
+
var import_auto_paper8 = require("@rific/auto-paper");
|
|
862
|
+
var import_feedback_press5 = require("@rific/feedback-press");
|
|
863
|
+
var import_core8 = require("@tastic/core");
|
|
864
|
+
var import_react_native18 = require("react-native");
|
|
865
|
+
var import_react_native_paper10 = require("react-native-paper");
|
|
866
|
+
|
|
867
|
+
// src/PopoverBody.tsx
|
|
853
868
|
var import_react_native16 = require("react-native");
|
|
854
|
-
var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
|
|
855
869
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
870
|
+
var CARET_SIZE = 7;
|
|
871
|
+
var CARET_RING_OFFSET = 2;
|
|
872
|
+
var CARET_DIP = 1;
|
|
873
|
+
function PopoverBody({ visible, children, align = "center", verticalAlign = "below", caretColor, caretBorderColor, caretBorderWidth = 1, triggerSize = 0 }) {
|
|
874
|
+
if (!visible) return null;
|
|
875
|
+
const above = verticalAlign === "above";
|
|
876
|
+
const alignStyle = align === "left" ? styles13.contentLeft : align === "right" ? styles13.contentRight : styles13.contentCenter;
|
|
877
|
+
const verticalStyle = above ? styles13.contentAbove : styles13.contentBelow;
|
|
878
|
+
const ringSize = CARET_SIZE + caretBorderWidth;
|
|
879
|
+
const caretOffset = (halfFootprint) => align === "right" ? { right: triggerSize / 2 - halfFootprint } : { left: triggerSize / 2 - halfFootprint };
|
|
880
|
+
const caretFill = above ? "borderTopColor" : "borderBottomColor";
|
|
881
|
+
const caretWidthProp = above ? "borderTopWidth" : "borderBottomWidth";
|
|
882
|
+
const caretEdge = (size) => above ? { bottom: -size + CARET_DIP } : { top: -size + CARET_DIP };
|
|
883
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native16.View, { style: [styles13.content, alignStyle, verticalStyle], children: [
|
|
884
|
+
children,
|
|
885
|
+
caretColor && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
886
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native16.View, { style: [styles13.caret, caretOffset(ringSize), caretEdge(ringSize), { [caretFill]: caretBorderColor ?? caretColor, [caretWidthProp]: ringSize, borderLeftWidth: ringSize, borderRightWidth: ringSize }] }),
|
|
887
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native16.View, { style: [styles13.caret, caretOffset(CARET_SIZE), caretEdge(CARET_SIZE - CARET_RING_OFFSET), { [caretFill]: caretColor, [caretWidthProp]: CARET_SIZE, borderLeftWidth: CARET_SIZE, borderRightWidth: CARET_SIZE }] })
|
|
888
|
+
] })
|
|
889
|
+
] });
|
|
890
|
+
}
|
|
891
|
+
var styles13 = import_react_native16.StyleSheet.create({
|
|
892
|
+
caret: {
|
|
893
|
+
borderLeftColor: "transparent",
|
|
894
|
+
borderRightColor: "transparent",
|
|
895
|
+
height: 0,
|
|
896
|
+
position: "absolute",
|
|
897
|
+
width: 0,
|
|
898
|
+
// Explicit, not left to DOM order - the box it dips into is itself a position:'relative' view,
|
|
899
|
+
// which React Native Web always gives an implicit zIndex:0 (see PopoverBody's stacking-context
|
|
900
|
+
// notes elsewhere in this codebase), so painting on top needs a real zIndex to beat that
|
|
901
|
+
// reliably rather than relying on being the later sibling.
|
|
902
|
+
zIndex: 1
|
|
903
|
+
},
|
|
904
|
+
content: {
|
|
905
|
+
position: "absolute",
|
|
906
|
+
zIndex: 50
|
|
907
|
+
},
|
|
908
|
+
contentAbove: {
|
|
909
|
+
bottom: "100%",
|
|
910
|
+
marginBottom: 8
|
|
911
|
+
},
|
|
912
|
+
contentBelow: {
|
|
913
|
+
marginTop: 8,
|
|
914
|
+
top: "100%"
|
|
915
|
+
},
|
|
916
|
+
// Stretched to the anchor's own (trigger) width, with alignItems centering the actual (usually
|
|
917
|
+
// much wider) popover box inside via plain flexbox - not `left:'50%'` plus a percentage
|
|
918
|
+
// `transform`, which depends on native resolving the box's own auto width before applying the
|
|
919
|
+
// transform and has proven unreliable there, visibly shifting the box off-center.
|
|
920
|
+
contentCenter: {
|
|
921
|
+
alignItems: "center",
|
|
922
|
+
left: 0,
|
|
923
|
+
right: 0
|
|
924
|
+
},
|
|
925
|
+
contentLeft: {
|
|
926
|
+
left: 0
|
|
927
|
+
},
|
|
928
|
+
contentRight: {
|
|
929
|
+
right: 0
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
|
|
933
|
+
// src/useAutoAlign.ts
|
|
934
|
+
var import_react8 = require("react");
|
|
935
|
+
var import_react_native17 = require("react-native");
|
|
936
|
+
var EDGE_MARGIN = 12;
|
|
937
|
+
function rotateRect(x, y, width, height, rotation, windowWidth, windowHeight) {
|
|
938
|
+
if (rotation === 0) return { x, y, width, height };
|
|
939
|
+
const cx = windowWidth / 2;
|
|
940
|
+
const cy = windowHeight / 2;
|
|
941
|
+
const dx = x + width / 2 - cx;
|
|
942
|
+
const dy = y + height / 2 - cy;
|
|
943
|
+
const [newDx, newDy, newWidth, newHeight] = rotation === 180 ? [-dx, -dy, width, height] : rotation === 90 ? [-dy, dx, height, width] : [dy, -dx, height, width];
|
|
944
|
+
return { x: cx + newDx - newWidth / 2, y: cy + newDy - newHeight / 2, width: newWidth, height: newHeight };
|
|
945
|
+
}
|
|
946
|
+
function useAutoAlign(open, contentWidth, contentHeight, rotation = 0) {
|
|
947
|
+
const triggerRef = (0, import_react8.useRef)(null);
|
|
948
|
+
const { width: windowWidth, height: windowHeight } = (0, import_react_native17.useWindowDimensions)();
|
|
949
|
+
const [align, setAlign] = (0, import_react8.useState)("center");
|
|
950
|
+
const [verticalAlign, setVerticalAlign] = (0, import_react8.useState)("below");
|
|
951
|
+
const [maxHeight, setMaxHeight] = (0, import_react8.useState)(contentHeight);
|
|
952
|
+
const [measured, setMeasured] = (0, import_react8.useState)(false);
|
|
953
|
+
const [prevOpen, setPrevOpen] = (0, import_react8.useState)(open);
|
|
954
|
+
if (open !== prevOpen) {
|
|
955
|
+
setPrevOpen(open);
|
|
956
|
+
if (open) setMeasured(false);
|
|
957
|
+
}
|
|
958
|
+
const measure = (0, import_react8.useCallback)(() => {
|
|
959
|
+
triggerRef.current?.measureInWindow((rawX, rawY, rawWidth, rawHeight) => {
|
|
960
|
+
const { x, y, width: triggerWidth, height: triggerHeight } = rotateRect(rawX, rawY, rawWidth, rawHeight, rotation, windowWidth, windowHeight);
|
|
961
|
+
const centerX = x + triggerWidth / 2;
|
|
962
|
+
const overflowsRight = centerX + contentWidth / 2 > windowWidth - EDGE_MARGIN;
|
|
963
|
+
const overflowsLeft = centerX - contentWidth / 2 < EDGE_MARGIN;
|
|
964
|
+
if (overflowsRight && !overflowsLeft) setAlign("right");
|
|
965
|
+
else if (overflowsLeft && !overflowsRight) setAlign("left");
|
|
966
|
+
else setAlign("center");
|
|
967
|
+
const roomBelow = windowHeight - (y + triggerHeight) - EDGE_MARGIN;
|
|
968
|
+
const roomAbove = y - EDGE_MARGIN;
|
|
969
|
+
const above = contentHeight > roomBelow && roomAbove > roomBelow;
|
|
970
|
+
setVerticalAlign(above ? "above" : "below");
|
|
971
|
+
setMaxHeight(Math.max(above ? roomAbove : roomBelow, 0));
|
|
972
|
+
setMeasured(true);
|
|
973
|
+
});
|
|
974
|
+
}, [contentWidth, contentHeight, windowWidth, windowHeight, rotation]);
|
|
975
|
+
(0, import_react8.useEffect)(() => {
|
|
976
|
+
if (open) measure();
|
|
977
|
+
}, [open, measure]);
|
|
978
|
+
return { align, maxHeight, measured, triggerRef, verticalAlign };
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// src/InlineColorPicker.tsx
|
|
982
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
983
|
+
var EMOJI_PATTERN = /\p{Extended_Pictographic}/u;
|
|
984
|
+
var DEFAULT_SIZE = 48;
|
|
985
|
+
var SWATCH_SIZE = 28;
|
|
986
|
+
var SWATCHES_PADDING = 8;
|
|
987
|
+
var SWATCHES_GAP = 6;
|
|
988
|
+
var SWATCHES_BORDER_WIDTH = 2;
|
|
989
|
+
var MIN_COLUMNS = 4;
|
|
990
|
+
var MAX_COLUMNS = 5;
|
|
991
|
+
var SCREEN_MARGIN = 40;
|
|
992
|
+
function widthForColumns(columns) {
|
|
993
|
+
return SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * columns + SWATCHES_GAP * (columns - 1);
|
|
994
|
+
}
|
|
995
|
+
function getInlineColorPickerContentSize(swatchCount, windowWidth, columns) {
|
|
996
|
+
const autoColumns = (0, import_core8.clamp)(Math.floor((windowWidth - 2 * SCREEN_MARGIN + SWATCHES_GAP) / (SWATCH_SIZE + SWATCHES_GAP)), MIN_COLUMNS, MAX_COLUMNS);
|
|
997
|
+
const resolvedColumns = columns ?? autoColumns;
|
|
998
|
+
const width = widthForColumns(resolvedColumns);
|
|
999
|
+
const rows = Math.ceil(swatchCount / resolvedColumns);
|
|
1000
|
+
const height = SWATCHES_BORDER_WIDTH * 2 + SWATCHES_PADDING * 2 + SWATCH_SIZE * rows + SWATCHES_GAP * (rows - 1);
|
|
1001
|
+
return { width, height };
|
|
1002
|
+
}
|
|
1003
|
+
function InlineColorPicker({ id, host, value, onChange, previewValue, swatches = import_auto_paper8.defaultColors, takenValue, allowSwapTaken, dark, align: forcedAlign, alignOverride, rotation: rotationOverride, icon = "palette", tag, labelFontFamily = MONO_FONT, autoDismiss = true, columns, size = DEFAULT_SIZE }) {
|
|
1004
|
+
const ambientRotation = (0, import_core8.useRotation)();
|
|
1005
|
+
const rotation = rotationOverride ?? ambientRotation;
|
|
1006
|
+
const menuBg = dark ? "#000000" : "#FFFFFF";
|
|
1007
|
+
const { width: windowWidth } = (0, import_react_native18.useWindowDimensions)();
|
|
1008
|
+
const { width: swatchesWidth, height: swatchesHeight } = getInlineColorPickerContentSize(swatches.length, windowWidth, columns);
|
|
1009
|
+
const open = host.openId === id;
|
|
1010
|
+
const auto = useAutoAlign(open, swatchesWidth, swatchesHeight, rotation);
|
|
1011
|
+
const placement = alignOverride ?? auto;
|
|
1012
|
+
const { maxHeight, measured, triggerRef, verticalAlign } = placement;
|
|
1013
|
+
const align = forcedAlign ?? placement.align;
|
|
1014
|
+
const displayFor = previewValue ?? ((hex) => hex);
|
|
1015
|
+
const displayValue = displayFor(value);
|
|
1016
|
+
const contrastColor = (0, import_auto_paper8.getContrastColor)(displayValue);
|
|
1017
|
+
const tagFontSize = size * (tag && EMOJI_PATTERN.test(tag) ? 0.6 : 0.4);
|
|
1018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native18.View, { style: [styles14.anchor, open && styles14.anchorOpen], children: [
|
|
1019
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_feedback_press5.TouchableRipple, { onPress: () => host.toggle(id), borderless: true, style: [styles14.trigger, { backgroundColor: displayValue, borderRadius: size / 2, height: size, width: size }], children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native18.View, { ref: triggerRef, collapsable: false, style: styles14.triggerMeasure, children: tag ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper10.Text, { style: [styles14.tagLabel, { color: contrastColor, fontFamily: labelFontFamily, fontSize: tagFontSize }], numberOfLines: 1, adjustsFontSizeToFit: true, children: tag }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper10.Icon, { source: icon, size: size * 0.6, color: contrastColor }) }) }),
|
|
1020
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverBody, { visible: open && measured, align, verticalAlign, caretColor: menuBg, caretBorderColor: displayValue, caretBorderWidth: SWATCHES_BORDER_WIDTH, triggerSize: size, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native18.ScrollView, { style: [styles14.swatches, { backgroundColor: menuBg, borderColor: displayValue, width: swatchesWidth, maxHeight }], contentContainerStyle: styles14.swatchesContent, showsVerticalScrollIndicator: false, children: swatches.map((swatch) => {
|
|
1021
|
+
const selected = swatch.value.toLowerCase() === value.toLowerCase();
|
|
1022
|
+
const taken = !selected && !!takenValue && swatch.value.toLowerCase() === takenValue.toLowerCase();
|
|
1023
|
+
const swappable = taken && allowSwapTaken;
|
|
1024
|
+
const swatchDisplay = displayFor(swatch.value);
|
|
1025
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1026
|
+
import_feedback_press5.TouchableRipple,
|
|
1027
|
+
{
|
|
1028
|
+
disabled: taken && !swappable,
|
|
1029
|
+
onPress: () => {
|
|
1030
|
+
onChange(swatch.value);
|
|
1031
|
+
if (autoDismiss) host.close();
|
|
1032
|
+
},
|
|
1033
|
+
borderless: true,
|
|
1034
|
+
style: [styles14.swatch, { backgroundColor: swatchDisplay }, selected && styles14.swatchSelected, taken && !swappable && styles14.swatchTaken],
|
|
1035
|
+
children: selected ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper10.Icon, { source: "check", size: 16, color: (0, import_auto_paper8.getContrastColor)(swatchDisplay) }) : swappable ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper10.Icon, { source: "swap-horizontal", size: 16, color: (0, import_auto_paper8.getContrastColor)(swatchDisplay) }) : taken ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native_paper10.Icon, { source: "close", size: 16, color: (0, import_auto_paper8.getContrastColor)(swatchDisplay) }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native18.View, {})
|
|
1036
|
+
},
|
|
1037
|
+
swatch.value
|
|
1038
|
+
);
|
|
1039
|
+
}) }) })
|
|
1040
|
+
] });
|
|
1041
|
+
}
|
|
1042
|
+
var styles14 = import_react_native18.StyleSheet.create({
|
|
1043
|
+
anchor: {
|
|
1044
|
+
position: "relative"
|
|
1045
|
+
},
|
|
1046
|
+
// See SectionedDropdown's identical comment - React Native Web gives every position:'relative' view
|
|
1047
|
+
// its own stacking context, so the elevation has to live on the anchor itself, not just the
|
|
1048
|
+
// popover content nested inside it, to correctly paint above this anchor's own later siblings.
|
|
1049
|
+
anchorOpen: {
|
|
1050
|
+
zIndex: 100
|
|
1051
|
+
},
|
|
1052
|
+
swatch: {
|
|
1053
|
+
alignItems: "center",
|
|
1054
|
+
borderRadius: SWATCH_SIZE / 2,
|
|
1055
|
+
height: SWATCH_SIZE,
|
|
1056
|
+
justifyContent: "center",
|
|
1057
|
+
width: SWATCH_SIZE
|
|
1058
|
+
},
|
|
1059
|
+
swatchSelected: {
|
|
1060
|
+
borderColor: "#ffffff",
|
|
1061
|
+
borderWidth: 2
|
|
1062
|
+
},
|
|
1063
|
+
swatchTaken: {
|
|
1064
|
+
opacity: 0.35
|
|
1065
|
+
},
|
|
1066
|
+
swatches: {
|
|
1067
|
+
borderRadius: 12,
|
|
1068
|
+
borderWidth: SWATCHES_BORDER_WIDTH,
|
|
1069
|
+
elevation: 8,
|
|
1070
|
+
shadowColor: "#000000",
|
|
1071
|
+
shadowOffset: { height: 2, width: 0 },
|
|
1072
|
+
shadowOpacity: 0.3,
|
|
1073
|
+
shadowRadius: 8
|
|
1074
|
+
// width is set inline above - border-box sizing means it has to include the border too
|
|
1075
|
+
// (2*SWATCHES_BORDER_WIDTH), not just padding+content, or exactly enough room goes missing that
|
|
1076
|
+
// the last column silently wraps to a new row. Anything wider than the exact sum just shows as
|
|
1077
|
+
// dead space on the right edge of each row instead.
|
|
1078
|
+
},
|
|
1079
|
+
// Separate from `swatches` itself - see SectionedDropdown's identical menu/menuContent split.
|
|
1080
|
+
// The scroll frame's own bounds (including maxHeight) live on the ScrollView; the actual grid
|
|
1081
|
+
// wrapping belongs to its contentContainerStyle, which sizes to the unclamped content instead.
|
|
1082
|
+
swatchesContent: {
|
|
1083
|
+
flexDirection: "row",
|
|
1084
|
+
flexWrap: "wrap",
|
|
1085
|
+
gap: SWATCHES_GAP,
|
|
1086
|
+
padding: SWATCHES_PADDING
|
|
1087
|
+
},
|
|
1088
|
+
tagLabel: {
|
|
1089
|
+
fontWeight: "700",
|
|
1090
|
+
letterSpacing: 0.5
|
|
1091
|
+
},
|
|
1092
|
+
// borderRadius/height/width come from the `size` prop instead (see render-site override) - no
|
|
1093
|
+
// fixed default here, since this style object is shared by every caller regardless of size.
|
|
1094
|
+
trigger: {
|
|
1095
|
+
alignItems: "center",
|
|
1096
|
+
alignSelf: "flex-start",
|
|
1097
|
+
justifyContent: "center"
|
|
1098
|
+
},
|
|
1099
|
+
// Wraps just the icon/tag, inside the TouchableRipple, purely so useAutoAlign has a plain View
|
|
1100
|
+
// to attach its measurement ref to - TouchableRipple itself doesn't forward a ref to a
|
|
1101
|
+
// measurable native node. Padded horizontally so a multi-character tag doesn't butt right up
|
|
1102
|
+
// against the trigger's own circular edge (an icon alone doesn't need it, but this style is
|
|
1103
|
+
// shared by both).
|
|
1104
|
+
triggerMeasure: {
|
|
1105
|
+
alignItems: "center",
|
|
1106
|
+
height: "100%",
|
|
1107
|
+
justifyContent: "center",
|
|
1108
|
+
paddingHorizontal: 4,
|
|
1109
|
+
width: "100%"
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
|
|
1113
|
+
// src/PressAwayOverlay.tsx
|
|
1114
|
+
var import_react_native19 = require("react-native");
|
|
1115
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1116
|
+
function PressAwayOverlay({ active, onPress, style }) {
|
|
1117
|
+
if (!active) return null;
|
|
1118
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Pressable, { accessibilityLabel: "Dismiss", accessibilityRole: "button", onPress, style: [import_react_native19.StyleSheet.absoluteFill, style] });
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
// src/StaggeredWord.tsx
|
|
1122
|
+
var import_react9 = require("react");
|
|
1123
|
+
var import_react_native20 = require("react-native");
|
|
1124
|
+
var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
|
|
1125
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
856
1126
|
var STAGGER_MS = 45;
|
|
857
1127
|
var LETTER_DURATION_MS = 320;
|
|
858
1128
|
function getStaggeredWordDuration(letterCount) {
|
|
@@ -860,7 +1130,7 @@ function getStaggeredWordDuration(letterCount) {
|
|
|
860
1130
|
}
|
|
861
1131
|
function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }) {
|
|
862
1132
|
const progress = (0, import_react_native_reanimated.useSharedValue)(reducedMotion ? 1 : 0);
|
|
863
|
-
(0,
|
|
1133
|
+
(0, import_react9.useEffect)(() => {
|
|
864
1134
|
if (reducedMotion) return;
|
|
865
1135
|
progress.value = (0, import_react_native_reanimated.withDelay)(index * STAGGER_MS, (0, import_react_native_reanimated.withTiming)(1, { duration: LETTER_DURATION_MS, easing: import_react_native_reanimated.Easing.out(import_react_native_reanimated.Easing.back(1.5)) }));
|
|
866
1136
|
}, [reducedMotion]);
|
|
@@ -868,12 +1138,12 @@ function AnimatedLetter({ char, index, color, reducedMotion, fontFamily, fontSiz
|
|
|
868
1138
|
opacity: progress.value,
|
|
869
1139
|
transform: [{ translateY: (1 - progress.value) * 12 }, { scale: 0.85 + progress.value * 0.15 }]
|
|
870
1140
|
}));
|
|
871
|
-
return /* @__PURE__ */ (0,
|
|
1141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native_reanimated.default.Text, { allowFontScaling: false, style: [{ color, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, style], children: char });
|
|
872
1142
|
}
|
|
873
1143
|
function StaggeredWord({ word, color, fontFamily, fontSize, lineHeight, reducedMotion, startIndex = 0, fontWeight = "bold", letterSpacing, style, onLayout }) {
|
|
874
|
-
return /* @__PURE__ */ (0,
|
|
1144
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native20.View, { style: [styles15.row, style], onLayout, children: word.split("").map((char, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AnimatedLetter, { char, index: startIndex + i, color, reducedMotion, fontFamily, fontSize, lineHeight, fontWeight, letterSpacing }, i)) });
|
|
875
1145
|
}
|
|
876
|
-
var
|
|
1146
|
+
var styles15 = import_react_native20.StyleSheet.create({
|
|
877
1147
|
row: {
|
|
878
1148
|
flexDirection: "row"
|
|
879
1149
|
}
|
|
@@ -881,12 +1151,23 @@ var styles13 = import_react_native16.StyleSheet.create({
|
|
|
881
1151
|
|
|
882
1152
|
// src/UpdateDialog.tsx
|
|
883
1153
|
var import_updater2 = require("@rific/updater");
|
|
884
|
-
var
|
|
1154
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
885
1155
|
function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onError }) {
|
|
886
1156
|
const { manifest, onConfirm, respond } = useUpdateConfirmBridge();
|
|
887
1157
|
(0, import_updater2.useUpdater)({ autoCheck, autoPrompt, onConfirm, onError });
|
|
888
1158
|
const date = manifest ? new Date(manifest.createdAt) : null;
|
|
889
|
-
return /* @__PURE__ */ (0,
|
|
1159
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ConfirmDialog, { visible: !!manifest, title: "Update Available", message: date ? `Released ${date.toLocaleDateString()} at ${date.toLocaleTimeString()}` : "", confirmLabel: "Restart", cancelLabel: "Later", icon: "update", rotation, onConfirm: () => respond(true), onCancel: () => respond(false) });
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
// src/usePopoverHost.ts
|
|
1163
|
+
var import_react10 = require("react");
|
|
1164
|
+
function usePopoverHost() {
|
|
1165
|
+
const [openId, setOpenId] = (0, import_react10.useState)(null);
|
|
1166
|
+
const toggle = (0, import_react10.useCallback)((id) => {
|
|
1167
|
+
setOpenId((prev) => prev === id ? null : id);
|
|
1168
|
+
}, []);
|
|
1169
|
+
const close = (0, import_react10.useCallback)(() => setOpenId(null), []);
|
|
1170
|
+
return { openId, toggle, close };
|
|
890
1171
|
}
|
|
891
1172
|
// Annotate the CommonJS export names for ESM import in node:
|
|
892
1173
|
0 && (module.exports = {
|
|
@@ -900,21 +1181,27 @@ function UpdateDialog({ rotation = 0, autoCheck = true, autoPrompt = true, onErr
|
|
|
900
1181
|
ContentGutter,
|
|
901
1182
|
CornerActionButtons,
|
|
902
1183
|
DialogHeader,
|
|
1184
|
+
InlineColorPicker,
|
|
903
1185
|
LOCKED_BADGE_COLOR,
|
|
904
1186
|
MONO_FONT,
|
|
905
1187
|
OverlayBackdrop,
|
|
906
1188
|
OverlayCard,
|
|
1189
|
+
PopoverBody,
|
|
1190
|
+
PressAwayOverlay,
|
|
907
1191
|
RotatedFrame,
|
|
908
1192
|
StaggeredWord,
|
|
909
1193
|
StatRow,
|
|
910
1194
|
StatSection,
|
|
911
1195
|
UpdateDialog,
|
|
912
1196
|
WELL_SHADOW,
|
|
1197
|
+
getInlineColorPickerContentSize,
|
|
913
1198
|
getStaggeredWordDuration,
|
|
914
1199
|
isCompactDialogHeight,
|
|
915
1200
|
overlayActionStyles,
|
|
916
1201
|
overlayStyles,
|
|
1202
|
+
useAutoAlign,
|
|
917
1203
|
useCompactDialog,
|
|
918
1204
|
useOverlayCardColors,
|
|
1205
|
+
usePopoverHost,
|
|
919
1206
|
useWellColors
|
|
920
1207
|
});
|
package/dist/chrome/index.mjs
CHANGED
|
@@ -7,18 +7,24 @@ import {
|
|
|
7
7
|
ConfirmDialog,
|
|
8
8
|
ContentGutter,
|
|
9
9
|
CornerActionButtons,
|
|
10
|
+
InlineColorPicker,
|
|
10
11
|
LOCKED_BADGE_COLOR,
|
|
11
12
|
MONO_FONT,
|
|
13
|
+
PopoverBody,
|
|
14
|
+
PressAwayOverlay,
|
|
12
15
|
RotatedFrame,
|
|
13
16
|
StaggeredWord,
|
|
14
17
|
StatRow,
|
|
15
18
|
StatSection,
|
|
16
19
|
UpdateDialog,
|
|
17
20
|
WELL_SHADOW,
|
|
21
|
+
getInlineColorPickerContentSize,
|
|
18
22
|
getStaggeredWordDuration,
|
|
23
|
+
useAutoAlign,
|
|
19
24
|
useCompactDialog,
|
|
25
|
+
usePopoverHost,
|
|
20
26
|
useWellColors
|
|
21
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-BXG44LIA.mjs";
|
|
22
28
|
import {
|
|
23
29
|
COMPACT_DIALOG_HEIGHT,
|
|
24
30
|
DialogHeader,
|
|
@@ -40,21 +46,27 @@ export {
|
|
|
40
46
|
ContentGutter,
|
|
41
47
|
CornerActionButtons,
|
|
42
48
|
DialogHeader,
|
|
49
|
+
InlineColorPicker,
|
|
43
50
|
LOCKED_BADGE_COLOR,
|
|
44
51
|
MONO_FONT,
|
|
45
52
|
OverlayBackdrop,
|
|
46
53
|
OverlayCard,
|
|
54
|
+
PopoverBody,
|
|
55
|
+
PressAwayOverlay,
|
|
47
56
|
RotatedFrame,
|
|
48
57
|
StaggeredWord,
|
|
49
58
|
StatRow,
|
|
50
59
|
StatSection,
|
|
51
60
|
UpdateDialog,
|
|
52
61
|
WELL_SHADOW,
|
|
62
|
+
getInlineColorPickerContentSize,
|
|
53
63
|
getStaggeredWordDuration,
|
|
54
64
|
isCompactDialogHeight,
|
|
55
65
|
overlayActionStyles,
|
|
56
66
|
overlayStyles,
|
|
67
|
+
useAutoAlign,
|
|
57
68
|
useCompactDialog,
|
|
58
69
|
useOverlayCardColors,
|
|
70
|
+
usePopoverHost,
|
|
59
71
|
useWellColors
|
|
60
72
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/loadSkiaWeb.ts
|
|
2
|
+
function loadSkiaWeb() {
|
|
3
|
+
return Promise.resolve();
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// src/locateSkiaWebFile.ts
|
|
7
|
+
function locateSkiaWebFile(file) {
|
|
8
|
+
return `${process.env.EXPO_BASE_URL ?? ""}/${file}`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
loadSkiaWeb,
|
|
13
|
+
locateSkiaWebFile
|
|
14
|
+
};
|