@threadlabs/looma 0.27.3 → 0.27.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.27.3",
3
+ "version": "0.27.5",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -280,11 +280,11 @@
280
280
  }
281
281
 
282
282
  /* A count can keep its containing control's contrasting ink instead of reversing it.
283
- The faint fill is painted over that control; no second rim or shadow competes with it. */
283
+ The faint fill preserves text contrast; a quiet boundary separates the count from its control. */
284
284
  :scope[data-ui-badge-state~="variant=overlay"] {
285
285
  --_badge-outline-surface: var(--ui-badge-surface, color-mix(in srgb, currentColor 6%, transparent));
286
286
  color: var(--ui-badge-text, inherit);
287
- border-color: var(--ui-badge-border, transparent);
287
+ border-color: var(--ui-badge-border, color-mix(in srgb, currentColor 20%, transparent));
288
288
  box-shadow: none;
289
289
  }
290
290
 
@@ -533,7 +533,7 @@
533
533
  Dark controls retain a shaded surface and theme ink with a quieter rim. */
534
534
 
535
535
  /* A count can keep its containing control's contrasting ink instead of reversing it.
536
- The faint fill is painted over that control; no second rim or shadow competes with it. */
536
+ The faint fill preserves text contrast; a quiet boundary separates the count from its control. */
537
537
 
538
538
  /* Neutral reverses a subtle surface/ink pair rather than a strong tone. Keep its original
539
539
  surface ink: moving it toward dark-theme primary text would reduce overlay contrast. */
@@ -105,6 +105,11 @@
105
105
  min-inline-size: 0;
106
106
  }
107
107
 
108
+ .heading {
109
+ display: block;
110
+ font-weight: var(--ui-font-semibold);
111
+ }
112
+
108
113
  :scope[data-ui-callout-state~="tone=neutral"], :scope[data-ui-callout-state~="tone=note"] {
109
114
  --_ui-selection-context-surface: initial;
110
115
  --_ui-selection-context-border: initial;
@@ -114,6 +119,18 @@
114
119
  --_callout-icon: var(--ui-text-secondary);
115
120
  }
116
121
 
122
+ :scope[data-ui-callout-state~="tone=tip"] {
123
+ --_callout-surface: var(--ui-success-soft);
124
+ --_callout-border: var(--ui-success-solid);
125
+ --_callout-icon: var(--ui-success-solid);
126
+ }
127
+
128
+ :scope[data-ui-callout-state~="tone=important"] {
129
+ --_callout-surface: var(--ui-accent-soft);
130
+ --_callout-border: var(--ui-accent-solid);
131
+ --_callout-icon: var(--ui-accent-solid);
132
+ }
133
+
117
134
  :scope[data-ui-callout-state~="tone=warning"] {
118
135
  --_callout-surface: var(--ui-warning-soft);
119
136
  --_callout-border: var(--ui-warning-solid);
@@ -126,7 +143,7 @@
126
143
  --_callout-icon: var(--ui-success-solid);
127
144
  }
128
145
 
