@silverpoint/core 0.6.0 → 0.8.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/README.md +14 -0
- package/dist/catalog.d.ts +2 -2
- package/dist/catalog.js +4 -2
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-OLYKR5PS.js → chunk-46QELMCG.js} +8 -213
- package/dist/chunk-46QELMCG.js.map +1 -0
- package/dist/chunk-5MP3BLZK.js +48 -0
- package/dist/chunk-5MP3BLZK.js.map +1 -0
- package/dist/chunk-6YFO7OP3.js +84 -0
- package/dist/chunk-6YFO7OP3.js.map +1 -0
- package/dist/chunk-ANJSW5JX.js +93 -0
- package/dist/chunk-ANJSW5JX.js.map +1 -0
- package/dist/{chunk-PD4MD7JU.js → chunk-E5CC2NNQ.js} +5 -3
- package/dist/chunk-E5CC2NNQ.js.map +1 -0
- package/dist/chunk-G7N4X5XD.js +12 -0
- package/dist/chunk-G7N4X5XD.js.map +1 -0
- package/dist/chunk-NI7B6UEO.js +24 -0
- package/dist/chunk-NI7B6UEO.js.map +1 -0
- package/dist/chunk-WYFRHI4S.js +179 -0
- package/dist/chunk-WYFRHI4S.js.map +1 -0
- package/dist/contrast-siWF_R5o.d.ts +30 -0
- package/dist/dashboard-demos.d.ts +2 -2
- package/dist/index.d.ts +13 -10
- package/dist/index.js +20 -9
- package/dist/index.js.map +1 -1
- package/dist/{model-CLhtoG75.d.ts → model-DVVt59AB.d.ts} +1 -1
- package/dist/palettes.d.ts +29 -0
- package/dist/palettes.js +79 -0
- package/dist/palettes.js.map +1 -0
- package/dist/{props-Dq8FC8GG.d.ts → props-BZ9CcrGv.d.ts} +53 -1
- package/dist/timeline.d.ts +90 -0
- package/dist/timeline.js +125 -0
- package/dist/timeline.js.map +1 -0
- package/dist/{types-B81k-s9_.d.ts → types-BT3Xm7fP.d.ts} +3 -1
- package/dist/types-D5ys35fF.d.ts +576 -0
- package/dist/types-DHBJ0PzV.d.ts +57 -0
- package/dist/ui-demos.d.ts +14 -3
- package/dist/ui-demos.js +163 -1
- package/dist/ui-demos.js.map +1 -1
- package/dist/ui.d.ts +346 -325
- package/dist/ui.js +932 -118
- package/dist/ui.js.map +1 -1
- package/dist/view-DteS9glE.d.ts +82 -0
- package/package.json +13 -1
- package/dist/chunk-OLYKR5PS.js.map +0 -1
- package/dist/chunk-PD4MD7JU.js.map +0 -1
package/dist/ui.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { DEFAULTS } from './chunk-KFBSQH5G.js';
|
|
2
|
-
|
|
2
|
+
export { uiSortRows } from './chunk-NI7B6UEO.js';
|
|
3
|
+
import { arcPath, circlePath, resolveSeed } from './chunk-46QELMCG.js';
|
|
4
|
+
import { paletteStyle, resolvePalette } from './chunk-ANJSW5JX.js';
|
|
5
|
+
import { round2, roundPathData } from './chunk-5MP3BLZK.js';
|
|
6
|
+
import { uiRequireName } from './chunk-G7N4X5XD.js';
|
|
7
|
+
export { uiRequireName } from './chunk-G7N4X5XD.js';
|
|
8
|
+
import { safeHref, el, root, frame, tone, glyph, slot, baseOf, text, headingTag, nativeInput, sr, UI_GLYPHS, cssLength, iconClose } from './chunk-6YFO7OP3.js';
|
|
9
|
+
export { UI_GLYPHS } from './chunk-6YFO7OP3.js';
|
|
10
|
+
import { diagnose } from './chunk-WYFRHI4S.js';
|
|
3
11
|
|
|
4
12
|
// src/ui/catalog.ts
|
|
5
13
|
var BATCH = {
|
|
@@ -15,14 +23,17 @@ var BATCH = {
|
|
|
15
23
|
Slider: "B2",
|
|
16
24
|
Rate: "B2"
|
|
17
25
|
};
|
|
18
|
-
var row = (name, group, states) => Object.freeze({
|
|
26
|
+
var row = (name, group, states, family2 = "ui", batch = BATCH[name] ?? "B3") => Object.freeze({
|
|
19
27
|
name,
|
|
20
|
-
batch
|
|
28
|
+
batch,
|
|
21
29
|
slug: name.replace(/[A-Z]/g, (m, i) => (i ? "-" : "") + m.toLowerCase()),
|
|
22
30
|
component: `Sp${name}`,
|
|
23
31
|
group,
|
|
32
|
+
family: family2,
|
|
24
33
|
states: Object.freeze([...states])
|
|
25
34
|
});
|
|
35
|
+
var composed = (name, group, batch, states) => row(name, group, states, "composed", batch);
|
|
36
|
+
var overlay = (name, states) => row(name, "overlays", states, "overlay", "B");
|
|
26
37
|
var UI_COMPONENTS = /* @__PURE__ */ Object.freeze([
|
|
27
38
|
row("Button", "actions", ["default", "primary", "danger", "disabled"]),
|
|
28
39
|
row("Input", "data-entry", ["empty", "filled", "invalid", "disabled"]),
|
|
@@ -40,13 +51,34 @@ var UI_COMPONENTS = /* @__PURE__ */ Object.freeze([
|
|
|
40
51
|
row("Divider", "data-display", ["plain", "text"]),
|
|
41
52
|
row("Progress", "feedback", ["line", "circle", "indeterminate"]),
|
|
42
53
|
row("Alert", "feedback", ["info", "success", "warning", "error"]),
|
|
43
|
-
row("Skeleton", "feedback", ["paragraph", "avatar"])
|
|
54
|
+
row("Skeleton", "feedback", ["paragraph", "avatar"]),
|
|
55
|
+
composed("Surface", "building-blocks", "A1", ["frame-card", "tone-2"]),
|
|
56
|
+
composed("Glyph", "building-blocks", "A1", ["all"]),
|
|
57
|
+
composed("Table", "data-display", "A1", ["plain", "sorted-striped", "empty"]),
|
|
58
|
+
composed("Pagination", "navigation", "A2", ["middle", "total"]),
|
|
59
|
+
composed("Breadcrumb", "navigation", "A1", ["three"]),
|
|
60
|
+
composed("Avatar", "data-display", "A1", ["initials", "square", "group"]),
|
|
61
|
+
composed("Statistic", "data-display", "A1", ["plain", "trend-down"]),
|
|
62
|
+
composed("Descriptions", "data-display", "A1", ["bordered", "plain"]),
|
|
63
|
+
composed("TimelineList", "data-display", "A1", ["mixed"]),
|
|
64
|
+
composed("Collapse", "disclosure", "A2", ["one-open", "accordion-disabled"]),
|
|
65
|
+
composed("Empty", "data-display", "A1", ["plain"]),
|
|
66
|
+
composed("Result", "data-display", "A1", ["success", "error"]),
|
|
67
|
+
composed("Textarea", "data-entry", "A2", ["count", "invalid"]),
|
|
68
|
+
composed("InputNumber", "data-entry", "A2", ["value", "at-min"]),
|
|
69
|
+
overlay("Modal", ["open"]),
|
|
70
|
+
overlay("Drawer", ["end-open"]),
|
|
71
|
+
overlay("Popover", ["open"]),
|
|
72
|
+
overlay("Tooltip", ["open"]),
|
|
73
|
+
overlay("Select", ["placeholder", "open-selected"]),
|
|
74
|
+
overlay("DropdownMenu", ["open"]),
|
|
75
|
+
overlay("Toast", ["info", "error-action"])
|
|
44
76
|
]);
|
|
45
77
|
|
|
46
78
|
// src/ui/value.ts
|
|
47
79
|
var DEFAULT_RANGE = { min: 0, max: 100, step: 1 };
|
|
48
|
-
function warn(component, property,
|
|
49
|
-
if (process.env.NODE_ENV !== "production") diagnose("SP017", component, { property, message });
|
|
80
|
+
function warn(component, property, message2) {
|
|
81
|
+
if (process.env.NODE_ENV !== "production") diagnose("SP017", component, { property, message: message2 });
|
|
50
82
|
}
|
|
51
83
|
var tidy = (x) => Number.parseFloat(x.toPrecision(12));
|
|
52
84
|
function uiRange(range, component = "UiValue") {
|
|
@@ -57,14 +89,14 @@ function uiRange(range, component = "UiValue") {
|
|
|
57
89
|
return DEFAULT_RANGE;
|
|
58
90
|
}
|
|
59
91
|
function uiValue(value, range, component = "UiValue") {
|
|
60
|
-
const
|
|
61
|
-
const { min, max, step } =
|
|
92
|
+
const valid2 = uiRange(range, component);
|
|
93
|
+
const { min, max, step } = valid2;
|
|
62
94
|
let next = Number.isFinite(value) ? Math.min(Math.max(value, min), max) : min;
|
|
63
95
|
if (step !== void 0) {
|
|
64
96
|
const steps = Math.min(Math.round((next - min) / step), Math.floor(tidy((max - min) / step)));
|
|
65
97
|
next = tidy(min + steps * step);
|
|
66
98
|
}
|
|
67
|
-
const corrected =
|
|
99
|
+
const corrected = valid2 !== range || next !== value;
|
|
68
100
|
if (next !== value) warn(component, "value", `${value} is drawn as ${next}.`);
|
|
69
101
|
return { value: next, fraction: round2((next - min) / (max - min)), corrected };
|
|
70
102
|
}
|
|
@@ -112,13 +144,13 @@ function uiSelectedKey(items, value, fallback) {
|
|
|
112
144
|
function uiSteps(items, current, component = "SpSteps") {
|
|
113
145
|
const steps = uiItems(items, component);
|
|
114
146
|
if (steps.length === 0) return [];
|
|
115
|
-
const
|
|
116
|
-
const at = Number.isFinite(current) ? Math.min(Math.max(Math.round(current), 0),
|
|
147
|
+
const last2 = steps.length - 1;
|
|
148
|
+
const at = Number.isFinite(current) ? Math.min(Math.max(Math.round(current), 0), last2) : 0;
|
|
117
149
|
if (at !== current && process.env.NODE_ENV !== "production") {
|
|
118
150
|
diagnose("SP017", component, { property: "current", message: `${current} is drawn as ${at}.` });
|
|
119
151
|
}
|
|
120
152
|
const statuses = steps.map((item, i) => item.status ?? (i < at ? "finish" : i === at ? "process" : "wait"));
|
|
121
|
-
return steps.map((item, i) => ({ key: item.key, status: statuses[i], connector: i <
|
|
153
|
+
return steps.map((item, i) => ({ key: item.key, status: statuses[i], connector: i < last2 ? statuses[i + 1] : null, current: i === at }));
|
|
122
154
|
}
|
|
123
155
|
|
|
124
156
|
// src/ui/keyboard.ts
|
|
@@ -127,12 +159,12 @@ function direction(key, orientation, dir) {
|
|
|
127
159
|
const forward = key === "ArrowRight" ? 1 : key === "ArrowLeft" ? -1 : 0;
|
|
128
160
|
return dir === "rtl" ? -forward : forward;
|
|
129
161
|
}
|
|
130
|
-
function uiRovingKey(
|
|
131
|
-
const { index, count, disabled } =
|
|
132
|
-
const
|
|
162
|
+
function uiRovingKey(state2, key, orientation, dir) {
|
|
163
|
+
const { index, count, disabled } = state2;
|
|
164
|
+
const enabled2 = (i2) => disabled[i2] !== true;
|
|
133
165
|
if (key === "Home" || key === "End") {
|
|
134
166
|
const step2 = key === "Home" ? 1 : -1;
|
|
135
|
-
for (let n = 0, i2 = key === "Home" ? 0 : count - 1; n < count; n++, i2 += step2) if (
|
|
167
|
+
for (let n = 0, i2 = key === "Home" ? 0 : count - 1; n < count; n++, i2 += step2) if (enabled2(i2)) return i2;
|
|
136
168
|
return index;
|
|
137
169
|
}
|
|
138
170
|
const step = direction(key, orientation, dir);
|
|
@@ -140,7 +172,7 @@ function uiRovingKey(state, key, orientation, dir) {
|
|
|
140
172
|
let i = index < 0 || index >= count ? step > 0 ? -1 : count : index;
|
|
141
173
|
for (let n = 0; n < count; n++) {
|
|
142
174
|
i = ((i + step) % count + count) % count;
|
|
143
|
-
if (
|
|
175
|
+
if (enabled2(i)) return i;
|
|
144
176
|
}
|
|
145
177
|
return index;
|
|
146
178
|
}
|
|
@@ -198,13 +230,6 @@ function uiFrameOutline(kind) {
|
|
|
198
230
|
};
|
|
199
231
|
}
|
|
200
232
|
|
|
201
|
-
// src/ui/names.ts
|
|
202
|
-
function uiRequireName(component, text2, label) {
|
|
203
|
-
if (process.env.NODE_ENV === "production") return;
|
|
204
|
-
if (text2?.trim() || label?.trim()) return;
|
|
205
|
-
diagnose("SP018", component, { property: "label" });
|
|
206
|
-
}
|
|
207
|
-
|
|
208
233
|
// src/ui/tokens.ts
|
|
209
234
|
var UI_TOKEN_DEFAULTS = /* @__PURE__ */ Object.freeze({
|
|
210
235
|
frame: "css",
|
|
@@ -212,11 +237,14 @@ var UI_TOKEN_DEFAULTS = /* @__PURE__ */ Object.freeze({
|
|
|
212
237
|
controlHeight: Object.freeze({ sm: 24, md: 32, lg: 40 }),
|
|
213
238
|
radius: 2,
|
|
214
239
|
focusWidth: 2,
|
|
215
|
-
tone: Object.freeze({ selected: 3, primary: 2, danger: 4, disabled: 1, alertError: 1 })
|
|
240
|
+
tone: Object.freeze({ selected: 3, primary: 2, danger: 4, disabled: 1, alertError: 1 }),
|
|
241
|
+
backdrop: 2,
|
|
242
|
+
rowTone: 1
|
|
216
243
|
});
|
|
217
244
|
var MIN_HEIGHT = 24;
|
|
218
245
|
var MIN_FOCUS = 2;
|
|
219
246
|
var within = (value, lo, hi, fallback) => Number.isFinite(value) ? Math.min(Math.max(value, lo), hi) : fallback;
|
|
247
|
+
var level = (value, fallback) => value === void 0 ? fallback : Math.round(within(value, 1, 4, fallback));
|
|
220
248
|
function resolveUiTokens(ground) {
|
|
221
249
|
const ui = ground.ui ?? UI_TOKEN_DEFAULTS;
|
|
222
250
|
const inked = ui.frame === "inked" && ground.tonalMechanism === "hatch";
|
|
@@ -231,7 +259,9 @@ function resolveUiTokens(ground) {
|
|
|
231
259
|
},
|
|
232
260
|
radius: within(ui.radius, 0, Infinity, 2),
|
|
233
261
|
focusWidth: within(ui.focusWidth, MIN_FOCUS, Infinity, 2),
|
|
234
|
-
tone: ui.tone
|
|
262
|
+
tone: ui.tone,
|
|
263
|
+
backdrop: level(ui.backdrop, 2),
|
|
264
|
+
rowTone: level(ui.rowTone, 1)
|
|
235
265
|
};
|
|
236
266
|
}
|
|
237
267
|
|
|
@@ -247,10 +277,10 @@ function family(gap, angle) {
|
|
|
247
277
|
const height = Math.abs(cos) < EPSILON ? lines * gap : lines * gap / Math.abs(cos);
|
|
248
278
|
const offset = (x, y) => -sin * x + cos * y;
|
|
249
279
|
const corners = [offset(0, 0), offset(width, 0), offset(0, height), offset(width, height)];
|
|
250
|
-
const
|
|
251
|
-
const
|
|
280
|
+
const first2 = Math.ceil(Math.min(...corners) / gap - 0.5);
|
|
281
|
+
const last2 = Math.floor(Math.max(...corners) / gap - 0.5);
|
|
252
282
|
const strokes = [];
|
|
253
|
-
for (let k =
|
|
283
|
+
for (let k = first2; k <= last2; k++) {
|
|
254
284
|
const c = (k + 0.5) * gap;
|
|
255
285
|
const at = (t) => ({ x: -sin * c + cos * t, y: cos * c + sin * t, t });
|
|
256
286
|
const hits = [
|
|
@@ -260,11 +290,11 @@ function family(gap, angle) {
|
|
|
260
290
|
const from = hits[0];
|
|
261
291
|
const to = hits.at(-1);
|
|
262
292
|
if (!from || !to || to.t - from.t < EPSILON * 1e3) continue;
|
|
263
|
-
const
|
|
293
|
+
const clamp2 = (v, hi) => round2(Math.min(Math.max(v, 0), hi));
|
|
264
294
|
const w = round2(width);
|
|
265
295
|
const h = round2(height);
|
|
266
296
|
strokes.push({
|
|
267
|
-
d: `M${
|
|
297
|
+
d: `M${clamp2(from.x, w)},${clamp2(from.y, h)}L${clamp2(to.x, w)},${clamp2(to.y, h)}`,
|
|
268
298
|
role: "ornament",
|
|
269
299
|
part: "ink"
|
|
270
300
|
});
|
|
@@ -278,75 +308,264 @@ function uiToneTile(spec) {
|
|
|
278
308
|
return layers;
|
|
279
309
|
}
|
|
280
310
|
|
|
281
|
-
// src/ui/
|
|
282
|
-
function
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
function
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
"
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
"
|
|
303
|
-
|
|
311
|
+
// src/ui/pages.ts
|
|
312
|
+
function warn2(component, property, message2) {
|
|
313
|
+
if (process.env.NODE_ENV !== "production") diagnose("SP017", component, { property, message: message2 });
|
|
314
|
+
}
|
|
315
|
+
function uiPageWindow(count, current, siblings) {
|
|
316
|
+
const first2 = Math.max(2, current - siblings);
|
|
317
|
+
const last2 = Math.min(count - 1, current + siblings);
|
|
318
|
+
const pages = [1];
|
|
319
|
+
if (first2 > 2) pages.push("start-gap");
|
|
320
|
+
for (let page2 = first2; page2 <= last2; page2++) pages.push(page2);
|
|
321
|
+
if (last2 < count - 1) pages.push("end-gap");
|
|
322
|
+
if (count > 1) pages.push(count);
|
|
323
|
+
return pages;
|
|
324
|
+
}
|
|
325
|
+
function uiPagination(total, pageSize, current, component = "SpPagination") {
|
|
326
|
+
let corrected = false;
|
|
327
|
+
if (!(Number.isInteger(total) && total >= 0)) {
|
|
328
|
+
warn2(component, "total", `${total} is drawn as 0.`);
|
|
329
|
+
[total, corrected] = [0, true];
|
|
330
|
+
}
|
|
331
|
+
if (!(Number.isInteger(pageSize) && pageSize >= 1)) {
|
|
332
|
+
warn2(component, "pageSize", `${pageSize} is drawn as 10.`);
|
|
333
|
+
[pageSize, corrected] = [10, true];
|
|
334
|
+
}
|
|
335
|
+
const count = Math.max(1, Math.ceil(total / pageSize));
|
|
336
|
+
const page2 = Number.isFinite(current) ? Math.min(Math.max(Math.round(current), 1), count) : 1;
|
|
337
|
+
if (page2 !== current) {
|
|
338
|
+
warn2(component, "current", `${current} is drawn as ${page2}.`);
|
|
339
|
+
corrected = true;
|
|
340
|
+
}
|
|
341
|
+
return { count, current: page2, start: total ? (page2 - 1) * pageSize + 1 : 0, end: Math.min(total, page2 * pageSize), corrected };
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// src/ui/number.ts
|
|
345
|
+
function warn3(component, property, message2) {
|
|
346
|
+
if (process.env.NODE_ENV !== "production") diagnose("SP017", component, { property, message: message2 });
|
|
347
|
+
}
|
|
348
|
+
var tidy2 = (x) => Number.parseFloat(x.toPrecision(12));
|
|
349
|
+
function valid(range, component) {
|
|
350
|
+
const drop = (property, value, as) => {
|
|
351
|
+
warn3(component, property, `${value} is ${as}.`);
|
|
352
|
+
return void 0;
|
|
304
353
|
};
|
|
354
|
+
let min = range.min !== void 0 && !Number.isFinite(range.min) ? drop("min", range.min, "ignored") : range.min;
|
|
355
|
+
let max = range.max !== void 0 && !Number.isFinite(range.max) ? drop("max", range.max, "ignored") : range.max;
|
|
356
|
+
if (min !== void 0 && max !== void 0 && min > max) min = max = drop("min", `The bounds ${min}..${max}`, "ignored");
|
|
357
|
+
const { step: s, precision: p } = range;
|
|
358
|
+
const step = s !== void 0 && !(Number.isFinite(s) && s > 0) ? drop("step", s, "drawn as 1") ?? 1 : s;
|
|
359
|
+
const precision = p !== void 0 && !(Number.isInteger(p) && p >= 0 && p <= 15) ? drop("precision", p, "ignored") : p;
|
|
360
|
+
return { min, max, step, precision };
|
|
305
361
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
return
|
|
362
|
+
function clamp(value, { min, max, precision }) {
|
|
363
|
+
let next = value;
|
|
364
|
+
if (min !== void 0) next = Math.max(min, next);
|
|
365
|
+
if (max !== void 0) next = Math.min(max, next);
|
|
366
|
+
if (precision !== void 0) next = Math.round(tidy2(next * 10 ** precision)) / 10 ** precision;
|
|
367
|
+
return tidy2(next);
|
|
368
|
+
}
|
|
369
|
+
function uiNumberValue(value, range, component = "SpInputNumber") {
|
|
370
|
+
const r = valid(range, component);
|
|
371
|
+
if (value === null) return { value: null, corrected: false, atMin: false, atMax: false, range: r };
|
|
372
|
+
const next = Number.isFinite(value) ? clamp(value, r) : clamp(r.min ?? 0, r);
|
|
373
|
+
if (next !== value) warn3(component, "value", `${value} is drawn as ${next}.`);
|
|
374
|
+
return { value: next, corrected: next !== value, atMin: r.min !== void 0 && next <= r.min, atMax: r.max !== void 0 && next >= r.max, range: r };
|
|
375
|
+
}
|
|
376
|
+
function uiNumberStep(value, direction2, range, component = "SpInputNumber") {
|
|
377
|
+
const r = valid(range, component);
|
|
378
|
+
const base = value !== null && Number.isFinite(value) ? value : r.min ?? 0;
|
|
379
|
+
return clamp(base + direction2 * (r.step ?? 1), r);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// src/ui/initials.ts
|
|
383
|
+
function uiInitials(name) {
|
|
384
|
+
const words = (name ?? "").replace(/-/g, " ").split(/\s+/).filter(Boolean);
|
|
385
|
+
return words.slice(0, 2).map((word) => [...word][0].toUpperCase()).join("") || "?";
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/ui/listbox.ts
|
|
389
|
+
function seek(state2, from, step) {
|
|
390
|
+
for (let i = from; i >= 0 && i < state2.count; i += step) if (state2.disabled[i] !== true) return i;
|
|
391
|
+
return -1;
|
|
392
|
+
}
|
|
393
|
+
var first = (s) => seek(s, 0, 1);
|
|
394
|
+
var last = (s) => seek(s, s.count - 1, -1);
|
|
395
|
+
var enabled = (s, i) => i >= 0 && i < s.count && s.disabled[i] !== true;
|
|
396
|
+
function arrow(state2, step, wrap) {
|
|
397
|
+
const { active, count } = state2;
|
|
398
|
+
if (active < 0 || active >= count) return step > 0 ? first(state2) : last(state2);
|
|
399
|
+
const next = seek(state2, active + step, step);
|
|
400
|
+
if (next >= 0) return next;
|
|
401
|
+
return wrap ? step > 0 ? first(state2) : last(state2) : active;
|
|
402
|
+
}
|
|
403
|
+
function page(state2, step) {
|
|
404
|
+
const target = Math.min(Math.max((state2.active < 0 ? 0 : state2.active) + 10 * step, 0), state2.count - 1);
|
|
405
|
+
const found = seek(state2, target, step);
|
|
406
|
+
return found >= 0 ? found : seek(state2, target, step > 0 ? -1 : 1);
|
|
407
|
+
}
|
|
408
|
+
function uiListKey(state2, key, kind) {
|
|
409
|
+
const { active } = state2;
|
|
410
|
+
const keep = (i) => i < 0 ? active : i;
|
|
411
|
+
if (!state2.open) {
|
|
412
|
+
if (key === "Home") return { active: keep(first(state2)), intent: "open" };
|
|
413
|
+
if (key === "End") return { active: keep(last(state2)), intent: "open" };
|
|
414
|
+
if (kind === "menu" && key === "ArrowUp") return { active: keep(last(state2)), intent: "open" };
|
|
415
|
+
if (["ArrowDown", "ArrowUp", "Enter", " "].includes(key)) {
|
|
416
|
+
const start = kind === "listbox" && enabled(state2, active) ? active : first(state2);
|
|
417
|
+
return { active: keep(start), intent: "open" };
|
|
418
|
+
}
|
|
419
|
+
return { active };
|
|
420
|
+
}
|
|
421
|
+
switch (key) {
|
|
422
|
+
case "ArrowDown":
|
|
423
|
+
return { active: keep(arrow(state2, 1, kind === "menu")) };
|
|
424
|
+
case "ArrowUp":
|
|
425
|
+
return { active: keep(arrow(state2, -1, kind === "menu")) };
|
|
426
|
+
case "Home":
|
|
427
|
+
return { active: keep(first(state2)) };
|
|
428
|
+
case "End":
|
|
429
|
+
return { active: keep(last(state2)) };
|
|
430
|
+
case "PageDown":
|
|
431
|
+
case "PageUp":
|
|
432
|
+
return kind === "listbox" ? { active: keep(page(state2, key === "PageDown" ? 1 : -1)) } : { active };
|
|
433
|
+
case "Enter":
|
|
434
|
+
case " ":
|
|
435
|
+
return { active, intent: enabled(state2, active) ? "select" : "close" };
|
|
436
|
+
case "Tab":
|
|
437
|
+
return { active, intent: kind === "listbox" && enabled(state2, active) ? "select" : "close" };
|
|
438
|
+
case "Escape":
|
|
439
|
+
return { active, intent: "close" };
|
|
440
|
+
default:
|
|
441
|
+
return { active };
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
function uiTypeahead(labels, disabled, buffer, from) {
|
|
445
|
+
const typed = buffer.toLowerCase();
|
|
446
|
+
if (!typed) return -1;
|
|
447
|
+
const single = [...typed].every((c) => c === typed[0]);
|
|
448
|
+
const prefix = single ? typed[0] : typed;
|
|
449
|
+
const count = labels.length;
|
|
450
|
+
const start = single ? from + 1 : Math.max(from, 0);
|
|
451
|
+
for (let n = 0; n < count; n++) {
|
|
452
|
+
const i = ((start + n) % count + count) % count;
|
|
453
|
+
if (disabled[i] !== true && labels[i].trim().toLowerCase().startsWith(prefix)) return i;
|
|
454
|
+
}
|
|
455
|
+
return -1;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/ui/place.ts
|
|
459
|
+
var OPPOSITE = { top: "bottom", bottom: "top", start: "end", end: "start" };
|
|
460
|
+
var shift = (at, extent, size, padding) => Math.max(padding, Math.min(at, size - padding - extent));
|
|
461
|
+
function uiPlace(input) {
|
|
462
|
+
const { anchor: a, floating: f, viewport: v, align, offset, padding, dir } = input;
|
|
463
|
+
const vertical = (side2) => side2 === "top" || side2 === "bottom";
|
|
464
|
+
const isLeft = (side2) => side2 === "start" === (dir === "ltr");
|
|
465
|
+
const main = (side2) => {
|
|
466
|
+
if (side2 === "bottom") return a.y + a.height + offset;
|
|
467
|
+
if (side2 === "top") return a.y - offset - f.height;
|
|
468
|
+
return isLeft(side2) ? a.x - offset - f.width : a.x + a.width + offset;
|
|
469
|
+
};
|
|
470
|
+
const fits = (side2) => {
|
|
471
|
+
const at = main(side2);
|
|
472
|
+
const [extent, size] = vertical(side2) ? [f.height, v.height] : [f.width, v.width];
|
|
473
|
+
return at >= padding && at + extent <= size - padding;
|
|
474
|
+
};
|
|
475
|
+
const side = !fits(input.side) && fits(OPPOSITE[input.side]) ? OPPOSITE[input.side] : input.side;
|
|
476
|
+
if (vertical(side)) {
|
|
477
|
+
const fromLeft = align === "center" ? null : align === "start" === (dir === "ltr");
|
|
478
|
+
const x = fromLeft === null ? a.x + (a.width - f.width) / 2 : fromLeft ? a.x : a.x + a.width - f.width;
|
|
479
|
+
return { x: round2(shift(x, f.width, v.width, padding)), y: round2(main(side)), side, align };
|
|
480
|
+
}
|
|
481
|
+
const y = align === "center" ? a.y + (a.height - f.height) / 2 : align === "start" ? a.y : a.y + a.height - f.height;
|
|
482
|
+
return { x: round2(main(side)), y: round2(shift(y, f.height, v.height, padding)), side, align };
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// src/ui/anchor.ts
|
|
486
|
+
function uiAnchor(anchor, floating, options) {
|
|
487
|
+
const view = floating.ownerDocument?.defaultView;
|
|
488
|
+
if (!view) return () => {
|
|
489
|
+
};
|
|
490
|
+
const place = () => {
|
|
491
|
+
const { width, height } = floating.getBoundingClientRect();
|
|
492
|
+
const at = uiPlace({
|
|
493
|
+
anchor: anchor.getBoundingClientRect(),
|
|
494
|
+
floating: { width, height },
|
|
495
|
+
viewport: { width: view.innerWidth, height: view.innerHeight },
|
|
496
|
+
side: options.side,
|
|
497
|
+
align: options.align,
|
|
498
|
+
offset: options.offset ?? 6,
|
|
499
|
+
padding: options.padding ?? 8,
|
|
500
|
+
dir: anchor.closest("[dir]")?.getAttribute("dir") === "rtl" ? "rtl" : "ltr"
|
|
501
|
+
});
|
|
502
|
+
floating.style.setProperty("--sp-ui-x", `${at.x}px`);
|
|
503
|
+
floating.style.setProperty("--sp-ui-y", `${at.y}px`);
|
|
504
|
+
floating.setAttribute("data-side", at.side);
|
|
505
|
+
};
|
|
506
|
+
place();
|
|
507
|
+
view.addEventListener("scroll", place, { capture: true, passive: true });
|
|
508
|
+
view.addEventListener("resize", place);
|
|
509
|
+
const sized = view.ResizeObserver ? new view.ResizeObserver(place) : void 0;
|
|
510
|
+
sized?.observe(anchor);
|
|
511
|
+
sized?.observe(floating);
|
|
512
|
+
return () => {
|
|
513
|
+
view.removeEventListener("scroll", place, { capture: true });
|
|
514
|
+
view.removeEventListener("resize", place);
|
|
515
|
+
sized?.disconnect();
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// src/ui/overlay.ts
|
|
520
|
+
function showing(element) {
|
|
521
|
+
try {
|
|
522
|
+
return element.matches(":popover-open");
|
|
523
|
+
} catch {
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
function uiOverlaySync(element, kind, open) {
|
|
528
|
+
if (kind === "popover") {
|
|
529
|
+
if (typeof element.showPopover !== "function") return;
|
|
530
|
+
if (open !== showing(element)) {
|
|
531
|
+
if (open) element.showPopover();
|
|
532
|
+
else element.hidePopover?.();
|
|
533
|
+
}
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (open && !element.open) {
|
|
537
|
+
if (kind === "modal") element.showModal?.();
|
|
538
|
+
else element.show?.();
|
|
539
|
+
} else if (!open && element.open) element.close?.();
|
|
324
540
|
}
|
|
325
541
|
|
|
326
542
|
// src/ui/view.ts
|
|
327
543
|
var FRAME_SLOTS = 6;
|
|
328
544
|
function resolveUi(props, env) {
|
|
329
|
-
const { provider = {}, cell = {} } = env;
|
|
330
|
-
const ground = props.ground ??
|
|
545
|
+
const { provider = {}, cell: cell2 = {} } = env;
|
|
546
|
+
const ground = props.ground ?? cell2.ground ?? provider.ground ?? DEFAULTS.ground;
|
|
331
547
|
return {
|
|
332
548
|
ground: typeof ground === "string" ? ground : ground.name,
|
|
333
|
-
substrate: props.substrate ??
|
|
334
|
-
mode: env.forcedPrecision ? "precision" : props.mode ??
|
|
549
|
+
substrate: props.substrate ?? cell2.substrate ?? provider.substrate ?? DEFAULTS.substrate,
|
|
550
|
+
mode: env.forcedPrecision ? "precision" : props.mode ?? cell2.mode ?? provider.mode ?? DEFAULTS.mode,
|
|
335
551
|
size: props.size ?? "md",
|
|
336
|
-
frame: uiFrameVariant(props.seed, props.id, FRAME_SLOTS)
|
|
552
|
+
frame: uiFrameVariant(props.seed, props.id, FRAME_SLOTS),
|
|
553
|
+
// Colours are not mode: a forced precision leaves them as resolved (REQ-468).
|
|
554
|
+
palette: paletteStyle(resolvePalette(provider.palette, cell2.palette, props.palette))
|
|
337
555
|
};
|
|
338
556
|
}
|
|
339
557
|
function uiButtonView(props, r, content) {
|
|
340
558
|
uiRequireName("SpButton", content.text, props.label);
|
|
341
559
|
const variant = props.variant ?? "default";
|
|
342
|
-
const
|
|
560
|
+
const href = safeHref(props.href, "SpButton");
|
|
561
|
+
const link = href !== void 0;
|
|
343
562
|
const toned = props.disabled ? "disabled" : variant === "default" ? void 0 : variant;
|
|
344
563
|
return el(
|
|
345
564
|
link ? "a" : "button",
|
|
346
565
|
root("button", props, r, {
|
|
347
566
|
id: props.id,
|
|
348
567
|
type: link ? void 0 : props.type ?? "button",
|
|
349
|
-
href: link && !props.disabled ?
|
|
568
|
+
href: link && !props.disabled ? href : void 0,
|
|
350
569
|
disabled: !link && props.disabled === true,
|
|
351
570
|
"aria-disabled": link && props.disabled ? "true" : void 0,
|
|
352
571
|
"aria-label": props.label,
|
|
@@ -361,14 +580,14 @@ function uiButtonView(props, r, content) {
|
|
|
361
580
|
]
|
|
362
581
|
);
|
|
363
582
|
}
|
|
364
|
-
function uiInputView(props, r,
|
|
583
|
+
function uiInputView(props, r, state2) {
|
|
365
584
|
const base = baseOf(props);
|
|
366
|
-
const
|
|
367
|
-
const messageId =
|
|
585
|
+
const message2 = props.message ? props.message : void 0;
|
|
586
|
+
const messageId = message2 && base ? `${base}--message` : void 0;
|
|
368
587
|
return el("span", root("input", props, r, { "data-invalid": props.invalid ? "true" : void 0 }), [
|
|
369
588
|
el("span", { class: "sp-ui-box" }, [
|
|
370
589
|
frame("control"),
|
|
371
|
-
...
|
|
590
|
+
...state2.prefix ? [el("span", { class: "sp-ui-affix", "data-slot": "prefix" }, [slot("prefix")])] : [],
|
|
372
591
|
el(
|
|
373
592
|
"input",
|
|
374
593
|
{
|
|
@@ -376,7 +595,7 @@ function uiInputView(props, r, state) {
|
|
|
376
595
|
id: props.id,
|
|
377
596
|
type: props.type ?? "text",
|
|
378
597
|
name: props.name,
|
|
379
|
-
value:
|
|
598
|
+
value: state2.value,
|
|
380
599
|
placeholder: props.placeholder,
|
|
381
600
|
disabled: props.disabled === true,
|
|
382
601
|
readonly: props.readOnly === true,
|
|
@@ -387,10 +606,10 @@ function uiInputView(props, r, state) {
|
|
|
387
606
|
[],
|
|
388
607
|
"native"
|
|
389
608
|
),
|
|
390
|
-
...
|
|
609
|
+
...state2.suffix ? [el("span", { class: "sp-ui-affix", "data-slot": "suffix" }, [slot("suffix")])] : [],
|
|
391
610
|
...props.invalid ? [glyph("warning")] : []
|
|
392
611
|
]),
|
|
393
|
-
...
|
|
612
|
+
...message2 ? [el("span", { class: "sp-ui-message", id: messageId }, [text(message2)])] : []
|
|
394
613
|
]);
|
|
395
614
|
}
|
|
396
615
|
function nativeCheckbox(props, checked, role) {
|
|
@@ -401,16 +620,16 @@ function nativeCheckbox(props, checked, role) {
|
|
|
401
620
|
"native"
|
|
402
621
|
);
|
|
403
622
|
}
|
|
404
|
-
function uiCheckboxView(props, r,
|
|
623
|
+
function uiCheckboxView(props, r, state2) {
|
|
405
624
|
return el("label", root("checkbox", props, r, { "data-indeterminate": props.indeterminate ? "true" : void 0 }), [
|
|
406
|
-
nativeCheckbox(props,
|
|
625
|
+
nativeCheckbox(props, state2.checked),
|
|
407
626
|
el("span", { class: "sp-ui-box", "aria-hidden": "true" }, [frame("box"), tone("selected", "box"), glyph("tick"), glyph("dash")]),
|
|
408
627
|
el("span", { class: "sp-ui-label" }, [text(props.label)])
|
|
409
628
|
]);
|
|
410
629
|
}
|
|
411
|
-
function uiSwitchView(props, r,
|
|
630
|
+
function uiSwitchView(props, r, state2) {
|
|
412
631
|
return el("label", root("switch", props, r), [
|
|
413
|
-
nativeCheckbox(props,
|
|
632
|
+
nativeCheckbox(props, state2.checked, "switch"),
|
|
414
633
|
el("span", { class: "sp-ui-track", "aria-hidden": "true" }, [frame("pill"), tone("selected", "pill"), el("span", { part: "sp-knob" })]),
|
|
415
634
|
el("span", { class: "sp-ui-label" }, [text(props.label)])
|
|
416
635
|
]);
|
|
@@ -426,7 +645,7 @@ function uiCardView(props, r, slots) {
|
|
|
426
645
|
frame("card"),
|
|
427
646
|
...header ? [
|
|
428
647
|
el("div", { class: "sp-ui-card-header" }, [
|
|
429
|
-
...titled ? [el(
|
|
648
|
+
...titled ? [el(headingTag(props.headingLevel, "SpCard"), { class: "sp-ui-card-title", id: titleId }, [text(props.title)])] : [],
|
|
430
649
|
...slots.extra ? [el("div", { class: "sp-ui-card-extra" }, [slot("extra")])] : []
|
|
431
650
|
]),
|
|
432
651
|
el("span", { part: "sp-rule", "aria-hidden": "true" })
|
|
@@ -454,11 +673,11 @@ function uiDividerView(props, r) {
|
|
|
454
673
|
|
|
455
674
|
// src/ui/view-b2.ts
|
|
456
675
|
var heighten = () => el("span", { part: "sp-heighten", "aria-hidden": "true" });
|
|
457
|
-
var legend = (
|
|
676
|
+
var legend = (label2, forSight) => el("legend", { class: forSight ? "sp-ui-legend" : "sp-ui-legend sp-ui-sr" }, [text(label2)]);
|
|
458
677
|
var groupName = (props) => props.name ?? (props.id ? `${props.id}--value` : void 0);
|
|
459
|
-
function uiRadioGroupView(props, r,
|
|
678
|
+
function uiRadioGroupView(props, r, state2) {
|
|
460
679
|
const items = uiItems(props.items, "SpRadioGroup");
|
|
461
|
-
const value = uiSelectedKey(items,
|
|
680
|
+
const value = uiSelectedKey(items, state2.value, "none");
|
|
462
681
|
return el("fieldset", root("radio-group", props, r, { id: props.id, "data-orientation": props.orientation ?? "vertical" }), [
|
|
463
682
|
legend(props.label, true),
|
|
464
683
|
...items.map(
|
|
@@ -476,9 +695,9 @@ function uiRadioGroupView(props, r, state) {
|
|
|
476
695
|
)
|
|
477
696
|
]);
|
|
478
697
|
}
|
|
479
|
-
function uiSegmentedView(props, r,
|
|
698
|
+
function uiSegmentedView(props, r, state2) {
|
|
480
699
|
const items = uiItems(props.items, "SpSegmented");
|
|
481
|
-
const value = uiSelectedKey(items,
|
|
700
|
+
const value = uiSelectedKey(items, state2.value, "first");
|
|
482
701
|
const name = groupName(props);
|
|
483
702
|
return el("fieldset", root("segmented", props, r, { id: props.id, "data-block": props.block ? "true" : void 0 }), [
|
|
484
703
|
legend(props.label, false),
|
|
@@ -497,9 +716,9 @@ function uiSegmentedView(props, r, state) {
|
|
|
497
716
|
])
|
|
498
717
|
]);
|
|
499
718
|
}
|
|
500
|
-
function uiTabsView(props, r,
|
|
719
|
+
function uiTabsView(props, r, state2) {
|
|
501
720
|
const items = uiItems(props.items, "SpTabs");
|
|
502
|
-
const value = uiSelectedKey(items,
|
|
721
|
+
const value = uiSelectedKey(items, state2.value, "first");
|
|
503
722
|
const vertical = props.orientation === "vertical";
|
|
504
723
|
const id = props.id;
|
|
505
724
|
return el("div", root("tabs", props, r, { id, "data-orientation": vertical ? "vertical" : "horizontal" }), [
|
|
@@ -543,11 +762,11 @@ function uiTabPanelView(props, tabs) {
|
|
|
543
762
|
[slot("content")]
|
|
544
763
|
);
|
|
545
764
|
}
|
|
546
|
-
function uiSliderView(props, r,
|
|
547
|
-
const
|
|
548
|
-
const { value, fraction } = uiValue(
|
|
549
|
-
const span =
|
|
550
|
-
const marks = (props.marks ?? []).filter((m) => Number.isFinite(m) && m >=
|
|
765
|
+
function uiSliderView(props, r, state2) {
|
|
766
|
+
const valid2 = uiRange({ min: props.min ?? 0, max: props.max ?? 100, step: props.step ?? 1 }, "SpSlider");
|
|
767
|
+
const { value, fraction } = uiValue(state2.value, valid2, "SpSlider");
|
|
768
|
+
const span = valid2.max - valid2.min;
|
|
769
|
+
const marks = (props.marks ?? []).filter((m) => Number.isFinite(m) && m >= valid2.min && m <= valid2.max);
|
|
551
770
|
return el("label", root("slider", props, r, { style: `--sp-ui-fraction: ${fraction}`, "data-disabled": props.disabled ? "true" : void 0 }), [
|
|
552
771
|
el("span", { class: "sp-ui-label" }, [text(props.label)]),
|
|
553
772
|
el("span", { class: "sp-ui-rail" }, [
|
|
@@ -561,9 +780,9 @@ function uiSliderView(props, r, state) {
|
|
|
561
780
|
class: "sp-ui-range",
|
|
562
781
|
id: props.id,
|
|
563
782
|
name: props.name,
|
|
564
|
-
min: String(
|
|
565
|
-
max: String(
|
|
566
|
-
step: String(
|
|
783
|
+
min: String(valid2.min),
|
|
784
|
+
max: String(valid2.max),
|
|
785
|
+
step: String(valid2.step ?? 1),
|
|
567
786
|
value: String(value),
|
|
568
787
|
disabled: props.disabled === true
|
|
569
788
|
},
|
|
@@ -575,14 +794,14 @@ function uiSliderView(props, r, state) {
|
|
|
575
794
|
el(
|
|
576
795
|
"span",
|
|
577
796
|
{ class: "sp-ui-scale", "aria-hidden": "true" },
|
|
578
|
-
marks.map((m) => el("span", { class: "sp-ui-scale-mark", style: `--sp-ui-at: ${round2((m -
|
|
797
|
+
marks.map((m) => el("span", { class: "sp-ui-scale-mark", style: `--sp-ui-at: ${round2((m - valid2.min) / span)}` }, [text(String(m))]))
|
|
579
798
|
)
|
|
580
799
|
] : []
|
|
581
800
|
]);
|
|
582
801
|
}
|
|
583
|
-
function uiRateView(props, r,
|
|
802
|
+
function uiRateView(props, r, state2) {
|
|
584
803
|
const count = uiRateCount(props.count);
|
|
585
|
-
const { value } = uiValue(
|
|
804
|
+
const { value } = uiValue(state2.value, { min: 0, max: count, step: 1 }, "SpRate");
|
|
586
805
|
const name = groupName(props);
|
|
587
806
|
const readOnly = props.readOnly === true;
|
|
588
807
|
return el(
|
|
@@ -608,7 +827,7 @@ function uiRateView(props, r, state) {
|
|
|
608
827
|
}
|
|
609
828
|
|
|
610
829
|
// src/ui/view-b3.ts
|
|
611
|
-
var closeButton = (
|
|
830
|
+
var closeButton = (label2) => el("button", { type: "button", class: "sp-ui-close", "aria-label": label2 }, [glyph("cross")], "close");
|
|
612
831
|
function uiStepsView(props, r) {
|
|
613
832
|
const steps = uiSteps(props.items, props.current);
|
|
614
833
|
const titles = new Map(props.items.map((item) => [item.key, item]));
|
|
@@ -631,13 +850,13 @@ function uiStepsView(props, r) {
|
|
|
631
850
|
);
|
|
632
851
|
}
|
|
633
852
|
function uiTagView(props, r, content) {
|
|
634
|
-
const
|
|
635
|
-
const
|
|
636
|
-
return el("span", root("tag", props, r, { id: props.id, "data-tone":
|
|
853
|
+
const level2 = String(props.tone ?? 1);
|
|
854
|
+
const label2 = props.closeLabel ?? (content.text ? `Remove ${content.text}` : "Remove");
|
|
855
|
+
return el("span", root("tag", props, r, { id: props.id, "data-tone": level2 }), [
|
|
637
856
|
frame("control"),
|
|
638
|
-
tone(
|
|
857
|
+
tone(level2, "control"),
|
|
639
858
|
el("span", { class: "sp-ui-label sp-ui-plate" }, [slot("content")]),
|
|
640
|
-
...props.closable ? [closeButton(
|
|
859
|
+
...props.closable ? [closeButton(label2)] : []
|
|
641
860
|
]);
|
|
642
861
|
}
|
|
643
862
|
function uiBadgeView(props, r, content) {
|
|
@@ -684,7 +903,7 @@ function uiProgressView(props, r) {
|
|
|
684
903
|
);
|
|
685
904
|
}
|
|
686
905
|
var ALERT_GLYPHS = { info: "info", success: "tick", warning: "warning", error: "cross" };
|
|
687
|
-
function uiAlertView(props, r,
|
|
906
|
+
function uiAlertView(props, r, state2) {
|
|
688
907
|
const kind = props.kind ?? "info";
|
|
689
908
|
const error = kind === "error";
|
|
690
909
|
return el("div", root("alert", props, r, { id: props.id, role: error || kind === "warning" ? "alert" : "status", "data-kind": kind }), [
|
|
@@ -695,7 +914,7 @@ function uiAlertView(props, r, state) {
|
|
|
695
914
|
...props.title ? [el("div", { class: "sp-ui-alert-title" }, [text(props.title)])] : [],
|
|
696
915
|
el("div", { class: "sp-ui-alert-text" }, [slot("content")])
|
|
697
916
|
]),
|
|
698
|
-
...
|
|
917
|
+
...state2.closable ? [closeButton(props.closeLabel ?? "Close")] : []
|
|
699
918
|
]);
|
|
700
919
|
}
|
|
701
920
|
function uiSkeletonView(props, r) {
|
|
@@ -711,6 +930,601 @@ function uiSkeletonView(props, r) {
|
|
|
711
930
|
]);
|
|
712
931
|
}
|
|
713
932
|
|
|
714
|
-
|
|
933
|
+
// src/ui/view-composed.ts
|
|
934
|
+
function warn4(component, property, message2) {
|
|
935
|
+
if (process.env.NODE_ENV !== "production") diagnose("SP017", component, { property, message: message2 });
|
|
936
|
+
}
|
|
937
|
+
var heighten2 = () => el("span", { part: "sp-heighten", "aria-hidden": "true" });
|
|
938
|
+
var heading = (level2, component, attrs, title) => el(headingTag(level2, component), attrs, [text(title)]);
|
|
939
|
+
var maybeText = (value) => value === "" ? [] : [text(value)];
|
|
940
|
+
function keyed(items, component) {
|
|
941
|
+
const seen = /* @__PURE__ */ new Set();
|
|
942
|
+
return items.filter((item) => {
|
|
943
|
+
if (item.key === void 0) return true;
|
|
944
|
+
if (!seen.has(item.key)) return seen.add(item.key), true;
|
|
945
|
+
if (process.env.NODE_ENV !== "production") diagnose("SP019", component, { property: "items", message: `The key "${item.key}" repeats; that item is skipped.` });
|
|
946
|
+
return false;
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
var IDENT = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
950
|
+
var UNSAFE_TAGS = /* @__PURE__ */ new Set(["script", "style", "iframe", "object", "embed", "template", "noscript"]);
|
|
951
|
+
function uiSurfaceView(props, r) {
|
|
952
|
+
let tag = props.as ?? "div";
|
|
953
|
+
if (!IDENT.test(tag) || UNSAFE_TAGS.has(tag)) {
|
|
954
|
+
warn4("SpSurface", "as", `${JSON.stringify(tag)} is drawn as "div".`);
|
|
955
|
+
tag = "div";
|
|
956
|
+
}
|
|
957
|
+
let name = props.name;
|
|
958
|
+
if (name !== void 0 && !IDENT.test(name)) {
|
|
959
|
+
warn4("SpSurface", "name", `${JSON.stringify(name)} adds no class.`);
|
|
960
|
+
name = void 0;
|
|
961
|
+
}
|
|
962
|
+
const attrs = root("surface", props, r, { id: props.id });
|
|
963
|
+
if (name) attrs.class = `${attrs.class} sp-${name}`;
|
|
964
|
+
return el(tag, attrs, [
|
|
965
|
+
...props.frame ? [frame(props.frame)] : [],
|
|
966
|
+
...props.tone !== void 0 ? [tone(String(props.tone), props.frame ?? "box")] : [],
|
|
967
|
+
slot("content")
|
|
968
|
+
]);
|
|
969
|
+
}
|
|
970
|
+
function uiGlyphView(props, r) {
|
|
971
|
+
const known = Object.hasOwn(UI_GLYPHS, props.glyph);
|
|
972
|
+
if (!known) warn4("SpGlyph", "glyph", `${JSON.stringify(props.glyph)} is not a glyph; nothing is drawn.`);
|
|
973
|
+
return el(
|
|
974
|
+
"svg",
|
|
975
|
+
root("glyph", props, r, { id: props.id, part: "sp-mark", "data-glyph": props.glyph, viewBox: "0 0 16 16", "aria-hidden": "true" }),
|
|
976
|
+
known ? [el("path", { d: UI_GLYPHS[props.glyph] })] : []
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
var cell = (value) => value === null || value === void 0 ? "" : String(value);
|
|
980
|
+
function uiTableView(props, r) {
|
|
981
|
+
const columns = uiItems(props.columns, "SpTable");
|
|
982
|
+
const order = props.sortOrder ?? "asc";
|
|
983
|
+
const sorted = columns.find((column) => column.key === props.sortKey && column.sortable === true);
|
|
984
|
+
const rows = props.data;
|
|
985
|
+
const headers = columns.map((column) => {
|
|
986
|
+
const width = cssLength(column.width, "SpTable", "columns");
|
|
987
|
+
const title = column.title ?? column.key;
|
|
988
|
+
const active = column === sorted;
|
|
989
|
+
return el(
|
|
990
|
+
"th",
|
|
991
|
+
{
|
|
992
|
+
scope: "col",
|
|
993
|
+
"data-align": column.align,
|
|
994
|
+
"aria-sort": active ? order === "asc" ? "ascending" : "descending" : void 0,
|
|
995
|
+
style: width ? `width:${width}` : void 0
|
|
996
|
+
},
|
|
997
|
+
column.sortable ? [
|
|
998
|
+
el("button", { type: "button", class: "sp-ui-sort", "data-key": column.key }, [
|
|
999
|
+
el("span", { class: "sp-ui-label" }, [text(title)]),
|
|
1000
|
+
glyph(active ? order === "asc" ? "sortUp" : "sortDown" : "sort")
|
|
1001
|
+
], "sort")
|
|
1002
|
+
] : [text(title)]
|
|
1003
|
+
);
|
|
1004
|
+
});
|
|
1005
|
+
const body = rows.length === 0 ? [el("tr", {}, [el("td", { class: "sp-ui-table-empty", colspan: String(columns.length) }, [text(props.emptyText ?? "No data")])])] : rows.map(
|
|
1006
|
+
(row2) => el(
|
|
1007
|
+
"tr",
|
|
1008
|
+
{ "data-key": props.rowKey !== void 0 ? cell(row2[props.rowKey]) : void 0 },
|
|
1009
|
+
// The text sits on a plate, so a toned row keeps the contrast of the substrate (Data Model §3.8).
|
|
1010
|
+
columns.map((column) => {
|
|
1011
|
+
const value = cell(row2[column.key]);
|
|
1012
|
+
return el("td", { "data-align": column.align }, value === "" ? [] : [el("span", { class: "sp-ui-plate" }, [text(value)])]);
|
|
1013
|
+
})
|
|
1014
|
+
)
|
|
1015
|
+
);
|
|
1016
|
+
return el(
|
|
1017
|
+
"div",
|
|
1018
|
+
root("table", props, r, {
|
|
1019
|
+
id: props.id,
|
|
1020
|
+
"data-striped": props.striped ? "true" : void 0,
|
|
1021
|
+
"data-hoverable": props.hoverable !== false ? "true" : void 0
|
|
1022
|
+
}),
|
|
1023
|
+
[
|
|
1024
|
+
...props.bordered !== false ? [frame("card")] : [],
|
|
1025
|
+
el("div", { class: "sp-ui-table-scroll" }, [
|
|
1026
|
+
el("table", { class: "sp-ui-table" }, [
|
|
1027
|
+
...props.caption ? [el("caption", {}, [text(props.caption)])] : [],
|
|
1028
|
+
el("thead", {}, [el("tr", {}, headers)]),
|
|
1029
|
+
el("tbody", {}, body)
|
|
1030
|
+
])
|
|
1031
|
+
])
|
|
1032
|
+
]
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
function uiPaginationView(props, r, state2) {
|
|
1036
|
+
const { count, current, start, end } = uiPagination(props.total, props.pageSize ?? 10, state2.current);
|
|
1037
|
+
const pageLabel = props.pageLabel ?? "Page";
|
|
1038
|
+
const off = props.disabled === true;
|
|
1039
|
+
const button = (page2, label2, disabled, content) => el("li", {}, [
|
|
1040
|
+
el("button", { type: "button", class: "sp-ui-page", "data-page": String(page2), "aria-label": label2, disabled: off || disabled }, [frame("control"), ...content], "page")
|
|
1041
|
+
]);
|
|
1042
|
+
const pages = uiPageWindow(count, current, props.siblings ?? 1).map(
|
|
1043
|
+
(entry) => typeof entry === "string" ? el("li", { class: "sp-ui-page-gap", "aria-hidden": "true" }, [glyph("ellipsis")]) : entry === current ? el("li", {}, [
|
|
1044
|
+
el("span", { class: "sp-ui-page", "aria-current": "page" }, [
|
|
1045
|
+
frame("control"),
|
|
1046
|
+
heighten2(),
|
|
1047
|
+
el("span", { class: "sp-ui-label sp-ui-plate" }, [sr(`${pageLabel} `), text(String(entry))])
|
|
1048
|
+
])
|
|
1049
|
+
]) : button(entry, `${pageLabel} ${entry}`, false, [el("span", { class: "sp-ui-label" }, [text(String(entry))])])
|
|
1050
|
+
);
|
|
1051
|
+
const summary = (props.totalTemplate ?? "{start}\u2013{end} of {total}").split("{start}").join(String(start)).split("{end}").join(String(end)).split("{total}").join(String(Math.max(0, props.total || 0)));
|
|
1052
|
+
return el("nav", root("pagination", props, r, { id: props.id, "aria-label": props.label ?? "Pagination", "data-disabled": off ? "true" : void 0 }), [
|
|
1053
|
+
...props.showTotal ? [el("span", { class: "sp-ui-page-total" }, [text(summary)])] : [],
|
|
1054
|
+
el("ul", { class: "sp-ui-pages" }, [
|
|
1055
|
+
button(current - 1, props.previousLabel ?? "Previous page", current <= 1, [glyph("chevronLeft")]),
|
|
1056
|
+
...pages,
|
|
1057
|
+
button(current + 1, props.nextLabel ?? "Next page", current >= count, [glyph("chevronRight")])
|
|
1058
|
+
])
|
|
1059
|
+
]);
|
|
1060
|
+
}
|
|
1061
|
+
function uiBreadcrumbView(props, r) {
|
|
1062
|
+
const items = keyed(props.items, "SpBreadcrumb");
|
|
1063
|
+
return el("nav", root("breadcrumb", props, r, { id: props.id, "aria-label": props.label ?? "Breadcrumb" }), [
|
|
1064
|
+
el(
|
|
1065
|
+
"ol",
|
|
1066
|
+
{ class: "sp-ui-crumbs" },
|
|
1067
|
+
items.map((item, i) => {
|
|
1068
|
+
const last2 = i === items.length - 1;
|
|
1069
|
+
const href = last2 ? void 0 : safeHref(item.href, "SpBreadcrumb", "items");
|
|
1070
|
+
const inner = last2 ? el("span", { "aria-current": "page" }, [text(item.label)]) : href !== void 0 ? el("a", { href }, [text(item.label)]) : el("span", {}, [text(item.label)]);
|
|
1071
|
+
return el("li", { class: "sp-ui-crumb" }, [inner]);
|
|
1072
|
+
})
|
|
1073
|
+
)
|
|
1074
|
+
]);
|
|
1075
|
+
}
|
|
1076
|
+
function uiAvatarView(props, r) {
|
|
1077
|
+
const name = props.alt ?? props.name ?? props.initials;
|
|
1078
|
+
uiRequireName("SpAvatar", name, void 0);
|
|
1079
|
+
let size = props.pixelSize;
|
|
1080
|
+
if (size !== void 0 && !(Number.isFinite(size) && size > 0)) {
|
|
1081
|
+
warn4("SpAvatar", "pixelSize", `${size} is dropped.`);
|
|
1082
|
+
size = void 0;
|
|
1083
|
+
}
|
|
1084
|
+
const square = props.shape === "square";
|
|
1085
|
+
const image = props.src !== void 0;
|
|
1086
|
+
return el(
|
|
1087
|
+
"span",
|
|
1088
|
+
root("avatar", props, r, {
|
|
1089
|
+
id: props.id,
|
|
1090
|
+
role: image ? void 0 : "img",
|
|
1091
|
+
"aria-label": image ? void 0 : name,
|
|
1092
|
+
"data-shape": square ? "square" : "circle",
|
|
1093
|
+
style: size !== void 0 ? `--sp-ui-avatar-size:${Math.round(size * 100) / 100}px` : void 0
|
|
1094
|
+
}),
|
|
1095
|
+
[
|
|
1096
|
+
frame(square ? "box" : "round"),
|
|
1097
|
+
image ? el("img", { class: "sp-ui-avatar-image", src: props.src, alt: props.alt ?? props.name ?? "" }) : el("span", { class: "sp-ui-avatar-initials", "aria-hidden": "true" }, [text(props.initials ?? uiInitials(props.name))])
|
|
1098
|
+
]
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1101
|
+
function uiAvatarGroupView(props, r) {
|
|
1102
|
+
return el("div", root("avatar-group", props, r, { id: props.id, role: "group", "aria-label": props.label }), [slot("content")]);
|
|
1103
|
+
}
|
|
1104
|
+
function uiStatisticView(props, r) {
|
|
1105
|
+
const affix = (value) => el("span", { class: "sp-ui-statistic-affix" }, [text(value)]);
|
|
1106
|
+
const up = props.trend === "up";
|
|
1107
|
+
return el("div", root("statistic", props, r, { id: props.id, "data-trend": props.trend }), [
|
|
1108
|
+
el("span", { class: "sp-ui-statistic-title" }, [text(props.title)]),
|
|
1109
|
+
el("span", { class: "sp-ui-statistic-value" }, [
|
|
1110
|
+
...props.prefix ? [affix(props.prefix)] : [],
|
|
1111
|
+
el("span", { class: "sp-ui-statistic-number" }, [text(String(props.value))]),
|
|
1112
|
+
...props.suffix ? [affix(props.suffix)] : []
|
|
1113
|
+
]),
|
|
1114
|
+
...props.trend ? [
|
|
1115
|
+
el("span", { class: "sp-ui-statistic-trend", "data-trend": props.trend }, [
|
|
1116
|
+
glyph(up ? "arrowUp" : "arrowDown"),
|
|
1117
|
+
props.delta ? el("span", { class: "sp-ui-statistic-delta" }, [text(props.delta)]) : sr(up ? "Up" : "Down")
|
|
1118
|
+
])
|
|
1119
|
+
] : []
|
|
1120
|
+
]);
|
|
1121
|
+
}
|
|
1122
|
+
function uiDescriptionsView(props, r) {
|
|
1123
|
+
let columns = props.columns ?? 3;
|
|
1124
|
+
const fixed = Number.isFinite(columns) ? Math.min(6, Math.max(1, Math.round(columns))) : 3;
|
|
1125
|
+
if (fixed !== columns) warn4("SpDescriptions", "columns", `${columns} is drawn as ${fixed}.`);
|
|
1126
|
+
columns = fixed;
|
|
1127
|
+
const titled = props.title !== void 0;
|
|
1128
|
+
const titleId = titled && props.id ? `${props.id}--title` : void 0;
|
|
1129
|
+
const bordered = props.bordered !== false;
|
|
1130
|
+
return el(
|
|
1131
|
+
"section",
|
|
1132
|
+
root("descriptions", props, r, {
|
|
1133
|
+
id: props.id,
|
|
1134
|
+
"aria-labelledby": titleId,
|
|
1135
|
+
"aria-label": titled && !titleId ? props.title : void 0,
|
|
1136
|
+
"data-bordered": bordered ? "true" : void 0,
|
|
1137
|
+
"data-columns": String(columns)
|
|
1138
|
+
}),
|
|
1139
|
+
[
|
|
1140
|
+
...bordered ? [frame("card")] : [],
|
|
1141
|
+
...titled ? [heading(props.headingLevel, "SpDescriptions", { class: "sp-ui-descriptions-title", id: titleId }, props.title)] : [],
|
|
1142
|
+
el(
|
|
1143
|
+
"dl",
|
|
1144
|
+
{},
|
|
1145
|
+
keyed(props.items, "SpDescriptions").map(
|
|
1146
|
+
(item) => el("div", { class: "sp-ui-description" }, [el("dt", {}, [text(item.label)]), el("dd", {}, maybeText(item.value))])
|
|
1147
|
+
)
|
|
1148
|
+
)
|
|
1149
|
+
]
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
function uiTimelineListView(props, r) {
|
|
1153
|
+
let current = false;
|
|
1154
|
+
const items = keyed(props.items, "SpTimelineList").map((item) => {
|
|
1155
|
+
let status = item.status ?? "done";
|
|
1156
|
+
if (status === "current") {
|
|
1157
|
+
if (current) {
|
|
1158
|
+
warn4("SpTimelineList", "items", `A second current item, "${item.title}", is drawn as done.`);
|
|
1159
|
+
status = "done";
|
|
1160
|
+
}
|
|
1161
|
+
current = true;
|
|
1162
|
+
}
|
|
1163
|
+
const mark = status === "done" ? [tone("selected", "round")] : status === "current" ? [heighten2()] : status === "error" ? [glyph("cross")] : [];
|
|
1164
|
+
return el("li", { class: "sp-ui-timeline-item", "data-status": status, "aria-current": status === "current" ? "step" : void 0 }, [
|
|
1165
|
+
el("span", { class: "sp-ui-timeline-mark", "aria-hidden": "true" }, [frame("round"), ...mark]),
|
|
1166
|
+
el("span", { class: "sp-ui-timeline-text" }, [
|
|
1167
|
+
...item.time ? [el("span", { class: "sp-ui-timeline-time" }, [text(item.time)])] : [],
|
|
1168
|
+
el("span", { class: "sp-ui-timeline-title" }, [text(item.title)]),
|
|
1169
|
+
...item.description ? [el("span", { class: "sp-ui-timeline-description" }, [text(item.description)])] : []
|
|
1170
|
+
])
|
|
1171
|
+
]);
|
|
1172
|
+
});
|
|
1173
|
+
return el("ol", root("timeline-list", props, r, { id: props.id, "aria-label": props.label }), items);
|
|
1174
|
+
}
|
|
1175
|
+
function uiCollapseView(props, r) {
|
|
1176
|
+
return el("div", root("collapse", props, r, { id: props.id, "data-accordion": props.accordion ? "true" : void 0 }), [
|
|
1177
|
+
...props.bordered !== false ? [frame("card")] : [],
|
|
1178
|
+
slot("content")
|
|
1179
|
+
]);
|
|
1180
|
+
}
|
|
1181
|
+
function uiCollapseGroup(props) {
|
|
1182
|
+
if (!props.accordion) return void 0;
|
|
1183
|
+
if (props.id) return `${props.id}--accordion`;
|
|
1184
|
+
warn4("SpCollapse", "id", "An accordion needs an id to name its items; they open independently.");
|
|
1185
|
+
return void 0;
|
|
1186
|
+
}
|
|
1187
|
+
function uiCollapseItemView(props, r, state2) {
|
|
1188
|
+
return el(
|
|
1189
|
+
"details",
|
|
1190
|
+
root("collapse-item", props, r, { id: props.id, name: state2.group, open: state2.open, "data-disabled": props.disabled ? "true" : void 0 }),
|
|
1191
|
+
[
|
|
1192
|
+
// A disabled item's summary leaves the Tab order: no `disabled` attribute exists for it (REQ-522).
|
|
1193
|
+
el("summary", { class: "sp-ui-collapse-summary", "aria-disabled": props.disabled ? "true" : void 0, tabindex: props.disabled ? "-1" : void 0 }, [
|
|
1194
|
+
el("span", { class: "sp-ui-label" }, [text(props.title)]),
|
|
1195
|
+
glyph("chevronDown")
|
|
1196
|
+
], "summary"),
|
|
1197
|
+
el("div", { class: "sp-ui-collapse-body" }, [slot("content")])
|
|
1198
|
+
]
|
|
1199
|
+
);
|
|
1200
|
+
}
|
|
1201
|
+
function uiEmptyView(props, r, slots) {
|
|
1202
|
+
return el("div", root("empty", props, r, { id: props.id }), [
|
|
1203
|
+
el("span", { class: "sp-ui-empty-tray", "aria-hidden": "true" }, [tone("1", "control"), frame("control")]),
|
|
1204
|
+
el("p", { class: "sp-ui-empty-description" }, [text(props.description ?? "No data")]),
|
|
1205
|
+
...slots.extra ? [el("div", { class: "sp-ui-empty-extra" }, [slot("extra")])] : []
|
|
1206
|
+
]);
|
|
1207
|
+
}
|
|
1208
|
+
var RESULT_GLYPHS = { success: "tick", info: "info", warning: "warning", error: "cross" };
|
|
1209
|
+
function uiResultView(props, r, slots) {
|
|
1210
|
+
const status = props.status ?? "info";
|
|
1211
|
+
const alert = status === "warning" || status === "error";
|
|
1212
|
+
return el("div", root("result", props, r, { id: props.id, role: alert ? "alert" : "status", "data-status": status }), [
|
|
1213
|
+
el("span", { class: "sp-ui-result-mark", "aria-hidden": "true" }, [frame("round"), glyph(RESULT_GLYPHS[status])]),
|
|
1214
|
+
heading(props.headingLevel, "SpResult", { class: "sp-ui-result-title" }, props.title),
|
|
1215
|
+
...props.subtitle ? [el("p", { class: "sp-ui-result-subtitle" }, [text(props.subtitle)])] : [],
|
|
1216
|
+
...slots.extra ? [el("div", { class: "sp-ui-result-extra" }, [slot("extra")])] : []
|
|
1217
|
+
]);
|
|
1218
|
+
}
|
|
1219
|
+
function message(props) {
|
|
1220
|
+
const base = baseOf(props);
|
|
1221
|
+
const id = props.message && base ? `${base}--message` : void 0;
|
|
1222
|
+
return { id, node: props.message ? [el("span", { class: "sp-ui-message", id }, [text(props.message)])] : [] };
|
|
1223
|
+
}
|
|
1224
|
+
function uiTextareaView(props, r, state2) {
|
|
1225
|
+
const said = message(props);
|
|
1226
|
+
const max = props.maxLength !== void 0 && Number.isInteger(props.maxLength) && props.maxLength >= 0 ? props.maxLength : void 0;
|
|
1227
|
+
return el("span", root("input sp-textarea", props, r, { "data-invalid": props.invalid ? "true" : void 0 }), [
|
|
1228
|
+
el("span", { class: "sp-ui-box" }, [
|
|
1229
|
+
frame("control"),
|
|
1230
|
+
el(
|
|
1231
|
+
"textarea",
|
|
1232
|
+
{
|
|
1233
|
+
class: "sp-ui-control",
|
|
1234
|
+
id: props.id,
|
|
1235
|
+
name: props.name,
|
|
1236
|
+
rows: String(props.rows ?? 3),
|
|
1237
|
+
maxlength: max !== void 0 ? String(max) : void 0,
|
|
1238
|
+
placeholder: props.placeholder,
|
|
1239
|
+
disabled: props.disabled === true,
|
|
1240
|
+
readonly: props.readOnly === true,
|
|
1241
|
+
"aria-label": props.label,
|
|
1242
|
+
"aria-invalid": props.invalid ? "true" : void 0,
|
|
1243
|
+
"aria-describedby": said.id
|
|
1244
|
+
},
|
|
1245
|
+
maybeText(state2.value),
|
|
1246
|
+
"native"
|
|
1247
|
+
),
|
|
1248
|
+
...props.invalid ? [glyph("warning")] : []
|
|
1249
|
+
]),
|
|
1250
|
+
...props.showCount ? [el("span", { class: "sp-ui-count" }, [text(max !== void 0 ? `${state2.value.length} / ${max}` : String(state2.value.length))])] : [],
|
|
1251
|
+
...said.node
|
|
1252
|
+
]);
|
|
1253
|
+
}
|
|
1254
|
+
function uiInputNumberView(props, r, state2) {
|
|
1255
|
+
const { value, atMin, atMax, range } = uiNumberValue(state2.value, props, "SpInputNumber");
|
|
1256
|
+
const said = message(props);
|
|
1257
|
+
const locked = props.disabled === true || props.readOnly === true;
|
|
1258
|
+
const stepper = (direction2, label2, disabled, mark) => el("button", { type: "button", class: "sp-ui-stepper", "data-step": direction2, "aria-label": label2, tabindex: "-1", disabled: locked || disabled }, [glyph(mark)], "stepper");
|
|
1259
|
+
return el("span", root("input sp-input-number", props, r, { "data-invalid": props.invalid ? "true" : void 0 }), [
|
|
1260
|
+
el("span", { class: "sp-ui-box" }, [
|
|
1261
|
+
frame("control"),
|
|
1262
|
+
stepper("-1", props.decrementLabel ?? "Decrease", atMin, "dash"),
|
|
1263
|
+
el(
|
|
1264
|
+
"input",
|
|
1265
|
+
{
|
|
1266
|
+
class: "sp-ui-control",
|
|
1267
|
+
type: "number",
|
|
1268
|
+
inputmode: "decimal",
|
|
1269
|
+
id: props.id,
|
|
1270
|
+
name: props.name,
|
|
1271
|
+
min: range.min !== void 0 ? String(range.min) : void 0,
|
|
1272
|
+
max: range.max !== void 0 ? String(range.max) : void 0,
|
|
1273
|
+
step: String(range.step ?? 1),
|
|
1274
|
+
value: value === null ? "" : String(value),
|
|
1275
|
+
placeholder: props.placeholder,
|
|
1276
|
+
disabled: props.disabled === true,
|
|
1277
|
+
readonly: props.readOnly === true,
|
|
1278
|
+
"aria-label": props.label,
|
|
1279
|
+
"aria-invalid": props.invalid ? "true" : void 0,
|
|
1280
|
+
"aria-describedby": said.id
|
|
1281
|
+
},
|
|
1282
|
+
[],
|
|
1283
|
+
"native"
|
|
1284
|
+
),
|
|
1285
|
+
stepper("1", props.incrementLabel ?? "Increase", atMax, "plus"),
|
|
1286
|
+
...props.invalid ? [glyph("warning")] : []
|
|
1287
|
+
]),
|
|
1288
|
+
...said.node
|
|
1289
|
+
]);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
// src/ui/view-overlay.ts
|
|
1293
|
+
var heighten3 = () => el("span", { part: "sp-heighten", "aria-hidden": "true" });
|
|
1294
|
+
var state = (open) => open ? "open" : "closed";
|
|
1295
|
+
var style = (property, value) => value !== void 0 ? `${property}:${value}` : void 0;
|
|
1296
|
+
var label = (value, plate) => el("span", { class: plate ? "sp-ui-label sp-ui-plate" : "sp-ui-label" }, [text(value)]);
|
|
1297
|
+
function uiTriggerView() {
|
|
1298
|
+
return el("span", { class: "sp-ui-trigger" }, [slot("trigger")], "trigger");
|
|
1299
|
+
}
|
|
1300
|
+
var CONTROLS = {
|
|
1301
|
+
dialog: ["dialog", "dialog"],
|
|
1302
|
+
popover: ["dialog", "popover"],
|
|
1303
|
+
menu: ["menu", "menu"]
|
|
1304
|
+
};
|
|
1305
|
+
function uiTriggerAria(kind, id, open) {
|
|
1306
|
+
if (kind === "tooltip") return id ? { "aria-describedby": `${id}--tooltip` } : {};
|
|
1307
|
+
const [popup, part] = CONTROLS[kind];
|
|
1308
|
+
return { "aria-haspopup": popup, "aria-expanded": String(open), ...id ? { "aria-controls": `${id}--${part}` } : {} };
|
|
1309
|
+
}
|
|
1310
|
+
function uiSelectItems(items) {
|
|
1311
|
+
return uiItems(
|
|
1312
|
+
items.map((item) => typeof item === "string" ? { key: item, label: item } : item),
|
|
1313
|
+
"SpSelect"
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
var actionable = (entry) => entry.type === void 0 || entry.type === "item";
|
|
1317
|
+
function uiMenuItems(entries) {
|
|
1318
|
+
return uiItems(entries, "SpDropdownMenu").filter(actionable).map((entry) => ({ key: entry.key, label: entry.label, ...entry.disabled ? { disabled: true } : {} }));
|
|
1319
|
+
}
|
|
1320
|
+
function uiToastDuration(duration, toaster) {
|
|
1321
|
+
const ms = duration ?? toaster ?? 5e3;
|
|
1322
|
+
if (ms === Infinity || Number.isFinite(ms) && ms >= 1e3) return ms;
|
|
1323
|
+
if (process.env.NODE_ENV !== "production") diagnose("SP017", "SpToast", { property: "duration", message: `${ms} ms is drawn as 1000 ms.` });
|
|
1324
|
+
return 1e3;
|
|
1325
|
+
}
|
|
1326
|
+
function dialog(component, slug, props, r, open, footer, attrs) {
|
|
1327
|
+
uiRequireName(component, props.title, props.label);
|
|
1328
|
+
const { id, title } = props;
|
|
1329
|
+
const titleId = title !== void 0 && id ? `${id}--title` : void 0;
|
|
1330
|
+
const descriptionId = props.description && id ? `${id}--description` : void 0;
|
|
1331
|
+
const closable = props.closable !== false;
|
|
1332
|
+
const header = title !== void 0 || closable;
|
|
1333
|
+
return el(
|
|
1334
|
+
"dialog",
|
|
1335
|
+
root(slug, props, r, {
|
|
1336
|
+
id: id ? `${id}--dialog` : void 0,
|
|
1337
|
+
"aria-labelledby": titleId,
|
|
1338
|
+
"aria-label": titleId ? void 0 : title ?? props.label,
|
|
1339
|
+
"aria-describedby": descriptionId,
|
|
1340
|
+
"data-state": state(open),
|
|
1341
|
+
...attrs
|
|
1342
|
+
}),
|
|
1343
|
+
[
|
|
1344
|
+
frame("card"),
|
|
1345
|
+
...header ? [
|
|
1346
|
+
el("div", { class: "sp-ui-overlay-header" }, [
|
|
1347
|
+
...title !== void 0 ? [el("h2", { class: "sp-ui-overlay-title", id: titleId }, [text(title)])] : [],
|
|
1348
|
+
...closable ? [iconClose(props.closeLabel ?? "Close")] : []
|
|
1349
|
+
]),
|
|
1350
|
+
el("span", { part: "sp-rule", "aria-hidden": "true" })
|
|
1351
|
+
] : [],
|
|
1352
|
+
...props.description ? [el("p", { class: "sp-ui-overlay-description", id: descriptionId }, [text(props.description)])] : [],
|
|
1353
|
+
el("div", { class: "sp-ui-overlay-body" }, [slot("content")]),
|
|
1354
|
+
...footer ? [el("div", { class: "sp-ui-overlay-footer" }, [slot("footer")])] : []
|
|
1355
|
+
],
|
|
1356
|
+
"dialog"
|
|
1357
|
+
);
|
|
1358
|
+
}
|
|
1359
|
+
function uiModalView(props, r, s, slots) {
|
|
1360
|
+
return dialog("SpModal", "modal", props, r, s.open, slots.footer === true, {
|
|
1361
|
+
style: style("--sp-ui-overlay-width", cssLength(props.width, "SpModal", "width"))
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
function uiDrawerView(props, r, s, slots) {
|
|
1365
|
+
return dialog("SpDrawer", "drawer", props, r, s.open, slots.footer === true, {
|
|
1366
|
+
"data-side": props.side ?? "end",
|
|
1367
|
+
style: style("--sp-ui-drawer-extent", cssLength(props.extent, "SpDrawer", "extent"))
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
function uiPopoverView(props, r, s) {
|
|
1371
|
+
uiRequireName("SpPopover", props.title, props.label);
|
|
1372
|
+
const { id, title } = props;
|
|
1373
|
+
const titleId = title !== void 0 && id ? `${id}--title` : void 0;
|
|
1374
|
+
const header = title !== void 0 || props.closable === true;
|
|
1375
|
+
return el(
|
|
1376
|
+
"div",
|
|
1377
|
+
root("popover", props, r, {
|
|
1378
|
+
id: id ? `${id}--popover` : void 0,
|
|
1379
|
+
popover: "auto",
|
|
1380
|
+
role: "dialog",
|
|
1381
|
+
"aria-labelledby": titleId,
|
|
1382
|
+
"aria-label": titleId ? void 0 : title ?? props.label,
|
|
1383
|
+
"data-state": state(s.open),
|
|
1384
|
+
style: style("--sp-ui-overlay-width", cssLength(props.width, "SpPopover", "width"))
|
|
1385
|
+
}),
|
|
1386
|
+
[
|
|
1387
|
+
frame("card"),
|
|
1388
|
+
...header ? [
|
|
1389
|
+
el("div", { class: "sp-ui-overlay-header" }, [
|
|
1390
|
+
...title !== void 0 ? [el("div", { class: "sp-ui-overlay-title", id: titleId }, [text(title)])] : [],
|
|
1391
|
+
...props.closable ? [iconClose(props.closeLabel ?? "Close")] : []
|
|
1392
|
+
])
|
|
1393
|
+
] : [],
|
|
1394
|
+
el("div", { class: "sp-ui-overlay-body" }, [slot("content")])
|
|
1395
|
+
],
|
|
1396
|
+
"popover"
|
|
1397
|
+
);
|
|
1398
|
+
}
|
|
1399
|
+
function uiTooltipView(props, r, s) {
|
|
1400
|
+
return el(
|
|
1401
|
+
"div",
|
|
1402
|
+
root("tooltip", props, r, { id: props.id ? `${props.id}--tooltip` : void 0, popover: "manual", role: "tooltip", "data-state": state(s.open) }),
|
|
1403
|
+
[frame("control"), el("span", { class: "sp-ui-tooltip-text" }, [text(props.text)])],
|
|
1404
|
+
"popover"
|
|
1405
|
+
);
|
|
1406
|
+
}
|
|
1407
|
+
function uiSelectView(props, r, s) {
|
|
1408
|
+
uiRequireName("SpSelect", void 0, props.label);
|
|
1409
|
+
const items = uiSelectItems(props.items);
|
|
1410
|
+
const value = uiSelectedKey(items, s.value, "none");
|
|
1411
|
+
const chosen = items.find((item) => item.key === value);
|
|
1412
|
+
const { id } = props;
|
|
1413
|
+
const optionId = (key) => id ? `${id}--option-${key}` : void 0;
|
|
1414
|
+
const active = s.open ? items.find((item) => item.key === s.active && item.disabled !== true) : void 0;
|
|
1415
|
+
const options = items.map((item) => {
|
|
1416
|
+
const isActive = item === active;
|
|
1417
|
+
const isChosen = item === chosen;
|
|
1418
|
+
return el(
|
|
1419
|
+
"div",
|
|
1420
|
+
{
|
|
1421
|
+
class: "sp-ui-option",
|
|
1422
|
+
role: "option",
|
|
1423
|
+
id: optionId(item.key),
|
|
1424
|
+
"data-key": item.key,
|
|
1425
|
+
"aria-selected": String(isChosen),
|
|
1426
|
+
"aria-disabled": item.disabled ? "true" : void 0
|
|
1427
|
+
},
|
|
1428
|
+
[...isActive ? [heighten3()] : [], label(item.label, isActive), ...isChosen ? [glyph("tick")] : []],
|
|
1429
|
+
"option"
|
|
1430
|
+
);
|
|
1431
|
+
});
|
|
1432
|
+
return el("span", root("select", props, r, { id, style: style("--sp-ui-select-width", cssLength(props.width, "SpSelect", "width")) }), [
|
|
1433
|
+
el(
|
|
1434
|
+
"button",
|
|
1435
|
+
{
|
|
1436
|
+
type: "button",
|
|
1437
|
+
class: "sp-ui-select-trigger",
|
|
1438
|
+
role: "combobox",
|
|
1439
|
+
"aria-haspopup": "listbox",
|
|
1440
|
+
"aria-expanded": String(s.open),
|
|
1441
|
+
"aria-controls": id ? `${id}--listbox` : void 0,
|
|
1442
|
+
"aria-activedescendant": active ? optionId(active.key) : void 0,
|
|
1443
|
+
"aria-label": props.label,
|
|
1444
|
+
"aria-required": props.required ? "true" : void 0,
|
|
1445
|
+
disabled: props.disabled === true
|
|
1446
|
+
},
|
|
1447
|
+
[
|
|
1448
|
+
frame("control"),
|
|
1449
|
+
el("span", { class: "sp-ui-select-value", "data-placeholder": chosen ? void 0 : "true" }, [text(chosen?.label ?? props.placeholder ?? "Select\u2026")]),
|
|
1450
|
+
glyph("chevronDown")
|
|
1451
|
+
],
|
|
1452
|
+
"trigger"
|
|
1453
|
+
),
|
|
1454
|
+
el("div", { class: "sp-ui-select-content", popover: "auto", "data-state": state(s.open) }, [
|
|
1455
|
+
frame("card"),
|
|
1456
|
+
el("div", { role: "listbox", id: id ? `${id}--listbox` : void 0, "aria-label": props.label }, options)
|
|
1457
|
+
], "popover"),
|
|
1458
|
+
...props.name ? [el("input", { type: "hidden", name: props.name, value: value ?? "" })] : []
|
|
1459
|
+
]);
|
|
1460
|
+
}
|
|
1461
|
+
function uiDropdownMenuView(props, r, s, slots) {
|
|
1462
|
+
const { id } = props;
|
|
1463
|
+
const entries = uiItems(props.items, "SpDropdownMenu");
|
|
1464
|
+
const active = s.open ? entries.find((entry) => actionable(entry) && entry.key === s.active && entry.disabled !== true) : void 0;
|
|
1465
|
+
const children = entries.map((entry) => {
|
|
1466
|
+
if (entry.type === "separator") return el("div", { class: "sp-ui-menu-separator", role: "separator" });
|
|
1467
|
+
if (entry.type === "label") return el("div", { class: "sp-ui-menu-label", role: "presentation" }, [text(entry.label)]);
|
|
1468
|
+
const isActive = entry === active;
|
|
1469
|
+
return el(
|
|
1470
|
+
"div",
|
|
1471
|
+
{
|
|
1472
|
+
class: "sp-ui-menuitem",
|
|
1473
|
+
role: "menuitem",
|
|
1474
|
+
tabindex: "-1",
|
|
1475
|
+
"data-key": entry.key,
|
|
1476
|
+
"aria-disabled": entry.disabled ? "true" : void 0,
|
|
1477
|
+
"data-danger": entry.danger ? "true" : void 0
|
|
1478
|
+
},
|
|
1479
|
+
[
|
|
1480
|
+
...isActive ? [heighten3()] : [],
|
|
1481
|
+
label(entry.label, isActive),
|
|
1482
|
+
...entry.shortcut ? [el("span", { class: "sp-ui-menu-shortcut", "aria-hidden": "true" }, [text(entry.shortcut)])] : []
|
|
1483
|
+
],
|
|
1484
|
+
"menuitem"
|
|
1485
|
+
);
|
|
1486
|
+
});
|
|
1487
|
+
const trigger = slots.trigger ? uiTriggerView() : el(
|
|
1488
|
+
"button",
|
|
1489
|
+
{ type: "button", class: "sp-ui-menu-trigger", ...uiTriggerAria("menu", id, s.open) },
|
|
1490
|
+
[frame("control"), el("span", { class: "sp-ui-label" }, [text(props.label)]), glyph("chevronDown")],
|
|
1491
|
+
"trigger"
|
|
1492
|
+
);
|
|
1493
|
+
return el("span", root("dropdown-menu", props, r, { id }), [
|
|
1494
|
+
trigger,
|
|
1495
|
+
el(
|
|
1496
|
+
"div",
|
|
1497
|
+
{ class: "sp-ui-menu", id: id ? `${id}--menu` : void 0, popover: "auto", role: "menu", "aria-label": props.label, "data-state": state(s.open) },
|
|
1498
|
+
[frame("card"), ...children],
|
|
1499
|
+
"popover"
|
|
1500
|
+
)
|
|
1501
|
+
]);
|
|
1502
|
+
}
|
|
1503
|
+
var TOAST_GLYPHS = { info: "info", success: "tick", warning: "warning", error: "cross" };
|
|
1504
|
+
function uiToastView(props, r, s, slots) {
|
|
1505
|
+
const kind = props.kind ?? "info";
|
|
1506
|
+
const urgent = kind === "warning" || kind === "error";
|
|
1507
|
+
return el("li", root("toast", props, r, { id: props.id, role: "listitem", "data-kind": kind, "data-state": state(s.open) }), [
|
|
1508
|
+
frame("card"),
|
|
1509
|
+
el("div", { class: "sp-ui-toast-body", role: urgent ? "alert" : "status" }, [
|
|
1510
|
+
glyph(TOAST_GLYPHS[kind]),
|
|
1511
|
+
el("div", { class: "sp-ui-toast-text" }, [
|
|
1512
|
+
el("span", { class: "sp-ui-toast-title" }, [text(props.title)]),
|
|
1513
|
+
...props.description ? [el("span", { class: "sp-ui-toast-description" }, [text(props.description)])] : []
|
|
1514
|
+
])
|
|
1515
|
+
]),
|
|
1516
|
+
...slots.action ? [el("div", { class: "sp-ui-toast-action" }, [slot("action")])] : [],
|
|
1517
|
+
iconClose(props.closeLabel ?? "Dismiss")
|
|
1518
|
+
]);
|
|
1519
|
+
}
|
|
1520
|
+
function uiToasterView(props, r) {
|
|
1521
|
+
return el(
|
|
1522
|
+
"section",
|
|
1523
|
+
root("toaster", props, r, { id: props.id, "aria-label": props.label ?? "Notifications", "data-position": props.position ?? "bottom-end" }),
|
|
1524
|
+
[el("ol", { class: "sp-ui-toaster-list", role: "list" }, [slot("content")])]
|
|
1525
|
+
);
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
export { UI_COMPONENTS, UI_FRAME_KINDS, UI_PROGRESS_VIEWBOX, UI_TOKEN_DEFAULTS, resolveUi, resolveUiTokens, uiAlertView, uiAnchor, uiAvatarGroupView, uiAvatarView, uiBadgeView, uiBreadcrumbView, uiButtonView, uiCardView, uiCheckboxView, uiCollapseGroup, uiCollapseItemView, uiCollapseView, uiDescriptionsView, uiDividerView, uiDrawerView, uiDropdownMenuView, uiEmptyView, uiFrameOutline, uiFrameVariant, uiGlyphView, uiInitials, uiInputNumberView, uiInputView, uiIsRovingKey, uiItems, uiListKey, uiMenuItems, uiModalView, uiNumberStep, uiNumberValue, uiOverlaySync, uiPageWindow, uiPagination, uiPaginationView, uiPlace, uiPopoverView, uiProgressArc, uiProgressView, uiRadioGroupView, uiRange, uiRateCount, uiRateView, uiResultView, uiRovingFocus, uiRovingKey, uiSegmentedView, uiSelectItems, uiSelectView, uiSelectedKey, uiSkeletonView, uiSliderView, uiStatisticView, uiSteps, uiStepsView, uiSurfaceView, uiSwitchView, uiTabPanelView, uiTableView, uiTabsView, uiTagView, uiTextareaView, uiTimelineListView, uiToastDuration, uiToastView, uiToasterView, uiToneTile, uiTooltipView, uiTriggerAria, uiTriggerView, uiTypeahead, uiValue };
|
|
715
1529
|
//# sourceMappingURL=ui.js.map
|
|
716
1530
|
//# sourceMappingURL=ui.js.map
|