@threadlabs/looma 0.40.0 → 0.41.1

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/docs/catalog.json CHANGED
@@ -365,6 +365,11 @@
365
365
  "package": "@threadlabs/looma",
366
366
  "resource": "@threadlabs/looma/components/ui-sidebar/ui-sidebar.html"
367
367
  },
368
+ {
369
+ "tag": "ui-site-header",
370
+ "package": "@threadlabs/looma",
371
+ "resource": "@threadlabs/looma/components/ui-site-header/ui-site-header.html"
372
+ },
368
373
  {
369
374
  "tag": "ui-skeleton",
370
375
  "package": "@threadlabs/looma",
@@ -458,7 +463,7 @@
458
463
  ],
459
464
  "schemaVersion": 1,
460
465
  "package": "@threadlabs/looma",
461
- "version": "0.40.0",
466
+ "version": "0.41.1",
462
467
  "groups": [
463
468
  {
464
469
  "id": "layout",
@@ -2999,7 +3004,7 @@
2999
3004
  {
3000
3005
  "name": "--ui-callout-surface",
3001
3006
  "declarations": [
3002
- "oklch(from var(--_callout-border) l c h / 10%)",
3007
+ "light-dark( oklch(from var(--_callout-border) 96% min(c, calc(0.02 + 0.03 * max(0, cos(calc((h - 140) * 1deg))))) h), oklch(from var(--_callout-border) 25% min(c, 0.035) h) )",
3003
3008
  "var(--ui-surface-muted)"
3004
3009
  ]
3005
3010
  },
@@ -20387,6 +20392,197 @@
20387
20392
  }
20388
20393
  ]
20389
20394
  },
