@threadlabs/looma 0.28.10 → 0.28.12

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 (37) hide show
  1. package/components/ui-editor-chip-editor/ui-editor-chip-editor.html +32 -0
  2. package/components/ui-editor-chip-editor/ui-editor-chip-editor.js +33 -0
  3. package/components/ui-radio-group/ui-radio-group.html +13 -1
  4. package/components/ui-swatch/ui-swatch.html +69 -0
  5. package/dist/index.js +38 -37
  6. package/editor/block-actions.d.ts +9 -0
  7. package/editor/extensions/table-commands.d.ts +7 -1
  8. package/package.json +1 -1
  9. package/styles/ui-editor-chip-editor.css +1 -0
  10. package/styles/ui-radio-group.css +9 -0
  11. package/styles/ui-swatch.css +76 -0
  12. package/vanilla/UiEditorChipEditor.d.ts +18 -0
  13. package/vanilla/UiEditorChipEditor.js +45 -0
  14. package/vanilla/UiRadioGroup.d.ts +1 -0
  15. package/vanilla/UiRadioGroup.js +18 -13
  16. package/vanilla/UiSwatch.d.ts +14 -0
  17. package/vanilla/UiSwatch.js +54 -0
  18. package/vanilla/index.js +2 -0
  19. package/vue/UiEditorChipEditor.d.ts +45 -0
  20. package/vue/UiEditorChipEditor.js +2 -0
  21. package/vue/UiEditorChipEditor.vue +163 -0
  22. package/vue/UiRadioGroup.d.ts +9 -0
  23. package/vue/UiRadioGroup.vue +44 -2
  24. package/vue/UiSwatch.d.ts +16 -0
  25. package/vue/UiSwatch.js +2 -0
  26. package/vue/UiSwatch.vue +150 -0
  27. package/vue/chunks/UiEditorChipEditor.js +157 -0
  28. package/vue/chunks/UiEditorImageToolbar.js +2 -2
  29. package/vue/chunks/UiEditorLinkCard.js +1 -1
  30. package/vue/chunks/UiEditorLinkForm.js +2 -2
  31. package/vue/chunks/UiRadioGroup.js +26 -3
  32. package/vue/chunks/UiSwatch.js +78 -0
  33. package/vue/components.css +461 -443
  34. package/vue/editor/index.js +148 -105
  35. package/vue/editor/primitives.d.ts +9 -1
  36. package/vue/index.d.ts +2 -0
  37. package/vue/index.js +6 -4
@@ -0,0 +1,9 @@
1
+ import type { Editor } from "@tiptap/core";
2
+ /**
3
+ * Applies a block menu action to the top-level block holding the caret, then focuses the editor:
4
+ * insert a paragraph below, duplicate the block, or delete it. Deleting the only block leaves an
5
+ * empty paragraph.
6
+ *
7
+ * @failure Returns false, and changes nothing, for an unknown action or a caret outside any block.
8
+ */
9
+ export declare function runBlockAction(editor: Editor, action: string): boolean;
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import type { Editor, Range } from "@tiptap/core";
6
6
  import type { TableContextMenuActionEventDetail } from "../table-context-menu.js";
7
- import type { TableOverlayActionEventDetail } from "../table-overlay.js";
7
+ import { type TableOverlayActionEventDetail } from "../table-overlay.js";
8
8
  import { type TableCellAlignment, type TableCellBackground } from "./table-formatting.js";
9
9
  /**
10
10
  * Bounded initial shape for table insertion.
@@ -120,3 +120,9 @@ export declare function normalizeActiveTableColumnWidths(editor: Editor, tableEl
120
120
  * return false before dispatching a transaction.
121
121
  */
122
122
  export declare function handleTableOverlayAction(editor: Editor, detail: TableOverlayActionEventDetail): boolean;
123
+ /**
124
+ * Moves the caret to the cell an overlay action names when the action comes from a table other
125
+ * than the selected one, so table commands act on that table. A cell menu also selects its cell,
126
+ * unless that cell is already part of the selection.
127
+ */
128
+ export declare function focusTableOverlayTarget(editor: Editor, table: HTMLTableElement, detail: TableOverlayActionEventDetail): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.28.10",
3
+ "version": "0.28.12",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -0,0 +1 @@
1
+ /* Generated by HTML Next 1.0.0-alpha.51. Do not edit. */
@@ -36,6 +36,15 @@
36
36
  clear: both;
37
37
  }
38
38
 
