@nxgt/material 3.76.0 → 3.77.0
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/CHANGELOG.md +36 -0
- package/README.md +2 -2
- package/dist/{calculator-BaSMe0SK.js → calculator-DSSaYRmM.js} +2 -2
- package/dist/calculator-field.js +2 -2
- package/dist/calculator.js +1 -1
- package/dist/components/ui/display/chip/chip-hairline.css +19 -0
- package/dist/components/ui/display/chip/chip-soft.css +18 -0
- package/dist/{components-Ci3Zo8kC.js → components-ZJx47chq.js} +11714 -11637
- package/dist/components.js +34 -34
- package/dist/{currency-field-BJ9rSrif.js → currency-field-DWHB5oms.js} +3 -2
- package/dist/editor.js +1 -1
- package/dist/{financial-variant-BsZEa5sF.js → financial-variant-vZdgyMeN.js} +3 -3
- package/dist/lib/components/ui/collections/row-menu/use-row-menu-focus.d.ts +11 -1
- package/dist/lib/components/ui/collections/server-table/partials/server-table-phone-row.d.ts +1 -1
- package/dist/lib/components/ui/display/entity-header/partials/entity-header-actions.d.ts +3 -1
- package/dist/lib/components/ui/display/entity-header/partials/entity-header-layout.d.ts +10 -0
- package/dist/lib/components/ui/fields/quantity-field/quantity-row.d.ts +4 -3
- package/dist/lib/components/ui/layout/app-shell/page-title.d.ts +4 -3
- package/dist/lib/components/ui/layout/hero/hero-backdrop.d.ts +7 -0
- package/dist/lib/components/ui/layout/hero/hero-parts.d.ts +27 -0
- package/dist/lib/components/ui/layout/hero/hero.d.ts +26 -1
- package/dist/lib/components/ui/primitives/tabs/tabs-manual-scroll.d.ts +16 -0
- package/dist/lib/components/ui/primitives/tabs/use-tabs-overflow.d.ts +1 -1
- package/dist/main.js +49 -49
- package/dist/material.css +1 -1
- package/dist/{percent-field-lahyDJDG.js → percent-field--WIXV5dX.js} +1 -1
- package/dist/{tabs-DzEqMb1W.js → tabs-BT9pSRwk.js} +128 -97
- package/dist/{use-chat-composer-DMXu9E1O.js → use-chat-composer-BOx4I6Ma.js} +1 -1
- package/docs/components/data-display.md +2 -1
- package/docs/components/data-table-filter-and-lists.md +13 -1
- package/docs/components/form-fields.md +6 -3
- package/docs/components/navigation-and-layout.md +29 -1
- package/docs/components/selection-and-choice.md +3 -1
- package/docs/guides/app-shell.md +6 -4
- package/docs/guides/theming.md +5 -5
- package/docs/troubleshooting.md +3 -2
- package/lib/components/ui/display/chip/chip-hairline.css +19 -0
- package/lib/components/ui/display/chip/chip-soft.css +18 -0
- package/lib/themes/ambre.css +1 -1
- package/lib/themes/ardoise.css +1 -1
- package/lib/themes/bleumono.css +1 -1
- package/lib/themes/bluemoon.css +1 -1
- package/lib/themes/corail.css +2 -2
- package/lib/themes/foret.css +1 -1
- package/lib/themes/lavande.css +1 -1
- package/lib/themes/menthe.css +1 -1
- package/lib/themes/ocean.css +1 -1
- package/lib/themes/pink.css +2 -2
- package/lib/themes/prune.css +1 -1
- package/lib/themes/sable.css +1 -1
- package/lib/themes/slate.css +1 -1
- package/lib/themes/teal.css +3 -3
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as e } from "./currency-field-
|
|
1
|
+
import { r as e } from "./currency-field-DWHB5oms.js";
|
|
2
2
|
import { jsx as t } from "react/jsx-runtime";
|
|
3
3
|
//#region lib/components/ui/fields/percent-field/percent-field.tsx
|
|
4
4
|
function n({ min: n = 0, max: r = 100, step: i = 1, ...a }) {
|
|
@@ -6,20 +6,20 @@ import { i as c, n as l, r as u, t as d } from "./dist-DOK3zo5C.js";
|
|
|
6
6
|
import { t as f } from "./use-material-translation-CD6QoVal.js";
|
|
7
7
|
import * as p from "react";
|
|
8
8
|
import { createContext as m, useCallback as h, useContext as g, useEffect as ee, useLayoutEffect as _, useRef as v, useState as te } from "react";
|
|
9
|
-
import { Fragment as
|
|
10
|
-
import { ChevronLeft as
|
|
9
|
+
import { Fragment as ne, jsx as y, jsxs as b } from "react/jsx-runtime";
|
|
10
|
+
import { ChevronLeft as re, ChevronRight as ie } from "lucide-react";
|
|
11
11
|
//#region ../../node_modules/@radix-ui/react-tabs/dist/index.mjs
|
|
12
|
-
var
|
|
12
|
+
var ae = Object.defineProperty, x = (e, t) => ae(e, "name", {
|
|
13
13
|
value: t,
|
|
14
14
|
configurable: !0
|
|
15
|
-
}),
|
|
15
|
+
}), S = "Tabs", [oe, se] = a(S, [u]), C = u(), [ce, w] = oe(S), le = /* @__PURE__ */ p.forwardRef(/* @__PURE__ */ x(function(e, t) {
|
|
16
16
|
let { __scopeTabs: r, value: a, onValueChange: o, defaultValue: l, orientation: u = "horizontal", dir: d, activationMode: f = "automatic", ...p } = e, m = c(d), [h, g] = i({
|
|
17
17
|
prop: a,
|
|
18
18
|
onChange: o,
|
|
19
19
|
defaultProp: l ?? "",
|
|
20
|
-
caller:
|
|
20
|
+
caller: S
|
|
21
21
|
});
|
|
22
|
-
return /* @__PURE__ */
|
|
22
|
+
return /* @__PURE__ */ y(ce, {
|
|
23
23
|
scope: r,
|
|
24
24
|
baseId: s(),
|
|
25
25
|
value: h,
|
|
@@ -27,36 +27,36 @@ var S = Object.defineProperty, C = (e, t) => S(e, "name", {
|
|
|
27
27
|
orientation: u,
|
|
28
28
|
dir: m,
|
|
29
29
|
activationMode: f,
|
|
30
|
-
children: /* @__PURE__ */
|
|
30
|
+
children: /* @__PURE__ */ y(n.div, {
|
|
31
31
|
dir: m,
|
|
32
32
|
"data-orientation": u,
|
|
33
33
|
...p,
|
|
34
34
|
ref: t
|
|
35
35
|
})
|
|
36
36
|
});
|
|
37
|
-
}, "Tabs")),
|
|
38
|
-
let { __scopeTabs: r, loop: i = !0, ...a } = e, o =
|
|
39
|
-
return /* @__PURE__ */
|
|
37
|
+
}, "Tabs")), ue = "TabsList", T = /* @__PURE__ */ p.forwardRef(/* @__PURE__ */ x(function(e, t) {
|
|
38
|
+
let { __scopeTabs: r, loop: i = !0, ...a } = e, o = w(ue, r);
|
|
39
|
+
return /* @__PURE__ */ y(l, {
|
|
40
40
|
asChild: !0,
|
|
41
|
-
...
|
|
41
|
+
...C(r),
|
|
42
42
|
orientation: o.orientation,
|
|
43
43
|
dir: o.dir,
|
|
44
44
|
loop: i,
|
|
45
|
-
children: /* @__PURE__ */
|
|
45
|
+
children: /* @__PURE__ */ y(n.div, {
|
|
46
46
|
role: "tablist",
|
|
47
47
|
"aria-orientation": o.orientation,
|
|
48
48
|
...a,
|
|
49
49
|
ref: t
|
|
50
50
|
})
|
|
51
51
|
});
|
|
52
|
-
}, "TabsList")),
|
|
53
|
-
let { __scopeTabs: i, value: a, disabled: o = !1, ...s } = e, c = E
|
|
54
|
-
return /* @__PURE__ */
|
|
52
|
+
}, "TabsList")), E = "TabsTrigger", D = /* @__PURE__ */ p.forwardRef(/* @__PURE__ */ x(function(e, t) {
|
|
53
|
+
let { __scopeTabs: i, value: a, disabled: o = !1, ...s } = e, c = w(E, i), l = C(i), u = k(c.baseId, a), f = A(c.baseId, a), p = a === c.value;
|
|
54
|
+
return /* @__PURE__ */ y(d, {
|
|
55
55
|
asChild: !0,
|
|
56
56
|
...l,
|
|
57
57
|
focusable: !o,
|
|
58
58
|
active: p,
|
|
59
|
-
children: /* @__PURE__ */
|
|
59
|
+
children: /* @__PURE__ */ y(n.button, {
|
|
60
60
|
type: "button",
|
|
61
61
|
role: "tab",
|
|
62
62
|
"aria-selected": p,
|
|
@@ -79,14 +79,14 @@ var S = Object.defineProperty, C = (e, t) => S(e, "name", {
|
|
|
79
79
|
})
|
|
80
80
|
})
|
|
81
81
|
});
|
|
82
|
-
}, "TabsTrigger")),
|
|
83
|
-
let { __scopeTabs: r, value: i, forceMount: a, children: s, ...c } = e, l =
|
|
82
|
+
}, "TabsTrigger")), O = "TabsContent", de = /* @__PURE__ */ p.forwardRef(/* @__PURE__ */ x(function(e, t) {
|
|
83
|
+
let { __scopeTabs: r, value: i, forceMount: a, children: s, ...c } = e, l = w(O, r), u = k(l.baseId, i), d = A(l.baseId, i), f = i === l.value, m = p.useRef(f);
|
|
84
84
|
return p.useEffect(() => {
|
|
85
85
|
let e = requestAnimationFrame(() => m.current = !1);
|
|
86
86
|
return () => cancelAnimationFrame(e);
|
|
87
|
-
}, []), /* @__PURE__ */
|
|
87
|
+
}, []), /* @__PURE__ */ y(o, {
|
|
88
88
|
present: a || f,
|
|
89
|
-
children: ({ present: r }) => /* @__PURE__ */
|
|
89
|
+
children: ({ present: r }) => /* @__PURE__ */ y(n.div, {
|
|
90
90
|
"data-state": f ? "active" : "inactive",
|
|
91
91
|
"data-orientation": l.orientation,
|
|
92
92
|
role: "tabpanel",
|
|
@@ -104,37 +104,37 @@ var S = Object.defineProperty, C = (e, t) => S(e, "name", {
|
|
|
104
104
|
})
|
|
105
105
|
});
|
|
106
106
|
}, "TabsContent"));
|
|
107
|
-
function
|
|
107
|
+
function k(e, t) {
|
|
108
108
|
return `${e}-trigger-${t}`;
|
|
109
109
|
}
|
|
110
|
-
|
|
111
|
-
function
|
|
110
|
+
x(k, "makeTriggerId");
|
|
111
|
+
function A(e, t) {
|
|
112
112
|
return `${e}-content-${t}`;
|
|
113
113
|
}
|
|
114
|
-
|
|
115
|
-
var
|
|
114
|
+
x(A, "makeContentId");
|
|
115
|
+
var fe = le, pe = T, me = D, he = de;
|
|
116
116
|
//#endregion
|
|
117
117
|
//#region lib/components/ui/primitives/tabs/tabs-classes.ts
|
|
118
|
-
function
|
|
118
|
+
function j(e) {
|
|
119
119
|
return e === "segmented" || e === "line" ? "segmented" : "underline";
|
|
120
120
|
}
|
|
121
|
-
var
|
|
121
|
+
var M = "aria-[orientation=vertical]:flex-col", ge = {
|
|
122
122
|
underline: "flex min-w-0 flex-col gap-2 items-stretch data-[orientation=vertical]:flex-row",
|
|
123
123
|
segmented: "flex min-w-0 flex-col gap-2 items-start data-[orientation=vertical]:flex-row"
|
|
124
|
-
},
|
|
125
|
-
underline: `group/tabs-list relative flex gap-1 border-b border-border overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden ${
|
|
126
|
-
segmented: `group/tabs-list relative inline-flex max-w-full rounded-full bg-muted p-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden ${
|
|
127
|
-
},
|
|
128
|
-
underline: `${
|
|
129
|
-
segmented: `${
|
|
130
|
-
},
|
|
131
|
-
underline: `${
|
|
132
|
-
segmented: `${
|
|
133
|
-
},
|
|
124
|
+
}, N = {
|
|
125
|
+
underline: `group/tabs-list relative flex gap-1 border-b border-border overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden ${M} aria-[orientation=vertical]:border-b-0 aria-[orientation=vertical]:border-l aria-[orientation=vertical]:overflow-x-visible aria-[orientation=vertical]:overflow-y-auto`,
|
|
126
|
+
segmented: `group/tabs-list relative inline-flex max-w-full rounded-full bg-muted p-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden ${M} aria-[orientation=vertical]:rounded-3xl aria-[orientation=vertical]:overflow-x-visible aria-[orientation=vertical]:overflow-y-auto`
|
|
127
|
+
}, P = "relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap text-sm font-medium text-muted-foreground transition-colors disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-4 focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-primary dark:focus-visible:outline-track-fill", F = "group-data-[indicator=ready]/tabs-list:after:hidden", I = {
|
|
128
|
+
underline: `${P} h-10 px-4 rounded-t-md hover:bg-primary/5 data-[state=inactive]:hover:text-foreground data-[state=active]:text-primary-text data-[orientation=vertical]:justify-start data-[orientation=vertical]:rounded-t-none data-[orientation=vertical]:rounded-r-md after:pointer-events-none after:absolute after:inset-x-0 after:bottom-0 after:h-0.5 after:rounded-full data-[state=active]:after:bg-primary dark:data-[state=active]:after:bg-track-fill data-[orientation=vertical]:after:inset-x-auto data-[orientation=vertical]:after:left-0 data-[orientation=vertical]:after:inset-y-0 data-[orientation=vertical]:after:h-auto data-[orientation=vertical]:after:w-0.5 ${F}`,
|
|
129
|
+
segmented: `${P} z-10 h-8 px-4 rounded-full data-[state=inactive]:hover:text-foreground data-[state=active]:text-foreground data-[state=active]:font-semibold after:pointer-events-none after:absolute after:inset-0 after:-z-10 after:rounded-full data-[state=active]:after:bg-background data-[state=active]:after:shadow-sm data-[state=active]:after:border data-[state=active]:after:border-muted-foreground dark:data-[state=active]:after:bg-card ${F}`
|
|
130
|
+
}, L = "pointer-events-none absolute left-0 invisible group-data-[indicator=ready]/tabs-list:visible group-data-[indicator=ready]/tabs-list:motion-safe:transition-[translate,width,height] duration-300 ease-out", _e = {
|
|
131
|
+
underline: `${L} bottom-0 h-0.5 rounded-full bg-primary dark:bg-track-fill w-(--tabs-indicator-w) translate-x-(--tabs-indicator-x) group-aria-[orientation=vertical]/tabs-list:bottom-auto group-aria-[orientation=vertical]/tabs-list:top-0 group-aria-[orientation=vertical]/tabs-list:w-0.5 group-aria-[orientation=vertical]/tabs-list:h-(--tabs-indicator-w) group-aria-[orientation=vertical]/tabs-list:translate-x-0 group-aria-[orientation=vertical]/tabs-list:translate-y-(--tabs-indicator-x)`,
|
|
132
|
+
segmented: `${L} inset-y-1 rounded-full bg-background shadow-sm border border-muted-foreground dark:bg-card w-(--tabs-indicator-w) translate-x-(--tabs-indicator-x) group-aria-[orientation=vertical]/tabs-list:inset-y-auto group-aria-[orientation=vertical]/tabs-list:inset-x-1 group-aria-[orientation=vertical]/tabs-list:top-0 group-aria-[orientation=vertical]/tabs-list:w-auto group-aria-[orientation=vertical]/tabs-list:h-(--tabs-indicator-w) group-aria-[orientation=vertical]/tabs-list:translate-x-0 group-aria-[orientation=vertical]/tabs-list:translate-y-(--tabs-indicator-x)`
|
|
133
|
+
}, ve = "inline-flex items-center gap-2", R = "flex justify-center", ye = "w-full flex-1 outline-none";
|
|
134
134
|
//#endregion
|
|
135
135
|
//#region lib/components/ui/primitives/tabs/partials/tabs-content.tsx
|
|
136
136
|
function be({ className: t, ...n }) {
|
|
137
|
-
return /* @__PURE__ */
|
|
137
|
+
return /* @__PURE__ */ y(he, {
|
|
138
138
|
"data-slot": "tabs-content",
|
|
139
139
|
className: e(ye, t),
|
|
140
140
|
...n
|
|
@@ -147,8 +147,33 @@ function H() {
|
|
|
147
147
|
return g(V);
|
|
148
148
|
}
|
|
149
149
|
//#endregion
|
|
150
|
+
//#region lib/components/ui/primitives/tabs/tabs-manual-scroll.ts
|
|
151
|
+
var U = "tabs-manual-scroll";
|
|
152
|
+
function we(e) {
|
|
153
|
+
e.dispatchEvent(new Event(U));
|
|
154
|
+
}
|
|
155
|
+
function Te(e, t) {
|
|
156
|
+
let n = 0, r = 0, i = "", a = () => `${e.clientWidth}/${e.scrollWidth}`, o = { follow: !0 }, s = () => {
|
|
157
|
+
o.follow = !1;
|
|
158
|
+
}, c = (e) => {
|
|
159
|
+
Math.abs(e.deltaX) > Math.abs(e.deltaY) && s();
|
|
160
|
+
}, l = () => {
|
|
161
|
+
a() === i && (e.scrollLeft < n - 1 || e.scrollLeft > r + 1) && s();
|
|
162
|
+
};
|
|
163
|
+
return i = a(), e.addEventListener("wheel", c, { passive: !0 }), e.addEventListener("scroll", l, { passive: !0 }), e.addEventListener(U, s), {
|
|
164
|
+
state: o,
|
|
165
|
+
reveal(o, s) {
|
|
166
|
+
let c = e.scrollLeft, l = t(e, o, s);
|
|
167
|
+
n = Math.min(c, c + l), r = Math.max(c, c + l), i = a();
|
|
168
|
+
},
|
|
169
|
+
dispose() {
|
|
170
|
+
e.removeEventListener("wheel", c), e.removeEventListener("scroll", l), e.removeEventListener(U, s);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
150
175
|
//#region lib/components/ui/primitives/tabs/tabs-selectors.ts
|
|
151
|
-
var
|
|
176
|
+
var W = "[role=\"tab\"], [data-slot=\"tabs-trigger\"]", G = "[role=\"tab\"][data-state=\"active\"], [data-slot=\"tabs-trigger\"][data-state=\"active\"]", K = 64, q = {
|
|
152
177
|
left: !1,
|
|
153
178
|
right: !1,
|
|
154
179
|
top: 0,
|
|
@@ -156,13 +181,13 @@ var U = "[role=\"tab\"], [data-slot=\"tabs-trigger\"]", W = "[role=\"tab\"][data
|
|
|
156
181
|
width: 0,
|
|
157
182
|
height: 0
|
|
158
183
|
};
|
|
159
|
-
function
|
|
184
|
+
function J() {
|
|
160
185
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches ? "instant" : "smooth";
|
|
161
186
|
}
|
|
162
|
-
function
|
|
163
|
-
if (e.getAttribute("aria-orientation") === "vertical") return
|
|
187
|
+
function Y(e) {
|
|
188
|
+
if (e.getAttribute("aria-orientation") === "vertical") return q;
|
|
164
189
|
let t = e.scrollWidth - e.clientWidth;
|
|
165
|
-
if (t <= 1) return
|
|
190
|
+
if (t <= 1) return q;
|
|
166
191
|
let n = Math.abs(e.scrollLeft), r = n > 1, i = t - n > 1, a = getComputedStyle(e).direction === "rtl";
|
|
167
192
|
return {
|
|
168
193
|
left: a ? i : r,
|
|
@@ -173,64 +198,69 @@ function J(e) {
|
|
|
173
198
|
height: e.offsetHeight
|
|
174
199
|
};
|
|
175
200
|
}
|
|
176
|
-
var
|
|
177
|
-
function
|
|
178
|
-
if (e.scrollWidth <= e.clientWidth) return;
|
|
201
|
+
var X = (e, t) => e.left === t.left && e.right === t.right && e.top === t.top && e.x === t.x && e.width === t.width && e.height === t.height;
|
|
202
|
+
function Ee(e, t, n = J()) {
|
|
203
|
+
if (e.scrollWidth <= e.clientWidth) return 0;
|
|
179
204
|
let r = e.getBoundingClientRect(), i = t.getBoundingClientRect(), a = 0;
|
|
180
|
-
i.left < r.left +
|
|
205
|
+
return i.left < r.left + K ? a = i.left - r.left - K : i.right > r.right - K && (a = i.right - r.right + K), a && e.scrollBy({
|
|
181
206
|
left: a,
|
|
182
207
|
behavior: n
|
|
183
|
-
});
|
|
208
|
+
}), a;
|
|
184
209
|
}
|
|
185
210
|
function Z(e, t = {
|
|
186
|
-
tab:
|
|
187
|
-
active:
|
|
211
|
+
tab: W,
|
|
212
|
+
active: G
|
|
188
213
|
}) {
|
|
189
|
-
let [n, r] = te(
|
|
214
|
+
let [n, r] = te(q);
|
|
190
215
|
return _(() => {
|
|
191
216
|
let n = e.current;
|
|
192
217
|
if (!n) return;
|
|
193
218
|
let i = 0, a = () => {
|
|
194
219
|
cancelAnimationFrame(i), i = requestAnimationFrame(() => {
|
|
195
|
-
let e =
|
|
196
|
-
r((t) =>
|
|
220
|
+
let e = Y(n);
|
|
221
|
+
r((t) => X(t, e) ? t : e);
|
|
197
222
|
});
|
|
198
|
-
}, o = () => n.querySelector(t.active), s =
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
223
|
+
}, o = () => n.querySelector(t.active), s = Te(n, Ee), { state: c, reveal: l } = s, u = new ResizeObserver(() => {
|
|
224
|
+
a();
|
|
225
|
+
let e = c.follow ? o() : null;
|
|
226
|
+
e && l(e, "instant");
|
|
227
|
+
}), d = () => {
|
|
228
|
+
u.disconnect(), u.observe(n);
|
|
229
|
+
for (let e of n.querySelectorAll(t.tab)) u.observe(e);
|
|
230
|
+
}, f = new MutationObserver((e) => {
|
|
231
|
+
if (d(), a(), e.some((e) => e.type === "attributes")) {
|
|
232
|
+
c.follow = !0;
|
|
203
233
|
let e = o();
|
|
204
|
-
e &&
|
|
234
|
+
e && l(e);
|
|
205
235
|
}
|
|
206
236
|
});
|
|
207
|
-
|
|
237
|
+
f.observe(n, {
|
|
208
238
|
subtree: !0,
|
|
209
239
|
childList: !0,
|
|
210
240
|
attributeFilter: ["data-state"]
|
|
211
241
|
});
|
|
212
|
-
let
|
|
213
|
-
e.target instanceof HTMLElement && e.target.matches(t.tab) &&
|
|
242
|
+
let p = (e) => {
|
|
243
|
+
e.target instanceof HTMLElement && e.target.matches(t.tab) && (c.follow = e.target.matches(t.active), l(e.target));
|
|
214
244
|
};
|
|
215
|
-
n.addEventListener("focusin",
|
|
216
|
-
let
|
|
217
|
-
return
|
|
218
|
-
cancelAnimationFrame(i),
|
|
245
|
+
n.addEventListener("focusin", p), d();
|
|
246
|
+
let m = o();
|
|
247
|
+
return m && l(m, "instant"), r(Y(n)), () => {
|
|
248
|
+
cancelAnimationFrame(i), u.disconnect(), f.disconnect(), n.removeEventListener("focusin", p), s.dispose();
|
|
219
249
|
};
|
|
220
250
|
}, [
|
|
221
251
|
e,
|
|
222
252
|
t.tab,
|
|
223
253
|
t.active
|
|
224
|
-
]),
|
|
254
|
+
]), De(e, n.left || n.right, r), n;
|
|
225
255
|
}
|
|
226
|
-
function
|
|
256
|
+
function De(e, t, n) {
|
|
227
257
|
ee(() => {
|
|
228
258
|
let r = e.current;
|
|
229
259
|
if (!r || !t) return;
|
|
230
260
|
let i = 0, a = () => {
|
|
231
261
|
cancelAnimationFrame(i), i = requestAnimationFrame(() => {
|
|
232
|
-
let e =
|
|
233
|
-
n((t) =>
|
|
262
|
+
let e = Y(r);
|
|
263
|
+
n((t) => X(t, e) ? t : e);
|
|
234
264
|
});
|
|
235
265
|
};
|
|
236
266
|
return document.addEventListener("scroll", a, {
|
|
@@ -254,14 +284,14 @@ function Q({ look: t }) {
|
|
|
254
284
|
if (!e || !t) return;
|
|
255
285
|
let r = 0, i = () => {
|
|
256
286
|
cancelAnimationFrame(r), r = requestAnimationFrame(() => {
|
|
257
|
-
let n = t.querySelector(
|
|
287
|
+
let n = t.querySelector(G);
|
|
258
288
|
if (!n) return;
|
|
259
289
|
let r = t.getAttribute("aria-orientation") === "vertical", i = r ? n.offsetHeight : n.offsetWidth, a = r ? n.offsetTop : n.offsetLeft;
|
|
260
290
|
e.style.setProperty("--tabs-indicator-w", `${i}px`), e.style.setProperty("--tabs-indicator-x", `${a}px`), t.dataset.indicator !== "ready" && (e.offsetWidth, t.dataset.indicator = "ready");
|
|
261
291
|
});
|
|
262
292
|
}, a = new ResizeObserver(i), o = () => {
|
|
263
293
|
a.disconnect(), a.observe(t);
|
|
264
|
-
for (let e of t.querySelectorAll(
|
|
294
|
+
for (let e of t.querySelectorAll(W)) a.observe(e);
|
|
265
295
|
}, s = new MutationObserver(() => {
|
|
266
296
|
o(), i();
|
|
267
297
|
});
|
|
@@ -274,11 +304,11 @@ function Q({ look: t }) {
|
|
|
274
304
|
return c && s.observe(c, { attributeFilter: ["dir"] }), o(), i(), () => {
|
|
275
305
|
cancelAnimationFrame(r), a.disconnect(), s.disconnect();
|
|
276
306
|
};
|
|
277
|
-
}, []), /* @__PURE__ */
|
|
307
|
+
}, []), /* @__PURE__ */ y("span", {
|
|
278
308
|
ref: n,
|
|
279
309
|
"aria-hidden": !0,
|
|
280
310
|
"data-slot": "tabs-indicator",
|
|
281
|
-
className: e(
|
|
311
|
+
className: e(_e[t])
|
|
282
312
|
});
|
|
283
313
|
}
|
|
284
314
|
//#endregion
|
|
@@ -289,17 +319,18 @@ function $({ list: e, overflow: t }) {
|
|
|
289
319
|
let r = (t) => {
|
|
290
320
|
let n = e.current;
|
|
291
321
|
if (!n) return;
|
|
322
|
+
we(n);
|
|
292
323
|
let r = Math.max(96, n.clientWidth * .75);
|
|
293
324
|
n.scrollBy({
|
|
294
325
|
left: t * r,
|
|
295
|
-
behavior:
|
|
326
|
+
behavior: J()
|
|
296
327
|
});
|
|
297
328
|
}, i = {
|
|
298
329
|
type: "button",
|
|
299
330
|
tabIndex: -1,
|
|
300
331
|
onMouseDown: (e) => e.preventDefault()
|
|
301
332
|
};
|
|
302
|
-
return /* @__PURE__ */
|
|
333
|
+
return /* @__PURE__ */ b("div", {
|
|
303
334
|
"data-slot": "tabs-scroll",
|
|
304
335
|
className: xe,
|
|
305
336
|
style: {
|
|
@@ -308,28 +339,28 @@ function $({ list: e, overflow: t }) {
|
|
|
308
339
|
width: t.width,
|
|
309
340
|
height: t.height
|
|
310
341
|
},
|
|
311
|
-
children: [t.left && /* @__PURE__ */
|
|
342
|
+
children: [t.left && /* @__PURE__ */ y("button", {
|
|
312
343
|
...i,
|
|
313
344
|
"data-slot": "tabs-scroll-left",
|
|
314
345
|
"aria-label": n("material.tabs.scroll-left", "Scroll tabs left"),
|
|
315
346
|
className: Se,
|
|
316
347
|
onClick: () => r(-1),
|
|
317
|
-
children: /* @__PURE__ */
|
|
318
|
-
}), t.right && /* @__PURE__ */
|
|
348
|
+
children: /* @__PURE__ */ y(re, { "aria-hidden": !0 })
|
|
349
|
+
}), t.right && /* @__PURE__ */ y("button", {
|
|
319
350
|
...i,
|
|
320
351
|
"data-slot": "tabs-scroll-right",
|
|
321
352
|
"aria-label": n("material.tabs.scroll-right", "Scroll tabs right"),
|
|
322
353
|
className: Ce,
|
|
323
354
|
onClick: () => r(1),
|
|
324
|
-
children: /* @__PURE__ */
|
|
355
|
+
children: /* @__PURE__ */ y(ie, { "aria-hidden": !0 })
|
|
325
356
|
})]
|
|
326
357
|
});
|
|
327
358
|
}
|
|
328
359
|
//#endregion
|
|
329
360
|
//#region lib/components/ui/primitives/tabs/partials/tabs-list.tsx
|
|
330
|
-
function
|
|
361
|
+
function Oe({ className: n, children: r, ref: i, ...a }) {
|
|
331
362
|
let o = H(), s = v(null), c = Z(s);
|
|
332
|
-
return /* @__PURE__ */
|
|
363
|
+
return /* @__PURE__ */ b(ne, { children: [/* @__PURE__ */ b(pe, {
|
|
333
364
|
ref: h((e) => {
|
|
334
365
|
s.current = e, typeof i == "function" ? i(e) : i && (i.current = e);
|
|
335
366
|
}, [i]),
|
|
@@ -337,28 +368,28 @@ function Te({ className: n, children: r, ref: i, ...a }) {
|
|
|
337
368
|
"data-pw": "tabs-list",
|
|
338
369
|
"data-overflow-left": c.left ? "" : void 0,
|
|
339
370
|
"data-overflow-right": c.right ? "" : void 0,
|
|
340
|
-
className: e(
|
|
371
|
+
className: e(N[o], z, n),
|
|
341
372
|
...a,
|
|
342
|
-
children: [/* @__PURE__ */
|
|
343
|
-
}), /* @__PURE__ */
|
|
373
|
+
children: [/* @__PURE__ */ y(t, { children: r }), /* @__PURE__ */ y(Q, { look: o })]
|
|
374
|
+
}), /* @__PURE__ */ y($, {
|
|
344
375
|
list: s,
|
|
345
376
|
overflow: c
|
|
346
377
|
})] });
|
|
347
378
|
}
|
|
348
379
|
//#endregion
|
|
349
380
|
//#region lib/components/ui/primitives/tabs/partials/tabs-trigger.tsx
|
|
350
|
-
function
|
|
351
|
-
return /* @__PURE__ */
|
|
381
|
+
function ke({ className: n, children: r, icon: i, ...a }) {
|
|
382
|
+
return /* @__PURE__ */ b(me, {
|
|
352
383
|
"data-slot": "tabs-trigger",
|
|
353
|
-
className: e(
|
|
384
|
+
className: e(I[H()], n),
|
|
354
385
|
...a,
|
|
355
|
-
children: [i && /* @__PURE__ */
|
|
386
|
+
children: [i && /* @__PURE__ */ y("span", {
|
|
356
387
|
"data-slot": "tabs-trigger-icon",
|
|
357
388
|
className: "flex justify-center",
|
|
358
389
|
children: i
|
|
359
|
-
}), /* @__PURE__ */
|
|
390
|
+
}), /* @__PURE__ */ y(t, {
|
|
360
391
|
child: r,
|
|
361
|
-
children: (e) => e && /* @__PURE__ */
|
|
392
|
+
children: (e) => e && /* @__PURE__ */ y("span", {
|
|
362
393
|
className: "inline-flex items-center gap-2",
|
|
363
394
|
children: e
|
|
364
395
|
})
|
|
@@ -367,17 +398,17 @@ function Ee({ className: n, children: r, icon: i, ...a }) {
|
|
|
367
398
|
}
|
|
368
399
|
//#endregion
|
|
369
400
|
//#region lib/components/ui/primitives/tabs/tabs.tsx
|
|
370
|
-
function
|
|
371
|
-
let i =
|
|
372
|
-
return /* @__PURE__ */
|
|
401
|
+
function Ae({ className: t, variant: n = "underline", ...r }) {
|
|
402
|
+
let i = j(n);
|
|
403
|
+
return /* @__PURE__ */ y(V.Provider, {
|
|
373
404
|
value: i,
|
|
374
|
-
children: /* @__PURE__ */
|
|
405
|
+
children: /* @__PURE__ */ y(fe, {
|
|
375
406
|
"data-slot": "tabs",
|
|
376
407
|
"data-variant": n,
|
|
377
|
-
className: e(
|
|
408
|
+
className: e(ge[i], t),
|
|
378
409
|
...r
|
|
379
410
|
})
|
|
380
411
|
});
|
|
381
412
|
}
|
|
382
413
|
//#endregion
|
|
383
|
-
export { Q as a, H as c,
|
|
414
|
+
export { Q as a, H as c, R as d, ve as f, j as h, $ as i, z as l, I as m, ke as n, Z as o, N as p, Oe as r, V as s, Ae as t, be as u };
|
|
@@ -14,7 +14,7 @@ import { D as je, E as Me, N as Ne, O as Pe, c as Fe, d as Ie, f as Le, i as Re,
|
|
|
14
14
|
import { a as Ke, i as qe, n as Je } from "./field-blur-context-BLGgf_3z.js";
|
|
15
15
|
import { i as Ye, n as Xe, r as Ze, t as Qe } from "./popover-Cd7DkND4.js";
|
|
16
16
|
import { a as $e, i as et, n as tt, o as nt, t as rt } from "./bubble-input-CQwVSoU3.js";
|
|
17
|
-
import { n as it, r as at, t as ot, u as st } from "./tabs-
|
|
17
|
+
import { n as it, r as at, t as ot, u as st } from "./tabs-BT9pSRwk.js";
|
|
18
18
|
import { a as ct, n as lt, o as ut, s as dt, v as ft, y as pt } from "./toolbar-items-D310xDuM.js";
|
|
19
19
|
import { t as mt } from "./dist-DkQbkF9T.js";
|
|
20
20
|
import { o as ht, s as gt, t as _t } from "./use-click-lock-BZYtTmVt.js";
|
|
@@ -554,7 +554,8 @@ and the `tag` dot still read `--chip-tone`, not the tone channel); `tag`
|
|
|
554
554
|
a smaller tag led by a colour dot; `dashed` a muted "add" pill. 28px tall,
|
|
555
555
|
24px with `size="sm"`, 44px with `size="lg"`. Selected (`active`, or `aria-pressed` on a toggle
|
|
556
556
|
chip) takes a primary tint and a primary edge, and a pressed toggle with
|
|
557
|
-
nothing leading draws a check.
|
|
557
|
+
nothing leading draws a check. An unselected neutral toggle chip keeps a
|
|
558
|
+
boundary of at least 3:1 against the page and the card. The label is truncated as one piece; the ✕
|
|
558
559
|
and `trailing` stay whole.
|
|
559
560
|
|
|
560
561
|
A chip with `onClick` is a button; with `onDismiss` it gains a ✕ button;
|
|
@@ -15,7 +15,7 @@ either can be used alone.
|
|
|
15
15
|
| --- | --- | --- |
|
|
16
16
|
| <img src="../previews/data-table-filter-lists-datatable.webp" width="96" alt=""> | [DataTable](#datatable) | TanStack Table v9 with sorting, selection, expansion and pagination, client-side or one server page at a time |
|
|
17
17
|
| <img src="../previews/data-table-filter-lists-servertable.webp" width="96" alt=""> | [ServerTable](#servertable) | A server-mode `DataTable` driven by the URL, with the Filter in its top band (a title and a description, or neither): sort, cursor paging, the empty page with a scene, an action and removable chips, one count announced |
|
|
18
|
-
| <img src="../previews/data-table-filter-lists-rowmenu.webp" width="96" alt=""> | [RowMenu](#rowmenu) | A row's "..." button named after its row ("Actions for Ada"), its menu aligned to the end with the destructive item last, a loading state while an action runs, `rowMenuColumn` to drop both in a table, and `useRowMenuFocus` to hand the focus back to a row's button after an action |
|
|
18
|
+
| <img src="../previews/data-table-filter-lists-rowmenu.webp" width="96" alt=""> | [RowMenu](#rowmenu) | A row's "..." button named after its row ("Actions for Ada"), its menu aligned to the end with the destructive item last, a loading state while an action runs, `rowMenuColumn` to drop both in a table, and `useRowMenuFocus` (with `rowFocusProps` for a plain row button) to hand the focus back to a row's button after an action |
|
|
19
19
|
| <img src="../previews/data-table-filter-lists-recordactionsmenu.webp" width="96" alt=""> | [RecordActionsMenu](#recordactionsmenu) | A record's archive, restore and delete menu over `RowMenu`: Archive runs at once with an Undo toast that stays until dismissed, Restore runs at once, Delete permanently asks first and keeps a refusal in its dialog; `archivePolicy="confirm"` asks before archiving, `consequence` notes what an action entails, `successAction` adds a toast action, and an `ActionRefusal` (`isActionRefusal`) carries a refusal's details and action |
|
|
20
20
|
| <img src="../previews/data-table-filter-lists-listempty.webp" width="96" alt=""> | [ListEmpty](#listempty) | A list's empty page: nothing yet, with a scene and an action, or nothing matches and the way out |
|
|
21
21
|
| <img src="../previews/data-table-filter-lists-pagefooter.webp" width="96" alt=""> | [PageFooter](#pagefooter) | The page footer of a feed that is not a table (cards, a news feed) under a FilterBar: the range and Previous / Next as links from the URL's cursor trail, `pageControls="icon"`; no `totalCount` for a feed with no total (no range, Previous / Next only); `hideOnSinglePage` hides it on a single page |
|
|
@@ -1312,6 +1312,18 @@ const columns = useMemo(
|
|
|
1312
1312
|
searched. For a dialog, [`onCloseAutoFocus`](#focus-after-a-bulk-action) with
|
|
1313
1313
|
`preventDefault()` is the precise hook if you want to take the focus yourself.
|
|
1314
1314
|
|
|
1315
|
+
A row whose action is a plain button (an edit pen that opens a dialog) has no
|
|
1316
|
+
`RowMenu`. Spread `rowFocusProps(rowId)` on it and `focusRowMenu(rowId)` finds
|
|
1317
|
+
it the same way; it writes the two attributes `RowMenu` writes on its trigger.
|
|
1318
|
+
|
|
1319
|
+
```tsx
|
|
1320
|
+
import { IconButton, rowFocusProps } from '@nxgt/material/components';
|
|
1321
|
+
|
|
1322
|
+
<IconButton aria-label={`Edit ${person.name}`} onClick={open} {...rowFocusProps(person.id)} />;
|
|
1323
|
+
// after the dialog closes
|
|
1324
|
+
focusRowMenu(person.id);
|
|
1325
|
+
```
|
|
1326
|
+
|
|
1315
1327
|
`findRowMenuTrigger(rowId, scope?)` is the lookup the hook uses: it returns the
|
|
1316
1328
|
row's button (an `HTMLElement`) inside `scope` (default `document`), or `null`.
|
|
1317
1329
|
Use it instead of the hook when you only need the element (to scroll it into
|
|
@@ -677,7 +677,8 @@ Without a form library, `QuantityField` takes `value` and `onChange` (or
|
|
|
677
677
|
`defaultValue`). The number is the one `NumberField` has: the language's
|
|
678
678
|
decimal separator, `min`, `max` and `step` (clamped on blur), and steppers
|
|
679
679
|
named after the field ("Increase Dose"). Both parts stay on one line on a
|
|
680
|
-
phone: the
|
|
680
|
+
phone: the unit is sized to its longest label and shrinks first, the
|
|
681
|
+
number keeps 9rem (see Unit width below).
|
|
681
682
|
|
|
682
683
|
| Prop | Type | Default | What it does |
|
|
683
684
|
| --- | --- | --- | --- |
|
|
@@ -698,8 +699,10 @@ phone: the number shrinks, the unit is sized to its longest label (see Unit widt
|
|
|
698
699
|
`allowCustomUnit`, a text input) named "Dose unit". The message describes
|
|
699
700
|
the group, the number and the unit, and both are `aria-invalid` on an error.
|
|
700
701
|
- **Unit width:** the unit part is sized to the longest label of `units`
|
|
701
|
-
(never under 7rem, never over 55% of the row
|
|
702
|
-
|
|
702
|
+
(never under 7rem, never over 55% of the row). It shrinks before the number
|
|
703
|
+
does: the number's cell keeps 9rem (two 44px steppers and a 44px input), so
|
|
704
|
+
the input stays a tap target at 375px, also in a padded side sheet. Beyond
|
|
705
|
+
the cap the label is cut with an ellipsis and the full label
|
|
703
706
|
is the select's `title` (the `units` select only; a free unit typed past
|
|
704
707
|
the cap scrolls in its input). No inline style is used for it.
|
|
705
708
|
- **Translations:** `material.quantity-field.unit` and `.unit-named` (English
|
|
@@ -25,7 +25,7 @@ documentation-site shell. Everything is imported from
|
|
|
25
25
|
| <img src="../previews/navigation-layout-toc.webp" width="96" alt=""> | [Toc](#toc) | On-this-page outline |
|
|
26
26
|
| <img src="../previews/navigation-layout-stepper.webp" width="96" alt=""> | [Stepper](#stepper) | Clickable steps with progress: shaped indicators, optional steps, a phone header |
|
|
27
27
|
| <img src="../previews/navigation-layout-steps.webp" width="96" alt=""> | [Steps](#steps) | Numbered editorial steps |
|
|
28
|
-
| <img src="../previews/navigation-layout-hero.webp" width="96" alt=""> | [Hero](#hero) | Landing band |
|
|
28
|
+
| <img src="../previews/navigation-layout-hero.webp" width="96" alt=""> | [Hero](#hero) | Landing band, or a compact greeting band, with an optional `Background` |
|
|
29
29
|
| <img src="../previews/navigation-layout-doc.webp" width="96" alt=""> | [Doc](#doc) | Documentation site shell |
|
|
30
30
|
| <img src="../previews/navigation-layout-background.webp" width="96" alt=""> | [Background](#background) | Gradient backdrop with colour blobs; the `/backgrounds` one takes its unset props from the nearest theme |
|
|
31
31
|
| | [NavigationRail](#navigationrail) | Placeholder, no props yet |
|
|
@@ -898,6 +898,34 @@ import { Button, Hero } from '@nxgt/material/components';
|
|
|
898
898
|
`eyebrow`, `title`, `description`, `actions` and `children` (below the
|
|
899
899
|
actions) are all content slots.
|
|
900
900
|
|
|
901
|
+
`background` draws a decorative `Background` (the props of the one in
|
|
902
|
+
`@nxgt/material/backgrounds`: `preset`, `intensity`, `tone`, `fill`, `animated`…)
|
|
903
|
+
`aria-hidden` behind the content, clipped by the band's radius.
|
|
904
|
+
It replaces the built-in gradient and glows, loads on demand, and follows
|
|
905
|
+
`Background` in dark mode and under reduced motion.
|
|
906
|
+
Its type, `HeroBackgroundProps`, is exported from `@nxgt/material/components`.
|
|
907
|
+
|
|
908
|
+
`headingLevel` (1 to 6, default 1) sets the title's heading.
|
|
909
|
+
|
|
910
|
+
`aria-label` names the section.
|
|
911
|
+
|
|
912
|
+
`size` is `'default'` (the landing band) or `'compact'`.
|
|
913
|
+
`size="compact"` is a greeting band for a home page: `rounded-xl`, the padding
|
|
914
|
+
of a Card's content, the title in `headline-lg` emphasized, a muted description,
|
|
915
|
+
and the actions at the end from `lg` (wrapping below it).
|
|
916
|
+
Each action is at least 44px tall, for its direct `a` and `button` children; a
|
|
917
|
+
Tooltip or Link wrapping a Button is not covered.
|
|
918
|
+
|
|
919
|
+
```tsx
|
|
920
|
+
<Hero
|
|
921
|
+
size="compact"
|
|
922
|
+
background={{ preset: 'gradient', intensity: 'subtle', fill: 'container' }}
|
|
923
|
+
title={`Hello ${name}`}
|
|
924
|
+
description="2 items in progress"
|
|
925
|
+
actions={<><Button variant="tonal">History</Button><Button>Browse</Button></>}
|
|
926
|
+
/>
|
|
927
|
+
```
|
|
928
|
+
|
|
901
929
|
**Storybook:** `Navigation & layout/Hero` · **Vue:** `Hero`
|
|
902
930
|
|
|
903
931
|
---
|
|
@@ -807,7 +807,9 @@ One choice or several, shown as chips. `type="single"` (the default) is a
|
|
|
807
807
|
radio group of `radio` chips; `type="multiple"` is a `group` of `checkbox`
|
|
808
808
|
chips. A chosen chip has the chip's selected tint and its leading check, so
|
|
809
809
|
colour is never the only cue (an option's `icon` gives way to the check while
|
|
810
|
-
it is chosen).
|
|
810
|
+
it is chosen). An unchosen chip keeps a boundary of at least 3:1 against the
|
|
811
|
+
page and the card, in light and dark, so it reads as a control and not as
|
|
812
|
+
plain text.
|
|
811
813
|
|
|
812
814
|
The `ref` reaches the chip that holds the tab stop (the first chosen enabled
|
|
813
815
|
chip, else the first), so a form library's `setFocus` works.
|
package/docs/guides/app-shell.md
CHANGED
|
@@ -376,8 +376,10 @@ export const invoiceRoute: RouteObject = {
|
|
|
376
376
|
context the page fills while it renders cannot do this: the bar is written
|
|
377
377
|
before the page is reached.)
|
|
378
378
|
- **It is the page's `h1`**, in `--font-display` (the body face when you
|
|
379
|
-
define none)
|
|
380
|
-
|
|
379
|
+
define none). On a phone a long title wraps to a second line first, so a
|
|
380
|
+
record's number stays readable by touch (#2324); from `md` up, and on a
|
|
381
|
+
phone once two lines are not enough, it is cut with an ellipsis. When it is
|
|
382
|
+
cut off, its full text is the `title` tooltip, as for `headerTitle` (#629), and its accessible
|
|
381
383
|
name stays the text itself. It sits after `headerTitle`, which gives it room.
|
|
382
384
|
- **Typing it.** `AppShellHandle<Data>` (`{ breadcrumb?, title?, titleAfter? }`) and
|
|
383
385
|
`PageTitle<Data>` are exported for a route's `handle`; `Data` types the
|
|
@@ -455,7 +457,7 @@ export const handle = {
|
|
|
455
457
|
(`[data-slot=app-header-title-after]`), vertically centred with the title, so
|
|
456
458
|
the heading's accessible name stays the plain title.
|
|
457
459
|
- **On a phone it stays on screen** and shares the row with the title: the
|
|
458
|
-
title
|
|
460
|
+
title gives way first (two lines, then an ellipsis), the slot never shrinks.
|
|
459
461
|
- **Nothing changes without it**: the markup of a bar with no slot is the same
|
|
460
462
|
as before, and the slot is read from the matches like the title, so it is in
|
|
461
463
|
the server HTML and does not flash on a route change.
|
|
@@ -484,7 +486,7 @@ A multi-tenant app keeps the current tenant visible on a desktop screen with
|
|
|
484
486
|
adds nothing to the bar, and setting both never shows the name twice on one
|
|
485
487
|
screen.
|
|
486
488
|
- **The title truncates first**: with a long title, the slot and the line
|
|
487
|
-
together, the title gives way; the slot stays whole and the line keeps its cap.
|
|
489
|
+
together, the title gives way (two lines on a phone, then an ellipsis); the slot stays whole and the line keeps its cap.
|
|
488
490
|
- **It needs a page title**: while the bar shows none (no `handle.title`),
|
|
489
491
|
`headerTitle` is the context line and `headerContext` is ignored.
|
|
490
492
|
|