@threadlabs/looma 0.13.4 → 0.13.6

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.
@@ -16,9 +16,15 @@
16
16
  this value.</prop>
17
17
  <prop name="items" type="list(object({ id: string, value: string, label: string, group?: string, disabled?: boolean }))"
18
18
  >The selected items in multiple mode, as JSON; a named combobox submits each one's value. A form reset returns to these items, or to none when unset.</prop>
19
+ <prop name="selectedValues" type="list(string)"
20
+ >The selected option values in multiple mode, when the consumer controls the selection. Once set, the consumer owns it: each value shows as a badge with its
21
+ authored option's label, adding or removing one reports selected-values-change with the new list, and the badges follow selectedValues, not the user,
22
+ unless it is updated to match. Setting it reports nothing. It takes precedence over items; leave it unset to let the combobox keep its own
23
+ selection.</prop>
19
24
  <prop name="multiple" type="boolean" default="false"
20
25
  >Lets the user choose several options. Each choice becomes a removable badge before the input, the list stays open between picks, and choosing a checked
21
- option removes it. value-change then reports the whole list of items; use items, not value, in this mode.</prop>
26
+ option removes it. value-change then reports the whole list of items, and selected-values-change the list of their values; use selectedValues or items,
27
+ not value, in this mode.</prop>
22
28
  <prop name="tokenSeparators" type="list(string)"
23
29
  >Keys that commit the typed text in multiple mode, as KeyboardEvent key values such as "," or ";". The text is added as the option whose label matches it,
24
30
  ignoring case, or with allowCreate is reported as create-item; otherwise it stays in the input.</prop>
@@ -110,6 +116,7 @@
110
116
  type="object({ item: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }), index: integer, trigger: keyboard | pointer | programmatic })"
111
117
  ></event>
112
118
  <event name="create-item" type="object({ query: string, trigger: keyboard | pointer | programmatic })"></event>
119
+ <event name="selected-values-change" type="object({ selectedValues: list(string), trigger: keyboard | pointer | programmatic })"></event>
113
120
  <method name="validate" export="validate" returns="promise(unknown)"></method>
114
121
  <method name="focusInput" export="focusInput" returns="promise(undefined)"></method>
115
122
  </defs>
@@ -50,9 +50,32 @@ export default function controller(host) {
50
50
  allowCreate: Boolean(host.state.allowCreate),
51
51
  });
52
52
  // Selected items work uncontrolled: the component keeps them and reports every change. A consumer
53
- // that owns `items` stays in charge, because the prop resyncs whatever it sets.
53
+ // that owns `items` stays in charge, because the prop resyncs whatever it sets. A consumer that sets
54
+ // `selectedValues` controls the selection: the chips follow it, and a user's change is only reported.
54
55
  const items = () => host.state.multiple && Array.isArray(host.state.internalItems) ? host.state.internalItems : [];
