@enigmax/primitives 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.
Files changed (79) hide show
  1. package/dist/{chunk-QQFNAKMY.js → chunk-45UHLZYT.js} +1 -1
  2. package/dist/chunk-4VUHQFAT.js +130 -0
  3. package/dist/{chunk-D5A2ZMAG.js → chunk-4ZPMP47J.js} +6 -1
  4. package/dist/chunk-DZMHY3SU.js +777 -0
  5. package/dist/{chunk-FWVWX67R.js → chunk-FGBIZDV2.js} +3 -3
  6. package/dist/chunk-N6PDHMAX.js +213 -0
  7. package/dist/chunk-NONGREXC.js +248 -0
  8. package/dist/{chunk-R4ZAEE7V.js → chunk-QJJ34E4G.js} +34 -10
  9. package/dist/chunk-S2FPN5ID.js +115 -0
  10. package/dist/chunk-S7EE57YB.js +9 -0
  11. package/dist/chunk-VKL3DEIQ.js +804 -0
  12. package/dist/chunk-WSQC3PCC.js +466 -0
  13. package/dist/chunk-Z3VDE7OA.js +532 -0
  14. package/dist/clipboard-menu-B_ouitfS.d.ts +264 -0
  15. package/dist/color-D_rZ83Oc.d.ts +152 -0
  16. package/dist/color-OPV3BJV6.js +452 -0
  17. package/dist/{index-BHpOZncw.d.ts → index-ZPvlf9vs.d.ts} +53 -5
  18. package/dist/index.d.ts +6 -2
  19. package/dist/index.js +9 -4
  20. package/dist/keys-D2zJs1uB.d.ts +100 -0
  21. package/dist/next/index.d.ts +10 -3
  22. package/dist/next/index.js +22 -13
  23. package/dist/react/context-menu.d.ts +219 -0
  24. package/dist/react/context-menu.js +6 -0
  25. package/dist/react/index.d.ts +12 -5
  26. package/dist/react/index.js +21 -12
  27. package/dist/react/input.d.ts +3 -3
  28. package/dist/react/input.js +2 -1
  29. package/dist/react/palette.d.ts +1 -1
  30. package/dist/react/palette.js +3 -3
  31. package/dist/react/search.d.ts +1 -1
  32. package/dist/react/search.js +2 -2
  33. package/dist/react/select.d.ts +217 -0
  34. package/dist/react/select.js +7 -0
  35. package/dist/react/selection.d.ts +104 -0
  36. package/dist/react/selection.js +4 -0
  37. package/dist/react-router/index.d.ts +10 -3
  38. package/dist/react-router/index.js +22 -13
  39. package/dist/search/index.d.ts +2 -2
  40. package/dist/search/index.js +1 -1
  41. package/dist/{search-BD9-5O5U.d.ts → search-DYgqRp37.d.ts} +13 -1
  42. package/dist/{search-UQEXAPQB.js → search-PBZORZ7P.js} +1 -1
  43. package/dist/select-ClSy-J1f.d.ts +100 -0
  44. package/dist/selection-B_pmzHpy.d.ts +150 -0
  45. package/package.json +23 -2
  46. package/recipes/color/styles.css +143 -0
  47. package/recipes/context-menu/styles.css +185 -0
  48. package/recipes/input/styles.css +9 -0
  49. package/recipes/palette/styles.css +3 -0
  50. package/recipes/search/tailwind.tsx +3 -2
  51. package/recipes/select/styles.css +230 -0
  52. package/recipes/toast/styles.css +1 -1
  53. package/registry.json +432 -5
  54. package/src/core/clipboard-menu.ts +270 -0
  55. package/src/core/color.ts +248 -0
  56. package/src/core/context-menu.ts +694 -0
  57. package/src/core/keys.ts +264 -0
  58. package/src/core/search.ts +19 -0
  59. package/src/core/select.ts +404 -0
  60. package/src/core/selection.ts +648 -0
  61. package/src/index.ts +92 -1
  62. package/src/react/context-menu/context.ts +64 -0
  63. package/src/react/context-menu/index.tsx +108 -0
  64. package/src/react/context-menu/root.tsx +970 -0
  65. package/src/react/context-menu/styles.ts +194 -0
  66. package/src/react/index.ts +100 -1
  67. package/src/react/input/color-styles.ts +156 -0
  68. package/src/react/input/color.tsx +466 -0
  69. package/src/react/input/index.tsx +54 -6
  70. package/src/react/input/types.ts +59 -3
  71. package/src/react/palette/root.tsx +2 -2
  72. package/src/react/select/context.ts +56 -0
  73. package/src/react/select/index.tsx +96 -0
  74. package/src/react/select/root.tsx +839 -0
  75. package/src/react/select/styles.ts +238 -0
  76. package/src/react/selection/index.tsx +115 -0
  77. package/src/react/selection/use-selection.ts +260 -0
  78. package/dist/password-C8lG4Zm9.d.ts +0 -71
  79. /package/dist/{chunk-U3V4EHOB.js → chunk-MSOCCQGH.js} +0 -0
