@threadlabs/looma 0.16.2 → 0.16.3

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.16.2",
3
+ "version": "0.16.3",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -67,6 +67,10 @@
67
67
  syntax: "*";
68
68
  inherits: false;
69
69
  }
70
+ @property --ui-button-white-space {
71
+ syntax: "*";
72
+ inherits: false;
73
+ }
70
74
  @scope ([data-component~="ui-button"]) to ([data-component], [data-slotted]) {
71
75
  /* This component's hooks style the element they are set on, and never a nested one. */
72
76
 
@@ -112,6 +116,8 @@
112
116
  font: inherit;
113
117
  font-weight: var(--ui-font-medium);
114
118
  text-decoration: none;
119
+ /* Unset, a button wraps as its container does. */
120
+ white-space: var(--ui-button-white-space, inherit);
115
121
  line-height: var(--ui-line-height-tight);
116
122
  padding: var(--ui-space-2) var(--ui-space-3);
117
123
  background-image: var(--ui-raised-highlight);
@@ -3,10 +3,30 @@
3
3
  syntax: "*";
4
4
  inherits: false;
5
5
  }
6
+ @property --ui-form-field-help-font-size {
7
+ syntax: "*";
8
+ inherits: false;
9
+ }
6
10
  @property --ui-form-field-help-min-block-size {
7
11
  syntax: "*";
8
12
  inherits: false;
9
13
  }
14
+ @property --ui-form-field-help-text {
15
+ syntax: "*";
16
+ inherits: false;
17
+ }
18
+ @property --ui-form-field-label-font-size {
19
+ syntax: "*";
20
+ inherits: false;
21
+ }
22
+ @property --ui-form-field-label-text {
23
+ syntax: "*";
24
+ inherits: false;
25
+ }
26
+ @property --ui-form-field-min-inline-size {
27
+ syntax: "*";
28
+ inherits: false;
29
+ }
10
30
  @scope ([data-component~="ui-form-field"]) to ([data-component], [data-slotted]) {
11
31
  /* This component's hooks style the element they are set on, and never a nested one. */
12
32
 
@@ -14,10 +34,14 @@
14
34
  /* Hooks do not inherit, so the parts below read them from the root. */
15
35
  --_ui-form-field-danger: var(--ui-form-field-danger);
16
36
  --_ui-form-field-help-min-block-size: var(--ui-form-field-help-min-block-size);
37
+ --_ui-form-field-label-text: var(--ui-form-field-label-text);
38
+ --_ui-form-field-label-font-size: var(--ui-form-field-label-font-size);
39
+ --_ui-form-field-help-text: var(--ui-form-field-help-text);
40
+ --_ui-form-field-help-font-size: var(--ui-form-field-help-font-size);
17
41
 
18
42
  display: grid;
19
43
  gap: var(--ui-space-2);
20
- min-inline-size: 0;
44
+ min-inline-size: var(--ui-form-field-min-inline-size, 0);
21
45
  align-content: start;
22
46
  color: var(--ui-text-primary);
23
47
  }
@@ -31,8 +55,8 @@
31
55
  }
32
56
 
33
57
  .label {
34
- color: var(--ui-text-secondary);
35
- font-size: var(--ui-font-size-sm);
58
+ color: var(--_ui-form-field-label-text, var(--ui-text-secondary));
59
+ font-size: var(--_ui-form-field-label-font-size, var(--ui-font-size-sm));
36
60
  }
37
61
 
