@leavepulse/ui 0.78.2 → 0.78.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.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineComponent, computed, useModel, ref, useId, onMounted, watch, nextTick, onBeforeUnmount, useSlots, openBlock, createElementBlock, mergeProps, unref, createElementVNode, withModifiers, toDisplayString, normalizeClass, createVNode, createSlots, withCtx, renderSlot, normalizeProps, guardReactiveProps, normalizeStyle, createCommentVNode, withDirectives, vShow, createBlock, Teleport, mergeModels } from "vue";
|
|
2
2
|
import { prefersReducedMotion, easingToken, durationToken } from "../composables/easing.js";
|
|
3
3
|
import { useLabels } from "../composables/useLpConfig.js";
|
|
4
|
+
import { useResizeObserver } from "../composables/useResizeObserver.js";
|
|
4
5
|
import { useScrollMemory } from "../composables/scrollMemory.js";
|
|
5
6
|
import { useView, viewWindow } from "../composables/useView.js";
|
|
6
7
|
import { _ as _sfc_main$6 } from "./AppShellContextNav-C6Ho2mof.js";
|
|
@@ -14,7 +15,7 @@ import { _ as _sfc_main$7 } from "./LpScrollArea-CqvwfZs2.js";
|
|
|
14
15
|
import { _ as _sfc_main$5 } from "./LpShift-DAgS_d2x.js";
|
|
15
16
|
import { _ as _sfc_main$1 } from "./LpSidebar-CvRvVBTt.js";
|
|
16
17
|
import { mergeClass, useMergedAttrs } from "../composables/useMergedClass.js";
|
|
17
|
-
import { nodeWindow } from "../composables/realm.js";
|
|
18
|
+
import { nodeWindow, isHTMLElement } from "../composables/realm.js";
|
|
18
19
|
const _hoisted_1 = ["href"];
|
|
19
20
|
const _hoisted_2 = { class: "truncate text-lg font-semibold" };
|
|
20
21
|
const _hoisted_3 = ["data-lp-density"];
|
|
@@ -132,8 +133,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
132
133
|
() => props.path,
|
|
133
134
|
() => props.hash,
|
|
134
135
|
"",
|
|
135
|
-
// The sticky header
|
|
136
|
-
() => documentScroll && !bleeding.value ? headerEl.value?.offsetHeight ?? 0 : 0
|
|
136
|
+
// The sticky header and sub-page row cover the top of the window; a region starts below them.
|
|
137
|
+
() => documentScroll && !bleeding.value ? (headerEl.value?.offsetHeight ?? 0) + contextRowHeight.value : 0
|
|
137
138
|
);
|
|
138
139
|
useScrollMemory(
|
|
139
140
|
() => asideArea.value?.viewportEl,
|
|
@@ -180,14 +181,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
180
181
|
});
|
|
181
182
|
const bottomBarEl = ref(null);
|
|
182
183
|
const bottomBarHeight = ref(0);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
onBeforeUnmount(() => bottomBarSize?.disconnect());
|
|
184
|
+
useResizeObserver(
|
|
185
|
+
() => bottomBarEl.value?.$el?.nodeType === 1 ? bottomBarEl.value.$el : null,
|
|
186
|
+
(_, el) => bottomBarHeight.value = el.offsetHeight,
|
|
187
|
+
{ immediate: true }
|
|
188
|
+
);
|
|
189
|
+
const contextRowEl = ref(null);
|
|
190
|
+
const contextRowHeight = ref(0);
|
|
191
191
|
let releaseDocument;
|
|
192
192
|
onMounted(() => {
|
|
193
193
|
if (!documentScroll || !pageEl.value) return;
|
|
@@ -250,7 +250,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
250
250
|
const columnClass = computed(() => hasAside.value ? "grid min-w-0 flex-1 grid-cols-[minmax(0,1fr)_auto]" : "flex min-w-0 flex-1 flex-col");
|
|
251
251
|
const columnStyle = computed(() => ({
|
|
252
252
|
...hasAside.value ? { gridTemplateRows: `auto ${contextVisible.value ? "auto " : ""}minmax(0,1fr) auto` } : {},
|
|
253
|
-
...
|
|
253
|
+
...shellVars.value
|
|
254
254
|
}));
|
|
255
255
|
const spanClass = computed(() => hasAside.value ? "col-span-2" : void 0);
|
|
256
256
|
const view = useView();
|
|
@@ -280,6 +280,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
280
280
|
const contextVisible = computed(
|
|
281
281
|
() => (navMode.value === "bottom" || navMode.value === "drawer") && (contextItems.value.length > 0 || !!slots["context-nav"] && !!props.adaptiveNav?.contextNav)
|
|
282
282
|
);
|
|
283
|
+
watch(
|
|
284
|
+
[contextVisible, mounted],
|
|
285
|
+
() => {
|
|
286
|
+
const next = headerEl.value?.nextElementSibling;
|
|
287
|
+
contextRowEl.value = contextVisible.value && isHTMLElement(next) && next !== mainEl.value ? next : null;
|
|
288
|
+
if (!contextRowEl.value) contextRowHeight.value = 0;
|
|
289
|
+
},
|
|
290
|
+
{ flush: "post" }
|
|
291
|
+
);
|
|
292
|
+
useResizeObserver(contextRowEl, (_, el) => contextRowHeight.value = el.offsetHeight, { immediate: true });
|
|
283
293
|
function onSelect(item) {
|
|
284
294
|
emit("select", item);
|
|
285
295
|
}
|
|
@@ -315,7 +325,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
315
325
|
);
|
|
316
326
|
const STICKY = "sticky z-(--z-sticky)";
|
|
317
327
|
const railClass = computed(() => windowScrolls.value ? "sticky top-0 flex h-dvh shrink-0 self-start" : "contents");
|
|
318
|
-
const
|
|
328
|
+
const shellHeader = computed(() => headerHidden.value ? "0px" : headerHeight.value);
|
|
329
|
+
const shellVars = computed(
|
|
330
|
+
() => windowScrolls.value ? {
|
|
331
|
+
"--lp-shell-header": shellHeader.value,
|
|
332
|
+
"--lp-shell-top": `calc(${shellHeader.value} + ${contextRowHeight.value}px)`,
|
|
333
|
+
"--lp-shell-bottom": `${bottomBarHeight.value}px`
|
|
334
|
+
} : { "--lp-shell-header": "0px", "--lp-shell-top": "0px", "--lp-shell-bottom": "0px" }
|
|
335
|
+
);
|
|
319
336
|
const BACK_TO_TOP_ABOVE_BAR = {
|
|
320
337
|
sm: "bottom-[calc(4.5rem+env(safe-area-inset-bottom))] sm:bottom-[calc(1rem+env(safe-area-inset-bottom))]",
|
|
321
338
|
md: "bottom-[calc(4.5rem+env(safe-area-inset-bottom))] md:bottom-[calc(1rem+env(safe-area-inset-bottom))]",
|
|
@@ -478,7 +495,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
478
495
|
mode: navMode.value
|
|
479
496
|
}, () => [
|
|
480
497
|
createVNode(_sfc_main$6, {
|
|
481
|
-
class: normalizeClass([spanClass.value, windowScrolls.value && `${STICKY} top-(--lp-shell-
|
|
498
|
+
class: normalizeClass([spanClass.value, windowScrolls.value && `${STICKY} top-(--lp-shell-header) transition-[top] duration-[var(--duration-medium)] ease-[var(--ease-settle)]`]),
|
|
482
499
|
items: contextItems.value,
|
|
483
500
|
"is-active": activeTest.value,
|
|
484
501
|
label: unref(text).contextNav,
|
|
@@ -575,8 +592,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
575
592
|
windowScrolls.value && __props.pageScrollbar ? (openBlock(), createBlock(_sfc_main$8, {
|
|
576
593
|
key: 2,
|
|
577
594
|
top: "var(--lp-shell-top)",
|
|
578
|
-
bottom:
|
|
579
|
-
}
|
|
595
|
+
bottom: "var(--lp-shell-bottom)"
|
|
596
|
+
})) : createCommentVNode("", true),
|
|
580
597
|
__props.bottomNav ? (openBlock(), createBlock(_sfc_main$9, {
|
|
581
598
|
key: 3,
|
|
582
599
|
ref_key: "bottomBarEl",
|
|
@@ -54,6 +54,15 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
54
54
|
* `min-h-[calc(100dvh-4rem)]` or `fullBleed`. `"region"`: the shell is
|
|
55
55
|
* the viewport and the page scrolls inside main. Read once: changing it
|
|
56
56
|
* remounts the page.
|
|
57
|
+
*
|
|
58
|
+
* A page's own sticky parts keep clear of the shell's with two variables
|
|
59
|
+
* set inside it: `--lp-shell-top`, how much of the window's top the shell
|
|
60
|
+
* covers (the header, 0 while `headerCollapse` has it away, plus the
|
|
61
|
+
* sub-page row), and `--lp-shell-bottom`, how much of its foot (the bottom
|
|
62
|
+
* bar). Both change as those do, and are 0px in `"region"` and on a
|
|
63
|
+
* `fullBleed` page, where nothing of the shell's lies over the page:
|
|
64
|
+
* `position: sticky; top: var(--lp-shell-top)`. Keep the page's sticky
|
|
65
|
+
* layers under `--z-sticky`, the shell's.
|
|
57
66
|
*/
|
|
58
67
|
scroll?: "document" | "region";
|
|
59
68
|
/**
|
|
@@ -210,6 +219,15 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
210
219
|
* `min-h-[calc(100dvh-4rem)]` or `fullBleed`. `"region"`: the shell is
|
|
211
220
|
* the viewport and the page scrolls inside main. Read once: changing it
|
|
212
221
|
* remounts the page.
|
|
222
|
+
*
|
|
223
|
+
* A page's own sticky parts keep clear of the shell's with two variables
|
|
224
|
+
* set inside it: `--lp-shell-top`, how much of the window's top the shell
|
|
225
|
+
* covers (the header, 0 while `headerCollapse` has it away, plus the
|
|
226
|
+
* sub-page row), and `--lp-shell-bottom`, how much of its foot (the bottom
|
|
227
|
+
* bar). Both change as those do, and are 0px in `"region"` and on a
|
|
228
|
+
* `fullBleed` page, where nothing of the shell's lies over the page:
|
|
229
|
+
* `position: sticky; top: var(--lp-shell-top)`. Keep the page's sticky
|
|
230
|
+
* layers under `--z-sticky`, the shell's.
|
|
213
231
|
*/
|
|
214
232
|
scroll?: "document" | "region";
|
|
215
233
|
/**
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { _ as _3 } from "./chunks/LpMapPicker-D5_YLLBC.js";
|
|
|
4
4
|
import { OSM_TILES, createNominatimProvider, emptyAddress, formatAddress, project, tileUrl, unproject } from "./components/address.js";
|
|
5
5
|
import { _ as _4 } from "./chunks/LpActionBar-BGMk5KoG.js";
|
|
6
6
|
import { _ as _5 } from "./chunks/LpAlert-CjvTZIKF.js";
|
|
7
|
-
import { _ as _6 } from "./chunks/LpAppShell-
|
|
7
|
+
import { _ as _6 } from "./chunks/LpAppShell-DRHoQtr-.js";
|
|
8
8
|
import { _ as _7 } from "./chunks/LpAutocomplete-CrZbd0uv.js";
|
|
9
9
|
import { _ as _8 } from "./chunks/LpAvatar-cQVsNk6F.js";
|
|
10
10
|
import { _ as _9 } from "./chunks/LpBadge-D5QQdDQ_.js";
|
package/package.json
CHANGED
|
@@ -47,8 +47,9 @@ export default { inheritAttrs: false }
|
|
|
47
47
|
import { computed, nextTick, onBeforeUnmount, onMounted, ref, useId, useSlots, watch } from "vue"
|
|
48
48
|
import { easingToken, durationToken, prefersReducedMotion } from "../composables/easing"
|
|
49
49
|
import { useLabels } from "../composables/useLpConfig"
|
|
50
|
+
import { useResizeObserver } from "../composables/useResizeObserver"
|
|
50
51
|
import { useScrollMemory } from "../composables/scrollMemory"
|
|
51
|
-
import { nodeWindow, useView, viewWindow } from "../composables/useView"
|
|
52
|
+
import { isHTMLElement, nodeWindow, useView, viewWindow } from "../composables/useView"
|
|
52
53
|
import AppShellContextNav from "./AppShellContextNav.vue"
|
|
53
54
|
import {
|
|
54
55
|
contextNavItems,
|
|
@@ -129,6 +130,15 @@ const props = withDefaults(
|
|
|
129
130
|
* `min-h-[calc(100dvh-4rem)]` or `fullBleed`. `"region"`: the shell is
|
|
130
131
|
* the viewport and the page scrolls inside main. Read once: changing it
|
|
131
132
|
* remounts the page.
|
|
133
|
+
*
|
|
134
|
+
* A page's own sticky parts keep clear of the shell's with two variables
|
|
135
|
+
* set inside it: `--lp-shell-top`, how much of the window's top the shell
|
|
136
|
+
* covers (the header, 0 while `headerCollapse` has it away, plus the
|
|
137
|
+
* sub-page row), and `--lp-shell-bottom`, how much of its foot (the bottom
|
|
138
|
+
* bar). Both change as those do, and are 0px in `"region"` and on a
|
|
139
|
+
* `fullBleed` page, where nothing of the shell's lies over the page:
|
|
140
|
+
* `position: sticky; top: var(--lp-shell-top)`. Keep the page's sticky
|
|
141
|
+
* layers under `--z-sticky`, the shell's.
|
|
132
142
|
*/
|
|
133
143
|
scroll?: "document" | "region"
|
|
134
144
|
/**
|
|
@@ -329,8 +339,8 @@ useScrollMemory(
|
|
|
329
339
|
() => props.path,
|
|
330
340
|
() => props.hash,
|
|
331
341
|
"",
|
|
332
|
-
// The sticky header
|
|
333
|
-
() => (documentScroll && !bleeding.value ? (headerEl.value?.offsetHeight ?? 0) : 0),
|
|
342
|
+
// The sticky header and sub-page row cover the top of the window; a region starts below them.
|
|
343
|
+
() => (documentScroll && !bleeding.value ? (headerEl.value?.offsetHeight ?? 0) + contextRowHeight.value : 0),
|
|
334
344
|
)
|
|
335
345
|
// The side region keeps its own place on the same address.
|
|
336
346
|
useScrollMemory(
|
|
@@ -389,17 +399,19 @@ watch(bleeding, (bleed) => {
|
|
|
389
399
|
void nextTick(() => view.scrollTo({ top, behavior: "instant" }))
|
|
390
400
|
}
|
|
391
401
|
})
|
|
392
|
-
|
|
402
|
+
/*
|
|
403
|
+
* What the shell's sticky bars cover of the window, for the page: the sub-page
|
|
404
|
+
* row's height (it sits under the header) and the bottom bar's (0 where hidden).
|
|
405
|
+
*/
|
|
393
406
|
const bottomBarEl = ref<{ $el: HTMLElement } | null>(null)
|
|
394
407
|
const bottomBarHeight = ref(0)
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
onBeforeUnmount(() => bottomBarSize?.disconnect())
|
|
408
|
+
useResizeObserver(
|
|
409
|
+
() => (bottomBarEl.value?.$el?.nodeType === 1 ? bottomBarEl.value.$el : null),
|
|
410
|
+
(_, el) => (bottomBarHeight.value = (el as HTMLElement).offsetHeight),
|
|
411
|
+
{ immediate: true },
|
|
412
|
+
)
|
|
413
|
+
const contextRowEl = ref<HTMLElement | null>(null)
|
|
414
|
+
const contextRowHeight = ref(0)
|
|
403
415
|
|
|
404
416
|
let releaseDocument: (() => void) | undefined
|
|
405
417
|
onMounted(() => {
|
|
@@ -480,7 +492,7 @@ const asideClasses = computed(() =>
|
|
|
480
492
|
const columnClass = computed(() => (hasAside.value ? "grid min-w-0 flex-1 grid-cols-[minmax(0,1fr)_auto]" : "flex min-w-0 flex-1 flex-col"))
|
|
481
493
|
const columnStyle = computed(() => ({
|
|
482
494
|
...(hasAside.value ? { gridTemplateRows: `auto ${contextVisible.value ? "auto " : ""}minmax(0,1fr) auto` } : {}),
|
|
483
|
-
...
|
|
495
|
+
...shellVars.value,
|
|
484
496
|
}))
|
|
485
497
|
const spanClass = computed(() => (hasAside.value ? "col-span-2" : undefined))
|
|
486
498
|
|
|
@@ -520,6 +532,17 @@ const contextItems = computed(() => (props.adaptiveNav?.contextNav ? contextNavI
|
|
|
520
532
|
const contextVisible = computed(
|
|
521
533
|
() => (navMode.value === "bottom" || navMode.value === "drawer") && (contextItems.value.length > 0 || (!!slots["context-nav"] && !!props.adaptiveNav?.contextNav)),
|
|
522
534
|
)
|
|
535
|
+
// The row is the app's own slot or the shell's, so it is found where it renders: right after the header.
|
|
536
|
+
watch(
|
|
537
|
+
[contextVisible, mounted],
|
|
538
|
+
() => {
|
|
539
|
+
const next = headerEl.value?.nextElementSibling
|
|
540
|
+
contextRowEl.value = contextVisible.value && isHTMLElement(next) && next !== mainEl.value ? next : null
|
|
541
|
+
if (!contextRowEl.value) contextRowHeight.value = 0
|
|
542
|
+
},
|
|
543
|
+
{ flush: "post" },
|
|
544
|
+
)
|
|
545
|
+
useResizeObserver(contextRowEl, (_, el) => (contextRowHeight.value = (el as HTMLElement).offsetHeight), { immediate: true })
|
|
523
546
|
|
|
524
547
|
function onSelect(item: SidebarItem) {
|
|
525
548
|
emit("select", item)
|
|
@@ -564,12 +587,27 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
|
|
|
564
587
|
|
|
565
588
|
/*
|
|
566
589
|
* What stays in view while the window scrolls the page. The header sits on
|
|
567
|
-
* top; the row of sub-pages
|
|
568
|
-
*
|
|
590
|
+
* top; the row of sub-pages sits under it and follows it out when it
|
|
591
|
+
* collapses (--lp-shell-header is how much of the header is showing).
|
|
592
|
+
*
|
|
593
|
+
* Two variables are the page's to use (documented on `scroll`), and set in
|
|
594
|
+
* every mode, so `var(--lp-shell-top)` never needs a fallback:
|
|
595
|
+
* --lp-shell-top is how much of the window's top the shell covers (header
|
|
596
|
+
* plus sub-page row), --lp-shell-bottom how much of its foot (the bottom
|
|
597
|
+
* bar). Both are 0px where the page scrolls in its own region or is full bleed.
|
|
569
598
|
*/
|
|
570
599
|
const STICKY = "sticky z-(--z-sticky)"
|
|
571
600
|
const railClass = computed(() => (windowScrolls.value ? "sticky top-0 flex h-dvh shrink-0 self-start" : "contents"))
|
|
572
|
-
const
|
|
601
|
+
const shellHeader = computed(() => (headerHidden.value ? "0px" : headerHeight.value))
|
|
602
|
+
const shellVars = computed(() =>
|
|
603
|
+
windowScrolls.value
|
|
604
|
+
? {
|
|
605
|
+
"--lp-shell-header": shellHeader.value,
|
|
606
|
+
"--lp-shell-top": `calc(${shellHeader.value} + ${contextRowHeight.value}px)`,
|
|
607
|
+
"--lp-shell-bottom": `${bottomBarHeight.value}px`,
|
|
608
|
+
}
|
|
609
|
+
: { "--lp-shell-header": "0px", "--lp-shell-top": "0px", "--lp-shell-bottom": "0px" },
|
|
610
|
+
)
|
|
573
611
|
const BACK_TO_TOP_ABOVE_BAR: Record<NavBreakpoint, string> = {
|
|
574
612
|
sm: "bottom-[calc(4.5rem+env(safe-area-inset-bottom))] sm:bottom-[calc(1rem+env(safe-area-inset-bottom))]",
|
|
575
613
|
md: "bottom-[calc(4.5rem+env(safe-area-inset-bottom))] md:bottom-[calc(1rem+env(safe-area-inset-bottom))]",
|
|
@@ -725,7 +763,7 @@ const backToTopClass = computed(() =>
|
|
|
725
763
|
<template v-if="contextVisible">
|
|
726
764
|
<slot name="context-nav" :items="contextItems" :mode="navMode">
|
|
727
765
|
<AppShellContextNav
|
|
728
|
-
:class="[spanClass, windowScrolls && `${STICKY} top-(--lp-shell-
|
|
766
|
+
:class="[spanClass, windowScrolls && `${STICKY} top-(--lp-shell-header) transition-[top] duration-[var(--duration-medium)] ease-[var(--ease-settle)]`]"
|
|
729
767
|
:items="contextItems"
|
|
730
768
|
:is-active="activeTest"
|
|
731
769
|
:label="text.contextNav"
|
|
@@ -769,7 +807,7 @@ const backToTopClass = computed(() =>
|
|
|
769
807
|
<slot name="aside" />
|
|
770
808
|
</LpScrollArea>
|
|
771
809
|
</aside>
|
|
772
|
-
<LpPageScrollbar v-if="windowScrolls && pageScrollbar" top="var(--lp-shell-top)"
|
|
810
|
+
<LpPageScrollbar v-if="windowScrolls && pageScrollbar" top="var(--lp-shell-top)" bottom="var(--lp-shell-bottom)" />
|
|
773
811
|
<LpBottomNav
|
|
774
812
|
v-if="bottomNav"
|
|
775
813
|
ref="bottomBarEl"
|