@leavepulse/ui 0.20.3 → 0.20.5

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.
Files changed (32) hide show
  1. package/dist/chunks/{LpAddressInput-DZxdRaVk.js → LpAddressInput-CK6y3xZm.js} +1 -1
  2. package/dist/chunks/{LpAppShell-D42la4ZD.js → LpAppShell-JWrWjNdC.js} +2 -2
  3. package/dist/chunks/{LpConfirmDialog-JEbhyY_y.js → LpConfirmDialog-ClefCHIT.js} +1 -1
  4. package/dist/chunks/{LpDrawer-CYm-nUIZ.js → LpDrawer-Dr1USsND.js} +1 -1
  5. package/dist/chunks/{LpFileTree-DXb3yKzH.js → LpFileTree-DcoePIZq.js} +1 -1
  6. package/dist/chunks/{LpLogViewer-tmKPNTuU.js → LpLogViewer-BDPbnCOU.js} +1 -2
  7. package/dist/chunks/{LpModal-DLgOAP4p.js → LpModal-BQvb6ekk.js} +1 -1
  8. package/dist/chunks/{LpNotificationBell-DHze8wYN.js → LpNotificationBell-DDzQY0YA.js} +1 -1
  9. package/dist/chunks/LpScrollArea-ZnycmmEI.js +120 -0
  10. package/dist/chunks/{LpSidebar-DlLZJk1u.js → LpSidebar-CC5759Mh.js} +2 -2
  11. package/dist/chunks/{LpSidebarNav-DSDa5mAY.js → LpSidebarNav-C0LjLp0O.js} +1 -1
  12. package/dist/chunks/{LpTable-DqZ-L4Au.js → LpTable-CWS2V4JO.js} +2 -1
  13. package/dist/components/LpAddressInput.vue.js +1 -1
  14. package/dist/components/LpAppShell.vue.js +1 -1
  15. package/dist/components/LpCommandPalette.vue.js +1 -1
  16. package/dist/components/LpConfirmDialog.vue.js +1 -1
  17. package/dist/components/LpDrawer.vue.js +1 -1
  18. package/dist/components/LpFileTree.vue.js +1 -1
  19. package/dist/components/LpLogViewer.vue.js +1 -1
  20. package/dist/components/LpModal.vue.js +1 -1
  21. package/dist/components/LpNotificationBell.vue.js +1 -1
  22. package/dist/components/LpScrollArea.vue.d.ts +3 -2
  23. package/dist/components/LpScrollArea.vue.js +1 -1
  24. package/dist/components/LpSidebar.vue.js +1 -1
  25. package/dist/components/LpSidebarNav.vue.js +1 -1
  26. package/dist/components/LpTable.vue.js +1 -1
  27. package/dist/index.js +11 -11
  28. package/package.json +1 -1
  29. package/src/components/LpLogViewer.vue +0 -1
  30. package/src/components/LpScrollArea.vue +91 -10
  31. package/src/components/LpTable.vue +7 -1
  32. package/dist/chunks/LpScrollArea-DQ0Yudfu.js +0 -72
@@ -6,7 +6,7 @@ import { _ as _sfc_main$3 } from "./LpButton-5VXXCjwF.js";
6
6
  import { _ as _sfc_main$1 } from "./LpFormField-Bn-ZwC6z.js";
7
7
  import { _ as _sfc_main$4 } from "./LpIcon-CCnX5_2j.js";
8
8
  import { _ as _sfc_main$5 } from "./LpInput-BauZRyzm.js";
9
- import { _ as _sfc_main$7 } from "./LpModal-DLgOAP4p.js";
9
+ import { _ as _sfc_main$7 } from "./LpModal-BQvb6ekk.js";
10
10
  import { _ as _sfc_main$6 } from "./LpSelect-D5mU4cZO.js";
11
11
  const _hoisted_1 = { class: "flex flex-col gap-3" };
12
12
  const _hoisted_2 = { class: "flex items-stretch gap-2" };
@@ -1,8 +1,8 @@
1
1
  import { defineComponent, computed, watch, openBlock, createElementBlock, createVNode, createSlots, withCtx, renderSlot, normalizeProps, guardReactiveProps, createElementVNode, normalizeClass, toDisplayString, createCommentVNode, createBlock } from "vue";
2
2
  import { _ as _sfc_main$2 } from "./LpButton-5VXXCjwF.js";
3
3
  import { _ as _sfc_main$3 } from "./LpIcon-CCnX5_2j.js";
4
- import { _ as _sfc_main$4 } from "./LpScrollArea-DQ0Yudfu.js";
5
- import { _ as _sfc_main$1 } from "./LpSidebar-DlLZJk1u.js";
4
+ import { _ as _sfc_main$4 } from "./LpScrollArea-ZnycmmEI.js";
5
+ import { _ as _sfc_main$1 } from "./LpSidebar-CC5759Mh.js";
6
6
  const _hoisted_1 = { class: "flex h-dvh overflow-hidden bg-surface text-ink" };
7
7
  const _hoisted_2 = { class: "flex min-w-0 flex-1 flex-col" };
8
8
  const _hoisted_3 = { class: "flex h-16 shrink-0 items-center gap-3 border-b border-line bg-surface px-4 md:px-6" };
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, openBlock, createBlock, withCtx, renderSlot, createVNode, createTextVNode, toDisplayString } from "vue";
2
2
  import { _ as _sfc_main$2 } from "./LpButton-5VXXCjwF.js";
