@leavepulse/ui 0.28.3 → 0.28.4

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 (34) hide show
  1. package/dist/chunks/{LpAddressInput-BTqnUXZG.js → LpAddressInput-BoTkszLk.js} +3 -3
  2. package/dist/chunks/{LpAppShell-B5k0J3Cf.js → LpAppShell-CGX0DlIW.js} +11 -6
  3. package/dist/chunks/{LpCard-gu11ZmSt.js → LpCard-DSefTGEH.js} +7 -1
  4. package/dist/chunks/{LpFormField-CesaPWPO.js → LpFormField-DEaakcHe.js} +1 -1
  5. package/dist/chunks/{LpInput-jwqXlAy0.js → LpInput-BXr40nqX.js} +1 -1
  6. package/dist/chunks/{LpPasswordInput-Bmo6q9Kd.js → LpPasswordInput-Bdv6o8ae.js} +1 -1
  7. package/dist/chunks/{LpSelect-Cw8-gL5F.js → LpSelect-ANIVtrpM.js} +1 -1
  8. package/dist/chunks/{LpSidebar-7Vpy2IJc.js → LpSidebar-CWehDCxN.js} +34 -8
  9. package/dist/chunks/LpSidebarNav-5RGNr2D3.js +185 -0
  10. package/dist/chunks/{LpTextarea-1ENb3ZAO.js → LpTextarea-tc8N4UO_.js} +1 -1
  11. package/dist/components/LpAddressInput.vue.js +1 -1
  12. package/dist/components/LpAppShell.vue.d.ts +17 -11
  13. package/dist/components/LpAppShell.vue.js +1 -1
  14. package/dist/components/LpCard.vue.js +1 -1
  15. package/dist/components/LpFormField.vue.js +1 -1
  16. package/dist/components/LpInput.vue.js +1 -1
  17. package/dist/components/LpPasswordInput.vue.js +1 -1
  18. package/dist/components/LpSelect.vue.js +1 -1
  19. package/dist/components/LpSidebar.vue.d.ts +32 -10
  20. package/dist/components/LpSidebar.vue.js +1 -1
  21. package/dist/components/LpSidebarNav.vue.d.ts +11 -2
  22. package/dist/components/LpSidebarNav.vue.js +1 -1
  23. package/dist/components/LpTextarea.vue.js +1 -1
  24. package/dist/components/sidebar.d.ts +18 -0
  25. package/dist/index.js +9 -9
  26. package/package.json +1 -1
  27. package/src/components/LpAppShell.vue +27 -3
  28. package/src/components/LpCard.vue +7 -1
  29. package/src/components/LpFormField.vue +6 -2
  30. package/src/components/LpSelect.vue +0 -0
  31. package/src/components/LpSidebar.vue +67 -1
  32. package/src/components/LpSidebarNav.vue +83 -4
  33. package/src/components/sidebar.ts +18 -0
  34. package/dist/chunks/LpSidebarNav-CFX5NxGs.js +0 -126
@@ -3,11 +3,11 @@ import { OSM_TILES, createNominatimProvider, emptyAddress, formatAddress } from
3
3
  import { flagEmoji, loadCountries } from "../components/countries.js";
4
4
  import { _ as _sfc_main$2 } from "./LpAutocomplete-DExlIZe_.js";
5
5
  import { _ as _sfc_main$3 } from "./LpButton-5VXXCjwF.js";
6
- import { _ as _sfc_main$1 } from "./LpFormField-CesaPWPO.js";
6
+ import { _ as _sfc_main$1 } from "./LpFormField-DEaakcHe.js";
7
7
  import { _ as _sfc_main$4 } from "./LpIcon-CCnX5_2j.js";
8
- import { _ as _sfc_main$5 } from "./LpInput-jwqXlAy0.js";
8
+ import { _ as _sfc_main$5 } from "./LpInput-BXr40nqX.js";
9
9
  import { _ as _sfc_main$7 } from "./LpModal-D_o-56To.js";
10
- import { _ as _sfc_main$6 } from "./LpSelect-Cw8-gL5F.js";
10
+ import { _ as _sfc_main$6 } from "./LpSelect-ANIVtrpM.js";
11
11
  const _hoisted_1 = { class: "flex flex-col gap-3" };
12
12
  const _hoisted_2 = { class: "flex items-stretch gap-2" };
13
13
  const _hoisted_3 = { class: "grid gap-3 sm:grid-cols-[minmax(0,1fr)_10rem]" };
