@leavepulse/ui 0.93.3 → 0.94.1

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 (79) hide show
  1. package/README.md +53 -3
  2. package/dist/assets/LpTabs-7yQjX2ih.css +18 -0
  3. package/dist/assets/LpVideoTrim-D8JDg9Qn.css +8 -0
  4. package/dist/chunks/AppShellContextNav-BoH4ffnC.js +54 -0
  5. package/dist/chunks/{LpAppShell-BWaVRsDB.js → LpAppShell-DlpQierx.js} +12 -5
  6. package/dist/chunks/{LpDateRangePicker-CAn2yGbn.js → LpDateRangePicker-DRBB8z6t.js} +1 -1
  7. package/dist/chunks/{LpDrawer-iRHwJOGn.js → LpDrawer-BkWjFdV0.js} +81 -42
  8. package/dist/chunks/{LpLightbox-a24V_0Wk.js → LpLightbox-DPgz7IsT.js} +62 -49
  9. package/dist/chunks/{LpMapPicker-DVfiy3rR.js → LpMapPicker-V0Lybi10.js} +19 -52
  10. package/dist/chunks/{LpMediaGallery-CtWA5Uab.js → LpMediaGallery-CTejKF2-.js} +1 -1
  11. package/dist/chunks/{LpModalNav-DivqT1NV.js → LpModalNav-BFjiHWbr.js} +1 -1
  12. package/dist/chunks/{LpRangeCalendar-C9gkNMYw.js → LpRangeCalendar-9BvaLZji.js} +3 -4
  13. package/dist/chunks/LpScrollStrip-D4tsOfAQ.js +78 -0
  14. package/dist/chunks/{LpSidebar-DQtCYlT4.js → LpSidebar-BKhVDsMt.js} +3 -3
  15. package/dist/chunks/{LpSidebarNav-CFcI7--7.js → LpSidebarNav-DbCap8z1.js} +33 -19
  16. package/dist/component-names.d.ts +1 -1
  17. package/dist/components/AppShellContextNav.vue.js +1 -1
  18. package/dist/components/LpAppShell.vue.js +1 -1
  19. package/dist/components/LpChart.vue.js +3 -3
  20. package/dist/components/LpDateRangePicker.vue.js +1 -1
  21. package/dist/components/LpDrawer.vue.d.ts +10 -2
  22. package/dist/components/LpDrawer.vue.js +1 -1
  23. package/dist/components/LpDropzone.vue.d.ts +1 -1
  24. package/dist/components/LpLightbox.vue.js +1 -1
  25. package/dist/components/LpMapPicker.vue.js +1 -1
  26. package/dist/components/LpMediaGallery.vue.js +1 -1
  27. package/dist/components/LpModalNav.vue.js +1 -1
  28. package/dist/components/LpRangeCalendar.vue.js +1 -1
  29. package/dist/components/LpRevealOnScroll.vue.d.ts +1 -1
  30. package/dist/components/LpScrollStrip.vue.d.ts +48 -0
  31. package/dist/components/LpScrollStrip.vue.js +4 -0
  32. package/dist/components/LpSidebar.vue.js +1 -1
  33. package/dist/components/LpSidebarNav.vue.js +1 -1
  34. package/dist/components/LpTabs.vue.d.ts +4 -4
  35. package/dist/components/LpTabs.vue.js +111 -92
  36. package/dist/components/LpVideoTrim.vue.js +41 -54
  37. package/dist/composables/gesture.d.ts +141 -0
  38. package/dist/composables/gesture.js +176 -0
  39. package/dist/composables/scroll.d.ts +5 -1
  40. package/dist/composables/scroll.js +16 -9
  41. package/dist/composables/useAppUpdate.d.ts +26 -0
  42. package/dist/composables/useAppUpdate.js +91 -0
  43. package/dist/composables/useGesture.d.ts +107 -0
  44. package/dist/composables/useGesture.js +281 -0
  45. package/dist/composables/usePaintSelect.js +3 -4
  46. package/dist/composables/useScrollStrip.d.ts +27 -0
  47. package/dist/composables/useScrollStrip.js +194 -0
  48. package/dist/composables/useTouchHold.d.ts +3 -1
  49. package/dist/composables/useTouchHold.js +9 -51
  50. package/dist/composables/useZoomPan.js +4 -6
  51. package/dist/index.d.ts +9 -0
  52. package/dist/index.js +180 -152
  53. package/package.json +1 -1
  54. package/src/component-names.ts +1 -0
  55. package/src/components/AppShellContextNav.vue +3 -2
  56. package/src/components/LpAppShell.vue +10 -1
  57. package/src/components/LpChart.vue +2 -2
  58. package/src/components/LpDrawer.vue +121 -54
  59. package/src/components/LpLightbox.vue +33 -20
  60. package/src/components/LpMapPicker.vue +22 -64
  61. package/src/components/LpRangeCalendar.vue +4 -5
  62. package/src/components/LpScrollStrip.vue +96 -0
  63. package/src/components/LpSidebar.vue +3 -3
  64. package/src/components/LpSidebarNav.vue +18 -8
  65. package/src/components/LpTabs.vue +47 -19
  66. package/src/components/LpVideoTrim.vue +35 -46
  67. package/src/composables/gesture.ts +314 -0
  68. package/src/composables/scroll.ts +20 -9
  69. package/src/composables/useAppUpdate.ts +156 -0
  70. package/src/composables/useGesture.ts +451 -0
  71. package/src/composables/usePaintSelect.ts +4 -5
  72. package/src/composables/useScrollStrip.ts +249 -0
  73. package/src/composables/useTouchHold.ts +15 -73
  74. package/src/composables/useZoomPan.ts +6 -9
  75. package/src/index.ts +27 -0
  76. package/src/tokens/effects.css +40 -0
  77. package/dist/assets/LpTabs-Bh7a-Bdl.css +0 -18
  78. package/dist/assets/LpVideoTrim-CMoUw3dJ.css +0 -8
  79. package/dist/chunks/AppShellContextNav-C6Ho2mof.js +0 -49