@@ -0,0 +1,466 @@
1
+ import { shortcutList, matchesShortcut } from './chunk-4VUHQFAT.js';
2
+
3
+ // src/core/selection.ts
4
+ var DEFAULT_SELECTION_SHORTCUTS = {
5
+ selectAll: "Mod+A",
6
+ clear: "Escape",
7
+ invert: false,
8
+ moveUp: "ArrowUp",
9
+ moveDown: "ArrowDown",
10
+ moveLeft: "ArrowLeft",
11
+ moveRight: "ArrowRight",
12
+ moveHome: "Home",
13
+ moveEnd: "End",
14
+ movePageUp: "PageUp",
15
+ movePageDown: "PageDown",
16
+ extendUp: "Shift+ArrowUp",
17
+ extendDown: "Shift+ArrowDown",
18
+ extendLeft: "Shift+ArrowLeft",
19
+ extendRight: "Shift+ArrowRight",
20
+ extendHome: "Shift+Home",
21
+ extendEnd: "Shift+End",
22
+ extendPageUp: "Shift+PageUp",
23
+ extendPageDown: "Shift+PageDown",
24
+ // The cursor moving WITHOUT the selection following, which is how a file manager lets you
25
+ // reach a distant row and add it with Ctrl+Space rather than starting again.
26
+ cursorUp: "Mod+ArrowUp",
27
+ cursorDown: "Mod+ArrowDown",
28
+ toggleCursor: "Mod+Space",
29
+ open: "Enter",
30
+ rename: "F2",
31
+ delete: "Delete",
32
+ deletePermanent: "Shift+Delete",
33
+ copy: "Mod+C",
34
+ cut: "Mod+X",
35
+ paste: "Mod+V"
36
+ };
37
+ var OWNED = /* @__PURE__ */ new Set([
38
+ "selectAll",
39
+ "clear",
40
+ "invert",
41
+ "moveUp",
42
+ "moveDown",
43
+ "moveLeft",
44
+ "moveRight",
45
+ "moveHome",
46
+ "moveEnd",
47
+ "movePageUp",
48
+ "movePageDown",
49
+ "extendUp",
50
+ "extendDown",
51
+ "extendLeft",
52
+ "extendRight",
53
+ "extendHome",
54
+ "extendEnd",
55
+ "extendPageUp",
56
+ "extendPageDown",
57
+ "cursorUp",
58
+ "cursorDown",
59
+ "toggleCursor"
60
+ ]);
61
+ function createSelection(options = {}) {
62
+ let opts = { ...options };
63
+ let items = opts.items ?? [];
64
+ let selected = /* @__PURE__ */ new Set();
65
+ let cursor = -1;
66
+ let anchor = -1;
67
+ let rangeBase = null;
68
+ let marqueeBase = null;
69
+ let destroyed = false;
70
+ const listeners = /* @__PURE__ */ new Set();
71
+ function idOf(index) {
72
+ const item = items[index];
73
+ if (item === void 0) return null;
74
+ return opts.getId ? opts.getId(item, index) : String(index);
75
+ }
76
+ function selectable(index) {
77
+ const item = items[index];
78
+ if (item === void 0) return false;
79
+ return !opts.disabled?.(item, index);
80
+ }
81
+ function multiple() {
82
+ return opts.multiple ?? true;
83
+ }
84
+ function columns() {
85
+ return Math.max(1, opts.columns ?? 1);
86
+ }
87
+ function orderedIds() {
88
+ const ids = [];
89
+ for (let index = 0; index < items.length; index++) {
90
+ const id = idOf(index);
91
+ if (id !== null && selected.has(id)) ids.push(id);
92
+ }
93
+ return ids;
94
+ }
95
+ function selectedItems() {
96
+ const chosen = [];
97
+ for (let index = 0; index < items.length; index++) {
98
+ const id = idOf(index);
99
+ if (id !== null && selected.has(id)) chosen.push(items[index]);
100
+ }
101
+ return chosen;
102
+ }
103
+ function snapshot() {
104
+ const ids = orderedIds();
105
+ let count = 0;
106
+ for (let index = 0; index < items.length; index++) if (selectable(index)) count++;
107
+ return {
108
+ selected: ids,
109
+ selectedSet: new Set(ids),
110
+ items: selectedItems(),
111
+ cursor,
112
+ anchor,
113
+ count: ids.length,
114
+ allSelected: count > 0 && ids.length === count,
115
+ partiallySelected: ids.length > 0 && ids.length < count,
116
+ marquee: marqueeBase !== null
117
+ };
118
+ }
119
+ function summary() {
120
+ let count = 0;
121
+ for (let index = 0; index < items.length; index++) if (selectable(index)) count++;
122
+ return `${cursor}:${anchor}:${count}:${orderedIds().join("\0")}`;
123
+ }
124
+ let reported = [];
125
+ function emit() {
126
+ const state = snapshot();
127
+ opts.onChange?.(state);
128
+ for (const listener of listeners) listener(state);
129
+ const ids = state.selected;
130
+ if (ids.length !== reported.length || ids.some((id, index) => id !== reported[index])) {
131
+ reported = ids;
132
+ opts.onSelectionChange?.(ids, state.items);
133
+ }
134
+ }
135
+ function replace(ids) {
136
+ selected = new Set(ids);
137
+ }
138
+ function nextEnabled(from, step) {
139
+ for (let index = from; index >= 0 && index < items.length; index += step) {
140
+ if (selectable(index)) return index;
141
+ }
142
+ return -1;
143
+ }
144
+ function rangeIds(from, to) {
145
+ const [low, high] = from < to ? [from, to] : [to, from];
146
+ const ids = [];
147
+ for (let index = low; index <= high; index++) {
148
+ if (!selectable(index)) continue;
149
+ const id = idOf(index);
150
+ if (id !== null) ids.push(id);
151
+ }
152
+ return ids;
153
+ }
154
+ function applyRange(index, additive) {
155
+ const from = anchor >= 0 ? anchor : index;
156
+ const ids = rangeIds(from, index);
157
+ if (additive) {
158
+ rangeBase = rangeBase ?? new Set(selected);
159
+ replace([...rangeBase, ...ids]);
160
+ } else {
161
+ rangeBase = null;
162
+ replace(ids);
163
+ }
164
+ cursor = index;
165
+ }
166
+ function table() {
167
+ if (opts.shortcuts === false) return {};
168
+ return { ...DEFAULT_SELECTION_SHORTCUTS, ...opts.shortcuts ?? {} };
169
+ }
170
+ function commandFor(event) {
171
+ const bindings = table();
172
+ let match = null;
173
+ for (const [command, spec] of Object.entries(bindings)) {
174
+ if (spec === false || spec == null) continue;
175
+ const hit = shortcutList(spec).find((shortcut) => matchesShortcut(event, shortcut));
176
+ if (!hit) continue;
177
+ const length = specificity(hit);
178
+ if (!match || length > match.length) match = { command, length };
179
+ }
180
+ return match?.command ?? null;
181
+ }
182
+ function specificity(shortcut) {
183
+ return Number(Boolean(shortcut.mod)) + Number(Boolean(shortcut.ctrl)) + Number(Boolean(shortcut.meta)) + Number(Boolean(shortcut.shift)) + Number(Boolean(shortcut.alt));
184
+ }
185
+ function perform(command) {
186
+ const step = columns();
187
+ const page = Math.max(1, opts.page ?? 10);
188
+ switch (command) {
189
+ case "selectAll":
190
+ instance.selectAll();
191
+ return true;
192
+ case "clear":
193
+ instance.clear();
194
+ return true;
195
+ case "invert":
196
+ instance.invert();
197
+ return true;
198
+ case "moveUp":
199
+ instance.moveCursor(-step);
200
+ return true;
201
+ case "moveDown":
202
+ instance.moveCursor(step);
203
+ return true;
204
+ case "moveLeft":
205
+ instance.moveCursor(-1);
206
+ return true;
207
+ case "moveRight":
208
+ instance.moveCursor(1);
209
+ return true;
210
+ case "moveHome":
211
+ instance.moveCursor(-items.length);
212
+ return true;
213
+ case "moveEnd":
214
+ instance.moveCursor(items.length);
215
+ return true;
216
+ case "movePageUp":
217
+ instance.moveCursor(-page * step);
218
+ return true;
219
+ case "movePageDown":
220
+ instance.moveCursor(page * step);
221
+ return true;
222
+ case "extendUp":
223
+ instance.moveCursor(-step, true);
224
+ return true;
225
+ case "extendDown":
226
+ instance.moveCursor(step, true);
227
+ return true;
228
+ case "extendLeft":
229
+ instance.moveCursor(-1, true);
230
+ return true;
231
+ case "extendRight":
232
+ instance.moveCursor(1, true);
233
+ return true;
234
+ case "extendHome":
235
+ instance.moveCursor(-items.length, true);
236
+ return true;
237
+ case "extendEnd":
238
+ instance.moveCursor(items.length, true);
239
+ return true;
240
+ case "extendPageUp":
241
+ instance.moveCursor(-page * step, true);
242
+ return true;
243
+ case "extendPageDown":
244
+ instance.moveCursor(page * step, true);
245
+ return true;
246
+ case "cursorUp":
247
+ instance.moveCursor(-step, false, true);
248
+ return true;
249
+ case "cursorDown":
250
+ instance.moveCursor(step, false, true);
251
+ return true;
252
+ case "toggleCursor":
253
+ if (cursor >= 0) instance.toggle(cursor);
254
+ return true;
255
+ default:
256
+ return false;
257
+ }
258
+ }
259
+ const instance = {
260
+ get state() {
261
+ return snapshot();
262
+ },
263
+ click(index, modifiers = {}) {
264
+ if (destroyed || !selectable(index)) return;
265
+ const mod = Boolean(modifiers.ctrlKey || modifiers.metaKey);
266
+ const shift = Boolean(modifiers.shiftKey) && multiple();
267
+ if (shift) {
268
+ applyRange(index, mod && multiple());
269
+ emit();
270
+ return;
271
+ }
272
+ rangeBase = null;
273
+ if (mod && multiple()) {
274
+ this.toggle(index);
275
+ return;
276
+ }
277
+ const id = idOf(index);
278
+ if (id === null) return;
279
+ replace([id]);
280
+ cursor = index;
281
+ anchor = index;
282
+ emit();
283
+ },
284
+ keyDown(event) {
285
+ if (destroyed) return false;
286
+ const command = commandFor(event);
287
+ if (!command) return false;
288
+ const targets = selected.size > 0 ? selectedItems() : cursor >= 0 && items[cursor] !== void 0 ? [items[cursor]] : [];
289
+ const ids = selected.size > 0 ? orderedIds() : cursor >= 0 ? [idOf(cursor)].filter((id) => id !== null) : [];
290
+ let prevented = false;
291
+ const report = {
292
+ command,
293
+ items: targets,
294
+ ids,
295
+ cursor: cursor >= 0 ? items[cursor] ?? null : null,
296
+ cursorIndex: cursor,
297
+ event,
298
+ preventDefault() {
299
+ prevented = true;
300
+ report.defaultPrevented = true;
301
+ },
302
+ defaultPrevented: false
303
+ };
304
+ opts.onCommand?.(report);
305
+ if (!prevented) perform(command);
306
+ return OWNED.has(command) || opts.onCommand !== void 0;
307
+ },
308
+ select(ids) {
309
+ if (destroyed) return;
310
+ replace(ids);
311
+ emit();
312
+ },
313
+ selectIndex(index, additive = false) {
314
+ if (destroyed || !selectable(index)) return;
315
+ const id = idOf(index);
316
+ if (id === null) return;
317
+ if (additive && multiple()) selected.add(id);
318
+ else replace([id]);
319
+ cursor = index;
320
+ anchor = index;
321
+ emit();
322
+ },
323
+ toggle(index) {
324
+ if (destroyed || !selectable(index)) return;
325
+ const id = idOf(index);
326
+ if (id === null) return;
327
+ if (!multiple()) {
328
+ replace([id]);
329
+ } else if (selected.has(id)) selected.delete(id);
330
+ else selected.add(id);
331
+ cursor = index;
332
+ anchor = index;
333
+ emit();
334
+ },
335
+ selectRange(index, additive = false) {
336
+ if (destroyed || !selectable(index) || !multiple()) return;
337
+ applyRange(index, additive);
338
+ emit();
339
+ },
340
+ selectAll() {
341
+ if (destroyed || !multiple()) return;
342
+ const ids = [];
343
+ for (let index = 0; index < items.length; index++) {
344
+ if (!selectable(index)) continue;
345
+ const id = idOf(index);
346
+ if (id !== null) ids.push(id);
347
+ }
348
+ replace(ids);
349
+ emit();
350
+ },
351
+ clear() {
352
+ if (destroyed || selected.size === 0) return;
353
+ selected = /* @__PURE__ */ new Set();
354
+ rangeBase = null;
355
+ emit();
356
+ },
357
+ invert() {
358
+ if (destroyed || !multiple()) return;
359
+ const next = /* @__PURE__ */ new Set();
360
+ for (let index = 0; index < items.length; index++) {
361
+ if (!selectable(index)) continue;
362
+ const id = idOf(index);
363
+ if (id !== null && !selected.has(id)) next.add(id);
364
+ }
365
+ selected = next;
366
+ emit();
367
+ },
368
+ moveCursor(delta, extend = false, carry = false) {
369
+ if (destroyed || items.length === 0) return;
370
+ const from = cursor >= 0 ? cursor : anchor >= 0 ? anchor : delta > 0 ? -1 : items.length;
371
+ const wanted = Math.max(0, Math.min(items.length - 1, from + delta));
372
+ const forward = delta >= 0 ? 1 : -1;
373
+ const ahead = nextEnabled(wanted, forward);
374
+ const next = ahead >= 0 ? ahead : nextEnabled(wanted, -forward);
375
+ if (next < 0) return;
376
+ if (extend && multiple()) {
377
+ applyRange(next, false);
378
+ emit();
379
+ return;
380
+ }
381
+ cursor = next;
382
+ if (carry) {
383
+ emit();
384
+ return;
385
+ }
386
+ const id = idOf(next);
387
+ if (id === null) return;
388
+ replace([id]);
389
+ anchor = next;
390
+ rangeBase = null;
391
+ emit();
392
+ },
393
+ setCursor(index) {
394
+ if (destroyed || index === cursor) return;
395
+ if (index < -1 || index >= items.length) return;
396
+ cursor = index;
397
+ emit();
398
+ },
399
+ targets(index) {
400
+ const id = idOf(index);
401
+ const item = items[index];
402
+ if (item === void 0) return selectedItems();
403
+ return id !== null && selected.has(id) ? selectedItems() : [item];
404
+ },
405
+ beginMarquee(additive = false) {
406
+ if (destroyed || !multiple()) return;
407
+ marqueeBase = additive ? new Set(selected) : /* @__PURE__ */ new Set();
408
+ if (!additive && selected.size > 0) selected = /* @__PURE__ */ new Set();
409
+ emit();
410
+ },
411
+ marqueeTo(indices) {
412
+ if (destroyed || marqueeBase === null) return;
413
+ const next = new Set(marqueeBase);
414
+ for (const index of indices) {
415
+ if (!selectable(index)) continue;
416
+ const id = idOf(index);
417
+ if (id !== null) next.add(id);
418
+ }
419
+ if (next.size === selected.size && [...next].every((id) => selected.has(id))) return;
420
+ selected = next;
421
+ emit();
422
+ },
423
+ endMarquee() {
424
+ if (destroyed || marqueeBase === null) return;
425
+ marqueeBase = null;
426
+ emit();
427
+ },
428
+ bindings() {
429
+ return table();
430
+ },
431
+ binding(command) {
432
+ return table()[command] ?? false;
433
+ },
434
+ update(next) {
435
+ if (destroyed) return;
436
+ const before = summary();
437
+ const hadItems = next.items !== void 0;
438
+ opts = { ...opts, ...next };
439
+ if (hadItems) {
440
+ items = next.items ?? [];
441
+ const live = /* @__PURE__ */ new Set();
442
+ for (let index = 0; index < items.length; index++) {
443
+ const id = idOf(index);
444
+ if (id !== null) live.add(id);
445
+ }
446
+ for (const id of selected) if (!live.has(id)) selected.delete(id);
447
+ if (cursor >= items.length) cursor = items.length - 1;
448
+ if (anchor >= items.length) anchor = items.length - 1;
449
+ }
450
+ if (summary() !== before) emit();
451
+ },
452
+ subscribe(listener) {
453
+ listeners.add(listener);
454
+ return () => {
455
+ listeners.delete(listener);
456
+ };
457
+ },
458
+ destroy() {
459
+ destroyed = true;
460
+ listeners.clear();
461
+ }
462
+ };
463
+ return instance;
464
+ }
465
+
466
+ export { DEFAULT_SELECTION_SHORTCUTS, createSelection };