38
62
  /* A label action, such as a small help button, sits after the label text in a box one line
@@ -55,8 +79,8 @@
55
79
  }
56
80
 
57
81
  .help {
58
- color: var(--ui-text-muted);
59
- font-size: var(--ui-font-size-sm);
82
+ color: var(--_ui-form-field-help-text, var(--ui-text-muted));
83
+ font-size: var(--_ui-form-field-help-font-size, var(--ui-font-size-sm));
60
84
  line-height: var(--ui-line-height-md);
61
85
  }
62
86
 
@@ -23,6 +23,10 @@
23
23
  syntax: "*";
24
24
  inherits: false;
25
25
  }
26
+ @property --ui-input-inline-size {
27
+ syntax: "*";
28
+ inherits: false;
29
+ }
26
30
  @property --ui-input-invalid-border {
27
31
  syntax: "*";
28
32
  inherits: false;
@@ -54,7 +58,7 @@
54
58
  :scope {
55
59
  box-sizing: border-box;
56
60
  display: inline-block;
57
- inline-size: 100%;
61
+ inline-size: var(--ui-input-inline-size, 100%);
58
62
  min-inline-size: 0;
59
63
  min-block-size: var(--ui-input-min-block-size, var(--_ui-default-input-min-block-size, var(--ui-control-size-md)));
60
64
  margin: 0;
@@ -11,6 +11,10 @@
11
11
  syntax: "*";
12
12
  inherits: false;
13
13
  }
14
+ @property --ui-nav-item-inline-size {
15
+ syntax: "*";
16
+ inherits: false;
17
+ }
14
18
  @scope ([data-component~="ui-nav-item"]) to ([data-component], [data-slotted]) {
15
19
  /* This component's hooks style the element they are set on, and never a nested one. */
16
20
 
@@ -26,7 +30,7 @@
26
30
  display: flex;
27
31
  align-items: center;
28
32
  gap: var(--ui-space-3);
29
- inline-size: 100%;
33
+ inline-size: var(--ui-nav-item-inline-size, 100%);
30
34
  min-inline-size: 0;
31
35
  min-block-size: var(--ui-control-size, 2.5rem);
32
36
  margin: 0;
@@ -1,8 +1,24 @@
1
1
  /* Generated by HTML Next 1.0.0-alpha.7. Do not edit. */
2
+ @property --ui-select-border {
3
+ syntax: "*";
4
+ inherits: false;
5
+ }
6
+ @property --ui-select-border-hover {
7
+ syntax: "*";
8
+ inherits: false;
9
+ }
10
+ @property --ui-select-focus-border {
11
+ syntax: "*";
12
+ inherits: false;
13
+ }
2
14
  @property --ui-select-focus-shadow {
3
15
  syntax: "*";
4
16
  inherits: false;
5
17
  }
18
+ @property --ui-select-inline-size {
19
+ syntax: "*";
20
+ inherits: false;
21
+ }
6
22
  @property --ui-select-invalid-border {
7
23
  syntax: "*";
8
24
  inherits: false;
@@ -19,20 +35,24 @@
19
35
  syntax: "*";
20
36
  inherits: false;
21
37
  }