@@ -6,6 +6,7 @@ import { useLabels } from "../composables/useLpConfig.js";
6
6
  import { easeTravel } from "../composables/easing.js";
7
7
  import { usePrefersReducedMotion } from "../composables/useReducedMotion.js";
8
8
  import { startPointerDrag } from "../composables/pointerDrag.js";
9
+ import { MOUSE_SLOP } from "../composables/gesture.js";
9
10
  import { nodeWindow } from "../composables/realm.js";
10
11
  import { usePillTransition } from "../composables/usePillTransition.js";
11
12
  import { useReveal } from "../composables/useReveal.js";
@@ -605,7 +606,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
605
606
  });
606
607
  const crosshair = computed(() => active.value >= 0 ? active.value : peerSlot.value);
607
608
  watch(active, (slot) => publish(slot >= 0 ? labels.value[slot] ?? null : null));
608
- const SELECT_SLOP = 4;
609
609
  let swallowClick = false;
610
610
  const selection = ref(null);
611
611
  const onPointerDown = (e) => {
@@ -616,7 +616,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
616
616
  startPointerDrag(e, {
617
617
  move(ev) {
618
618
  const x = offset(ev);
619
- if (Math.abs(x - pressedAt) > SELECT_SLOP) selection.value = { from: pressedAt, to: x };
619
+ if (Math.abs(x - pressedAt) > MOUSE_SLOP) selection.value = { from: pressedAt, to: x };
620
620
  },
621
621
  end(completed) {
622
622
  const picked = selection.value;
@@ -1457,7 +1457,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1457
1457
  };
1458
1458
  }
1459
1459
  });
1460
- const LpChart = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-39ed90d7"]]);
1460
+ const LpChart = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-946a5b6d"]]);
1461
1461
  export {
1462
1462
  LpChart as default
1463
1463
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpDateRangePicker-CAn2yGbn.js";
1
+ import { _ as _sfc_main } from "../chunks/LpDateRangePicker-DRBB8z6t.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -55,7 +55,11 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
55
55
  * does), so a wide touch screen with the rail visible doesn't pull it too.
56
56
  */
57
57
  edgeBreakpoint?: "sm" | "md" | "lg" | "xl";
58
- /** Distance (px) from the edge within which a touch can start a pull. */
58
+ /**
59
+ * Distance (px) from the edge within which a touch can start a pull. Wide
60
+ * enough to start a thumb's width in, clear of the system's back gesture
61
+ * along the very edge.
62
+ */
59
63
  edgeSize?: number;
60
64
  /** Fraction (0–1) of the panel width the pull must reach to open on release. */
61
65
  edgeOpenThreshold?: number;
@@ -152,7 +156,11 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
152
156
  * does), so a wide touch screen with the rail visible doesn't pull it too.
153
157
  */
154
158
  edgeBreakpoint?: "sm" | "md" | "lg" | "xl";
155
- /** Distance (px) from the edge within which a touch can start a pull. */
159
+ /**
160
+ * Distance (px) from the edge within which a touch can start a pull. Wide
161
+ * enough to start a thumb's width in, clear of the system's back gesture
162
+ * along the very edge.
163
+ */
156
164
  edgeSize?: number;
157
165
  /** Fraction (0–1) of the panel width the pull must reach to open on release. */
158
166
  edgeOpenThreshold?: number;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpDrawer-iRHwJOGn.js";
