@enigmax/primitives 0.17.0 → 0.18.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.
Files changed (89) hide show
  1. package/dist/button-CaXaqG_K.d.ts +63 -0
  2. package/dist/chunk-2QFTRNAZ.js +88 -0
  3. package/dist/chunk-6BGBYUSZ.js +114 -0
  4. package/dist/chunk-AU3H5WIY.js +107 -0
  5. package/dist/chunk-F25CGNQC.js +19 -0
  6. package/dist/chunk-HC2ME5PU.js +168 -0
  7. package/dist/chunk-HS3X3XCW.js +43 -0
  8. package/dist/chunk-IIT6U7LM.js +249 -0
  9. package/dist/chunk-IXVMRVD4.js +96 -0
  10. package/dist/chunk-KJINGUQN.js +188 -0
  11. package/dist/chunk-LKA2UG4P.js +542 -0
  12. package/dist/chunk-MMQPZGSU.js +161 -0
  13. package/dist/chunk-OCMI7R6H.js +79 -0
  14. package/dist/chunk-QYMUIW5I.js +28 -0
  15. package/dist/chunk-S653GLSF.js +17 -0
  16. package/dist/chunk-SNYUBXWQ.js +149 -0
  17. package/dist/chunk-U3V4EHOB.js +41 -0
  18. package/dist/chunk-UOSSNUSC.js +309 -0
  19. package/dist/chunk-WSB655JB.js +47 -0
  20. package/dist/chunk-XNNQRA35.js +31 -0
  21. package/dist/chunk-XQHCZAPJ.js +102 -0
  22. package/dist/chunk-ZCUFYBPB.js +154 -0
  23. package/dist/chunk-ZWR2EXHQ.js +55 -0
  24. package/dist/flags-BBJc9unY.d.ts +133 -0
  25. package/dist/index-D-ARvWpQ.d.ts +306 -0
  26. package/dist/index-DNXPtY9X.d.ts +144 -0
  27. package/dist/index.d.ts +16 -602
  28. package/dist/index.js +9 -1
  29. package/dist/input-BwXjFenq.d.ts +77 -0
  30. package/dist/marquee-CJ3Uwy3E.d.ts +81 -0
  31. package/dist/network-D2LsBG_k.d.ts +39 -0
  32. package/dist/next/index.d.ts +20 -3
  33. package/dist/next/index.js +23 -3
  34. package/dist/notifications-BpVV6sel.d.ts +70 -0
  35. package/dist/password-3DRQYAYQ.js +2 -0
  36. package/dist/password-C8lG4Zm9.d.ts +71 -0
  37. package/dist/password-FB2CUEKJ.js +1 -0
  38. package/dist/react/button.d.ts +75 -0
  39. package/dist/react/button.js +4 -0
  40. package/dist/react/flag.d.ts +37 -0
  41. package/dist/react/flag.js +3 -0
  42. package/dist/react/index.d.ts +28 -312
  43. package/dist/react/index.js +22 -2
  44. package/dist/react/input.d.ts +4 -0
  45. package/dist/react/input.js +3 -0
  46. package/dist/react/marquee.d.ts +44 -0
  47. package/dist/react/marquee.js +3 -0
  48. package/dist/react/network.d.ts +20 -0
  49. package/dist/react/network.js +3 -0
  50. package/dist/react/notifications.d.ts +17 -0
  51. package/dist/react/notifications.js +3 -0
  52. package/dist/react/palette.d.ts +3 -0
  53. package/dist/react/palette.js +4 -0
  54. package/dist/react/relative-time.d.ts +21 -0
  55. package/dist/react/relative-time.js +3 -0
  56. package/dist/react/search.d.ts +30 -0
  57. package/dist/react/search.js +3 -0
  58. package/dist/react/slot.d.ts +47 -0
  59. package/dist/react/slot.js +2 -0
  60. package/dist/react/toast.d.ts +40 -0
  61. package/dist/react/toast.js +4 -0
  62. package/dist/react-router/index.d.ts +20 -3
  63. package/dist/react-router/index.js +23 -3
  64. package/dist/relative-time-YpRTG7YH.d.ts +106 -0
  65. package/dist/search-P4OHCRXD.js +50 -0
  66. package/package.json +52 -2
  67. package/registry.json +175 -18
  68. package/src/core/flags.ts +88 -42
  69. package/src/core/input-icons.ts +34 -0
  70. package/src/core/input.ts +5 -21
  71. package/src/core/palette.ts +0 -0
  72. package/src/index.ts +2 -2
  73. package/src/react/button.tsx +70 -4
  74. package/src/react/flag.tsx +18 -6
  75. package/src/react/index.ts +40 -5
  76. package/src/react/input/icon.tsx +17 -0
  77. package/src/react/input/index.tsx +307 -0
  78. package/src/react/input/password.tsx +174 -0
  79. package/src/react/input/search.tsx +82 -0
  80. package/src/react/input/types.ts +146 -0
  81. package/src/react/input/write-value.ts +18 -0
  82. package/src/react/palette/context.ts +60 -0
  83. package/src/react/palette/index.tsx +66 -0
  84. package/src/react/palette/root.tsx +621 -0
  85. package/src/react/slot.tsx +91 -0
  86. package/src/react/use-button.ts +3 -1
  87. package/dist/chunk-4GLYRF4B.js +0 -1259
  88. package/dist/chunk-JFNND6P4.js +0 -749
  89. package/src/react/input.tsx +0 -429