@@ -3,10 +3,10 @@ import { _ as _sfc_main$2 } from "./LpButton-5VXXCjwF.js";
3
3
  import { _ as _sfc_main$3 } from "./LpIcon-CCnX5_2j.js";
4
4
  import { _ as _sfc_main$5 } from "./LpScrollArea-D8xyKXcF.js";
5
5
  import { _ as _sfc_main$4 } from "./LpShift-DXNsauQZ.js";
6
- import { _ as _sfc_main$1 } from "./LpSidebar-7Vpy2IJc.js";
6
+ import { _ as _sfc_main$1 } from "./LpSidebar-CWehDCxN.js";
7
7
  const _hoisted_1 = { class: "flex h-dvh overflow-hidden bg-surface text-ink" };
8
8
  const _hoisted_2 = { class: "flex min-w-0 flex-1 flex-col" };
9
- const _hoisted_3 = { class: "flex h-16 shrink-0 items-center gap-3 border-b border-line bg-surface px-4 md:px-6" };
9
+ const _hoisted_3 = { class: "relative flex h-16 shrink-0 items-center gap-3 border-b border-line bg-surface px-4 md:px-6" };
10
10
  const _hoisted_4 = { class: "truncate text-lg font-semibold" };
11
11
  const _hoisted_5 = {
12
12
  key: 0,
@@ -17,6 +17,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
17
17
  props: {
18
18
  items: {},
19
19
  sections: {},
20
+ collapsed: {},
21
+ autoCollapseAfter: {},
20
22
  modelValue: {},
21
23
  path: {},
22
24
  isActive: {},
@@ -28,7 +30,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
28
30
  fullBleed: { type: Boolean },
29
31
  loading: { type: Boolean }
30
32
  },
31
- emits: ["update:modelValue", "update:open", "select"],
33
+ emits: ["update:modelValue", "update:open", "update:collapsed", "select"],
32
34
  setup(__props, { expose: __expose, emit: __emit }) {
33
35
  const props = __props;
34
36
  const emit = __emit;
@@ -91,9 +93,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
91
93
  "mobile-breakpoint": __props.mobileBreakpoint,
92
94
  divider: __props.divider,
93
95
  loading: __props.loading,
96
+ collapsed: __props.collapsed,
97
+ "auto-collapse-after": __props.autoCollapseAfter,
94
98
  class: "shrink-0",
95
99
  "onUpdate:modelValue": onModel,
96
100
  "onUpdate:open": _cache[0] || (_cache[0] = (v) => emit("update:open", v)),
101
+ "onUpdate:collapsed": _cache[1] || (_cache[1] = (v) => emit("update:collapsed", v)),
97
102
  onSelect
98
103
  }, createSlots({ _: 2 }, [
99
104
  _ctx.$slots.logo ? {
@@ -124,7 +129,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
124
129
  ]),
125
130
  key: "3"
126
131
  } : void 0
127
- ]), 1032, ["model-value", "items", "sections", "is-active", "open", "mobile-breakpoint", "divider", "loading"]),
132
+ ]), 1032, ["model-value", "items", "sections", "is-active", "open", "mobile-breakpoint", "divider", "loading", "collapsed", "auto-collapse-after"]),
128
133
  createElementVNode("div", _hoisted_2, [
129
134
  createElementVNode("header", _hoisted_3, [
130
135
  createVNode(_sfc_main$2, {
@@ -133,7 +138,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
133
138
  size: "sm",
134
139
  square: "",
135
140
  "aria-label": "Open menu",
136
- onClick: _cache[1] || (_cache[1] = ($event) => emit("update:open", true))
141
+ onClick: _cache[2] || (_cache[2] = ($event) => emit("update:open", true))
137
142
  }, {
138
143
  default: withCtx(() => [
139
144
  createVNode(_sfc_main$3, {
@@ -156,7 +161,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
156
161
  }),
157
162
  createVNode(_sfc_main$4, {
158
163
  axis: "width",
159
- class: "ml-auto flex shrink-0 items-center gap-2"
164
+ class: "ml-auto flex max-w-[66%] shrink items-center gap-2 overflow-x-auto lp-scrollbar-none md:max-w-none md:shrink-0 md:overflow-visible"
160
165
  }, {
161
166
  default: withCtx(() => [
162
167
  renderSlot(_ctx.$slots, "header-actions")
@@ -22,7 +22,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
22
22
  // renders: two lines that look identical must not wrap differently.
23
23
  // Anything that genuinely must not break (a code block, a log line) sets its
24
24
  // own overflow and scrolls instead.
25
- base: "rounded-card border bg-surface-raised break-words",
25
+ // min-w-0: a card is nearly always laid out by a grid or a flex row, and both
26
+ // give their children `min-width: auto` — meaning "never narrower than your
27
+ // contents". A card holding a form then refuses to shrink and pushes its own
28
+ // column past the viewport: measured at 490px inside a 358px grid, with the
29
+ // inputs ending up off-screen on a phone. The card is a container; it takes
30
+ // the width it is given and wraps what is inside it.
31
+ base: "min-w-0 rounded-card border bg-surface-raised break-words",
26
32
  variants: {
27
33
  variant: {
28
34
  // raised opts into the skin painter (.lp-skin-panel) so it follows the
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, useId, openBlock, createElementBlock, createBlock, unref, withCtx, createTextVNode, toDisplayString, createCommentVNode, renderSlot, createVNode } from "vue";
2
2
  import { Label } from "reka-ui";
3
3
  import { _ as _sfc_main$1 } from "./LpShift-DXNsauQZ.js";
4
- const _hoisted_1 = { class: "flex flex-col gap-1.5" };
4
+ const _hoisted_1 = { class: "flex min-w-0 flex-col gap-1.5" };
5
5
  const _hoisted_2 = {
6
6
  key: 0,
7
7
  class: "text-danger"
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, computed, useSlots, useAttrs, ref, openBlock, createBlock, resolveDynamicComponent, normalizeStyle, normalizeClass, withCtx, createElementVNode, createElementBlock, renderSlot, createCommentVNode, mergeProps, unref } from "vue";
2
2
  import { tv } from "tailwind-variants";
3
3
  import { useInputFilter } from "../composables/useInputFilter.js";
4
- import { _ as _sfc_main$1 } from "./LpFormField-CesaPWPO.js";
4
+ import { _ as _sfc_main$1 } from "./LpFormField-DEaakcHe.js";
5
5
  import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
6
6
  const _hoisted_1 = {
7
7
  key: 0,
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, ref, openBlock, createBlock, createSlots, withCtx, createElementVNode, createVNode, renderSlot } from "vue";
2
2
  import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
3
- import { _ as _sfc_main$1 } from "./LpInput-jwqXlAy0.js";
3
+ import { _ as _sfc_main$1 } from "./LpInput-BXr40nqX.js";
4
4
  const _hoisted_1 = ["aria-label"];
5
5
  const __default__ = { inheritAttrs: false };
6
6
  const _sfc_main = /* @__PURE__ */ defineComponent({
@@ -128,7 +128,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
128
128
  ])
129
129
  }, {
130
130
  default: withCtx(() => [
131
- createVNode(unref(ComboboxTrigger), { class: "flex flex-1 items-center gap-2 outline-none" }, {
131
+ createVNode(unref(ComboboxTrigger), { class: "flex min-w-0 flex-1 items-center gap-2 outline-none" }, {
132
132
  default: withCtx(() => [
133
133
  displayLabel.value ? (openBlock(), createElementBlock("span", _hoisted_1, toDisplayString(displayLabel.value), 1)) : (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString(__props.placeholder), 1))
134
134
  ]),
@@ -1,6 +1,6 @@
1
- import { defineComponent, computed, useId, openBlock, createElementBlock, Fragment, createElementVNode, mergeProps, normalizeClass, renderSlot, createCommentVNode, createVNode, createSlots, withCtx, normalizeProps, guardReactiveProps, createBlock } from "vue";
1
+ import { defineComponent, computed, ref, useId, openBlock, createElementBlock, Fragment, createElementVNode, mergeProps, normalizeClass, renderSlot, createCommentVNode, createVNode, createSlots, withCtx, normalizeProps, guardReactiveProps, createBlock } from "vue";
2
2
  import { _ as _sfc_main$2 } from "./LpDrawer-DAJN5rGK.js";
3
- import { _ as _sfc_main$1 } from "./LpSidebarNav-CFX5NxGs.js";
3
+ import { _ as _sfc_main$1 } from "./LpSidebarNav-5RGNr2D3.js";
4
4
  const _hoisted_1 = {
5
5
  key: 1,
6
6
  class: "mt-2 flex shrink-0 flex-col gap-2"
@@ -33,9 +33,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
33
33
  open: { type: Boolean },
34
34
  mobileBreakpoint: { default: "md" },
35
35
  edgeOpen: { type: Boolean },
36
- divider: { type: Boolean, default: true }
36
+ divider: { type: Boolean, default: true },
37
+ collapsed: {},
38
+ autoCollapseAfter: { default: 14 }
37
39
  },
38
- emits: ["update:modelValue", "update:open", "select"],
40
+ emits: ["update:modelValue", "update:open", "update:collapsed", "select"],
39
41
  setup(__props, { emit: __emit }) {
40
42
  const props = __props;
41
43
  const emit = __emit;
@@ -45,6 +47,26 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
45
47
  function itemActive(item) {
46
48
  return props.isActive ? props.isActive(item) : item.id === props.modelValue;
47
49
  }
50
+ function keyOf(section) {
51
+ return section.key ?? section.title ?? "";
52
+ }
53
+ const ownCollapsed = ref(null);
54
+ const navLength = computed(
55
+ () => groups.value.reduce((n, g) => n + g.items.length + (g.title ? 1 : 0), 0)
56
+ );
57
+ const autoCollapsed = computed(() => {
58
+ const limit = props.autoCollapseAfter;
59
+ if (!limit || navLength.value <= limit) return [];
60
+ return groups.value.filter((g) => g.collapsible && !g.items.some(itemActive)).map(keyOf).filter(Boolean);
61
+ });
62
+ const collapsedKeys = computed(
63
+ () => props.collapsed ?? ownCollapsed.value ?? autoCollapsed.value
64
+ );
65
+ function toggleSection(key, collapsed) {
66
+ const next = collapsed ? [.../* @__PURE__ */ new Set([...collapsedKeys.value, key])] : collapsedKeys.value.filter((k) => k !== key);
67
+ ownCollapsed.value = next;
68
+ emit("update:collapsed", next);
69
+ }
48
70
  function activate(item) {
49
71
  if (item.disabled) return;
50
72
  emit("update:modelValue", item.id);
@@ -82,7 +104,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
82
104
  loading: __props.loading,
83
105
  "skeleton-rows": __props.skeletonRows,
84
106
  "skeleton-header": __props.skeletonHeader,
85
- onActivate: activate
107
+ "collapsed-keys": collapsedKeys.value,
108
+ onActivate: activate,
109
+ onToggleSection: toggleSection
86
110
  }, createSlots({ _: 2 }, [
87
111
  _ctx.$slots.item ? {
88
112
  name: "item",
@@ -91,7 +115,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
91
115
  ]),
92
116
  key: "0"
93
117
  } : void 0
94
- ]), 1032, ["groups", "loading", "skeleton-rows", "skeleton-header"]),
118
+ ]), 1032, ["groups", "loading", "skeleton-rows", "skeleton-header", "collapsed-keys"]),
95
119
  _ctx.$slots.actions ? (openBlock(), createElementBlock("div", _hoisted_1, [
96
120
  renderSlot(_ctx.$slots, "actions")
97
121
  ])) : createCommentVNode("", true),
@@ -123,7 +147,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
123
147
  loading: __props.loading,
124
148
  "skeleton-rows": __props.skeletonRows,
125
149
  "skeleton-header": __props.skeletonHeader,
126
- onActivate: activate
150
+ "collapsed-keys": collapsedKeys.value,
151
+ onActivate: activate,
152
+ onToggleSection: toggleSection
127
153
  }, createSlots({ _: 2 }, [
128
154
  _ctx.$slots.item ? {
129
155
  name: "item",
@@ -132,7 +158,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
132
158
  ]),
133
159
  key: "0"
134
160
  } : void 0
135
- ]), 1032, ["groups", "loading", "skeleton-rows", "skeleton-header"]),
161
+ ]), 1032, ["groups", "loading", "skeleton-rows", "skeleton-header", "collapsed-keys"]),
136
162
  _ctx.$slots.actions ? (openBlock(), createElementBlock("div", _hoisted_4, [
137
163
  renderSlot(_ctx.$slots, "actions")
138
164
  ])) : createCommentVNode("", true),
@@ -0,0 +1,185 @@
1
+ import { defineComponent, computed, openBlock, createElementBlock, createElementVNode, createCommentVNode, Fragment, renderList, createBlock, withCtx, unref, toDisplayString, createVNode, normalizeClass, createTextVNode, resolveDynamicComponent, renderSlot } from "vue";
2
+ import { Motion } from "motion-v";
3
+ import { CollapsibleRoot, CollapsibleTrigger, CollapsibleContent } from "reka-ui";
4
+ import { usePillTransition } from "../composables/usePillTransition.js";
5
+ import { _ as _sfc_main$3 } from "./LpBadge-BPodVcJa.js";
6
+ import { _ as _sfc_main$4 } from "./LpContextMenu-D0mzXqA7.js";
7
+ import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
8
+ import { _ as _sfc_main$1 } from "./LpScrollArea-D8xyKXcF.js";
9
+ const _hoisted_1 = {
10
+ key: 0,
11
+ class: "flex min-h-0 flex-1 flex-col gap-4"
12
+ };
13
+ const _hoisted_2 = {
14
+ key: 0,
15
+ class: "flex items-center gap-3 px-1"
16
+ };
17
+ const _hoisted_3 = { class: "space-y-1" };
18
+ const _hoisted_4 = { class: "min-w-0 flex-1 truncate text-left" };
19
+ const _hoisted_5 = {
20
+ key: 1,
21
+ class: "px-2 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted"
22
+ };
23
+ const _hoisted_6 = { class: "relative z-10 min-w-0 flex-1 truncate text-left" };
24
+ const _sfc_main = /* @__PURE__ */ defineComponent({
25
+ __name: "LpSidebarNav",
26
+ props: {
27
+ groups: {},
28
+ pillId: {},
29
+ itemActive: {},
30
+ loading: { type: Boolean },
31
+ skeletonRows: { default: 6 },
32
+ skeletonHeader: { type: Boolean, default: true },
33
+ collapsedKeys: { default: () => [] }
34
+ },
35
+ emits: ["activate", "toggle-section"],
36
+ setup(__props, { emit: __emit }) {
37
+ const props = __props;
38
+ const emit = __emit;
39
+ function sectionKey(section) {
40
+ return section.key ?? section.title ?? "";
41
+ }
42
+ const foldedKeys = computed(() => {
43
+ const holdsActive = new Set(
44
+ props.groups.filter((g) => g.items.some((i) => props.itemActive(i))).map(sectionKey)
45
+ );
46
+ return new Set(
47
+ props.collapsedKeys.filter((k) => k && !holdsActive.has(k))
48
+ );
49
+ });
50
+ function isOpen(section) {
51
+ return !foldedKeys.value.has(sectionKey(section));
52
+ }
53
+ const pillTransition = usePillTransition();
54
+ return (_ctx, _cache) => {
55
+ return __props.loading ? (openBlock(), createElementBlock("div", _hoisted_1, [
56
+ __props.skeletonHeader ? (openBlock(), createElementBlock("div", _hoisted_2, [..._cache[0] || (_cache[0] = [
57
+ createElementVNode("div", { class: "size-10 shrink-0 animate-pulse rounded-pill bg-surface-soft" }, null, -1),
58
+ createElementVNode("div", { class: "flex-1 space-y-2" }, [
59
+ createElementVNode("div", { class: "h-3.5 w-24 animate-pulse rounded bg-surface-soft" }),
60
+ createElementVNode("div", { class: "h-3 w-16 animate-pulse rounded bg-surface-soft/60" })
61
+ ], -1)
62
+ ])])) : createCommentVNode("", true),
63
+ createElementVNode("div", _hoisted_3, [
64
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.skeletonRows, (n) => {
65
+ return openBlock(), createElementBlock("div", {
66
+ key: n,
67
+ class: "h-9 animate-pulse rounded-control bg-surface-soft"
68
+ });
69
+ }), 128))
70
+ ])
71
+ ])) : (openBlock(), createBlock(_sfc_main$1, {
72
+ key: 1,
73
+ class: "min-h-0 flex-1",
74
+ "content-class": "flex min-h-full flex-col gap-4"
75
+ }, {
76
+ default: withCtx(() => [
77
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.groups, (section, si) => {
78
+ return openBlock(), createBlock(unref(CollapsibleRoot), {
79
+ key: si,
80
+ as: "div",
81
+ class: "flex flex-col gap-0.5",
82
+ open: isOpen(section),
83
+ disabled: !section.collapsible || !section.title,
84
+ "onUpdate:open": (o) => emit("toggle-section", sectionKey(section), !o)
85
+ }, {
86
+ default: withCtx(() => [
87
+ section.title && section.collapsible ? (openBlock(), createBlock(unref(CollapsibleTrigger), {
88
+ key: 0,
89
+ class: "group/section mt-2 flex cursor-pointer items-center gap-2 rounded-control px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:bg-white/[0.04] hover:text-ink focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
90
+ }, {
91
+ default: withCtx(() => [
92
+ section.icon ? (openBlock(), createBlock(_sfc_main$2, {
93
+ key: 0,
94
+ name: section.icon,
95
+ size: 14,
96
+ class: "shrink-0"
97
+ }, null, 8, ["name"])) : createCommentVNode("", true),
98
+ createElementVNode("span", _hoisted_4, toDisplayString(section.title), 1),
99
+ createVNode(_sfc_main$3, {
100
+ tone: "neutral",
101
+ class: normalizeClass(["shrink-0 transition-opacity duration-[var(--duration-fast)] motion-reduce:transition-none", isOpen(section) ? "opacity-0" : "opacity-100"]),
102
+ "aria-hidden": isOpen(section) || void 0
103
+ }, {
104
+ default: withCtx(() => [
105
+ createTextVNode(toDisplayString(section.items.length), 1)
106
+ ]),
107
+ _: 2
108
+ }, 1032, ["class", "aria-hidden"]),
109
+ createVNode(_sfc_main$2, {
110
+ name: "lucide:chevron-down",
111
+ size: 14,
112
+ class: "shrink-0 text-muted transition-transform duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] group-data-[state=closed]/section:-rotate-90 motion-reduce:transition-none"
113
+ })
114
+ ]),
115
+ _: 2
116
+ }, 1024)) : section.title ? (openBlock(), createElementBlock("p", _hoisted_5, toDisplayString(section.title), 1)) : createCommentVNode("", true),
117
+ createVNode(unref(CollapsibleContent), { class: "flex flex-col gap-0.5 overflow-hidden data-[state=open]:animate-[collapsible-down_260ms_var(--ease-emphasized)] data-[state=closed]:animate-[collapsible-up_200ms_var(--ease-emphasized)] motion-reduce:animate-none" }, {
118
+ default: withCtx(() => [
119
+ (openBlock(true), createElementBlock(Fragment, null, renderList(section.items, (item) => {
120
+ return openBlock(), createBlock(_sfc_main$4, {
121
+ key: item.id,
122
+ items: item.menu ?? []
123
+ }, {
124
+ default: withCtx(() => [
125
+ (openBlock(), createBlock(resolveDynamicComponent(item.href && !item.disabled ? "a" : "button"), {
126
+ href: item.href && !item.disabled ? item.href : void 0,
127
+ type: item.href ? void 0 : "button",
128
+ disabled: item.href ? void 0 : item.disabled,
129
+ "aria-current": __props.itemActive(item) ? "page" : void 0,
130
+ "aria-disabled": item.disabled || void 0,
131
+ class: normalizeClass(["group/item relative flex items-center gap-3 rounded-control px-3 py-2 text-sm font-medium outline-none transition-colors duration-[var(--duration-fast)] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring", item.disabled ? "cursor-not-allowed text-muted/50" : __props.itemActive(item) ? "text-ink" : "text-muted hover:text-ink"]),
132
+ onClick: ($event) => emit("activate", item)
133
+ }, {
134
+ default: withCtx(() => [
135
+ __props.itemActive(item) ? (openBlock(), createBlock(unref(Motion), {
136
+ key: 0,
137
+ "layout-id": __props.pillId,
138
+ transition: unref(pillTransition),
139
+ class: "absolute inset-0 z-0 rounded-control bg-brand-soft"
140
+ }, null, 8, ["layout-id", "transition"])) : createCommentVNode("", true),
141
+ renderSlot(_ctx.$slots, "item", {
142
+ item,
143
+ active: __props.itemActive(item)
144
+ }, () => [
145
+ item.icon ? (openBlock(), createBlock(_sfc_main$2, {
146
+ key: 0,
147
+ name: item.icon,
148
+ size: 17,
149
+ class: normalizeClass(["relative z-10 shrink-0 transition-colors", __props.itemActive(item) ? "text-brand" : ""])
150
+ }, null, 8, ["name", "class"])) : createCommentVNode("", true),
151
+ createElementVNode("span", _hoisted_6, toDisplayString(item.label), 1),
152
+ item.badge != null ? (openBlock(), createBlock(_sfc_main$3, {
153
+ key: 1,
154
+ tone: __props.itemActive(item) ? "brand" : "neutral",
155
+ class: "relative z-10 shrink-0"
156
+ }, {
157
+ default: withCtx(() => [
158
+ createTextVNode(toDisplayString(item.badge), 1)
159
+ ]),
160
+ _: 2
161
+ }, 1032, ["tone"])) : createCommentVNode("", true)
162
+ ])
163
+ ]),
164
+ _: 2
165
+ }, 1032, ["href", "type", "disabled", "aria-current", "aria-disabled", "class", "onClick"]))
166
+ ]),
167
+ _: 2
168
+ }, 1032, ["items"]);
169
+ }), 128))
170
+ ]),
171
+ _: 2
172
+ }, 1024)
173
+ ]),
174
+ _: 2
175
+ }, 1032, ["open", "disabled", "onUpdate:open"]);
176
+ }), 128))
177
+ ]),
178
+ _: 3
179
+ }));
180
+ };
181
+ }
182
+ });
183
+ export {
184
+ _sfc_main as _
185
+ };
@@ -1,5 +1,5 @@
1
1
  import { defineComponent, computed, openBlock, createBlock, resolveDynamicComponent, normalizeClass, withCtx, createElementVNode } from "vue";