1
+ import { _ as _sfc_main } from "../chunks/LpDrawer-BkWjFdV0.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -109,11 +109,11 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
109
109
  }> & Readonly<{
110
110
  onLink?: ((url: string) => any) | undefined;
111
111
  onFiles?: ((files: File[]) => any) | undefined;
112
- "onUpdate:linking"?: ((value: boolean) => any) | undefined;
113
112
  onRejected?: ((reason: {
114
113
  file: File;
115
114
  cause: "type" | "size";
116
115
  }[]) => any) | undefined;
116
+ "onUpdate:linking"?: ((value: boolean) => any) | undefined;
117
117
  }>, {
118
118
  title: string;
119
119
  animate: boolean;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpLightbox-a24V_0Wk.js";
1
+ import { _ as _sfc_main } from "../chunks/LpLightbox-DPgz7IsT.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpMapPicker-DVfiy3rR.js";
1
+ import { _ as _sfc_main } from "../chunks/LpMapPicker-V0Lybi10.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpMediaGallery-CtWA5Uab.js";
1
+ import { _ as _sfc_main } from "../chunks/LpMediaGallery-CTejKF2-.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpModalNav-DivqT1NV.js";
1
+ import { _ as _sfc_main } from "../chunks/LpModalNav-BFjiHWbr.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpRangeCalendar-C9gkNMYw.js";
1
+ import { _ as _sfc_main } from "../chunks/LpRangeCalendar-9BvaLZji.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -53,10 +53,10 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
53
53
  direction: RevealDirection;
54
54
  delay: number;
55
55
  immediate: boolean;
56
+ distance: number;
56
57
  threshold: number;
57
58
  preset: RevealPreset;
58
59
  stagger: number;
59
- distance: number;
60
60
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
61
61
  default?: (props: {}) => any;
62
62
  }>;
@@ -0,0 +1,48 @@
1
+ type __VLS_Props = {
2
+ /** Classes for the scrolling row (layout, gap, padding, snap). */
3
+ contentClass?: unknown;
4
+ /** Fade the edges that have items beyond them. */
5
+ fade?: boolean;
6
+ /** Previous/next buttons: `auto` shows them on hover where the pointer is fine (a mouse), true on any device, false never. */
7
+ buttons?: boolean | "auto";
8
+ /** Map a vertical wheel to sideways scrolling while the row can move. */
9
+ wheel?: boolean;
10
+ /** Drag to scroll with a mouse or pen. */
11
+ drag?: boolean;
12
+ /** The row element's tag. */
13
+ as?: string;
14
+ /** Size to the content up to the parent's width (inline-flex), rather than fill the line. */
15
+ inline?: boolean;
16
+ };
17
+ declare var __VLS_9: {};
18
+ type __VLS_Slots = {} & {
19
+ default?: (props: typeof __VLS_9) => any;
20
+ };
21
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
22
+ scroller: import("vue").Ref<HTMLElement | null, HTMLElement | null>;
23
+ page: (direction: -1 | 1) => void;
24
+ scrollBy: (px: number) => void;
25
+ reveal: (el: Element | null | undefined, options?: {
26
+ smooth?: boolean;
27
+ block?: "nearest" | "center";
28
+ }) => void;
29
+ measure: () => void;
30
+ overflowing: import("vue").Ref<boolean, boolean>;
31
+ atStart: import("vue").Ref<boolean, boolean>;
32
+ atEnd: import("vue").Ref<boolean, boolean>;
33
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
34
+ drag: boolean;
35
+ wheel: boolean;
36
+ inline: boolean;
37
+ as: string;
38
+ fade: boolean;
39
+ buttons: boolean | "auto";
40
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
42
+ declare const _default: typeof __VLS_export;
43
+ export default _default;
44
+ type __VLS_WithSlots<T, S> = T & {
45
+ new (): {
46
+ $slots: S;
47
+ };
48
+ };
@@ -0,0 +1,4 @@
1
+ import { _ as _sfc_main } from "../chunks/LpScrollStrip-D4tsOfAQ.js";
2
+ export {
3
+ _sfc_main as default
4
+ };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpSidebar-DQtCYlT4.js";
1
+ import { _ as _sfc_main } from "../chunks/LpSidebar-BKhVDsMt.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpSidebarNav-CFcI7--7.js";
1
+ import { _ as _sfc_main } from "../chunks/LpSidebarNav-DbCap8z1.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -61,13 +61,13 @@ type __VLS_Props = {
61
61
  */
62
62
  history?: boolean;
63
63
  };
64
- declare var __VLS_67: {
64
+ declare var __VLS_77: {
65
65
  value: string;
66
- }, __VLS_69: {};
66
+ }, __VLS_79: {};
67
67
  type __VLS_Slots = {} & {
68
- panel?: (props: typeof __VLS_67) => any;
68
+ panel?: (props: typeof __VLS_77) => any;
69
69
  } & {
70
- default?: (props: typeof __VLS_69) => any;
70
+ default?: (props: typeof __VLS_79) => any;
71
71
  };