@@ -0,0 +1,79 @@
1
+ import { relativeTimeView, relativeTimeAttributes } from './chunk-IXVMRVD4.js';
2
+ import { useEffect, useCallback, createElement } from 'react';
3
+
4
+ var loading = null;
5
+ function loadElement() {
6
+ if (loading || typeof window === "undefined") return;
7
+ loading = import('@github/relative-time-element').catch(() => {
8
+ return null;
9
+ });
10
+ }
11
+ function RelativeTime({
12
+ date,
13
+ fallback = null,
14
+ capitalize = false,
15
+ capitalizeFirst = true,
16
+ now,
17
+ format,
18
+ tense,
19
+ precision,
20
+ threshold,
21
+ prefix,
22
+ formatStyle,
23
+ locale,
24
+ timeZone,
25
+ second,
26
+ minute,
27
+ hour,
28
+ weekday,
29
+ day,
30
+ month,
31
+ year,
32
+ timeZoneName,
33
+ noTitle,
34
+ numericBeyondThreshold,
35
+ ...rest
36
+ }) {
37
+ useEffect(loadElement, []);
38
+ const applyPrefix = useCallback((node) => {
39
+ if (!node) return;
40
+ if (prefix === void 0 || prefix === "") node.removeAttribute("prefix");
41
+ else node.setAttribute("prefix", prefix);
42
+ }, [prefix]);
43
+ const options = {
44
+ format,
45
+ tense,
46
+ precision,
47
+ threshold,
48
+ prefix,
49
+ formatStyle,
50
+ locale,
51
+ timeZone,
52
+ second,
53
+ minute,
54
+ hour,
55
+ weekday,
56
+ day,
57
+ month,
58
+ year,
59
+ timeZoneName,
60
+ noTitle,
61
+ numericBeyondThreshold
62
+ };
63
+ const view = relativeTimeView(date, options, now);
64
+ if (!view.date) return fallback;
65
+ const marks = {
66
+ "data-relative-time-capitalize": capitalize ? "true" : void 0,
67
+ "data-relative-time-capitalize-first-letter": capitalizeFirst ? "true" : void 0,
68
+ // The text differs between the server's instant and the browser's, which is the
69
+ // one hydration difference React has an escape hatch for rather than a bug.
70
+ suppressHydrationWarning: true
71
+ };
72
+ if (view.absoluteOnly) {
73
+ return createElement("time", { dateTime: view.iso, title: noTitle ? void 0 : view.exact, ...marks, ...rest }, view.label);
74
+ }
75
+ const { prefix: prefixAttribute, ...attributes } = relativeTimeAttributes(view, options);
76
+ return createElement("relative-time", { ...attributes, ...marks, ...rest, ref: applyPrefix }, view.label);
77
+ }
78
+
79
+ export { RelativeTime };
@@ -0,0 +1,28 @@
1
+ import { createNotifications } from './chunk-SNYUBXWQ.js';
2
+ import { useRef, useSyncExternalStore, useMemo } from 'react';
3
+
4
+ var defaultQueue = createNotifications();
5
+ function useNotifications(queue = defaultQueue) {
6
+ const snapshot = useRef(queue.items);
7
+ const items = useSyncExternalStore(
8
+ (listener) => queue.subscribe((next) => {
9
+ snapshot.current = next;
10
+ listener();
11
+ }),
12
+ () => snapshot.current,
13
+ () => snapshot.current
14
+ );
15
+ return useMemo(() => ({
16
+ items,
17
+ notify: queue.notify,
18
+ dismiss: queue.dismiss,
19
+ dismissAll: queue.dismissAll,
20
+ pause: queue.pause,
21
+ resume: queue.resume
22
+ }), [items, queue]);
23
+ }
24
+ function createNotificationQueue(options) {
25
+ return createNotifications(options);
26
+ }
27
+
28
+ export { createNotificationQueue, defaultQueue, useNotifications };
@@ -0,0 +1,17 @@
1
+ import { createNetworkMonitor, SERVER_NETWORK_STATE } from './chunk-2QFTRNAZ.js';
2
+ import { useMemo, useRef, useSyncExternalStore } from 'react';
3
+
4
+ function useNetworkState() {
5
+ const monitor = useMemo(() => createNetworkMonitor(), []);
6
+ const snapshot = useRef(monitor.state);
7
+ return useSyncExternalStore(
8
+ (listener) => monitor.subscribe((next) => {
9
+ snapshot.current = next;
10
+ listener();
11
+ }),
12
+ () => snapshot.current,
13
+ () => SERVER_NETWORK_STATE
14
+ );
15
+ }
16
+
17
+ export { useNetworkState };
@@ -0,0 +1,149 @@
1
+ // src/core/notifications.ts
2
+ var DEFAULT_MAX = 4;
3
+ var DEFAULT_DURATION = 5e3;
4
+ function createNotifications(options = {}) {
5
+ const view = typeof document === "undefined" ? null : document;
6
+ const max = options.max ?? DEFAULT_MAX;
7
+ const defaultDuration = options.duration ?? DEFAULT_DURATION;
8
+ const sticky = /* @__PURE__ */ new Set([...options.stickyTones ?? ["error"], "loading"]);
9
+ let items = [];
10
+ let paused = false;
11
+ let sequence = 0;
12
+ const listeners = /* @__PURE__ */ new Set();
13
+ const timers = /* @__PURE__ */ new Map();
14
+ function emit() {
15
+ const snapshot = Object.freeze([...items]);
16
+ for (const listener of listeners) listener(snapshot);
17
+ }
18
+ function clearTimer(id) {
19
+ const timer = timers.get(id);
20
+ if (timer?.handle) clearTimeout(timer.handle);
21
+ timers.delete(id);
22
+ }
23
+ function startTimer(id, remaining) {
24
+ if (!Number.isFinite(remaining) || remaining <= 0) return;
25
+ const handle = paused ? null : setTimeout(() => dismiss(id), remaining);
26
+ timers.set(id, { handle, remaining, startedAt: Date.now() });
27
+ }
28
+ function dismiss(id) {
29
+ const next = items.filter((item) => item.id !== id);
30
+ if (next.length === items.length) return;
31
+ items = next;
32
+ clearTimer(id);
33
+ emit();
34
+ }
35
+ function notify(input) {
36
+ const tone = input.tone ?? "info";
37
+ const duration = input.duration ?? (sticky.has(tone) ? Infinity : defaultDuration);
38
+ const existing = input.key ? items.find((item) => item.key === input.key) : void 0;
39
+ const id = existing?.id ?? `n${++sequence}`;
40
+ const notification = {
41
+ id,
42
+ key: input.key,
43
+ title: input.title,
44
+ body: input.body,
45
+ tone,
46
+ duration,
47
+ action: input.action,
48
+ data: input.data,
49
+ createdAt: Date.now()
50
+ };
51
+ items = existing ? items.map((item) => item.id === id ? notification : item) : [...items, notification];
52
+ if (items.length > max) {
53
+ const evictable = items.find((item) => Number.isFinite(item.duration) && item.id !== id);
54
+ if (evictable) {
55
+ items = items.filter((item) => item.id !== evictable.id);
56
+ clearTimer(evictable.id);
57
+ } else {
58
+ items = items.slice(items.length - max);
59
+ }
60
+ }
61
+ clearTimer(id);
62
+ startTimer(id, duration);
63
+ emit();
64
+ return id;
65
+ }
66
+ const onVisibility = () => {
67
+ if (!view) return;
68
+ if (view.hidden) instance.pause();
69
+ else instance.resume();
70
+ };
71
+ function update(id, patch) {
72
+ const current = items.find((item) => item.id === id);
73
+ if (!current) return;
74
+ const tone = patch.tone ?? current.tone;
75
+ const duration = patch.duration ?? (patch.tone ? sticky.has(tone) ? Infinity : defaultDuration : current.duration);
76
+ items = items.map((item) => item.id === id ? { ...current, ...patch, tone, duration } : item);
77
+ clearTimer(id);
78
+ startTimer(id, duration);
79
+ emit();
80
+ }
81
+ function resolveMessage(message, value) {
82
+ const resolved = typeof message === "function" ? message(value) : message;
83
+ return typeof resolved === "string" ? { title: resolved } : resolved;
84
+ }
85
+ async function promise(work, messages) {
86
+ const start = typeof messages.loading === "string" ? { title: messages.loading } : messages.loading;
87
+ const key = start.key ?? `p${++sequence}`;
88
+ notify({ ...start, key, tone: "loading" });
89
+ try {
90
+ const value = await work;
91
+ notify({ ...resolveMessage(messages.success, value), key, tone: "success" });
92
+ return value;
93
+ } catch (error) {
94
+ notify({ ...resolveMessage(messages.error, error), key, tone: "error" });
95
+ throw error;
96
+ }
97
+ }
98
+ const instance = {
99
+ get items() {
100
+ return Object.freeze([...items]);
101
+ },
102
+ notify,
103
+ update,
104
+ promise,
105
+ dismiss,
106
+ dismissAll() {
107
+ for (const item of items) clearTimer(item.id);
108
+ items = [];
109
+ emit();
110
+ },
111
+ pause() {
112
+ if (paused) return;
113
+ paused = true;
114
+ for (const [id, timer] of timers) {
115
+ if (!timer.handle) continue;
116
+ clearTimeout(timer.handle);
117
+ timers.set(id, {
118
+ handle: null,
119
+ remaining: Math.max(timer.remaining - (Date.now() - timer.startedAt), 0),
120
+ startedAt: Date.now()
121
+ });
122
+ }
123
+ },
124
+ resume() {
125
+ if (!paused) return;
126
+ paused = false;
127
+ for (const [id, timer] of [...timers]) {
128
+ clearTimer(id);
129
+ startTimer(id, timer.remaining);
130
+ }
131
+ },
132
+ subscribe(listener) {
133
+ listeners.add(listener);
134
+ return () => {
135
+ listeners.delete(listener);
136
+ };
137
+ },
138
+ destroy() {
139
+ for (const item of items) clearTimer(item.id);
140
+ items = [];
141
+ listeners.clear();
142
+ view?.removeEventListener("visibilitychange", onVisibility);
143
+ }
144
+ };
145
+ view?.addEventListener("visibilitychange", onVisibility);
146
+ return instance;
147
+ }
148
+
149
+ export { createNotifications };
@@ -0,0 +1,41 @@
1
+ import { createInput } from './chunk-KJINGUQN.js';
2
+ import { useRef, useState, useEffect, useLayoutEffect } from 'react';
3
+
4
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
5
+ function useInput(options = {}) {
6
+ const inputRef = useRef(null);
7
+ const actionsRef = useRef(null);
8
+ const instanceRef = useRef(null);
9
+ const optionsRef = useRef(options);
10
+ optionsRef.current = options;
11
+ const [revealed, setRevealed] = useState(false);
12
+ useIsomorphicLayoutEffect(() => {
13
+ const input = inputRef.current;
14
+ if (!input) return;
15
+ const instance = createInput(input, {
16
+ ...optionsRef.current,
17
+ container: actionsRef.current ?? optionsRef.current.container,
18
+ onRevealChange: (next) => {
19
+ setRevealed(next);
20
+ optionsRef.current.onRevealChange?.(next);
21
+ }
22
+ });
23
+ instanceRef.current = instance;
24
+ return () => {
25
+ instance.destroy();
26
+ instanceRef.current = null;
27
+ };
28
+ }, []);
29
+ useIsomorphicLayoutEffect(() => {
30
+ instanceRef.current?.update(options);
31
+ }, [options.reveal, options.actions, options.position]);
32
+ return {
33
+ inputRef,
34
+ actionsRef,
35
+ revealed,
36
+ reveal: (next) => instanceRef.current?.reveal(next),
37
+ refresh: () => instanceRef.current?.refresh()
38
+ };
39
+ }
40
+
41
+ export { useInput };
@@ -0,0 +1,309 @@
1
+ // src/core/marquee.ts
2
+ var DEFAULT_DECAY = 0.12;
3
+ var DRAG_THRESHOLD = 6;
4
+ var STILL_MS = 90;
5
+ var MAX_DT = 0.05;
6
+ var VELOCITY_SMOOTHING = 0.6;
7
+ var TOUCH_HOVER_SUPPRESS_MS = 1e3;
8
+ var IDLE_EPSILON = 0.01;
9
+ var DEFAULTS = {
10
+ speed: 60,
11
+ reverse: false,
12
+ vertical: false,
13
+ draggable: true,
14
+ hover: "off",
15
+ decay: DEFAULT_DECAY,
16
+ manageStyles: true,
17
+ copies: "clone"
18
+ };
19
+ var MAX_COPIES = 24;
20
+ function createMarquee(lane, track, options = {}) {
21
+ let opts = { ...DEFAULTS, ...options };
22
+ let period = 0;
23
+ let copyCount = Math.max(2, track.children.length);
24
+ let offset = 0;
25
+ let velocity = 0;
26
+ let running = false;
27
+ let paused = false;
28
+ let destroyed = false;
29
+ let frame = 0;
30
+ let lastTime = 0;
31
+ let dragging = false;
32
+ let pointerId = null;
33
+ let lastPointer = 0;
34
+ let startPointer = 0;
35
+ let lastMoveTime = 0;
36
+ let maxTravel = 0;
37
+ let hovering = false;
38
+ let lastTouchAt = 0;
39
+ const motionQuery = typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null;
40
+ let reducedMotion = motionQuery?.matches ?? false;
41
+ function hoverTarget(cruise) {
42
+ const hover = opts.hover ?? "off";
43
+ if (hover === "off") return cruise;
44
+ if (hover === "pause") return 0;
45
+ if (typeof hover === "number") return cruise * hover;
46
+ return (cruise < 0 ? -1 : 1) * Math.abs(hover.speed);
47
+ }
48
+ function target() {
49
+ if (reducedMotion || paused) return 0;
50
+ const cruise = opts.reverse ? -opts.speed : opts.speed;
51
+ return hovering ? hoverTarget(cruise) : cruise;
52
+ }
53
+ function axisSize(element) {
54
+ return opts.vertical ? element.offsetHeight : element.offsetWidth;
55
+ }
56
+ function axisStart(element) {
57
+ return opts.vertical ? element.offsetTop : element.offsetLeft;
58
+ }
59
+ function applyStyles() {
60
+ if (!opts.manageStyles) return;
61
+ lane.style.overflow = "hidden";
62
+ lane.style.touchAction = opts.vertical ? "pan-x" : "pan-y";
63
+ lane.style.userSelect = "none";
64
+ lane.style.webkitUserSelect = "none";
65
+ track.style.willChange = "transform";
66
+ }
67
+ function render() {
68
+ const x = opts.vertical ? 0 : -offset;
69
+ const y = opts.vertical ? -offset : 0;
70
+ track.style.transform = `translate3d(${x}px, ${y}px, 0)`;
71
+ }
72
+ function readPeriod() {
73
+ const first = track.children[0];
74
+ const second = track.children[1];
75
+ if (!first) return 0;
76
+ if (second) {
77
+ const step = axisStart(second) - axisStart(first);
78
+ if (step > 0) return step;
79
+ }
80
+ return axisSize(first);
81
+ }
82
+ function requiredCopies(measured) {
83
+ if (measured <= 0) return 2;
84
+ return Math.min(MAX_COPIES, Math.max(2, Math.ceil(axisSize(lane) / measured) + 1));
85
+ }
86
+ function syncClones(count) {
87
+ const source = track.children[0];
88
+ if (!source) return;
89
+ while (track.children.length > count) track.removeChild(track.lastElementChild);
90
+ while (track.children.length < count) {
91
+ const clone = source.cloneNode(true);
92
+ clone.setAttribute("aria-hidden", "true");
93
+ clone.dataset.enigmaMarqueeCopy = String(track.children.length);
94
+ track.appendChild(clone);
95
+ }
96
+ }
97
+ function measure() {
98
+ if (destroyed) return;
99
+ const cloning = opts.copies === "clone";
100
+ if (cloning && track.children.length < 2) syncClones(2);
101
+ let measured = readPeriod();
102
+ let needed = requiredCopies(measured);
103
+ if (cloning && track.children.length !== needed) {
104
+ syncClones(needed);
105
+ measured = readPeriod();
106
+ needed = requiredCopies(measured);
107
+ }
108
+ const changed = measured !== period || needed !== copyCount;
109
+ period = measured;
110
+ if (needed !== copyCount) {
111
+ copyCount = needed;
112
+ opts.onCopyCountChange?.(needed);
113
+ }
114
+ if (period > 0) offset = wrap(offset);
115
+ render();
116
+ if (changed) opts.onMeasure?.(period, copyCount);
117
+ start();
118
+ }
119
+ function wrap(value) {
120
+ if (period <= 0) return value;
121
+ return (value % period + period) % period;
122
+ }
123
+ function tick(now) {
124
+ frame = 0;
125
+ if (destroyed) return;
126
+ const dt = Math.min((now - lastTime) / 1e3, MAX_DT);
127
+ lastTime = now;
128
+ if (!dragging) {
129
+ velocity += (target() - velocity) * (1 - Math.pow(opts.decay, dt));
130
+ offset = wrap(offset + velocity * dt);
131
+ }
132
+ render();
133
+ const idle = !dragging && Math.abs(velocity) < IDLE_EPSILON && Math.abs(target()) < IDLE_EPSILON;
134
+ if (idle) {
135
+ velocity = 0;
136
+ running = false;
137
+ return;
138
+ }
139
+ frame = requestAnimationFrame(tick);
140
+ }
141
+ function start() {
142
+ if (destroyed || running) return;
143
+ running = true;
144
+ lastTime = performance.now();
145
+ frame = requestAnimationFrame(tick);
146
+ }
147
+ function pointerDelta(event) {
148
+ return opts.vertical ? event.clientY : event.clientX;
149
+ }
150
+ function onPointerDown(event) {
151
+ if (event.pointerType !== "mouse") noteTouch();
152
+ if (!opts.draggable || event.button > 0 || pointerId !== null) return;
153
+ pointerId = event.pointerId;
154
+ dragging = true;
155
+ lastPointer = pointerDelta(event);
156
+ startPointer = lastPointer;
157
+ lastMoveTime = event.timeStamp;
158
+ maxTravel = 0;
159
+ lane.dataset.dragging = "true";
160
+ window.addEventListener("pointermove", onPointerMove);
161
+ window.addEventListener("pointerup", onPointerUp);
162
+ window.addEventListener("pointercancel", onPointerUp);
163
+ start();
164
+ }
165
+ function onPointerMove(event) {
166
+ if (event.pointerId !== pointerId) return;
167
+ const position = pointerDelta(event);
168
+ const delta = position - lastPointer;
169
+ lastPointer = position;
170
+ const dt = Math.max((event.timeStamp - lastMoveTime) / 1e3, 1e-3);
171
+ lastMoveTime = event.timeStamp;
172
+ maxTravel = Math.max(maxTravel, Math.abs(position - startPointer));
173
+ offset = wrap(offset - delta);
174
+ const instant = -delta / dt;
175
+ velocity = velocity * VELOCITY_SMOOTHING + instant * (1 - VELOCITY_SMOOTHING);
176
+ }
177
+ function onPointerUp(event) {
178
+ if (event.pointerId !== pointerId) return;
179
+ pointerId = null;
180
+ dragging = false;
181
+ delete lane.dataset.dragging;
182
+ window.removeEventListener("pointermove", onPointerMove);
183
+ window.removeEventListener("pointerup", onPointerUp);
184
+ window.removeEventListener("pointercancel", onPointerUp);
185
+ if (event.timeStamp - lastMoveTime > STILL_MS) velocity = 0;
186
+ start();
187
+ }
188
+ function onClickCapture(event) {
189
+ if (maxTravel <= DRAG_THRESHOLD) return;
190
+ event.preventDefault();
191
+ event.stopPropagation();
192
+ }
193
+ function onClick(event) {
194
+ if (maxTravel > DRAG_THRESHOLD) return;
195
+ opts.onItemClick?.(event);
196
+ }
197
+ function onPointerEnter(event) {
198
+ if (event.pointerType !== "mouse") {
199
+ noteTouch();
200
+ return;
201
+ }
202
+ if (Date.now() - lastTouchAt < TOUCH_HOVER_SUPPRESS_MS) return;
203
+ hovering = true;
204
+ lane.dataset.hovering = "true";
205
+ start();
206
+ }
207
+ function onPointerLeave() {
208
+ hovering = false;
209
+ delete lane.dataset.hovering;
210
+ start();
211
+ }
212
+ function noteTouch() {
213
+ lastTouchAt = Date.now();
214
+ if (!hovering) return;
215
+ hovering = false;
216
+ delete lane.dataset.hovering;
217
+ start();
218
+ }
219
+ function onMotionChange(event) {
220
+ reducedMotion = event.matches;
221
+ lane.dataset.reducedMotion = String(reducedMotion);
222
+ start();
223
+ }
224
+ const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(() => measure()) : null;
225
+ function init() {
226
+ applyStyles();
227
+ lane.dataset.enigmaMarquee = "";
228
+ lane.dataset.reducedMotion = String(reducedMotion);
229
+ track.dataset.enigmaMarqueeTrack = "";
230
+ for (const child of Array.from(track.children)) {
231
+ child.dataset.enigmaMarqueeCopy ??= "0";
232
+ }
233
+ lane.addEventListener("pointerdown", onPointerDown);
234
+ lane.addEventListener("pointerenter", onPointerEnter);
235
+ lane.addEventListener("pointerleave", onPointerLeave);
236
+ lane.addEventListener("touchstart", noteTouch, { passive: true });
237
+ lane.addEventListener("click", onClickCapture, true);
238
+ lane.addEventListener("click", onClick);
239
+ motionQuery?.addEventListener("change", onMotionChange);
240
+ resizeObserver?.observe(lane);
241
+ const first = track.children[0];
242
+ if (first) resizeObserver?.observe(first);
243
+ measure();
244
+ void document.fonts?.ready.then(() => measure());
245
+ remeasureOnImageLoad();
246
+ }
247
+ function remeasureOnImageLoad() {
248
+ for (const image of track.querySelectorAll("img")) {
249
+ if (image.complete) continue;
250
+ const done = () => {
251
+ image.removeEventListener("load", done);
252
+ image.removeEventListener("error", done);
253
+ if (!destroyed) measure();
254
+ };
255
+ image.addEventListener("load", done);
256
+ image.addEventListener("error", done);
257
+ }
258
+ }
259
+ init();
260
+ return {
261
+ get offset() {
262
+ return offset;
263
+ },
264
+ get period() {
265
+ return period;
266
+ },
267
+ get copyCount() {
268
+ return copyCount;
269
+ },
270
+ get dragging() {
271
+ return dragging;
272
+ },
273
+ get reducedMotion() {
274
+ return reducedMotion;
275
+ },
276
+ update(next) {
277
+ const styleKeys = next.vertical !== void 0 || next.manageStyles !== void 0;
278
+ opts = { ...opts, ...next };
279
+ if (styleKeys) applyStyles();
280
+ measure();
281
+ },
282
+ measure,
283
+ pause() {
284
+ paused = true;
285
+ start();
286
+ },
287
+ resume() {
288
+ paused = false;
289
+ start();
290
+ },
291
+ destroy() {
292
+ destroyed = true;
293
+ if (frame) cancelAnimationFrame(frame);
294
+ resizeObserver?.disconnect();
295
+ motionQuery?.removeEventListener("change", onMotionChange);
296
+ lane.removeEventListener("pointerdown", onPointerDown);
297
+ lane.removeEventListener("pointerenter", onPointerEnter);
298
+ lane.removeEventListener("pointerleave", onPointerLeave);
299
+ lane.removeEventListener("touchstart", noteTouch);
300
+ lane.removeEventListener("click", onClickCapture, true);
301
+ lane.removeEventListener("click", onClick);
302
+ window.removeEventListener("pointermove", onPointerMove);
303
+ window.removeEventListener("pointerup", onPointerUp);
304
+ window.removeEventListener("pointercancel", onPointerUp);
305
+ }
306
+ };
307
+ }
308
+
309
+ export { createMarquee };
@@ -0,0 +1,47 @@
1
+ import { createSearch } from './chunk-UZFEEFMF.js';
2
+ import { useRef, useState, useMemo, useEffect } from 'react';
3
+
4
+ function useSearch(options = {}) {
5
+ const inputRef = useRef(null);
6
+ const instanceRef = useRef(null);
7
+ const optionsRef = useRef(options);
8
+ optionsRef.current = options;
9
+ const [query, setQuery] = useState("");
10
+ const [results, setResults] = useState([]);
11
+ const instance = useMemo(() => {
12
+ const created = createSearch({
13
+ ...optionsRef.current,
14
+ onResults: (next, nextQuery) => {
15
+ setResults(next);
16
+ setQuery(nextQuery);
17
+ optionsRef.current.onResults?.(next, nextQuery);
18
+ }
19
+ });
20
+ instanceRef.current = created;
21
+ return created;
22
+ }, []);
23
+ useEffect(() => () => instance.destroy(), [instance]);
24
+ useEffect(() => {
25
+ instance.setItems(options.items ?? []);
26
+ }, [instance, options.items]);
27
+ useEffect(() => {
28
+ const input = inputRef.current;
29
+ if (!input) return;
30
+ return instance.attach(input);
31
+ }, [instance]);
32
+ return {
33
+ inputRef,
34
+ query,
35
+ results,
36
+ search: (next) => instance.search(next),
37
+ searchNow: (next) => {
38
+ instance.searchNow(next);
39
+ },
40
+ clear: () => {
41
+ if (inputRef.current) inputRef.current.value = "";
42
+ instance.searchNow("");
43
+ }
44
+ };
45
+ }
46
+
47
+ export { useSearch };
@@ -0,0 +1,31 @@
1
+ import { flagView } from './chunk-AU3H5WIY.js';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ function Flag({ code, label, decorative = false, locale, shape, format, source, basePath, size, fallback = null, ...rest }) {
5
+ const options = { shape, format, source, basePath, size, locale };
6
+ for (const key of Object.keys(options)) {
7
+ if (options[key] === void 0) delete options[key];
8
+ }
9
+ const view = flagView(code, options);
10
+ if (!view) return fallback;
11
+ const name = decorative ? "" : label?.trim() || view.name || "";
12
+ return /* @__PURE__ */ jsx(
13
+ "img",
14
+ {
15
+ src: view.src,
16
+ alt: name,
17
+ width: view.width,
18
+ height: view.height,
19
+ loading: "lazy",
20
+ decoding: "async",
21
+ "aria-hidden": name ? void 0 : true,
22
+ suppressHydrationWarning: true,
23
+ "data-enigma-flag": "",
24
+ "data-flag-code": view.code,
25
+ "data-flag-shape": view.shape,
26
+ ...rest
27
+ }
28
+ );
29
+ }
30
+
31
+ export { Flag };