20395
+ {
20396
+ "tag": "ui-site-header",
20397
+ "package": "@threadlabs/looma",
20398
+ "root": "header",
20399
+ "description": "A responsive site banner with slots for branding, navigation links, actions, and a consumer-owned mobile menu trigger. Keeps text baselines aligned while centering controls of different heights.",
20400
+ "designTokens": {
20401
+ "sources": [
20402
+ "packages/looma/src/components/ui-site-header/ui-site-header.html"
20403
+ ],
20404
+ "component": [
20405
+ {
20406
+ "name": "--ui-site-header-border",
20407
+ "fallbacks": [
20408
+ "var(--ui-border)"
20409
+ ]
20410
+ },
20411
+ {
20412
+ "name": "--ui-site-header-compact-height",
20413
+ "fallbacks": [
20414
+ "3.75rem"
20415
+ ]
20416
+ },
20417
+ {
20418
+ "name": "--ui-site-header-height",
20419
+ "fallbacks": [
20420
+ "4.25rem"
20421
+ ]
20422
+ },
20423
+ {
20424
+ "name": "--ui-site-header-padding-inline",
20425
+ "fallbacks": [
20426
+ "var(--ui-space-4)"
20427
+ ]
20428
+ },
20429
+ {
20430
+ "name": "--ui-site-header-surface",
20431
+ "fallbacks": [
20432
+ "var(--ui-surface)"
20433
+ ]
20434
+ },
20435
+ {
20436
+ "name": "--ui-site-header-z-index",
20437
+ "fallbacks": [
20438
+ "10"
20439
+ ]
20440
+ }
20441
+ ],
20442
+ "shared": [
20443
+ {
20444
+ "name": "--ui-accent-active"
20445
+ },
20446
+ {
20447
+ "name": "--ui-border"
20448
+ },
20449
+ {
20450
+ "name": "--ui-border-width"
20451
+ },
20452
+ {
20453
+ "name": "--ui-focus-ring"
20454
+ },
20455
+ {
20456
+ "name": "--ui-focus-width"
20457
+ },
20458
+ {
20459
+ "name": "--ui-font-bold"
20460
+ },
20461
+ {
20462
+ "name": "--ui-font-semibold"
20463
+ },
20464
+ {
20465
+ "name": "--ui-font-size-lg"
20466
+ },
20467
+ {
20468
+ "name": "--ui-font-size-sm"
20469
+ },
20470
+ {
20471
+ "name": "--ui-space-2"
20472
+ },
20473
+ {
20474
+ "name": "--ui-space-3"
20475
+ },
20476
+ {
20477
+ "name": "--ui-space-4"
20478
+ },
20479
+ {
20480
+ "name": "--ui-space-5"
20481
+ },
20482
+ {
20483
+ "name": "--ui-space-6"
20484
+ },
20485
+ {
20486
+ "name": "--ui-surface"
20487
+ },
20488
+ {
20489
+ "name": "--ui-text-primary"
20490
+ }
20491
+ ]
20492
+ },
20493
+ "attributes": [
20494
+ {
20495
+ "name": "breakpoint",
20496
+ "property": "breakpoint",
20497
+ "description": "The viewport width at which navigation replaces the menu trigger: sm is 40rem, md 48rem, and lg 64rem. The consumer owns the menu or drawer the trigger opens.",
20498
+ "type": "keyword",
20499
+ "default": "lg",
20500
+ "options": [
20501
+ "sm",
20502
+ "md",
20503
+ "lg"
20504
+ ]
20505
+ },
20506
+ {
20507
+ "name": "label",
20508
+ "property": "label",
20509
+ "description": "Accessible name for the primary navigation region.",
20510
+ "type": "string",
20511
+ "default": "Main"
20512
+ },
20513
+ {
20514
+ "name": "sticky",
20515
+ "property": "sticky",
20516
+ "description": "Keeps the header at the top of its scrolling container.",
20517
+ "type": "boolean",
20518
+ "default": false
20519
+ }
20520
+ ],
20521
+ "properties": [
20522
+ {
20523
+ "name": "breakpoint",
20524
+ "description": "The viewport width at which navigation replaces the menu trigger: sm is 40rem, md 48rem, and lg 64rem. The consumer owns the menu or drawer the trigger opens.",
20525
+ "type": "\"sm\" | \"md\" | \"lg\"",
20526
+ "default": "lg",
20527
+ "options": [
20528
+ "sm",
20529
+ "md",
20530
+ "lg"
20531
+ ]
20532
+ },
20533
+ {
20534
+ "name": "label",
20535
+ "description": "Accessible name for the primary navigation region.",
20536
+ "type": "string",
20537
+ "default": "Main"
20538
+ },
20539
+ {
20540
+ "name": "sticky",
20541
+ "description": "Keeps the header at the top of its scrolling container.",
20542
+ "type": "boolean",
20543
+ "default": false
20544
+ }
20545
+ ],
20546
+ "events": [],
20547
+ "slots": [
20548
+ {
20549
+ "name": "menu",
20550
+ "description": "Named content for the menu region."
20551
+ },
20552
+ {
20553
+ "name": "brand",
20554
+ "description": "Named content for the brand region."
20555
+ },
20556
+ {
20557
+ "name": "navigation",
20558
+ "description": "Named content for the navigation region."
20559
+ },
20560
+ {
20561
+ "name": "actions",
20562
+ "description": "Named content for the actions region."
20563
+ }
20564
+ ],
20565
+ "group": "display",
20566
+ "id": "@threadlabs/looma/ui-site-header",
20567
+ "title": "Site Header",
20568
+ "resource": "@threadlabs/looma/components/ui-site-header/ui-site-header.html",
20569
+ "targets": [
20570
+ "html-next",
20571
+ "vue"
20572
+ ],
20573
+ "examples": [
20574
+ {
20575
+ "id": "@threadlabs/looma/ui-site-header/01-default",
20576
+ "name": "01-default",
20577
+ "title": "Site navigation",
20578
+ "description": "A full-width header keeps its logo visible, places desktop navigation beside it, and puts search and account controls at the trailing edge. On mobile, the navigation moves into the menu.",
20579
+ "markup": "<ui-site-header>\n <a slot=\"brand\" href=\"#home\" aria-label=\"Folio home\"><ui-icon name=\"compass\"></ui-icon>Folio</a>\n <a slot=\"navigation\" href=\"#guide\" aria-current=\"page\">Guide</a>\n <a slot=\"navigation\" href=\"#components\">Components</a>\n <a slot=\"navigation\" href=\"#journal\">Journal</a>\n <ui-icon-button id=\"site-header-menu-trigger\" slot=\"menu\" size=\"sm\" label=\"Open navigation\"><ui-icon name=\"panel-left\"></ui-icon></ui-icon-button>\n <ui-cluster slot=\"actions\" gap=\"xs\">\n <ui-icon-button id=\"site-header-search-trigger\" size=\"sm\" label=\"Search pages\"><ui-icon name=\"search\"></ui-icon></ui-icon-button>\n <ui-icon-button id=\"site-header-account-trigger\" size=\"sm\" label=\"Account\"><ui-icon name=\"user-round\"></ui-icon></ui-icon-button>\n </ui-cluster>\n</ui-site-header>\n<ui-popover for=\"site-header-menu-trigger\"><nav aria-label=\"Compact navigation\">\n <ui-stack gap=\"s\"><a href=\"#guide\" aria-current=\"page\">Guide</a><a href=\"#components\">Components</a><a href=\"#journal\">Journal</a></ui-stack>\n </nav></ui-popover>\n<ui-popover for=\"site-header-search-trigger\"><ui-form-field>\n <label slot=\"label\" for=\"site-header-search\">Search pages</label><ui-input id=\"site-header-search\" type=\"search\" placeholder=\"Find a page\"></ui-input>\n </ui-form-field></ui-popover>\n<ui-popover for=\"site-header-account-trigger\"><nav aria-label=\"Account\">\n <ui-stack gap=\"s\"><a href=\"#profile\">Your profile</a><a href=\"#settings\">Settings</a></ui-stack>\n </nav></ui-popover>",
20580
+ "resizable": false,
20581
+ "bindings": "",
20582
+ "frameworks": {}
20583
+ }
20584
+ ]
20585
+ },
20390
20586
  {
20391
20587
  "tag": "ui-skeleton",
20392
20588
  "package": "@threadlabs/looma",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.40.0",
3
+ "version": "0.41.1",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -59,7 +59,11 @@
59
59
  --_ui-callout-icon: var(--ui-callout-icon);
60
60
  --_ui-callout-icon-size: var(--ui-callout-icon-size);
61
61
 
62
- --_callout-surface: oklch(from var(--_callout-border) l c h / 10%);
62
+ /* Near white, sRGB retains more green chroma than blue/red; bound chroma by hue to avoid clipping. */
63
+ --_callout-surface: light-dark(
64
+ oklch(from var(--_callout-border) 96% min(c, calc(0.02 + 0.03 * max(0, cos(calc((h - 140) * 1deg))))) h),
65
+ oklch(from var(--_callout-border) 25% min(c, 0.035) h)
66
+ );
63
67
  --_ui-selection-context-surface: light-dark(
64
68
  oklch(from var(--ui-callout-surface, var(--_callout-surface)) calc(l - 0.045) calc(max(c, min(0.045, c * 3))) h),
65
69
  oklch(from var(--ui-callout-surface, var(--_callout-surface)) calc(l + 0.045) calc(max(c, min(0.045, c * 3))) h)
@@ -0,0 +1,165 @@
1
+ /* Generated by HTML Next 1.0.0-alpha.69. Do not edit. */
2
+ @supports (-moz-appearance: none) {
3
+ :where([data-component], [data-slotted]) { --html-next-scope-owner: boundary; }
4
+ :where([data-slotted]:not([data-component])) { --html-next-scope-owner: projected !important; }
5
+ }
6
+ @supports (-moz-appearance: none) {
7
+ [data-component~="ui-site-header"] { --html-next-scope-owner: "ui-site-header" !important; }
8
+ }
9
+ @scope ([data-component~="ui-site-header"]) to ([data-component], [data-slotted]) {
10
+ @property --ui-site-header-height {
11
+ syntax: "*";
12
+ inherits: false;
13
+ }
14
+ @property --ui-site-header-compact-height {
15
+ syntax: "*";
16
+ inherits: false;
17
+ }
18
+ @property --ui-site-header-padding-inline {
19
+ syntax: "*";
20
+ inherits: false;
21
+ }
22
+ @property --ui-site-header-surface {
23
+ syntax: "*";
24
+ inherits: false;
25
+ }
26
+ @property --ui-site-header-border {
27
+ syntax: "*";
28
+ inherits: false;
29
+ }
30
+ @property --ui-site-header-z-index {
31
+ syntax: "*";
32
+ inherits: false;
33
+ }
34
+
35
+ :scope:where([data-component~="ui-site-header"]) {
36
+ box-sizing: border-box !important;
37
+ display: flex !important;
38
+ flex-wrap: wrap !important;
39
+ align-items: center !important;
40
+ align-content: center !important;
41
+ gap: var(--ui-space-2) !important;
42
+ min-inline-size: 0;
43
+ min-block-size: var(--ui-site-header-compact-height, 3.75rem);
44
+ padding: var(--ui-space-2) var(--ui-site-header-padding-inline, var(--ui-space-4)) !important;
45
+ border-block-end: var(--ui-border-width) solid var(--ui-site-header-border, var(--ui-border));
46
+ background: var(--ui-site-header-surface, var(--ui-surface));
47
+ color: var(--ui-text-primary);
48
+ }
49
+ :scope:where([data-component~="ui-site-header"])[data-ui-site-header-state~="sticky"] {
50
+ position: sticky;
51
+ inset-block-start: 0;
52
+ z-index: var(--ui-site-header-z-index, 10);
53
+ }
54
+ .menu, .actions {
55
+ display: flex !important;
56
+ flex: none;
57
+ align-items: center !important;
58
+ gap: var(--ui-space-2) !important;
59
+ min-inline-size: 0;
60
+ max-inline-size: 100%;
61
+ }
62
+ .actions {
63
+ flex-wrap: wrap !important;
64
+ margin-inline-start: auto !important;
65
+ }
66
+ /* Text shares a baseline inside one group; the group is centred beside any control height. */
67
+ .identity {
68
+ display: flex !important;
69
+ flex: 1 1 auto;
70
+ flex-wrap: wrap !important;
71
+ align-items: baseline !important;
72
+ gap: var(--ui-space-2) var(--ui-space-6) !important;
73
+ min-inline-size: 0;
74
+ }
75
+ .brand {
76
+ min-inline-size: 0;
77
+ font-size: var(--ui-font-size-lg);
78
+ font-weight: var(--ui-font-bold);
79
+ }
80
+ .navigation {
81
+ display: flex !important;
82
+ flex-wrap: wrap !important;
83
+ align-items: baseline !important;
84
+ gap: var(--ui-space-2) var(--ui-space-5) !important;
85
+ min-inline-size: 0;
86
+ font-size: var(--ui-font-size-sm);
87
+ font-weight: var(--ui-font-semibold);
88
+ }
89
+ /* Without a supplied menu trigger, keep the destinations available on narrow screens. */
90
+ :scope:where([data-component~="ui-site-header"]):has(> .menu:not(:empty)) .navigation {
91
+ display: none !important;
92
+ }
93
+ .menu:empty, .actions:empty, .brand:empty, .navigation:empty {
94
+ display: none !important;
95
+ }
96
+ @media (min-width: 40rem) {
97
+ :scope:where([data-component~="ui-site-header"])[data-ui-site-header-state~="breakpoint=sm"] {
98
+ min-block-size: var(--ui-site-header-height, 4.25rem);
99
+ column-gap: var(--ui-space-4) !important;
100
+ }
101
+ :scope:where([data-component~="ui-site-header"])[data-ui-site-header-state~="breakpoint=sm"] .navigation:not(:empty) {
102
+ display: flex !important;
103
+ }
104
+ :scope:where([data-component~="ui-site-header"])[data-ui-site-header-state~="breakpoint=sm"] .menu {
105
+ display: none !important;
106
+ }
107
+ }
108
+ @media (min-width: 48rem) {
109
+ :scope:where([data-component~="ui-site-header"])[data-ui-site-header-state~="breakpoint=md"] {
110
+ min-block-size: var(--ui-site-header-height, 4.25rem);
111
+ column-gap: var(--ui-space-4) !important;
112
+ }
113
+ :scope:where([data-component~="ui-site-header"])[data-ui-site-header-state~="breakpoint=md"] .navigation:not(:empty) {
114
+ display: flex !important;
115
+ }
116
+ :scope:where([data-component~="ui-site-header"])[data-ui-site-header-state~="breakpoint=md"] .menu {
117
+ display: none !important;
118
+ }
119
+ }
120
+ @media (min-width: 64rem) {
121
+ :scope:where([data-component~="ui-site-header"])[data-ui-site-header-state~="breakpoint=lg"] {
122
+ min-block-size: var(--ui-site-header-height, 4.25rem);
123
+ column-gap: var(--ui-space-4) !important;
124
+ }
125
+ :scope:where([data-component~="ui-site-header"])[data-ui-site-header-state~="breakpoint=lg"] .navigation:not(:empty) {
126
+ display: flex !important;
127
+ }
128
+ :scope:where([data-component~="ui-site-header"])[data-ui-site-header-state~="breakpoint=lg"] .menu {
129
+ display: none !important;
130
+ }
131
+ }
132
+ :scope:where([data-component~="ui-site-header"])[hidden] {
133
+ display: none !important;
134
+ }
135
+ }
136
+ @scope ([data-component~="ui-site-header"]) to ([data-component]) {
137
+ /* Text shares a baseline inside one group; the group is centred beside any control height. */
138
+ .brand > :where([data-slotted], [data-slotted] *):is(a) {
139
+ display: inline-flex !important;
140
+ align-items: baseline !important;
141
+ gap: var(--ui-space-3) !important;
142
+ min-inline-size: 0;
143
+ max-inline-size: 100%;
144
+ color: inherit;
145
+ text-decoration: none;
146
+ }
147
+ /* Without a supplied menu trigger, keep the destinations available on narrow screens. */
148
+ .navigation > :where([data-slotted], [data-slotted] *):is(a) {
149
+ color: inherit;
150
+ text-decoration: none;
151
+ }
152
+ .navigation > :where([data-slotted], [data-slotted] *):is(a):is(:hover, [aria-current="page"], [aria-current="true"]) {
153
+ color: var(--ui-accent-active);
154
+ }
155
+ .brand > :where([data-slotted], [data-slotted] *):is(a):focus-visible, .navigation > :where([data-slotted], [data-slotted] *):is(a):focus-visible {
156
+ outline: var(--ui-focus-width) solid var(--ui-focus-ring);
157
+ outline-offset: var(--ui-focus-width);
158
+ }
159
+ @media (min-width: 40rem) {
160
+ }
161
+ @media (min-width: 48rem) {
162
+ }
163
+ @media (min-width: 64rem) {
164
+ }
165
+ }
@@ -0,0 +1,25 @@
1
+ // Generated by HTML Next 1.0.0-alpha.69 for Vanilla DOM. Do not edit.
2
+ export interface UiSiteHeaderEventMap {
3
+ }
4
+ export interface UiSiteHeaderElement extends HTMLElement {
5
+ addEventListener<K extends keyof UiSiteHeaderEventMap>(type: K, listener: (this: UiSiteHeaderElement, event: UiSiteHeaderEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
6
+ addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: UiSiteHeaderElement, event: HTMLElementEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
7
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
8
+ removeEventListener<K extends keyof UiSiteHeaderEventMap>(type: K, listener: (this: UiSiteHeaderElement, event: UiSiteHeaderEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
9
+ removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: UiSiteHeaderElement, event: HTMLElementEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
10
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
11
+ }
12
+ export interface UiSiteHeaderProps {
13
+ breakpoint?: "sm" | "md" | "lg" | null;
14
+ label?: string | null;
15
+ sticky?: boolean | null;
16
+ attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
17
+ children?: readonly (string | Node)[];
18
+ slots?: Readonly<Record<string, readonly (string | Node)[]>>;
19
+ }
20
+ export declare function createUiSiteHeader(props?: UiSiteHeaderProps): UiSiteHeaderElement;
21
+ declare global {
22
+ interface ComponentTagMap {
23
+ "ui-site-header": { element: UiSiteHeaderElement; props: Omit<UiSiteHeaderProps, "attributes" | "children" | "slots"> };
24
+ }
25
+ }
@@ -0,0 +1,96 @@
1
+ // Generated by HTML Next 1.0.0-alpha.69 for Vanilla DOM. Do not edit.
2
+ import { attachGeneratedController, buildTemplate, toAttribute, writeAttribute, dispose, formatOf, keywordFormat, hostState, acceptProps, manageProps, generatedInputs, project, fillSlot, checkBoolean, checkFormat, checkString, defineComponent } from "@nextwebwg/html-next/generated-runtime";
3
+ import "../styles/ui-site-header.css";
4
+
5
+ const T0 = ["",[],"\n ",["span",["class","menu"],4],"\n ",["div",["class","identity"],"\n ",["div",["class","brand"],4],"\n ",["nav",["class","navigation"],4],"\n "],"\n ",["div",["class","actions"],4],"\n "];
6
+ const T1 = ["",[]];
7
+ const T2 = ["",[]];
8
+ const T3 = ["",[]];
9
+ const T4 = ["",[]];
10
+ let P0, P1, P2, P3, P4;
11
+ const S = { n: [], t: [], f: import.meta.url, g: "ui-site-header", b: generatedInputs };
12
+ const D = { g: "ui-site-header", props: { "breakpoint": { "required":false,"values":["sm","md","lg"],"default":"lg", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat)] }, "label": { "required":false,"default":"Main", c: checkString, t: "string", j: 0, m: "s" }, "sticky": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" } } };
13
+
14
+ export function createUiSiteHeader(options = {}, html) {
15
+ const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
16
+ const element = document.createElement("header");
17
+ for (const [name, value] of Object.entries(attributes)) {
18
+ if (value === null || value === undefined || value === false) continue;
19
+ element.setAttribute(name, value === true ? "" : String(value));
20
+ }
21
+ element.setAttribute("data-component", "ui-site-header");
22
+ element.append((P0 ??= buildTemplate(T0)).cloneNode(true));
23
+ const v = [null, null, null];
24
+ const B = acceptProps(element, D, S.n, v, componentProps, [], html);
25
+ const m1 = (d) => {
26
+ const n = (P1 ??= buildTemplate(T1)).cloneNode(true);
27
+ const r = { n };
28
+ p1(r, -1, d);
29
+ return r;
30
+ };
31
+ const p1 = (r, c, d) => {
32
+ };
33
+ const m2 = (d) => {
34
+ const n = (P2 ??= buildTemplate(T2)).cloneNode(true);
35
+ const r = { n };
36
+ p2(r, -1, d);
37
+ return r;
38
+ };
39
+ const p2 = (r, c, d) => {
40
+ };
41
+ const m3 = (d) => {
42
+ const n = (P3 ??= buildTemplate(T3)).cloneNode(true);
43
+ const r = { n };
44
+ p3(r, -1, d);
45
+ return r;
46
+ };
47
+ const p3 = (r, c, d) => {
48
+ };
49
+ const m4 = (d) => {
50
+ const n = (P4 ??= buildTemplate(T4)).cloneNode(true);
51
+ const r = { n };
52
+ p4(r, -1, d);
53
+ return r;
54
+ };
55
+ const p4 = (r, c, d) => {
56
+ };
57
+ const p0 = (r, c, d) => {
58
+ if (c & 2) {
59
+ const x0 = v[1];
60
+ const s0 = toAttribute(x0, "aria-label");
61
+ if (s0 !== r.v0) writeAttribute(r.a2, "aria-label", r.v0 = s0);
62
+ }
63
+ if (c & 5) {
64
+ const x1 = hostState(["sticky","breakpoint"], [v[2], v[0]]);
65
+ const s1 = x1;
66
+ if (s1 !== r.v1) writeAttribute(r.n, "data-ui-site-header-state", (r.v1 = s1) === "" ? null : s1);
67
+ }
68
+ if (r.f0 === undefined) { r.f0 = 1; const at = fillSlot(r.a0, r.e0, "menu", J, false, undefined, d);
69
+ if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b0 = m1(d); at.before(r.b0.n); } }
70
+ else if (r.b0 !== undefined) p1(r.b0, c, d);
71
+ if (r.f1 === undefined) { r.f1 = 1; const at = fillSlot(r.a1, r.e1, "brand", J, false, undefined, d);
72
+ if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b1 = m2(d); at.before(r.b1.n); } }
73
+ else if (r.b1 !== undefined) p2(r.b1, c, d);
74
+ if (r.f2 === undefined) { r.f2 = 1; const at = fillSlot(r.a3, r.e2, "navigation", J, false, undefined, d);
75
+ if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b2 = m3(d); at.before(r.b2.n); } }
76
+ else if (r.b2 !== undefined) p3(r.b2, c, d);
77
+ if (r.f3 === undefined) { r.f3 = 1; const at = fillSlot(r.a4, r.e3, "actions", J, false, undefined, d);
78
+ if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b3 = m4(d); at.before(r.b3.n); } }
79
+ else if (r.b3 !== undefined) p4(r.b3, c, d);
80
+ };
81
+ const t0 = element.firstChild.nextSibling;
82
+ const t1 = t0.firstChild;
83
+ const t2 = t0.nextSibling.nextSibling;
84
+ const t3 = t2.firstChild.nextSibling;
85
+ const t4 = t3.firstChild;
86
+ const t5 = t3.nextSibling.nextSibling;
87
+ const t6 = t5.firstChild;
88
+ const t7 = t2.nextSibling.nextSibling.firstChild;
89
+ const R = { n: element, a2: t5, v0: null, v1: undefined, a0: t1, e0: t1.nextSibling, b0: undefined, f0: undefined, a1: t4, e1: t4.nextSibling, b1: undefined, f1: undefined, a3: t6, e2: t6.nextSibling, b2: undefined, f2: undefined, a4: t7, e3: t7.nextSibling, b3: undefined, f3: undefined };
90
+ const I = { B };
91
+ const J = project(I, children, slots);
92
+ attachGeneratedController(element, S, v, ((c, d) => p0(R, c, d)), undefined, undefined, I);
93
+ manageProps(I);
94
+ return element;
95
+ }
96
+ defineComponent("ui-site-header", createUiSiteHeader, ["breakpoint","label","sticky"]);
package/vanilla/index.js CHANGED
@@ -71,6 +71,7 @@ export * from "./UiSection.js";
71
71
  export * from "./UiSelect.js";
72
72
  export * from "./UiSeparator.js";
73
73
  export * from "./UiSidebar.js";
74
+ export * from "./UiSiteHeader.js";
74
75
  export * from "./UiSkeleton.js";
75
76
  export * from "./UiSlider.js";
76
77
  export * from "./UiSpinner.js";
package/vue/UiCallout.vue CHANGED
@@ -325,7 +325,15 @@ const hostState = computed(() =>
325
325
  --_ui-callout-icon: var(--ui-callout-icon);
326
326
  --_ui-callout-icon-size: var(--ui-callout-icon-size);
327
327
 
328
- --_callout-surface: oklch(from var(--_callout-border) l c h / 10%);
328
+ /* Near white, sRGB retains more green chroma than blue/red; bound chroma by hue to avoid clipping. */
329
+ --_callout-surface: light-dark(
330
+ oklch(
331
+ from var(--_callout-border)
332
+ 96% min(c, calc(0.02 + 0.03 * max(0, cos(calc((h - 140) * 1deg)))))
333
+ h
334
+ ),
335
+ oklch(from var(--_callout-border) 25% min(c, 0.035) h)
336
+ );
329
337
  --_ui-selection-context-surface: light-dark(
330
338
  oklch(
331
339
  from var(--ui-callout-surface, var(--_callout-surface))
@@ -0,0 +1,47 @@
1
+ import type { PropType } from 'vue';
2
+ import { type InputBindings } from './props.js';
3
+ declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {}, __VLS_7: {};
4
+ type __VLS_Slots = {} & {
5
+ menu?: (props: typeof __VLS_1) => any;
6
+ } & {
7
+ brand?: (props: typeof __VLS_3) => any;
8
+ } & {
9
+ navigation?: (props: typeof __VLS_5) => any;
10
+ } & {
11
+ actions?: (props: typeof __VLS_7) => any;
12
+ };
13
+ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
14
+ breakpoint: {
15
+ type: PropType<"sm" | "md" | "lg" | null>;
16
+ };
17
+ label: {
18
+ type: PropType<string | null>;
19
+ };
20
+ sticky: {
21
+ type: PropType<boolean | null>;
22
+ };
23
+ "\0htmlNextInputStatus": {
24
+ type: PropType<InputBindings>;
25
+ };
26
+ }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
27
+ breakpoint: {
28
+ type: PropType<"sm" | "md" | "lg" | null>;
29
+ };
30
+ label: {
31
+ type: PropType<string | null>;
32
+ };
33
+ sticky: {
34
+ type: PropType<boolean | null>;
35
+ };
36
+ "\0htmlNextInputStatus": {
37
+ type: PropType<InputBindings>;
38
+ };
39
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
40
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
41
+ declare const _default: typeof __VLS_export;
42
+ export default _default;
43
+ type __VLS_WithSlots<T, S> = T & {
44
+ new (): {
45
+ $slots: S;
46
+ };
47
+ };
@@ -0,0 +1,2 @@
1
+ import { t as UiSiteHeader_default } from "./chunks/UiSiteHeader.js";
2
+ export { UiSiteHeader_default as default };