@threadlabs/looma 0.12.2 → 0.12.4

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/editor/icons.d.ts CHANGED
@@ -6,7 +6,9 @@ export declare const LOOMA_ICONS: {
6
6
  'align-right': IconNode;
7
7
  'arrow-left': IconNode;
8
8
  bold: IconNode;
9
+ 'book-user': IconNode;
9
10
  braces: IconNode;
11
+ calculator: IconNode;
10
12
  'circle-check': IconNode;
11
13
  'circle-x': IconNode;
12
14
  'chevron-down': IconNode;
@@ -14,6 +16,7 @@ export declare const LOOMA_ICONS: {
14
16
  'chevron-right': IconNode;
15
17
  'code-xml': IconNode;
16
18
  columns: IconNode;
19
+ 'credit-card': IconNode;
17
20
  ellipsis: IconNode;
18
21
  eraser: IconNode;
19
22
  'file-text': IconNode;
@@ -27,6 +30,7 @@ export declare const LOOMA_ICONS: {
27
30
  image: IconNode;
28
31
  info: IconNode;
29
32
  italic: IconNode;
33
+ 'layout-dashboard': IconNode;
30
34
  list: IconNode;
31
35
  'list-ordered': IconNode;
32
36
  'list-todo': IconNode;
@@ -42,14 +46,18 @@ export declare const LOOMA_ICONS: {
42
46
  pilcrow: IconNode;
43
47
  plus: IconNode;
44
48
  quote: IconNode;
49
+ receipt: IconNode;
45
50
  redo: IconNode;
46
51
  rows: IconNode;
52
+ settings: IconNode;
47
53
  split: IconNode;
48
54
  strikethrough: IconNode;
49
55
  table: IconNode;
50
56
  trash: IconNode;
51
57
  'triangle-alert': IconNode;
58
+ truck: IconNode;
52
59
  underline: IconNode;
60
+ users: IconNode;
53
61
  undo: IconNode;
54
62
  };
55
63
  /** Stable key selecting an icon from Looma's shipped interaction vocabulary. */
package/editor/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { n as TABLE_CELL_BACKGROUND_PRESETS, t as TABLE_CELL_BACKGROUND_OPTIONS } from "./chunks/table-backgrounds.js";
2
2
  import { n as resolveTableCellAt, t as measureTableOverlayGeometry } from "./chunks/ui.js";
3
3
  import { A as LOOMA_ACTIVE_BLOCK_CLASS, C as DEFAULT_MENTION_RESULT_LIMIT, D as LOOMA_CALLOUT_TONES, E as normalizeMentionResultLimit, M as LoomaActiveBlock, N as LoomaActiveBlockPluginKey, O as LoomaCallout, S as createLoomaMentionExtension, T as filterLoomaMentionItems, _ as getActiveTableCellBackground, a as handleTableAction, b as LoomaSmartPaste, c as normalizeActiveTableColumnWidths, d as getDefaultEditorExtensions, f as getLoomaTableExtensions, g as getActiveTableCellAlignment, h as LoomaTableHeader, i as getActiveTableUiState, j as LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, k as LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, l as shouldShowTextFormattingToolbar, m as LoomaTableCell, n as createLoomaSlashCommandExtension, o as handleTableOverlayAction, p as LoomaTable, r as getDefaultSlashCommands, s as insertTableAtRange, t as LoomaSlashCommand, u as LoomaTableKit, v as setActiveTableCellAlignment, w as MAX_MENTION_RESULT_LIMIT, x as LoomaMentionSuggestionPluginKey, y as setActiveTableCellBackground } from "./chunks/extensions.js";
4
- import { AlignCenter, AlignLeft, AlignRight, ArrowLeft, Bold, Braces, ChevronDown, ChevronLeft, ChevronRight, CircleCheck, CircleX, CodeXml, Columns3, Ellipsis, Eraser, FileText, Folder, GripHorizontal, GripVertical, Heading1, Heading2, Heading3, Highlighter, Image, Info, Italic, List, ListOrdered, ListTodo, LoaderCircle, Merge, Minus, NotebookPen, PaintBucket, PanelBottom, PanelLeft, PanelRight, PanelTop, Pilcrow, Plus, Quote, Redo2, Rows3, Split, Strikethrough, Table2, Trash2, TriangleAlert, Underline, Undo2 } from "lucide";
4
+ import { AlignCenter, AlignLeft, AlignRight, ArrowLeft, Bold, BookUser, Braces, Calculator, ChevronDown, ChevronLeft, ChevronRight, CircleCheck, CircleX, CodeXml, Columns3, CreditCard, Ellipsis, Eraser, FileText, Folder, GripHorizontal, GripVertical, Heading1, Heading2, Heading3, Highlighter, Image, Info, Italic, LayoutDashboard, List, ListOrdered, ListTodo, LoaderCircle, Merge, Minus, NotebookPen, PaintBucket, PanelBottom, PanelLeft, PanelRight, PanelTop, Pilcrow, Plus, Quote, Receipt, Redo2, Rows3, Settings, Split, Strikethrough, Table2, Trash2, TriangleAlert, Truck, Underline, Undo2, Users } from "lucide";
5
5
  //#region src/editor/icons.ts
6
6
  /** The opinionated Lucide set used by Looma's shipped interaction surfaces. */
7
7
  var LOOMA_ICONS = {
@@ -10,7 +10,9 @@ var LOOMA_ICONS = {
10
10
  "align-right": AlignRight,
11
11
  "arrow-left": ArrowLeft,
12
12
  bold: Bold,
13
+ "book-user": BookUser,
13
14
  braces: Braces,
15
+ calculator: Calculator,
14
16
  "circle-check": CircleCheck,
15
17
  "circle-x": CircleX,
16
18
  "chevron-down": ChevronDown,
@@ -18,6 +20,7 @@ var LOOMA_ICONS = {
18
20
  "chevron-right": ChevronRight,
19
21
  "code-xml": CodeXml,
20
22
  columns: Columns3,
23
+ "credit-card": CreditCard,
21
24
  ellipsis: Ellipsis,
22
25
  eraser: Eraser,
23
26
  "file-text": FileText,
@@ -31,6 +34,7 @@ var LOOMA_ICONS = {
31
34
  image: Image,
32
35
  info: Info,
33
36
  italic: Italic,
37
+ "layout-dashboard": LayoutDashboard,
34
38
  list: List,
35
39
  "list-ordered": ListOrdered,
36
40
  "list-todo": ListTodo,
@@ -46,14 +50,18 @@ var LOOMA_ICONS = {
46
50
  pilcrow: Pilcrow,
47
51
  plus: Plus,
48
52
  quote: Quote,
53
+ receipt: Receipt,
49
54
  redo: Redo2,
50
55
  rows: Rows3,
56
+ settings: Settings,
51
57
  split: Split,
52
58
  strikethrough: Strikethrough,
53
59
  table: Table2,
54
60
  trash: Trash2,
55
61
  "triangle-alert": TriangleAlert,
62
+ truck: Truck,
56
63
  underline: Underline,
64
+ users: Users,
57
65
  undo: Undo2
58
66
  };
59
67
  function serializeAttributes(attributes) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.12.2",
3
+ "version": "0.12.4",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -3,7 +3,8 @@
3
3
  :scope {
4
4
  --_badge-surface: var(--ui-surface-subtle);
5
5
  --_badge-text: var(--ui-text-secondary);
6
- --_badge-border: color-mix(in srgb, var(--ui-text-secondary) 30%, transparent);
6
+ /* Every tone's edge is its fill, so it is unseen until forced colors draw it. */
7
+ --_badge-border: var(--ui-surface-subtle);
7
8
 
8
9
  display: inline-flex;
9
10
  align-items: center;
@@ -21,12 +22,12 @@
21
22
  white-space: nowrap;
22
23
  }
23
24
 
24
- /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
25
25
  /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
26
- * Trimming applies to block containers, so the box is a block with centred content. */
26
+ * Trimming applies to block containers; an inline-block is one and, like the inline-flex it
27
+ * replaces, still sizes to its label rather than filling its container. */
27
28
  @supports (text-box-trim: trim-both) {
28
29
  :scope {
29
- display: block;
30
+ display: inline-block;
30
31
  min-block-size: var(--ui-badge-min-block-size, 1.5rem);
31
32
  text-align: center;
32
33
  align-content: center;
@@ -119,9 +120,9 @@
119
120
  }
120
121
  }
121
122
  @scope ([data-component~="ui-badge"]) to ([data-component]) {
122
- /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
123
- /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
124
- * Trimming applies to block containers, so the box is a block with centred content. */
123
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
124
+ * Trimming applies to block containers; an inline-block is one and, like the inline-flex it
125
+ * replaces, still sizes to its label rather than filling its container. */
125
126
  @supports (text-box-trim: trim-both) {
126
127
  }
127
128
 
@@ -0,0 +1,141 @@
1
+ /* Generated by HTML Next 1.0.0-alpha.5. Do not edit. */
2
+ @scope ([data-component~="ui-nav-item"]) to ([data-component], [data-slotted]) {
3
+ /* One destination in a side or rail navigation: an icon to find it by (leading), its name (the
4
+ default slot), and an optional line under it (description), such as the record a section
5
+ belongs to. Label and description are one line each and end in an ellipsis, so every item in a
6
+ navigation has the same height and the rail never grows sideways. */
7
+ :scope {
8
+ --_indicator-width: var(--ui-nav-item-indicator-width, 3px);
9
+ --_indicator-color: var(--ui-nav-item-indicator-color, var(--ui-accent));
10
+ position: relative;
11
+ box-sizing: border-box;
12
+ display: flex;
13
+ align-items: center;
14
+ gap: var(--ui-space-3);
15
+ inline-size: 100%;
16
+ min-inline-size: 0;
17
+ min-block-size: var(--ui-control-size, 2.5rem);
18
+ margin: 0;
19
+ padding-block: var(--ui-space-2);
20
+ padding-inline: var(--ui-space-3);
21
+ border: 0;
22
+ border-radius: var(--ui-radius-md);
23
+ background: transparent;
24
+ color: var(--ui-text-secondary);
25
+ font: inherit;
26
+ font-weight: var(--ui-font-medium);
27
+ text-align: start;
28
+ text-decoration: none;
29
+ cursor: pointer;
30
+ appearance: none;
31
+ transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);
32
+ }
33
+
34
+ :scope:hover:not([aria-current]) {
35
+ background: var(--ui-surface-hover);
36
+ color: var(--ui-text-primary);
37
+ }
38
+
39
+ /* The ring is an outline, drawn inside the item: forced colors keep an outline where they drop a
40
+ box shadow, and a scrolling rail cannot clip a ring that stays within the item. */
41
+ :scope:focus-visible {
42
+ outline: 2px solid var(--ui-focus-ring);
43
+ outline-offset: -2px;
44
+ }
45
+
46
+ :scope[aria-current] {
47
+ background: var(--ui-nav-item-current-surface, var(--ui-accent-soft));
48
+ color: var(--ui-accent-subtle-text, var(--ui-text-primary));
49
+ font-weight: var(--ui-font-semibold);
50
+ }
51
+
52
+ /* The bar on the start edge is a border, not a fill: forced colors replace backgrounds but keep a
53
+ border, so the current item stays marked in high contrast. Logical edges mirror it in a
54
+ right-to-left page. */
55
+ .indicator {
56
+ position: absolute;
57
+ inset-block: var(--ui-space-2);
58
+ inset-inline-start: 0;
59
+ display: none;
60
+ border-inline-start: var(--_indicator-width) solid var(--_indicator-color);
61
+ border-radius: var(--ui-radius-round);
62
+ }
63
+
64
+ :scope[aria-current] .indicator {
65
+ display: block;
66
+ }
67
+
68
+ @media (forced-colors: active) {
69
+ .indicator {
70
+ border-inline-start-color: Highlight;
71
+ }
72
+ }
73
+
74
+ .leading {
75
+ display: inline-flex;
76
+ flex: none;
77
+ align-items: center;
78
+ color: inherit;
79
+ font-size: var(--ui-font-size-lg);
80
+ }
81
+
82
+ .content {
83
+ display: flex;
84
+ flex: 1;
85
+ flex-direction: column;
86
+ gap: var(--ui-space-0-5, 2px);
87
+ min-inline-size: 0;
88
+ }
89
+
90
+ .label,
91
+ .description {
92
+ display: block;
93
+ min-inline-size: 0;
94
+ overflow: hidden;
95
+ text-overflow: ellipsis;
96
+ white-space: nowrap;
97
+ }
98
+
99
+ .label {
100
+ font-size: var(--ui-font-size-md);
101
+ line-height: var(--ui-line-height-tight);
102
+ }
103
+
104
+ .description {
105
+ color: var(--ui-text-muted);
106
+ font-size: var(--ui-font-size-sm);
107
+ font-weight: var(--ui-font-normal);
108
+ line-height: var(--ui-line-height-tight);
109
+ }
110
+
111
+ /* An unused region takes no space. */
112
+ .leading:empty,
113
+ .description:empty {
114
+ display: none;
115
+ }
116
+
117
+ /* A component that sets its display still honours the hidden attribute on its root. */
118
+ :scope[hidden] {
119
+ display: none;
120
+ }
121
+ }
122
+ @scope ([data-component~="ui-nav-item"]) to ([data-component]) {
123
+ /* One destination in a side or rail navigation: an icon to find it by (leading), its name (the
124
+ default slot), and an optional line under it (description), such as the record a section
125
+ belongs to. Label and description are one line each and end in an ellipsis, so every item in a
126
+ navigation has the same height and the rail never grows sideways. */
127
+
128
+ /* The ring is an outline, drawn inside the item: forced colors keep an outline where they drop a
129
+ box shadow, and a scrolling rail cannot clip a ring that stays within the item. */
130
+
131
+ /* The bar on the start edge is a border, not a fill: forced colors replace backgrounds but keep a
132
+ border, so the current item stays marked in high contrast. Logical edges mirror it in a
133
+ right-to-left page. */
134
+
135
+ @media (forced-colors: active) {
136
+ }
137
+
138
+ /* An unused region takes no space. */
139
+
140
+ /* A component that sets its display still honours the hidden attribute on its root. */
141
+ }
package/vanilla/UiIcon.js CHANGED
@@ -3,7 +3,7 @@ import { manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
3
3
  import * as controller from "../components/ui-icon/ui-icon.js";
4
4
  import "../styles/ui-icon.css";
5
5
 
6
- const definition = {...{"contract":{"tag":"ui-icon","props":{"name":{"type":"string","required":false,"target":{"attribute":"name"},"default":""}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"},{"kind":"literal","name":"focusable","value":"false"}],"children":[{"kind":"element","name":"g","attributes":[],"children":[{"kind":"element","name":"path","attributes":[{"kind":"attribute","name":"d","expression":"shape.d","expressionPlan":{"source":"shape.d","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"d"},"dependencies":["shape.d"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'path'","testPlan":{"source":"shape.tag = 'path'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"path"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"circle","attributes":[{"kind":"attribute","name":"cx","expression":"shape.cx","expressionPlan":{"source":"shape.cx","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"cx"},"dependencies":["shape.cx"]}},{"kind":"attribute","name":"cy","expression":"shape.cy","expressionPlan":{"source":"shape.cy","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"cy"},"dependencies":["shape.cy"]}},{"kind":"attribute","name":"r","expression":"shape.r","expressionPlan":{"source":"shape.r","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"r"},"dependencies":["shape.r"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'circle'","testPlan":{"source":"shape.tag = 'circle'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"circle"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"rect","attributes":[{"kind":"attribute","name":"x","expression":"shape.x","expressionPlan":{"source":"shape.x","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"x"},"dependencies":["shape.x"]}},{"kind":"attribute","name":"y","expression":"shape.y","expressionPlan":{"source":"shape.y","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"y"},"dependencies":["shape.y"]}},{"kind":"attribute","name":"width","expression":"shape.width","expressionPlan":{"source":"shape.width","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"width"},"dependencies":["shape.width"]}},{"kind":"attribute","name":"height","expression":"shape.height","expressionPlan":{"source":"shape.height","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"height"},"dependencies":["shape.height"]}},{"kind":"attribute","name":"rx","expression":"shape.rx","expressionPlan":{"source":"shape.rx","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"rx"},"dependencies":["shape.rx"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'rect'","testPlan":{"source":"shape.tag = 'rect'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"rect"}},"dependencies":["shape.tag"]}}}],"flow":{"kind":"each","item":"shape","list":"shapes","listPlan":{"source":"shapes","ast":{"kind":"id","name":"shapes"},"dependencies":["shapes"]}}}]}]},"declarations":[{"kind":"state","name":"shapes","type":"list(object({ tag: path | circle | rect, d?: string, cx?: string, cy?: string, r?: string, x?: string, y?: string, width?: string, height?: string, rx?: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}}],"root":{"kind":"native","element":"span","choices":["span"]}},source:{file:import.meta.url},css:""};
6
+ const definition = {...{"contract":{"tag":"ui-icon","props":{"name":{"type":"string","required":false,"target":{"attribute":"name"},"default":""}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"},{"kind":"literal","name":"focusable","value":"false"}],"children":[{"kind":"element","name":"g","attributes":[],"children":[{"kind":"element","name":"path","attributes":[{"kind":"attribute","name":"d","expression":"shape.d","expressionPlan":{"source":"shape.d","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"d"},"dependencies":["shape.d"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'path'","testPlan":{"source":"shape.tag = 'path'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"path"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"circle","attributes":[{"kind":"attribute","name":"cx","expression":"shape.cx","expressionPlan":{"source":"shape.cx","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"cx"},"dependencies":["shape.cx"]}},{"kind":"attribute","name":"cy","expression":"shape.cy","expressionPlan":{"source":"shape.cy","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"cy"},"dependencies":["shape.cy"]}},{"kind":"attribute","name":"r","expression":"shape.r","expressionPlan":{"source":"shape.r","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"r"},"dependencies":["shape.r"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'circle'","testPlan":{"source":"shape.tag = 'circle'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"circle"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"rect","attributes":[{"kind":"attribute","name":"x","expression":"shape.x","expressionPlan":{"source":"shape.x","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"x"},"dependencies":["shape.x"]}},{"kind":"attribute","name":"y","expression":"shape.y","expressionPlan":{"source":"shape.y","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"y"},"dependencies":["shape.y"]}},{"kind":"attribute","name":"width","expression":"shape.width","expressionPlan":{"source":"shape.width","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"width"},"dependencies":["shape.width"]}},{"kind":"attribute","name":"height","expression":"shape.height","expressionPlan":{"source":"shape.height","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"height"},"dependencies":["shape.height"]}},{"kind":"attribute","name":"rx","expression":"shape.rx","expressionPlan":{"source":"shape.rx","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"rx"},"dependencies":["shape.rx"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'rect'","testPlan":{"source":"shape.tag = 'rect'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"rect"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"line","attributes":[{"kind":"attribute","name":"x1","expression":"shape.x1","expressionPlan":{"source":"shape.x1","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"x1"},"dependencies":["shape.x1"]}},{"kind":"attribute","name":"x2","expression":"shape.x2","expressionPlan":{"source":"shape.x2","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"x2"},"dependencies":["shape.x2"]}},{"kind":"attribute","name":"y1","expression":"shape.y1","expressionPlan":{"source":"shape.y1","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"y1"},"dependencies":["shape.y1"]}},{"kind":"attribute","name":"y2","expression":"shape.y2","expressionPlan":{"source":"shape.y2","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"y2"},"dependencies":["shape.y2"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'line'","testPlan":{"source":"shape.tag = 'line'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"line"}},"dependencies":["shape.tag"]}}}],"flow":{"kind":"each","item":"shape","list":"shapes","listPlan":{"source":"shapes","ast":{"kind":"id","name":"shapes"},"dependencies":["shapes"]}}}]}]},"declarations":[{"kind":"state","name":"shapes","type":"list(object({ tag: path | circle | rect | line, d?: string, cx?: string, cy?: string, r?: string, x?: string, y?: string, width?: string, height?: string, rx?: string, x1?: string, x2?: string, y1?: string, y2?: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}}],"root":{"kind":"native","element":"span","choices":["span"]}},source:{file:import.meta.url},css:""};
7
7
 
8
8
  export function createUiIcon(options = {}) {
9
9
  const { attributes = {}, children = [], slots = {}, as, ...componentProps } = options;
@@ -30,6 +30,8 @@ export function createUiIcon(options = {}) {
30
30
  element1.append(element3);
31
31
  const element4 = document.createElementNS("http://www.w3.org/2000/svg", "rect");
32
32
  element1.append(element4);
33
+ const element5 = document.createElementNS("http://www.w3.org/2000/svg", "line");
34
+ element1.append(element5);
33
35
  element0.append(element1);
34
36
  element.append(element0);
35
37
  manageComponentLifecycle(element, definition, { props: componentProps, projected,
@@ -0,0 +1,18 @@
1
+ // Generated by HTML Next 1.0.0-alpha.5 for Vanilla DOM. Do not edit.
2
+ export interface UiNavItemEventMap {
3
+ }
4
+ export interface UiNavItemElement extends HTMLButtonElement {
5
+ addEventListener<K extends keyof UiNavItemEventMap>(type: K, listener: (this: UiNavItemElement, event: UiNavItemEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
6
+ removeEventListener<K extends keyof UiNavItemEventMap>(type: K, listener: (this: UiNavItemElement, event: UiNavItemEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
7
+ }
8
+ export interface UiNavItemProps {
9
+ current?: boolean | "page" | "step" | "location" | null;
10
+ href?: string | null;
11
+ rel?: string | null;
12
+ target?: string | null;
13
+ attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
14
+ children?: readonly (string | Node)[];
15
+ slots?: Readonly<Record<string, readonly (string | Node)[]>>;
16
+ as?: "button" | "a";
17
+ }
18
+ export declare function createUiNavItem(props?: UiNavItemProps): UiNavItemElement;
@@ -0,0 +1,69 @@
1
+ // Generated by HTML Next 1.0.0-alpha.5 for Vanilla DOM. Do not edit.
2
+ import { manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
3
+ import "../styles/ui-nav-item.css";
4
+
5
+ const definition = {...{"contract":{"tag":"ui-nav-item","props":{"current":{"type":{"kind":"union","members":[{"kind":"terminal","name":"boolean"},{"kind":"keyword","value":"page"},{"kind":"keyword","value":"step"},{"kind":"keyword","value":"location"}]},"required":false,"target":{"attribute":"current"},"default":false},"href":{"type":"string","required":false,"target":{"attribute":"href"}},"rel":{"type":"string","required":false,"target":{"attribute":"rel"}},"target":{"type":"string","required":false,"target":{"attribute":"target"}}}},"template":{"kind":"element","name":"button","attributes":[{"kind":"attribute","name":"type","expression":"{ true: 'button', false: null }[format('%s', not href)]","expressionPlan":{"source":"{ true: 'button', false: null }[format('%s', not href)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"button"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"unary","op":"not","operand":{"kind":"id","name":"href"}}]}},"dependencies":["href"]}},{"kind":"attribute","name":"href","expression":"href","expressionPlan":{"source":"href","ast":{"kind":"id","name":"href"},"dependencies":["href"]}},{"kind":"attribute","name":"target","expression":"target","expressionPlan":{"source":"target","ast":{"kind":"id","name":"target"},"dependencies":["target"]}},{"kind":"attribute","name":"rel","expression":"rel","expressionPlan":{"source":"rel","ast":{"kind":"id","name":"rel"},"dependencies":["rel"]}},{"kind":"attribute","name":"aria-current","expression":"{ true: 'page', false: null, page: 'page', step: 'step', location: 'location' }[format('%s', current)]","expressionPlan":{"source":"{ true: 'page', false: null, page: 'page', step: 'step', location: 'location' }[format('%s', current)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"page"}},{"key":"false","value":{"kind":"literal","value":null}},{"key":"page","value":{"kind":"literal","value":"page"}},{"key":"step","value":{"kind":"literal","value":"step"}},{"key":"location","value":{"kind":"literal","value":"location"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"id","name":"current"}]}},"dependencies":["current"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"indicator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]}]},"declarations":[],"root":{"kind":"native","element":"button","choices":["button","a"]}},source:{file:import.meta.url},css:""};
6
+
7
+ export function createUiNavItem(options = {}) {
8
+ const { attributes = {}, children = [], slots = {}, as, ...componentProps } = options;
9
+ const projected = [];
10
+ const element = document.createElement(as ?? "button");
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
+ const value0 = componentProps["href"] === undefined ? undefined : componentProps["href"];
16
+ if (value0 === null || value0 === undefined) element.removeAttribute("href");
17
+ else element.setAttribute("href", String(value0));
18
+ const value1 = componentProps["target"] === undefined ? undefined : componentProps["target"];
19
+ if (value1 === null || value1 === undefined) element.removeAttribute("target");
20
+ else element.setAttribute("target", String(value1));
21
+ const value2 = componentProps["rel"] === undefined ? undefined : componentProps["rel"];
22
+ if (value2 === null || value2 === undefined) element.removeAttribute("rel");
23
+ else element.setAttribute("rel", String(value2));
24
+ element.setAttribute("data-component", "ui-nav-item");
25
+ const element0 = document.createElement("span");
26
+ element0.setAttribute("class", "indicator");
27
+ element0.setAttribute("aria-hidden", "true");
28
+ element.append(element0);
29
+ const element1 = document.createElement("span");
30
+ element1.setAttribute("class", "leading");
31
+ if (slots["leading"] ?? [].length > 0) {
32
+ for (const child of slots["leading"] ?? []) {
33
+ const node = typeof child === "string" ? document.createTextNode(child) : child;
34
+ projected.push([node, "leading"]);
35
+ element1.append(node);
36
+ }
37
+ } else {
38
+ }
39
+ element.append(element1);
40
+ const element2 = document.createElement("span");
41
+ element2.setAttribute("class", "content");
42
+ const element3 = document.createElement("span");
43
+ element3.setAttribute("class", "label");
44
+ if (children.length > 0) {
45
+ for (const child of children) {
46
+ const node = typeof child === "string" ? document.createTextNode(child) : child;
47
+ projected.push([node, ""]);
48
+ element3.append(node);
49
+ }
50
+ } else {
51
+ }
52
+ element2.append(element3);
53
+ const element4 = document.createElement("span");
54
+ element4.setAttribute("class", "description");
55
+ if (slots["description"] ?? [].length > 0) {
56
+ for (const child of slots["description"] ?? []) {
57
+ const node = typeof child === "string" ? document.createTextNode(child) : child;
58
+ projected.push([node, "description"]);
59
+ element4.append(node);
60
+ }
61
+ } else {
62
+ }
63
+ element2.append(element4);
64
+ element.append(element2);
65
+ manageComponentLifecycle(element, definition, { props: componentProps, projected,
66
+ });
67
+ return element;
68
+ }
69
+
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 "./UiNavItem.js";
40
41
  export * from "./UiPageHeader.js";
41
42
  export * from "./UiPopover.js";
42
43
  export * from "./UiRadio.js";
package/vue/UiBadge.vue CHANGED
@@ -39,7 +39,8 @@ const hostState = computed(() =>
39
39
  [data-component~="ui-badge"] {
40
40
  --_badge-surface: var(--ui-surface-subtle);
41
41
  --_badge-text: var(--ui-text-secondary);
42
- --_badge-border: color-mix(in srgb, var(--ui-text-secondary) 30%, transparent);
42
+ /* Every tone's edge is its fill, so it is unseen until forced colors draw it. */
43
+ --_badge-border: var(--ui-surface-subtle);
43
44
 
44
45
  display: inline-flex;
45
46
  align-items: center;
@@ -58,12 +59,12 @@ const hostState = computed(() =>
58
59
  white-space: nowrap;
59
60
  }
60
61
 
61
- /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
62
62
  /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
63
- * Trimming applies to block containers, so the box is a block with centred content. */
63
+ * Trimming applies to block containers; an inline-block is one and, like the inline-flex it
64
+ * replaces, still sizes to its label rather than filling its container. */
64
65
  @supports (text-box-trim: trim-both) {
65
66
  [data-component~="ui-badge"] {
66
- display: block;
67
+ display: inline-block;
67
68
  min-block-size: var(--ui-badge-min-block-size, 1.5rem);
68
69
  text-align: center;
69
70
  align-content: center;
package/vue/UiIcon.vue CHANGED
@@ -18,7 +18,7 @@ const props = withDefaults(
18
18
  const root = ref<HTMLElement | null>(null)
19
19
  const shapes = ref<
20
20
  {
21
- tag: 'path' | 'circle' | 'rect'
21
+ tag: 'path' | 'circle' | 'rect' | 'line'
22
22
  d?: string
23
23
  cx?: string
24
24
  cy?: string
@@ -28,6 +28,10 @@ const shapes = ref<
28
28
  width?: string
29
29
  height?: string
30
30
  rx?: string
31
+ x1?: string
32
+ x2?: string
33
+ y1?: string
34
+ y2?: string
31
35
  }[]
32
36
  >([])
33
37
 
@@ -63,6 +67,14 @@ useComponentHost(controllerModule.default, {
63
67
  :rx="shape.rx"
64
68
  >
65
69
  </rect>
70
+ <line
71
+ v-if="shape.tag === 'line'"
72
+ :x1="shape.x1"
73
+ :x2="shape.x2"
74
+ :y1="shape.y1"
75
+ :y2="shape.y2"
76
+ >
77
+ </line>
66
78
  </g>
67
79
  </svg></span>
68
80
  </template>
@@ -0,0 +1,27 @@
1
+ type __VLS_Props = {
2
+ as?: 'button' | 'a';
3
+ current?: boolean | 'page' | 'step' | 'location';
4
+ href?: string;
5
+ rel?: string;
6
+ target?: string;
7
+ };
8
+ declare var __VLS_8: {}, __VLS_10: {}, __VLS_12: {};
9
+ type __VLS_Slots = {} & {
10
+ leading?: (props: typeof __VLS_8) => any;
11
+ } & {
12
+ default?: (props: typeof __VLS_10) => any;
13
+ } & {
14
+ description?: (props: typeof __VLS_12) => any;
15
+ };
16
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
17
+ current: boolean | "page" | "step" | "location";
18
+ as: "button" | "a";
19
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
21
+ declare const _default: typeof __VLS_export;
22
+ export default _default;
23
+ type __VLS_WithSlots<T, S> = T & {
24
+ new (): {
25
+ $slots: S;
26
+ };
27
+ };
@@ -0,0 +1,2 @@
1
+ import { t as UiNavItem_default } from "./chunks/UiNavItem.js";
2
+ export { UiNavItem_default as default };