@silverpoint/core 0.3.0 → 0.7.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 +18 -0
- package/dist/catalog.d.ts +97 -0
- package/dist/catalog.js +8004 -0
- package/dist/catalog.js.map +1 -0
- package/dist/{chunk-I6BAZ7MJ.js → chunk-46QELMCG.js} +41 -236
- 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-E5CC2NNQ.js +172 -0
- 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-KFBSQH5G.js +34 -0
- package/dist/chunk-KFBSQH5G.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 +16 -60
- package/dist/index.js +34 -179
- package/dist/index.js.map +1 -1
- package/dist/model-DVVt59AB.d.ts +53 -0
- package/dist/palettes.d.ts +29 -0
- package/dist/palettes.js +79 -0
- package/dist/palettes.js.map +1 -0
- package/dist/{props-3G1XYd-r.d.ts → props-BZ9CcrGv.d.ts} +394 -2
- package/dist/timeline.d.ts +90 -0
- package/dist/timeline.js +125 -0
- package/dist/timeline.js.map +1 -0
- package/dist/{types-CbVMKvyQ.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 +933 -118
- package/dist/ui.js.map +1 -1
- package/dist/view-DteS9glE.d.ts +82 -0
- package/package.json +19 -1
- package/dist/chunk-I6BAZ7MJ.js.map +0 -1
package/dist/ui.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DEFAULTS } from './chunk-KFBSQH5G.js';
|
|
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';
|
|
2
11
|
|
|
3
12
|
// src/ui/catalog.ts
|
|
4
13
|
var BATCH = {
|
|
@@ -14,14 +23,17 @@ var BATCH = {
|
|
|
14
23
|
Slider: "B2",
|
|
15
24
|
Rate: "B2"
|
|
16
25
|
};
|
|
17
|
-
var row = (name, group, states) => Object.freeze({
|
|
26
|
+
var row = (name, group, states, family2 = "ui", batch = BATCH[name] ?? "B3") => Object.freeze({
|
|
18
27
|
name,
|
|
19
|
-
batch
|
|
28
|
+
batch,
|
|
20
29
|
slug: name.replace(/[A-Z]/g, (m, i) => (i ? "-" : "") + m.toLowerCase()),
|
|
21
30
|
component: `Sp${name}`,
|
|
22
31
|
group,
|
|
32
|
+
family: family2,
|
|
23
33
|
states: Object.freeze([...states])
|
|
24
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");
|
|
25
37
|
var UI_COMPONENTS = /* @__PURE__ */ Object.freeze([
|
|
26
38
|
row("Button", "actions", ["default", "primary", "danger", "disabled"]),
|
|
27
39
|
row("Input", "data-entry", ["empty", "filled", "invalid", "disabled"]),
|
|
@@ -39,13 +51,34 @@ var UI_COMPONENTS = /* @__PURE__ */ Object.freeze([
|
|
|
39
51
|
row("Divider", "data-display", ["plain", "text"]),
|
|
40
52
|
row("Progress", "feedback", ["line", "circle", "indeterminate"]),
|
|
41
53
|
row("Alert", "feedback", ["info", "success", "warning", "error"]),
|
|
42
|
-
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"])
|
|
43
76
|
]);
|
|
44
77
|
|
|
45
78
|
// src/ui/value.ts
|
|
46
79
|
var DEFAULT_RANGE = { min: 0, max: 100, step: 1 };
|
|
47
|
-
function warn(component, property,
|
|
48
|
-
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 });
|
|
49
82
|
}
|
|
50
83
|
var tidy = (x) => Number.parseFloat(x.toPrecision(12));
|
|
51
84
|
function uiRange(range, component = "UiValue") {
|
|
@@ -56,14 +89,14 @@ function uiRange(range, component = "UiValue") {
|
|
|
56
89
|
return DEFAULT_RANGE;
|
|
57
90
|
}
|
|
58
91
|
function uiValue(value, range, component = "UiValue") {
|
|
59
|
-
const
|
|
60
|
-
const { min, max, step } =
|
|
92
|
+
const valid2 = uiRange(range, component);
|
|
93
|
+
const { min, max, step } = valid2;
|
|
61
94
|
let next = Number.isFinite(value) ? Math.min(Math.max(value, min), max) : min;
|
|
62
95
|
if (step !== void 0) {
|
|
63
96
|
const steps = Math.min(Math.round((next - min) / step), Math.floor(tidy((max - min) / step)));
|
|
64
97
|
next = tidy(min + steps * step);
|
|
65
98
|
}
|
|
66
|
-
const corrected =
|
|
99
|
+
const corrected = valid2 !== range || next !== value;
|
|
67
100
|
if (next !== value) warn(component, "value", `${value} is drawn as ${next}.`);
|
|
68
101
|
return { value: next, fraction: round2((next - min) / (max - min)), corrected };
|
|
69
102
|
}
|
|
@@ -111,13 +144,13 @@ function uiSelectedKey(items, value, fallback) {
|
|
|
111
144
|
function uiSteps(items, current, component = "SpSteps") {
|
|
112
145
|
const steps = uiItems(items, component);
|
|
113
146
|
if (steps.length === 0) return [];
|
|
114
|
-
const
|
|
115
|
-
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;
|
|
116
149
|
if (at !== current && process.env.NODE_ENV !== "production") {
|
|
117
150
|
diagnose("SP017", component, { property: "current", message: `${current} is drawn as ${at}.` });
|
|
118
151
|
}
|
|
119
152
|
const statuses = steps.map((item, i) => item.status ?? (i < at ? "finish" : i === at ? "process" : "wait"));
|
|
120
|
-
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 }));
|
|
121
154
|
}
|
|
122
155
|
|
|
123
156
|
// src/ui/keyboard.ts
|
|
@@ -126,12 +159,12 @@ function direction(key, orientation, dir) {
|
|
|
126
159
|
const forward = key === "ArrowRight" ? 1 : key === "ArrowLeft" ? -1 : 0;
|
|
127
160
|
return dir === "rtl" ? -forward : forward;
|
|
128
161
|
}
|
|
129
|
-
function uiRovingKey(
|
|
130
|
-
const { index, count, disabled } =
|
|
131
|
-
const
|
|
162
|
+
function uiRovingKey(state2, key, orientation, dir) {
|
|
163
|
+
const { index, count, disabled } = state2;
|
|
164
|
+
const enabled2 = (i2) => disabled[i2] !== true;
|
|
132
165
|
if (key === "Home" || key === "End") {
|
|
133
166
|
const step2 = key === "Home" ? 1 : -1;
|
|
134
|
-
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;
|
|
135
168
|
return index;
|
|
136
169
|
}
|
|
137
170
|
const step = direction(key, orientation, dir);
|
|
@@ -139,7 +172,7 @@ function uiRovingKey(state, key, orientation, dir) {
|
|
|
139
172
|
let i = index < 0 || index >= count ? step > 0 ? -1 : count : index;
|
|
140
173
|
for (let n = 0; n < count; n++) {
|
|
141
174
|
i = ((i + step) % count + count) % count;
|
|
142
|
-
if (
|
|
175
|
+
if (enabled2(i)) return i;
|
|
143
176
|
}
|
|
144
177
|
return index;
|
|
145
178
|
}
|
|
@@ -197,13 +230,6 @@ function uiFrameOutline(kind) {
|
|
|
197
230
|
};
|
|
198
231
|
}
|
|
199
232
|
|
|
200
|
-
// src/ui/names.ts
|
|
201
|
-
function uiRequireName(component, text2, label) {
|
|
202
|
-
if (process.env.NODE_ENV === "production") return;
|
|
203
|
-
if (text2?.trim() || label?.trim()) return;
|
|
204
|
-
diagnose("SP018", component, { property: "label" });
|
|
205
|
-
}
|
|
206
|
-
|
|
207
233
|
// src/ui/tokens.ts
|
|
208
234
|
var UI_TOKEN_DEFAULTS = /* @__PURE__ */ Object.freeze({
|
|
209
235
|
frame: "css",
|
|
@@ -211,11 +237,14 @@ var UI_TOKEN_DEFAULTS = /* @__PURE__ */ Object.freeze({
|
|
|
211
237
|
controlHeight: Object.freeze({ sm: 24, md: 32, lg: 40 }),
|
|
212
238
|
radius: 2,
|
|
213
239
|
focusWidth: 2,
|
|
214
|
-
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
|
|
215
243
|
});
|
|
216
244
|
var MIN_HEIGHT = 24;
|
|
217
245
|
var MIN_FOCUS = 2;
|
|
218
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));
|
|
219
248
|
function resolveUiTokens(ground) {
|
|
220
249
|
const ui = ground.ui ?? UI_TOKEN_DEFAULTS;
|
|
221
250
|
const inked = ui.frame === "inked" && ground.tonalMechanism === "hatch";
|
|
@@ -230,7 +259,9 @@ function resolveUiTokens(ground) {
|
|
|
230
259
|
},
|
|
231
260
|
radius: within(ui.radius, 0, Infinity, 2),
|
|
232
261
|
focusWidth: within(ui.focusWidth, MIN_FOCUS, Infinity, 2),
|
|
233
|
-
tone: ui.tone
|
|
262
|
+
tone: ui.tone,
|
|
263
|
+
backdrop: level(ui.backdrop, 2),
|
|
264
|
+
rowTone: level(ui.rowTone, 1)
|
|
234
265
|
};
|
|
235
266
|
}
|
|
236
267
|
|
|
@@ -246,10 +277,10 @@ function family(gap, angle) {
|
|
|
246
277
|
const height = Math.abs(cos) < EPSILON ? lines * gap : lines * gap / Math.abs(cos);
|
|
247
278
|
const offset = (x, y) => -sin * x + cos * y;
|
|
248
279
|
const corners = [offset(0, 0), offset(width, 0), offset(0, height), offset(width, height)];
|
|
249
|
-
const
|
|
250
|
-
const
|
|
280
|
+
const first2 = Math.ceil(Math.min(...corners) / gap - 0.5);
|
|
281
|
+
const last2 = Math.floor(Math.max(...corners) / gap - 0.5);
|
|
251
282
|
const strokes = [];
|
|
252
|
-
for (let k =
|
|
283
|
+
for (let k = first2; k <= last2; k++) {
|
|
253
284
|
const c = (k + 0.5) * gap;
|
|
254
285
|
const at = (t) => ({ x: -sin * c + cos * t, y: cos * c + sin * t, t });
|
|
255
286
|
const hits = [
|
|
@@ -259,11 +290,11 @@ function family(gap, angle) {
|
|
|
259
290
|
const from = hits[0];
|
|
260
291
|
const to = hits.at(-1);
|
|
261
292
|
if (!from || !to || to.t - from.t < EPSILON * 1e3) continue;
|
|
262
|
-
const
|
|
293
|
+
const clamp2 = (v, hi) => round2(Math.min(Math.max(v, 0), hi));
|
|
263
294
|
const w = round2(width);
|
|
264
295
|
const h = round2(height);
|
|
265
296
|
strokes.push({
|
|
266
|
-
d: `M${
|
|
297
|
+
d: `M${clamp2(from.x, w)},${clamp2(from.y, h)}L${clamp2(to.x, w)},${clamp2(to.y, h)}`,
|
|
267
298
|
role: "ornament",
|
|
268
299
|
part: "ink"
|
|
269
300
|
});
|
|
@@ -277,75 +308,264 @@ function uiToneTile(spec) {
|
|
|
277
308
|
return layers;
|
|
278
309
|
}
|
|
279
310
|
|
|
280
|
-
// src/ui/
|
|
281
|
-
function
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
function
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
"
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
"
|
|
302
|
-
|
|
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;
|
|
303
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 };
|
|
304
361
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
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?.();
|
|
323
540
|
}
|
|
324
541
|
|
|
325
542
|
// src/ui/view.ts
|
|
326
543
|
var FRAME_SLOTS = 6;
|
|
327
544
|
function resolveUi(props, env) {
|
|
328
|
-
const { provider = {}, cell = {} } = env;
|
|
329
|
-
const ground = props.ground ??
|
|
545
|
+
const { provider = {}, cell: cell2 = {} } = env;
|
|
546
|
+
const ground = props.ground ?? cell2.ground ?? provider.ground ?? DEFAULTS.ground;
|
|
330
547
|
return {
|
|
331
548
|
ground: typeof ground === "string" ? ground : ground.name,
|
|
332
|
-
substrate: props.substrate ??
|
|
333
|
-
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,
|
|
334
551
|
size: props.size ?? "md",
|
|
335
|
-
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))
|
|
336
555
|
};
|
|
337
556
|
}
|
|
338
557
|
function uiButtonView(props, r, content) {
|
|
339
558
|
uiRequireName("SpButton", content.text, props.label);
|
|
340
559
|
const variant = props.variant ?? "default";
|
|
341
|
-
const
|
|
560
|
+
const href = safeHref(props.href, "SpButton");
|
|
561
|
+
const link = href !== void 0;
|
|
342
562
|
const toned = props.disabled ? "disabled" : variant === "default" ? void 0 : variant;
|
|
343
563
|
return el(
|
|
344
564
|
link ? "a" : "button",
|
|
345
565
|
root("button", props, r, {
|
|
346
566
|
id: props.id,
|
|
347
567
|
type: link ? void 0 : props.type ?? "button",
|
|
348
|
-
href: link && !props.disabled ?
|
|
568
|
+
href: link && !props.disabled ? href : void 0,
|
|
349
569
|
disabled: !link && props.disabled === true,
|
|
350
570
|
"aria-disabled": link && props.disabled ? "true" : void 0,
|
|
351
571
|
"aria-label": props.label,
|
|
@@ -360,14 +580,14 @@ function uiButtonView(props, r, content) {
|
|
|
360
580
|
]
|
|
361
581
|
);
|
|
362
582
|
}
|
|
363
|
-
function uiInputView(props, r,
|
|
583
|
+
function uiInputView(props, r, state2) {
|
|
364
584
|
const base = baseOf(props);
|
|
365
|
-
const
|
|
366
|
-
const messageId =
|
|
585
|
+
const message2 = props.message ? props.message : void 0;
|
|
586
|
+
const messageId = message2 && base ? `${base}--message` : void 0;
|
|
367
587
|
return el("span", root("input", props, r, { "data-invalid": props.invalid ? "true" : void 0 }), [
|
|
368
588
|
el("span", { class: "sp-ui-box" }, [
|
|
369
589
|
frame("control"),
|
|
370
|
-
...
|
|
590
|
+
...state2.prefix ? [el("span", { class: "sp-ui-affix", "data-slot": "prefix" }, [slot("prefix")])] : [],
|
|
371
591
|
el(
|
|
372
592
|
"input",
|
|
373
593
|
{
|
|
@@ -375,7 +595,7 @@ function uiInputView(props, r, state) {
|
|
|
375
595
|
id: props.id,
|
|
376
596
|
type: props.type ?? "text",
|
|
377
597
|
name: props.name,
|
|
378
|
-
value:
|
|
598
|
+
value: state2.value,
|
|
379
599
|
placeholder: props.placeholder,
|
|
380
600
|
disabled: props.disabled === true,
|
|
381
601
|
readonly: props.readOnly === true,
|
|
@@ -386,10 +606,10 @@ function uiInputView(props, r, state) {
|
|
|
386
606
|
[],
|
|
387
607
|
"native"
|
|
388
608
|
),
|
|
389
|
-
...
|
|
609
|
+
...state2.suffix ? [el("span", { class: "sp-ui-affix", "data-slot": "suffix" }, [slot("suffix")])] : [],
|
|
390
610
|
...props.invalid ? [glyph("warning")] : []
|
|
391
611
|
]),
|
|
392
|
-
...
|
|
612
|
+
...message2 ? [el("span", { class: "sp-ui-message", id: messageId }, [text(message2)])] : []
|
|
393
613
|
]);
|
|
394
614
|
}
|
|
395
615
|
function nativeCheckbox(props, checked, role) {
|
|
@@ -400,16 +620,16 @@ function nativeCheckbox(props, checked, role) {
|
|
|
400
620
|
"native"
|
|
401
621
|
);
|
|
402
622
|
}
|
|
403
|
-
function uiCheckboxView(props, r,
|
|
623
|
+
function uiCheckboxView(props, r, state2) {
|
|
404
624
|
return el("label", root("checkbox", props, r, { "data-indeterminate": props.indeterminate ? "true" : void 0 }), [
|
|
405
|
-
nativeCheckbox(props,
|
|
625
|
+
nativeCheckbox(props, state2.checked),
|
|
406
626
|
el("span", { class: "sp-ui-box", "aria-hidden": "true" }, [frame("box"), tone("selected", "box"), glyph("tick"), glyph("dash")]),
|
|
407
627
|
el("span", { class: "sp-ui-label" }, [text(props.label)])
|
|
408
628
|
]);
|
|
409
629
|
}
|
|
410
|
-
function uiSwitchView(props, r,
|
|
630
|
+
function uiSwitchView(props, r, state2) {
|
|
411
631
|
return el("label", root("switch", props, r), [
|
|
412
|
-
nativeCheckbox(props,
|
|
632
|
+
nativeCheckbox(props, state2.checked, "switch"),
|
|
413
633
|
el("span", { class: "sp-ui-track", "aria-hidden": "true" }, [frame("pill"), tone("selected", "pill"), el("span", { part: "sp-knob" })]),
|
|
414
634
|
el("span", { class: "sp-ui-label" }, [text(props.label)])
|
|
415
635
|
]);
|
|
@@ -425,7 +645,7 @@ function uiCardView(props, r, slots) {
|
|
|
425
645
|
frame("card"),
|
|
426
646
|
...header ? [
|
|
427
647
|
el("div", { class: "sp-ui-card-header" }, [
|
|
428
|
-
...titled ? [el(
|
|
648
|
+
...titled ? [el(headingTag(props.headingLevel, "SpCard"), { class: "sp-ui-card-title", id: titleId }, [text(props.title)])] : [],
|
|
429
649
|
...slots.extra ? [el("div", { class: "sp-ui-card-extra" }, [slot("extra")])] : []
|
|
430
650
|
]),
|
|
431
651
|
el("span", { part: "sp-rule", "aria-hidden": "true" })
|
|
@@ -453,11 +673,11 @@ function uiDividerView(props, r) {
|
|
|
453
673
|
|
|
454
674
|
// src/ui/view-b2.ts
|
|
455
675
|
var heighten = () => el("span", { part: "sp-heighten", "aria-hidden": "true" });
|
|
456
|
-
var legend = (
|
|
676
|
+
var legend = (label2, forSight) => el("legend", { class: forSight ? "sp-ui-legend" : "sp-ui-legend sp-ui-sr" }, [text(label2)]);
|
|
457
677
|
var groupName = (props) => props.name ?? (props.id ? `${props.id}--value` : void 0);
|
|
458
|
-
function uiRadioGroupView(props, r,
|
|
678
|
+
function uiRadioGroupView(props, r, state2) {
|
|
459
679
|
const items = uiItems(props.items, "SpRadioGroup");
|
|
460
|
-
const value = uiSelectedKey(items,
|
|
680
|
+
const value = uiSelectedKey(items, state2.value, "none");
|
|
461
681
|
return el("fieldset", root("radio-group", props, r, { id: props.id, "data-orientation": props.orientation ?? "vertical" }), [
|
|
462
682
|
legend(props.label, true),
|
|
463
683
|
...items.map(
|
|
@@ -475,9 +695,9 @@ function uiRadioGroupView(props, r, state) {
|
|
|
475
695
|
)
|
|
476
696
|
]);
|
|
477
697
|
}
|
|
478
|
-
function uiSegmentedView(props, r,
|
|
698
|
+
function uiSegmentedView(props, r, state2) {
|
|
479
699
|
const items = uiItems(props.items, "SpSegmented");
|
|
480
|
-
const value = uiSelectedKey(items,
|
|
700
|
+
const value = uiSelectedKey(items, state2.value, "first");
|
|
481
701
|
const name = groupName(props);
|
|
482
702
|
return el("fieldset", root("segmented", props, r, { id: props.id, "data-block": props.block ? "true" : void 0 }), [
|
|
483
703
|
legend(props.label, false),
|
|
@@ -496,9 +716,9 @@ function uiSegmentedView(props, r, state) {
|
|
|
496
716
|
])
|
|
497
717
|
]);
|
|
498
718
|
}
|
|
499
|
-
function uiTabsView(props, r,
|
|
719
|
+
function uiTabsView(props, r, state2) {
|
|
500
720
|
const items = uiItems(props.items, "SpTabs");
|
|
501
|
-
const value = uiSelectedKey(items,
|
|
721
|
+
const value = uiSelectedKey(items, state2.value, "first");
|
|
502
722
|
const vertical = props.orientation === "vertical";
|
|
503
723
|
const id = props.id;
|
|
504
724
|
return el("div", root("tabs", props, r, { id, "data-orientation": vertical ? "vertical" : "horizontal" }), [
|
|
@@ -542,11 +762,11 @@ function uiTabPanelView(props, tabs) {
|
|
|
542
762
|
[slot("content")]
|
|
543
763
|
);
|
|
544
764
|
}
|
|
545
|
-
function uiSliderView(props, r,
|
|
546
|
-
const
|
|
547
|
-
const { value, fraction } = uiValue(
|
|
548
|
-
const span =
|
|
549
|
-
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);
|
|
550
770
|
return el("label", root("slider", props, r, { style: `--sp-ui-fraction: ${fraction}`, "data-disabled": props.disabled ? "true" : void 0 }), [
|
|
551
771
|
el("span", { class: "sp-ui-label" }, [text(props.label)]),
|
|
552
772
|
el("span", { class: "sp-ui-rail" }, [
|
|
@@ -560,9 +780,9 @@ function uiSliderView(props, r, state) {
|
|
|
560
780
|
class: "sp-ui-range",
|
|
561
781
|
id: props.id,
|
|
562
782
|
name: props.name,
|
|
563
|
-
min: String(
|
|
564
|
-
max: String(
|
|
565
|
-
step: String(
|
|
783
|
+
min: String(valid2.min),
|
|
784
|
+
max: String(valid2.max),
|
|
785
|
+
step: String(valid2.step ?? 1),
|
|
566
786
|
value: String(value),
|
|
567
787
|
disabled: props.disabled === true
|
|
568
788
|
},
|
|
@@ -574,14 +794,14 @@ function uiSliderView(props, r, state) {
|
|
|
574
794
|
el(
|
|
575
795
|
"span",
|
|
576
796
|
{ class: "sp-ui-scale", "aria-hidden": "true" },
|
|
577
|
-
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))]))
|
|
578
798
|
)
|
|
579
799
|
] : []
|
|
580
800
|
]);
|
|
581
801
|
}
|
|
582
|
-
function uiRateView(props, r,
|
|
802
|
+
function uiRateView(props, r, state2) {
|
|
583
803
|
const count = uiRateCount(props.count);
|
|
584
|
-
const { value } = uiValue(
|
|
804
|
+
const { value } = uiValue(state2.value, { min: 0, max: count, step: 1 }, "SpRate");
|
|
585
805
|
const name = groupName(props);
|
|
586
806
|
const readOnly = props.readOnly === true;
|
|
587
807
|
return el(
|
|
@@ -607,7 +827,7 @@ function uiRateView(props, r, state) {
|
|
|
607
827
|
}
|
|
608
828
|
|
|
609
829
|
// src/ui/view-b3.ts
|
|
610
|
-
var closeButton = (
|
|
830
|
+
var closeButton = (label2) => el("button", { type: "button", class: "sp-ui-close", "aria-label": label2 }, [glyph("cross")], "close");
|
|
611
831
|
function uiStepsView(props, r) {
|
|
612
832
|
const steps = uiSteps(props.items, props.current);
|
|
613
833
|
const titles = new Map(props.items.map((item) => [item.key, item]));
|
|
@@ -630,13 +850,13 @@ function uiStepsView(props, r) {
|
|
|
630
850
|
);
|
|
631
851
|
}
|
|
632
852
|
function uiTagView(props, r, content) {
|
|
633
|
-
const
|
|
634
|
-
const
|
|
635
|
-
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 }), [
|
|
636
856
|
frame("control"),
|
|
637
|
-
tone(
|
|
857
|
+
tone(level2, "control"),
|
|
638
858
|
el("span", { class: "sp-ui-label sp-ui-plate" }, [slot("content")]),
|
|
639
|
-
...props.closable ? [closeButton(
|
|
859
|
+
...props.closable ? [closeButton(label2)] : []
|
|
640
860
|
]);
|
|
641
861
|
}
|
|
642
862
|
function uiBadgeView(props, r, content) {
|
|
@@ -683,7 +903,7 @@ function uiProgressView(props, r) {
|
|
|
683
903
|
);
|
|
684
904
|
}
|
|
685
905
|
var ALERT_GLYPHS = { info: "info", success: "tick", warning: "warning", error: "cross" };
|
|
686
|
-
function uiAlertView(props, r,
|
|
906
|
+
function uiAlertView(props, r, state2) {
|
|
687
907
|
const kind = props.kind ?? "info";
|
|
688
908
|
const error = kind === "error";
|
|
689
909
|
return el("div", root("alert", props, r, { id: props.id, role: error || kind === "warning" ? "alert" : "status", "data-kind": kind }), [
|
|
@@ -694,7 +914,7 @@ function uiAlertView(props, r, state) {
|
|
|
694
914
|
...props.title ? [el("div", { class: "sp-ui-alert-title" }, [text(props.title)])] : [],
|
|
695
915
|
el("div", { class: "sp-ui-alert-text" }, [slot("content")])
|
|
696
916
|
]),
|
|
697
|
-
...
|
|
917
|
+
...state2.closable ? [closeButton(props.closeLabel ?? "Close")] : []
|
|
698
918
|
]);
|
|
699
919
|
}
|
|
700
920
|
function uiSkeletonView(props, r) {
|
|
@@ -710,6 +930,601 @@ function uiSkeletonView(props, r) {
|
|
|
710
930
|
]);
|
|
711
931
|
}
|
|
712
932
|
|
|
713
|
-
|
|
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 };
|
|
714
1529
|
//# sourceMappingURL=ui.js.map
|
|
715
1530
|
//# sourceMappingURL=ui.js.map
|