39
+ legend.sr-only {
40
+ position: absolute;
41
+ inline-size: 1px;
42
+ block-size: 1px;
43
+ overflow: hidden;
44
+ clip-path: inset(50%);
45
+ white-space: nowrap;
46
+ }
47
+
39
48
  :scope:where([data-component~="ui-radio-group"])[data-ui-radio-group-state~="invalid"] legend {
40
49
  color: var(--_ui-radio-group-invalid-text);
41
50
  }
@@ -0,0 +1,76 @@
1
+ /* Generated by HTML Next 1.0.0-alpha.51. Do not edit. */
2
+ @supports (-moz-appearance: none) {
3
+ :where([data-component], [data-slotted]) { --html-next-scope-owner: boundary; }
4
+ :where([data-slotted]:not([data-component])) { --html-next-scope-owner: projected !important; }
5
+ }
6
+ @supports (-moz-appearance: none) {
7
+ [data-component~="ui-swatch"] { --html-next-scope-owner: "ui-swatch" !important; }
8
+ }
9
+ @scope ([data-component~="ui-swatch"]) to ([data-component], [data-slotted]) {
10
+ @property --ui-swatch-size {
11
+ syntax: "*";
12
+ inherits: false;
13
+ }
14
+
15
+ /* A native radio drawn as a round dot. Inside a ui-radio-group the group names it, applies its
16
+ value, and moves between swatches with the arrow keys. */
17
+ :scope:where([data-component~="ui-swatch"]) {
18
+ --_surface: var(--ui-surface-subtle);
19
+ --_text: var(--ui-text-secondary);
20
+
21
+ appearance: none;
22
+ box-sizing: border-box;
23
+ flex: 0 0 auto;
24
+ inline-size: var(--ui-swatch-size, 1.65rem);
25
+ block-size: var(--ui-swatch-size, 1.65rem);
26
+ margin: 0;
27
+ border: var(--ui-border-width) solid color-mix(in srgb, var(--_surface) 75%, var(--_text) 25%);
28
+ border-radius: 50%;
29
+ background: var(--_surface);
30
+ cursor: pointer;
31
+ }
32
+
33
+ :scope:where([data-component~="ui-swatch"])[data-ui-swatch-state~="tone=blue"] {
34
+ --_surface: var(--ui-info-soft);
35
+ --_text: var(--ui-info-subtle-text);
36
+ }
37
+
38
+ :scope:where([data-component~="ui-swatch"])[data-ui-swatch-state~="tone=green"] {
39
+ --_surface: var(--ui-success-soft);
40
+ --_text: var(--ui-success-subtle-text);
41
+ }
42
+
43
+ :scope:where([data-component~="ui-swatch"])[data-ui-swatch-state~="tone=yellow"] {
44
+ --_surface: var(--ui-warning-soft);
45
+ --_text: var(--ui-warning-subtle-text);
46
+ }
47
+
48
+ :scope:where([data-component~="ui-swatch"])[data-ui-swatch-state~="tone=red"] {
49
+ --_surface: var(--ui-danger-soft);
50
+ --_text: var(--ui-danger-subtle-text);
51
+ }
52
+
53
+ :scope:where([data-component~="ui-swatch"])[data-ui-swatch-state~="tone=purple"] {
54
+ --_surface: var(--ui-accent-soft);
55
+ --_text: var(--ui-accent-subtle-text);
56
+ }
57
+
58
+ /* The chosen swatch and the focused one share one ring at the focus width (2px by default), in
59
+ the tone or the focus colour. */
60
+ :scope:where([data-component~="ui-swatch"]):checked {
61
+ outline: var(--ui-focus-width) solid var(--_text);
62
+ outline-offset: var(--ui-focus-width);
63
+ }
64
+
65
+ :scope:where([data-component~="ui-swatch"]):focus-visible {
66
+ outline: var(--ui-focus-width) solid var(--ui-focus-ring, var(--ui-accent-solid));
67
+ outline-offset: var(--ui-focus-width);
68
+ }
69
+ }
70
+ @scope ([data-component~="ui-swatch"]) to ([data-component]) {
71
+ /* A native radio drawn as a round dot. Inside a ui-radio-group the group names it, applies its
72
+ value, and moves between swatches with the arrow keys. */
73
+
74
+ /* The chosen swatch and the focused one share one ring at the focus width (2px by default), in
75
+ the tone or the focus colour. */
76
+ }
@@ -0,0 +1,18 @@
1
+ // Generated by HTML Next 1.0.0-alpha.51 for Vanilla DOM. Do not edit.
2
+ export interface UiEditorChipEditorEventMap {
3
+ label: CustomEvent<{ readonly label: string }>;
4
+ color: CustomEvent<{ readonly color: "neutral" | "blue" | "green" | "yellow" | "red" | "purple" }>;
5
+ done: CustomEvent<Readonly<Record<string, unknown>>>;
6
+ }
7
+ export interface UiEditorChipEditorElement extends HTMLDivElement {
8
+ addEventListener<K extends keyof UiEditorChipEditorEventMap>(type: K, listener: (this: UiEditorChipEditorElement, event: UiEditorChipEditorEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
9
+ removeEventListener<K extends keyof UiEditorChipEditorEventMap>(type: K, listener: (this: UiEditorChipEditorElement, event: UiEditorChipEditorEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
10
+ }
11
+ export interface UiEditorChipEditorProps {
12
+ color?: "neutral" | "blue" | "green" | "yellow" | "red" | "purple" | null;
13
+ label?: string | null;
14
+ attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
15
+ children?: readonly (string | Node)[];
16
+ slots?: Readonly<Record<string, readonly (string | Node)[]>>;
17
+ }
18
+ export declare function createUiEditorChipEditor(props?: UiEditorChipEditorProps): UiEditorChipEditorElement;
@@ -0,0 +1,45 @@
1
+ // Generated by HTML Next 1.0.0-alpha.51 for Vanilla DOM. Do not edit.
2
+ import { attachGeneratedController, buildTemplate, toAttribute, writeAttribute, dispatchDeclared, detailCheck, formatOf, keywordFormat, acceptProps, manageProps, checkConstrained, checkFormat, checkObject, checkRecord, checkString, checkUnknown } from "@nextwebwg/html-next/generated-runtime";
3
+ import * as controller from "../components/ui-editor-chip-editor/ui-editor-chip-editor.js";
4
+ import "../styles/ui-editor-chip-editor.css";
5
+
6
+ const T0 = ["",[],["ui-stack",["gap","s"],["ui-input",["data-chip-label","","size","sm","placeholder","Set a label","aria-label","Chip text"]],["ui-radio-group",["label","Chip color","label-visibility","sr-only"],["ui-swatch",["tone","neutral"]],["ui-swatch",["tone","blue"]],["ui-swatch",["tone","green"]],["ui-swatch",["tone","yellow"]],["ui-swatch",["tone","red"]],["ui-swatch",["tone","purple"]]]]];
7
+ let P0;
8
+ const S = { n: [], t: [], f: import.meta.url, g: "ui-editor-chip-editor", d: { "label": [detailCheck(checkObject([["label", checkString, false]], false)), true, true, false], "color": [detailCheck(checkObject([["color", checkConstrained(checkFormat("keyword", keywordFormat), "keyword", {"values":["neutral","blue","green","yellow","red","purple"]}), false]], false)), true, true, false], "done": [detailCheck(checkRecord(checkUnknown)), true, true, false] }, x: dispatchDeclared };
9
+ const D = { props: { "color": { "required":false,"values":["neutral","blue","green","yellow","red","purple"],"default":"neutral", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] }, "label": { "required":false,"default":"", c: checkString, t: "string", j: 0, m: "s" } } };
10
+ const C = (host) => controller.default(host);
11
+
12
+ export function createUiEditorChipEditor(options = {}, html) {
13
+ const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
14
+ const element = document.createElement("div");
15
+ for (const [name, value] of Object.entries(attributes)) {
16
+ if (value === null || value === undefined || value === false) continue;
17
+ element.setAttribute(name, value === true ? "" : String(value));
18
+ }
19
+ if (!element.hasAttribute("role")) element.setAttribute("role", "dialog");
20
+ if (!element.hasAttribute("aria-label")) element.setAttribute("aria-label", "Edit chip");
21
+ element.setAttribute("data-component", "ui-editor-chip-editor");
22
+ element.append((P0 ??= buildTemplate(T0)).cloneNode(true));
23
+ const v = [null, null];
24
+ const B = acceptProps(element, D, S.n, v, componentProps, [], html);
25
+ const p0 = (r, c, d) => {
26
+ if (c & 2) {
27
+ const x0 = v[1];
28
+ const s0 = toAttribute(x0, "value");
29
+ if (s0 !== r.v0) writeAttribute(r.a0, "value", r.v0 = s0);
30
+ }
31
+ if (c & 1073741825) {
32
+ const x1 = v[0];
33
+ const s1 = toAttribute(x1, "value");
34
+ if (s1 !== r.v1) writeAttribute(r.a1, "value", r.v1 = s1);
35
+ }
36
+ };
37
+ const t0 = element.firstChild;
38
+ const t1 = t0.firstChild;
39
+ const t2 = t1.nextSibling;
40
+ const R = { a0: t1, a1: t2, v0: null, v1: null };
41
+ const I = { B };
42
+ attachGeneratedController(element, S, v, ((c, d) => p0(R, c, d)), C, undefined, I);
43
+ manageProps(I);
44
+ return element;
45
+ }
@@ -11,6 +11,7 @@ export interface UiRadioGroupProps {
11
11
  disabled?: boolean | null;
12
12
  invalid?: boolean | null;
13
13
  label?: string | null;
14
+ labelVisibility?: "visible" | "sr-only" | null;
14
15
  name?: string | null;
15
16
  orientation?: "horizontal" | "vertical" | null;
16
17
  required?: boolean | null;
@@ -7,7 +7,7 @@ const T0 = ["",[],["legend",[],0],4];
7
7
  const T1 = ["",[]];
8
8
  let P0, P1;
9
9
  const S = { n: ["internalValue"], t: ["s"], f: import.meta.url, g: "ui-radio-group", d: { "select": [detailCheck(checkObject([["value", checkString, false], ["previousValue", checkString, false], ["trigger", checkConstrained(checkFormat("keyword", keywordFormat), "keyword", {"values":["keyboard","pointer","programmatic"]}), false]], false)), true, true, false], "change": [detailCheck(checkObject([["checked", checkBoolean, false], ["value", checkString, false], ["trigger", checkConstrained(checkFormat("keyword", keywordFormat), "keyword", {"values":["keyboard","pointer","programmatic"]}), false]], false)), true, true, false] }, x: dispatchDeclared };
10
- const D = { props: { "disabled": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" }, "invalid": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" }, "label": { "required":false,"default":"Options", c: checkString, t: "string", j: 0, m: "s" }, "name": { "required":false,"default":"", c: checkString, t: "string", j: 0, m: "s" }, "orientation": { "required":false,"values":["horizontal","vertical"],"default":"horizontal", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] }, "required": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" }, "value": { "required":false,"default":"", c: checkString, t: "string", j: 0, m: "s" } } };
10
+ const D = { props: { "disabled": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" }, "invalid": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" }, "label": { "required":false,"default":"Options", c: checkString, t: "string", j: 0, m: "s" }, "labelVisibility": { "required":false,"values":["visible","sr-only"],"default":"visible", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] }, "name": { "required":false,"default":"", c: checkString, t: "string", j: 0, m: "s" }, "orientation": { "required":false,"values":["horizontal","vertical"],"default":"horizontal", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] }, "required": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" }, "value": { "required":false,"default":"", c: checkString, t: "string", j: 0, m: "s" } } };
11
11
  const C = (host) => controller.default(host);
12
12
 
13
13
  export function createUiRadioGroup(options = {}, html) {
@@ -20,7 +20,7 @@ export function createUiRadioGroup(options = {}, html) {
20
20
  if (!element.hasAttribute("role")) element.setAttribute("role", "radiogroup");
21
21
  element.setAttribute("data-component", "ui-radio-group");
22
22
  element.append((P0 ??= buildTemplate(T0)).cloneNode(true));
23
- const v = ["", null, null, null, null, null, null, null];
23
+ const v = ["", null, null, null, null, null, null, null, null];
24
24
  const B = acceptProps(element, D, S.n, v, componentProps, [], html);
25
25
  const m1 = (d) => {
26
26
  const n = (P1 ??= buildTemplate(T1)).cloneNode(true);
@@ -31,8 +31,8 @@ export function createUiRadioGroup(options = {}, html) {
31
31
  const p1 = (r, c, d) => {
32
32
  };
33
33
  const p0 = (r, c, d) => {
34
- if (c & 64) {
35
- const x0 = v[6];
34
+ if (c & 128) {
35
+ const x0 = v[7];
36
36
  const s0 = toAttribute(x0, "aria-required");
37
37
  if (s0 !== r.v0) writeAttribute(r.n, "aria-required", r.v0 = s0);
38
38
  }
@@ -46,24 +46,29 @@ export function createUiRadioGroup(options = {}, html) {
46
46
  const s2 = toAttribute(x2, "disabled");
47
47
  if (s2 !== r.v2) writeAttribute(r.n, "disabled", r.v2 = s2);
48
48
  }
49
+ if (c & 16) {
50
+ const x3 = (v[4] === "sr-only");
51
+ const s3 = x3;
52
+ if (s3 !== r.v3) r.a1.classList.toggle("sr-only", r.v3 = s3);
53
+ }
49
54
  if (c & 8) {
50
- const x3 = v[3];
51
- const s3 = toText(x3);
52
- if (s3 !== r.v3) r.a1.data = r.v3 = s3;
55
+ const x4 = v[3];
56
+ const s4 = toText(x4);
57
+ if (s4 !== r.v4) r.a2.data = r.v4 = s4;
53
58
  }
54
- if (c & 36) {
55
- const x4 = hostState(["invalid","orientation"], [v[2], v[5]]);
56
- const s4 = x4;
57
- if (s4 !== r.v4) writeAttribute(r.n, "data-ui-radio-group-state", (r.v4 = s4) === "" ? null : s4);
59
+ if (c & 68) {
60
+ const x5 = hostState(["invalid","orientation"], [v[2], v[6]]);
61
+ const s5 = x5;
62
+ if (s5 !== r.v5) writeAttribute(r.n, "data-ui-radio-group-state", (r.v5 = s5) === "" ? null : s5);
58
63
  }
59
- if (r.f0 === undefined) { r.f0 = 1; const at = fillSlot(r.a2, r.e0, "", J, false, undefined, d);
64
+ if (r.f0 === undefined) { r.f0 = 1; const at = fillSlot(r.a3, r.e0, "", J, false, undefined, d);
60
65
  if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b0 = m1(d); at.before(r.b0.n); } }
61
66
  else if (r.b0 !== undefined) p1(r.b0, c, d);
62
67
  };
63
68
  const t0 = element.firstChild;
64
69
  const t1 = t0.firstChild;
65
70
  const t2 = t0.nextSibling;
66
- const R = { n: element, a1: t1, v0: undefined, v1: undefined, v2: undefined, v3: "", v4: undefined, a2: t2, e0: t2.nextSibling, b0: undefined, f0: undefined };
71
+ const R = { n: element, a1: t0, a2: t1, v0: undefined, v1: undefined, v2: undefined, v3: false, v4: "", v5: undefined, a3: t2, e0: t2.nextSibling, b0: undefined, f0: undefined };
67
72
  const I = { B };
68
73
  const J = project(I, children, slots);
69
74
  I.R = new Set();
@@ -0,0 +1,14 @@
1
+ // Generated by HTML Next 1.0.0-alpha.51 for Vanilla DOM. Do not edit.
2
+ export interface UiSwatchEventMap {
3
+ }
4
+ export interface UiSwatchElement extends HTMLInputElement {
5
+ addEventListener<K extends keyof UiSwatchEventMap>(type: K, listener: (this: UiSwatchElement, event: UiSwatchEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
6
+ removeEventListener<K extends keyof UiSwatchEventMap>(type: K, listener: (this: UiSwatchElement, event: UiSwatchEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
7
+ }
8
+ export interface UiSwatchProps {
9
+ tone?: "neutral" | "blue" | "green" | "yellow" | "red" | "purple" | null;
10
+ attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
11
+ children?: readonly (string | Node)[];
12
+ slots?: Readonly<Record<string, readonly (string | Node)[]>>;
13
+ }
14
+ export declare function createUiSwatch(props?: UiSwatchProps): UiSwatchElement;
@@ -0,0 +1,54 @@
1
+ // Generated by HTML Next 1.0.0-alpha.51 for Vanilla DOM. Do not edit.
2
+ import { attachGeneratedController, readIndex, toAttribute, writeAttribute, computedCycle, formatOf, keywordFormat, hostState, acceptProps, manageProps, readonlyView, checkFormat } from "@nextwebwg/html-next/generated-runtime";
3
+ import "../styles/ui-swatch.css";
4
+
5
+ const S = { n: ["toneName"], t: ["?"], f: import.meta.url, g: "ui-swatch", k: 0, r: readonlyView };
6
+ const D = { props: { "tone": { "required":false,"values":["neutral","blue","green","yellow","red","purple"],"default":"neutral", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] } } };
7
+
8
+ export function createUiSwatch(options = {}, html) {
9
+ const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
10
+ const element = document.createElement("input");
11
+ for (const [name, value] of Object.entries(attributes)) {
12
+ if (value === null || value === undefined || value === false) continue;
13
+ element.setAttribute(name, value === true ? "" : String(value));
14
+ }
15
+ if (!element.hasAttribute("type")) element.setAttribute("type", "radio");
16
+ element.setAttribute("data-component", "ui-swatch");
17
+ const v = [undefined, null];
18
+ const B = acceptProps(element, D, S.n, v, componentProps, [], html);
19
+ const X = { e: 0, g: (j) => g(j), w: new Set() };
20
+ const ke = [];
21
+ const K = [() => readIndex({ "neutral": "Neutral", "blue": "Blue", "green": "Green", "yellow": "Yellow", "red": "Red", "purple": "Purple" }, v[1])];
22
+ const g = (j) => {
23
+ const i = j - 0;
24
+ if (ke[i] === X.e) return v[j];
25
+ if (ke[i] === -1) computedCycle();
26
+ ke[i] = -1;
27
+ let next;
28
+ try { next = K[i](); } catch (error) { ke[i] = undefined; throw error; }
29
+ ke[i] = X.e;
30
+ const previous = v[j];
31
+ if (!Object.is(previous, next)) { v[j] = next; X.n?.(j, previous, next); }
32
+ return next;
33
+ };
34
+ const p0 = (r, c, d) => {
35
+ if (c & 1073741826) {
36
+ const x0 = v[1];
37
+ const s0 = toAttribute(x0, "value");
38
+ if (s0 !== r.v0) writeAttribute(r.n, "value", r.v0 = s0);
39
+ const x1 = g(0);
40
+ const s1 = toAttribute(x1, "aria-label");
41
+ if (s1 !== r.v1) writeAttribute(r.n, "aria-label", r.v1 = s1);
42
+ }
43
+ if (c & 2) {
44
+ const x2 = hostState(["tone"], [v[1]]);
45
+ const s2 = x2;
46
+ if (s2 !== r.v2) writeAttribute(r.n, "data-ui-swatch-state", (r.v2 = s2) === "" ? null : s2);
47
+ }
48
+ };
49
+ const R = { n: element, v0: undefined, v1: undefined, v2: undefined };
50
+ const I = { B };
51
+ attachGeneratedController(element, S, v, ((c, d) => p0(R, c, d)), undefined, X, I);
52
+ manageProps(I);
53
+ return element;
54
+ }
package/vanilla/index.js CHANGED
@@ -20,6 +20,7 @@ export * from "./UiDialog.js";
20
20
  export * from "./UiDisclosure.js";
21
21
  export * from "./UiEditable.js";
22
22
  export * from "./UiEditorBlockActions.js";
23
+ export * from "./UiEditorChipEditor.js";
23
24
  export * from "./UiEditorCodeLanguage.js";
24
25
  export * from "./UiEditorImageToolbar.js";
25
26
  export * from "./UiEditorInsertTableGrid.js";
@@ -66,6 +67,7 @@ export * from "./UiSidebar.js";
66
67
  export * from "./UiSpinner.js";
67
68
  export * from "./UiStack.js";
68
69
  export * from "./UiStatusMessage.js";
70
+ export * from "./UiSwatch.js";
69
71
  export * from "./UiSwitch.js";
70
72
  export * from "./UiSwitcher.js";
71
73
  export * from "./UiTable.js";
@@ -0,0 +1,45 @@
1
+ import type { PropType } from 'vue';
2
+ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
3
+ color: {
4
+ type: PropType<"neutral" | "blue" | "green" | "yellow" | "red" | "purple" | null>;
5
+ default: string;
6
+ };
7
+ label: {
8
+ type: PropType<string | null>;
9
+ default: string;
10
+ };
11
+ }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ done: (event: CustomEvent<Readonly<Record<string, unknown>>>) => any;
13
+ label: (event: CustomEvent<{
14
+ readonly label: string;
15
+ }>) => any;
16
+ color: (event: CustomEvent<{
17
+ readonly color: "neutral" | "blue" | "green" | "yellow" | "red" | "purple";
18
+ }>) => any;
19
+ "update:color": (value: string) => any;
20
+ "update:label": (value: string) => any;
21
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
22
+ color: {
23
+ type: PropType<"neutral" | "blue" | "green" | "yellow" | "red" | "purple" | null>;
24
+ default: string;
25
+ };
26
+ label: {
27
+ type: PropType<string | null>;
28
+ default: string;
29
+ };
30
+ }>> & Readonly<{
31
+ onDone?: ((event: CustomEvent<Readonly<Record<string, unknown>>>) => any) | undefined;
32
+ onLabel?: ((event: CustomEvent<{
33
+ readonly label: string;
34
+ }>) => any) | undefined;
35
+ onColor?: ((event: CustomEvent<{
36
+ readonly color: "neutral" | "blue" | "green" | "yellow" | "red" | "purple";
37
+ }>) => any) | undefined;
38
+ "onUpdate:color"?: ((value: string) => any) | undefined;
39
+ "onUpdate:label"?: ((value: string) => any) | undefined;
40
+ }>, {
41
+ label: string | null;
42
+ color: "blue" | "green" | "purple" | "red" | "yellow" | "neutral" | null;
43
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
44
+ declare const _default: typeof __VLS_export;
45
+ export default _default;
@@ -0,0 +1,2 @@
1
+ import { t as UiEditorChipEditor_default } from "./chunks/UiEditorChipEditor.js";
2
+ export { UiEditorChipEditor_default as default };
@@ -0,0 +1,163 @@
1
+ <!-- Generated by HTML Next 1.0.0-alpha.51 for Vue 3.5. Do not edit. -->
2
+ <script setup lang="ts">
3
+ import { computed, getCurrentInstance, ref, watchSyncEffect } from 'vue'
4
+ import type { PropType } from 'vue'
5
+ import {
6
+ checkHydratedRoot,
7
+ createDispatch,
8
+ nativeAttrs,
9
+ useComponentHost,
10
+ useReflectedProp,
11
+ } from './host'
12
+ import { checkedProp, propValidityState, vPropValidity } from './props'
13
+ import UiInput from './UiInput.vue'
14
+ import UiRadioGroup from './UiRadioGroup.vue'
15
+ import UiStack from './UiStack.vue'
16
+ import UiSwatch from './UiSwatch.vue'
17
+
18
+ defineOptions({ inheritAttrs: false })
19
+
20
+ const propValidityContract = {
21
+ props: {
22
+ color: {
23
+ type: { kind: 'terminal', name: 'keyword' },
24
+ required: false,
25
+ target: { attribute: 'value' },
26
+ description: 'The chip\'s colour, checked among the swatches.',
27
+ values: ['neutral', 'blue', 'green', 'yellow', 'red', 'purple'],
28
+ default: 'neutral',
29
+ },
30
+ label: {
31
+ type: { kind: 'terminal', name: 'string' },
32
+ required: false,
33
+ target: { attribute: 'value' },
34
+ description: 'The chip\'s text, shown in the field as the reader edits it.',
35
+ default: '',
36
+ },
37
+ },
38
+ } as const
39
+ const props = defineProps({
40
+ color: {
41
+ type: null as unknown as PropType<
42
+ 'neutral' | 'blue' | 'green' | 'yellow' | 'red' | 'purple' | null
43
+ >,
44
+ default: 'neutral',
45
+ },
46
+ label: { type: null as unknown as PropType<string | null>, default: '' },
47
+ })
48
+ const acceptedProps: Record<string, unknown> = { color: 'neutral', label: '' }
49
+ const checkedProps = computed(() => ({
50
+ color: checkedProp<'neutral' | 'blue' | 'green' | 'yellow' | 'red' | 'purple'>(
51
+ props['color'],
52
+ { kind: 'terminal', name: 'keyword' },
53
+ false,
54
+ 'color',
55
+ acceptedProps,
56
+ ) as 'neutral' | 'blue' | 'green' | 'yellow' | 'red' | 'purple',
57
+ label: checkedProp<string>(
58
+ props['label'],
59
+ { kind: 'terminal', name: 'string' },
60
+ false,
61
+ 'label',
62
+ acceptedProps,
63
+ ) as string,
64
+ }))
65
+ void checkedProps.value
66
+ watchSyncEffect(() => {
67
+ void checkedProps.value
68
+ })
69
+ const reflectedProp = useReflectedProp()
70
+ const hydrationInstance = getCurrentInstance()
71
+ const emit = defineEmits<{
72
+ 'update:color': [value: string]
73
+ 'update:label': [value: string]
74
+ label: [event: CustomEvent<{ readonly label: string }>]
75
+ color: [
76
+ event: CustomEvent<
77
+ { readonly color: 'neutral' | 'blue' | 'green' | 'yellow' | 'red' | 'purple' }
78
+ >,
79
+ ]
80
+ done: [event: CustomEvent<Readonly<Record<string, unknown>>>]
81
+ }>()
82
+
83
+ const root = ref<HTMLElement | null>(null)
84
+ checkHydratedRoot('div', 'ui-editor-chip-editor')
85
+
86
+ const isLabelDetail = (
87
+ detail: unknown,
88
+ ): boolean => (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
89
+ && typeof (detail as Record<string, unknown>)['label'] === 'string'
90
+ && Object.keys(detail as object).every((key) => ['label'].includes(key)))
91
+ const isColorDetail = (
92
+ detail: unknown,
93
+ ): boolean => (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
94
+ && ((detail as Record<string, unknown>)['color'] === 'neutral'
95
+ || (detail as Record<string, unknown>)['color'] === 'blue'
96
+ || (detail as Record<string, unknown>)['color'] === 'green'
97
+ || (detail as Record<string, unknown>)['color'] === 'yellow'
98
+ || (detail as Record<string, unknown>)['color'] === 'red'
99
+ || (detail as Record<string, unknown>)['color'] === 'purple')
100
+ && Object.keys(detail as object).every((key) => ['color'].includes(key)))
101
+ const isDoneDetail = (
102
+ detail: unknown,
103
+ ): boolean => (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
104
+ && Object.values(detail as object).every((item: unknown) => true))
105
+ const dispatch = createDispatch(root, emit as (name: string, detail: unknown) => void, {
106
+ checks: {
107
+ label: isLabelDetail,
108
+ color: isColorDetail,
109
+ done: isDoneDetail,
110
+ },
111
+ modeled: ['color', 'label'],
112
+ })
113
+
114
+ useComponentHost(() => import('../components/ui-editor-chip-editor/ui-editor-chip-editor.js'), {
115
+ root,
116
+ dispatch,
117
+ controllerSource: {
118
+ specifier: '../components/ui-editor-chip-editor/ui-editor-chip-editor.js',
119
+ definition: './components/ui-editor-chip-editor/ui-editor-chip-editor.html',
120
+ },
121
+ props: checkedProps,
122
+ propInputs: (name: string) => {
123
+ const incoming = hydrationInstance?.vnode.props
124
+ const kebab = name.replace(/[A-Z]/g, (letter) => '-' + letter.toLowerCase())
125
+ return incoming !== null && incoming !== undefined
126
+ ? (incoming[name] ?? incoming[kebab] ?? null)
127
+ : null
128
+ },
129
+ propNames: ['color', 'label'],
130
+ propValidity: (name: string) =>
131
+ propValidityState({ contract: propValidityContract, values: { ...props } }, name),
132
+ })
133
+ </script>
134
+
135
+ <template>
136
+ <div
137
+ role="dialog"
138
+ aria-label="Edit chip"
139
+ v-bind="nativeAttrs($attrs)"
140
+ v-prop-validity="{ contract: propValidityContract, values: { ...props } }"
141
+ :data-color="reflectedProp('color', 'color', checkedProps.color, undefined, false)"
142
+ :data-label="reflectedProp('label', 'label', checkedProps.label, undefined, false)"
143
+ ref="root"
144
+ >
145
+ <UiStack gap="s"><UiInput
146
+ data-chip-label=""
147
+ size="sm"
148
+ placeholder="Set a label"
149
+ aria-label="Chip text"
150
+ :value="checkedProps.label"
151
+ />
152
+ <UiRadioGroup
153
+ label="Chip color"
154
+ label-visibility="sr-only"
155
+ :value="checkedProps.color"
156
+ ><UiSwatch tone="neutral" />
157
+ <UiSwatch tone="blue" />
158
+ <UiSwatch tone="green" />
159
+ <UiSwatch tone="yellow" />
160
+ <UiSwatch tone="red" />
161
+ <UiSwatch tone="purple" /></UiRadioGroup></UiStack>
162
+ </div>
163
+ </template>
@@ -16,6 +16,10 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
16
16
  type: PropType<string | null>;
17
17
  default: string;
18
18
  };
19
+ labelVisibility: {
20
+ type: PropType<"visible" | "sr-only" | null>;
21
+ default: string;
22
+ };
19
23
  name: {
20
24
  type: PropType<string | null>;
21
25
  default: string;
@@ -57,6 +61,10 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
57
61
  type: PropType<string | null>;
58
62
  default: string;
59
63
  };
64
+ labelVisibility: {
65
+ type: PropType<"visible" | "sr-only" | null>;
66
+ default: string;
67
+ };
60
68
  name: {
61
69
  type: PropType<string | null>;
62
70
  default: string;
@@ -92,6 +100,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
92
100
  label: string | null;
93
101
  invalid: boolean | null;
94
102
  disabled: boolean | null;
103
+ labelVisibility: "visible" | "sr-only" | null;
95
104
  orientation: "vertical" | "horizontal" | null;
96
105
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
97
106
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;