72
72
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
73
73
  "update:modelValue": (value: string) => any;
@@ -1,17 +1,18 @@
1
- import { defineComponent, computed, ref, watch, nextTick, useId, openBlock, createBlock, unref, withCtx, createVNode, normalizeClass, createElementBlock, Fragment, renderList, createCommentVNode, renderSlot } from "vue";
1
+ import { defineComponent, computed, ref, watch, nextTick, onMounted, useId, openBlock, createBlock, unref, withCtx, resolveDynamicComponent, mergeProps, createVNode, normalizeClass, createElementBlock, Fragment, renderList, createCommentVNode, renderSlot } from "vue";
2
2
  import { isHTMLElement } from "../composables/realm.js";
3
3
  import { usePaletteScope, usePaletteCommands } from "../composables/usePaletteCommands.js";
4
4
  import { Motion } from "motion-v";
5
5
  import { TabsRoot, TabsList, TabsTrigger, TabsContent } from "reka-ui";
6
+ import { useResizeObserver } from "../composables/useResizeObserver.js";
6
7
  import { usePillTransition } from "../composables/usePillTransition.js";
7
8
  import { useStepHistory } from "../composables/useOverlayHistory.js";
8
- import { prefersReducedMotion } from "../composables/easing.js";
9
- import { _ as _sfc_main$1 } from "../chunks/LpContextMenu-DEFirphS.js";
10
- import { _ as _sfc_main$3 } from "../chunks/LpSkeleton-leTl53V9.js";
11
- import { _ as _sfc_main$2 } from "../chunks/LpTabFace-uoZgD_SN.js";
9
+ import { _ as _sfc_main$2 } from "../chunks/LpContextMenu-DEFirphS.js";
10
+ import { _ as _sfc_main$4 } from "../chunks/LpSkeleton-leTl53V9.js";
11
+ import { _ as _sfc_main$3 } from "../chunks/LpTabFace-uoZgD_SN.js";
12
+ import { _ as _sfc_main$1 } from "../chunks/LpScrollStrip-D4tsOfAQ.js";
12
13
  import { pickTab, BOTTOM_BAR, BOTTOM_ITEM, BOTTOM_MARKER } from "./tabs.js";
13
14
  import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper-1tPrXgE0.js";
