@mkbabb/glass-ui 3.4.0 → 3.5.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/dist/{DataTable-FfkaAg2z.js → DataTable-DyKc_26a.js} +144 -106
- package/dist/{NumberFieldContent-iOTQ5rGO.js → NumberFieldContent-jO-zGOHf.js} +1 -1
- package/dist/api/index.d.ts +1 -0
- package/dist/{button-Ckn3eDfB.js → button-i8Ek5vvg.js} +1 -1
- package/dist/button.js +1 -1
- package/dist/carousel.js +1 -1
- package/dist/components/custom/deck-progress/DeckProgress.vue.d.ts +27 -0
- package/dist/components/custom/deck-progress/index.d.ts +2 -0
- package/dist/components/custom/dock/composables/useLayerTransition.d.ts +11 -0
- package/dist/components/ui/data-table/composables/useDataTableResponsive.d.ts +28 -0
- package/dist/components/ui/data-table/composables/useDataTableRowIdentity.d.ts +33 -0
- package/dist/composables/dark/useGlobalDark.d.ts +17 -6
- package/dist/composables/dom/index.d.ts +3 -0
- package/dist/composables/dom/useBreakpoint.d.ts +38 -0
- package/dist/composables/dom/useIdleReady.d.ts +63 -0
- package/dist/composables/dom/useTokenColor.d.ts +13 -0
- package/dist/composables/dom/useViewportReady.d.ts +87 -0
- package/dist/composables/glass/index.d.ts +1 -1
- package/dist/composables/glass/useGlassRenderer.d.ts +10 -3
- package/dist/composables/motion/useAnimatedNumber.d.ts +8 -2
- package/dist/composables/motion/useCountup.d.ts +8 -2
- package/dist/composables/motion/useNumericTransition.d.ts +17 -6
- package/dist/composables/motion/useViewTransition.d.ts +16 -1
- package/dist/confirm-dialog.js +1 -1
- package/dist/data-table.js +1 -1
- package/dist/dock.js +169 -158
- package/dist/dom.js +4 -4
- package/dist/glass-panel.js +14 -14
- package/dist/glass-ui.css +1 -1
- package/dist/glass-ui.js +134 -119
- package/dist/goo-blob.js +108 -89
- package/dist/index.d.ts +1 -0
- package/dist/labeled-field.js +1 -1
- package/dist/motion-core.js +1 -1
- package/dist/number-field.js +1 -1
- package/dist/search.js +1 -1
- package/dist/{slider-BOh8ycfZ.js → slider-CgNzRSh6.js} +1 -1
- package/dist/slider.js +1 -1
- package/dist/styles/components.css +1 -1
- package/dist/styles/dock.css +91 -36
- package/dist/styles/glass.css +44 -1
- package/dist/styles/instrument-chassis.css +10 -13
- package/dist/styles/instrument-rail.css +11 -12
- package/dist/styles/tokens.css +9 -7
- package/dist/styles/utilities.css +20 -0
- package/dist/styles/view-transition.css +24 -0
- package/dist/tabs.js +1 -1
- package/dist/timeline.js +1 -1
- package/dist/useViewTransition-CJnqg6wl.js +21 -0
- package/dist/useViewportReady-Dcvf0c4p.js +191 -0
- package/package.json +2 -1
- package/src/styles/dock.css +91 -36
- package/src/styles/glass.css +44 -1
- package/src/styles/instrument-chassis.css +10 -13
- package/src/styles/instrument-rail.css +11 -12
- package/src/styles/tokens.css +9 -7
- package/src/styles/utilities.css +20 -0
- package/src/styles/view-transition.css +24 -0
- package/dist/useClipboard-D8vFyRCa.js +0 -97
- package/dist/useViewTransition-D4ssvnXZ.js +0 -18
package/dist/styles/tokens.css
CHANGED
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
snappy: (0.35s, ζ=0.65) — quick crisp, overshoot ~+6.8%
|
|
147
147
|
bouncy: (0.50s, ζ=0.45) — emphatic overshoot ~+20.5%
|
|
148
148
|
gentle: (0.70s, ζ=1.00) — patient critically-damped
|
|
149
|
-
dock: (0.
|
|
149
|
+
dock: (0.32s, ζ=0.70) — dock expand/collapse morph, overshoot ~+4.6%
|
|
150
150
|
|
|
151
151
|
Note on `smooth`: at ζ=0.86 the analytic solver produces a peak
|
|
152
152
|
of 1.00498 (+0.5%) at the 24% slot — mathematically present but
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
--spring-snappy: linear(0, 0.10438 2.041%, 0.32622 4.082%, 0.56668 6.122%, 0.77153 8.163%, 0.91961 10.204%, 1.01073 12.245%, 1.05549 14.286%, 1.06804 16.327%, 1.06171 18.367%, 1.04686 20.408%, 1.03044 22.449%, 1.01629 24.490%, 1.00596 26.531%, 0.99954 28.571%, 0.99633 30.612%, 0.99537 32.653%, 0.99575 34.694%, 0.99674 36.735%, 0.99786 38.776%, 0.99884 40.816%, 0.99956 42.857%, 1.00001 44.898%, 1.00024 46.939%, 1.00000 48.980%, 1.00000 51.020%, 1.00000 53.061%, 1.00000 55.102%, 1.00000 57.143%, 1.00000 59.184%, 1.00000 61.224%, 1.00000 63.265%, 1.00000 65.306%, 1.00000 67.347%, 1.00000 69.388%, 1.00000 71.429%, 1.00000 73.469%, 1.00000 75.510%, 1.00000 77.551%, 1.00000 79.592%, 1.00000 81.633%, 1.00000 83.673%, 1.00000 85.714%, 1.00000 87.755%, 1.00000 89.796%, 1.00000 91.837%, 1.00000 93.878%, 1.00000 95.918%, 1.00000 97.959%, 1);
|
|
161
161
|
--spring-bouncy: linear(0, 0.11105 2.041%, 0.36430 4.082%, 0.65496 6.122%, 0.90929 8.163%, 1.08828 10.204%, 1.18289 12.245%, 1.20482 14.286%, 1.17641 16.327%, 1.12214 18.367%, 1.06276 20.408%, 1.01239 22.449%, 0.97809 24.490%, 0.96099 26.531%, 0.95826 28.571%, 0.96514 30.612%, 0.97666 32.653%, 0.98873 34.694%, 0.99867 36.735%, 1.00520 38.776%, 1.00825 40.816%, 1.00847 42.857%, 1.00686 44.898%, 1.00443 46.939%, 1.00199 48.980%, 1.00004 51.020%, 0.99880 53.061%, 0.99827 55.102%, 0.99829 57.143%, 0.99866 59.184%, 0.99916 61.224%, 0.99966 63.265%, 1.00004 65.306%, 1.00027 67.347%, 1.00000 69.388%, 1.00000 71.429%, 1.00000 73.469%, 1.00000 75.510%, 1.00000 77.551%, 1.00000 79.592%, 1.00000 81.633%, 1.00000 83.673%, 1.00000 85.714%, 1.00000 87.755%, 1.00000 89.796%, 1.00000 91.837%, 1.00000 93.878%, 1.00000 95.918%, 1.00000 97.959%, 1);
|
|
162
162
|
--spring-gentle: linear(0, 0.09415 2.041%, 0.27374 4.082%, 0.45506 6.122%, 0.60779 8.163%, 0.72570 10.204%, 0.81213 12.245%, 0.87336 14.286%, 0.91570 16.327%, 0.94445 18.367%, 0.96371 20.408%, 0.97645 22.449%, 0.98481 24.490%, 0.99025 26.531%, 0.99377 28.571%, 0.99604 30.612%, 0.99749 32.653%, 0.99841 34.694%, 0.99900 36.735%, 0.99937 38.776%, 0.99961 40.816%, 0.99975 42.857%, 0.99985 44.898%, 1.00000 46.939%, 1.00000 48.980%, 1.00000 51.020%, 1.00000 53.061%, 1.00000 55.102%, 1.00000 57.143%, 1.00000 59.184%, 1.00000 61.224%, 1.00000 63.265%, 1.00000 65.306%, 1.00000 67.347%, 1.00000 69.388%, 1.00000 71.429%, 1.00000 73.469%, 1.00000 75.510%, 1.00000 77.551%, 1.00000 79.592%, 1.00000 81.633%, 1.00000 83.673%, 1.00000 85.714%, 1.00000 87.755%, 1.00000 89.796%, 1.00000 91.837%, 1.00000 93.878%, 1.00000 95.918%, 1.00000 97.959%, 1);
|
|
163
|
-
--spring-dock: linear(0, 0.
|
|
163
|
+
--spring-dock: linear(0, 0.10282 2.041%, 0.31773 4.082%, 0.54783 6.122%, 0.74309 8.163%, 0.88550 10.204%, 0.97598 12.245%, 1.02452 14.286%, 1.04368 16.327%, 1.04501 18.367%, 1.03739 20.408%, 1.02681 22.449%, 1.01672 24.490%, 1.00873 26.531%, 1.00323 28.571%, 0.99996 30.612%, 0.99837 32.653%, 0.99789 34.694%, 0.99805 36.735%, 0.99848 38.776%, 0.99897 40.816%, 0.99940 42.857%, 0.99972 44.898%, 0.99993 46.939%, 1.00004 48.980%, 1.00000 51.020%, 1.00000 53.061%, 1.00000 55.102%, 1.00000 57.143%, 1.00000 59.184%, 1.00000 61.224%, 1.00000 63.265%, 1.00000 65.306%, 1.00000 67.347%, 1.00000 69.388%, 1.00000 71.429%, 1.00000 73.469%, 1.00000 75.510%, 1.00000 77.551%, 1.00000 79.592%, 1.00000 81.633%, 1.00000 83.673%, 1.00000 85.714%, 1.00000 87.755%, 1.00000 89.796%, 1.00000 91.837%, 1.00000 93.878%, 1.00000 95.918%, 1.00000 97.959%, 1);
|
|
164
164
|
|
|
165
165
|
/* Core cubic-bezier (exits, fallbacks, non-spring uses) */
|
|
166
166
|
--motion-ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
|
|
@@ -1287,17 +1287,19 @@
|
|
|
1287
1287
|
both engine paths are timing-IDENTICAL: the FLIP fallback (via
|
|
1288
1288
|
`--dock-motion-resize`), the native View-Transition group (its
|
|
1289
1289
|
`animation-timing-function`), AND the runtime SpringProgress driver
|
|
1290
|
-
(AU.W8.3) consume this same `(0.
|
|
1290
|
+
(AU.W8.3) consume this same `(0.32, 0.7)` source curve. Retires the AQ.W6
|
|
1291
1291
|
fork where the VT path ran `--vt-ease` (apple-spring, +27.5% overshoot)
|
|
1292
1292
|
while the FLIP ran the snappy spring. `--vt-ease` still defaults the
|
|
1293
1293
|
other VT recipes (`.gl-list-item`).
|
|
1294
1294
|
|
|
1295
1295
|
AU.W8 — RETARGET snappy → dock. `--spring-snappy` (ζ=0.65, +6.8%) read as
|
|
1296
1296
|
mechanical: a stiff plateau at ~48% with too little overshoot to feel
|
|
1297
|
-
alive ("not iOS-smooth").
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1297
|
+
alive ("not iOS-smooth"). AW.W2 then retuned the dock spring to the
|
|
1298
|
+
iOS-control register: `--spring-dock` ((0.32, 0.7), ~+4.6%) settles snappy
|
|
1299
|
+
with a restrained overshoot — the felt iOS dock morph, off the prior
|
|
1300
|
+
playful +18.5% register. The runtime driver's DOCK_SPRING const MIRRORS the
|
|
1301
|
+
(0.32, 0.7) PRESETS row, so the CSS token and the JS-driven morph are
|
|
1302
|
+
bit-identical. */
|
|
1301
1303
|
--dock-resize-spring: var(--spring-dock);
|
|
1302
1304
|
|
|
1303
1305
|
/* AT.W7-dock-b — dock-control press micro-feedback spring. A TRANSFORM-ONLY
|
|
@@ -688,6 +688,26 @@
|
|
|
688
688
|
}
|
|
689
689
|
}
|
|
690
690
|
|
|
691
|
+
/* ── Twin-line divider — the chassis catch-light / under-shadow groove ───────
|
|
692
|
+
AW.W15 DRY extraction. The twin-line idiom (a 1px white catch-light over a
|
|
693
|
+
1px black under-shadow reading as one engraved hairline groove) is the
|
|
694
|
+
chassis-divider signature. The exact light/dark α pair was DUPLICATED in
|
|
695
|
+
`instrument-chassis.css` (`.bezel-line.top`/`.bottom`) and `instrument-rail.css`
|
|
696
|
+
(the sibling `::before`/`::after`). This utility is the SINGLE source of that
|
|
697
|
+
α pair: it publishes `--twin-line-catch` (the top catch-light) and
|
|
698
|
+
`--twin-line-shadow` (the bottom under-shadow) as cascade tokens, dark-adaptive
|
|
699
|
+
by construction (the `.dark &` arm re-resolves them). Both consumers read the
|
|
700
|
+
tokens; a retint touches one rule. Real DRY, ≥2 consumers. */
|
|
701
|
+
@utility twin-line-divider {
|
|
702
|
+
--twin-line-catch: rgb(255 255 255 / 0.10);
|
|
703
|
+
--twin-line-shadow: rgb(0 0 0 / 0.12);
|
|
704
|
+
|
|
705
|
+
:where(.dark) & {
|
|
706
|
+
--twin-line-catch: rgb(255 255 255 / 0.06);
|
|
707
|
+
--twin-line-shadow: rgb(0 0 0 / 0.18);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
691
711
|
/* ── Control transition recipe (AU.W8b.4) ───────────────────────────────
|
|
692
712
|
Shared compound transition for interactive controls that animate their
|
|
693
713
|
surface (background-color/color/box-shadow/border-color) on the four-state
|
|
@@ -61,6 +61,30 @@
|
|
|
61
61
|
animation-timing-function: var(--dock-resize-spring, var(--spring-dock));
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/* AW.W3 — typed directional dock curves. The swap tags the active transition
|
|
65
|
+
* `dock-expand` / `dock-collapse` (the outer collapsed↔expanded pair) and
|
|
66
|
+
* `layer-forward` / `layer-back` (the inner DockLayerGroup pane swap) via the
|
|
67
|
+
* `types` argument to `startViewTransition` (Chrome 140+; feature-detected, the
|
|
68
|
+
* untyped fallback is the symmetric `.gl-dock-layer` curve above). iOS-feel
|
|
69
|
+
* motion is ASYMMETRIC — a snappier exit, a softer entry-overshoot. EXPAND
|
|
70
|
+
* (and forward) lead with the overshooting `--spring-dock`; COLLAPSE (and back)
|
|
71
|
+
* exit on the non-overshooting `--spring-snappy` (a quicker settle, no bounce on
|
|
72
|
+
* the way out). The shorter `--duration-fast` on the exit reads as the crisp
|
|
73
|
+
* dismiss. A non-typed engine never matches these — it runs the symmetric curve,
|
|
74
|
+
* which is the acceptable contract. PRM zeroes the animation (the `@media` at
|
|
75
|
+
* the top of this file). */
|
|
76
|
+
:active-view-transition-type(dock-expand) ::view-transition-group(.gl-dock-layer),
|
|
77
|
+
:active-view-transition-type(layer-forward) ::view-transition-group(.gl-dock-layer) {
|
|
78
|
+
animation-duration: var(--vt-duration, var(--duration-normal));
|
|
79
|
+
animation-timing-function: var(--dock-resize-spring, var(--spring-dock));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:active-view-transition-type(dock-collapse) ::view-transition-group(.gl-dock-layer),
|
|
83
|
+
:active-view-transition-type(layer-back) ::view-transition-group(.gl-dock-layer) {
|
|
84
|
+
animation-duration: var(--vt-duration-exit, var(--duration-fast));
|
|
85
|
+
animation-timing-function: var(--spring-snappy);
|
|
86
|
+
}
|
|
87
|
+
|
|
64
88
|
@keyframes gl-vt-slide-in { from { opacity: 0; translate: 0 var(--vt-rise, 8px); } }
|
|
65
89
|
@keyframes gl-vt-slide-out { to { opacity: 0; translate: 0 var(--vt-rise, 8px); } }
|
|
66
90
|
|
package/dist/tabs.js
CHANGED
|
@@ -208,7 +208,7 @@ var M = [
|
|
|
208
208
|
}, () => [p(E(e.label), 1)], !0)], 10, N))], 64))), 128))
|
|
209
209
|
], 2));
|
|
210
210
|
}
|
|
211
|
-
}), [["__scopeId", "data-v-
|
|
211
|
+
}), [["__scopeId", "data-v-ba2dfb91"]]), F = /* @__PURE__ */ h({
|
|
212
212
|
__name: "BouncyTabs",
|
|
213
213
|
props: /* @__PURE__ */ g({
|
|
214
214
|
options: {},
|
package/dist/timeline.js
CHANGED
|
@@ -197,7 +197,7 @@ var A = ["aria-label"], j = [
|
|
|
197
197
|
_: 2
|
|
198
198
|
}, 1032, ["class", "onUpdate:open"]))], 4))), 128))], 8, A)) : a("", !0);
|
|
199
199
|
}
|
|
200
|
-
}), [["__scopeId", "data-v-
|
|
200
|
+
}), [["__scopeId", "data-v-8e53d036"]]), H = [
|
|
201
201
|
"aria-valuemax",
|
|
202
202
|
"aria-valuenow",
|
|
203
203
|
"aria-label"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/composables/motion/useViewTransition.ts
|
|
2
|
+
function e() {
|
|
3
|
+
return typeof document < "u" && typeof document.startViewTransition == "function";
|
|
4
|
+
}
|
|
5
|
+
function t(e, t) {
|
|
6
|
+
let n = typeof document > "u" ? void 0 : document;
|
|
7
|
+
if (!n || typeof n.startViewTransition != "function") return e(), {
|
|
8
|
+
finished: Promise.resolve(),
|
|
9
|
+
transitioned: !1
|
|
10
|
+
};
|
|
11
|
+
let r = t?.types && t.types.length > 0 ? n.startViewTransition({
|
|
12
|
+
update: () => e(),
|
|
13
|
+
types: t.types
|
|
14
|
+
}) : n.startViewTransition(() => e());
|
|
15
|
+
return r.ready?.catch(() => {}), {
|
|
16
|
+
finished: r.finished.then(() => void 0, () => void 0),
|
|
17
|
+
transitioned: !0
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { e as n, t };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { getCurrentScope as e, onMounted as t, onScopeDispose as n, readonly as r, ref as i, toValue as a, watch as o } from "vue";
|
|
2
|
+
//#region src/composables/dom/useTokenColor.ts
|
|
3
|
+
function s(r, s = {}) {
|
|
4
|
+
let c = s.fallback ?? "", l = i(c), u = s.resolver ?? ((e, t) => getComputedStyle(t ?? document.documentElement).getPropertyValue(e));
|
|
5
|
+
function d() {
|
|
6
|
+
let e = a(r);
|
|
7
|
+
return !e || !s.resolver && typeof document > "u" ? c : u(e, (s.element ? a(s.element) : null) ?? (typeof document < "u" ? document.documentElement : void 0) ?? void 0 ?? void 0).trim() || c;
|
|
8
|
+
}
|
|
9
|
+
function f() {
|
|
10
|
+
l.value = d();
|
|
11
|
+
}
|
|
12
|
+
if (f(), t(f), typeof document < "u") {
|
|
13
|
+
let t = new MutationObserver(f);
|
|
14
|
+
t.observe(document.documentElement, {
|
|
15
|
+
attributes: !0,
|
|
16
|
+
attributeFilter: ["class"]
|
|
17
|
+
});
|
|
18
|
+
let r = typeof window < "u" && window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)") : null;
|
|
19
|
+
r?.addEventListener?.("change", f), e() && n(() => {
|
|
20
|
+
t.disconnect(), r?.removeEventListener?.("change", f);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return o(() => a(r), f), s.element !== void 0 && o(() => a(s.element), f), {
|
|
24
|
+
value: l,
|
|
25
|
+
refresh: f
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/composables/dom/useClipboard.ts
|
|
30
|
+
async function c(e) {
|
|
31
|
+
if (typeof navigator > "u" || !navigator.clipboard?.writeText) return {
|
|
32
|
+
ok: !1,
|
|
33
|
+
reason: "no-api"
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
return await navigator.clipboard.writeText(e), { ok: !0 };
|
|
37
|
+
} catch {
|
|
38
|
+
return {
|
|
39
|
+
ok: !1,
|
|
40
|
+
reason: "clipboard-api"
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function l(e) {
|
|
45
|
+
if (typeof document > "u") return {
|
|
46
|
+
ok: !1,
|
|
47
|
+
reason: "no-api"
|
|
48
|
+
};
|
|
49
|
+
let t = document.createElement("textarea");
|
|
50
|
+
t.value = e, t.setAttribute("readonly", ""), t.style.position = "fixed", t.style.top = "-9999px", document.body.appendChild(t), t.select();
|
|
51
|
+
let n = !1;
|
|
52
|
+
try {
|
|
53
|
+
n = document.execCommand("copy");
|
|
54
|
+
} catch {
|
|
55
|
+
n = !1;
|
|
56
|
+
}
|
|
57
|
+
return document.body.removeChild(t), n ? { ok: !0 } : {
|
|
58
|
+
ok: !1,
|
|
59
|
+
reason: "exec-command"
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async function u(e, t) {
|
|
63
|
+
let n = await c(e);
|
|
64
|
+
if (n.ok) return n;
|
|
65
|
+
let r = l(e);
|
|
66
|
+
if (r.ok) return r;
|
|
67
|
+
let i = r.reason ?? n.reason ?? "no-api";
|
|
68
|
+
return t?.(i), {
|
|
69
|
+
ok: !1,
|
|
70
|
+
reason: i
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async function d(e, t = {}) {
|
|
74
|
+
let { ok: n } = await u(e, t.onCopyError);
|
|
75
|
+
return n;
|
|
76
|
+
}
|
|
77
|
+
function f(e = {}) {
|
|
78
|
+
let t = e.resetMs ?? 1500, r = i(!1), a = null;
|
|
79
|
+
function o() {
|
|
80
|
+
a != null && (clearTimeout(a), a = null);
|
|
81
|
+
}
|
|
82
|
+
async function s(n) {
|
|
83
|
+
let i = await u(n, e.onCopyError);
|
|
84
|
+
return i.ok && (r.value = !0, o(), a = setTimeout(() => {
|
|
85
|
+
r.value = !1, a = null;
|
|
86
|
+
}, t)), i;
|
|
87
|
+
}
|
|
88
|
+
return n(o), {
|
|
89
|
+
copied: r,
|
|
90
|
+
copy: s
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/composables/dom/useBreakpoint.ts
|
|
95
|
+
function p(t) {
|
|
96
|
+
let a = i(!1), o = null;
|
|
97
|
+
function s(e) {
|
|
98
|
+
a.value = e.matches;
|
|
99
|
+
}
|
|
100
|
+
function c() {
|
|
101
|
+
typeof window > "u" || !window.matchMedia || (o = window.matchMedia(t), a.value = o.matches, o.addEventListener("change", s));
|
|
102
|
+
}
|
|
103
|
+
function l() {
|
|
104
|
+
o?.removeEventListener("change", s), o = null;
|
|
105
|
+
}
|
|
106
|
+
return e() && n(l), c(), {
|
|
107
|
+
matches: r(a),
|
|
108
|
+
stop: l
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/composables/dom/useIdleReady.ts
|
|
113
|
+
function m(t = {}) {
|
|
114
|
+
let r = t.timeout ?? 2e3, a = i(!1), o = null, s = null, c = !1;
|
|
115
|
+
function l() {
|
|
116
|
+
c || a.value || (a.value = !0, t.onReady?.(), u());
|
|
117
|
+
}
|
|
118
|
+
function u() {
|
|
119
|
+
o !== null && typeof window < "u" && "cancelIdleCallback" in window && (window.cancelIdleCallback(o), o = null), s !== null && (clearTimeout(s), s = null);
|
|
120
|
+
}
|
|
121
|
+
function d() {
|
|
122
|
+
if (!c) {
|
|
123
|
+
if (typeof window > "u") {
|
|
124
|
+
l();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
"requestIdleCallback" in window ? o = window.requestIdleCallback(l, { timeout: r }) : s = setTimeout(l, 0);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
d();
|
|
131
|
+
function f() {
|
|
132
|
+
c || (c = !0, u());
|
|
133
|
+
}
|
|
134
|
+
return e() && n(f), {
|
|
135
|
+
ready: a,
|
|
136
|
+
stop: f
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/composables/dom/useViewportReady.ts
|
|
141
|
+
function h(t, r = {}) {
|
|
142
|
+
let a = r.rootMargin ?? "200px", s = r.idleTimeout ?? 1e4, c = r.threshold ?? .01, l = i(!1), u = null, d, f = null, p = null, m = !1;
|
|
143
|
+
function h() {
|
|
144
|
+
m || l.value || (l.value = !0, _());
|
|
145
|
+
}
|
|
146
|
+
function g() {
|
|
147
|
+
if (!m) {
|
|
148
|
+
if (typeof window > "u") {
|
|
149
|
+
h();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
"requestIdleCallback" in window ? f = window.requestIdleCallback(h, { timeout: s }) : p = setTimeout(h, 16);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function _() {
|
|
156
|
+
u &&= (u.disconnect(), null), f !== null && typeof window < "u" && "cancelIdleCallback" in window && (window.cancelIdleCallback(f), f = null), p !== null && (clearTimeout(p), p = null);
|
|
157
|
+
}
|
|
158
|
+
function v(e) {
|
|
159
|
+
if (typeof window > "u" || !("IntersectionObserver" in window)) {
|
|
160
|
+
g();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
u = new IntersectionObserver((e) => {
|
|
164
|
+
if (!m) {
|
|
165
|
+
for (let t of e) if (t.isIntersecting) {
|
|
166
|
+
g(), u?.disconnect(), u = null;
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}, {
|
|
171
|
+
rootMargin: a,
|
|
172
|
+
threshold: c
|
|
173
|
+
}), u.observe(e);
|
|
174
|
+
}
|
|
175
|
+
function y(e) {
|
|
176
|
+
m || l.value || d !== void 0 && d === e || (_(), d = e, e ? v(e) : g());
|
|
177
|
+
}
|
|
178
|
+
y(t.value);
|
|
179
|
+
let b = o(t, (e) => {
|
|
180
|
+
y(e);
|
|
181
|
+
}, { flush: "post" });
|
|
182
|
+
function x() {
|
|
183
|
+
m || (m = !0, b(), _());
|
|
184
|
+
}
|
|
185
|
+
return e() && n(x), {
|
|
186
|
+
ready: l,
|
|
187
|
+
stop: x
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//#endregion
|
|
191
|
+
export { f as a, d as i, m as n, s as o, p as r, h as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mkbabb/glass-ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "Glassmorphic design system — Vue 3.5 components, reka-ui primitives, Tailwind CSS v4 tokens",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -550,6 +550,7 @@
|
|
|
550
550
|
"proof:phantom-classes": "node scripts/proof-phantom-classes.mjs",
|
|
551
551
|
"proof:vt-names": "node scripts/proof-vt-names.mjs",
|
|
552
552
|
"proof:dock-animation-live": "node scripts/proof-dock-animation-live.mjs",
|
|
553
|
+
"proof:dock-clip-reveal": "node scripts/proof-dock-clip-reveal.mjs",
|
|
553
554
|
"proof:dock-motion-parity": "node scripts/proof-dock-motion-parity.mjs",
|
|
554
555
|
"proof:dock-motion-single-source": "node scripts/proof-dock-motion-single-source.mjs",
|
|
555
556
|
"proof:dock-opacity-lockstep": "node scripts/proof-dock-opacity-lockstep.mjs",
|
package/src/styles/dock.css
CHANGED
|
@@ -95,14 +95,56 @@
|
|
|
95
95
|
box-shadow: var(--glass-edge-light), var(--shadow-dock-override, var(--shadow-dock));
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
/*
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
/* AW.W2 — the box IS the reveal aperture (clip-reveal one-clock morph).
|
|
99
|
+
Migrated from `overflow: hidden` to a SINGLE-AXIS `overflow: clip` on the
|
|
100
|
+
MORPH axis (horizontal clips X / visible Y; vertical clips Y / visible X),
|
|
101
|
+
gated on a `data-morphing` attribute the driver owns (set at gesture START,
|
|
102
|
+
cleared on SETTLE). The clip PERSISTS through the morph — content is laid
|
|
103
|
+
out ONCE at its natural size behind the aperture and the growing/shrinking
|
|
104
|
+
box uncovers it, never spills it — and lifts to `visible` only at REST
|
|
105
|
+
expanded (so grown content + the focus ring paint past the box). The
|
|
106
|
+
prior `.expanded { overflow: visible }` (bound synchronously to
|
|
107
|
+
`visualExpanded`) lifted the clip at frame 0, leaving no aperture to reveal
|
|
108
|
+
through; the `:not([data-morphing])` guard holds the clip for the whole
|
|
109
|
+
gesture and lifts it on the final paint.
|
|
110
|
+
|
|
111
|
+
`overflow: clip` is PAINT-ONLY (not a scroll container): it never
|
|
112
|
+
participates in `scrollIntoView`/scroll-anchoring, cannot be a
|
|
113
|
+
scroll-driven-animation `scroller`, and drops the `min-width:0` scroll-box
|
|
114
|
+
dance for the non-scroll shell. The cross axis is ALWAYS explicitly
|
|
115
|
+
`visible` (the MDN single-axis-clip-degrades-to-hidden caveat). The
|
|
116
|
+
legitimate scroll ports (`.dock-scroll-{x,y}`, `overflow: auto`) STAY
|
|
117
|
+
`auto` — they are NOT migrated. AT.W7-dock-a's orthogonality holds: the
|
|
118
|
+
`containerName` opt-in does not touch the clip. */
|
|
119
|
+
.glass-dock:not(.vertical) {
|
|
120
|
+
overflow-x: clip;
|
|
121
|
+
overflow-y: visible;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.glass-dock.vertical {
|
|
125
|
+
overflow-x: visible;
|
|
126
|
+
overflow-y: clip;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* DURING a morph the clip is the aperture — keyed off `data-morphing`, NOT
|
|
130
|
+
off `.expanded`, so it survives the whole gesture and the box reveals its
|
|
131
|
+
content rather than letting it spill. */
|
|
132
|
+
.glass-dock[data-morphing]:not(.vertical) {
|
|
133
|
+
overflow-x: clip;
|
|
134
|
+
overflow-y: visible;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.glass-dock[data-morphing].vertical {
|
|
138
|
+
overflow-x: visible;
|
|
139
|
+
overflow-y: clip;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* AT REST EXPANDED — lift the morph-axis clip (grown content + focus ring
|
|
143
|
+
paint past the box). Fires ONLY when NOT morphing; the [data-morphing]
|
|
144
|
+
rules above win during the gesture by being more specific + later. */
|
|
145
|
+
.glass-dock.expanded:not([data-morphing]),
|
|
146
|
+
.glass-dock.always-expanded:not([data-morphing]) {
|
|
147
|
+
overflow: visible;
|
|
106
148
|
}
|
|
107
149
|
|
|
108
150
|
.glass-dock[data-density="compact"] {
|
|
@@ -283,13 +325,17 @@
|
|
|
283
325
|
width: auto;
|
|
284
326
|
height: auto;
|
|
285
327
|
max-block-size: var(--dock-max-block-size);
|
|
286
|
-
overflow-
|
|
287
|
-
|
|
328
|
+
/* overflow on the block (morph) axis is the data-morphing-gated clip
|
|
329
|
+
shell above; the cross axis stays visible there. */
|
|
288
330
|
padding: var(--dock-vertical-padding, var(--dock-padding-block, 0.375rem));
|
|
289
331
|
border-radius: var(--radius-dock);
|
|
332
|
+
/* AW.W2 — axis-parity carve: NON-morph properties only. The block-axis
|
|
333
|
+
(height) morph is owned by the inner `.dock-layer-stack` / DockLayerGroup
|
|
334
|
+
spring (or the VT path); a `height var(--dock-motion-resize)` here would
|
|
335
|
+
be a second driver on the same axis (the AV.W9.0 dual-driver race),
|
|
336
|
+
and `width` is the cross axis the spring never writes. Matches how
|
|
337
|
+
`:not(.vertical)` already excludes `width`. */
|
|
290
338
|
transition:
|
|
291
|
-
height var(--dock-motion-resize),
|
|
292
|
-
width var(--dock-motion-resize),
|
|
293
339
|
padding var(--dock-motion-resize),
|
|
294
340
|
box-shadow var(--dock-motion-standard),
|
|
295
341
|
transform var(--dock-motion-resize),
|
|
@@ -549,13 +595,16 @@
|
|
|
549
595
|
opacity: 1;
|
|
550
596
|
visibility: visible;
|
|
551
597
|
pointer-events: auto;
|
|
552
|
-
/*
|
|
553
|
-
the
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
598
|
+
/* AW.W2 — the active pane is STATICALLY opacity:1, REVEALED by the clip
|
|
599
|
+
aperture (the box is the reveal mechanism), never faded. The prior
|
|
600
|
+
`opacity var(--dock-motion-resize)` arm is DELETED: there is ZERO
|
|
601
|
+
opacity authority on the active pane now — the aperture uncovers a
|
|
602
|
+
layout that is laid out ONCE at natural size behind it. Only `visibility
|
|
603
|
+
0s` survives (the active layer must paint at once, no fade-in delay —
|
|
604
|
+
the AU.W2 governing rule). The leaving pane keeps the shared-token
|
|
605
|
+
opacity fade below (the ONLY surviving opacity animation, the thin
|
|
606
|
+
polish proof:dock-opacity-lockstep names). */
|
|
607
|
+
transition: visibility 0s;
|
|
559
608
|
}
|
|
560
609
|
|
|
561
610
|
/* A leaving layer is inactive for hit-testing but still painted
|
|
@@ -585,9 +634,19 @@
|
|
|
585
634
|
.dock-layer {
|
|
586
635
|
display: flex;
|
|
587
636
|
align-items: center;
|
|
588
|
-
white-space: nowrap;
|
|
589
637
|
grid-area: 1 / 1;
|
|
590
638
|
gap: var(--dock-layer-gap, 0.375rem);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/* AW.W2 — content-intrinsic axis follows the MORPH axis. A horizontal dock
|
|
642
|
+
lays its inline content out ONCE at `width: max-content` (nowrap) so the
|
|
643
|
+
width aperture uncovers a static row; the fixed `height` keeps the row a
|
|
644
|
+
single line. Scoped to `:not(.vertical)` so a vertical rail (whose
|
|
645
|
+
block-axis morph reveals a column) is NOT forced onto one nowrap row — the
|
|
646
|
+
vertical group's active host block-sizes to `height: max-content` below
|
|
647
|
+
(the AP.W3 column treatment, KEPT). */
|
|
648
|
+
.glass-dock:not(.vertical) .dock-layer {
|
|
649
|
+
white-space: nowrap;
|
|
591
650
|
height: var(--dock-layer-height, 2.5rem);
|
|
592
651
|
}
|
|
593
652
|
|
|
@@ -600,10 +659,11 @@
|
|
|
600
659
|
inset: 0;
|
|
601
660
|
}
|
|
602
661
|
|
|
603
|
-
.
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
662
|
+
/* AW.W2 — the at-rest clip-lift moved to `.expanded:not([data-morphing])` /
|
|
663
|
+
`.always-expanded:not([data-morphing])` (the clip-shell block at the top).
|
|
664
|
+
A plain `overflow: visible` here would lift the clip DURING the morph (the
|
|
665
|
+
load-bearing sequencing gap), so the `overflow` declarations are dropped
|
|
666
|
+
from these state rules; they keep only their non-overflow concerns. */
|
|
607
667
|
.glass-dock.expanded:not(.fit-content) .dock-layers {
|
|
608
668
|
width: 100%;
|
|
609
669
|
}
|
|
@@ -614,15 +674,6 @@
|
|
|
614
674
|
|
|
615
675
|
.glass-dock.always-expanded {
|
|
616
676
|
cursor: default;
|
|
617
|
-
overflow: visible;
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
/* Z.W2.T2 — always-expanded vertical rails inherit the same
|
|
621
|
-
grow-to-fit + visible contract. The prior auto pair re-introduced
|
|
622
|
-
the scroll affordance that A2 §B6 rejected. */
|
|
623
|
-
.glass-dock.vertical.always-expanded {
|
|
624
|
-
overflow-x: visible;
|
|
625
|
-
overflow-y: visible;
|
|
626
677
|
}
|
|
627
678
|
|
|
628
679
|
/* ── Scroll-on-overflow opt-in (GlassDock `overflow="scroll"`) ───────
|
|
@@ -854,9 +905,13 @@
|
|
|
854
905
|
.dock-layer-stack {
|
|
855
906
|
position: relative;
|
|
856
907
|
display: grid;
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
908
|
+
/* AW.W2 — the morph axis (width for a horizontal group, height for a
|
|
909
|
+
vertical one) is driven by the `useLayerTransition` SpringProgress in
|
|
910
|
+
pixel space (FLIP path) or the View-Transition (native path); a CSS
|
|
911
|
+
`width`/`height` transition here would be a SECOND driver on the same
|
|
912
|
+
axis (the AV.W9.0 dual-driver race that froze the dock). The cross axis
|
|
913
|
+
is intrinsic-sized and never morphs. So NO size transition on the stack
|
|
914
|
+
— one owner per axis. */
|
|
860
915
|
}
|
|
861
916
|
|
|
862
917
|
/* Base layout — the crossfade + hit-test contract is shared with
|
package/src/styles/glass.css
CHANGED
|
@@ -285,7 +285,13 @@
|
|
|
285
285
|
|
|
286
286
|
height: 2.5rem;
|
|
287
287
|
border-radius: var(--radius-pill);
|
|
288
|
-
|
|
288
|
+
/* AW.W13 — the resting field edge reads as an enclosed control at rest.
|
|
289
|
+
Was `--glass-border-wash` (~8%α), which nearly vanished on cream; the
|
|
290
|
+
lift to `--surface-tint-15` (15%α — ~2× the prior floor) makes the
|
|
291
|
+
edge legible without going loud. The `:focus-visible` accent ring +
|
|
292
|
+
the `:user-invalid`/`[aria-invalid]` destructive ring below still win
|
|
293
|
+
by order + specificity, so this only raises the resting alpha. */
|
|
294
|
+
border: 1.5px solid var(--surface-tint-15);
|
|
289
295
|
background: var(--glass-bg-quiet);
|
|
290
296
|
backdrop-filter: var(--glass-blur-wash);
|
|
291
297
|
padding: 0 1rem;
|
|
@@ -361,6 +367,43 @@
|
|
|
361
367
|
opacity: 0.5;
|
|
362
368
|
cursor: not-allowed;
|
|
363
369
|
}
|
|
370
|
+
|
|
371
|
+
/* AW.W13 — the Select trigger mirrors the input pill's resting border lift.
|
|
372
|
+
The reka-ui SelectTrigger renders `role="combobox"` over the `.glass-wash`
|
|
373
|
+
surface; its 8%α `--glass-border-wash` field edge vanished on cream just
|
|
374
|
+
like the input pill, so the same `--surface-tint-15` lift makes the
|
|
375
|
+
trigger read as an enclosed control at rest. Scoped to the combobox role
|
|
376
|
+
so the lift reaches ONLY the Select trigger, not every `.glass-wash`
|
|
377
|
+
surface. */
|
|
378
|
+
.glass-wash[role="combobox"] {
|
|
379
|
+
border-color: var(--surface-tint-15);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/* ── Deck-position rail (AW.W16) ──────────────────────────────────────
|
|
383
|
+
A CSS recipe that RESTYLES the shipped `<Progress variant="default">`
|
|
384
|
+
(the reka-ui ProgressRoot track + its indicator child) into the thin
|
|
385
|
+
bottom-of-deck position rail. It composes the EXISTING fill — it does NOT
|
|
386
|
+
re-author a second track/range mechanic. Every visual axis is a
|
|
387
|
+
`--progress-rail-*` token, so a consumer/dark-flip re-tints with zero
|
|
388
|
+
library edit (`:root { --progress-rail-fill: … }`). The viewport-pinned
|
|
389
|
+
chrome (`position: fixed`, `env(safe-area-inset-bottom)`, the z-index) is
|
|
390
|
+
CONSUMER-supplied — this recipe owns only the LOOK. */
|
|
391
|
+
.glass-progress-rail {
|
|
392
|
+
/* The track hairline — the rail reads as a thin sliver, not a 16px bar. */
|
|
393
|
+
height: var(--progress-rail-h, 3px);
|
|
394
|
+
border-radius: 0;
|
|
395
|
+
background: var(--progress-rail-track, color-mix(in srgb, var(--foreground) 8%, transparent));
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* The fill — the shipped ProgressIndicator child. A leading-edge glow on the
|
|
399
|
+
fill's trailing edge reads as a moving position head. */
|
|
400
|
+
.glass-progress-rail > * {
|
|
401
|
+
border-radius: 0;
|
|
402
|
+
background: var(--progress-rail-fill, var(--primary));
|
|
403
|
+
box-shadow:
|
|
404
|
+
var(--progress-rail-glow-x, 4px) 0 var(--progress-rail-glow-blur, 8px)
|
|
405
|
+
color-mix(in srgb, var(--progress-rail-fill, var(--primary)) var(--progress-rail-glow-strength, 55%), transparent);
|
|
406
|
+
}
|
|
364
407
|
}
|
|
365
408
|
|
|
366
409
|
/* ── Accessibility: reduced transparency ────────── */
|
|
@@ -231,6 +231,9 @@
|
|
|
231
231
|
/* Chassis dividers — twin-line hairline grooves ─────────────── */
|
|
232
232
|
|
|
233
233
|
.chassis-divider {
|
|
234
|
+
/* AW.W15 — consume the shared twin-line α pair (the catch-light +
|
|
235
|
+
under-shadow tokens publish here; the .bezel-line rules read them). */
|
|
236
|
+
@apply twin-line-divider;
|
|
234
237
|
flex-shrink: 0;
|
|
235
238
|
position: relative;
|
|
236
239
|
background: transparent;
|
|
@@ -269,19 +272,13 @@
|
|
|
269
272
|
height: 100%;
|
|
270
273
|
}
|
|
271
274
|
|
|
272
|
-
/*
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
0.06 / 0.18 against a low-light bg). */
|
|
280
|
-
.bezel-line.top { background: rgb(255 255 255 / 0.10); }
|
|
281
|
-
.bezel-line.bottom { background: rgb(0 0 0 / 0.12); }
|
|
282
|
-
|
|
283
|
-
.dark .bezel-line.top { background: rgb(255 255 255 / 0.06); }
|
|
284
|
-
.dark .bezel-line.bottom { background: rgb(0 0 0 / 0.18); }
|
|
275
|
+
/* AW.W15 — the twin-line α pair now lives in the `twin-line-divider`
|
|
276
|
+
@utility (single source, dark-adaptive). The `.chassis-divider` host
|
|
277
|
+
`@apply`s it, publishing `--twin-line-catch` / `--twin-line-shadow`; these
|
|
278
|
+
rules read the tokens. The prior Q.W4.A light pair (0.10 / 0.12) and the
|
|
279
|
+
dark pair (0.06 / 0.18) are the values the utility resolves. */
|
|
280
|
+
.bezel-line.top { background: var(--twin-line-catch); }
|
|
281
|
+
.bezel-line.bottom { background: var(--twin-line-shadow); }
|
|
285
282
|
|
|
286
283
|
/* Inner dial divider — same primitive, vertical on desktop. Speedtest
|
|
287
284
|
slots its <ChassisDivider orientation="vertical" class="dial-divider" />
|