129
- :scope[data-ui-callout-state~="tone=danger"] {
146
+ :scope[data-ui-callout-state~="tone=danger"], :scope[data-ui-callout-state~="tone=caution"] {
130
147
  --_callout-surface: var(--ui-danger-soft);
131
148
  --_callout-border: var(--ui-danger-solid);
132
149
  --_callout-icon: var(--ui-danger-solid);
@@ -6,7 +6,8 @@ export interface UiCalloutElement extends HTMLDivElement {
6
6
  removeEventListener<K extends keyof UiCalloutEventMap>(type: K, listener: (this: UiCalloutElement, event: UiCalloutEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
7
7
  }
8
8
  export interface UiCalloutProps {
9
- tone?: "info" | "neutral" | "note" | "warning" | "success" | "danger" | null;
9
+ heading?: string | null;
10
+ tone?: "info" | "neutral" | "note" | "tip" | "important" | "warning" | "caution" | "success" | "danger" | null;
10
11
  attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
11
12
  children?: readonly (string | Node)[];
12
13
  slots?: Readonly<Record<string, readonly (string | Node)[]>>;
@@ -1,17 +1,20 @@
1
1
  // Generated by HTML Next 1.0.0-alpha.35 for Vanilla DOM. Do not edit.
2
- import { attachGeneratedController, buildTemplate, clearRegion, writeAttribute, dispose, formatOf, keywordFormat, hostState, acceptProps, manageProps, project, fillSlot, checkFormat } from "@nextwebwg/html-next/generated-runtime";
2
+ import { attachGeneratedController, buildTemplate, clearRegion, toText, truthy, writeAttribute, dispose, formatOf, keywordFormat, hostState, acceptProps, manageProps, project, fillSlot, checkFormat, checkString } from "@nextwebwg/html-next/generated-runtime";
3
3
  import "../styles/ui-callout.css";
4
4
 
5
- const T0 = ["",[],["span",["class","icon","aria-hidden","true"],1,1,1,1,1],["div",["class","content"],4]];
5
+ const T0 = ["",[],["span",["class","icon","aria-hidden","true"],1,1,1,1,1,1,1],["div",["class","content"],1,4]];
6
6
  const T1 = ["svg",["viewBox","0 0 24 24","fill","none","stroke","currentColor","stroke-width","2","stroke-linecap","round","stroke-linejoin","round"],["circle",["cx","12","cy","12","r","10"]],["path",["d","M12 16v-4"]],["path",["d","M12 8h.01"]]];
7
7
  const T2 = ["svg",["viewBox","0 0 24 24","fill","none","stroke","currentColor","stroke-width","2","stroke-linecap","round","stroke-linejoin","round"],["path",["d","M13.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8.5L13.5 2Z"]],["path",["d","M13 2v7h7"]],["path",["d","m9.5 17.5 4-4 2 2-4 4H9.5v-2Z"]]];
8
- const T3 = ["svg",["viewBox","0 0 24 24","fill","none","stroke","currentColor","stroke-width","2","stroke-linecap","round","stroke-linejoin","round"],["path",["d","m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"]],["path",["d","M12 9v4"]],["path",["d","M12 17h.01"]]];
9
- const T4 = ["svg",["viewBox","0 0 24 24","fill","none","stroke","currentColor","stroke-width","2","stroke-linecap","round","stroke-linejoin","round"],["circle",["cx","12","cy","12","r","10"]],["path",["d","m9 12 2 2 4-4"]]];
10
- const T5 = ["svg",["viewBox","0 0 24 24","fill","none","stroke","currentColor","stroke-width","2","stroke-linecap","round","stroke-linejoin","round"],["circle",["cx","12","cy","12","r","10"]],["path",["d","m15 9-6 6"]],["path",["d","m9 9 6 6"]]];
11
- const T6 = ["",[]];
12
- let P0, P1, P2, P3, P4, P5, P6;
8
+ const T3 = ["svg",["viewBox","0 0 24 24","fill","none","stroke","currentColor","stroke-width","2","stroke-linecap","round","stroke-linejoin","round"],["path",["d","M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"]],["path",["d","M9 18h6"]],["path",["d","M10 22h4"]]];
9
+ const T4 = ["svg",["viewBox","0 0 24 24","fill","none","stroke","currentColor","stroke-width","2","stroke-linecap","round","stroke-linejoin","round"],["path",["d","M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"]],["path",["d","M12 15h.01"]],["path",["d","M12 7v4"]]];
10
+ const T5 = ["svg",["viewBox","0 0 24 24","fill","none","stroke","currentColor","stroke-width","2","stroke-linecap","round","stroke-linejoin","round"],["path",["d","m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"]],["path",["d","M12 9v4"]],["path",["d","M12 17h.01"]]];
11
+ const T6 = ["svg",["viewBox","0 0 24 24","fill","none","stroke","currentColor","stroke-width","2","stroke-linecap","round","stroke-linejoin","round"],["circle",["cx","12","cy","12","r","10"]],["path",["d","m9 12 2 2 4-4"]]];
12
+ const T7 = ["svg",["viewBox","0 0 24 24","fill","none","stroke","currentColor","stroke-width","2","stroke-linecap","round","stroke-linejoin","round"],["circle",["cx","12","cy","12","r","10"]],["path",["d","m15 9-6 6"]],["path",["d","m9 9 6 6"]]];
13
+ const T8 = ["strong",["class","heading"],0];
14
+ const T9 = ["",[]];
15
+ let P0, P1, P2, P3, P4, P5, P6, P7, P8, P9;
13
16
  const S = { n: [], t: [], f: import.meta.url, g: "ui-callout" };
14
- const D = { props: { "tone": { "required":false,"values":["info","neutral","note","warning","success","danger"],"default":"info", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] } } };
17
+ const D = { props: { "heading": { "required":false,"default":"", c: checkString, t: "string", j: 0, m: "s" }, "tone": { "required":false,"values":["info","neutral","note","tip","important","warning","caution","success","danger"],"default":"info", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] } } };
15
18
 
16
19
  export function createUiCallout(options = {}, html) {
17
20
  const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
@@ -23,7 +26,7 @@ export function createUiCallout(options = {}, html) {
23
26
  if (!element.hasAttribute("role")) element.setAttribute("role", "note");
24
27
  element.setAttribute("data-component", "ui-callout");
25
28
  element.append((P0 ??= buildTemplate(T0)).cloneNode(true));
26
- const v = [null];
29
+ const v = [null, null];
27
30
  const B = acceptProps(element, D, S.n, v, componentProps, [], html);
28
31
  const m1 = (d) => {
29
32
  const n = (P1 ??= buildTemplate(T1)).cloneNode(true);
@@ -73,14 +76,44 @@ export function createUiCallout(options = {}, html) {
73
76
  };
74
77
  const p6 = (r, c, d) => {
75
78
  };
76
- const p0 = (r, c, d) => {
79
+ const m7 = (d) => {
80
+ const n = (P7 ??= buildTemplate(T7)).cloneNode(true);
81
+ const r = { n };
82
+ p7(r, -1, d);
83
+ return r;
84
+ };
85
+ const p7 = (r, c, d) => {
86
+ };
87
+ const m8 = (d) => {
88
+ const n = (P8 ??= buildTemplate(T8)).cloneNode(true);
89
+ const t0 = n.firstChild;
90
+ const r = { n, a0: t0, v0: "" };
91
+ p8(r, -1, d);
92
+ return r;
93
+ };
94
+ const p8 = (r, c, d) => {
77
95
  if (c & 1) {
78
- const x0 = hostState(["tone"], [v[0]]);
96
+ const x0 = v[0];
97
+ const s0 = toText(x0);
98
+ if (s0 !== r.v0) r.a0.data = r.v0 = s0;
99
+ }
100
+ };
101
+ const m9 = (d) => {
102
+ const n = (P9 ??= buildTemplate(T9)).cloneNode(true);
103
+ const r = { n };
104
+ p9(r, -1, d);
105
+ return r;
106
+ };
107
+ const p9 = (r, c, d) => {
108
+ };
109
+ const p0 = (r, c, d) => {
110
+ if (c & 2) {
111
+ const x0 = hostState(["tone"], [v[1]]);
79
112
  const s0 = x0;
80
113
  if (s0 !== r.v0) writeAttribute(r.n, "data-ui-callout-state", (r.v0 = s0) === "" ? null : s0);
81
114
  }
82
- if (c & 1) {
83
- const t0 = (v[0] === "info");
115
+ if (c & 2) {
116
+ const t0 = (v[1] === "info");
84
117
  if (true) {
85
118
  {
86
119
  r.b0 = undefined;
@@ -89,8 +122,8 @@ export function createUiCallout(options = {}, html) {
89
122
  }
90
123
  } else if (r.b0 !== undefined) p1(r.b0, c, d);
91
124
  } else if (r.b0 !== undefined) p1(r.b0, c, d);
92
- if (c & 1) {
93
- const t1 = ((v[0] === "neutral") || (v[0] === "note"));
125
+ if (c & 2) {
126
+ const t1 = ((v[1] === "neutral") || (v[1] === "note"));
94
127
  if (true) {
95
128
  {
96
129
  r.b1 = undefined;
@@ -99,8 +132,8 @@ export function createUiCallout(options = {}, html) {
99
132
  }
100
133
  } else if (r.b1 !== undefined) p2(r.b1, c, d);
101
134
  } else if (r.b1 !== undefined) p2(r.b1, c, d);
102
- if (c & 1) {
103
- const t2 = (v[0] === "warning");
135
+ if (c & 2) {
136
+ const t2 = (v[1] === "tip");
104
137
  if (true) {
105
138
  {
106
139
  r.b2 = undefined;
@@ -109,8 +142,8 @@ export function createUiCallout(options = {}, html) {
109
142
  }
110
143
  } else if (r.b2 !== undefined) p3(r.b2, c, d);
111
144
  } else if (r.b2 !== undefined) p3(r.b2, c, d);
112
- if (c & 1) {
113
- const t3 = (v[0] === "success");
145
+ if (c & 2) {
146
+ const t3 = (v[1] === "important");
114
147
  if (true) {
115
148
  {
116
149
  r.b3 = undefined;
@@ -119,8 +152,8 @@ export function createUiCallout(options = {}, html) {
119
152
  }
120
153
  } else if (r.b3 !== undefined) p4(r.b3, c, d);
121
154
  } else if (r.b3 !== undefined) p4(r.b3, c, d);
122
- if (c & 1) {
123
- const t4 = (v[0] === "danger");
155
+ if (c & 2) {
156
+ const t4 = (v[1] === "warning");
124
157
  if (true) {
125
158
  {
126
159
  r.b4 = undefined;
@@ -129,9 +162,39 @@ export function createUiCallout(options = {}, html) {
129
162
  }
130
163
  } else if (r.b4 !== undefined) p5(r.b4, c, d);
131
164
  } else if (r.b4 !== undefined) p5(r.b4, c, d);
132
- if (r.f5 === undefined) { r.f5 = 1; const at = fillSlot(r.a5, r.e5, "", J, false, undefined, d);
133
- if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b5 = m6(d); at.before(r.b5.n); } }
134
- else if (r.b5 !== undefined) p6(r.b5, c, d);
165
+ if (c & 2) {
166
+ const t5 = (v[1] === "success");
167
+ if (true) {
168
+ {
169
+ r.b5 = undefined;
170
+ clearRegion(r.a5, r.e5);
171
+ if (t5) { r.b5 = m6(d); r.e5.before(r.b5.n); }
172
+ }
173
+ } else if (r.b5 !== undefined) p6(r.b5, c, d);
174
+ } else if (r.b5 !== undefined) p6(r.b5, c, d);
175
+ if (c & 2) {
176
+ const t6 = ((v[1] === "danger") || (v[1] === "caution"));
177
+ if (true) {
178
+ {
179
+ r.b6 = undefined;
180
+ clearRegion(r.a6, r.e6);
181
+ if (t6) { r.b6 = m7(d); r.e6.before(r.b6.n); }
182
+ }
183
+ } else if (r.b6 !== undefined) p7(r.b6, c, d);
184
+ } else if (r.b6 !== undefined) p7(r.b6, c, d);
185
+ if (c & 1) {
186
+ const t7 = truthy(v[0]);
187
+ if (true) {
188
+ {
189
+ r.b7 = undefined;
190
+ clearRegion(r.a7, r.e7);
191
+ if (t7) { r.b7 = m8(d); r.e7.before(r.b7.n); }
192
+ }
193
+ } else if (r.b7 !== undefined) p8(r.b7, c, d);
194
+ } else if (r.b7 !== undefined) p8(r.b7, c, d);
195
+ if (r.f8 === undefined) { r.f8 = 1; const at = fillSlot(r.a8, r.e8, "", J, false, undefined, d);
196
+ if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b8 = m9(d); at.before(r.b8.n); } }
197
+ else if (r.b8 !== undefined) p9(r.b8, c, d);
135
198
  };
136
199
  const t0 = element.firstChild;
137
200
  const t1 = t0.firstChild;
@@ -139,8 +202,12 @@ export function createUiCallout(options = {}, html) {
139
202
  const t3 = t2.nextSibling.nextSibling;
140
203
  const t4 = t3.nextSibling.nextSibling;
141
204
  const t5 = t4.nextSibling.nextSibling;
142
- const t6 = t0.nextSibling.firstChild;
143
- const R = { n: element, v0: undefined, a0: t1, e0: t1.nextSibling, b0: undefined, a1: t2, e1: t2.nextSibling, b1: undefined, a2: t3, e2: t3.nextSibling, b2: undefined, a3: t4, e3: t4.nextSibling, b3: undefined, a4: t5, e4: t5.nextSibling, b4: undefined, a5: t6, e5: t6.nextSibling, b5: undefined, f5: undefined };
205
+ const t6 = t5.nextSibling.nextSibling;
206
+ const t7 = t6.nextSibling.nextSibling;
207
+ const t8 = t0.nextSibling;
208
+ const t9 = t8.firstChild;
209
+ const t10 = t9.nextSibling.nextSibling;
210
+ const R = { n: element, v0: undefined, a0: t1, e0: t1.nextSibling, b0: undefined, a1: t2, e1: t2.nextSibling, b1: undefined, a2: t3, e2: t3.nextSibling, b2: undefined, a3: t4, e3: t4.nextSibling, b3: undefined, a4: t5, e4: t5.nextSibling, b4: undefined, a5: t6, e5: t6.nextSibling, b5: undefined, a6: t7, e6: t7.nextSibling, b6: undefined, a7: t9, e7: t9.nextSibling, b7: undefined, a8: t10, e8: t10.nextSibling, b8: undefined, f8: undefined };
144
211
  const I = { B };
145
212
  const J = project(I, children, slots);
146
213
  attachGeneratedController(element, S, v, ((c, d) => p0(R, c, d)), undefined, undefined, I);
@@ -9,6 +9,7 @@ export interface UiTabsElement extends HTMLDivElement {
9
9
  export interface UiTabsProps {
10
10
  activation?: "auto" | "manual" | null;
11
11
  density?: "comfortable" | "compact" | null;
12
+ group?: string | null;
12
13
  label?: string | null;
13
14
  orientation?: "horizontal" | "vertical" | null;
14
15
  stretch?: boolean | null;
package/vanilla/UiTabs.js CHANGED
@@ -10,7 +10,7 @@ const T3 = ["",[]];
10
10
  let P0, P1, P2, P3;
11
11
  const E = new Map();
12
12
  const S = { n: ["internalValue","tabs"], t: ["s",["l",["o",["id","s","label","s"]]]], f: import.meta.url, g: "ui-tabs", 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] }, x: dispatchDeclared };
13
- const D = { props: { "activation": { "required":false,"values":["auto","manual"],"default":"auto", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] }, "density": { "required":false,"values":["comfortable","compact"],"default":"comfortable", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] }, "label": { "required":false,"default":"Tabs", 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] }, "stretch": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" }, "value": { "required":false,"default":"", c: checkString, t: "string", j: 0, m: "s" } } };
13
+ const D = { props: { "activation": { "required":false,"values":["auto","manual"],"default":"auto", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] }, "density": { "required":false,"values":["comfortable","compact"],"default":"comfortable", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat),false] }, "group": { "required":false,"default":"", c: checkString, t: "string", j: 0, m: "s" }, "label": { "required":false,"default":"Tabs", 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] }, "stretch": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" }, "value": { "required":false,"default":"", c: checkString, t: "string", j: 0, m: "s" } } };
14
14
  const C = (host) => controller.default(host);
15
15
 
16
16
  export function createUiTabs(options = {}, html) {
@@ -22,7 +22,7 @@ export function createUiTabs(options = {}, html) {
22
22
  }
23
23
  element.setAttribute("data-component", "ui-tabs");
24
24
  element.append((P0 ??= buildTemplate(T0)).cloneNode(true));
25
- const v = ["", [], null, null, null, null, null, null];
25
+ const v = ["", [], null, null, null, null, null, null, null];
26
26
  const B = acceptProps(element, D, S.n, v, componentProps, [], html);
27
27
  const m1 = (d) => {
28
28
  const n = (P1 ??= buildTemplate(T1)).cloneNode(true);
@@ -74,18 +74,18 @@ export function createUiTabs(options = {}, html) {
74
74
  const p3 = (r, c, d) => {
75
75
  };
76
76
  const p0 = (r, c, d) => {
77
- if (c & 16) {
78
- const x0 = v[4];
77
+ if (c & 32) {
78
+ const x0 = v[5];
79
79
  const s0 = toAttribute(x0, "aria-label");
80
80
  if (s0 !== r.v0) writeAttribute(r.a0, "aria-label", r.v0 = s0);
81
81
  }
82
- if (c & 1073741856) {
83
- const x1 = v[5];
82
+ if (c & 1073741888) {
83
+ const x1 = v[6];
84
84
  const s1 = toAttribute(x1, "aria-orientation");
85
85
  if (s1 !== r.v1) writeAttribute(r.a0, "aria-orientation", r.v1 = s1);
86
86
  }
87
- if (c & 104) {
88
- const x2 = hostState(["density","stretch","orientation"], [v[3], v[6], v[5]]);
87
+ if (c & 200) {
88
+ const x2 = hostState(["density","stretch","orientation"], [v[3], v[7], v[6]]);
89
89
  const s2 = x2;
90
90
  if (s2 !== r.v2) writeAttribute(r.n, "data-ui-tabs-state", (r.v2 = s2) === "" ? null : s2);
91
91
  }
package/vue/UiBadge.vue CHANGED
@@ -40,7 +40,7 @@ const propValidityContract = {
40
40
  required: false,
41
41
  target: { attribute: 'variant' },
42
42
  description:
43
- 'Emphasis. subtle sets toned text over a soft wash; solid fills with the tone and uses contrasting text; outline keeps the surface with a toned edge.\n inverse uses a translucent contrasting surface and toned ink for a count or label on a filled control of that tone. Neutral looks the same in solid and\n subtle. overlay inherits the containing filled control\'s text colour on a faint translucent fill, without a visible rim or shadow. Its small circle is\n 20px. When space is constrained, the label truncates with an ellipsis while its full text remains available.',
43
+ 'Emphasis. subtle sets toned text over a soft wash; solid fills with the tone and uses contrasting text; outline keeps the surface with a toned edge.\n inverse uses a translucent contrasting surface and toned ink for a count or label on a filled control of that tone. Neutral looks the same in solid and\n subtle. overlay inherits the containing filled control\'s text colour on a faint translucent fill, with a quiet single-pixel boundary and no shadow. Its small circle is\n 20px. When space is constrained, the label truncates with an ellipsis while its full text remains available.',
44
44
  values: ['solid', 'subtle', 'outline', 'inverse', 'overlay'],
45
45
  default: 'subtle',
46
46
  },
@@ -536,14 +536,14 @@ const hostState = computed(() =>
536
536
  }
537
537
 
538
538
  /* A count can keep its containing control's contrasting ink instead of reversing it.
539
- The faint fill is painted over that control; no second rim or shadow competes with it. */
539
+ The faint fill preserves text contrast; a quiet boundary separates the count from its control. */
540
540
  [data-component~="ui-badge"][data-ui-badge-state~="variant=overlay"] {
541
541
  --_badge-outline-surface: var(
542
542
  --ui-badge-surface,
543
543
  color-mix(in srgb, currentColor 6%, transparent)
544
544
  );
545
545
  color: var(--ui-badge-text, inherit);
546
- border-color: var(--ui-badge-border, transparent);
546
+ border-color: var(--ui-badge-border, color-mix(in srgb, currentColor 20%, transparent));
547
547
  box-shadow: none;
548
548
  }
549
549
 
@@ -4,17 +4,26 @@ type __VLS_Slots = {} & {
4
4
  default?: (props: typeof __VLS_1) => any;
5
5
  };
6
6
  declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
7
+ heading: {
8
+ type: PropType<string | null>;
9
+ default: string;
10
+ };
7
11
  tone: {
8
- type: PropType<"info" | "neutral" | "note" | "warning" | "success" | "danger" | null>;
12
+ type: PropType<"info" | "neutral" | "note" | "tip" | "important" | "warning" | "caution" | "success" | "danger" | null>;
9
13
  default: string;
10
14
  };
11
15
  }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
16
+ heading: {
17
+ type: PropType<string | null>;
18
+ default: string;
19
+ };
12
20
  tone: {
13
- type: PropType<"info" | "neutral" | "note" | "warning" | "success" | "danger" | null>;
21
+ type: PropType<"info" | "neutral" | "note" | "tip" | "important" | "warning" | "caution" | "success" | "danger" | null>;
14
22
  default: string;
15
23
  };
16
24
  }>> & Readonly<{}>, {
17
- tone: "info" | "neutral" | "success" | "warning" | "danger" | "note" | null;
25
+ tone: "info" | "neutral" | "success" | "warning" | "danger" | "note" | "tip" | "important" | "caution" | null;
26
+ heading: string | null;
18
27
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
19
28
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
20
29
  declare const _default: typeof __VLS_export;
package/vue/UiCallout.vue CHANGED
@@ -8,34 +8,74 @@ defineOptions({ inheritAttrs: false })
8
8
 
9
9
  const propValidityContract = {
10
10
  props: {
11
+ heading: {
12
+ type: { kind: 'terminal', name: 'string' },
13
+ required: false,
14
+ target: { attribute: 'heading' },
15
+ description:
16
+ 'A short heading above the message, such as "Before you upgrade". Optional; without it the message stands alone.',
17
+ default: '',
18
+ },
11
19
  tone: {
12
20
  type: { kind: 'terminal', name: 'keyword' },
13
21
  required: false,
14
22
  target: { attribute: 'tone' },
15
23
  description:
16
- 'Which kind of message the callout carries, shown by its icon and colour: info (the default) for information, neutral for a muted aside, warning for a\n caution, success for a confirmation, and danger for a harmful consequence. note remains as an alias for neutral.',
17
- values: ['info', 'neutral', 'note', 'warning', 'success', 'danger'],
24
+ 'Which kind of message the callout carries, shown by its icon and colour: info (the default) for information, note or neutral for a muted aside, tip for\n advice, important for something the reader must not miss, warning for a caution, danger (or its alias caution) for a harmful consequence, and success for\n a confirmation. These are the tones of VitePress, Docusaurus and GitHub alerts.',
25
+ values: [
26
+ 'info',
27
+ 'neutral',
28
+ 'note',
29
+ 'tip',
30
+ 'important',
31
+ 'warning',
32
+ 'caution',
33
+ 'success',
34
+ 'danger',
35
+ ],
18
36
  default: 'info',
19
37
  },
20
38
  },
21
39
  } as const
22
40
  const props = defineProps({
41
+ heading: { type: null as unknown as PropType<string | null>, default: '' },
23
42
  tone: {
24
43
  type: null as unknown as PropType<
25
- 'info' | 'neutral' | 'note' | 'warning' | 'success' | 'danger' | null
44
+ | 'info'
45
+ | 'neutral'
46
+ | 'note'
47
+ | 'tip'
48
+ | 'important'
49
+ | 'warning'
50
+ | 'caution'
51
+ | 'success'
52
+ | 'danger'
53
+ | null
26
54
  >,
27
55
  default: 'info',
28
56
  },
29
57
  })
30
- const acceptedProps: Record<string, unknown> = { tone: 'info' }
58
+ const acceptedProps: Record<string, unknown> = { heading: '', tone: 'info' }
31
59
  const checkedProps = computed(() => ({
32
- tone: checkedProp<'info' | 'neutral' | 'note' | 'warning' | 'success' | 'danger'>(
33
- props['tone'],
34
- { kind: 'terminal', name: 'keyword' },
60
+ heading: checkedProp<string>(
61
+ props['heading'],
62
+ { kind: 'terminal', name: 'string' },
35
63
  false,
36
- 'tone',
64
+ 'heading',
37
65
  acceptedProps,
38
- ) as 'info' | 'neutral' | 'note' | 'warning' | 'success' | 'danger',
66
+ ) as string,
67
+ tone: checkedProp<
68
+ 'info' | 'neutral' | 'note' | 'tip' | 'important' | 'warning' | 'caution' | 'success' | 'danger'
69
+ >(props['tone'], { kind: 'terminal', name: 'keyword' }, false, 'tone', acceptedProps) as
70
+ | 'info'
71
+ | 'neutral'
72
+ | 'note'
73
+ | 'tip'
74
+ | 'important'
75
+ | 'warning'
76
+ | 'caution'
77
+ | 'success'
78
+ | 'danger',
39
79
  }))
40
80
  void checkedProps.value
41
81
  watchSyncEffect(() => {
@@ -107,6 +147,7 @@ const hostState = computed(() =>
107
147
  role="note"
108
148
  v-bind="nativeAttrs($attrs)"
109
149
  v-prop-validity="{ contract: propValidityContract, values: { ...props } }"
150
+ :data-heading="reflectedProp('heading', 'heading', checkedProps.heading, undefined, false)"
110
151
  :data-tone="reflectedProp('tone', 'tone', checkedProps.tone, undefined, false)"
111
152
  :data-ui-callout-state="hostState || undefined"
112
153
  >
@@ -136,6 +177,34 @@ const hostState = computed(() =>
136
177
  <path d="M13 2v7h7"></path>
137
178
  <path d="m9.5 17.5 4-4 2 2-4 4H9.5v-2Z"></path>
138
179
  </svg>
180
+ <svg
181
+ v-if="checkedProps.tone === 'tip'"
182
+ viewBox="0 0 24 24"
183
+ fill="none"
184
+ stroke="currentColor"
185
+ stroke-width="2"
186
+ stroke-linecap="round"
187
+ stroke-linejoin="round"
188
+ >
189
+ <path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5">
190
+ </path>
191
+ <path d="M9 18h6"></path>
192
+ <path d="M10 22h4"></path>
193
+ </svg>
194
+ <svg
195
+ v-if="checkedProps.tone === 'important'"
196
+ viewBox="0 0 24 24"
197
+ fill="none"
198
+ stroke="currentColor"
199
+ stroke-width="2"
200
+ stroke-linecap="round"
201
+ stroke-linejoin="round"
202
+ >
203
+ <path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z">
204
+ </path>
205
+ <path d="M12 15h.01"></path>
206
+ <path d="M12 7v4"></path>
207
+ </svg>
139
208
  <svg
140
209
  v-if="checkedProps.tone === 'warning'"
141
210
  viewBox="0 0 24 24"
@@ -162,7 +231,7 @@ const hostState = computed(() =>
162
231
  <path d="m9 12 2 2 4-4"></path>
163
232
  </svg>
164
233
  <svg
165
- v-if="checkedProps.tone === 'danger'"
234
+ v-if="checkedProps.tone === 'danger' || checkedProps.tone === 'caution'"
166
235
  viewBox="0 0 24 24"
167
236
  fill="none"
168
237
  stroke="currentColor"
@@ -174,7 +243,10 @@ const hostState = computed(() =>
174
243
  <path d="m15 9-6 6"></path>
175
244
  <path d="m9 9 6 6"></path>
176
245
  </svg></span>
177
- <div class="content"><slot /></div>
246
+ <div class="content">
247
+ <strong v-if="checkedProps.heading" class="heading">{{ checkedProps.heading }}</strong>
248
+ <slot />
249
+ </div>
178
250
  </div>
179
251
  </template>
180
252
 
@@ -306,6 +378,11 @@ const hostState = computed(() =>
306
378
  min-inline-size: 0;
307
379
  }
308
380
 
381
+ .heading {
382
+ display: block;
383
+ font-weight: var(--ui-font-semibold);
384
+ }
385
+
309
386
  [data-component~="ui-callout"][data-ui-callout-state~="tone=neutral"],
310
387
  [data-component~="ui-callout"][data-ui-callout-state~="tone=note"] {
311
388
  --_ui-selection-context-surface: initial;
@@ -316,6 +393,18 @@ const hostState = computed(() =>
316
393
  --_callout-icon: var(--ui-text-secondary);
317
394
  }
318
395
 
396
+ [data-component~="ui-callout"][data-ui-callout-state~="tone=tip"] {
397
+ --_callout-surface: var(--ui-success-soft);
398
+ --_callout-border: var(--ui-success-solid);
399
+ --_callout-icon: var(--ui-success-solid);
400
+ }
401
+
402
+ [data-component~="ui-callout"][data-ui-callout-state~="tone=important"] {
403
+ --_callout-surface: var(--ui-accent-soft);
404
+ --_callout-border: var(--ui-accent-solid);
405
+ --_callout-icon: var(--ui-accent-solid);
406
+ }
407
+
319
408
  [data-component~="ui-callout"][data-ui-callout-state~="tone=warning"] {
320
409
  --_callout-surface: var(--ui-warning-soft);
321
410
  --_callout-border: var(--ui-warning-solid);
@@ -328,7 +417,8 @@ const hostState = computed(() =>
328
417
  --_callout-icon: var(--ui-success-solid);
329
418
  }
330
419
 
331
- [data-component~="ui-callout"][data-ui-callout-state~="tone=danger"] {
420
+ [data-component~="ui-callout"][data-ui-callout-state~="tone=danger"],
421
+ [data-component~="ui-callout"][data-ui-callout-state~="tone=caution"] {
332
422
  --_callout-surface: var(--ui-danger-soft);
333
423
  --_callout-border: var(--ui-danger-solid);
334
424
  --_callout-icon: var(--ui-danger-solid);
@@ -33,8 +33,8 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
33
33
  };
34
34
  }>> & Readonly<{}>, {
35
35
  kind: "loading" | "error" | "empty" | null;
36
- layout: "fill" | "inline" | "panel" | null;
37
36
  heading: string | null;
37
+ layout: "fill" | "inline" | "panel" | null;
38
38
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
39
39
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
40
40
  declare const _default: typeof __VLS_export;
package/vue/UiTabs.d.ts CHANGED
@@ -14,6 +14,10 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
14
14
  type: PropType<"comfortable" | "compact" | null>;
15
15
  default: string;
16
16
  };
17
+ group: {
18
+ type: PropType<string | null>;
19
+ default: string;
20
+ };
17
21
  label: {
18
22
  type: PropType<string | null>;
19
23
  default: string;
@@ -46,6 +50,10 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
46
50
  type: PropType<"comfortable" | "compact" | null>;
47
51
  default: string;
48
52
  };
53
+ group: {
54
+ type: PropType<string | null>;
55
+ default: string;
56
+ };
49
57
  label: {
50
58
  type: PropType<string | null>;
51
59
  default: string;
@@ -72,6 +80,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
72
80
  }>, {
73
81
  label: string | null;
74
82
  value: string | null;
83
+ group: string | null;
75
84
  stretch: boolean | null;
76
85
  density: "comfortable" | "compact" | null;
77
86
  orientation: "vertical" | "horizontal" | null;