14
- import '../assets/LpTabs-Bh7a-Bdl.css';const _sfc_main = /* @__PURE__ */ defineComponent({
15
+ import '../assets/LpTabs-7yQjX2ih.css';const _sfc_main = /* @__PURE__ */ defineComponent({
15
16
  __name: "LpTabs",
16
17
  props: {
17
18
  modelValue: {},
@@ -44,19 +45,25 @@ import '../assets/LpTabs-Bh7a-Bdl.css';const _sfc_main = /* @__PURE__ */ defineC
44
45
  },
45
46
  { deep: true }
46
47
  );
48
+ const strip = ref(null);
49
+ const Passthrough = (_, { slots }) => slots.default?.();
47
50
  const list = ref(null);
48
- watch(current, () => {
49
- void nextTick(() => {
50
- const row = list.value?.$el;
51
- const active = row?.querySelector('[data-state="active"]');
52
- if (!row || !active || row.scrollWidth <= row.clientWidth) return;
53
- const start = active.offsetLeft - row.offsetLeft;
54
- const end = start + active.offsetWidth;
55
- if (start >= row.scrollLeft && end <= row.scrollLeft + row.clientWidth) return;
56
- const left = start < row.scrollLeft ? start : end - row.clientWidth;
57
- row.scrollTo({ left, behavior: prefersReducedMotion() ? "auto" : "smooth" });
58
- });
59
- });
51
+ function revealActive(smooth) {
52
+ if (bottom.value) return;
53
+ strip.value?.reveal(list.value?.$el?.querySelector('[data-state="active"]'), { smooth });
54
+ }
55
+ watch(current, () => void nextTick(() => revealActive(true)));
56
+ onMounted(() => requestAnimationFrame(() => revealActive(false)));
57
+ useResizeObserver(() => strip.value?.scroller, () => revealActive(false));
58
+ function holdMousePick(event) {
59
+ if (event.button !== 0 || event.ctrlKey || bottom.value) return;
60
+ if (!isHTMLElement(event.target) || !event.target.closest('[role="tab"]')) return;
61
+ event.stopPropagation();
62
+ event.preventDefault();
63
+ }
64
+ function clickPick(item) {
65
+ if (!item.disabled && !bottom.value) select(item.value);
66
+ }
60
67
  function show(value) {
61
68
  if (props.modelValue === void 0) current.value = value;
62
69
  emit("update:modelValue", value);
@@ -99,86 +106,98 @@ import '../assets/LpTabs-Bh7a-Bdl.css';const _sfc_main = /* @__PURE__ */ defineC
99
106
  "onUpdate:modelValue": _cache[1] || (_cache[1] = (v) => select(v))
100
107
  }, {
101
108
  default: withCtx(() => [
102
- createVNode(unref(TabsList), {
103
- ref_key: "list",
104
- ref: list,
105
- "aria-label": __props.label,
106
- class: normalizeClass(bottom.value ? unref(BOTTOM_BAR) : [
107
- "max-w-full gap-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
108
- __props.block ? "flex w-full" : "inline-flex",
109
- __props.variant === "contained" ? "rounded-control border border-line bg-surface-soft p-1" : "",
110
- __props.variant === "underline" ? "border-b border-line" : ""
111
- ]),
112
- onPointerleave: _cache[0] || (_cache[0] = ($event) => hovered.value = null)
113
- }, {
109
+ (openBlock(), createBlock(resolveDynamicComponent(bottom.value ? Passthrough : _sfc_main$1), mergeProps({
110
+ ref_key: "strip",
111
+ ref: strip
112
+ }, bottom.value ? {} : {
113
+ inline: !__props.block,
114
+ class: __props.variant === "contained" ? "rounded-control border border-line bg-surface-soft" : void 0,
115
+ contentClass: __props.variant === "contained" ? "p-1" : void 0
116
+ }), {
114
117
  default: withCtx(() => [
115
- (openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item) => {
116
- return openBlock(), createBlock(_sfc_main$1, {
117
- key: item.value,
118
- items: item.menu ?? [],
119
- title: item.label,
120
- "title-icon": item.icon
121
- }, {
122
- default: withCtx(() => [
123
- createVNode(unref(TabsTrigger), {
124
- value: item.value,
125
- disabled: item.disabled,
126
- title: __props.compact && item.icon && !bottom.value ? item.label : void 0,
127
- class: normalizeClass(["relative inline-flex items-center justify-center outline-none transition-[color,opacity] duration-[var(--duration-fast)] focus-visible:ring-2 focus-visible:ring-ring data-[disabled]:cursor-not-allowed data-[disabled]:opacity-45", [
128
- bottom.value ? unref(BOTTOM_ITEM) : "shrink-0 gap-1.5 whitespace-nowrap text-sm",
129
- __props.block && !bottom.value ? "flex-1" : "",
130
- __props.variant === "underline" ? "rounded-t-inner px-3 pt-1.5 pb-2" : "",
131
- __props.variant === "contained" || __props.variant === "plain" ? "rounded-inner px-3 py-1.5" : "",
132
- __props.accent ? "data-[state=active]:text-brand" : "data-[state=active]:text-ink",
133
- hovered.value === item.value && !bottom.value ? "text-ink" : !__props.hoverFollow && !bottom.value ? "text-muted hover:text-ink" : "text-muted"
134
- ]]),
135
- onPointerenter: ($event) => __props.hoverFollow && !item.disabled && (hovered.value = item.value),
136
- onPointerup: releaseFocusAfterPointer
118
+ createVNode(unref(TabsList), {
119
+ ref_key: "list",
120
+ ref: list,
121
+ "aria-label": __props.label,
122
+ class: normalizeClass(bottom.value ? unref(BOTTOM_BAR) : [
123
+ "flex w-max min-w-full gap-1",
124
+ __props.variant === "underline" ? "border-b border-line" : ""
125
+ ]),
126
+ onPointerleave: _cache[0] || (_cache[0] = ($event) => hovered.value = null),
127
+ onMousedownCapture: holdMousePick
128
+ }, {
129
+ default: withCtx(() => [
130
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item) => {
131
+ return openBlock(), createBlock(_sfc_main$2, {
132
+ key: item.value,
133
+ items: item.menu ?? [],
134
+ title: item.label,
135
+ "title-icon": item.icon
137
136
  }, {
138
137
  default: withCtx(() => [
139
- pillUnder(item.value, current.value) ? (openBlock(), createBlock(unref(Motion), {
140
- key: 0,
141
- "layout-id": pillId,
142
- transition: unref(pillTransition),
143
- class: normalizeClass(__props.variant === "underline" ? [
144
- "absolute inset-x-0 -bottom-px z-0 h-0.5 rounded-full",
145
- __props.accent ? "bg-brand" : "bg-ink"
146
- ] : bottom.value ? [unref(BOTTOM_MARKER), __props.accent ? "bg-brand" : "bg-ink"] : [
147
- "absolute inset-0 z-0 rounded-inner shadow-sm",
148
- __props.accent ? "border border-brand/35 bg-brand/12" : "border border-line bg-surface-raised"
149
- ])
150
- }, null, 8, ["transition", "class"])) : createCommentVNode("", true),
151
- createVNode(_sfc_main$2, {
152
- item,
153
- bottom: bottom.value,
154
- compact: __props.compact,
155
- active: current.value === item.value
156
- }, null, 8, ["item", "bottom", "compact", "active"])
138
+ createVNode(unref(TabsTrigger), {
139
+ value: item.value,
140
+ disabled: item.disabled,
141
+ title: __props.compact && item.icon && !bottom.value ? item.label : void 0,
142
+ class: normalizeClass(["relative inline-flex items-center justify-center outline-none transition-[color,opacity] duration-[var(--duration-fast)] focus-visible:ring-2 focus-visible:ring-ring data-[disabled]:cursor-not-allowed data-[disabled]:opacity-45", [
143
+ bottom.value ? unref(BOTTOM_ITEM) : "shrink-0 gap-1.5 whitespace-nowrap text-sm",
144
+ __props.block && !bottom.value ? "flex-1" : "",
145
+ __props.variant === "underline" ? "rounded-t-inner px-3 pt-1.5 pb-2" : "",
146
+ __props.variant === "contained" || __props.variant === "plain" ? "rounded-inner px-3 py-1.5" : "",
147
+ __props.accent ? "data-[state=active]:text-brand" : "data-[state=active]:text-ink",
148
+ hovered.value === item.value && !bottom.value ? "text-ink" : !__props.hoverFollow && !bottom.value ? "text-muted hover:text-ink" : "text-muted"
149
+ ]]),
150
+ onPointerenter: ($event) => __props.hoverFollow && !item.disabled && (hovered.value = item.value),
151
+ onPointerup: releaseFocusAfterPointer,
152
+ onClick: ($event) => clickPick(item)
153
+ }, {
154
+ default: withCtx(() => [
155
+ pillUnder(item.value, current.value) ? (openBlock(), createBlock(unref(Motion), {
156
+ key: 0,
157
+ "layout-id": pillId,
158
+ transition: unref(pillTransition),
159
+ class: normalizeClass(__props.variant === "underline" ? [
160
+ "absolute inset-x-0 -bottom-px z-0 h-0.5 rounded-full",
161
+ __props.accent ? "bg-brand" : "bg-ink"
162
+ ] : bottom.value ? [unref(BOTTOM_MARKER), __props.accent ? "bg-brand" : "bg-ink"] : [
163
+ "absolute inset-0 z-0 rounded-inner shadow-sm",
164
+ __props.accent ? "border border-brand/35 bg-brand/12" : "border border-line bg-surface-raised"
165
+ ])
166
+ }, null, 8, ["transition", "class"])) : createCommentVNode("", true),
167
+ createVNode(_sfc_main$3, {
168
+ item,
169
+ bottom: bottom.value,
170
+ compact: __props.compact,
171
+ active: current.value === item.value
172
+ }, null, 8, ["item", "bottom", "compact", "active"])
173
+ ]),
174
+ _: 2
175
+ }, 1032, ["value", "disabled", "title", "class", "onPointerenter", "onClick"])
157
176
  ]),
158
177
  _: 2
159
- }, 1032, ["value", "disabled", "title", "class", "onPointerenter"])
160
- ]),
161
- _: 2
162
- }, 1032, ["items", "title", "title-icon"]);
163
- }), 128)),
164
- !__props.items.length ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(bottom.value ? 4 : 3, (n) => {
165
- return openBlock(), createElementBlock("span", {
166
- key: `skeleton-${n}`,
167
- class: normalizeClass(["flex items-center justify-center", bottom.value ? "min-h-14 flex-col gap-1.5 py-1.5" : "px-1 py-1.5"])
168
- }, [
169
- bottom.value ? (openBlock(), createBlock(_sfc_main$3, {
170
- key: 0,
171
- rounded: "pill",
172
- class: "size-5"
173
- })) : createCommentVNode("", true),
174
- createVNode(_sfc_main$3, {
175
- class: normalizeClass(bottom.value ? "h-2.5 w-10" : "h-5 w-16")
176
- }, null, 8, ["class"])
177
- ], 2);
178
- }), 128)) : createCommentVNode("", true)
178
+ }, 1032, ["items", "title", "title-icon"]);
179
+ }), 128)),
180
+ !__props.items.length ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(bottom.value ? 4 : 3, (n) => {
181
+ return openBlock(), createElementBlock("span", {
182
+ key: `skeleton-${n}`,
183
+ class: normalizeClass(["flex items-center justify-center", bottom.value ? "min-h-14 flex-col gap-1.5 py-1.5" : "px-1 py-1.5"])
184
+ }, [
185
+ bottom.value ? (openBlock(), createBlock(_sfc_main$4, {
186
+ key: 0,
187
+ rounded: "pill",
188
+ class: "size-5"
189
+ })) : createCommentVNode("", true),
190
+ createVNode(_sfc_main$4, {
191
+ class: normalizeClass(bottom.value ? "h-2.5 w-10" : "h-5 w-16")
192
+ }, null, 8, ["class"])
193
+ ], 2);
194
+ }), 128)) : createCommentVNode("", true)
195
+ ]),
196
+ _: 1
197
+ }, 8, ["aria-label", "class"])
179
198
  ]),