3
- import { _ as _sfc_main$1 } from "./LpModal-DLgOAP4p.js";
3
+ import { _ as _sfc_main$1 } from "./LpModal-BQvb6ekk.js";
4
4
  const _sfc_main = /* @__PURE__ */ defineComponent({
5
5
  __name: "LpConfirmDialog",
6
6
  props: {
@@ -3,7 +3,7 @@ import { usePointerSwipe } from "@vueuse/core";
3
3
  import { DrawerRoot, DrawerPortal, DrawerOverlay, DrawerContent, DrawerHandle, DrawerTitle, DrawerDescription, DrawerClose } from "vaul-vue";
4
4
  import { CLOSE_ICON } from "../components/dropdown.js";
5
5
  import { _ as _sfc_main$1 } from "./LpIcon-CCnX5_2j.js";
6
- import { _ as _sfc_main$2 } from "./LpScrollArea-DQ0Yudfu.js";
6
+ import { _ as _sfc_main$2 } from "./LpScrollArea-ZnycmmEI.js";
7
7
  const _hoisted_1 = { class: "text-base font-semibold text-ink" };
8
8
  const _hoisted_2 = { class: "flex flex-col gap-1" };
9
9
  const _hoisted_3 = ["data-vaul-no-drag"];
@@ -2,7 +2,7 @@ import { defineComponent, ref, watch, computed, openBlock, createElementBlock, F
2
2
  import { formatSize, sortNodes, computeStats, subtreeIds, ancestorIds } from "../components/fileTree.js";
3
3
  import { _ as _sfc_main$1 } from "./LpEmptyState-CrfyRJUG.js";
4
4
  import { _ as _sfc_main$3 } from "./LpFileTreeNode-DFg4PhOK.js";
5
- import { _ as _sfc_main$2 } from "./LpScrollArea-DQ0Yudfu.js";
5
+ import { _ as _sfc_main$2 } from "./LpScrollArea-ZnycmmEI.js";
6
6
  const _hoisted_1 = {
7
7
  key: 0,
8
8
  class: "flex h-full w-full min-w-0 flex-col gap-1 overflow-hidden"
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, computed, ref, watch, nextTick, onMounted, onBeforeUnmount, openBlock, createElementBlock, createVNode, normalizeStyle, withCtx, createElementVNode, toDisplayString, createCommentVNode, Fragment, createBlock, resolveDynamicComponent, TransitionGroup, mergeProps, renderList, normalizeClass, createTextVNode, Transition } from "vue";
2
2
  import { _ as _sfc_main$3 } from "./LpContextMenu-D0mzXqA7.js";
3
3
  import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
4
- import { _ as _sfc_main$1 } from "./LpScrollArea-DQ0Yudfu.js";
4
+ import { _ as _sfc_main$1 } from "./LpScrollArea-ZnycmmEI.js";
5
5
  const _hoisted_1 = { class: "relative overflow-hidden rounded-card border border-line bg-surface font-mono text-xs leading-relaxed" };
6
6
  const _hoisted_2 = {
7
7
  key: 0,
@@ -353,7 +353,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
353
353
  createVNode(_sfc_main$1, {
354
354
  ref_key: "scrollRef",
355
355
  ref: scrollRef,
356
- fade: "",
357
356
  instant: "",
358
357
  "content-class": __props.wrap ? "" : "min-w-max",
359
358
  style: normalizeStyle({ height: __props.height }),
@@ -2,7 +2,7 @@ import { defineComponent, computed, useSlots, ref, watch, onBeforeUnmount, openB
2
2
  import { DialogRoot, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose } from "reka-ui";
3
3
  import { CLOSE_ICON } from "../components/dropdown.js";
4
4
  import { _ as _sfc_main$1 } from "./LpIcon-CCnX5_2j.js";
5
- import { _ as _sfc_main$2 } from "./LpScrollArea-DQ0Yudfu.js";
5
+ import { _ as _sfc_main$2 } from "./LpScrollArea-ZnycmmEI.js";
6
6
  const _hoisted_1 = { class: "fixed inset-0 z-(--z-modal) flex items-center justify-center pointer-events-none" };
7
7
  const _hoisted_2 = {
8
8
  key: 0,
@@ -5,7 +5,7 @@ import { _ as _sfc_main$4 } from "./LpContextMenu-D0mzXqA7.js";
5
5
  import { _ as _sfc_main$2 } from "./LpEmptyState-CrfyRJUG.js";
6
6
  import { _ as _sfc_main$5 } from "./LpIcon-CCnX5_2j.js";
7
7
  import { _ as _sfc_main$1 } from "./LpPopover-8268UmlC.js";
8
- import { _ as _sfc_main$3 } from "./LpScrollArea-DQ0Yudfu.js";
8
+ import { _ as _sfc_main$3 } from "./LpScrollArea-ZnycmmEI.js";
9
9
  const _hoisted_1 = { class: "flex items-center justify-between gap-2 px-3 py-2.5" };
10
10
  const _hoisted_2 = { class: "text-sm font-semibold" };
11
11
  const _hoisted_3 = {
@@ -0,0 +1,120 @@
1
+ import { defineComponent, ref, computed, watch, onBeforeUnmount, openBlock, createBlock, unref, normalizeClass, withCtx, createVNode, normalizeStyle, createElementVNode, renderSlot } from "vue";
2
+ import { ScrollAreaRoot, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport } from "reka-ui";
3
+ const barFade = "opacity-0 data-[state=visible]:animate-[fade-in_180ms_ease] data-[state=visible]:opacity-100 data-[state=hidden]:animate-[fade-out_240ms_ease]";
4
+ const FADE_PX = 14;
5
+ const _sfc_main = /* @__PURE__ */ defineComponent({
6
+ __name: "LpScrollArea",
7
+ props: {
8
+ fade: { type: Boolean, default: true },
9
+ instant: { type: Boolean, default: false },
10
+ contentClass: {},
11
+ barInsetTop: {}
12
+ },
13
+ emits: ["scroll"],
14
+ setup(__props, { expose: __expose, emit: __emit }) {
15
+ const props = __props;
16
+ const emit = __emit;
17
+ const viewportRef = ref(null);
18
+ const viewportEl = computed(
19
+ () => viewportRef.value?.viewportElement ?? null
20
+ );
21
+ __expose({ viewportEl });
22
+ const dragging = ref(false);
23
+ const atTop = ref(true);
24
+ const atBottom = ref(true);
25
+ const fadeMask = computed(() => {
26
+ const top = atTop.value ? "black 0" : `transparent 0, black ${FADE_PX}px`;
27
+ const bottom = atBottom.value ? "black 100%" : `black calc(100% - ${FADE_PX}px), transparent 100%`;
28
+ return `linear-gradient(to bottom, ${top}, ${bottom})`;
29
+ });
30
+ function measureEdges(el) {
31
+ atTop.value = el.scrollTop <= 1;
32
+ atBottom.value = el.scrollTop + el.clientHeight >= el.scrollHeight - 1;
33
+ }
34
+ function onViewportScroll(event) {
35
+ if (props.fade) measureEdges(event.target);
36
+ emit("scroll", event);
37
+ }
38
+ let edgeObserver;
39
+ watch(
40
+ [viewportEl, () => props.fade],
41
+ ([el, enabled]) => {
42
+ edgeObserver?.disconnect();
43
+ edgeObserver = void 0;
44
+ if (!el || !enabled || typeof ResizeObserver === "undefined") return;
45
+ measureEdges(el);
46
+ edgeObserver = new ResizeObserver(() => measureEdges(el));
47
+ edgeObserver.observe(el);
48
+ for (const child of Array.from(el.children)) edgeObserver.observe(child);
49
+ },
50
+ { immediate: true, flush: "post" }
51
+ );
52
+ onBeforeUnmount(() => edgeObserver?.disconnect());
53
+ function onThumbPointerDown() {
54
+ dragging.value = true;
55
+ const stop = () => {
56
+ dragging.value = false;
57
+ window.removeEventListener("pointerup", stop);
58
+ window.removeEventListener("pointercancel", stop);
59
+ };
60
+ window.addEventListener("pointerup", stop);
61
+ window.addEventListener("pointercancel", stop);
62
+ }
63
+ return (_ctx, _cache) => {
64
+ return openBlock(), createBlock(unref(ScrollAreaRoot), {
65
+ class: normalizeClass(["relative flex flex-col overflow-hidden", dragging.value ? "select-none" : void 0]),
66
+ type: "hover",
67
+ "scroll-hide-delay": 500
68
+ }, {
69
+ default: withCtx(() => [
70
+ createVNode(unref(ScrollAreaScrollbar), {
71
+ orientation: "vertical",
72
+ "force-mount": "",
73
+ class: normalizeClass(["group flex w-3.5 touch-none select-none justify-end py-px pl-2.5 pr-px", barFade]),
74
+ style: normalizeStyle(__props.barInsetTop ? { marginTop: __props.barInsetTop } : void 0)
75
+ }, {
76
+ default: withCtx(() => [
77
+ createVNode(unref(ScrollAreaThumb), {
78
+ class: "min-w-1 rounded-l-pill bg-brand/40 transition-[min-width,background-color] duration-[var(--duration-fast)] group-hover:min-w-1.5 group-hover:bg-brand",
79
+ onPointerdown: onThumbPointerDown
80
+ })
81
+ ]),
82
+ _: 1
83
+ }, 8, ["style"]),
84
+ createVNode(unref(ScrollAreaScrollbar), {
85
+ orientation: "horizontal",
86
+ class: normalizeClass(["group flex h-3.5 flex-col touch-none select-none justify-end px-px pb-px pt-2.5", barFade])
87
+ }, {
88
+ default: withCtx(() => [
89
+ createVNode(unref(ScrollAreaThumb), {
90
+ class: "min-h-1 rounded-t-pill bg-brand/40 transition-[min-height,background-color] duration-[var(--duration-fast)] group-hover:min-h-1.5 group-hover:bg-brand",
91
+ onPointerdown: onThumbPointerDown
92
+ })
93
+ ]),
94
+ _: 1
95
+ }),
96
+ createVNode(unref(ScrollAreaViewport), {
97
+ ref_key: "viewportRef",
98
+ ref: viewportRef,
99
+ class: normalizeClass(["w-full min-h-0 min-w-0 flex-1 [&>div]:!block [&>div]:!min-w-0", __props.instant ? "" : "scroll-smooth motion-reduce:scroll-auto"]),
100
+ style: normalizeStyle(__props.fade ? { maskImage: fadeMask.value, WebkitMaskImage: fadeMask.value } : void 0),
101
+ onScrollPassive: onViewportScroll
102
+ }, {
103
+ default: withCtx(() => [
104
+ createElementVNode("div", {
105
+ class: normalizeClass(__props.contentClass)
106
+ }, [
107
+ renderSlot(_ctx.$slots, "default")
108
+ ], 2)
109
+ ]),
110
+ _: 3
111
+ }, 8, ["class", "style"])
112
+ ]),
113
+ _: 3
114
+ }, 8, ["class"]);
115
+ };
116
+ }
117
+ });
118
+ export {
119
+ _sfc_main as _
120
+ };
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, computed, useId, openBlock, createElementBlock, Fragment, createElementVNode, mergeProps, normalizeClass, renderSlot, createCommentVNode, createVNode, createSlots, withCtx, normalizeProps, guardReactiveProps, createBlock } from "vue";
2
- import { _ as _sfc_main$2 } from "./LpDrawer-CYm-nUIZ.js";
3
- import { _ as _sfc_main$1 } from "./LpSidebarNav-DSDa5mAY.js";
2
+ import { _ as _sfc_main$2 } from "./LpDrawer-Dr1USsND.js";
3
+ import { _ as _sfc_main$1 } from "./LpSidebarNav-C0LjLp0O.js";
4
4
  const _hoisted_1 = {
5
5
  key: 1,
6
6
  class: "mt-2 flex shrink-0 flex-col gap-2"
@@ -4,7 +4,7 @@ import { usePillTransition } from "../composables/usePillTransition.js";
4
4
  import { _ as _sfc_main$4 } from "./LpBadge-CXzBPnwO.js";
5
5
  import { _ as _sfc_main$2 } from "./LpContextMenu-D0mzXqA7.js";
6
6
  import { _ as _sfc_main$3 } from "./LpIcon-CCnX5_2j.js";
7
- import { _ as _sfc_main$1 } from "./LpScrollArea-DQ0Yudfu.js";
7
+ import { _ as _sfc_main$1 } from "./LpScrollArea-ZnycmmEI.js";
8
8
  const _hoisted_1 = {
9
9
  key: 0,
10
10
  class: "flex min-h-0 flex-1 flex-col gap-4"
@@ -2,7 +2,7 @@ import { defineComponent, computed, ref, watch, onBeforeUnmount, openBlock, crea
2
2
  import { _ as _sfc_main$2 } from "./LpCheckbox-BO0zuuPh.js";
3
3
  import { _ as _sfc_main$4 } from "./LpContextMenu-D0mzXqA7.js";
4
4
  import { _ as _sfc_main$3 } from "./LpIcon-CCnX5_2j.js";
5
- import { _ as _sfc_main$1 } from "./LpScrollArea-DQ0Yudfu.js";
5
+ import { _ as _sfc_main$1 } from "./LpScrollArea-ZnycmmEI.js";
6
6
  const _hoisted_1 = { class: "w-full border-collapse text-sm" };
7
7
  const _hoisted_2 = { class: "border-b border-line bg-surface-soft" };
8
8
  const _hoisted_3 = {
@@ -116,6 +116,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
116
116
  );
117
117
  return (_ctx, _cache) => {
118
118
  return openBlock(), createBlock(_sfc_main$1, {
119
+ fade: false,
119
120
  class: "rounded-card border border-line",
120
121
  "bar-inset-top": barInsetTop.value
121
122
  }, {
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAddressInput-DZxdRaVk.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAddressInput-CK6y3xZm.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAppShell-D42la4ZD.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAppShell-JWrWjNdC.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, ref, computed, watch, nextTick, onMounted, onBeforeUnmount, openBlock, createBlock, unref, withCtx, createVNode, withModifiers, createTextVNode, createElementVNode, withDirectives, withKeys, vModelText, createElementBlock, toDisplayString, createCommentVNode, Fragment, renderList, normalizeClass } from "vue";
2
2
  import { DialogRoot, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription } from "reka-ui";
3
3
  import { _ as _sfc_main$1 } from "../chunks/LpIcon-CCnX5_2j.js";
4
- import { _ as _sfc_main$2 } from "../chunks/LpScrollArea-DQ0Yudfu.js";
4
+ import { _ as _sfc_main$2 } from "../chunks/LpScrollArea-ZnycmmEI.js";
5
5
  import '../assets/LpCommandPalette-Cp6Y-j7g.css';const _hoisted_1 = { class: "flex shrink-0 items-center gap-2.5 border-b border-line px-4" };
6
6
  const _hoisted_2 = ["placeholder", "onKeydown"];
7
7
  const _hoisted_3 = {
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpConfirmDialog-JEbhyY_y.js";
1
+ import { _ as _sfc_main } from "../chunks/LpConfirmDialog-ClefCHIT.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpDrawer-CYm-nUIZ.js";
1
+ import { _ as _sfc_main } from "../chunks/LpDrawer-Dr1USsND.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpFileTree-DXb3yKzH.js";
1
+ import { _ as _sfc_main } from "../chunks/LpFileTree-DcoePIZq.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpLogViewer-tmKPNTuU.js";
1
+ import { _ as _sfc_main } from "../chunks/LpLogViewer-BDPbnCOU.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpModal-DLgOAP4p.js";
1
+ import { _ as _sfc_main } from "../chunks/LpModal-BQvb6ekk.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpNotificationBell-DHze8wYN.js";
1
+ import { _ as _sfc_main } from "../chunks/LpNotificationBell-DDzQY0YA.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -4,9 +4,9 @@ type __VLS_Props = {
4
4
  contentClass?: string;
5
5
  barInsetTop?: string;
6
6
  };
7
- declare var __VLS_40: {};
7
+ declare var __VLS_44: {};
8
8
  type __VLS_Slots = {} & {
9
- default?: (props: typeof __VLS_40) => any;
9
+ default?: (props: typeof __VLS_44) => any;
10
10
  };
11
11
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
12
12
  viewportEl: import('vue').ComputedRef<HTMLElement | null>;
@@ -15,6 +15,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
15
15
  }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
16
16
  onScroll?: ((event: Event) => any) | undefined;
17
17
  }>, {
18
+ fade: boolean;
18
19
  instant: boolean;
19
20
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
20
21
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpScrollArea-DQ0Yudfu.js";
1
+ import { _ as _sfc_main } from "../chunks/LpScrollArea-ZnycmmEI.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpSidebar-DlLZJk1u.js";
1
+ import { _ as _sfc_main } from "../chunks/LpSidebar-CC5759Mh.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpSidebarNav-DSDa5mAY.js";
1
+ import { _ as _sfc_main } from "../chunks/LpSidebarNav-C0LjLp0O.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpTable-DqZ-L4Au.js";
1
+ import { _ as _sfc_main } from "../chunks/LpTable-CWS2V4JO.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { _ } from "./chunks/LayoutCanvas-Dd20boUG.js";
2
- import { _ as _2 } from "./chunks/LpAddressInput-DZxdRaVk.js";
2
+ import { _ as _2 } from "./chunks/LpAddressInput-CK6y3xZm.js";
3
3
  import { _ as _3 } from "./chunks/LpMapPicker-DFKrd1Ne.js";
4
4
  import { OSM_TILES, createNominatimProvider, emptyAddress, formatAddress, project, tileUrl, unproject } from "./components/address.js";
5
5
  import { _ as _4 } from "./chunks/LpAlert-BAYHDSS1.js";
6
- import { _ as _5 } from "./chunks/LpAppShell-D42la4ZD.js";
6
+ import { _ as _5 } from "./chunks/LpAppShell-JWrWjNdC.js";
7
7
  import { _ as _6 } from "./chunks/LpAutocomplete-DIgXmtCA.js";
8
8
  import { _ as _7 } from "./chunks/LpAvatar-B1Ez0ZAx.js";
9
9
  import { _ as _8 } from "./chunks/LpBadge-CXzBPnwO.js";
@@ -14,15 +14,15 @@ import { _ as _12 } from "./chunks/LpCard-BmrTvWOe.js";
14
14
  import { _ as _13 } from "./chunks/LpCheckbox-BO0zuuPh.js";
15
15
  import { _ as _14 } from "./chunks/LpCodeBlock-CSiOSPs8.js";
16
16
  import { default as default2 } from "./components/LpCommandPalette.vue.js";
17
- import { _ as _15 } from "./chunks/LpConfirmDialog-JEbhyY_y.js";
17
+ import { _ as _15 } from "./chunks/LpConfirmDialog-ClefCHIT.js";
18
18
  import { _ as _16 } from "./chunks/LpContextMenu-D0mzXqA7.js";
19
19
  import { _ as _17 } from "./chunks/LpDatePicker-dY2q4dr4.js";
20
20
  import { _ as _18 } from "./chunks/LpDisclosure-DP6yfgfM.js";
21
21
  import { _ as _19 } from "./chunks/LpDivider-CUX46KR0.js";
22
- import { _ as _20 } from "./chunks/LpDrawer-CYm-nUIZ.js";
22
+ import { _ as _20 } from "./chunks/LpDrawer-Dr1USsND.js";
23
23
  import { _ as _21 } from "./chunks/LpDropdownMenu-DJpoqRCb.js";
24
24
  import { _ as _22 } from "./chunks/LpEmptyState-CrfyRJUG.js";
25
- import { _ as _23 } from "./chunks/LpFileTree-DXb3yKzH.js";
25
+ import { _ as _23 } from "./chunks/LpFileTree-DcoePIZq.js";
26
26
  import { ancestorIds, checkStateOf, checkedCount, computeStats, fileIcon, formatModified, formatSize, sortNodes, subtreeIds, subtreeSize } from "./components/fileTree.js";
27
27
  import { _ as _24 } from "./chunks/LpFormField-Bn-ZwC6z.js";
28
28
  import { _ as _25 } from "./chunks/LpIcon-CCnX5_2j.js";
@@ -31,9 +31,9 @@ import { _ as _27 } from "./chunks/LpInput-BauZRyzm.js";
31
31
  import { _ as _28 } from "./chunks/LpLightbox-CzhFe9wZ.js";
32
32
  import { fileNameOf } from "./components/lightbox.js";
33
33
  import { _ as _29 } from "./chunks/LpLink-DHwOEp4e.js";
34
- import { _ as _30 } from "./chunks/LpLogViewer-tmKPNTuU.js";
35
- import { _ as _31 } from "./chunks/LpModal-DLgOAP4p.js";
36
- import { _ as _32 } from "./chunks/LpNotificationBell-DHze8wYN.js";
34
+ import { _ as _30 } from "./chunks/LpLogViewer-BDPbnCOU.js";
35
+ import { _ as _31 } from "./chunks/LpModal-BQvb6ekk.js";
36
+ import { _ as _32 } from "./chunks/LpNotificationBell-DDzQY0YA.js";
37
37
  import { _ as _33 } from "./chunks/LpNumberField-C5ar-OwE.js";
38
38
  import { _ as _34 } from "./chunks/LpOtpInput-DqaT0Z75.js";
39
39
  import { _ as _35 } from "./chunks/LpPagination-CeGuNe_q.js";
@@ -44,17 +44,17 @@ import { _ as _38 } from "./chunks/LpPopover-8268UmlC.js";
44
44
  import { _ as _39 } from "./chunks/LpProgress-BhI0IbjC.js";
45
45
  import { _ as _40 } from "./chunks/LpRadio-CL-pI0_O.js";
46
46
  import { _ as _41 } from "./chunks/LpRadioGroup-B4yDTmi6.js";
47
- import { _ as _42 } from "./chunks/LpScrollArea-DQ0Yudfu.js";
47
+ import { _ as _42 } from "./chunks/LpScrollArea-ZnycmmEI.js";
48
48
  import { _ as _43 } from "./chunks/LpSegmented-BmpanyAo.js";
49
49
  import { _ as _44 } from "./chunks/LpSelect-D5mU4cZO.js";
50
50
  import { _ as _45 } from "./chunks/LpServiceNode-Dc-Ut5RS.js";
51
- import { _ as _46 } from "./chunks/LpSidebar-DlLZJk1u.js";
51
+ import { _ as _46 } from "./chunks/LpSidebar-CC5759Mh.js";
52
52
  import { _ as _47 } from "./chunks/LpSkeleton-eSFIo4kD.js";
53
53
  import { _ as _48 } from "./chunks/LpSlider-B1SF3pRV.js";
54
54
  import { _ as _49 } from "./chunks/LpStat-CdbEFOvn.js";
55
55
  import { _ as _50 } from "./chunks/LpStepper-5dFTrW21.js";
56
56
  import { _ as _51 } from "./chunks/LpSwitch-v6fnccSM.js";
57
- import { _ as _52 } from "./chunks/LpTable-DqZ-L4Au.js";
57
+ import { _ as _52 } from "./chunks/LpTable-CWS2V4JO.js";
58
58
  import { _ as _53 } from "./chunks/LpTableOfContents-CjvxPMpU.js";
59
59
  import { _ as _54 } from "./chunks/LpTabs-D7aTVPOb.js";
60
60
  import { _ as _55 } from "./chunks/LpTextarea-CRAkhemZ.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leavepulse/ui",
3
- "version": "0.20.3",
3
+ "version": "0.20.5",
4
4
  "type": "module",
5
5
  "description": "LeavePulse token-driven Vue component kit.",
6
6
  "repository": {
@@ -556,7 +556,6 @@ const transitionProps = {
556
556
  lines. A CSS smooth scroll would override both. -->
557
557
  <LpScrollArea
558
558
  ref="scrollRef"
559
- fade
560
559
  instant
561
560
  :content-class="wrap ? '' : 'min-w-max'"
562
561
  :style="{ height }"
@@ -6,7 +6,7 @@
6
6
  * exit animation). Rounded only on the OUTER edge — the side flush to the wall
7
7
  * stays square. Themed via tokens; native scroll/keyboard/touch preserved.
8
8
  */
9
- import { computed, ref } from "vue"
9
+ import { computed, onBeforeUnmount, ref, watch } from "vue"
10
10
  import {
11
11
  ScrollAreaRoot,
12
12
  ScrollAreaScrollbar,
@@ -14,7 +14,11 @@ import {
14
14
  ScrollAreaViewport,
15
15
  } from "reka-ui"
16
16
 
17
- // `fade` softens the top/bottom edges to hint more content.
17
+ // `fade` softens whichever of the top/bottom edges currently has content beyond
18
+ // it, so a clipped list reads as continuing rather than as cut off. On by
19
+ // default: a hard crop through a row looks like damage wherever it happens, and
20
+ // every consumer wanted it. Pass `:fade="false"` where the edge must stay
21
+ // crisp — content that has to be read to its last pixel.
18
22
  // `contentClass` styles the scrollable CONTENT container (the viewport's inner
19
23
  // wrapper) — put list layout here (display:grid / gap / padding), not on the
20
24
  // component root, since items live inside reka's viewport.
@@ -33,14 +37,14 @@ const props = withDefaults(
33
37
  contentClass?: string
34
38
  barInsetTop?: string
35
39
  }>(),
36
- { instant: false },
40
+ { fade: true, instant: false },
37
41
  )
38
42
 
39
43
  // Re-emit the native scroll event of the underlying viewport so consumers that
40
44
  // drive scroll-following (e.g. log tails) can track position. The listener is
41
45
  // bound on ScrollAreaViewport, whose `$attrs` reka forwards onto the scrollable
42
46
  // element itself.
43
- defineEmits<{ scroll: [event: Event] }>()
47
+ const emit = defineEmits<{ scroll: [event: Event] }>()
44
48
 
45
49
  // Expose the scrollable viewport element so callers can read/write scrollTop
46
50
  // (auto-scroll to bottom, "is at bottom" checks). reka's ScrollAreaViewport
@@ -56,6 +60,78 @@ defineExpose({ viewportEl })
56
60
  // would snap back to visible once the animation finished.
57
61
  const barFade =
58
62
  "opacity-0 data-[state=visible]:animate-[fade-in_180ms_ease] data-[state=visible]:opacity-100 data-[state=hidden]:animate-[fade-out_240ms_ease]"
63
+
64
+ // Dragging the thumb pulls the pointer off the bar and across the content, and
65
+ // the browser reads that as a text selection — the rows highlight blue while
66
+ // the user is only trying to scroll. Suppressed for the duration of the drag
67
+ // rather than with a blanket `select-none`, which would cost the content its
68
+ // selectability for good.
69
+ const dragging = ref(false)
70
+
71
+ /** How far the fade reaches in from an edge that has content beyond it. */
72
+ const FADE_PX = 14
73
+
74
+ const atTop = ref(true)
75
+ const atBottom = ref(true)
76
+
77
+ /// Only the edges that actually hide something are softened. A fixed mask dims
78
+ /// the last line of a list that has already been scrolled to the end, which
79
+ /// reads as content missing rather than as content continuing.
80
+ const fadeMask = computed(() => {
81
+ const top = atTop.value ? "black 0" : `transparent 0, black ${FADE_PX}px`
82
+ const bottom = atBottom.value
83
+ ? "black 100%"
84
+ : `black calc(100% - ${FADE_PX}px), transparent 100%`
85
+ return `linear-gradient(to bottom, ${top}, ${bottom})`
86
+ })
87
+
88
+ function measureEdges(el: HTMLElement) {
89
+ atTop.value = el.scrollTop <= 1
90
+ // A rounded-up scrollHeight can sit a pixel above the sum, so the comparison
91
+ // is given the same slack as the top rather than demanding an exact landing.
92
+ atBottom.value = el.scrollTop + el.clientHeight >= el.scrollHeight - 1
93
+ }
94
+
95
+ function onViewportScroll(event: Event) {
96
+ if (props.fade) measureEdges(event.target as HTMLElement)
97
+ emit("scroll", event)
98
+ }
99
+
100
+ // Scrolling is not the only thing that changes which edges hide content: a list
101
+ // that fills in, a panel that resizes, or content short enough to need no fade
102
+ // at all never fire a scroll event. Watched only when `fade` is on, since
103
+ // nothing else here depends on the measurements.
104
+ let edgeObserver: ResizeObserver | undefined
105
+
106
+ watch(
107
+ [viewportEl, () => props.fade],
108
+ ([el, enabled]) => {
109
+ edgeObserver?.disconnect()
110
+ edgeObserver = undefined
111
+ if (!el || !enabled || typeof ResizeObserver === "undefined") return
112
+ measureEdges(el)
113
+ edgeObserver = new ResizeObserver(() => measureEdges(el))
114
+ edgeObserver.observe(el)
115
+ // The content box grows independently of the viewport's own size.
116
+ for (const child of Array.from(el.children)) edgeObserver.observe(child)
117
+ },
118
+ { immediate: true, flush: "post" },
119
+ )
120
+
121
+ onBeforeUnmount(() => edgeObserver?.disconnect())
122
+
123
+ function onThumbPointerDown() {
124
+ dragging.value = true
125
+ const stop = () => {
126
+ dragging.value = false
127
+ window.removeEventListener("pointerup", stop)
128
+ window.removeEventListener("pointercancel", stop)
129
+ }
130
+ // Bound on the window: the pointer is captured by the thumb, and the release
131
+ // routinely happens far outside the scroll area.
132
+ window.addEventListener("pointerup", stop)
133
+ window.addEventListener("pointercancel", stop)
134
+ }
59
135
  </script>
60
136
 
61
137
  <template>
@@ -65,7 +141,12 @@ const barFade =
65
141
  by `flex-1` inside a capped panel — is itself content-derived, so the
66
142
  viewport grew to the full content height and scrolled nothing while the
67
143
  root clipped the overflow. -->
68
- <ScrollAreaRoot class="relative flex flex-col overflow-hidden" type="hover" :scroll-hide-delay="500">
144
+ <ScrollAreaRoot
145
+ class="relative flex flex-col overflow-hidden"
146
+ :class="dragging ? 'select-none' : undefined"
147
+ type="hover"
148
+ :scroll-hide-delay="500"
149
+ >
69
150
  <!-- The bar itself is a pointer target far wider than it looks: the visible
70
151
  rail is the thumb, sized below, while the track pads it out to a
71
152
  grabbable strip. A 4px-wide hit area is near-impossible to catch with a
@@ -91,6 +172,7 @@ const barFade =
91
172
  the positioning reka owns. -->
92
173
  <ScrollAreaThumb
93
174
  class="min-w-1 rounded-l-pill bg-brand/40 transition-[min-width,background-color] duration-[var(--duration-fast)] group-hover:min-w-1.5 group-hover:bg-brand"
175
+ @pointerdown="onThumbPointerDown"
94
176
  />
95
177
  </ScrollAreaScrollbar>
96
178
 
@@ -101,17 +183,16 @@ const barFade =
101
183
  >
102
184
  <ScrollAreaThumb
103
185
  class="min-h-1 rounded-t-pill bg-brand/40 transition-[min-height,background-color] duration-[var(--duration-fast)] group-hover:min-h-1.5 group-hover:bg-brand"
186
+ @pointerdown="onThumbPointerDown"
104
187
  />
105
188
  </ScrollAreaScrollbar>
106
189
 
107
190
  <ScrollAreaViewport
108
191
  ref="viewportRef"
109
192
  class="w-full min-h-0 min-w-0 flex-1 [&>div]:!block [&>div]:!min-w-0"
110
- :class="[
111
- instant ? '' : 'scroll-smooth motion-reduce:scroll-auto',
112
- fade ? '[mask-image:linear-gradient(to_bottom,transparent_0,black_14px,black_calc(100%-14px),transparent_100%)]' : '',
113
- ]"
114
- @scroll.passive="$emit('scroll', $event)"
193
+ :class="instant ? '' : 'scroll-smooth motion-reduce:scroll-auto'"
194
+ :style="fade ? { maskImage: fadeMask, WebkitMaskImage: fadeMask } : undefined"
195
+ @scroll.passive="onViewportScroll"
115
196
  >
116
197
  <div :class="contentClass">
117
198
  <slot />
@@ -164,7 +164,13 @@ const barInsetTop = computed(() =>
164
164
  </script>
165
165
 
166
166
  <template>
167
- <LpScrollArea class="rounded-card border border-line" :bar-inset-top="barInsetTop">
167
+ <!-- No top fade: a sticky header sits in the masked band and would be dimmed
168
+ by it. The bottom edge is left crisp with it for symmetry. -->
169
+ <LpScrollArea
170
+ :fade="false"
171
+ class="rounded-card border border-line"
172
+ :bar-inset-top="barInsetTop"
173
+ >
168
174
  <table class="w-full border-collapse text-sm">
169
175
  <thead ref="headEl" :class="stickyHeader ? 'sticky top-0 z-10' : ''">
170
176
  <tr class="border-b border-line bg-surface-soft">
@@ -1,72 +0,0 @@
1
- import { defineComponent, ref, computed, openBlock, createBlock, unref, withCtx, createVNode, normalizeStyle, normalizeClass, createElementVNode, renderSlot } from "vue";
2
- import { ScrollAreaRoot, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport } from "reka-ui";
3
- const barFade = "opacity-0 data-[state=visible]:animate-[fade-in_180ms_ease] data-[state=visible]:opacity-100 data-[state=hidden]:animate-[fade-out_240ms_ease]";
4
- const _sfc_main = /* @__PURE__ */ defineComponent({
5
- __name: "LpScrollArea",
6
- props: {
7
- fade: { type: Boolean },
8
- instant: { type: Boolean, default: false },
9
- contentClass: {},
10
- barInsetTop: {}
11
- },
12
- emits: ["scroll"],
13
- setup(__props, { expose: __expose }) {
14
- const viewportRef = ref(null);
15
- const viewportEl = computed(
16
- () => viewportRef.value?.viewportElement ?? null
17
- );
18
- __expose({ viewportEl });
19
- return (_ctx, _cache) => {
20
- return openBlock(), createBlock(unref(ScrollAreaRoot), {
21
- class: "relative flex flex-col overflow-hidden",
22
- type: "hover",
23
- "scroll-hide-delay": 500
24
- }, {
25
- default: withCtx(() => [
26
- createVNode(unref(ScrollAreaScrollbar), {
27
- orientation: "vertical",
28
- "force-mount": "",
29
- class: normalizeClass(["group flex w-3.5 touch-none select-none justify-end py-px pl-2.5 pr-px", barFade]),
30
- style: normalizeStyle(__props.barInsetTop ? { marginTop: __props.barInsetTop } : void 0)
31
- }, {
32
- default: withCtx(() => [
33
- createVNode(unref(ScrollAreaThumb), { class: "min-w-1 rounded-l-pill bg-brand/40 transition-[min-width,background-color] duration-[var(--duration-fast)] group-hover:min-w-1.5 group-hover:bg-brand" })
34
- ]),
35
- _: 1
36
- }, 8, ["style"]),
37
- createVNode(unref(ScrollAreaScrollbar), {
38
- orientation: "horizontal",
39
- class: normalizeClass(["group flex h-3.5 flex-col touch-none select-none justify-end px-px pb-px pt-2.5", barFade])
40
- }, {
41
- default: withCtx(() => [
42
- createVNode(unref(ScrollAreaThumb), { class: "min-h-1 rounded-t-pill bg-brand/40 transition-[min-height,background-color] duration-[var(--duration-fast)] group-hover:min-h-1.5 group-hover:bg-brand" })
43
- ]),
44
- _: 1
45
- }),
46
- createVNode(unref(ScrollAreaViewport), {
47
- ref_key: "viewportRef",
48
- ref: viewportRef,
49
- class: normalizeClass(["w-full min-h-0 min-w-0 flex-1 [&>div]:!block [&>div]:!min-w-0", [
50
- __props.instant ? "" : "scroll-smooth motion-reduce:scroll-auto",
51
- __props.fade ? "[mask-image:linear-gradient(to_bottom,transparent_0,black_14px,black_calc(100%-14px),transparent_100%)]" : ""
52
- ]]),
53
- onScrollPassive: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("scroll", $event))
54
- }, {
55
- default: withCtx(() => [
56
- createElementVNode("div", {
57
- class: normalizeClass(__props.contentClass)
58
- }, [
59
- renderSlot(_ctx.$slots, "default")
60
- ], 2)
61
- ]),
62
- _: 3
63
- }, 8, ["class"])
64
- ]),
65
- _: 3
66
- });
67
- };
68
- }
69
- });
70
- export {
71
- _sfc_main as _
72
- };