55
- const selectedValues = () => new Set(items().map((item) => item.value));
56
+ const selectedSet = () => new Set(items().map((item) => item.value));
57
+ const controlledValues = () => Array.isArray(host.state.selectedValues);
58
+ // Each controlled value shows its authored option; a value no option describes yet keeps the chip it
59
+ // had, or shows the value itself until its option arrives. A repeated value shows once: the chips and
60
+ // hidden inputs are keyed by value. Array.from, not a spread: a loose transpile turns [...set] into [set].
61
+ const itemsForValues = () => {
62
+ const options = config().options;
63
+ return Array.from(new Set(host.state.selectedValues)).map((value) => asItem(options.find((option) => option.value === value)
64
+ ?? items().find((item) => item.value === value) ?? { id: value, value, label: value }));
65
+ };
66
+ const markSelectedRows = () => {
67
+ if (!host.state.multiple || !host.state.rows?.length) return;
68
+ const selected = selectedSet();
69
+ host.state.rows = host.state.rows.map((row) => ({ ...row, selected: selected.has(row.value) }));
70
+ };
71
+ const syncValues = () => {
72
+ if (!controlledValues()) return;
73
+ const next = itemsForValues();
74
+ // An equal selection (a re-rendered literal, an unrelated option edit) leaves the chips alone.
75
+ if (JSON.stringify(next) === JSON.stringify(items())) return;
76
+ host.state.internalItems = next;
77
+ markSelectedRows();
78
+ };
56
79
  const setValidation = (result, touched = host.state.validation?.touched ?? false) => {
57
80
  const issues = result.issues ?? [];
58
81
  const blocking = issues.some((issue) => issue.severity !== "warning");
@@ -113,7 +136,7 @@ export default function controller(host) {
113
136
  resetValidation();
114
137
  }
115
138
  const ids = new Set();
116
- const selected = host.state.multiple ? selectedValues() : undefined;
139
+ const selected = host.state.multiple ? selectedSet() : undefined;
117
140
  // Multiple keeps its chosen options in the list, checked. Dropping them hid what was picked
118
141
  // from the list and from assistive technology, which only ever heard aria-selected="false".
119
142
  const filtered = options.filter((option) => {
@@ -179,9 +202,12 @@ export default function controller(host) {
179
202
  proposedChange = undefined;
180
203
  });
181
204
  };
182
- const emitItems = (next) => {
183
- host.state.internalItems = next;
205
+ const emitItems = (next, trigger) => {
206
+ if (!controlledValues()) host.state.internalItems = next;
184
207
  host.dispatch("value-change", next);
208
+ // Not `values`: Vue's adapter reads a modeled prop with `in`, and every list-shaped detail (this
209
+ // value-change, options-change) has Array.prototype.values, so it would emit update:values wrongly.
210
+ host.dispatch("selected-values-change", { selectedValues: next.map((item) => item.value), trigger });
185
211
  };
186
212
  const setMultiQuery = (query, trigger) => {
187
213
  if (host.state.query === undefined) {
@@ -203,7 +229,7 @@ export default function controller(host) {
203
229
  const option = asItem(row);
204
230
  const current = items();
205
231
  host.dispatch("add-item", { item: option, index: current.length, trigger });
206
- emitItems([...current, option]);
232
+ emitItems([...current, option], trigger);
207
233
  };
208
234
  const createSelectedItem = (query, trigger) => { if (query) host.dispatch("create-item", { query, trigger }); };
209
235
  const choose = (index, trigger) => {
@@ -261,7 +287,8 @@ export default function controller(host) {
261
287
  const query = String(host.state.raw).trim();
262
288
  if (!query) return;
263
289
  const option = (host.state.rows ?? []).find((row) => row.label.trim().toLocaleLowerCase() === query.toLocaleLowerCase());
264
- if (option) { setMultiQuery("", trigger); addSelectedItem(option, trigger); }
290
+ // Typing a label already chosen just clears the text; adding it again would duplicate the chip.
291
+ if (option) { setMultiQuery("", trigger); if (!selectedSet().has(option.value)) addSelectedItem(option, trigger); }
265
292
  else if (config().allowCreate) { setMultiQuery("", trigger); createSelectedItem(query, trigger); }
266
293
  };
267
294
  const itemButtons = () => Array.from(field.querySelectorAll(".item"));
@@ -270,7 +297,7 @@ export default function controller(host) {
270
297
  const item = current[index];
271
298
  if (!item || item.disabled || host.state.disabled || host.state.readonly) return;
272
299
  host.dispatch("remove-item", { item, index, trigger });
273
- emitItems(current.filter((_, position) => position !== index));
300
+ emitItems(current.filter((_, position) => position !== index), trigger);
274
301
  requestAnimationFrame(() => itemButtons()[Math.min(index, itemButtons().length - 1)]?.focus?.() ?? input.focus());
275
302
  };
276
303
  const move = (key) => {
@@ -457,7 +484,7 @@ export default function controller(host) {
457
484
  const stopReset = afterFormReset(input, () => {
458
485
  close();
459
486
  lastSelection = null;
460
- host.state.internalItems = Array.isArray(host.state.items) ? host.state.items : [];
487
+ host.state.internalItems = controlledValues() ? itemsForValues() : Array.isArray(host.state.items) ? host.state.items : [];
461
488
  applyDefaults();
462
489
  input.value = host.state.display;
463
490
  resetValidation();
@@ -468,6 +495,8 @@ export default function controller(host) {
468
495
  let lastOptionsKey = optionsKey();
469
496
  const observer = new MutationObserver(() => {
470
497
  relabel();
498
+ // Controlled chips show their options' current labels, including options that arrive late.
499
+ if (host.state.multiple) syncValues();
471
500
  const key = optionsKey();
472
501
  if (key === lastOptionsKey) return;
473
502
  lastOptionsKey = key;
@@ -475,19 +504,19 @@ export default function controller(host) {
475
504
  });
476
505
  observer.observe(authored, { childList: true, subtree: true, characterData: true, attributes: true });
477
506
  let lastItems = host.state.items;
478
- if (Array.isArray(lastItems)) host.state.internalItems = lastItems;
507
+ let lastSelectedValues = host.state.selectedValues;
508
+ if (controlledValues()) host.state.internalItems = itemsForValues();
509
+ else if (Array.isArray(lastItems)) host.state.internalItems = lastItems;
479
510
  const stop = host.effect(() => {
480
- // A consumer that sets `items` owns them; otherwise the component keeps its own.
511
+ // A consumer that sets `items` owns them; otherwise the component keeps its own. selectedValues wins.
481
512
  if (host.state.items !== lastItems) {
482
513
  lastItems = host.state.items;
483
- if (Array.isArray(lastItems)) host.state.internalItems = lastItems;
514
+ if (Array.isArray(lastItems) && !controlledValues()) host.state.internalItems = lastItems;
484
515
  // The list shows the selection; a consumer that adds or removes an item later (after creating
485
516
  // it, say) is reflected at once rather than at the next search.
486
- if (host.state.multiple && host.state.rows?.length) {
487
- const selected = selectedValues();
488
- host.state.rows = host.state.rows.map((row) => ({ ...row, selected: selected.has(row.value) }));
489
- }
517
+ markSelectedRows();
490
518
  }
519
+ if (host.state.selectedValues !== lastSelectedValues) { lastSelectedValues = host.state.selectedValues; syncValues(); }
491
520
  if (host.state.value !== lastValue) { lastValue = host.state.value; syncValue(); }
492
521
  if (host.state.query !== lastQuery) { lastQuery = host.state.query; syncQuery(); }
493
522
  if (host.state.disabled || host.state.readonly) close();
@@ -1,21 +1,81 @@
1
- <template component="ui-icon" controller="./ui-icon.js">
1
+ <template component="ui-icon">
2
2
  <defs>
3
3
  <prop name="name" type="string" default=""
4
4
  >Which icon to draw, by its name in Looma's icon set (LOOMA_ICONS), such as "align-left". An unknown or empty name draws nothing. The icon is hidden from
5
5
  assistive technology, so name the control it sits in.</prop>
6
- <state
6
+ <!-- Derived from name as it renders, so every render path, a server render included, draws the icon without JavaScript. Generated from LOOMA_ICONS by tools/scripts/generate-icon-catalog.mjs. -->
7
+ <computed
7
8
  name="shapes"
8
- type="list(object({ tag: path | circle | rect | line, d?: string, cx?: string, cy?: string, r?: string, x?: string, y?: string, width?: string, height?: string, rx?: string, x1?: string, x2?: string, y1?: string, y2?: string }))"
9
- :value="[]"
10
- ></state>
9
+ from="{
10
+ 'align-center': [{ tag: 'path', d: 'M21 5H3' }, { tag: 'path', d: 'M17 12H7' }, { tag: 'path', d: 'M19 19H5' }],
11
+ 'align-left': [{ tag: 'path', d: 'M21 5H3' }, { tag: 'path', d: 'M15 12H3' }, { tag: 'path', d: 'M17 19H3' }],
12
+ 'align-right': [{ tag: 'path', d: 'M21 5H3' }, { tag: 'path', d: 'M21 12H9' }, { tag: 'path', d: 'M21 19H7' }],
13
+ 'arrow-left': [{ tag: 'path', d: 'm12 19-7-7 7-7' }, { tag: 'path', d: 'M19 12H5' }],
14
+ 'bold': [{ tag: 'path', d: 'M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8' }],
15
+ 'book-user': [{ tag: 'path', d: 'M15 13a3 3 0 1 0-6 0' }, { tag: 'path', d: 'M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20' }, { tag: 'circle', cx: '12', cy: '8', r: '2' }],
16
+ 'braces': [{ tag: 'path', d: 'M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1' }, { tag: 'path', d: 'M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1' }],
17
+ 'calculator': [{ tag: 'rect', width: '16', height: '20', x: '4', y: '2', rx: '2' }, { tag: 'line', x1: '8', x2: '16', y1: '6', y2: '6' }, { tag: 'line', x1: '16', x2: '16', y1: '14', y2: '18' }, { tag: 'path', d: 'M16 10h.01' }, { tag: 'path', d: 'M12 10h.01' }, { tag: 'path', d: 'M8 10h.01' }, { tag: 'path', d: 'M12 14h.01' }, { tag: 'path', d: 'M8 14h.01' }, { tag: 'path', d: 'M12 18h.01' }, { tag: 'path', d: 'M8 18h.01' }],
18
+ 'chevron-down': [{ tag: 'path', d: 'm6 9 6 6 6-6' }],
19
+ 'chevron-left': [{ tag: 'path', d: 'm15 18-6-6 6-6' }],
20
+ 'chevron-right': [{ tag: 'path', d: 'm9 18 6-6-6-6' }],
21
+ 'circle-check': [{ tag: 'circle', cx: '12', cy: '12', r: '10' }, { tag: 'path', d: 'm9 12 2 2 4-4' }],
22
+ 'circle-x': [{ tag: 'circle', cx: '12', cy: '12', r: '10' }, { tag: 'path', d: 'm15 9-6 6' }, { tag: 'path', d: 'm9 9 6 6' }],
23
+ 'code-xml': [{ tag: 'path', d: 'm18 16 4-4-4-4' }, { tag: 'path', d: 'm6 8-4 4 4 4' }, { tag: 'path', d: 'm14.5 4-5 16' }],
24
+ 'columns': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M9 3v18' }, { tag: 'path', d: 'M15 3v18' }],
25
+ 'credit-card': [{ tag: 'rect', width: '20', height: '14', x: '2', y: '5', rx: '2' }, { tag: 'line', x1: '2', x2: '22', y1: '10', y2: '10' }],
26
+ 'ellipsis': [{ tag: 'circle', cx: '12', cy: '12', r: '1' }, { tag: 'circle', cx: '19', cy: '12', r: '1' }, { tag: 'circle', cx: '5', cy: '12', r: '1' }],
27
+ 'eraser': [{ tag: 'path', d: 'M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21' }, { tag: 'path', d: 'm5.082 11.09 8.828 8.828' }],
28
+ 'file-text': [{ tag: 'path', d: 'M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z' }, { tag: 'path', d: 'M14 2v5a1 1 0 0 0 1 1h5' }, { tag: 'path', d: 'M10 9H8' }, { tag: 'path', d: 'M16 13H8' }, { tag: 'path', d: 'M16 17H8' }],
29
+ 'folder': [{ tag: 'path', d: 'M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z' }],
30
+ 'grip-horizontal': [{ tag: 'circle', cx: '12', cy: '9', r: '1' }, { tag: 'circle', cx: '19', cy: '9', r: '1' }, { tag: 'circle', cx: '5', cy: '9', r: '1' }, { tag: 'circle', cx: '12', cy: '15', r: '1' }, { tag: 'circle', cx: '19', cy: '15', r: '1' }, { tag: 'circle', cx: '5', cy: '15', r: '1' }],
31
+ 'grip-vertical': [{ tag: 'circle', cx: '9', cy: '12', r: '1' }, { tag: 'circle', cx: '9', cy: '5', r: '1' }, { tag: 'circle', cx: '9', cy: '19', r: '1' }, { tag: 'circle', cx: '15', cy: '12', r: '1' }, { tag: 'circle', cx: '15', cy: '5', r: '1' }, { tag: 'circle', cx: '15', cy: '19', r: '1' }],
32
+ 'heading-1': [{ tag: 'path', d: 'M4 12h8' }, { tag: 'path', d: 'M4 18V6' }, { tag: 'path', d: 'M12 18V6' }, { tag: 'path', d: 'm17 12 3-2v8' }],
33
+ 'heading-2': [{ tag: 'path', d: 'M4 12h8' }, { tag: 'path', d: 'M4 18V6' }, { tag: 'path', d: 'M12 18V6' }, { tag: 'path', d: 'M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1' }],
34
+ 'heading-3': [{ tag: 'path', d: 'M4 12h8' }, { tag: 'path', d: 'M4 18V6' }, { tag: 'path', d: 'M12 18V6' }, { tag: 'path', d: 'M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2' }, { tag: 'path', d: 'M17 17.5c2 1.5 4 .3 4-1.5a2 2 0 0 0-2-2' }],
35
+ 'help': [{ tag: 'circle', cx: '12', cy: '12', r: '10' }, { tag: 'path', d: 'M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3' }, { tag: 'path', d: 'M12 17h.01' }],
36
+ 'highlighter': [{ tag: 'path', d: 'm9 11-6 6v3h9l3-3' }, { tag: 'path', d: 'm22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4' }],
37
+ 'image': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2', ry: '2' }, { tag: 'circle', cx: '9', cy: '9', r: '2' }, { tag: 'path', d: 'm21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21' }],
38
+ 'info': [{ tag: 'circle', cx: '12', cy: '12', r: '10' }, { tag: 'path', d: 'M12 16v-4' }, { tag: 'path', d: 'M12 8h.01' }],
39
+ 'italic': [{ tag: 'line', x1: '19', x2: '10', y1: '4', y2: '4' }, { tag: 'line', x1: '14', x2: '5', y1: '20', y2: '20' }, { tag: 'line', x1: '15', x2: '9', y1: '4', y2: '20' }],
40
+ 'layout-dashboard': [{ tag: 'rect', width: '7', height: '9', x: '3', y: '3', rx: '1' }, { tag: 'rect', width: '7', height: '5', x: '14', y: '3', rx: '1' }, { tag: 'rect', width: '7', height: '9', x: '14', y: '12', rx: '1' }, { tag: 'rect', width: '7', height: '5', x: '3', y: '16', rx: '1' }],
41
+ 'list': [{ tag: 'path', d: 'M3 5h.01' }, { tag: 'path', d: 'M3 12h.01' }, { tag: 'path', d: 'M3 19h.01' }, { tag: 'path', d: 'M8 5h13' }, { tag: 'path', d: 'M8 12h13' }, { tag: 'path', d: 'M8 19h13' }],
42
+ 'list-ordered': [{ tag: 'path', d: 'M11 5h10' }, { tag: 'path', d: 'M11 12h10' }, { tag: 'path', d: 'M11 19h10' }, { tag: 'path', d: 'M4 4h1v5' }, { tag: 'path', d: 'M4 9h2' }, { tag: 'path', d: 'M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02' }],
43
+ 'list-todo': [{ tag: 'path', d: 'M13 5h8' }, { tag: 'path', d: 'M13 12h8' }, { tag: 'path', d: 'M13 19h8' }, { tag: 'path', d: 'm3 17 2 2 4-4' }, { tag: 'rect', x: '3', y: '4', width: '6', height: '6', rx: '1' }],
44
+ 'loader': [{ tag: 'path', d: 'M21 12a9 9 0 1 1-6.219-8.56' }],
45
+ 'merge': [{ tag: 'path', d: 'm8 6 4-4 4 4' }, { tag: 'path', d: 'M12 2v10.3a4 4 0 0 1-1.172 2.872L4 22' }, { tag: 'path', d: 'm20 22-5-5' }],
46
+ 'minus': [{ tag: 'path', d: 'M5 12h14' }],
47
+ 'notebook-pen': [{ tag: 'path', d: 'M13.4 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7.4' }, { tag: 'path', d: 'M2 6h4' }, { tag: 'path', d: 'M2 10h4' }, { tag: 'path', d: 'M2 14h4' }, { tag: 'path', d: 'M2 18h4' }, { tag: 'path', d: 'M21.378 5.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z' }],
48
+ 'paint-bucket': [{ tag: 'path', d: 'm19 11-8-8-8.6 8.6a2 2 0 0 0 0 2.8l5.2 5.2c.8.8 2 .8 2.8 0L19 11Z' }, { tag: 'path', d: 'm5 2 5 5' }, { tag: 'path', d: 'M2 13h15' }, { tag: 'path', d: 'M22 20a2 2 0 1 1-4 0c0-1.6 1.7-2.4 2-4 .3 1.6 2 2.4 2 4Z' }],
49
+ 'panel-bottom': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M3 15h18' }],
50
+ 'panel-left': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M9 3v18' }],
51
+ 'panel-right': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M15 3v18' }],
52
+ 'panel-top': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M3 9h18' }],
53
+ 'pilcrow': [{ tag: 'path', d: 'M13 4v16' }, { tag: 'path', d: 'M17 4v16' }, { tag: 'path', d: 'M19 4H9.5a4.5 4.5 0 0 0 0 9H13' }],
54
+ 'plus': [{ tag: 'path', d: 'M5 12h14' }, { tag: 'path', d: 'M12 5v14' }],
55
+ 'quote': [{ tag: 'path', d: 'M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z' }, { tag: 'path', d: 'M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z' }],
56
+ 'receipt': [{ tag: 'path', d: 'M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z' }, { tag: 'path', d: 'M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8' }, { tag: 'path', d: 'M12 17.5v-11' }],
57
+ 'redo': [{ tag: 'path', d: 'm15 14 5-5-5-5' }, { tag: 'path', d: 'M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13' }],
58
+ 'rows': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M21 9H3' }, { tag: 'path', d: 'M21 15H3' }],
59
+ 'settings': [{ tag: 'path', d: 'M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915' }, { tag: 'circle', cx: '12', cy: '12', r: '3' }],
60
+ 'split': [{ tag: 'path', d: 'M16 3h5v5' }, { tag: 'path', d: 'M8 3H3v5' }, { tag: 'path', d: 'M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3' }, { tag: 'path', d: 'm15 9 6-6' }],
61
+ 'strikethrough': [{ tag: 'path', d: 'M16 4H9a3 3 0 0 0-2.83 4' }, { tag: 'path', d: 'M14 12a4 4 0 0 1 0 8H6' }, { tag: 'line', x1: '4', x2: '20', y1: '12', y2: '12' }],
62
+ 'table': [{ tag: 'path', d: 'M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18' }],
63
+ 'trash': [{ tag: 'path', d: 'M10 11v6' }, { tag: 'path', d: 'M14 11v6' }, { tag: 'path', d: 'M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6' }, { tag: 'path', d: 'M3 6h18' }, { tag: 'path', d: 'M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2' }],
64
+ 'triangle-alert': [{ tag: 'path', d: 'm21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3' }, { tag: 'path', d: 'M12 9v4' }, { tag: 'path', d: 'M12 17h.01' }],
65
+ 'truck': [{ tag: 'path', d: 'M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2' }, { tag: 'path', d: 'M15 18H9' }, { tag: 'path', d: 'M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14' }, { tag: 'circle', cx: '17', cy: '18', r: '2' }, { tag: 'circle', cx: '7', cy: '18', r: '2' }],
66
+ 'underline': [{ tag: 'path', d: 'M6 4v6a6 6 0 0 0 12 0V4' }, { tag: 'line', x1: '4', x2: '20', y1: '20', y2: '20' }],
67
+ 'undo': [{ tag: 'path', d: 'M9 14 4 9l5-5' }, { tag: 'path', d: 'M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11' }],
68
+ 'users': [{ tag: 'path', d: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2' }, { tag: 'path', d: 'M16 3.128a4 4 0 0 1 0 7.744' }, { tag: 'path', d: 'M22 21v-2a4 4 0 0 0-3-3.87' }, { tag: 'circle', cx: '9', cy: '7', r: '4' }],
69
+ }[name]"
70
+ ></computed>
11
71
  </defs>
12
72
  <span aria-hidden="true">
13
73
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false">
14
74
  <g $each="shape of shapes">
15
75
  <path $if="shape.tag = 'path'" :d="shape.d"></path>
16
76
  <circle $if="shape.tag = 'circle'" :cx="shape.cx" :cy="shape.cy" :r="shape.r"></circle>
17
- <rect $if="shape.tag = 'rect'" :x="shape.x" :y="shape.y" :width="shape.width" :height="shape.height" :rx="shape.rx"></rect>
18
- <line $if="shape.tag = 'line'" :x1="shape.x1" :x2="shape.x2" :y1="shape.y1" :y2="shape.y2"></line>
77
+ <rect $if="shape.tag = 'rect'" :x="shape.x" :y="shape.y" :width="shape.width" :height="shape.height" :rx="shape.rx" :ry="shape.ry"></rect>
78
+ <line $if="shape.tag = 'line'" :x1="shape.x1" :y1="shape.y1" :x2="shape.x2" :y2="shape.y2"></line>
19
79
  </g>
20
80
  </svg>
21
81
  </span>