180
199
  _: 1
181
- }, 8, ["aria-label", "class"]),
200
+ }, 16)),
182
201
  _ctx.$slots.panel ? (openBlock(), createBlock(unref(Motion), {
183
202
  key: 0,
184
203
  layout: true,
@@ -210,7 +229,7 @@ import '../assets/LpTabs-Bh7a-Bdl.css';const _sfc_main = /* @__PURE__ */ defineC
210
229
  };
211
230
  }
212
231
  });
213
- const LpTabs = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-ef828291"]]);
232
+ const LpTabs = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-60b1eda3"]]);
214
233
  export {
215
234
  LpTabs as default
216
235
  };
@@ -1,5 +1,6 @@
1
- import { defineComponent, ref, computed, watch, shallowRef, nextTick, onMounted, onBeforeUnmount, openBlock, createElementBlock, mergeProps, unref, createVNode, withCtx, createElementVNode, toHandlers, Transition, normalizeProps, guardReactiveProps, normalizeStyle, Fragment, renderList, normalizeClass, createCommentVNode, toDisplayString, renderSlot, createBlock, createTextVNode, TransitionGroup, withKeys, withModifiers } from "vue";
1
+ import { defineComponent, ref, computed, watch, onBeforeUnmount, shallowRef, nextTick, onMounted, openBlock, createElementBlock, mergeProps, unref, createVNode, withCtx, createElementVNode, toHandlers, Transition, normalizeProps, guardReactiveProps, normalizeStyle, Fragment, renderList, normalizeClass, createCommentVNode, toDisplayString, renderSlot, createBlock, createTextVNode, TransitionGroup, withKeys, withModifiers } from "vue";
2
2
  import { startPointerDrag } from "../composables/pointerDrag.js";
3
+ import { createGesture } from "../composables/useGesture.js";
3
4
  import { nodeWindow, isHTMLElement } from "../composables/realm.js";
4
5
  import { useLabels } from "../composables/useLpConfig.js";
5
6
  import { useMergedAttrs } from "../composables/useMergedClass.js";
@@ -20,7 +21,7 @@ import { formatClipTime, widestClipTime } from "./videoBackdrop.js";
20
21
  import { stillSpan, FrameSampler } from "./videoFrames.js";
21
22
  import { normalizeRange, ticks, tickStep, containRect, setEnd, revealTime, zoomView, shiftView, adjustRegion, dragEnd, parseClipTime, regionBetween } from "./videoTrim.js";
22
23
  import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper-1tPrXgE0.js";
23
- import '../assets/LpVideoTrim-CMoUw3dJ.css';const _hoisted_1 = ["data-disabled"];
24
+ import '../assets/LpVideoTrim-D8JDg9Qn.css';const _hoisted_1 = ["data-disabled"];
24
25
  const _hoisted_2 = ["src", "poster"];
25
26
  const _hoisted_3 = ["src"];
26
27
  const _hoisted_4 = ["data-live", "aria-label"];
@@ -261,8 +262,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
261
262
  }
262
263
  const marks = computed(() => ready.value ? ticks(view.value, tickStep(span.value, trackWidth.value)) : []);
263
264
  const markDigits = computed(() => tickStep(span.value, trackWidth.value) < 1);
264
- const pointers = /* @__PURE__ */ new Map();
265
- let pinch = null;
266
265
  const pinching = ref(false);
267
266
  let edgeFrame = 0;
268
267
  let lastX = 0;
@@ -310,48 +309,40 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
310
309
  edgeScroll();
311
310
  });
312
311
  }
313
- function onTrackDown(event) {
314
- if (off.value || event.pointerType === "mouse" && event.button !== 0) return;
315
- event.currentTarget.setPointerCapture(event.pointerId);
316
- pointers.set(event.pointerId, event.clientX);
317
- if (pointers.size === 2) {
312
+ let pinchDistance = 0;
313
+ let pinchAnchor = 0;
314
+ const track = createGesture({
315
+ threshold: 0,
316
+ onPress(event) {
317
+ if (off.value || event.pointerType === "mouse" && event.button !== 0) return false;
318
+ event.preventDefault();
319
+ trackEl.value?.querySelector("[data-lp-playhead]")?.focus({ preventScroll: true });
320
+ pause();
321
+ scrubbing.value = true;
322
+ lastX = event.clientX;
323
+ seek(timeAt(event.clientX));
324
+ },
325
+ onDrag({ point }) {
326
+ if (!scrubbing.value) return;
327
+ lastX = point.x;
328
+ seek(timeAt(point.x));
329
+ edgeScroll();
330
+ },
331
+ onDragEnd: () => scrubbing.value = false,
332
+ onTap: () => scrubbing.value = false,
333
+ onPinchStart(pinch) {
318
334
  scrubbing.value = false;
319
- const [a, b] = [...pointers.values()];
320
- pinch = { distance: Math.max(8, Math.abs(a - b)), anchor: timeAt((a + b) / 2) };
321
335
  pinching.value = true;
322
- return;
323
- }
324
- if (pointers.size > 2) return;
325
- event.preventDefault();
326
- trackEl.value?.querySelector("[data-lp-playhead]")?.focus({ preventScroll: true });
327
- pause();
328
- scrubbing.value = true;
329
- lastX = event.clientX;
330
- seek(timeAt(event.clientX));
331
- }
332
- function onTrackMove(event) {
333
- if (!pointers.has(event.pointerId)) return;
334
- pointers.set(event.pointerId, event.clientX);
335
- if (pinch && pointers.size === 2) {
336
- const [a, b] = [...pointers.values()];
337
- const distance = Math.max(8, Math.abs(a - b));
338
- zoomBy(distance / pinch.distance, pinch.anchor);
339
- pinch.distance = distance;
340
- return;
341
- }
342
- if (!scrubbing.value) return;
343
- lastX = event.clientX;
344
- seek(timeAt(event.clientX));
345
- edgeScroll();
346
- }
347
- function onTrackUp(event) {
348
- pointers.delete(event.pointerId);
349
- if (pointers.size < 2) {
350
- pinch = null;
351
- pinching.value = false;
352
- }
353
- if (!pointers.size) scrubbing.value = false;
354
- }
336
+ pinchDistance = pinch.distance;
337
+ pinchAnchor = timeAt(pinch.origin.x);
338
+ },
339
+ onPinch(pinch) {
340
+ zoomBy(pinch.distance / Math.max(8, pinchDistance), pinchAnchor);
341
+ pinchDistance = pinch.distance;
342
+ },
343
+ onPinchEnd: () => pinching.value = false
344
+ });
345
+ onBeforeUnmount(track.dispose);
355
346
  function onOverviewDown(event) {
356
347
  if (off.value || event.button !== 0) return;
357
348
  const box = event.currentTarget.getBoundingClientRect();
@@ -908,17 +899,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
908
899
  ]),
909
900
  _: 1
910
901
  }, 16),
911
- createElementVNode("div", {
902
+ createElementVNode("div", mergeProps({
912
903
  ref_key: "trackEl",
913
904
  ref: trackEl,
914
- class: normalizeClass(["relative h-14 touch-none rounded-control bg-surface-soft transition-opacity duration-(--duration-fast) motion-reduce:transition-none", off.value ? "opacity-60" : "cursor-text"]),
905
+ class: ["relative h-14 touch-none rounded-control bg-surface-soft transition-opacity duration-(--duration-fast) motion-reduce:transition-none", off.value ? "opacity-60" : "cursor-text"],
915
906
  "aria-label": unref(text).timeline,
916
- role: "group",
917
- onPointerdown: onTrackDown,
918
- onPointermove: onTrackMove,
919
- onPointerup: onTrackUp,
920
- onPointercancel: onTrackUp
921
- }, [
907
+ role: "group"
908
+ }, unref(track).handlers), [
922
909
  createElementVNode("div", _hoisted_13, [
923
910
  createVNode(TransitionGroup, normalizeProps(guardReactiveProps(unref(FADE))), {
924
911
  default: withCtx(() => [
@@ -1001,7 +988,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1001
988
  createElementVNode("span", { class: "absolute -top-0.5 -left-1.5 size-3 rounded-full bg-white shadow-[0_0_0_1px_rgb(0_0_0/0.3),0_1px_3px_rgb(0_0_0/0.35)] group-focus-visible/playhead:ring-2 group-focus-visible/playhead:ring-ring" }, null, -1)
1002
989
  ])], 2)
1003
990
  ], 12, _hoisted_16)
1004
- ], 42, _hoisted_12),
991
+ ], 16, _hoisted_12),
1005
992
  createVNode(Transition, normalizeProps(guardReactiveProps(unref(FADE))), {
1006
993
  default: withCtx(() => [
1007
994
  zoomed.value ? (openBlock(), createElementBlock("div", {
@@ -1100,7 +1087,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1100
1087
  };
1101
1088
  }
1102
1089
  });
1103
- const LpVideoTrim = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-ba15829e"]]);
1090
+ const LpVideoTrim = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-5ee84a84"]]);
1104
1091
  export {
1105
1092
  LpVideoTrim as default
1106
1093
  };