@threadlabs/looma 0.14.0 → 0.14.2

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.14.0",
3
+ "version": "0.14.2",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -3,24 +3,63 @@
3
3
  /* Named values: a term and what it is, for each item (ui-description-item). */
4
4
  /* Rows line every term up in one column and every value in the next, through subgrid. */
5
5
  :scope {
6
+ --_gap: var(--ui-space-2);
7
+ --_gap-compact: var(--ui-space-1);
8
+ --_column-gap: var(--ui-space-6);
9
+ --_min: 10rem;
10
+ --_track: var(--_min);
11
+ --_tile-padding: var(--ui-space-3);
6
12
  display: grid;
7
13
  grid-template-columns: minmax(6rem, max-content) minmax(0, 1fr);
8
- gap: var(--ui-space-2) var(--ui-space-6);
14
+ gap: var(--_gap) var(--_column-gap);
9
15
  min-inline-size: 0;
10
16
  margin: 0;
11
17
  }
12
18
 
13
- /* Tiles pass their shape to the items through private properties, which cross into each item. */
19
+ /* Stacked, grid, and tiles set each term above its value, passing the shape to the items through
20
+ private properties, which cross into each item. */
21
+ :scope[data-ui-description-list-state~="layout=stacked"],
22
+ :scope[data-ui-description-list-state~="layout=grid"],
14
23
  :scope[data-ui-description-list-state~="layout=tiles"] {
15
24
  --_ui-description-display: flex;
16
25
  --_ui-description-column: auto;
26
+ --_ui-description-align: stretch;
27
+ --_gap: var(--ui-space-4);
28
+ --_gap-compact: var(--ui-space-2);
29
+ grid-template-columns: minmax(0, 1fr);
30
+ }
31
+
32
+ /* A column is at least --_min wide; with columns set, at least its share of the width, so no more
33
+ than that many fit. */
34
+ :scope[data-ui-description-list-state~="layout=grid"],
35
+ :scope[data-ui-description-list-state~="layout=tiles"] {
36
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--_track)), 1fr));
37
+ }
38
+
39
+ :scope[data-ui-description-list-state~="layout=tiles"] {
17
40
  --_ui-description-align: flex-start;
18
41
  --_ui-description-value-size: var(--ui-font-size-lg);
19
- --_ui-description-padding: var(--ui-space-3);
42
+ --_ui-description-padding: var(--_tile-padding);
20
43
  --_ui-description-border-width: 1px;
21
- display: grid;
22
- grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr));
23
- gap: var(--ui-space-3);
44
+ --_gap: var(--ui-space-3);
45
+ --_gap-compact: var(--ui-space-2);
46
+ --_column-gap: var(--_gap);
47
+ }
48
+
49
+ :scope[data-ui-description-list-state~="columns=2"] {
50
+ --_track: max(var(--_min), (100% - var(--_column-gap)) / 2);
51
+ }
52
+ :scope[data-ui-description-list-state~="columns=3"] {
53
+ --_track: max(var(--_min), (100% - 2 * var(--_column-gap)) / 3);
54
+ }
55
+ :scope[data-ui-description-list-state~="columns=4"] {
56
+ --_track: max(var(--_min), (100% - 3 * var(--_column-gap)) / 4);
57
+ }
58
+
59
+ /* Compact takes each layout's closer spacing. */
60
+ :scope[data-ui-description-list-state~="density=compact"] {
61
+ --_gap: var(--_gap-compact);
62
+ --_tile-padding: var(--ui-space-2);
24
63
  }
25
64
 
26
65
  /* A component that sets its display still honours the hidden attribute on its root. */
@@ -32,7 +71,13 @@
32
71
  /* Named values: a term and what it is, for each item (ui-description-item). */
33
72
  /* Rows line every term up in one column and every value in the next, through subgrid. */
34
73
 
35
- /* Tiles pass their shape to the items through private properties, which cross into each item. */
74
+ /* Stacked, grid, and tiles set each term above its value, passing the shape to the items through
75
+ private properties, which cross into each item. */
76
+
77
+ /* A column is at least --_min wide; with columns set, at least its share of the width, so no more
78
+ than that many fit. */
79
+
80
+ /* Compact takes each layout's closer spacing. */
36
81
 
37
82
  /* A component that sets its display still honours the hidden attribute on its root. */
38
83
  }
@@ -0,0 +1,81 @@
1
+ /* Generated by HTML Next 1.0.0-alpha.7. Do not edit. */
2
+ @property --ui-meter-inline-size {
3
+ syntax: "*";
4
+ inherits: false;
5
+ }
6
+ @scope ([data-component~="ui-meter"]) to ([data-component], [data-slotted]) {
7
+ /* How far along something is: a track, filled from the start in the tone's colour. The track is a
8
+ quiet border colour, so an empty meter still shows; every tone's fill keeps 3:1 against the
9
+ track and the page. */
10
+
11
+ :scope {
12
+ --_meter-fill: var(--ui-text-muted);
13
+
14
+ display: inline-block;
15
+ flex: none;
16
+ vertical-align: middle;
17
+ inline-size: var(--ui-meter-inline-size, 8rem);
18
+ max-inline-size: 100%;
19
+ block-size: var(--ui-space-2);
20
+ overflow: hidden;
21
+ border-radius: var(--ui-radius-round);
22
+ background: var(--ui-border);
23
+ /* Unseen until forced colours draw it, where the track's own colour is gone. */
24
+ outline: 1px solid transparent;
25
+ }
26
+
27
+ :scope[data-ui-meter-state~="size=sm"] {
28
+ inline-size: var(--ui-meter-inline-size, 5rem);
29
+ block-size: var(--ui-space-1);
30
+ }
31
+
32
+ .fill {
33
+ display: block;
34
+ block-size: 100%;
35
+ background: var(--_meter-fill);
36
+ }
37
+
38
+ :scope[data-ui-meter-state~="tone=accent"] {
39
+ --_meter-fill: var(--ui-accent-solid);
40
+ }
41
+
42
+ :scope[data-ui-meter-state~="tone=info"] {
43
+ --_meter-fill: var(--ui-info-solid);
44
+ }
45
+
46
+ :scope[data-ui-meter-state~="tone=success"] {
47
+ --_meter-fill: var(--ui-success-solid);
48
+ }
49
+
50
+ :scope[data-ui-meter-state~="tone=warning"] {
51
+ --_meter-fill: var(--ui-warning-solid);
52
+ }
53
+
54
+ :scope[data-ui-meter-state~="tone=danger"] {
55
+ --_meter-fill: var(--ui-danger-solid);
56
+ }
57
+
58
+ /* Forced colours drop backgrounds: draw the fill in the text colour inside the outlined track. */
59
+ @media (forced-colors: active) {
60
+ .fill {
61
+ forced-color-adjust: none;
62
+ background: CanvasText;
63
+ }
64
+ }
65
+
66
+ /* A component that sets its display still honours the hidden attribute on its root. */
67
+ :scope[hidden] {
68
+ display: none;
69
+ }
70
+ }
71
+ @scope ([data-component~="ui-meter"]) to ([data-component]) {
72
+ /* How far along something is: a track, filled from the start in the tone's colour. The track is a
73
+ quiet border colour, so an empty meter still shows; every tone's fill keeps 3:1 against the
74
+ track and the page. */
75
+
76
+ /* Forced colours drop backgrounds: draw the fill in the text colour inside the outlined track. */
77
+ @media (forced-colors: active) {
78
+ }
79
+
80
+ /* A component that sets its display still honours the hidden attribute on its root. */
81
+ }
@@ -0,0 +1,134 @@
1
+ /* Generated by HTML Next 1.0.0-alpha.7. Do not edit. */
2
+ @scope ([data-component~="ui-table"]) to ([data-component], [data-slotted]) {
3
+ /* Styles an authored <table> (caption, thead, tbody, th scope) without replacing it: the table is
4
+ meaningful before JavaScript, and a screen reader reads it as a table. The root scrolls a table
5
+ wider than it, or taller than a bounded height; while it does, the controller makes the root a named, focusable region so a
6
+ keyboard can scroll it. A cell's data-ui-align (start, center, or end; start by default) sets its
7
+ content along the row, such as end for a column of figures. */
8
+ :scope {
9
+ --_pad-block: var(--ui-space-1);
10
+ --_pad-inline: var(--ui-space-3);
11
+ --_row-size: var(--ui-control-size);
12
+ display: block;
13
+ box-sizing: border-box;
14
+ max-inline-size: 100%;
15
+ min-inline-size: 0;
16
+ min-block-size: 0;
17
+ overflow: auto;
18
+ overscroll-behavior-inline: contain;
19
+ /* The sideways scroll fade every Looma scroller uses (see ui-scroll-area). Only the inline edges
20
+ fade, so a sticky header never fades. */
21
+ --_ui-scroll-fade-direction: to right;
22
+ --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);
23
+ mask-image: linear-gradient(
24
+ var(--_ui-scroll-fade-direction),
25
+ transparent,
26
+ #000 var(--_ui-scroll-fade-start),
27
+ #000 calc(100% - var(--_ui-scroll-fade-end)),
28
+ transparent
29
+ );
30
+ animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;
31
+ animation-timeline: scroll(self inline);
32
+ animation-range:
33
+ 0 var(--_ui-scroll-fade-size),
34
+ var(--_ui-scroll-fade-size) calc(100% + 1px),
35
+ -1px calc(100% - var(--_ui-scroll-fade-size)),
36
+ calc(100% - var(--_ui-scroll-fade-size)) 100%;
37
+ }
38
+
39
+ :scope:dir(rtl) {
40
+ --_ui-scroll-fade-direction: to left;
41
+ }
42
+
43
+ :scope:focus-visible {
44
+ outline: 2px solid var(--ui-focus-ring);
45
+ outline-offset: -2px;
46
+ }
47
+
48
+ :scope[data-ui-table-state~="density=compact"] {
49
+ --_pad-block: var(--ui-space-0-5);
50
+ --_pad-inline: var(--ui-space-2);
51
+ --_row-size: var(--ui-control-size-sm);
52
+ }
53
+
54
+ /* Separate borders stay on their cells when a sticky header scrolls; collapsed ones stay behind. */
55
+
56
+ /* Every row is at least one control tall, so a row holding a checkbox, select, or input keeps the
57
+ rhythm of the rows around it. A cell's height is its minimum. */
58
+
59
+ /* A component that sets its display still honours the hidden attribute on its root. */
60
+ :scope[hidden] {
61
+ display: none;
62
+ }
63
+ }
64
+ @scope ([data-component~="ui-table"]) to ([data-component]) {
65
+ /* Styles an authored <table> (caption, thead, tbody, th scope) without replacing it: the table is
66
+ meaningful before JavaScript, and a screen reader reads it as a table. The root scrolls a table
67
+ wider than it, or taller than a bounded height; while it does, the controller makes the root a named, focusable region so a
68
+ keyboard can scroll it. A cell's data-ui-align (start, center, or end; start by default) sets its
69
+ content along the row, such as end for a column of figures. */
70
+
71
+ /* Separate borders stay on their cells when a sticky header scrolls; collapsed ones stay behind. */
72
+ :where([data-slotted], [data-slotted] *):is(table) {
73
+ inline-size: 100%;
74
+ border-collapse: separate;
75
+ border-spacing: 0;
76
+ color: var(--ui-text-primary);
77
+ font-size: var(--ui-font-size-sm);
78
+ line-height: var(--ui-line-height);
79
+ font-variant-numeric: tabular-nums;
80
+ }
81
+
82
+ :where([data-slotted], [data-slotted] *):is(caption) {
83
+ padding-block-end: var(--ui-space-2);
84
+ color: var(--ui-text-secondary);
85
+ font-weight: var(--ui-font-medium);
86
+ text-align: start;
87
+ }
88
+
89
+ /* Every row is at least one control tall, so a row holding a checkbox, select, or input keeps the
90
+ rhythm of the rows around it. A cell's height is its minimum. */
91
+ :where([data-slotted], [data-slotted] *):is(th),
92
+ :where([data-slotted], [data-slotted] *):is(td) {
93
+ block-size: var(--_row-size);
94
+ padding: var(--_pad-block) var(--_pad-inline);
95
+ border-block-end: 1px solid var(--ui-border-subtle);
96
+ text-align: start;
97
+ vertical-align: middle;
98
+ }
99
+
100
+ :where([data-slotted], [data-slotted] *):is(thead th) {
101
+ block-size: auto;
102
+ padding-block: var(--ui-space-2);
103
+ border-block-end-color: var(--ui-border-default);
104
+ background: var(--ui-surface);
105
+ color: var(--ui-text-muted);
106
+ font-weight: var(--ui-font-medium);
107
+ white-space: nowrap;
108
+ vertical-align: bottom;
109
+ }
110
+
111
+ :where([data-slotted], [data-slotted] *):is(tbody th) {
112
+ font-weight: var(--ui-font-medium);
113
+ }
114
+
115
+ :where([data-slotted], [data-slotted] *):is(tbody tr:last-child > *) {
116
+ border-block-end-width: 0;
117
+ }
118
+
119
+ :where([data-slotted], [data-slotted] *):is([data-ui-align="center"]) {
120
+ text-align: center;
121
+ }
122
+
123
+ :where([data-slotted], [data-slotted] *):is([data-ui-align="end"]) {
124
+ text-align: end;
125
+ }
126
+
127
+ :scope[data-ui-table-state~="stickyHeader"] :where([data-slotted], [data-slotted] *):is(thead th) {
128
+ position: sticky;
129
+ inset-block-start: 0;
130
+ z-index: 1;
131
+ }
132
+
133
+ /* A component that sets its display still honours the hidden attribute on its root. */
134
+ }
@@ -6,7 +6,9 @@ export interface UiDescriptionListElement extends HTMLDListElement {
6
6
  removeEventListener<K extends keyof UiDescriptionListEventMap>(type: K, listener: (this: UiDescriptionListElement, event: UiDescriptionListEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
7
7
  }
8
8
  export interface UiDescriptionListProps {
9
- layout?: "rows" | "tiles" | null;
9
+ columns?: "2" | "3" | "4" | null;
10
+ density?: "comfortable" | "compact" | null;
11
+ layout?: "rows" | "stacked" | "grid" | "tiles" | null;
10
12
  attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
11
13
  children?: readonly (string | Node)[];
12
14
  slots?: Readonly<Record<string, readonly (string | Node)[]>>;
@@ -5,7 +5,9 @@ import "../styles/ui-description-list.css";
5
5
  export function createUiDescriptionList(options = {}) {
6
6
  const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
7
7
  const projected = [];
8
- const prop0 = componentProps["layout"] === undefined ? "rows" : componentProps["layout"];
8
+ const prop0 = componentProps["columns"] === undefined ? undefined : componentProps["columns"];
9
+ const prop1 = componentProps["density"] === undefined ? "comfortable" : componentProps["density"];
10
+ const prop2 = componentProps["layout"] === undefined ? "rows" : componentProps["layout"];
9
11
  const element = document.createElement("dl");
10
12
  for (const [name, value] of Object.entries(attributes)) {
11
13
  if (value === null || value === undefined || value === false) continue;
@@ -21,7 +23,9 @@ export function createUiDescriptionList(options = {}) {
21
23
  } else {
22
24
  }
23
25
  manageGeneratedProps(element, [
24
- { name: "layout", attribute: "data-layout", value: componentProps["layout"], default: "rows", type: ["rows","tiles"], required: false },
26
+ { name: "columns", attribute: "data-columns", value: componentProps["columns"], type: ["2","3","4"], required: false },
27
+ { name: "density", attribute: "data-density", value: componentProps["density"], default: "comfortable", type: ["comfortable","compact"], required: false },
28
+ { name: "layout", attribute: "data-layout", value: componentProps["layout"], default: "rows", type: ["rows","stacked","grid","tiles"], required: false },
25
29
  ]);
26
30
  return element;
27
31
  }
@@ -0,0 +1,19 @@
1
+ // Generated by HTML Next 1.0.0-alpha.7 for Vanilla DOM. Do not edit.
2
+ export interface UiMeterEventMap {
3
+ }
4
+ export interface UiMeterElement extends HTMLSpanElement {
5
+ addEventListener<K extends keyof UiMeterEventMap>(type: K, listener: (this: UiMeterElement, event: UiMeterEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
6
+ removeEventListener<K extends keyof UiMeterEventMap>(type: K, listener: (this: UiMeterElement, event: UiMeterEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
7
+ }
8
+ export interface UiMeterProps {
9
+ label?: string | null;
10
+ max?: number | null;
11
+ size?: "sm" | "md" | null;
12
+ tone?: "neutral" | "accent" | "info" | "success" | "warning" | "danger" | null;
13
+ value?: number | null;
14
+ valueText?: string | null;
15
+ attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
16
+ children?: readonly (string | Node)[];
17
+ slots?: Readonly<Record<string, readonly (string | Node)[]>>;
18
+ }
19
+ export declare function createUiMeter(props?: UiMeterProps): UiMeterElement;
@@ -0,0 +1,28 @@
1
+ // Generated by HTML Next 1.0.0-alpha.7 for Vanilla DOM. Do not edit.
2
+ import { manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
3
+ import "../styles/ui-meter.css";
4
+
5
+ const definition = {...{"contract":{"tag":"ui-meter","props":{"label":{"type":"string","required":false,"target":{"attribute":"label"},"default":""},"max":{"type":"number","required":false,"target":{"attribute":"aria-valuemax"},"default":1},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"default":"md"},"tone":{"type":{"enum":["neutral","accent","info","success","warning","danger"]},"required":false,"target":{"attribute":"tone"},"default":"neutral"},"value":{"type":"number","required":false,"target":{"attribute":"value"},"default":0},"valueText":{"type":"string","required":false,"target":{"attribute":"valuetext"},"default":""}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"role","value":"meter"},{"kind":"literal","name":"aria-valuemin","value":"0"},{"kind":"attribute","name":"aria-valuemax","expression":"max","expressionPlan":{"source":"max","ast":{"kind":"id","name":"max"},"dependencies":["max"]}},{"kind":"attribute","name":"aria-valuenow","expression":"amount","expressionPlan":{"source":"amount","ast":{"kind":"id","name":"amount"},"dependencies":["amount"]}},{"kind":"attribute","name":"aria-valuetext","expression":"{ true: valueText, false: format('%s%', whole) }[format('%s', valueText != '')]","expressionPlan":{"source":"{ true: valueText, false: format('%s%', whole) }[format('%s', valueText != '')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"id","name":"valueText"}},{"key":"false","value":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s%"},{"kind":"id","name":"whole"}]}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"!=","left":{"kind":"id","name":"valueText"},"right":{"kind":"literal","value":""}}]}},"dependencies":["valueText","whole"]}},{"kind":"attribute","name":"aria-label","expression":"{ true: label, false: null }[format('%s', label != '')]","expressionPlan":{"source":"{ true: label, false: null }[format('%s', label != '')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"id","name":"label"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"!=","left":{"kind":"id","name":"label"},"right":{"kind":"literal","value":""}}]}},"dependencies":["label"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"fill"},{"kind":"attribute","name":"inline-size","expression":"format('%s%', percent)","expressionPlan":{"source":"format('%s%', percent)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s%"},{"kind":"id","name":"percent"}]},"dependencies":["percent"]},"target":"style"}],"children":[]}]},"declarations":[{"kind":"computed","name":"amount","expression":{"source":"clamp(0, value, max)","ast":{"kind":"call","fn":"clamp","args":[{"kind":"literal","value":0},{"kind":"id","name":"value"},{"kind":"id","name":"max"}]},"dependencies":["max","value"]}},{"kind":"computed","name":"percent","expression":{"source":"{ true: amount / max * 100, false: 0 }[format('%s', max > 0)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"binary","op":"*","left":{"kind":"binary","op":"/","left":{"kind":"id","name":"amount"},"right":{"kind":"id","name":"max"}},"right":{"kind":"literal","value":100}}},{"key":"false","value":{"kind":"literal","value":0}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":">","left":{"kind":"id","name":"max"},"right":{"kind":"literal","value":0}}]}},"dependencies":["amount","max"]}},{"kind":"computed","name":"whole","expression":{"source":"percent + 0.5 - (percent + 0.5) % 1","ast":{"kind":"binary","op":"-","left":{"kind":"binary","op":"+","left":{"kind":"id","name":"percent"},"right":{"kind":"literal","value":0.5}},"right":{"kind":"binary","op":"%","left":{"kind":"binary","op":"+","left":{"kind":"id","name":"percent"},"right":{"kind":"literal","value":0.5}},"right":{"kind":"literal","value":1}}},"dependencies":["percent"]}}],"root":{"kind":"native","element":"span","choices":["span"]}},source:{file:import.meta.url},css:""};
6
+
7
+ export function createUiMeter(options = {}) {
8
+ const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
9
+ const projected = [];
10
+ const element = document.createElement("span");
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("role")) element.setAttribute("role", "meter");
16
+ if (!element.hasAttribute("aria-valuemin")) element.setAttribute("aria-valuemin", "0");
17
+ const value0 = componentProps["max"] === undefined ? 1 : componentProps["max"];
18
+ if (value0 === null || value0 === undefined) element.removeAttribute("aria-valuemax");
19
+ else element.setAttribute("aria-valuemax", String(value0));
20
+ element.setAttribute("data-component", "ui-meter");
21
+ const element0 = document.createElement("span");
22
+ element0.setAttribute("class", "fill");
23
+ element.append(element0);
24
+ manageComponentLifecycle(element, definition, { props: componentProps, projected,
25
+ });
26
+ return element;
27
+ }
28
+
@@ -0,0 +1,15 @@
1
+ // Generated by HTML Next 1.0.0-alpha.7 for Vanilla DOM. Do not edit.
2
+ export interface UiTableEventMap {
3
+ }
4
+ export interface UiTableElement extends HTMLDivElement {
5
+ addEventListener<K extends keyof UiTableEventMap>(type: K, listener: (this: UiTableElement, event: UiTableEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
6
+ removeEventListener<K extends keyof UiTableEventMap>(type: K, listener: (this: UiTableElement, event: UiTableEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
7
+ }
8
+ export interface UiTableProps {
9
+ density?: "comfortable" | "compact" | null;
10
+ stickyHeader?: boolean | null;
11
+ attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
12
+ children?: readonly (string | Node)[];
13
+ slots?: Readonly<Record<string, readonly (string | Node)[]>>;
14
+ }
15
+ export declare function createUiTable(props?: UiTableProps): UiTableElement;
@@ -0,0 +1,30 @@
1
+ // Generated by HTML Next 1.0.0-alpha.7 for Vanilla DOM. Do not edit.
2
+ import { manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
3
+ import * as controller from "../components/ui-table/ui-table.js";
4
+ import "../styles/ui-table.css";
5
+
6
+ const definition = {...{"contract":{"tag":"ui-table","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"default":"comfortable"},"stickyHeader":{"type":"boolean","required":false,"target":{"attribute":"stickyheader"},"default":false}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"declarations":[],"root":{"kind":"native","element":"div","choices":["div"]}},source:{file:import.meta.url},css:""};
7
+
8
+ export function createUiTable(options = {}) {
9
+ const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
10
+ const projected = [];
11
+ const element = document.createElement("div");
12
+ for (const [name, value] of Object.entries(attributes)) {
13
+ if (value === null || value === undefined || value === false) continue;
14
+ element.setAttribute(name, value === true ? "" : String(value));
15
+ }
16
+ element.setAttribute("data-component", "ui-table");
17
+ if (children.length > 0) {
18
+ for (const child of children) {
19
+ const node = typeof child === "string" ? document.createTextNode(child) : child;
20
+ projected.push([node, ""]);
21
+ element.append(node);
22
+ }
23
+ } else {
24
+ }
25
+ manageComponentLifecycle(element, definition, { props: componentProps, projected,
26
+ controller,
27
+ });
28
+ return element;
29
+ }
30
+
package/vanilla/index.js CHANGED
@@ -37,6 +37,7 @@ export * from "./UiList.js";
37
37
  export * from "./UiListItem.js";
38
38
  export * from "./UiMenu.js";
39
39
  export * from "./UiMenuItem.js";
40
+ export * from "./UiMeter.js";
40
41
  export * from "./UiNavItem.js";
41
42
  export * from "./UiPageHeader.js";
42
43
  export * from "./UiPopover.js";
@@ -55,6 +56,7 @@ export * from "./UiStack.js";
55
56
  export * from "./UiStatusMessage.js";
56
57
  export * from "./UiSwitch.js";
57
58
  export * from "./UiSwitcher.js";
59
+ export * from "./UiTable.js";
58
60
  export * from "./UiTabs.js";
59
61
  export * from "./UiText.js";
60
62
  export * from "./UiTextarea.js";
@@ -1,12 +1,15 @@
1
1
  type __VLS_Props = {
2
- layout?: 'rows' | 'tiles';
2
+ columns?: '2' | '3' | '4';
3
+ density?: 'comfortable' | 'compact';
4
+ layout?: 'rows' | 'stacked' | 'grid' | 'tiles';
3
5
  };
4
6
  declare var __VLS_1: {};
5
7
  type __VLS_Slots = {} & {
6
8
  default?: (props: typeof __VLS_1) => any;
7
9
  };
8
10
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
9
- layout: "rows" | "tiles";
11
+ density: "comfortable" | "compact";
12
+ layout: "rows" | "stacked" | "grid" | "tiles";
10
13
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
14
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
12
15
  declare const _default: typeof __VLS_export;
@@ -6,9 +6,12 @@ defineOptions({ inheritAttrs: false })
6
6
 
7
7
  const props = withDefaults(
8
8
  defineProps<{
9
- layout?: 'rows' | 'tiles'
9
+ columns?: '2' | '3' | '4'
10
+ density?: 'comfortable' | 'compact'
11
+ layout?: 'rows' | 'stacked' | 'grid' | 'tiles'
10
12
  }>(),
11
13
  {
14
+ density: 'comfortable',
12
15
  layout: 'rows',
13
16
  },
14
17
  )
@@ -17,6 +20,8 @@ const props = withDefaults(
17
20
  const hostState = computed(() =>
18
21
  [
19
22
  props.layout && `layout layout=${props.layout}`,
23
+ props.columns && `columns columns=${props.columns}`,
24
+ props.density && `density density=${props.density}`,
20
25
  ].filter(Boolean).join(' ')
21
26
  )
22
27
  </script>
@@ -35,24 +40,63 @@ const hostState = computed(() =>
35
40
  /* Named values: a term and what it is, for each item (ui-description-item). */
36
41
  /* Rows line every term up in one column and every value in the next, through subgrid. */
37
42
  [data-component~="ui-description-list"] {
43
+ --_gap: var(--ui-space-2);
44
+ --_gap-compact: var(--ui-space-1);
45
+ --_column-gap: var(--ui-space-6);
46
+ --_min: 10rem;
47
+ --_track: var(--_min);
48
+ --_tile-padding: var(--ui-space-3);
38
49
  display: grid;
39
50
  grid-template-columns: minmax(6rem, max-content) minmax(0, 1fr);
40
- gap: var(--ui-space-2) var(--ui-space-6);
51
+ gap: var(--_gap) var(--_column-gap);
41
52
  min-inline-size: 0;
42
53
  margin: 0;
43
54
  }
44
55
 
45
- /* Tiles pass their shape to the items through private properties, which cross into each item. */
56
+ /* Stacked, grid, and tiles set each term above its value, passing the shape to the items through
57
+ private properties, which cross into each item. */
58
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=stacked"],
59
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=grid"],
46
60
  [data-component~="ui-description-list"][data-ui-description-list-state~="layout=tiles"] {
47
61
  --_ui-description-display: flex;
48
62
  --_ui-description-column: auto;
63
+ --_ui-description-align: stretch;
64
+ --_gap: var(--ui-space-4);
65
+ --_gap-compact: var(--ui-space-2);
66
+ grid-template-columns: minmax(0, 1fr);
67
+ }
68
+
69
+ /* A column is at least --_min wide; with columns set, at least its share of the width, so no more
70
+ than that many fit. */
71
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=grid"],
72
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=tiles"] {
73
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--_track)), 1fr));
74
+ }
75
+
76
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=tiles"] {
49
77
  --_ui-description-align: flex-start;
50
78
  --_ui-description-value-size: var(--ui-font-size-lg);
51
- --_ui-description-padding: var(--ui-space-3);
79
+ --_ui-description-padding: var(--_tile-padding);
52
80
  --_ui-description-border-width: 1px;
53
- display: grid;
54
- grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr));
55
- gap: var(--ui-space-3);
81
+ --_gap: var(--ui-space-3);
82
+ --_gap-compact: var(--ui-space-2);
83
+ --_column-gap: var(--_gap);
84
+ }
85
+
86
+ [data-component~="ui-description-list"][data-ui-description-list-state~="columns=2"] {
87
+ --_track: max(var(--_min), (100% - var(--_column-gap)) / 2);
88
+ }
89
+ [data-component~="ui-description-list"][data-ui-description-list-state~="columns=3"] {
90
+ --_track: max(var(--_min), (100% - 2 * var(--_column-gap)) / 3);
91
+ }
92
+ [data-component~="ui-description-list"][data-ui-description-list-state~="columns=4"] {
93
+ --_track: max(var(--_min), (100% - 3 * var(--_column-gap)) / 4);
94
+ }
95
+
96
+ /* Compact takes each layout's closer spacing. */
97
+ [data-component~="ui-description-list"][data-ui-description-list-state~="density=compact"] {
98
+ --_gap: var(--_gap-compact);
99
+ --_tile-padding: var(--ui-space-2);
56
100
  }
57
101
 
58
102
  /* A component that sets its display still honours the hidden attribute on its root. */
package/vue/UiList.d.ts CHANGED
@@ -7,8 +7,8 @@ type __VLS_Slots = {} & {
7
7
  default?: (props: typeof __VLS_1) => any;
8
8
  };
9
9
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
10
- layout: "rows" | "grid";
11
10
  density: "comfortable" | "compact";
11
+ layout: "rows" | "grid";
12
12
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
13
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
14
14
  declare const _default: typeof __VLS_export;
@@ -0,0 +1,18 @@
1
+ type __VLS_Props = {
2
+ label?: string;
3
+ max?: number;
4
+ size?: 'sm' | 'md';
5
+ tone?: 'neutral' | 'accent' | 'info' | 'success' | 'warning' | 'danger';
6
+ value?: number;
7
+ valueText?: string;
8
+ };
9
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
10
+ label: string;
11
+ size: "sm" | "md";
12
+ value: number;
13
+ max: number;
14
+ tone: "neutral" | "accent" | "info" | "success" | "warning" | "danger";
15
+ valueText: string;
16
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
+ declare const _default: typeof __VLS_export;
18
+ export default _default;
package/vue/UiMeter.js ADDED
@@ -0,0 +1,2 @@
1
+ import { t as UiMeter_default } from "./chunks/UiMeter.js";
2
+ export { UiMeter_default as default };