38
+ @property --ui-select-surface {
39
+ syntax: "*";
40
+ inherits: false;
41
+ }
22
42
  @scope ([data-component~="ui-select"]) to ([data-component], [data-slotted]) {
23
43
  /* This component's hooks style the element they are set on, and never a nested one. */
24
44
 
25
45
  :scope {
26
46
  box-sizing: border-box;
27
47
  display: inline-block;
28
- inline-size: 100%;
48
+ inline-size: var(--ui-select-inline-size, 100%);
29
49
  min-inline-size: 0;
30
50
  min-block-size: var(--ui-control-size-md);
31
51
  margin: 0;
32
52
  padding: var(--ui-space-2) var(--ui-space-3);
33
- border: 1px solid var(--ui-control-border, var(--ui-border-strong));
53
+ border: 1px solid var(--ui-select-border, var(--ui-control-border, var(--ui-border-strong)));
34
54
  border-radius: var(--ui-select-radius, var(--ui-field-radius, var(--ui-radius-md)));
35
- background-color: var(--ui-control-surface, var(--ui-surface-elevated));
55
+ background-color: var(--ui-select-surface, var(--ui-control-surface, var(--ui-surface-elevated)));
36
56
  color: var(--ui-text-primary);
37
57
  color-scheme: light dark;
38
58
  font: inherit;
@@ -59,11 +79,11 @@
59
79
  }
60
80
 
61
81
  :scope:hover:not(:focus):not(:disabled) {
62
- border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
82
+ border-color: var(--ui-select-border-hover, var(--ui-control-border-hover, var(--ui-text-secondary)));
63
83
  }
64
84
 
65
85
  :scope:focus-visible {
66
- border-color: var(--ui-control-focus, var(--ui-accent-solid));
86
+ border-color: var(--ui-select-focus-border, var(--ui-control-focus, var(--ui-accent-solid)));
67
87
  outline: none;
68
88
  box-shadow: var(--ui-select-focus-shadow, var(--ui-control-inset), var(--ui-control-focus-halo-shadow));
69
89
  }
@@ -1,7 +1,8 @@
1
1
  /* Generated by HTML Next 1.0.0-alpha.7. Do not edit. */
2
2
  @scope ([data-component~="ui-text"]) to ([data-component], [data-slotted]) {
3
3
  /* Running text, set on the type scale and in a tone that says what it is, so a view never styles
4
- text of its own. The root is a paragraph unless as= names a span, div, small, strong, or label. */
4
+ text of its own. The root is a paragraph unless as= names a span, div, small, strong, label, or
5
+ heading. */
5
6
  :scope {
6
7
  margin: 0;
7
8
  min-inline-size: 0;
@@ -9,6 +10,13 @@
9
10
  text-align: start;
10
11
  }
11
12
 
13
+ /* A heading drops the browser's heading size and weight, so size and weight set it as they set
14
+ any text, and inherit keeps the text around it. */
15
+ :scope:is(h2, h3, h4, h5, h6) {
16
+ font-size: inherit;
17
+ font-weight: inherit;
18
+ }
19
+
12
20
  :scope[data-ui-text-state~="size=xs"] {
13
21
  font-size: var(--ui-font-size-xs);
14
22
  line-height: var(--ui-line-height);
@@ -90,7 +98,11 @@
90
98
  }
91
99
  @scope ([data-component~="ui-text"]) to ([data-component]) {
92
100
  /* Running text, set on the type scale and in a tone that says what it is, so a view never styles
93
- text of its own. The root is a paragraph unless as= names a span, div, small, strong, or label. */
101
+ text of its own. The root is a paragraph unless as= names a span, div, small, strong, label, or
102
+ heading. */
103
+
104
+ /* A heading drops the browser's heading size and weight, so size and weight set it as they set
105
+ any text, and inherit keeps the text around it. */
94
106
  /* Every status tone uses the text-safe token a subtle badge sets its words in, so text and badges
95
107
  in one tone match, and each holds 4.5:1 on sunken surfaces where some base colours fall short. */
96
108
 
@@ -11,7 +11,7 @@ export interface UiInputProps {
11
11
  readonly?: boolean | null;
12
12
  required?: boolean | null;
13
13
  size?: "sm" | "md" | "lg" | null;
14
- value?: string | null;
14
+ value?: string | number | null;
15
15
  attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
16
16
  children?: readonly (string | Node)[];
17
17
  slots?: Readonly<Record<string, readonly (string | Node)[]>>;
@@ -3,7 +3,7 @@ import { manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
3
3
  import * as controller from "../components/ui-input/ui-input.js";
4
4
  import "../styles/ui-input.css";
5
5
 
6
- const definition = {...{"contract":{"tag":"ui-input","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"default":false},"invalid":{"type":"boolean","required":false,"target":{"attribute":"aria-invalid"},"default":false},"readonly":{"type":"boolean","required":false,"target":{"attribute":"readonly"},"default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"default":false},"size":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"size"},"default":"md"},"value":{"type":"string","required":false,"target":{"attribute":"value"}}}},"template":{"kind":"element","name":"input","attributes":[{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"readonly","expression":"readonly","expressionPlan":{"source":"readonly","ast":{"kind":"id","name":"readonly"},"dependencies":["readonly"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"aria-invalid","expression":"invalid","expressionPlan":{"source":"invalid","ast":{"kind":"id","name":"invalid"},"dependencies":["invalid"]}}],"children":[]},"declarations":[],"root":{"kind":"native","element":"input","choices":["input"]}},source:{file:import.meta.url},css:""};
6
+ const definition = {...{"contract":{"tag":"ui-input","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"default":false},"invalid":{"type":"boolean","required":false,"target":{"attribute":"aria-invalid"},"default":false},"readonly":{"type":"boolean","required":false,"target":{"attribute":"readonly"},"default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"default":false},"size":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"size"},"default":"md"},"value":{"type":{"kind":"union","members":[{"kind":"terminal","name":"string"},{"kind":"terminal","name":"number"}]},"required":false,"target":{"attribute":"value"}}}},"template":{"kind":"element","name":"input","attributes":[{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"readonly","expression":"readonly","expressionPlan":{"source":"readonly","ast":{"kind":"id","name":"readonly"},"dependencies":["readonly"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"aria-invalid","expression":"invalid","expressionPlan":{"source":"invalid","ast":{"kind":"id","name":"invalid"},"dependencies":["invalid"]}}],"children":[]},"declarations":[],"root":{"kind":"native","element":"input","choices":["input"]}},source:{file:import.meta.url},css:""};
7
7
 
8
8
  export function createUiInput(options = {}) {
9
9
  const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
@@ -7,7 +7,7 @@ export interface UiTextElement extends HTMLElement {
7
7
  }
8
8
  export interface UiTextProps {
9
9
  align?: "start" | "center" | null;
10
- as?: "p" | "span" | "div" | "small" | "strong" | "label" | null;
10
+ as?: "p" | "span" | "div" | "small" | "strong" | "label" | "h2" | "h3" | "h4" | "h5" | "h6" | null;
11
11
  size?: "inherit" | "xs" | "sm" | "md" | "lg" | null;
12
12
  tone?: "default" | "secondary" | "muted" | "accent" | "danger" | "success" | "info" | "warning" | null;
13
13
  truncate?: boolean | null;
package/vanilla/UiText.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { componentRootIndex, manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
3
3
  import "../styles/ui-text.css";
4
4
 
5
- const definition = {...{"contract":{"tag":"ui-text","props":{"align":{"type":{"enum":["start","center"]},"required":false,"target":{"attribute":"align"},"default":"start"},"as":{"type":{"enum":["p","span","div","small","strong","label"]},"required":false,"target":{"attribute":"as"},"default":"p"},"size":{"type":{"enum":["inherit","xs","sm","md","lg"]},"required":false,"target":{"attribute":"size"},"default":"inherit"},"tone":{"type":{"enum":["default","secondary","muted","accent","danger","success","info","warning"]},"required":false,"target":{"attribute":"tone"},"default":"default"},"truncate":{"type":"boolean","required":false,"target":{"attribute":"truncate"},"default":false},"variant":{"type":{"enum":["body","eyebrow","code"]},"required":false,"target":{"attribute":"variant"},"default":"body"},"weight":{"type":{"enum":["inherit","normal","medium","semibold"]},"required":false,"target":{"attribute":"weight"},"default":"inherit"}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'span'","testPlan":{"source":"as = 'span'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"span"}},"dependencies":["as"]}}},{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'div'","testPlan":{"source":"as = 'div'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"div"}},"dependencies":["as"]}}},{"kind":"element","name":"small","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'small'","testPlan":{"source":"as = 'small'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"small"}},"dependencies":["as"]}}},{"kind":"element","name":"strong","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'strong'","testPlan":{"source":"as = 'strong'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"strong"}},"dependencies":["as"]}}},{"kind":"element","name":"label","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'label'","testPlan":{"source":"as = 'label'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"label"}},"dependencies":["as"]}}},{"kind":"element","name":"p","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"declarations":[],"root":{"kind":"native","element":"p","choices":["span","div","small","strong","label","p"]}},source:{file:import.meta.url},css:""};
5
+ const definition = {...{"contract":{"tag":"ui-text","props":{"align":{"type":{"enum":["start","center"]},"required":false,"target":{"attribute":"align"},"default":"start"},"as":{"type":{"enum":["p","span","div","small","strong","label","h2","h3","h4","h5","h6"]},"required":false,"target":{"attribute":"as"},"default":"p"},"size":{"type":{"enum":["inherit","xs","sm","md","lg"]},"required":false,"target":{"attribute":"size"},"default":"inherit"},"tone":{"type":{"enum":["default","secondary","muted","accent","danger","success","info","warning"]},"required":false,"target":{"attribute":"tone"},"default":"default"},"truncate":{"type":"boolean","required":false,"target":{"attribute":"truncate"},"default":false},"variant":{"type":{"enum":["body","eyebrow","code"]},"required":false,"target":{"attribute":"variant"},"default":"body"},"weight":{"type":{"enum":["inherit","normal","medium","semibold"]},"required":false,"target":{"attribute":"weight"},"default":"inherit"}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'span'","testPlan":{"source":"as = 'span'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"span"}},"dependencies":["as"]}}},{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'div'","testPlan":{"source":"as = 'div'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"div"}},"dependencies":["as"]}}},{"kind":"element","name":"small","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'small'","testPlan":{"source":"as = 'small'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"small"}},"dependencies":["as"]}}},{"kind":"element","name":"strong","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'strong'","testPlan":{"source":"as = 'strong'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"strong"}},"dependencies":["as"]}}},{"kind":"element","name":"label","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'label'","testPlan":{"source":"as = 'label'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"label"}},"dependencies":["as"]}}},{"kind":"element","name":"h2","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'h2'","testPlan":{"source":"as = 'h2'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"h2"}},"dependencies":["as"]}}},{"kind":"element","name":"h3","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'h3'","testPlan":{"source":"as = 'h3'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"h3"}},"dependencies":["as"]}}},{"kind":"element","name":"h4","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'h4'","testPlan":{"source":"as = 'h4'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"h4"}},"dependencies":["as"]}}},{"kind":"element","name":"h5","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'h5'","testPlan":{"source":"as = 'h5'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"h5"}},"dependencies":["as"]}}},{"kind":"element","name":"h6","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'h6'","testPlan":{"source":"as = 'h6'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"h6"}},"dependencies":["as"]}}},{"kind":"element","name":"p","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"declarations":[],"root":{"kind":"native","element":"p","choices":["span","div","small","strong","label","h2","h3","h4","h5","h6","p"]}},source:{file:import.meta.url},css:""};
6
6
 
7
7
  export function createUiText(options = {}) {
8
8
  const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
@@ -84,6 +84,81 @@ export function createUiText(options = {}) {
84
84
  }
85
85
  } else {
86
86
  }
87
+ } else if (root === 5) {
88
+ element = document.createElement("h2");
89
+ for (const [name, value] of Object.entries(attributes)) {
90
+ if (value === null || value === undefined || value === false) continue;
91
+ element.setAttribute(name, value === true ? "" : String(value));
92
+ }
93
+ element.setAttribute("data-component", "ui-text");
94
+ if (children.length > 0) {
95
+ for (const child of children) {
96
+ const node = typeof child === "string" ? document.createTextNode(child) : child;
97
+ projected.push([node, ""]);
98
+ element.append(node);
99
+ }
100
+ } else {
101
+ }
102
+ } else if (root === 6) {
103
+ element = document.createElement("h3");
104
+ for (const [name, value] of Object.entries(attributes)) {
105
+ if (value === null || value === undefined || value === false) continue;
106
+ element.setAttribute(name, value === true ? "" : String(value));
107
+ }
108
+ element.setAttribute("data-component", "ui-text");
109
+ if (children.length > 0) {
110
+ for (const child of children) {
111
+ const node = typeof child === "string" ? document.createTextNode(child) : child;
112
+ projected.push([node, ""]);
113
+ element.append(node);
114
+ }
115
+ } else {
116
+ }
117
+ } else if (root === 7) {
118
+ element = document.createElement("h4");
119
+ for (const [name, value] of Object.entries(attributes)) {
120
+ if (value === null || value === undefined || value === false) continue;
121
+ element.setAttribute(name, value === true ? "" : String(value));
122
+ }
123
+ element.setAttribute("data-component", "ui-text");
124
+ if (children.length > 0) {
125
+ for (const child of children) {
126
+ const node = typeof child === "string" ? document.createTextNode(child) : child;
127
+ projected.push([node, ""]);
128
+ element.append(node);
129
+ }
130
+ } else {
131
+ }
132
+ } else if (root === 8) {
133
+ element = document.createElement("h5");
134
+ for (const [name, value] of Object.entries(attributes)) {
135
+ if (value === null || value === undefined || value === false) continue;
136
+ element.setAttribute(name, value === true ? "" : String(value));
137
+ }
138
+ element.setAttribute("data-component", "ui-text");
139
+ if (children.length > 0) {
140
+ for (const child of children) {
141
+ const node = typeof child === "string" ? document.createTextNode(child) : child;
142
+ projected.push([node, ""]);
143
+ element.append(node);
144
+ }
145
+ } else {
146
+ }
147
+ } else if (root === 9) {
148
+ element = document.createElement("h6");
149
+ for (const [name, value] of Object.entries(attributes)) {
150
+ if (value === null || value === undefined || value === false) continue;
151
+ element.setAttribute(name, value === true ? "" : String(value));
152
+ }
153
+ element.setAttribute("data-component", "ui-text");
154
+ if (children.length > 0) {
155
+ for (const child of children) {
156
+ const node = typeof child === "string" ? document.createTextNode(child) : child;
157
+ projected.push([node, ""]);
158
+ element.append(node);
159
+ }
160
+ } else {
161
+ }
87
162
  } else {
88
163
  element = document.createElement("p");
89
164
  for (const [name, value] of Object.entries(attributes)) {
package/vue/UiButton.vue CHANGED
@@ -176,6 +176,10 @@ function attribute(value: unknown): any {
176
176
  syntax: "*";
177
177
  inherits: false;
178
178
  }
179
+ @property --ui-button-white-space {
180
+ syntax: "*";
181
+ inherits: false;
182
+ }
179
183
 
180
184
  [data-component~="ui-button"] {
181
185
  --_hue: var(--ui-accent);
@@ -219,6 +223,8 @@ function attribute(value: unknown): any {
219
223
  font: inherit;
220
224
  font-weight: var(--ui-font-medium);
221
225
  text-decoration: none;
226
+ /* Unset, a button wraps as its container does. */
227
+ white-space: var(--ui-button-white-space, inherit);
222
228
  line-height: var(--ui-line-height-tight);
223
229
  padding: var(--ui-space-2) var(--ui-space-3);
224
230
  background-image: var(--ui-raised-highlight);
@@ -60,19 +60,43 @@ useComponentHost(controllerModule.default, {
60
60
  syntax: "*";
61
61
  inherits: false;
62
62
  }
63
+ @property --ui-form-field-help-font-size {
64
+ syntax: "*";
65
+ inherits: false;
66
+ }
63
67
  @property --ui-form-field-help-min-block-size {
64
68
  syntax: "*";
65
69
  inherits: false;
66
70
  }
71
+ @property --ui-form-field-help-text {
72
+ syntax: "*";
73
+ inherits: false;
74
+ }
75
+ @property --ui-form-field-label-font-size {
76
+ syntax: "*";
77
+ inherits: false;
78
+ }
79
+ @property --ui-form-field-label-text {
80
+ syntax: "*";
81
+ inherits: false;
82
+ }
83
+ @property --ui-form-field-min-inline-size {
84
+ syntax: "*";
85
+ inherits: false;
86
+ }
67
87
 
68
88
  [data-component~="ui-form-field"] {
69
89
  /* Hooks do not inherit, so the parts below read them from the root. */
70
90
  --_ui-form-field-danger: var(--ui-form-field-danger);
71
91
  --_ui-form-field-help-min-block-size: var(--ui-form-field-help-min-block-size);
92
+ --_ui-form-field-label-text: var(--ui-form-field-label-text);
93
+ --_ui-form-field-label-font-size: var(--ui-form-field-label-font-size);
94
+ --_ui-form-field-help-text: var(--ui-form-field-help-text);
95
+ --_ui-form-field-help-font-size: var(--ui-form-field-help-font-size);
72
96
 
73
97
  display: grid;
74
98
  gap: var(--ui-space-2);
75
- min-inline-size: 0;
99
+ min-inline-size: var(--ui-form-field-min-inline-size, 0);
76
100
  align-content: start;
77
101
  color: var(--ui-text-primary);
78
102
  }
@@ -86,8 +110,8 @@ useComponentHost(controllerModule.default, {
86
110
  }
87
111
 
88
112
  .label {
89
- color: var(--ui-text-secondary);
90
- font-size: var(--ui-font-size-sm);
113
+ color: var(--_ui-form-field-label-text, var(--ui-text-secondary));
114
+ font-size: var(--_ui-form-field-label-font-size, var(--ui-font-size-sm));
91
115
  }
92
116
 
93
117
  /* A label action, such as a small help button, sits after the label text in a box one line
@@ -110,8 +134,8 @@ useComponentHost(controllerModule.default, {
110
134
  }
111
135
 
112
136
  .help {
113
- color: var(--ui-text-muted);
114
- font-size: var(--ui-font-size-sm);
137
+ color: var(--_ui-form-field-help-text, var(--ui-text-muted));
138
+ font-size: var(--_ui-form-field-help-font-size, var(--ui-font-size-sm));
115
139
  line-height: var(--ui-line-height-md);
116
140
  }
117
141
 
package/vue/UiInput.d.ts CHANGED
@@ -4,8 +4,8 @@ type __VLS_Props = {
4
4
  readonly?: boolean;
5
5
  required?: boolean;
6
6
  size?: 'sm' | 'md' | 'lg';
7
- value?: string;
8
- modelValue?: string | null;
7
+ value?: string | number;
8
+ modelValue?: string | number | null;
9
9
  };
10
10
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
11
  "update:modelValue": (value: string) => any;
package/vue/UiInput.vue CHANGED
@@ -13,8 +13,8 @@ const props = withDefaults(
13
13
  readonly?: boolean
14
14
  required?: boolean
15
15
  size?: 'sm' | 'md' | 'lg'
16
- value?: string
17
- modelValue?: string | null
16
+ value?: string | number
17
+ modelValue?: string | number | null
18
18
  }>(),
19
19
  {
20
20
  disabled: false,
@@ -91,6 +91,10 @@ useComponentHost(controllerModule.default, {
91
91
  syntax: "*";
92
92
  inherits: false;
93
93
  }
94
+ @property --ui-input-inline-size {
95
+ syntax: "*";
96
+ inherits: false;
97
+ }
94
98
  @property --ui-input-invalid-border {
95
99
  syntax: "*";
96
100
  inherits: false;
@@ -119,7 +123,7 @@ useComponentHost(controllerModule.default, {
119
123
  [data-component~="ui-input"] {
120
124
  box-sizing: border-box;
121
125
  display: inline-block;
122
- inline-size: 100%;
126
+ inline-size: var(--ui-input-inline-size, 100%);
123
127
  min-inline-size: 0;
124
128
  min-block-size: var(
125
129
  --ui-input-min-block-size,
package/vue/UiNavItem.vue CHANGED
@@ -87,6 +87,10 @@ function attribute(value: unknown): any {
87
87
  syntax: "*";
88
88
  inherits: false;
89
89
  }
90
+ @property --ui-nav-item-inline-size {
91
+ syntax: "*";
92
+ inherits: false;
93
+ }
90
94
 
91
95
  /* One destination in a side or rail navigation: an icon to find it by (leading), its name (the
92
96
  default slot), and an optional line under it (description), such as the record a section
@@ -100,7 +104,7 @@ function attribute(value: unknown): any {
100
104
  display: flex;
101
105
  align-items: center;
102
106
  gap: var(--ui-space-3);
103
- inline-size: 100%;
107
+ inline-size: var(--ui-nav-item-inline-size, 100%);
104
108
  min-inline-size: 0;
105
109
  min-block-size: var(--ui-control-size, 2.5rem);
106
110
  margin: 0;
package/vue/UiSelect.vue CHANGED
@@ -65,10 +65,26 @@ useComponentHost(controllerModule.default, {
65
65
 
66
66
  <style scoped>
67
67
  /* This component's hooks style the element they are set on, and never a nested one. */
68
+ @property --ui-select-border {
69
+ syntax: "*";
70
+ inherits: false;
71
+ }
72
+ @property --ui-select-border-hover {
73
+ syntax: "*";
74
+ inherits: false;
75
+ }
76
+ @property --ui-select-focus-border {
77
+ syntax: "*";
78
+ inherits: false;
79
+ }
68
80
  @property --ui-select-focus-shadow {
69
81
  syntax: "*";
70
82
  inherits: false;
71
83
  }
84
+ @property --ui-select-inline-size {
85
+ syntax: "*";
86
+ inherits: false;
87
+ }
72
88
  @property --ui-select-invalid-border {
73
89
  syntax: "*";
74
90
  inherits: false;
@@ -85,18 +101,22 @@ useComponentHost(controllerModule.default, {
85
101
  syntax: "*";
86
102
  inherits: false;
87
103
  }
104
+ @property --ui-select-surface {
105
+ syntax: "*";
106
+ inherits: false;
107
+ }
88
108
 
89
109
  [data-component~="ui-select"] {
90
110
  box-sizing: border-box;
91
111
  display: inline-block;
92
- inline-size: 100%;
112
+ inline-size: var(--ui-select-inline-size, 100%);
93
113
  min-inline-size: 0;
94
114
  min-block-size: var(--ui-control-size-md);
95
115
  margin: 0;
96
116
  padding: var(--ui-space-2) var(--ui-space-3);
97
- border: 1px solid var(--ui-control-border, var(--ui-border-strong));
117
+ border: 1px solid var(--ui-select-border, var(--ui-control-border, var(--ui-border-strong)));
98
118
  border-radius: var(--ui-select-radius, var(--ui-field-radius, var(--ui-radius-md)));
99
- background-color: var(--ui-control-surface, var(--ui-surface-elevated));
119
+ background-color: var(--ui-select-surface, var(--ui-control-surface, var(--ui-surface-elevated)));
100
120
  color: var(--ui-text-primary);
101
121
  color-scheme: light dark;
102
122
  font: inherit;
@@ -123,11 +143,14 @@ useComponentHost(controllerModule.default, {
123
143
  }
124
144
 
125
145
  [data-component~="ui-select"]:hover:not(:focus):not(:disabled) {
126
- border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
146
+ border-color: var(
147
+ --ui-select-border-hover,
148
+ var(--ui-control-border-hover, var(--ui-text-secondary))
149
+ );
127
150
  }
128
151
 
129
152
  [data-component~="ui-select"]:focus-visible {
130
- border-color: var(--ui-control-focus, var(--ui-accent-solid));
153
+ border-color: var(--ui-select-focus-border, var(--ui-control-focus, var(--ui-accent-solid)));
131
154
  outline: none;
132
155
  box-shadow: var(
133
156
  --ui-select-focus-shadow,