2
- import { _ as _sfc_main$1 } from "./LpFormField-CesaPWPO.js";
2
+ import { _ as _sfc_main$1 } from "./LpFormField-DEaakcHe.js";
3
3
  const _hoisted_1 = ["value", "placeholder", "rows", "disabled", "required"];
4
4
  const _sfc_main = /* @__PURE__ */ defineComponent({
5
5
  __name: "LpTextarea",
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAddressInput-BTqnUXZG.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAddressInput-BoTkszLk.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -4,6 +4,10 @@ type __VLS_Props = {
4
4
  /** Flat items, or sections for grouped nav. Forwarded to LpSidebar. */
5
5
  items?: SidebarItem[];
6
6
  sections?: SidebarSection[];
7
+ /** Folded nav groups (v-model:collapsed). Forwarded to LpSidebar. */
8
+ collapsed?: string[];
9
+ /** Fold long navs automatically; 0 disables. Forwarded to LpSidebar. */
10
+ autoCollapseAfter?: number;
7
11
  /** Active item id (v-model) when not using a custom `isActive`. */
8
12
  modelValue?: string;
9
13
  /**
@@ -35,28 +39,28 @@ type __VLS_Props = {
35
39
  /** Loading skeleton for the nav. */
36
40
  loading?: boolean;
37
41
  };
38
- declare var __VLS_12: {}, __VLS_15: {}, __VLS_18: {}, __VLS_21: {
42
+ declare var __VLS_13: {}, __VLS_16: {}, __VLS_19: {}, __VLS_22: {
39
43
  item: SidebarItem;
40
44
  active: boolean;
41
- }, __VLS_42: {}, __VLS_50: {}, __VLS_52: {}, __VLS_60: {}, __VLS_62: {};
45
+ }, __VLS_43: {}, __VLS_51: {}, __VLS_53: {}, __VLS_61: {}, __VLS_63: {};
42
46
  type __VLS_Slots = {} & {
43
- logo?: (props: typeof __VLS_12) => any;
47
+ logo?: (props: typeof __VLS_13) => any;
44
48
  } & {
45
- 'sidebar-actions'?: (props: typeof __VLS_15) => any;
49
+ 'sidebar-actions'?: (props: typeof __VLS_16) => any;
46
50
  } & {
47
- 'sidebar-footer'?: (props: typeof __VLS_18) => any;
51
+ 'sidebar-footer'?: (props: typeof __VLS_19) => any;
48
52
  } & {
49
- 'sidebar-item'?: (props: typeof __VLS_21) => any;
53
+ 'sidebar-item'?: (props: typeof __VLS_22) => any;
50
54
  } & {
51
- 'header-title'?: (props: typeof __VLS_42) => any;
55
+ 'header-title'?: (props: typeof __VLS_43) => any;
52
56
  } & {
53
- 'header-actions'?: (props: typeof __VLS_50) => any;
57
+ 'header-actions'?: (props: typeof __VLS_51) => any;
54
58
  } & {
55
- default?: (props: typeof __VLS_52) => any;
59
+ default?: (props: typeof __VLS_53) => any;
56
60
  } & {
57
- default?: (props: typeof __VLS_60) => any;
61
+ default?: (props: typeof __VLS_61) => any;
58
62
  } & {
59
- overlays?: (props: typeof __VLS_62) => any;
63
+ overlays?: (props: typeof __VLS_63) => any;
60
64
  };
61
65
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
62
66
  openDrawer: () => void;
@@ -64,10 +68,12 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
64
68
  select: (item: SidebarItem) => any;
65
69
  "update:modelValue": (id: string) => any;
66
70
  "update:open": (value: boolean) => any;
71
+ "update:collapsed": (keys: string[]) => any;
67
72
  }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
68
73
  onSelect?: ((item: SidebarItem) => any) | undefined;
69
74
  "onUpdate:modelValue"?: ((id: string) => any) | undefined;
70
75
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
76
+ "onUpdate:collapsed"?: ((keys: string[]) => any) | undefined;
71
77
  }>, {
72
78
  contentClass: string;
73
79
  mobileBreakpoint: "sm" | "md" | "lg" | "xl";
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAppShell-B5k0J3Cf.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAppShell-CGX0DlIW.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpCard-gu11ZmSt.js";
1
+ import { _ as _sfc_main } from "../chunks/LpCard-DSefTGEH.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpFormField-CesaPWPO.js";
1
+ import { _ as _sfc_main } from "../chunks/LpFormField-DEaakcHe.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpInput-jwqXlAy0.js";
1
+ import { _ as _sfc_main } from "../chunks/LpInput-BXr40nqX.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpPasswordInput-Bmo6q9Kd.js";
1
+ import { _ as _sfc_main } from "../chunks/LpPasswordInput-Bdv6o8ae.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpSelect-Cw8-gL5F.js";
1
+ import { _ as _sfc_main } from "../chunks/LpSelect-ANIVtrpM.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -35,45 +35,67 @@ type __VLS_Props = {
35
35
  * flush, header-less look.
36
36
  */
37
37
  divider?: boolean;
38
+ /**
39
+ * Which collapsible groups are folded away (v-model:collapsed). Leave it
40
+ * unbound to let the sidebar fold long navs on its own — see
41
+ * `autoCollapseAfter`.
42
+ */
43
+ collapsed?: string[];
44
+ /**
45
+ * Fold collapsible groups automatically once the nav has more than this
46
+ * many rows, counting headings and items alike.
47
+ *
48
+ * The reason is the reader, not the pixels: a short nav is taken in at a
49
+ * glance, a long one has to be searched, and searching a list you did not
50
+ * choose to have is the part that grates. Past the threshold the groups
51
+ * that are not today's work fold themselves, and the one holding the
52
+ * current page always stays open.
53
+ *
54
+ * 0 turns it off — the app then owns the state through `collapsed`.
55
+ */
56
+ autoCollapseAfter?: number;
38
57
  };
