vireuikit 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 +106 -4
- package/dist/chunk-VY5MD3CX.js +684 -0
- package/dist/chunk-VY5MD3CX.js.map +1 -0
- package/dist/context-DQaAcRq-.d.cts +104 -0
- package/dist/context-DQaAcRq-.d.ts +104 -0
- package/dist/index.cjs +751 -151
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +533 -98
- package/dist/index.d.ts +533 -98
- package/dist/index.js +250 -1
- package/dist/index.js.map +1 -1
- package/dist/web.cjs +1347 -83
- package/dist/web.cjs.map +1 -1
- package/dist/web.d.cts +39 -3
- package/dist/web.d.ts +39 -3
- package/dist/web.js +924 -37
- package/dist/web.js.map +1 -1
- package/package.json +1 -1
- package/dist/a11y-D3SS74I3.d.cts +0 -25
- package/dist/a11y-D3SS74I3.d.ts +0 -25
- package/dist/chunk-I3BD3XGC.js +0 -392
- package/dist/chunk-I3BD3XGC.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -27,135 +27,129 @@ function presentationFor(mode, wantsGlass) {
|
|
|
27
27
|
function sameA11y(a, b) {
|
|
28
28
|
return a.reduceTransparency === b.reduceTransparency && a.increaseContrast === b.increaseContrast && a.reduceMotion === b.reduceMotion;
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
};
|
|
36
|
-
function
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return 1;
|
|
42
|
-
default:
|
|
43
|
-
return 0;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
var DISABLED_PRESENCE = 0.25;
|
|
47
|
-
var HOVER_GAIN = 0.35;
|
|
48
|
-
function activation(state) {
|
|
49
|
-
if (state.disabled) return 0;
|
|
50
|
-
const clamp = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
|
|
51
|
-
return Math.max(clamp(state.selected), clamp(state.pressed), clamp(state.hovered) * HOVER_GAIN);
|
|
30
|
+
|
|
31
|
+
// src/kit/adaptive/classes.ts
|
|
32
|
+
var WIDTH_CLASSES = ["compact", "medium", "expanded", "large", "xlarge"];
|
|
33
|
+
var HEIGHT_CLASSES = ["compact", "medium", "expanded"];
|
|
34
|
+
var WIDTH_BREAKPOINTS = { medium: 600, expanded: 840, large: 1200, xlarge: 1600 };
|
|
35
|
+
var HEIGHT_BREAKPOINTS = { medium: 480, expanded: 900 };
|
|
36
|
+
function widthClass(width) {
|
|
37
|
+
if (!(width >= WIDTH_BREAKPOINTS.medium)) return "compact";
|
|
38
|
+
if (width < WIDTH_BREAKPOINTS.expanded) return "medium";
|
|
39
|
+
if (width < WIDTH_BREAKPOINTS.large) return "expanded";
|
|
40
|
+
return width < WIDTH_BREAKPOINTS.xlarge ? "large" : "xlarge";
|
|
52
41
|
}
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return { ...out, presence: out.presence * DISABLED_PRESENCE };
|
|
42
|
+
function heightClass(height) {
|
|
43
|
+
if (!(height >= HEIGHT_BREAKPOINTS.medium)) return "compact";
|
|
44
|
+
return height < HEIGHT_BREAKPOINTS.expanded ? "medium" : "expanded";
|
|
57
45
|
}
|
|
58
|
-
function
|
|
59
|
-
return
|
|
46
|
+
function classifyWindow(size) {
|
|
47
|
+
return { width: widthClass(size.width), height: heightClass(size.height) };
|
|
60
48
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
var FROST_LIFT = 0.26;
|
|
64
|
-
function atomBody(base, state = ATOM_AT_REST, frost = false) {
|
|
65
|
-
const on = activation(state);
|
|
66
|
-
const mix2 = (key) => REST_BODY[key] + (PRESSED_BODY[key] - REST_BODY[key]) * on;
|
|
67
|
-
let alpha = mix2("alpha");
|
|
68
|
-
let white = mix2("white");
|
|
69
|
-
let lift = mix2("lift");
|
|
70
|
-
if (state.disabled) alpha *= DISABLED_PRESENCE;
|
|
71
|
-
if (frost) {
|
|
72
|
-
const density = vireglass.applyAccessibility(vireglass.resolveOptics(base), {
|
|
73
|
-
reduceTransparency: true,
|
|
74
|
-
increaseContrast: false,
|
|
75
|
-
reduceMotion: false
|
|
76
|
-
}).bodyDensity;
|
|
77
|
-
alpha = Math.max(alpha, density);
|
|
78
|
-
white = 0;
|
|
79
|
-
lift = FROST_LIFT;
|
|
80
|
-
}
|
|
81
|
-
return { alpha, white, lift };
|
|
49
|
+
function widthAtLeast(value, minimum) {
|
|
50
|
+
return WIDTH_CLASSES.indexOf(value) >= WIDTH_CLASSES.indexOf(minimum);
|
|
82
51
|
}
|
|
83
52
|
|
|
84
|
-
// src/kit/
|
|
85
|
-
function
|
|
86
|
-
|
|
53
|
+
// src/kit/geometry.ts
|
|
54
|
+
function intersectRect(a, b) {
|
|
55
|
+
const x = Math.max(a.x, b.x);
|
|
56
|
+
const y = Math.max(a.y, b.y);
|
|
57
|
+
const right = Math.min(a.x + a.width, b.x + b.width);
|
|
58
|
+
const bottom = Math.min(a.y + a.height, b.y + b.height);
|
|
59
|
+
return right > x && bottom > y ? { x, y, width: right - x, height: bottom - y } : null;
|
|
87
60
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
function stepHover(event, canHover) {
|
|
91
|
-
return canHover && event.type === "enter";
|
|
61
|
+
function rectContains(outer, inner, tolerance = 0) {
|
|
62
|
+
return inner.x >= outer.x - tolerance && inner.y >= outer.y - tolerance && inner.x + inner.width <= outer.x + outer.width + tolerance && inner.y + inner.height <= outer.y + outer.height + tolerance;
|
|
92
63
|
}
|
|
93
64
|
|
|
94
|
-
// src/kit/
|
|
95
|
-
var
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
65
|
+
// src/kit/adaptive/context.ts
|
|
66
|
+
var INPUT_TOUCH = { primary: "coarse", anyCoarse: true, hover: false, keyboard: false };
|
|
67
|
+
var INPUT_POINTER = { primary: "fine", anyCoarse: false, hover: true, keyboard: true };
|
|
68
|
+
var INPUT_MIXED = { primary: "fine", anyCoarse: true, hover: true, keyboard: true };
|
|
69
|
+
var INPUT_TABLET_KEYBOARD = { primary: "coarse", anyCoarse: true, hover: true, keyboard: true };
|
|
70
|
+
var POSTURE_FLAT = { kind: "flat" };
|
|
71
|
+
function adaptiveContext(partial) {
|
|
72
|
+
return {
|
|
73
|
+
window: partial.window,
|
|
74
|
+
input: partial.input ?? INPUT_POINTER,
|
|
75
|
+
posture: partial.posture ?? POSTURE_FLAT,
|
|
76
|
+
reduceMotion: partial.reduceMotion ?? false
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function halfOpen(kind, window, options = {}) {
|
|
80
|
+
const band = Math.max(options.band ?? 0, 0);
|
|
81
|
+
const span = kind === "tabletop" ? window.height : window.width;
|
|
82
|
+
const at = options.at ?? span / 2;
|
|
83
|
+
const start = at - band / 2;
|
|
84
|
+
const bounds = kind === "tabletop" ? { x: 0, y: start, width: window.width, height: band } : { x: start, y: 0, width: band, height: window.height };
|
|
85
|
+
return { kind, fold: { bounds, occluding: options.occluding ?? band > 0 } };
|
|
86
|
+
}
|
|
87
|
+
function windowSegments(ctx) {
|
|
88
|
+
const { width, height } = ctx.window;
|
|
89
|
+
const whole = { x: 0, y: 0, width, height };
|
|
90
|
+
if (ctx.posture.kind === "flat") return [whole];
|
|
91
|
+
const { bounds, occluding } = ctx.posture.fold;
|
|
92
|
+
const tabletop = ctx.posture.kind === "tabletop";
|
|
93
|
+
const span = tabletop ? height : width;
|
|
94
|
+
const lo = Math.min(Math.max(tabletop ? bounds.y : bounds.x, 0), span);
|
|
95
|
+
const hi = Math.min(Math.max(lo + (tabletop ? bounds.height : bounds.width), lo), span);
|
|
96
|
+
const end = occluding ? lo : (lo + hi) / 2;
|
|
97
|
+
const start = occluding ? hi : (lo + hi) / 2;
|
|
98
|
+
const parts = tabletop ? [
|
|
99
|
+
{ x: 0, y: 0, width, height: end },
|
|
100
|
+
{ x: 0, y: start, width, height: height - start }
|
|
101
|
+
] : [
|
|
102
|
+
{ x: 0, y: 0, width: end, height },
|
|
103
|
+
{ x: start, y: 0, width: width - start, height }
|
|
104
|
+
];
|
|
105
|
+
const kept = parts.filter((r) => r.width > 0 && r.height > 0);
|
|
106
|
+
return kept.length ? kept : [whole];
|
|
107
|
+
}
|
|
108
|
+
function postureFromSegments(window, segments) {
|
|
109
|
+
if (segments.length !== 2) return POSTURE_FLAT;
|
|
110
|
+
const [a, b] = [...segments].sort((p, q) => p.x - q.x || p.y - q.y);
|
|
111
|
+
const gapX = b.x - (a.x + a.width);
|
|
112
|
+
if (gapX >= 0 && a.y < b.y + b.height && b.y < a.y + a.height) {
|
|
113
|
+
return { kind: "book", fold: { bounds: { x: a.x + a.width, y: 0, width: gapX, height: window.height }, occluding: gapX > 0 } };
|
|
114
|
+
}
|
|
115
|
+
const [top, bottom] = [...segments].sort((p, q) => p.y - q.y);
|
|
116
|
+
const gapY = bottom.y - (top.y + top.height);
|
|
117
|
+
if (gapY >= 0) {
|
|
118
|
+
return { kind: "tabletop", fold: { bounds: { x: 0, y: top.y + top.height, width: window.width, height: gapY }, occluding: gapY > 0 } };
|
|
108
119
|
}
|
|
120
|
+
return POSTURE_FLAT;
|
|
109
121
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
case "up":
|
|
124
|
-
case "cancel": {
|
|
125
|
-
const next = stepPress(state.press, event, !state.disabled);
|
|
126
|
-
return { state: { ...state, press: next.state }, activated: next.activated };
|
|
122
|
+
var area = (r) => r ? r.width * r.height : 0;
|
|
123
|
+
function segmentOf(box, segments) {
|
|
124
|
+
const cx = box.x + box.width / 2;
|
|
125
|
+
const cy = box.y + box.height / 2;
|
|
126
|
+
const holding = segments.find((s) => cx >= s.x && cx < s.x + s.width && cy >= s.y && cy < s.y + s.height);
|
|
127
|
+
if (holding) return holding;
|
|
128
|
+
let best;
|
|
129
|
+
let most = 0;
|
|
130
|
+
for (const s of segments) {
|
|
131
|
+
const overlap = area(intersectRect(s, box));
|
|
132
|
+
if (overlap > most) {
|
|
133
|
+
most = overlap;
|
|
134
|
+
best = s;
|
|
127
135
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
case "focus":
|
|
138
|
-
case "blur": {
|
|
139
|
-
const press = event.type === "blur" && state.press.by === "keyboard" ? PRESS_IDLE : state.press;
|
|
140
|
-
return {
|
|
141
|
-
state: { ...state, press, focused: !state.disabled && stepFocus(event) },
|
|
142
|
-
activated: false
|
|
143
|
-
};
|
|
136
|
+
}
|
|
137
|
+
if (best) return best;
|
|
138
|
+
let nearest;
|
|
139
|
+
let distance = Number.POSITIVE_INFINITY;
|
|
140
|
+
for (const s of segments) {
|
|
141
|
+
const d = Math.hypot(s.x + s.width / 2 - cx, s.y + s.height / 2 - cy);
|
|
142
|
+
if (d < distance) {
|
|
143
|
+
distance = d;
|
|
144
|
+
nearest = s;
|
|
144
145
|
}
|
|
145
|
-
case "disable":
|
|
146
|
-
return {
|
|
147
|
-
state: event.disabled ? { press: PRESS_IDLE, hovered: false, focused: false, disabled: true } : { ...state, disabled: false },
|
|
148
|
-
activated: false
|
|
149
|
-
};
|
|
150
146
|
}
|
|
147
|
+
return nearest;
|
|
151
148
|
}
|
|
152
|
-
function
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
focus: state.focused ? 1 : 0,
|
|
157
|
-
disabled: state.disabled
|
|
158
|
-
};
|
|
149
|
+
function surfaceRegion(ctx, source) {
|
|
150
|
+
const segments = windowSegments(ctx);
|
|
151
|
+
if (source) return segmentOf(source, segments) ?? segments[0];
|
|
152
|
+
return segments.reduce((best, s) => area(s) > area(best) ? s : best, segments[0]);
|
|
159
153
|
}
|
|
160
154
|
function stepSpring(s, dt, response, damping, instant = false) {
|
|
161
155
|
if (instant) {
|
|
@@ -190,8 +184,8 @@ var NECK_GAIN = 0.3;
|
|
|
190
184
|
var NECK_RAMP = 4;
|
|
191
185
|
var CORNER_EASE_START = 0.55;
|
|
192
186
|
var INK_OUT_END = 0.4;
|
|
193
|
-
var INK_IN_START = 0.
|
|
194
|
-
var INK_IN_END =
|
|
187
|
+
var INK_IN_START = 0.9;
|
|
188
|
+
var INK_IN_END = 1;
|
|
195
189
|
function growthInk(phase) {
|
|
196
190
|
const a = Math.min(Math.max(phase.shrink, 0), 1);
|
|
197
191
|
const b = Math.max(phase.grow, 0);
|
|
@@ -272,9 +266,9 @@ var growthPhase = (state) => ({
|
|
|
272
266
|
grow: state.grow.x
|
|
273
267
|
});
|
|
274
268
|
var DEFAULT_GROWTH_TIMING = {
|
|
275
|
-
shrinkOpen: 0.
|
|
276
|
-
shrinkClose: 0.
|
|
277
|
-
growOpen: 0.
|
|
269
|
+
shrinkOpen: 0.21,
|
|
270
|
+
shrinkClose: 0.14,
|
|
271
|
+
growOpen: 0.38,
|
|
278
272
|
growClose: 0.4,
|
|
279
273
|
growDampingOpen: 0.72
|
|
280
274
|
};
|
|
@@ -311,42 +305,46 @@ function stepGrowth(state, dt, open, reduceMotion = false, timing = DEFAULT_GROW
|
|
|
311
305
|
return movedShrink || movedGrow;
|
|
312
306
|
}
|
|
313
307
|
|
|
314
|
-
// src/kit/
|
|
315
|
-
var
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
var FOCUS = { response: 0.16, damping: 1 };
|
|
323
|
-
function stepControlVisual(visual, dt, state, instant = false) {
|
|
324
|
-
const t = controlTargets(state);
|
|
325
|
-
visual.pressed.target = t.pressed;
|
|
326
|
-
visual.hovered.target = t.hovered;
|
|
327
|
-
visual.focus.target = t.focus;
|
|
328
|
-
const a = stepSpring(visual.pressed, dt, PRESS.response, PRESS.damping, instant);
|
|
329
|
-
const b = stepSpring(visual.hovered, dt, HOVER.response, HOVER.damping, instant);
|
|
330
|
-
const c = stepSpring(visual.focus, dt, FOCUS.response, FOCUS.damping, instant);
|
|
331
|
-
return a || b || c;
|
|
308
|
+
// src/kit/adaptive/form-morph.ts
|
|
309
|
+
var HIDDEN = /* @__PURE__ */ new Set(["hidden", "closed", "none"]);
|
|
310
|
+
function formMorph(change, ctx, options = {}) {
|
|
311
|
+
const instant = ctx.reduceMotion;
|
|
312
|
+
if (options.anchorGone) return { ...change, mode: "retract", staysOpen: false, instant };
|
|
313
|
+
if (change.from === change.to) return { ...change, mode: "none", staysOpen: true, instant };
|
|
314
|
+
const mode = HIDDEN.has(change.from) ? "appear" : HIDDEN.has(change.to) ? "disappear" : "reshape";
|
|
315
|
+
return { ...change, mode, staysOpen: mode !== "disappear", instant };
|
|
332
316
|
}
|
|
333
|
-
|
|
317
|
+
var FORM_MORPH_TIMING = { response: DEFAULT_GROWTH_TIMING.growOpen, damping: 1 };
|
|
318
|
+
var createFormMorph = () => ({ t: { x: 0, v: 0, target: 0 }, fromInk: 1 });
|
|
319
|
+
function stepFormMorph(state, dt, toward, instant = false) {
|
|
320
|
+
state.t.target = toward;
|
|
321
|
+
return stepSpring(state.t, dt, FORM_MORPH_TIMING.response, FORM_MORPH_TIMING.damping, instant);
|
|
322
|
+
}
|
|
323
|
+
var OUT_END = 0.45;
|
|
324
|
+
var IN_START = 0.55;
|
|
325
|
+
function formMorphFrame(from, to, state) {
|
|
326
|
+
const t = Math.min(Math.max(state.t.x, 0), 1);
|
|
327
|
+
const mix2 = (a, b) => a + (b - a) * t;
|
|
334
328
|
return {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
329
|
+
box: {
|
|
330
|
+
x: mix2(from.x, to.x),
|
|
331
|
+
y: mix2(from.y, to.y),
|
|
332
|
+
width: mix2(from.width, to.width),
|
|
333
|
+
height: mix2(from.height, to.height),
|
|
334
|
+
radius: mix2(from.radius, to.radius)
|
|
335
|
+
},
|
|
336
|
+
ink: inkAt(state, t),
|
|
337
|
+
showing: t < 0.5 ? "from" : "to"
|
|
339
338
|
};
|
|
340
339
|
}
|
|
341
|
-
function
|
|
342
|
-
|
|
340
|
+
function inkAt(state, t) {
|
|
341
|
+
return { outgoing: (state.fromInk ?? 1) * (1 - smoothstep(0, OUT_END, t)), incoming: smoothstep(IN_START, 1, t) };
|
|
343
342
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return atomLift(kind) === 1 ? LIFTING : SINKING;
|
|
343
|
+
function rebaseFormMorph(state) {
|
|
344
|
+
const t = Math.min(Math.max(state.t.x, 0), 1);
|
|
345
|
+
const ink = inkAt(state, t);
|
|
346
|
+
state.fromInk = t < 0.5 ? ink.outgoing : ink.incoming;
|
|
347
|
+
state.t = { x: 0, v: 0, target: 0 };
|
|
350
348
|
}
|
|
351
349
|
var CONTROL_SIZES = ["touch", "small", "medium", "large", "xlarge"];
|
|
352
350
|
var MIN_TOUCH_TARGET_DP = 44;
|
|
@@ -376,6 +374,19 @@ function iconButtonSize(size) {
|
|
|
376
374
|
const spec = BUTTON_SIZES[size];
|
|
377
375
|
return { ...spec, width: spec.height, paddingX: 0 };
|
|
378
376
|
}
|
|
377
|
+
var MENU_PADDING = 0.3;
|
|
378
|
+
function menuSize(size) {
|
|
379
|
+
const spec = BUTTON_SIZES[size];
|
|
380
|
+
const padding = Math.round(spec.height * MENU_PADDING);
|
|
381
|
+
return {
|
|
382
|
+
row: spec.height,
|
|
383
|
+
padding,
|
|
384
|
+
itemRadius: spec.radius,
|
|
385
|
+
radius: spec.radius + padding,
|
|
386
|
+
icon: spec.icon,
|
|
387
|
+
labelPad: spec.paddingX
|
|
388
|
+
};
|
|
389
|
+
}
|
|
379
390
|
function nestedRadius(outerRadius, inset, minimum = 0) {
|
|
380
391
|
return vireglass.concentricRadius(outerRadius, inset, minimum);
|
|
381
392
|
}
|
|
@@ -389,45 +400,634 @@ function minTarget(input) {
|
|
|
389
400
|
return input.touch ? MIN_TOUCH_TARGET_DP : MIN_POINTER_TARGET_DP;
|
|
390
401
|
}
|
|
391
402
|
|
|
403
|
+
// src/kit/adaptive/input.ts
|
|
404
|
+
function sizeTier(input) {
|
|
405
|
+
return defaultSize({ touch: input.primary === "coarse" });
|
|
406
|
+
}
|
|
407
|
+
function hitTarget(input) {
|
|
408
|
+
return minTarget({ touch: input.anyCoarse });
|
|
409
|
+
}
|
|
410
|
+
function hoversWith(pointerType) {
|
|
411
|
+
return pointerType !== "touch";
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// src/kit/adaptive/navigation.ts
|
|
415
|
+
var BAR_SLOTS = 5;
|
|
416
|
+
function formFor(ctx, spec) {
|
|
417
|
+
const { width, height } = classifyWindow(ctx.window);
|
|
418
|
+
if (ctx.posture.kind === "tabletop") return "bar";
|
|
419
|
+
if (widthAtLeast(width, "large")) return spec.sidebarCollapsed ? "rail" : "sidebar";
|
|
420
|
+
if (height === "compact") return "rail";
|
|
421
|
+
if (width === "compact") return "bar";
|
|
422
|
+
if (width === "medium" && (spec.panes ?? 1) > 1 && ctx.posture.kind !== "book") return "bar";
|
|
423
|
+
return "rail";
|
|
424
|
+
}
|
|
425
|
+
function navigationForm(ctx, spec) {
|
|
426
|
+
const form = formFor(ctx, spec);
|
|
427
|
+
const width = classifyWindow(ctx.window).width;
|
|
428
|
+
const large = widthAtLeast(width, "large");
|
|
429
|
+
const slots = BAR_SLOTS - (spec.search ? 1 : 0);
|
|
430
|
+
const primary = Math.max(0, Math.min(spec.primary, slots));
|
|
431
|
+
const secondary = Math.max(0, spec.secondary ?? 0) + Math.max(0, spec.primary - primary);
|
|
432
|
+
let search = null;
|
|
433
|
+
if (spec.search) {
|
|
434
|
+
const shortcut = large || ctx.input.keyboard;
|
|
435
|
+
if (large) search = { form: "field", place: form === "sidebar" ? "sidebar" : "toolbar", shortcut };
|
|
436
|
+
else search = form === "bar" ? { form: "button", place: "bar", shortcut } : { form: "item", place: "rail", shortcut };
|
|
437
|
+
}
|
|
438
|
+
return {
|
|
439
|
+
form,
|
|
440
|
+
edge: form === "bar" ? "bottom" : "leading",
|
|
441
|
+
primary,
|
|
442
|
+
secondary,
|
|
443
|
+
secondaryVisible: form === "sidebar",
|
|
444
|
+
search,
|
|
445
|
+
expandable: form !== "rail" ? null : large ? "beside" : width === "expanded" ? "over" : null,
|
|
446
|
+
collapsible: form === "sidebar"
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
function bottomAccessory(nav, state = {}) {
|
|
450
|
+
if (nav.form !== "bar") return { placement: "content-bottom", compact: false };
|
|
451
|
+
return state.barMinimized ? { placement: "in-bar", compact: true } : { placement: "above-bar", compact: false };
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// src/kit/adaptive/panes.ts
|
|
455
|
+
var LIST_PANE_WIDTH = { expanded: 360, large: 412 };
|
|
456
|
+
var SUPPORTING_PANE_MAX_WIDTH = 400;
|
|
457
|
+
function splitFor(ctx, sparse) {
|
|
458
|
+
const { width, height } = classifyWindow(ctx.window);
|
|
459
|
+
if (ctx.posture.kind === "book") return { kind: "fold", gap: ctx.posture.fold.bounds };
|
|
460
|
+
if (height === "compact") return null;
|
|
461
|
+
if (widthAtLeast(width, "large")) return { kind: "fixed", list: LIST_PANE_WIDTH.large };
|
|
462
|
+
if (width === "expanded") return { kind: "fixed", list: LIST_PANE_WIDTH.expanded };
|
|
463
|
+
return width === "medium" && sparse ? { kind: "half" } : null;
|
|
464
|
+
}
|
|
465
|
+
function paneLayout(ctx, state) {
|
|
466
|
+
const split = splitFor(ctx, state.sparse ?? false);
|
|
467
|
+
if (split) {
|
|
468
|
+
return { panes: 2, visible: ["list", "detail"], split, placeholder: !state.selected, back: false, selectionShown: state.selected };
|
|
469
|
+
}
|
|
470
|
+
const detail = state.selected && state.showing === "detail";
|
|
471
|
+
return { panes: 1, visible: [detail ? "detail" : "list"], split: null, placeholder: false, back: detail, selectionShown: false };
|
|
472
|
+
}
|
|
473
|
+
function supportingPane(ctx, state) {
|
|
474
|
+
const width = classifyWindow(ctx.window).width;
|
|
475
|
+
const base = { edge: "trailing", maxWidth: SUPPORTING_PANE_MAX_WIDTH, remembered: state.pinned };
|
|
476
|
+
if (widthAtLeast(width, "large")) return { ...base, form: state.pinned || state.open ? "beside" : "hidden", scrim: false };
|
|
477
|
+
if (width === "expanded" && state.open) return { ...base, form: "over", scrim: true };
|
|
478
|
+
return { ...base, form: "hidden", scrim: false };
|
|
479
|
+
}
|
|
480
|
+
function postureSplit(ctx) {
|
|
481
|
+
if (ctx.posture.kind === "flat") return { kind: "single" };
|
|
482
|
+
const segments = windowSegments(ctx);
|
|
483
|
+
if (segments.length < 2) return { kind: "single" };
|
|
484
|
+
return { kind: "split", axis: ctx.posture.kind === "tabletop" ? "horizontal" : "vertical", primary: segments[0], secondary: segments[1] };
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// src/kit/adaptive/presentation.ts
|
|
488
|
+
var SURFACE_KINDS = ["menu", "picker", "popover", "sheet", "modal-sheet", "alert", "dialog"];
|
|
489
|
+
var BOTTOM_SHEET_MAX_WIDTH = 640;
|
|
490
|
+
var SIDE_SHEET_MAX_WIDTH = 400;
|
|
491
|
+
var DIALOG_MAX_WIDTH = 560;
|
|
492
|
+
function baseForm(kind, ctx) {
|
|
493
|
+
const { width, height } = classifyWindow(ctx.window);
|
|
494
|
+
const compactWidth = width === "compact";
|
|
495
|
+
const plain = { fromSource: false, scrim: false, compresses: false, maxWidth: null };
|
|
496
|
+
const sheet = (form) => height === "compact" ? { ...plain, form: "full-screen", scrim: true } : form;
|
|
497
|
+
switch (kind) {
|
|
498
|
+
case "menu":
|
|
499
|
+
return { ...plain, form: "grown", fromSource: true };
|
|
500
|
+
case "popover":
|
|
501
|
+
return compactWidth ? sheet({ ...plain, form: "bottom-sheet", fromSource: true, scrim: true }) : { ...plain, form: "popover", fromSource: true };
|
|
502
|
+
case "picker":
|
|
503
|
+
case "modal-sheet":
|
|
504
|
+
return sheet(
|
|
505
|
+
compactWidth ? { ...plain, form: "bottom-sheet", scrim: true } : { ...plain, form: "centered-sheet", scrim: true, maxWidth: DIALOG_MAX_WIDTH }
|
|
506
|
+
);
|
|
507
|
+
case "sheet":
|
|
508
|
+
if (width === "xlarge") return { ...plain, form: "side-pane", compresses: true, maxWidth: SIDE_SHEET_MAX_WIDTH };
|
|
509
|
+
if (widthAtLeast(width, "expanded")) return { ...plain, form: "side-sheet", compresses: true, maxWidth: SIDE_SHEET_MAX_WIDTH };
|
|
510
|
+
return sheet({ ...plain, form: "bottom-sheet", maxWidth: compactWidth ? null : BOTTOM_SHEET_MAX_WIDTH });
|
|
511
|
+
case "alert":
|
|
512
|
+
return { ...plain, form: "alert", scrim: true, maxWidth: DIALOG_MAX_WIDTH };
|
|
513
|
+
case "dialog":
|
|
514
|
+
return compactWidth ? { ...plain, form: "full-screen", scrim: true } : { ...plain, form: "basic-dialog", scrim: true, maxWidth: DIALOG_MAX_WIDTH };
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
function presentationForm(kind, ctx, source) {
|
|
518
|
+
const base = baseForm(kind, ctx);
|
|
519
|
+
const side = base.form === "side-sheet" || base.form === "side-pane";
|
|
520
|
+
const region = side && ctx.posture.kind === "book" ? windowSegments(ctx).at(-1) : surfaceRegion(ctx, source);
|
|
521
|
+
return { ...base, region };
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// src/kit/adaptive/toolbar.ts
|
|
525
|
+
var TOOLBAR_GAP = 8;
|
|
526
|
+
var MORE_ID = "\u2026";
|
|
527
|
+
function toolbarPlacement(ctx) {
|
|
528
|
+
const { width, height } = classifyWindow(ctx.window);
|
|
529
|
+
if (height === "compact") {
|
|
530
|
+
return { edge: "trailing", orientation: "vertical", maxGroups: Number.POSITIVE_INFINITY };
|
|
531
|
+
}
|
|
532
|
+
if (width === "compact") return { edge: "bottom", orientation: "horizontal", maxGroups: 3 };
|
|
533
|
+
return { edge: "top", orientation: "horizontal", maxGroups: Number.POSITIVE_INFINITY };
|
|
534
|
+
}
|
|
535
|
+
function toolbarLayout(items, options) {
|
|
536
|
+
const orientation = options.orientation ?? "horizontal";
|
|
537
|
+
const gap = options.gap ?? TOOLBAR_GAP;
|
|
538
|
+
const maxGroups = options.maxGroups ?? Number.POSITIVE_INFINITY;
|
|
539
|
+
const side = BUTTON_SIZES[options.tier].height;
|
|
540
|
+
const vertical = orientation === "vertical";
|
|
541
|
+
const aside = vertical ? items.filter((i) => i.kind === "text").map((i) => i.id) : [];
|
|
542
|
+
const pool = items.map((item, index) => ({ item, index })).filter((e) => !vertical || e.item.kind === "icon");
|
|
543
|
+
const extentOf = (item) => item.kind === "icon" ? side : item.width ?? 3 * side;
|
|
544
|
+
const lay = (visible2, merge, more) => {
|
|
545
|
+
const ordered = [...visible2.filter((e) => !e.item.primary)];
|
|
546
|
+
const capsules = [];
|
|
547
|
+
let open = null;
|
|
548
|
+
const close = () => {
|
|
549
|
+
if (open) capsules.push({ kind: open.kind, items: open.items, extent: open.extent });
|
|
550
|
+
open = null;
|
|
551
|
+
};
|
|
552
|
+
for (const { item } of ordered) {
|
|
553
|
+
const kind = item.kind;
|
|
554
|
+
const group = item.group ?? `kind:${kind}`;
|
|
555
|
+
if (merge && open && open.kind === kind && open.group === group) {
|
|
556
|
+
open.items.push(item.id);
|
|
557
|
+
open.extent += extentOf(item);
|
|
558
|
+
} else {
|
|
559
|
+
close();
|
|
560
|
+
open = { kind, group, items: [item.id], extent: extentOf(item) };
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
close();
|
|
564
|
+
if (more) capsules.push({ kind: "more", items: [MORE_ID], extent: side });
|
|
565
|
+
for (const { item } of visible2) if (item.primary) capsules.push({ kind: "primary", items: [item.id], extent: extentOf(item) });
|
|
566
|
+
const extent = capsules.reduce((sum, c) => sum + c.extent, 0) + gap * Math.max(capsules.length - 1, 0);
|
|
567
|
+
return { capsules, extent, fits: extent <= options.available && capsules.length <= maxGroups };
|
|
568
|
+
};
|
|
569
|
+
const done = (stage, laid2, overflow) => ({
|
|
570
|
+
orientation,
|
|
571
|
+
stage,
|
|
572
|
+
capsules: laid2.capsules,
|
|
573
|
+
overflow,
|
|
574
|
+
aside,
|
|
575
|
+
extent: laid2.extent,
|
|
576
|
+
fits: laid2.fits
|
|
577
|
+
});
|
|
578
|
+
const separate = lay(pool, false, false);
|
|
579
|
+
if (separate.fits) return done("separate", separate, []);
|
|
580
|
+
const merged = lay(pool, true, false);
|
|
581
|
+
if (merged.fits) return done("merged", merged, []);
|
|
582
|
+
const candidates = pool.filter((e) => !e.item.badge && !e.item.primary).sort((a, b) => (a.item.priority ?? 0) - (b.item.priority ?? 0) || b.index - a.index);
|
|
583
|
+
let visible = pool;
|
|
584
|
+
const hidden = [];
|
|
585
|
+
let laid = merged;
|
|
586
|
+
for (const candidate of candidates) {
|
|
587
|
+
visible = visible.filter((e) => e !== candidate);
|
|
588
|
+
hidden.push(candidate);
|
|
589
|
+
laid = lay(visible, true, true);
|
|
590
|
+
if (laid.fits) break;
|
|
591
|
+
}
|
|
592
|
+
if (!hidden.length) return done("merged", merged, []);
|
|
593
|
+
return done("overflow", laid, hidden.sort((a, b) => a.index - b.index).map((e) => e.item.id));
|
|
594
|
+
}
|
|
595
|
+
var ATOM_AT_REST = {
|
|
596
|
+
pressed: 0,
|
|
597
|
+
hovered: 0,
|
|
598
|
+
selected: 0,
|
|
599
|
+
disabled: false
|
|
600
|
+
};
|
|
601
|
+
function atomLift(kind) {
|
|
602
|
+
switch (kind) {
|
|
603
|
+
case "iconButton":
|
|
604
|
+
case "switch":
|
|
605
|
+
case "slider":
|
|
606
|
+
return 1;
|
|
607
|
+
default:
|
|
608
|
+
return 0;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
var DISABLED_PRESENCE = 0.25;
|
|
612
|
+
var HOVER_GAIN = 0.35;
|
|
613
|
+
function activation(state) {
|
|
614
|
+
if (state.disabled) return 0;
|
|
615
|
+
const clamp2 = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
|
|
616
|
+
return Math.max(clamp2(state.selected), clamp2(state.pressed), clamp2(state.hovered) * HOVER_GAIN);
|
|
617
|
+
}
|
|
618
|
+
function atomMaterial(base, kind, state = ATOM_AT_REST) {
|
|
619
|
+
const out = vireglass.activeMaterial(base, activation(state));
|
|
620
|
+
if (!state.disabled) return out;
|
|
621
|
+
return { ...out, presence: out.presence * DISABLED_PRESENCE };
|
|
622
|
+
}
|
|
623
|
+
function atomAtRest(state) {
|
|
624
|
+
return state.pressed === 0 && state.hovered === 0 && state.selected === 0 && state.disabled === false;
|
|
625
|
+
}
|
|
626
|
+
var REST_BODY = { alpha: 0.25, white: 0.15, lift: 0.1 };
|
|
627
|
+
var PRESSED_BODY = { alpha: 0.34, white: 0.35, lift: 0 };
|
|
628
|
+
var FROST_LIFT = 0.26;
|
|
629
|
+
function atomBody(base, state = ATOM_AT_REST, frost = false) {
|
|
630
|
+
const on = activation(state);
|
|
631
|
+
const mix2 = (key) => REST_BODY[key] + (PRESSED_BODY[key] - REST_BODY[key]) * on;
|
|
632
|
+
let alpha = mix2("alpha");
|
|
633
|
+
let white = mix2("white");
|
|
634
|
+
let lift = mix2("lift");
|
|
635
|
+
if (state.disabled) alpha *= DISABLED_PRESENCE;
|
|
636
|
+
if (frost) {
|
|
637
|
+
const density = vireglass.applyAccessibility(vireglass.resolveOptics(base), {
|
|
638
|
+
reduceTransparency: true,
|
|
639
|
+
increaseContrast: false,
|
|
640
|
+
reduceMotion: false
|
|
641
|
+
}).bodyDensity;
|
|
642
|
+
alpha = Math.max(alpha, density);
|
|
643
|
+
white = 0;
|
|
644
|
+
lift = FROST_LIFT;
|
|
645
|
+
}
|
|
646
|
+
return { alpha, white, lift };
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// src/kit/behavior/focus.ts
|
|
650
|
+
function stepFocus(event) {
|
|
651
|
+
return event.type === "focus" && event.visible;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// src/kit/behavior/hover.ts
|
|
655
|
+
function stepHover(event, canHover) {
|
|
656
|
+
return canHover && event.type === "enter";
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// src/kit/behavior/press.ts
|
|
660
|
+
var PRESS_IDLE = { by: null };
|
|
661
|
+
function stepPress(state, event, enabled2) {
|
|
662
|
+
switch (event.type) {
|
|
663
|
+
case "down":
|
|
664
|
+
if (!enabled2 || state.by !== null) return { state, activated: false };
|
|
665
|
+
return { state: { by: event.source }, activated: false };
|
|
666
|
+
case "up":
|
|
667
|
+
if (state.by !== event.source) return { state, activated: false };
|
|
668
|
+
return { state: PRESS_IDLE, activated: enabled2 };
|
|
669
|
+
case "cancel":
|
|
670
|
+
return { state: PRESS_IDLE, activated: false };
|
|
671
|
+
case "leave":
|
|
672
|
+
return state.by === "pointer" ? { state: PRESS_IDLE, activated: false } : { state, activated: false };
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// src/kit/behavior/control.ts
|
|
677
|
+
var TOUCH_INPUT = { hover: false };
|
|
678
|
+
var POINTER_INPUT = { hover: true };
|
|
679
|
+
var CONTROL_IDLE = {
|
|
680
|
+
press: PRESS_IDLE,
|
|
681
|
+
hovered: false,
|
|
682
|
+
focused: false,
|
|
683
|
+
disabled: false
|
|
684
|
+
};
|
|
685
|
+
function stepControl(state, event, caps) {
|
|
686
|
+
switch (event.type) {
|
|
687
|
+
case "down":
|
|
688
|
+
case "up":
|
|
689
|
+
case "cancel": {
|
|
690
|
+
const next = stepPress(state.press, event, !state.disabled);
|
|
691
|
+
return { state: { ...state, press: next.state }, activated: next.activated };
|
|
692
|
+
}
|
|
693
|
+
case "leave": {
|
|
694
|
+
const next = stepPress(state.press, event, !state.disabled);
|
|
695
|
+
return { state: { ...state, press: next.state, hovered: false }, activated: false };
|
|
696
|
+
}
|
|
697
|
+
case "enter":
|
|
698
|
+
return {
|
|
699
|
+
state: { ...state, hovered: !state.disabled && stepHover(event, caps.hover) },
|
|
700
|
+
activated: false
|
|
701
|
+
};
|
|
702
|
+
case "focus":
|
|
703
|
+
case "blur": {
|
|
704
|
+
const press = event.type === "blur" && state.press.by === "keyboard" ? PRESS_IDLE : state.press;
|
|
705
|
+
return {
|
|
706
|
+
state: { ...state, press, focused: !state.disabled && stepFocus(event) },
|
|
707
|
+
activated: false
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
case "disable":
|
|
711
|
+
return {
|
|
712
|
+
state: event.disabled ? { press: PRESS_IDLE, hovered: false, focused: false, disabled: true } : { ...state, disabled: false },
|
|
713
|
+
activated: false
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
function controlTargets(state) {
|
|
718
|
+
return {
|
|
719
|
+
pressed: state.press.by !== null ? 1 : 0,
|
|
720
|
+
hovered: state.hovered ? 1 : 0,
|
|
721
|
+
focus: state.focused ? 1 : 0,
|
|
722
|
+
disabled: state.disabled
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// src/kit/behavior/visual.ts
|
|
727
|
+
var createControlVisual = () => ({
|
|
728
|
+
pressed: { x: 0, v: 0, target: 0 },
|
|
729
|
+
hovered: { x: 0, v: 0, target: 0 },
|
|
730
|
+
focus: { x: 0, v: 0, target: 0 }
|
|
731
|
+
});
|
|
732
|
+
var PRESS = { response: 0.18, damping: 0.78 };
|
|
733
|
+
var HOVER = { response: 0.22, damping: 1 };
|
|
734
|
+
var FOCUS = { response: 0.16, damping: 1 };
|
|
735
|
+
function stepControlVisual(visual, dt, state, instant = false) {
|
|
736
|
+
const t = controlTargets(state);
|
|
737
|
+
visual.pressed.target = t.pressed;
|
|
738
|
+
visual.hovered.target = t.hovered;
|
|
739
|
+
visual.focus.target = t.focus;
|
|
740
|
+
const a = stepSpring(visual.pressed, dt, PRESS.response, PRESS.damping, instant);
|
|
741
|
+
const b = stepSpring(visual.hovered, dt, HOVER.response, HOVER.damping, instant);
|
|
742
|
+
const c = stepSpring(visual.focus, dt, FOCUS.response, FOCUS.damping, instant);
|
|
743
|
+
return a || b || c;
|
|
744
|
+
}
|
|
745
|
+
function visualAtomState(visual, state) {
|
|
746
|
+
return {
|
|
747
|
+
pressed: visual.pressed.x,
|
|
748
|
+
hovered: visual.hovered.x,
|
|
749
|
+
selected: 0,
|
|
750
|
+
disabled: state.disabled
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
function settleControlVisual(visual, state) {
|
|
754
|
+
stepControlVisual(visual, 0, state, true);
|
|
755
|
+
}
|
|
756
|
+
var MENU_CLOSED = { open: false, active: -1, typed: "", typedAt: Number.NEGATIVE_INFINITY };
|
|
757
|
+
var TYPEAHEAD_SECONDS = 0.5;
|
|
758
|
+
var exists = (items, i) => i >= 0 && i < items.length;
|
|
759
|
+
var enabled = (items, i) => exists(items, i) && !items[i].disabled;
|
|
760
|
+
var reachable = (items, i) => exists(items, i) && (items[i].focusable ?? !items[i].disabled);
|
|
761
|
+
function seek(items, from, step) {
|
|
762
|
+
const n = items.length;
|
|
763
|
+
for (let k = 1; k <= n; k += 1) {
|
|
764
|
+
const i = ((from + step * k) % n + n) % n;
|
|
765
|
+
if (reachable(items, i)) return i;
|
|
766
|
+
}
|
|
767
|
+
return -1;
|
|
768
|
+
}
|
|
769
|
+
var first = (items) => seek(items, -1, 1);
|
|
770
|
+
var last = (items) => seek(items, items.length, -1);
|
|
771
|
+
var toItem = (index) => index < 0 ? { to: "menu" } : { to: "item", index };
|
|
772
|
+
function typeahead(state, items, key, at) {
|
|
773
|
+
const fresh = at - state.typedAt > TYPEAHEAD_SECONDS;
|
|
774
|
+
const typed = (fresh ? "" : state.typed) + key.toLowerCase();
|
|
775
|
+
const repeated = typed.length > 1 && [...typed].every((c) => c === typed[0]);
|
|
776
|
+
const needle = repeated ? typed[0] : typed;
|
|
777
|
+
const start = needle.length > 1 ? state.active - 1 : state.active;
|
|
778
|
+
const n = items.length;
|
|
779
|
+
for (let k = 1; k <= n; k += 1) {
|
|
780
|
+
const i = ((start + k) % n + n) % n;
|
|
781
|
+
if (reachable(items, i) && items[i].label.trim().toLowerCase().startsWith(needle)) {
|
|
782
|
+
return { state: { ...state, active: i, typed, typedAt: at }, focus: { to: "item", index: i }, chosen: null };
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
return { state: { ...state, typed, typedAt: at }, focus: { to: "stay" }, chosen: null };
|
|
786
|
+
}
|
|
787
|
+
function stepMenu(state, event, items) {
|
|
788
|
+
const stay = { state, focus: { to: "stay" }, chosen: null };
|
|
789
|
+
if (event.type === "open") {
|
|
790
|
+
const active = event.focus === "first" ? first(items) : event.focus === "last" ? last(items) : -1;
|
|
791
|
+
return { state: { ...MENU_CLOSED, open: true, active }, focus: toItem(active), chosen: null };
|
|
792
|
+
}
|
|
793
|
+
if (!state.open) return stay;
|
|
794
|
+
switch (event.type) {
|
|
795
|
+
case "move": {
|
|
796
|
+
const active = event.to === "first" ? first(items) : event.to === "last" ? last(items) : seek(items, state.active < 0 && event.to === "previous" ? items.length : state.active, event.to === "next" ? 1 : -1);
|
|
797
|
+
if (active < 0) return stay;
|
|
798
|
+
return { state: { ...state, active, typed: "" }, focus: { to: "item", index: active }, chosen: null };
|
|
799
|
+
}
|
|
800
|
+
case "point":
|
|
801
|
+
if (!reachable(items, event.index) || event.index === state.active) return stay;
|
|
802
|
+
return { state: { ...state, active: event.index, typed: "" }, focus: { to: "item", index: event.index }, chosen: null };
|
|
803
|
+
case "type":
|
|
804
|
+
return typeahead(state, items, event.key, event.at);
|
|
805
|
+
case "choose":
|
|
806
|
+
if (!enabled(items, event.index)) return stay;
|
|
807
|
+
return { state: MENU_CLOSED, focus: { to: "trigger" }, chosen: event.index };
|
|
808
|
+
case "dismiss":
|
|
809
|
+
return { state: MENU_CLOSED, focus: event.reason === "outside" ? { to: "none" } : { to: "trigger" }, chosen: null };
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
var MENU_CORNERS = {
|
|
813
|
+
"top-left": { x: -1, y: -1 },
|
|
814
|
+
"top-right": { x: 1, y: -1 },
|
|
815
|
+
"bottom-left": { x: -1, y: 1 },
|
|
816
|
+
"bottom-right": { x: 1, y: 1 }
|
|
817
|
+
};
|
|
818
|
+
function menuCorner(trigger, region) {
|
|
819
|
+
const x0 = region.x ?? 0;
|
|
820
|
+
const y0 = region.y ?? 0;
|
|
821
|
+
return {
|
|
822
|
+
x: trigger.x + trigger.width / 2 <= x0 + region.width / 2 ? -1 : 1,
|
|
823
|
+
y: trigger.y + trigger.height / 2 <= y0 + region.height / 2 ? -1 : 1
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
function along(start, length, size, side) {
|
|
827
|
+
return side < 0 ? start : start + length - size;
|
|
828
|
+
}
|
|
829
|
+
function fits(at, size, lo, hi, margin) {
|
|
830
|
+
return at >= lo + margin && at + size <= hi - margin;
|
|
831
|
+
}
|
|
832
|
+
var clamp = (v, lo, hi) => Math.min(Math.max(v, lo), Math.max(lo, hi));
|
|
833
|
+
function menuPlacement(trigger, menu, region, options = {}) {
|
|
834
|
+
const margin = options.margin ?? 8;
|
|
835
|
+
const x0 = region.x ?? 0;
|
|
836
|
+
const y0 = region.y ?? 0;
|
|
837
|
+
const x1 = x0 + region.width;
|
|
838
|
+
const y1 = y0 + region.height;
|
|
839
|
+
const width = Math.max(0, Math.min(menu.width, region.width - 2 * margin));
|
|
840
|
+
const height = Math.max(0, Math.min(menu.height, region.height - 2 * margin));
|
|
841
|
+
const corner = { ...options.corner ?? menuCorner(trigger, region) };
|
|
842
|
+
let x = along(trigger.x, trigger.width, width, corner.x);
|
|
843
|
+
let y = along(trigger.y, trigger.height, height, corner.y);
|
|
844
|
+
if (!options.corner) {
|
|
845
|
+
const fx = along(trigger.x, trigger.width, width, corner.x === -1 ? 1 : -1);
|
|
846
|
+
if (!fits(x, width, x0, x1, margin) && fits(fx, width, x0, x1, margin)) {
|
|
847
|
+
corner.x = corner.x === -1 ? 1 : -1;
|
|
848
|
+
x = fx;
|
|
849
|
+
}
|
|
850
|
+
const fy = along(trigger.y, trigger.height, height, corner.y === -1 ? 1 : -1);
|
|
851
|
+
if (!fits(y, height, y0, y1, margin) && fits(fy, height, y0, y1, margin)) {
|
|
852
|
+
corner.y = corner.y === -1 ? 1 : -1;
|
|
853
|
+
y = fy;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
x = clamp(x, x0 + margin, x1 - margin - width);
|
|
857
|
+
y = clamp(y, y0 + margin, y1 - margin - height);
|
|
858
|
+
const rect = { x, y, width, height };
|
|
859
|
+
return {
|
|
860
|
+
rect,
|
|
861
|
+
corner,
|
|
862
|
+
anchor: { x: corner.x < 0 ? x : x + width, y: corner.y < 0 ? y : y + height }
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
var center = (r) => ({ x: r.x + r.width / 2, y: r.y + r.height / 2 });
|
|
866
|
+
function menuActivity(phase) {
|
|
867
|
+
const shrink = Math.min(Math.max(phase.shrink, 0), 1);
|
|
868
|
+
const grow = Math.min(Math.max(phase.grow, 0), 1);
|
|
869
|
+
return shrink * (1 - grow);
|
|
870
|
+
}
|
|
871
|
+
function menuSurfaceFrame(trigger, menu, anchor, phase, bounds) {
|
|
872
|
+
const frame = growthFrame(
|
|
873
|
+
{ geometry: { width: trigger.width, height: trigger.height, cornerRadius: trigger.radius }, center: center(trigger) },
|
|
874
|
+
{ geometry: { width: menu.width, height: menu.height, cornerRadius: menu.radius }, center: center(menu) },
|
|
875
|
+
anchor,
|
|
876
|
+
phase
|
|
877
|
+
);
|
|
878
|
+
const { geometry, center: c } = frame.body;
|
|
879
|
+
let box = {
|
|
880
|
+
x: c.x - geometry.width / 2,
|
|
881
|
+
y: c.y - geometry.height / 2,
|
|
882
|
+
width: geometry.width,
|
|
883
|
+
height: geometry.height,
|
|
884
|
+
radius: geometry.cornerRadius
|
|
885
|
+
};
|
|
886
|
+
let morph = frame.merge;
|
|
887
|
+
const held = bounds ? intersectRect(box, bounds) : null;
|
|
888
|
+
if (held && (held.width < box.width || held.height < box.height)) {
|
|
889
|
+
const was = center(box);
|
|
890
|
+
const now = center(held);
|
|
891
|
+
box = { ...held, radius: Math.min(box.radius, held.width / 2, held.height / 2) };
|
|
892
|
+
if (morph) morph = { ...morph, offsetX: morph.offsetX + was.x - now.x, offsetY: morph.offsetY + was.y - now.y };
|
|
893
|
+
}
|
|
894
|
+
return {
|
|
895
|
+
box,
|
|
896
|
+
morph,
|
|
897
|
+
content: { x: menu.x - box.x, y: menu.y - box.y },
|
|
898
|
+
ink: frame.ink,
|
|
899
|
+
activity: menuActivity(phase)
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
function menuGlass(base) {
|
|
903
|
+
return { ...base, roughness: Math.max(base.roughness, vireglass.VIREGLASS_SHEET_MATERIAL.roughness) };
|
|
904
|
+
}
|
|
905
|
+
function menuMaterial(base, activity) {
|
|
906
|
+
return atomMaterial(menuGlass(base), "menu", { ...ATOM_AT_REST, pressed: activity });
|
|
907
|
+
}
|
|
908
|
+
var MENU_DROP_BODY = { alpha: 0.9, white: 0.1, lift: 0.2 };
|
|
909
|
+
function menuBody(base, activity, frost = false) {
|
|
910
|
+
const rest = atomBody(base, ATOM_AT_REST, frost);
|
|
911
|
+
if (frost) return rest;
|
|
912
|
+
const k = Math.min(Math.max(activity, 0), 1);
|
|
913
|
+
const mix2 = (key) => rest[key] + (MENU_DROP_BODY[key] - rest[key]) * k;
|
|
914
|
+
return { alpha: mix2("alpha"), white: mix2("white"), lift: mix2("lift") };
|
|
915
|
+
}
|
|
916
|
+
var MENU_ITEM_FILL = { active: 0.1, pressed: 0.18 };
|
|
917
|
+
function menuItemFill(state) {
|
|
918
|
+
if (state.disabled) return 0;
|
|
919
|
+
if (state.pressed) return MENU_ITEM_FILL.pressed;
|
|
920
|
+
return state.active ? MENU_ITEM_FILL.active : 0;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// src/kit/response.ts
|
|
924
|
+
var LIFTING = { grow: 0.18, defocus: 1.6 };
|
|
925
|
+
var SINKING = { grow: 0.06, defocus: 1 };
|
|
926
|
+
function pressResponse(kind) {
|
|
927
|
+
return atomLift(kind) === 1 ? LIFTING : SINKING;
|
|
928
|
+
}
|
|
929
|
+
|
|
392
930
|
exports.A11Y_NONE = A11Y_NONE;
|
|
393
931
|
exports.ATOM_AT_REST = ATOM_AT_REST;
|
|
932
|
+
exports.BAR_SLOTS = BAR_SLOTS;
|
|
933
|
+
exports.BOTTOM_SHEET_MAX_WIDTH = BOTTOM_SHEET_MAX_WIDTH;
|
|
394
934
|
exports.BUTTON_SIZES = BUTTON_SIZES;
|
|
395
935
|
exports.CONTROL_IDLE = CONTROL_IDLE;
|
|
396
936
|
exports.CONTROL_SIZES = CONTROL_SIZES;
|
|
397
937
|
exports.DEFAULT_GROWTH_TIMING = DEFAULT_GROWTH_TIMING;
|
|
938
|
+
exports.DIALOG_MAX_WIDTH = DIALOG_MAX_WIDTH;
|
|
939
|
+
exports.FORM_MORPH_TIMING = FORM_MORPH_TIMING;
|
|
940
|
+
exports.HEIGHT_BREAKPOINTS = HEIGHT_BREAKPOINTS;
|
|
941
|
+
exports.HEIGHT_CLASSES = HEIGHT_CLASSES;
|
|
942
|
+
exports.INPUT_MIXED = INPUT_MIXED;
|
|
943
|
+
exports.INPUT_POINTER = INPUT_POINTER;
|
|
944
|
+
exports.INPUT_TABLET_KEYBOARD = INPUT_TABLET_KEYBOARD;
|
|
945
|
+
exports.INPUT_TOUCH = INPUT_TOUCH;
|
|
946
|
+
exports.LIST_PANE_WIDTH = LIST_PANE_WIDTH;
|
|
947
|
+
exports.MENU_CLOSED = MENU_CLOSED;
|
|
948
|
+
exports.MENU_CORNERS = MENU_CORNERS;
|
|
949
|
+
exports.MENU_DROP_BODY = MENU_DROP_BODY;
|
|
950
|
+
exports.MENU_ITEM_FILL = MENU_ITEM_FILL;
|
|
398
951
|
exports.MIN_POINTER_TARGET_DP = MIN_POINTER_TARGET_DP;
|
|
399
952
|
exports.MIN_TOUCH_TARGET_DP = MIN_TOUCH_TARGET_DP;
|
|
953
|
+
exports.MORE_ID = MORE_ID;
|
|
400
954
|
exports.POINTER_INPUT = POINTER_INPUT;
|
|
955
|
+
exports.POSTURE_FLAT = POSTURE_FLAT;
|
|
401
956
|
exports.PRESS_IDLE = PRESS_IDLE;
|
|
957
|
+
exports.SIDE_SHEET_MAX_WIDTH = SIDE_SHEET_MAX_WIDTH;
|
|
958
|
+
exports.SUPPORTING_PANE_MAX_WIDTH = SUPPORTING_PANE_MAX_WIDTH;
|
|
959
|
+
exports.SURFACE_KINDS = SURFACE_KINDS;
|
|
960
|
+
exports.TOOLBAR_GAP = TOOLBAR_GAP;
|
|
402
961
|
exports.TOUCH_INPUT = TOUCH_INPUT;
|
|
962
|
+
exports.TYPEAHEAD_SECONDS = TYPEAHEAD_SECONDS;
|
|
963
|
+
exports.WIDTH_BREAKPOINTS = WIDTH_BREAKPOINTS;
|
|
964
|
+
exports.WIDTH_CLASSES = WIDTH_CLASSES;
|
|
965
|
+
exports.adaptiveContext = adaptiveContext;
|
|
403
966
|
exports.atomAtRest = atomAtRest;
|
|
404
967
|
exports.atomBody = atomBody;
|
|
405
968
|
exports.atomLift = atomLift;
|
|
406
969
|
exports.atomMaterial = atomMaterial;
|
|
970
|
+
exports.bottomAccessory = bottomAccessory;
|
|
971
|
+
exports.classifyWindow = classifyWindow;
|
|
407
972
|
exports.controlTargets = controlTargets;
|
|
408
973
|
exports.createControlVisual = createControlVisual;
|
|
974
|
+
exports.createFormMorph = createFormMorph;
|
|
409
975
|
exports.createGrowthState = createGrowthState;
|
|
410
976
|
exports.defaultSize = defaultSize;
|
|
977
|
+
exports.formMorph = formMorph;
|
|
978
|
+
exports.formMorphFrame = formMorphFrame;
|
|
411
979
|
exports.growthFrame = growthFrame;
|
|
412
980
|
exports.growthInk = growthInk;
|
|
413
981
|
exports.growthPhase = growthPhase;
|
|
982
|
+
exports.halfOpen = halfOpen;
|
|
983
|
+
exports.heightClass = heightClass;
|
|
414
984
|
exports.hitSlop = hitSlop;
|
|
985
|
+
exports.hitTarget = hitTarget;
|
|
986
|
+
exports.hoversWith = hoversWith;
|
|
415
987
|
exports.iconButtonSize = iconButtonSize;
|
|
988
|
+
exports.intersectRect = intersectRect;
|
|
989
|
+
exports.menuActivity = menuActivity;
|
|
990
|
+
exports.menuBody = menuBody;
|
|
991
|
+
exports.menuCorner = menuCorner;
|
|
992
|
+
exports.menuGlass = menuGlass;
|
|
993
|
+
exports.menuItemFill = menuItemFill;
|
|
994
|
+
exports.menuMaterial = menuMaterial;
|
|
995
|
+
exports.menuPlacement = menuPlacement;
|
|
996
|
+
exports.menuSize = menuSize;
|
|
997
|
+
exports.menuSurfaceFrame = menuSurfaceFrame;
|
|
416
998
|
exports.minTarget = minTarget;
|
|
999
|
+
exports.navigationForm = navigationForm;
|
|
417
1000
|
exports.nestedRadius = nestedRadius;
|
|
1001
|
+
exports.paneLayout = paneLayout;
|
|
1002
|
+
exports.postureFromSegments = postureFromSegments;
|
|
1003
|
+
exports.postureSplit = postureSplit;
|
|
418
1004
|
exports.presentationFor = presentationFor;
|
|
1005
|
+
exports.presentationForm = presentationForm;
|
|
419
1006
|
exports.pressResponse = pressResponse;
|
|
1007
|
+
exports.rebaseFormMorph = rebaseFormMorph;
|
|
1008
|
+
exports.rectContains = rectContains;
|
|
420
1009
|
exports.resolveA11y = resolveA11y;
|
|
421
1010
|
exports.sameA11y = sameA11y;
|
|
1011
|
+
exports.segmentOf = segmentOf;
|
|
422
1012
|
exports.settleControlVisual = settleControlVisual;
|
|
1013
|
+
exports.sizeTier = sizeTier;
|
|
423
1014
|
exports.smoothstep = smoothstep;
|
|
424
1015
|
exports.stepControl = stepControl;
|
|
425
1016
|
exports.stepControlVisual = stepControlVisual;
|
|
426
1017
|
exports.stepFocus = stepFocus;
|
|
1018
|
+
exports.stepFormMorph = stepFormMorph;
|
|
427
1019
|
exports.stepGrowth = stepGrowth;
|
|
428
1020
|
exports.stepHover = stepHover;
|
|
1021
|
+
exports.stepMenu = stepMenu;
|
|
429
1022
|
exports.stepPress = stepPress;
|
|
430
1023
|
exports.stepSpring = stepSpring;
|
|
1024
|
+
exports.supportingPane = supportingPane;
|
|
1025
|
+
exports.surfaceRegion = surfaceRegion;
|
|
1026
|
+
exports.toolbarLayout = toolbarLayout;
|
|
1027
|
+
exports.toolbarPlacement = toolbarPlacement;
|
|
431
1028
|
exports.visualAtomState = visualAtomState;
|
|
1029
|
+
exports.widthAtLeast = widthAtLeast;
|
|
1030
|
+
exports.widthClass = widthClass;
|
|
1031
|
+
exports.windowSegments = windowSegments;
|
|
432
1032
|
//# sourceMappingURL=index.cjs.map
|
|
433
1033
|
//# sourceMappingURL=index.cjs.map
|