@celestia-island/hikari 0.51.1 → 0.51.3
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/package.json
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
// handle hasn't resolved yet — zIndex briefly starts at 0).
|
|
32
32
|
z-index: 0;
|
|
33
33
|
background: var(--hk-modal-overlay-bg, rgba(0, 0, 0, 0.45));
|
|
34
|
-
backdrop-filter: var(--hk-modal-overlay-blur, blur(
|
|
34
|
+
backdrop-filter: var(--hk-modal-overlay-blur, blur(3px));
|
|
35
35
|
pointer-events: auto;
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
// viewport in place, never sliding or scaling with the content frame.
|
|
41
41
|
@include sf.scrim-fade(
|
|
42
42
|
"hk-modal-overlay",
|
|
43
|
-
$enter-duration: var(--hk-modal-duration, 0.
|
|
44
|
-
$enter-ease: var(--hk-modal-ease-out, cubic-bezier(0.
|
|
45
|
-
$leave-duration: var(--hk-modal-duration, 0.
|
|
46
|
-
$leave-ease: var(--hk-modal-ease-in, cubic-bezier(0.
|
|
43
|
+
$enter-duration: var(--hk-modal-duration, 0.42s),
|
|
44
|
+
$enter-ease: var(--hk-modal-ease-out, cubic-bezier(0.33, 1, 0.68, 1)),
|
|
45
|
+
$leave-duration: var(--hk-modal-duration, 0.42s),
|
|
46
|
+
$leave-ease: var(--hk-modal-ease-in, cubic-bezier(0.45, 0, 0.55, 1))
|
|
47
47
|
);
|
|
48
48
|
|
|
49
49
|
// ------
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
height var(--duration-fast, 0.15s) var(--ease-standard, cubic-bezier(0.4, 0, 0.2, 1)),
|
|
73
73
|
max-height var(--duration-fast, 0.15s) var(--ease-standard, cubic-bezier(0.4, 0, 0.2, 1));
|
|
74
74
|
background: var(--hk-modal-bg, var(--hi-color-surface, rgba(240,244,248,0.95)));
|
|
75
|
-
backdrop-filter: var(--hk-modal-blur,
|
|
75
|
+
backdrop-filter: var(--hk-modal-blur, none);
|
|
76
76
|
border: 1px solid var(--hk-modal-border-color, var(--hi-color-border, rgba(100,100,100,0.08)));
|
|
77
77
|
border-radius: var(--hk-modal-radius, var(--radius-lg, 12px));
|
|
78
78
|
box-shadow:
|
|
@@ -109,12 +109,12 @@
|
|
|
109
109
|
@media (min-width: 768px) {
|
|
110
110
|
.hk-modal-content-enter-active {
|
|
111
111
|
transition:
|
|
112
|
-
opacity var(--hk-modal-duration, 0.
|
|
113
|
-
var(--hk-modal-ease-out, cubic-bezier(0.
|
|
114
|
-
transform var(--hk-modal-duration, 0.
|
|
115
|
-
var(--hk-modal-ease-out, cubic-bezier(0.
|
|
116
|
-
clip-path var(--hk-modal-duration, 0.
|
|
117
|
-
var(--hk-modal-ease-out, cubic-bezier(0.
|
|
112
|
+
opacity var(--hk-modal-duration, 0.42s)
|
|
113
|
+
var(--hk-modal-ease-out, cubic-bezier(0.33, 1, 0.68, 1)),
|
|
114
|
+
transform var(--hk-modal-duration, 0.42s)
|
|
115
|
+
var(--hk-modal-ease-out, cubic-bezier(0.33, 1, 0.68, 1)),
|
|
116
|
+
clip-path var(--hk-modal-duration, 0.42s)
|
|
117
|
+
var(--hk-modal-ease-out, cubic-bezier(0.33, 1, 0.68, 1));
|
|
118
118
|
will-change: transform, opacity, clip-path;
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -125,16 +125,11 @@
|
|
|
125
125
|
// (user report 2026-09-14).
|
|
126
126
|
.hk-modal-content-leave-active {
|
|
127
127
|
transition:
|
|
128
|
-
opacity var(--hk-modal-duration, 0.
|
|
129
|
-
var(--hk-modal-ease-in, cubic-bezier(0.
|
|
130
|
-
transform var(--hk-modal-duration, 0.
|
|
131
|
-
var(--hk-modal-ease-in, cubic-bezier(0.
|
|
128
|
+
opacity var(--hk-modal-duration, 0.32s)
|
|
129
|
+
var(--hk-modal-ease-in, cubic-bezier(0.45, 0, 0.55, 1)),
|
|
130
|
+
transform var(--hk-modal-duration, 0.32s)
|
|
131
|
+
var(--hk-modal-ease-in, cubic-bezier(0.45, 0, 0.55, 1));
|
|
132
132
|
will-change: transform, opacity;
|
|
133
|
-
// Collapse toward the frame's own top edge: the height shrink reads as
|
|
134
|
-
// the box folding upward (the unveil's reverse), not as a centered
|
|
135
|
-
// shrink — and the top-of-content (header) keeps its anchor while the
|
|
136
|
-
// rest eases down and out with the fade.
|
|
137
|
-
transform-origin: 50% 0;
|
|
138
133
|
}
|
|
139
134
|
|
|
140
135
|
.hk-modal-content-enter-from {
|
|
@@ -153,12 +148,12 @@
|
|
|
153
148
|
|
|
154
149
|
.hk-modal-content-leave-from {
|
|
155
150
|
opacity: 1;
|
|
156
|
-
transform: translate(-50%, -50%)
|
|
151
|
+
transform: translate(-50%, -50%);
|
|
157
152
|
}
|
|
158
153
|
|
|
159
154
|
.hk-modal-content-leave-to {
|
|
160
155
|
opacity: 0;
|
|
161
|
-
transform: translate(-50%, -50%)
|
|
156
|
+
transform: translate(-50%, -50%) translateY(5%);
|
|
162
157
|
}
|
|
163
158
|
}
|
|
164
159
|
|
|
@@ -445,17 +440,17 @@
|
|
|
445
440
|
// Sheet slide reveal replaces the height-clip reveal on mobile.
|
|
446
441
|
.hk-modal-content-enter-active {
|
|
447
442
|
transition:
|
|
448
|
-
opacity var(--hk-modal-duration, 0.
|
|
449
|
-
transform var(--hk-modal-duration, 0.
|
|
450
|
-
var(--hk-modal-ease-out, cubic-bezier(0.
|
|
443
|
+
opacity var(--hk-modal-duration, 0.42s) ease-out,
|
|
444
|
+
transform var(--hk-modal-duration, 0.42s)
|
|
445
|
+
var(--hk-modal-ease-out, cubic-bezier(0.33, 1, 0.68, 1));
|
|
451
446
|
will-change: transform, opacity;
|
|
452
447
|
}
|
|
453
448
|
|
|
454
449
|
.hk-modal-content-leave-active {
|
|
455
450
|
transition:
|
|
456
|
-
opacity var(--hk-modal-duration, 0.
|
|
457
|
-
transform var(--hk-modal-duration, 0.
|
|
458
|
-
var(--hk-modal-ease-in, cubic-bezier(0.
|
|
451
|
+
opacity var(--hk-modal-duration, 0.32s) ease-in,
|
|
452
|
+
transform var(--hk-modal-duration, 0.32s)
|
|
453
|
+
var(--hk-modal-ease-in, cubic-bezier(0.45, 0, 0.55, 1));
|
|
459
454
|
will-change: transform, opacity;
|
|
460
455
|
}
|
|
461
456
|
|
|
@@ -474,13 +469,8 @@
|
|
|
474
469
|
padding: 0.625rem 1rem 0.625rem;
|
|
475
470
|
}
|
|
476
471
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
.hk-modal-body {
|
|
480
|
-
--hk-scroll-pad-top: 1rem;
|
|
481
|
-
--hk-scroll-pad-right: 1rem;
|
|
482
|
-
--hk-scroll-pad-bottom: 1rem;
|
|
483
|
-
--hk-scroll-pad-left: 1rem;
|
|
472
|
+
.hk-modal-body-inner {
|
|
473
|
+
padding: 1rem;
|
|
484
474
|
}
|
|
485
475
|
|
|
486
476
|
// Lift the desktop 70vh body cap on phones: with a docked sheet the cap
|
|
@@ -491,6 +481,13 @@
|
|
|
491
481
|
// scrolls, and the footer always sits on the sheet's bottom edge.
|
|
492
482
|
.hk-modal-body {
|
|
493
483
|
max-height: none;
|
|
484
|
+
|
|
485
|
+
// The gutter contract retunes here too — the covers and the inner's
|
|
486
|
+
// padding both consume the vars, so one override moves both.
|
|
487
|
+
--hk-scroll-pad-top: 1rem;
|
|
488
|
+
--hk-scroll-pad-right: 1rem;
|
|
489
|
+
--hk-scroll-pad-bottom: 1rem;
|
|
490
|
+
--hk-scroll-pad-left: 1rem;
|
|
494
491
|
}
|
|
495
492
|
|
|
496
493
|
.hk-modal-footer {
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Dock-slot contract for HkScrollContainer.
|
|
2
|
+
//
|
|
3
|
+
// A dock (dockTop / dockBottom named slot) renders as a NON-scrolling
|
|
4
|
+
// flex sibling of the viewport: pinned to its edge, occupying layout
|
|
5
|
+
// space (the flex: 1 viewport shrinks by the dock's height — content
|
|
6
|
+
// can never slide under it). The container measures each mounted dock
|
|
7
|
+
// and publishes --hk-scroll-dock-top / --hk-scroll-dock-bottom on the
|
|
8
|
+
// host so consumers size their content end-padding against the dock
|
|
9
|
+
// without hand-rolled px. The dock-edge fade rides on data-dock-fade.
|
|
10
|
+
//
|
|
11
|
+
// House style: raw createApp mounts on shared containers (no
|
|
12
|
+
// @vue/test-utils).
|
|
13
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
14
|
+
import { createApp, h, defineComponent } from "vue";
|
|
15
|
+
|
|
16
|
+
import HkScrollContainer from "./HkScrollContainer";
|
|
17
|
+
|
|
18
|
+
const mounts: ReturnType<typeof createApp>[] = [];
|
|
19
|
+
const containers: HTMLElement[] = [];
|
|
20
|
+
|
|
21
|
+
function mountDock(slots: Record<string, () => any>, props: Record<string, unknown> = {}) {
|
|
22
|
+
const container = document.createElement("div");
|
|
23
|
+
document.body.appendChild(container);
|
|
24
|
+
containers.push(container);
|
|
25
|
+
const app = createApp(defineComponent({
|
|
26
|
+
setup() {
|
|
27
|
+
return () => h(HkScrollContainer, props, slots);
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
30
|
+
mounts.push(app);
|
|
31
|
+
return app.mount(container);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
for (const app of mounts) app.unmount();
|
|
36
|
+
mounts.length = 0;
|
|
37
|
+
for (const el of containers) el.remove();
|
|
38
|
+
containers.length = 0;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe("HkScrollContainer dock slots", () => {
|
|
42
|
+
it("renders a bottom dock as a non-scrolling sibling with the fade marker", () => {
|
|
43
|
+
const vm = mountDock({
|
|
44
|
+
default: () => h("div", { class: "content" }, "rows"),
|
|
45
|
+
dockBottom: () => h("div", { class: "the-dock" }, "dock"),
|
|
46
|
+
});
|
|
47
|
+
const host = vm.$el as HTMLElement;
|
|
48
|
+
const dock = host.querySelector(".hk-scroll-dock[data-side='bottom']");
|
|
49
|
+
expect(dock).toBeTruthy();
|
|
50
|
+
// Sibling of the viewport, not inside it — the dock never scrolls.
|
|
51
|
+
const viewport = host.querySelector(".hk-scroll-container-viewport")!;
|
|
52
|
+
expect(viewport.contains(dock as Node)).toBe(false);
|
|
53
|
+
// The dock-edge fade engages by default for a bottom dock.
|
|
54
|
+
expect(host.getAttribute("data-dock-fade")).toBe("bottom");
|
|
55
|
+
// The measured-height vars are published on the host (0px in
|
|
56
|
+
// happy-dom — no layout; the contract is the vars exist + RO wired).
|
|
57
|
+
expect(host.style.getPropertyValue("--hk-scroll-dock-bottom")).toBe("0px");
|
|
58
|
+
expect(host.style.getPropertyValue("--hk-scroll-dock-top")).toBe("0px");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("renders a top dock and fades the top edge instead", () => {
|
|
62
|
+
const vm = mountDock({
|
|
63
|
+
default: () => h("div", { class: "content" }, "rows"),
|
|
64
|
+
dockTop: () => h("div", { class: "the-dock" }, "progress"),
|
|
65
|
+
});
|
|
66
|
+
const host = vm.$el as HTMLElement;
|
|
67
|
+
expect(host.querySelector(".hk-scroll-dock[data-side='top']")).toBeTruthy();
|
|
68
|
+
expect(host.getAttribute("data-dock-fade")).toBe("top");
|
|
69
|
+
expect(host.querySelector(".hk-scroll-dock[data-side='bottom']")).toBeNull();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("omits the dock fade marker when dockFade is off", () => {
|
|
73
|
+
const vm = mountDock(
|
|
74
|
+
{
|
|
75
|
+
default: () => h("div", { class: "content" }, "rows"),
|
|
76
|
+
dockBottom: () => h("div", { class: "the-dock" }, "dock"),
|
|
77
|
+
},
|
|
78
|
+
{ dockFade: false },
|
|
79
|
+
);
|
|
80
|
+
const host = vm.$el as HTMLElement;
|
|
81
|
+
expect(host.querySelector(".hk-scroll-dock[data-side='bottom']")).toBeTruthy();
|
|
82
|
+
expect(host.getAttribute("data-dock-fade")).toBeNull();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("publishes no dock marker without dock slots", () => {
|
|
86
|
+
const vm = mountDock({ default: () => h("div", { class: "content" }, "rows") });
|
|
87
|
+
const host = vm.$el as HTMLElement;
|
|
88
|
+
expect(host.querySelector(".hk-scroll-dock")).toBeNull();
|
|
89
|
+
expect(host.getAttribute("data-dock-fade")).toBeNull();
|
|
90
|
+
expect(host.style.getPropertyValue("--hk-scroll-dock-bottom")).toBe("");
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -53,6 +53,38 @@
|
|
|
53
53
|
mask-image: linear-gradient(to left, transparent 0, #000 var(--hk-scroll-fade-size));
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/* ── Anchored docks (dockTop / dockBottom slots) ─────────────────
|
|
57
|
+
A dock renders as a NON-scrolling flex sibling of the viewport: it
|
|
58
|
+
stays pinned to its edge, never scrolls, and occupies layout space —
|
|
59
|
+
the flex: 1 viewport shrinks by the dock's height, so the content's
|
|
60
|
+
scroll end lands exactly at the dock's edge and can never slide
|
|
61
|
+
under it. The container measures each mounted dock (ResizeObserver)
|
|
62
|
+
and publishes --hk-scroll-dock-top / --hk-scroll-dock-bottom on the
|
|
63
|
+
host, so a consumer's content end-padding clears the dock with
|
|
64
|
+
breathing room (padding-bottom: calc(var(--hk-scroll-dock-bottom)
|
|
65
|
+
+ 2rem)) instead of hand-rolled px guesses that go stale when the
|
|
66
|
+
dock reflows. */
|
|
67
|
+
.hk-scroll-dock {
|
|
68
|
+
flex: none;
|
|
69
|
+
min-height: 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Dock-edge fade: mid-scroll content dissolving at the dock's edge
|
|
73
|
+
(opacity 100 -> 0 across --hk-scroll-dock-fade) reads as intentional
|
|
74
|
+
instead of a hard clip against the dock's top edge. Content never
|
|
75
|
+
sits under the dock, so this fades the viewport's last few pixels,
|
|
76
|
+
not the dock itself. */
|
|
77
|
+
.hk-scroll-container[data-dock-fade="bottom"] > .hk-scroll-container-viewport {
|
|
78
|
+
-webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - var(--hk-scroll-dock-fade, 2rem)), transparent);
|
|
79
|
+
mask-image: linear-gradient(to bottom, #000 calc(100% - var(--hk-scroll-dock-fade, 2rem)), transparent);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.hk-scroll-container[data-dock-fade="top"] > .hk-scroll-container-viewport {
|
|
83
|
+
-webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--hk-scroll-dock-fade, 2rem));
|
|
84
|
+
mask-image: linear-gradient(to bottom, transparent, #000 var(--hk-scroll-dock-fade, 2rem));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
56
88
|
.hk-scroll-container[data-fade="true"][data-h-overflow="start"] > .hk-scroll-container-viewport {
|
|
57
89
|
-webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--hk-scroll-fade-size));
|
|
58
90
|
mask-image: linear-gradient(to right, transparent 0, #000 var(--hk-scroll-fade-size));
|
|
@@ -80,12 +80,21 @@ export default defineComponent({
|
|
|
80
80
|
* approaching (`approachEnd`). Read live, so runtime changes need
|
|
81
81
|
* no remount. */
|
|
82
82
|
approachDistance: { type: Number, default: 160 },
|
|
83
|
+
/** Fade the viewport's bottom edge (CSS mask, --hk-scroll-dock-fade
|
|
84
|
+
* tall, opacity 100 -> 0) while a dock slot is mounted, so mid-
|
|
85
|
+
* scroll content dissolving at the dock's edge reads as
|
|
86
|
+
* intentional instead of a hard clip. */
|
|
87
|
+
dockFade: { type: Boolean, default: true },
|
|
83
88
|
},
|
|
84
89
|
emits: { approachEnd: () => true },
|
|
85
90
|
setup(props, { slots, expose, emit }) {
|
|
86
91
|
const { t } = useI18n();
|
|
87
92
|
const viewportRef = ref<HTMLElement>();
|
|
93
|
+
const hostRef = ref<HTMLElement>();
|
|
94
|
+
const dockTopRef = ref<HTMLElement>();
|
|
95
|
+
const dockBottomRef = ref<HTMLElement>();
|
|
88
96
|
let ro: ResizeObserver | null = null;
|
|
97
|
+
let dockRO: ResizeObserver | null = null;
|
|
89
98
|
let scheduled: AnimationHandle | null = null;
|
|
90
99
|
// Overlay track/thumb machinery lives in the shared composable;
|
|
91
100
|
// this component keeps overflow sensing, autoFollow, the aligner,
|
|
@@ -292,10 +301,40 @@ export default defineComponent({
|
|
|
292
301
|
}
|
|
293
302
|
}
|
|
294
303
|
|
|
304
|
+
/** Publish each mounted dock's measured height as a host-level custom
|
|
305
|
+
* property (`--hk-scroll-dock-top` / `--hk-scroll-dock-bottom`). The
|
|
306
|
+
* dock is a non-scrolling flex sibling, so the viewport already
|
|
307
|
+
* shrinks by its height; the published var exists so a consumer's
|
|
308
|
+
* content end-padding can clear the dock with breathing room
|
|
309
|
+
* (padding-bottom: calc(var(--hk-scroll-dock-bottom, 0px) + 2rem))
|
|
310
|
+
* instead of hand-rolled px guesses that go stale when the dock
|
|
311
|
+
* reflows. ResizeObserver keeps it live across dock reflows. */
|
|
312
|
+
function publishDockSizes() {
|
|
313
|
+
const host = hostRef.value;
|
|
314
|
+
if (!host) return;
|
|
315
|
+
const top = dockTopRef.value;
|
|
316
|
+
const bottom = dockBottomRef.value;
|
|
317
|
+
host.style.setProperty(
|
|
318
|
+
"--hk-scroll-dock-top",
|
|
319
|
+
top ? `${Math.round(top.getBoundingClientRect().height)}px` : "0px",
|
|
320
|
+
);
|
|
321
|
+
host.style.setProperty(
|
|
322
|
+
"--hk-scroll-dock-bottom",
|
|
323
|
+
bottom ? `${Math.round(bottom.getBoundingClientRect().height)}px` : "0px",
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
295
327
|
onMounted(() => {
|
|
296
328
|
const vp = viewportRef.value;
|
|
297
329
|
if (!vp) return;
|
|
298
330
|
|
|
331
|
+
if (dockTopRef.value || dockBottomRef.value) {
|
|
332
|
+
dockRO = new ResizeObserver(publishDockSizes);
|
|
333
|
+
if (dockTopRef.value) dockRO.observe(dockTopRef.value);
|
|
334
|
+
if (dockBottomRef.value) dockRO.observe(dockBottomRef.value);
|
|
335
|
+
publishDockSizes();
|
|
336
|
+
}
|
|
337
|
+
|
|
299
338
|
if (props.scrollbar) {
|
|
300
339
|
mountScrollbars();
|
|
301
340
|
}
|
|
@@ -340,6 +379,8 @@ export default defineComponent({
|
|
|
340
379
|
settleHandle = null;
|
|
341
380
|
ro?.disconnect();
|
|
342
381
|
ro = null;
|
|
382
|
+
dockRO?.disconnect();
|
|
383
|
+
dockRO = null;
|
|
343
384
|
followRO?.disconnect();
|
|
344
385
|
followRO = null;
|
|
345
386
|
alignRO?.disconnect();
|
|
@@ -431,13 +472,34 @@ export default defineComponent({
|
|
|
431
472
|
if (alignCenter()) {
|
|
432
473
|
content = <div ref={setAligner} class="hk-scroll-container-aligner">{content}</div>;
|
|
433
474
|
}
|
|
475
|
+
// Anchored dock slots: a dock renders as a NON-scrolling flex
|
|
476
|
+
// sibling of the viewport — it stays pinned to its edge, never
|
|
477
|
+
// scrolls, and occupies layout space (the flex: 1 viewport shrinks
|
|
478
|
+
// by the dock's height). The container measures each mounted dock
|
|
479
|
+
// and publishes --hk-scroll-dock-top/bottom so consumers can size
|
|
480
|
+
// their content end-padding against the dock without guessing px.
|
|
481
|
+
const dockTopSlot = slots.dockTop;
|
|
482
|
+
const dockBottomSlot = slots.dockBottom;
|
|
434
483
|
return (
|
|
435
484
|
<Tag
|
|
485
|
+
ref={hostRef}
|
|
436
486
|
class="hk-scroll-container"
|
|
437
487
|
data-axis={props.axis}
|
|
438
488
|
data-align={alignCenter() ? "center" : undefined}
|
|
439
489
|
data-fade={props.fade ? "true" : undefined}
|
|
490
|
+
data-dock-fade={
|
|
491
|
+
props.dockFade && dockBottomSlot
|
|
492
|
+
? "bottom"
|
|
493
|
+
: props.dockFade && dockTopSlot
|
|
494
|
+
? "top"
|
|
495
|
+
: undefined
|
|
496
|
+
}
|
|
440
497
|
>
|
|
498
|
+
{dockTopSlot && (
|
|
499
|
+
<div ref={dockTopRef} class="hk-scroll-dock" data-side="top">
|
|
500
|
+
{dockTopSlot()}
|
|
501
|
+
</div>
|
|
502
|
+
)}
|
|
441
503
|
{/* Scroll-pin host marker: the viewport participates in the pin
|
|
442
504
|
contract with its live axis; generic containers declare no
|
|
443
505
|
standard padding, so pins inside resolve their strategy from
|
|
@@ -449,6 +511,11 @@ export default defineComponent({
|
|
|
449
511
|
>
|
|
450
512
|
{content}
|
|
451
513
|
</div>
|
|
514
|
+
{dockBottomSlot && (
|
|
515
|
+
<div ref={dockBottomRef} class="hk-scroll-dock" data-side="bottom">
|
|
516
|
+
{dockBottomSlot()}
|
|
517
|
+
</div>
|
|
518
|
+
)}
|
|
452
519
|
{showAutoTag.value && (
|
|
453
520
|
<span class="hk-scroll-container-autotag" aria-hidden="true">{t("hikari::scrollContainer.auto", "Auto")}</span>
|
|
454
521
|
)}
|