39
- declare var __VLS_1: {}, __VLS_12: {
58
+ declare var __VLS_1: {}, __VLS_13: {
40
59
  item: SidebarItem;
41
60
  active: boolean;
42
- }, __VLS_14: {}, __VLS_16: {}, __VLS_26: {}, __VLS_37: {
61
+ }, __VLS_15: {}, __VLS_17: {}, __VLS_27: {}, __VLS_39: {
43
62
  item: SidebarItem;
44
63
  active: boolean;
45
- }, __VLS_39: {}, __VLS_41: {};
64
+ }, __VLS_41: {}, __VLS_43: {};
46
65
  type __VLS_Slots = {} & {
47
66
  header?: (props: typeof __VLS_1) => any;
48
67
  } & {
49
- item?: (props: typeof __VLS_12) => any;
68
+ item?: (props: typeof __VLS_13) => any;
50
69
  } & {
51
- actions?: (props: typeof __VLS_14) => any;
70
+ actions?: (props: typeof __VLS_15) => any;
52
71
  } & {
53
- footer?: (props: typeof __VLS_16) => any;
72
+ footer?: (props: typeof __VLS_17) => any;
54
73
  } & {
55
- header?: (props: typeof __VLS_26) => any;
74
+ header?: (props: typeof __VLS_27) => any;
56
75
  } & {
57
- item?: (props: typeof __VLS_37) => any;
76
+ item?: (props: typeof __VLS_39) => any;
58
77
  } & {
59
- actions?: (props: typeof __VLS_39) => any;
78
+ actions?: (props: typeof __VLS_41) => any;
60
79
  } & {
61
- footer?: (props: typeof __VLS_41) => any;
80
+ footer?: (props: typeof __VLS_43) => any;
62
81
  };
63
82
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
64
83
  select: (item: SidebarItem) => any;
65
84
  "update:modelValue": (id: string) => any;
66
85
  "update:open": (value: boolean) => any;
86
+ "update:collapsed": (keys: string[]) => any;
67
87
  }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
68
88
  onSelect?: ((item: SidebarItem) => any) | undefined;
69
89
  "onUpdate:modelValue"?: ((id: string) => any) | undefined;
70
90
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
91
+ "onUpdate:collapsed"?: ((keys: string[]) => any) | undefined;
71
92
  }>, {
72
93
  skeletonRows: number;
73
94
  skeletonHeader: boolean;
74
95
  responsive: boolean;
75
96
  mobileBreakpoint: "sm" | "md" | "lg" | "xl";
76
97
  divider: boolean;
98
+ autoCollapseAfter: number;
77
99
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
78
100
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
79
101
  declare const _default: typeof __VLS_export;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpSidebar-7Vpy2IJc.js";
1
+ import { _ as _sfc_main } from "../chunks/LpSidebar-CWehDCxN.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };