@leavepulse/ui 0.22.21 → 0.23.0

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 (64) hide show
  1. package/dist/chunks/{LpAddressInput-CxKwIG6T.js → LpAddressInput-BTqnUXZG.js} +3 -3
  2. package/dist/chunks/{LpAppShell-D8CAP9oF.js → LpAppShell-CaQYQKZV.js} +25 -14
  3. package/dist/chunks/{LpAvatar-B1Ez0ZAx.js → LpAvatar-D-jHoHR7.js} +15 -5
  4. package/dist/chunks/{LpConfirmDialog-CmgeAdCh.js → LpConfirmDialog-CObRah9c.js} +11 -6
  5. package/dist/chunks/{LpFileTree-Cw50eG_y.js → LpFileTree-CN0IOIY7.js} +1 -1
  6. package/dist/chunks/{LpFileTreeNode-DFg4PhOK.js → LpFileTreeNode-D7WgUPcJ.js} +23 -21
  7. package/dist/chunks/{LpFormField-Bn-ZwC6z.js → LpFormField-CesaPWPO.js} +12 -6
  8. package/dist/chunks/{LpInput-BkomKdqQ.js → LpInput-jwqXlAy0.js} +6 -3
  9. package/dist/chunks/{LpLink-DHwOEp4e.js → LpLink-DU9kkKGW.js} +25 -10
  10. package/dist/chunks/{LpModal-CNNSf5pv.js → LpModal-D_o-56To.js} +13 -76
  11. package/dist/chunks/{LpNotificationBell-DWDEkmdA.js → LpNotificationBell-a08cl0yY.js} +67 -61
  12. package/dist/chunks/{LpPasswordInput-DgUC2Ur7.js → LpPasswordInput-Bmo6q9Kd.js} +11 -3
  13. package/dist/chunks/LpShift-DXNsauQZ.js +40 -0
  14. package/dist/chunks/{LpTextarea-CRAkhemZ.js → LpTextarea-1ENb3ZAO.js} +7 -4
  15. package/dist/chunks/{LpThemeSwitcher-B_kj0T2b.js → LpThemeSwitcher-BgpJgrnP.js} +27 -0
  16. package/dist/component-names.d.ts +1 -1
  17. package/dist/components/LpAddressInput.vue.js +1 -1
  18. package/dist/components/LpAppShell.vue.d.ts +6 -6
  19. package/dist/components/LpAppShell.vue.js +1 -1
  20. package/dist/components/LpAvatar.vue.d.ts +10 -0
  21. package/dist/components/LpAvatar.vue.js +1 -1
  22. package/dist/components/LpConfirmDialog.vue.d.ts +8 -0
  23. package/dist/components/LpConfirmDialog.vue.js +1 -1
  24. package/dist/components/LpFileTree.vue.js +1 -1
  25. package/dist/components/LpFileTreeNode.vue.js +1 -1
  26. package/dist/components/LpFormField.vue.js +1 -1
  27. package/dist/components/LpInput.vue.d.ts +12 -0
  28. package/dist/components/LpInput.vue.js +1 -1
  29. package/dist/components/LpLink.vue.d.ts +20 -2
  30. package/dist/components/LpLink.vue.js +1 -1
  31. package/dist/components/LpModal.vue.js +1 -1
  32. package/dist/components/LpNotificationBell.vue.js +1 -1
  33. package/dist/components/LpPasswordInput.vue.d.ts +8 -0
  34. package/dist/components/LpPasswordInput.vue.js +1 -1
  35. package/dist/components/LpShift.vue.d.ts +36 -0
  36. package/dist/components/LpShift.vue.js +4 -0
  37. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  38. package/dist/components/LpTextarea.vue.d.ts +5 -0
  39. package/dist/components/LpTextarea.vue.js +1 -1
  40. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  41. package/dist/composables/useShift.d.ts +35 -0
  42. package/dist/composables/useShift.js +112 -0
  43. package/dist/index.d.ts +3 -0
  44. package/dist/index.js +48 -44
  45. package/dist/theme/tokens.d.ts +3 -0
  46. package/package.json +1 -1
  47. package/src/component-names.ts +1 -0
  48. package/src/components/LpAppShell.vue +27 -7
  49. package/src/components/LpAvatar.vue +17 -5
  50. package/src/components/LpConfirmDialog.vue +21 -6
  51. package/src/components/LpFileTreeNode.vue +11 -2
  52. package/src/components/LpFormField.vue +19 -2
  53. package/src/components/LpInput.vue +8 -0
  54. package/src/components/LpLink.vue +40 -8
  55. package/src/components/LpModal.vue +20 -128
  56. package/src/components/LpNotificationBell.vue +48 -42
  57. package/src/components/LpPasswordInput.vue +16 -1
  58. package/src/components/LpShift.vue +90 -0
  59. package/src/components/LpTextarea.vue +7 -0
  60. package/src/composables/useShift.ts +236 -0
  61. package/src/index.ts +3 -0
  62. package/src/theme/presets.ts +24 -0
  63. package/src/theme/tokens.ts +6 -0
  64. package/src/tokens/tokens.css +3 -0
@@ -3,10 +3,10 @@ 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-Bn-ZwC6z.js";
6
+ import { _ as _sfc_main$1 } from "./LpFormField-CesaPWPO.js";
7
7
  import { _ as _sfc_main$4 } from "./LpIcon-CCnX5_2j.js";
8
- import { _ as _sfc_main$5 } from "./LpInput-BkomKdqQ.js";
9
- import { _ as _sfc_main$7 } from "./LpModal-CNNSf5pv.js";
8
+ import { _ as _sfc_main$5 } from "./LpInput-jwqXlAy0.js";
9
+ import { _ as _sfc_main$7 } from "./LpModal-D_o-56To.js";
10
10
  import { _ as _sfc_main$6 } from "./LpSelect-Cw8-gL5F.js";
11
11
  const _hoisted_1 = { class: "flex flex-col gap-3" };
12
12
  const _hoisted_2 = { class: "flex items-stretch gap-2" };
@@ -1,17 +1,14 @@
1
- import { defineComponent, computed, watch, openBlock, createElementBlock, createVNode, createSlots, withCtx, renderSlot, normalizeProps, guardReactiveProps, createElementVNode, normalizeClass, toDisplayString, createCommentVNode, createBlock } from "vue";
1
+ import { defineComponent, computed, watch, openBlock, createElementBlock, createVNode, createSlots, withCtx, renderSlot, normalizeProps, guardReactiveProps, createElementVNode, normalizeClass, toDisplayString, 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-D8xyKXcF.js";
4
+ import { _ as _sfc_main$5 } from "./LpScrollArea-D8xyKXcF.js";
5
+ import { _ as _sfc_main$4 } from "./LpShift-DXNsauQZ.js";
5
6
  import { _ as _sfc_main$1 } from "./LpSidebar-D3GGLSE7.js";
6
7
  const _hoisted_1 = { class: "flex h-dvh overflow-hidden bg-surface text-ink" };
7
8
  const _hoisted_2 = { class: "flex min-w-0 flex-1 flex-col" };
8
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
10
  const _hoisted_4 = { class: "truncate text-lg font-semibold" };
10
11
  const _hoisted_5 = {
11
- key: 0,
12
- class: "ml-auto flex items-center gap-2"
13
- };
14
- const _hoisted_6 = {
15
12
  key: 0,
16
13
  class: "min-h-0 flex-1 overflow-hidden"
17
14
  };
@@ -146,16 +143,30 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
146
143
  ]),
147
144
  _: 1
148
145
  }, 8, ["class"]),
149
- renderSlot(_ctx.$slots, "header-title", {}, () => [
150
- createElementVNode("h1", _hoisted_4, toDisplayString(pageTitle.value), 1)
151
- ]),
152
- _ctx.$slots["header-actions"] ? (openBlock(), createElementBlock("div", _hoisted_5, [
153
- renderSlot(_ctx.$slots, "header-actions")
154
- ])) : createCommentVNode("", true)
146
+ createVNode(_sfc_main$4, {
147
+ axis: "height",
148
+ class: "flex min-w-0 flex-1 items-center"
149
+ }, {
150
+ default: withCtx(() => [
151
+ renderSlot(_ctx.$slots, "header-title", {}, () => [
152
+ createElementVNode("h1", _hoisted_4, toDisplayString(pageTitle.value), 1)
153
+ ])
154
+ ]),
155
+ _: 3
156
+ }),
157
+ createVNode(_sfc_main$4, {
158
+ axis: "width",
159
+ class: "ml-auto flex shrink-0 items-center gap-2"
160
+ }, {
161
+ default: withCtx(() => [
162
+ renderSlot(_ctx.$slots, "header-actions")
163
+ ]),
164
+ _: 3
165
+ })
155
166
  ]),
156
- __props.fullBleed ? (openBlock(), createElementBlock("div", _hoisted_6, [
167
+ __props.fullBleed ? (openBlock(), createElementBlock("div", _hoisted_5, [
157
168
  renderSlot(_ctx.$slots, "default")
158
- ])) : (openBlock(), createBlock(_sfc_main$4, {
169
+ ])) : (openBlock(), createBlock(_sfc_main$5, {
159
170
  key: 1,
160
171
  class: "min-h-0 flex-1",
161
172
  "content-class": `px-4 py-6 md:px-6 ${__props.contentClass}`
@@ -11,19 +11,29 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
11
11
  alt: {},
12
12
  fallback: {},
13
13
  size: { default: "md" },
14
+ shape: { default: "circle" },
15
+ ring: { type: Boolean, default: false },
14
16
  menuItems: {}
15
17
  },
16
18
  setup(__props) {
17
19
  const avatar = tv({
18
- base: "inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-pill bg-surface-soft font-medium text-muted-strong",
20
+ base: "inline-flex shrink-0 select-none items-center justify-center overflow-hidden bg-surface-soft font-medium text-muted-strong",
19
21
  variants: {
20
22
  size: {
21
23
  sm: "size-7 text-xs",
22
24
  md: "size-9 text-sm",
23
25
  lg: "size-12 text-base"
24
- }
26
+ },
27
+ // People read as circles; things (servers, projects, orgs) read as
28
+ // rounded squares — the same distinction platform icons make.
29
+ shape: {
30
+ circle: "rounded-pill",
31
+ soft: "rounded-card",
32
+ square: "rounded-control"
33
+ },
34
+ ring: { true: "ring-2 ring-line", false: "" }
25
35
  },
26
- defaultVariants: { size: "md" }
36
+ defaultVariants: { size: "md", shape: "circle", ring: false }
27
37
  });
28
38
  const props = __props;
29
39
  const initials = computed(
@@ -40,7 +50,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
40
50
  }, {
41
51
  default: withCtx(() => [
42
52
  createVNode(unref(AvatarRoot), mergeProps({
43
- class: unref(avatar)({ size: __props.size })
53
+ class: unref(avatar)({ size: __props.size, shape: __props.shape, ring: __props.ring })
44
54
  }, _ctx.$attrs), {
45
55
  default: withCtx(() => [
46
56
  __props.src && mounted.value ? (openBlock(), createBlock(unref(AvatarImage), {
@@ -62,7 +72,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
62
72
  _: 1
63
73
  }, 8, ["items"])) : (openBlock(), createBlock(unref(AvatarRoot), mergeProps({
64
74
  key: 1,
65
- class: unref(avatar)({ size: __props.size })
75
+ class: unref(avatar)({ size: __props.size, shape: __props.shape, ring: __props.ring })
66
76
  }, _ctx.$attrs), {
67
77
  default: withCtx(() => [
68
78
  __props.src ? (openBlock(), createBlock(unref(AvatarImage), {
@@ -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-CNNSf5pv.js";
3
+ import { _ as _sfc_main$1 } from "./LpModal-D_o-56To.js";
4
4
  const _sfc_main = /* @__PURE__ */ defineComponent({
5
5
  __name: "LpConfirmDialog",
6
6
  props: {
@@ -9,14 +9,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
9
9
  description: {},
10
10
  confirmLabel: { default: "Confirm" },
11
11
  cancelLabel: { default: "Cancel" },
12
- danger: { type: Boolean }
12
+ danger: { type: Boolean },
13
+ loading: { type: Boolean },
14
+ loadingLabel: { default: "Working…" }
13
15
  },
14
16
  emits: ["update:open", "confirm", "cancel"],
15
17
  setup(__props, { emit: __emit }) {
18
+ const props = __props;
16
19
  const emit = __emit;
17
20
  function confirm() {
18
21
  emit("confirm");
19
- emit("update:open", false);
22
+ if (!props.loading) emit("update:open", false);
20
23
  }
21
24
  function cancel() {
22
25
  emit("cancel");
@@ -32,22 +35,24 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
32
35
  footer: withCtx(() => [
33
36
  createVNode(_sfc_main$2, {
34
37
  variant: "ghost",
38
+ disabled: __props.loading,
35
39
  onClick: cancel
36
40
  }, {
37
41
  default: withCtx(() => [
38
42
  createTextVNode(toDisplayString(__props.cancelLabel), 1)
39
43
  ]),
40
44
  _: 1
41
- }),
45
+ }, 8, ["disabled"]),
42
46
  createVNode(_sfc_main$2, {
43
47
  variant: __props.danger ? "danger" : "solid",
48
+ disabled: __props.loading,
44
49
  onClick: confirm
45
50
  }, {
46
51
  default: withCtx(() => [
47
- createTextVNode(toDisplayString(__props.confirmLabel), 1)
52
+ createTextVNode(toDisplayString(__props.loading ? __props.loadingLabel : __props.confirmLabel), 1)
48
53
  ]),
49
54
  _: 1
50
- }, 8, ["variant"])
55
+ }, 8, ["variant", "disabled"])
51
56
  ]),
52
57
  default: withCtx(() => [
53
58
  renderSlot(_ctx.$slots, "default")
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, ref, watch, computed, openBlock, createElementBlock, Fragment, renderList, normalizeStyle, createBlock, createVNode, withCtx, createElementVNode, renderSlot, mergeProps, normalizeProps, guardReactiveProps, createTextVNode, toDisplayString, createCommentVNode } from "vue";
2
2
  import { computeStats, formatSize, sortNodes, subtreeIds, ancestorIds } from "../components/fileTree.js";
3
3
  import { _ as _sfc_main$1 } from "./LpEmptyState-CrfyRJUG.js";
4
- import { _ as _sfc_main$3 } from "./LpFileTreeNode-DFg4PhOK.js";
4
+ import { _ as _sfc_main$3 } from "./LpFileTreeNode-D7WgUPcJ.js";
5
5
  import { _ as _sfc_main$2 } from "./LpScrollArea-D8xyKXcF.js";
6
6
  const _hoisted_1 = {
7
7
  key: 0,
@@ -5,25 +5,24 @@ import { _ as _sfc_main$1 } from "./LpContextMenu-D0mzXqA7.js";
5
5
  import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
6
6
  const _hoisted_1 = ["aria-level", "aria-selected", "aria-expanded", "aria-disabled"];
7
7
  const _hoisted_2 = ["data-node-id", "tabindex"];
8
- const _hoisted_3 = { class: "flex size-4 shrink-0 items-center justify-center" };
9
- const _hoisted_4 = { class: "min-w-0 flex-1 shrink-[2] truncate" };
10
- const _hoisted_5 = {
8
+ const _hoisted_3 = { class: "min-w-0 flex-1 shrink-[2] truncate" };
9
+ const _hoisted_4 = {
11
10
  key: 1,
12
11
  class: "shrink-0 rounded-pill bg-brand-soft px-1.5 py-0.5 text-[11px] font-medium tabular-nums text-brand"
13
12
  };
14
- const _hoisted_6 = {
13
+ const _hoisted_5 = {
15
14
  key: 2,
16
15
  class: "min-w-0 shrink truncate text-xs text-muted"
17
16
  };
18
- const _hoisted_7 = {
17
+ const _hoisted_6 = {
19
18
  key: 3,
20
19
  class: "shrink-0 text-xs tabular-nums text-muted/80"
21
20
  };
22
- const _hoisted_8 = {
21
+ const _hoisted_7 = {
23
22
  key: 4,
24
23
  class: "w-16 shrink-0 text-right text-xs tabular-nums text-muted"
25
24
  };
26
- const _hoisted_9 = {
25
+ const _hoisted_8 = {
27
26
  key: 0,
28
27
  role: "group",
29
28
  class: "flex min-w-0 flex-col overflow-hidden"
@@ -134,7 +133,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
134
133
  style: normalizeStyle({ paddingLeft: `${__props.depth * 14 + 6}px` }),
135
134
  onClick: withModifiers(onActivate, ["stop"])
136
135
  }, [
137
- createElementVNode("span", _hoisted_3, [
136
+ createElementVNode("span", {
137
+ class: normalizeClass(["flex size-4 shrink-0 items-center justify-center", canExpand.value ? "cursor-pointer rounded-sm hover:bg-line" : ""]),
138
+ onClick: _cache[0] || (_cache[0] = withModifiers(($event) => canExpand.value && !__props.node.disabled ? emit("toggle", __props.node) : void 0, ["stop"]))
139
+ }, [
138
140
  isLoading.value ? (openBlock(), createBlock(_sfc_main$2, {
139
141
  key: 0,
140
142
  name: "lucide:loader-circle",
@@ -146,7 +148,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
146
148
  size: 14,
147
149
  class: normalizeClass(["text-muted transition-transform duration-[var(--duration-fast)]", isOpen.value ? "rotate-90" : ""])
148
150
  }, null, 8, ["class"])) : createCommentVNode("", true)
149
- ]),
151
+ ], 2),
150
152
  __props.checkable ? (openBlock(), createBlock(_sfc_main$3, {
151
153
  key: 0,
152
154
  "model-value": checkState.value === "checked",
@@ -154,16 +156,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
154
156
  disabled: __props.node.disabled,
155
157
  class: "shrink-0",
156
158
  "aria-label": __props.node.name,
157
- onClick: _cache[0] || (_cache[0] = withModifiers(() => {
159
+ onClick: _cache[1] || (_cache[1] = withModifiers(() => {
158
160
  }, ["stop"])),
159
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => emit("check", __props.node, $event))
161
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => emit("check", __props.node, $event))
160
162
  }, null, 8, ["model-value", "indeterminate", "disabled", "aria-label"])) : createCommentVNode("", true),
161
163
  createVNode(_sfc_main$2, {
162
164
  name: unref(fileIcon)(__props.node, isOpen.value),
163
165
  size: __props.iconSize,
164
166
  class: normalizeClass(["shrink-0", __props.node.disabled ? "" : isDir.value ? "text-brand" : "text-muted"])
165
167
  }, null, 8, ["name", "size", "class"]),
166
- createElementVNode("span", _hoisted_4, [
168
+ createElementVNode("span", _hoisted_3, [
167
169
  renderSlot(_ctx.$slots, "row", {
168
170
  node: __props.node,
169
171
  depth: __props.depth,
@@ -173,10 +175,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
173
175
  createTextVNode(toDisplayString(__props.node.name), 1)
174
176
  ])
175
177
  ]),
176
- countLabel.value ? (openBlock(), createElementBlock("span", _hoisted_5, toDisplayString(countLabel.value), 1)) : createCommentVNode("", true),
177
- __props.node.meta ? (openBlock(), createElementBlock("span", _hoisted_6, toDisplayString(__props.node.meta), 1)) : createCommentVNode("", true),
178
- modifiedLabel.value ? (openBlock(), createElementBlock("span", _hoisted_7, toDisplayString(modifiedLabel.value), 1)) : createCommentVNode("", true),
179
- sizeLabel.value ? (openBlock(), createElementBlock("span", _hoisted_8, toDisplayString(sizeLabel.value), 1)) : createCommentVNode("", true)
178
+ countLabel.value ? (openBlock(), createElementBlock("span", _hoisted_4, toDisplayString(countLabel.value), 1)) : createCommentVNode("", true),
179
+ __props.node.meta ? (openBlock(), createElementBlock("span", _hoisted_5, toDisplayString(__props.node.meta), 1)) : createCommentVNode("", true),
180
+ modifiedLabel.value ? (openBlock(), createElementBlock("span", _hoisted_6, toDisplayString(modifiedLabel.value), 1)) : createCommentVNode("", true),
181
+ sizeLabel.value ? (openBlock(), createElementBlock("span", _hoisted_7, toDisplayString(sizeLabel.value), 1)) : createCommentVNode("", true)
180
182
  ], 14, _hoisted_2)
181
183
  ]),
182
184
  _: 3
@@ -187,7 +189,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
187
189
  onLeave: onBranchLeave
188
190
  }, {
189
191
  default: withCtx(() => [
190
- isOpen.value && hasChildren.value ? (openBlock(), createElementBlock("ul", _hoisted_9, [
192
+ isOpen.value && hasChildren.value ? (openBlock(), createElementBlock("ul", _hoisted_8, [
191
193
  (openBlock(true), createElementBlock(Fragment, null, renderList(children.value, (child, i) => {
192
194
  return openBlock(), createBlock(_component_LpFileTreeNode, {
193
195
  key: child.id,
@@ -206,10 +208,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
206
208
  stats: __props.stats,
207
209
  "show-size": __props.showSize,
208
210
  "show-modified": __props.showModified,
209
- onSelect: _cache[2] || (_cache[2] = ($event) => emit("select", $event)),
210
- onToggle: _cache[3] || (_cache[3] = ($event) => emit("toggle", $event)),
211
- onFocus: _cache[4] || (_cache[4] = ($event) => emit("focus", $event)),
212
- onCheck: _cache[5] || (_cache[5] = (n, v) => emit("check", n, v))
211
+ onSelect: _cache[3] || (_cache[3] = ($event) => emit("select", $event)),
212
+ onToggle: _cache[4] || (_cache[4] = ($event) => emit("toggle", $event)),
213
+ onFocus: _cache[5] || (_cache[5] = ($event) => emit("focus", $event)),
214
+ onCheck: _cache[6] || (_cache[6] = (n, v) => emit("check", n, v))
213
215
  }, {
214
216
  row: withCtx((slotProps) => [
215
217
  renderSlot(_ctx.$slots, "row", mergeProps({ ref_for: true }, slotProps))
@@ -1,17 +1,18 @@
1
- import { defineComponent, useId, openBlock, createElementBlock, createBlock, unref, withCtx, createTextVNode, toDisplayString, createCommentVNode, renderSlot } from "vue";
1
+ import { defineComponent, useId, openBlock, createElementBlock, createBlock, unref, withCtx, createTextVNode, toDisplayString, createCommentVNode, renderSlot, createVNode } from "vue";
2
2
  import { Label } from "reka-ui";
3
+ import { _ as _sfc_main$1 } from "./LpShift-DXNsauQZ.js";
3
4
  const _hoisted_1 = { class: "flex flex-col gap-1.5" };
4
5
  const _hoisted_2 = {
5
6
  key: 0,
6
7
  class: "text-danger"
7
8
  };
8
9
  const _hoisted_3 = {
9
- key: 1,
10
- class: "text-xs text-danger"
10
+ key: 0,
11
+ class: "pt-1.5 text-xs text-danger"
11
12
  };
12
13
  const _hoisted_4 = {
13
- key: 2,
14
- class: "text-xs text-muted"
14
+ key: 1,
15
+ class: "pt-1.5 text-xs text-muted"
15
16
  };
16
17
  const _sfc_main = /* @__PURE__ */ defineComponent({
17
18
  __name: "LpFormField",
@@ -37,7 +38,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
37
38
  _: 1
38
39
  }, 8, ["for"])) : createCommentVNode("", true),
39
40
  renderSlot(_ctx.$slots, "default", { id: unref(id) }),
40
- __props.error ? (openBlock(), createElementBlock("p", _hoisted_3, toDisplayString(__props.error), 1)) : __props.hint ? (openBlock(), createElementBlock("p", _hoisted_4, toDisplayString(__props.hint), 1)) : createCommentVNode("", true)
41
+ createVNode(_sfc_main$1, { axis: "height" }, {
42
+ default: withCtx(() => [
43
+ __props.error ? (openBlock(), createElementBlock("p", _hoisted_3, toDisplayString(__props.error), 1)) : __props.hint ? (openBlock(), createElementBlock("p", _hoisted_4, toDisplayString(__props.hint), 1)) : createCommentVNode("", true)
44
+ ]),
45
+ _: 1
46
+ })
41
47
  ]);
42
48
  };
43
49
  }
@@ -1,13 +1,13 @@
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-Bn-ZwC6z.js";
4
+ import { _ as _sfc_main$1 } from "./LpFormField-CesaPWPO.js";
5
5
  import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
6
6
  const _hoisted_1 = {
7
7
  key: 0,
8
8
  class: "flex shrink-0 items-center text-muted"
9
9
  };
10
- const _hoisted_2 = ["type", "value", "placeholder", "disabled", "aria-invalid"];
10
+ const _hoisted_2 = ["type", "value", "placeholder", "disabled", "required", "aria-invalid"];
11
11
  const __default__ = { inheritAttrs: false };
12
12
  const _sfc_main = /* @__PURE__ */ defineComponent({
13
13
  ...__default__,
@@ -23,6 +23,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
23
23
  hint: {},
24
24
  error: {},
25
25
  icon: {},
26
+ required: { type: Boolean },
26
27
  pattern: {},
27
28
  restrict: {}
28
29
  },
@@ -90,6 +91,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
90
91
  label: hasField.value ? __props.label : void 0,
91
92
  hint: hasField.value ? __props.hint : void 0,
92
93
  error: hasField.value ? __props.error : void 0,
94
+ required: hasField.value ? __props.required : void 0,
93
95
  class: normalizeClass(hasField.value ? rootClass.value : void 0),
94
96
  style: normalizeStyle(hasField.value ? rootStyle.value : void 0)
95
97
  }, {
@@ -116,6 +118,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
116
118
  value: __props.modelValue,
117
119
  placeholder: __props.placeholder,
118
120
  disabled: __props.disabled,
121
+ required: __props.required || void 0,
119
122
  "aria-invalid": isInvalidState.value || void 0,
120
123
  class: [
121
124
  "lp-autofill min-w-0 flex-1 self-stretch bg-transparent outline-none placeholder:text-muted",
@@ -132,7 +135,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
132
135
  ], 6)
133
136
  ]),
134
137
  _: 3
135
- }, 8, ["label", "hint", "error", "class", "style"]);
138
+ }, 8, ["label", "hint", "error", "required", "class", "style"]);
136
139
  };
137
140
  }
138
141
  });
@@ -1,5 +1,4 @@
1
- import { defineComponent, computed, openBlock, createElementBlock, normalizeClass, renderSlot } from "vue";
2
- const _hoisted_1 = ["href", "target", "rel"];
1
+ import { defineComponent, computed, openBlock, createBlock, resolveDynamicComponent, normalizeClass, withCtx, renderSlot } from "vue";
3
2
  const revealClass = "relative after:absolute after:inset-x-0 after:-bottom-0.5 after:h-px after:origin-left after:scale-x-0 after:bg-current after:transition-transform after:duration-[var(--duration-medium)] hover:after:scale-x-100 focus-visible:after:scale-x-100";
4
3
  const _sfc_main = /* @__PURE__ */ defineComponent({
5
4
  __name: "LpLink",
@@ -7,27 +6,43 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
7
6
  href: {},
8
7
  external: { type: Boolean },
9
8
  muted: { type: Boolean },
9
+ tone: {},
10
+ as: { default: "a" },
10
11
  variant: { default: "default" }
11
12
  },
12
13
  setup(__props) {
13
14
  const props = __props;
15
+ const isAnchor = computed(() => props.as === "a");
14
16
  const rel = computed(() => props.external ? "noopener noreferrer" : void 0);
15
17
  const target = computed(() => props.external ? "_blank" : void 0);
16
- const colorClass = computed(
17
- () => props.muted ? "text-muted hover:text-ink" : "text-brand hover:text-brand-hover"
18
- );
18
+ const colorClass = computed(() => {
19
+ const tone = props.tone ?? (props.muted ? "muted" : "brand");
20
+ switch (tone) {
21
+ case "ink":
22
+ return "text-ink";
23
+ case "muted":
24
+ return "text-muted-strong hover:text-ink";
25
+ case "soft":
26
+ return "text-muted hover:text-ink";
27
+ default:
28
+ return "text-brand hover:text-brand-hover";
29
+ }
30
+ });
19
31
  return (_ctx, _cache) => {
20
- return openBlock(), createElementBlock("a", {
21
- href: __props.href,
32
+ return openBlock(), createBlock(resolveDynamicComponent(__props.as), {
33
+ href: isAnchor.value ? __props.href : void 0,
22
34
  target: target.value,
23
35
  rel: rel.value,
24
36
  class: normalizeClass(["inline-flex items-center gap-1 underline-offset-2 outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring", [
25
37
  colorClass.value,
26
38
  __props.variant === "reveal" ? revealClass : "hover:underline"
27
39
  ]])
28
- }, [
29
- renderSlot(_ctx.$slots, "default")
30
- ], 10, _hoisted_1);
40
+ }, {
41
+ default: withCtx(() => [
42
+ renderSlot(_ctx.$slots, "default")
43
+ ]),
44
+ _: 3
45
+ }, 8, ["href", "target", "rel", "class"]);
31
46
  };
32
47
  }
33
48
  });
@@ -1,5 +1,6 @@
1
- import { defineComponent, computed, useSlots, ref, watch, onBeforeUnmount, openBlock, createBlock, unref, withCtx, createVNode, createElementVNode, mergeProps, createElementBlock, renderSlot, createTextVNode, toDisplayString, createCommentVNode, normalizeClass } from "vue";
1
+ import { defineComponent, computed, useSlots, ref, watch, openBlock, createBlock, unref, withCtx, createVNode, createElementVNode, mergeProps, createElementBlock, renderSlot, createTextVNode, toDisplayString, createCommentVNode, normalizeClass } from "vue";
2
2
  import { DialogRoot, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose } from "reka-ui";
3
+ import { useShift } from "../composables/useShift.js";
3
4
  import { CLOSE_ICON } from "../components/dropdown.js";
4
5
  import { _ as _sfc_main$1 } from "./LpIcon-CCnX5_2j.js";
5
6
  import { _ as _sfc_main$2 } from "./LpScrollArea-D8xyKXcF.js";
@@ -13,7 +14,6 @@ const _hoisted_4 = {
13
14
  key: 3,
14
15
  class: "flex shrink-0 justify-end gap-2 p-5 pt-4"
15
16
  };
16
- const TWEEN_MS = 160;
17
17
  const _sfc_main = /* @__PURE__ */ defineComponent({
18
18
  __name: "LpModal",
19
19
  props: {
@@ -82,82 +82,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
82
82
  return;
83
83
  }
84
84
  }
85
- const tweening = ref(false);
86
- const resizing = ref(false);
87
- let ro;
88
- let mo;
89
- let raf = 0;
90
- let settleTimer;
91
- let lastHeight = 0;
92
- let inFlight = false;
93
- const retune = (el) => {
94
- if (inFlight) return;
95
- const from = lastHeight;
96
- el.style.height = "";
97
- el.style.maxHeight = "none";
98
- const to = el.offsetHeight;
99
- el.style.maxHeight = "";
100
- lastHeight = to;
101
- if (to === 0 || from === 0 || to === from) return;
102
- el.style.height = `${from}px`;
103
- void el.offsetHeight;
104
- el.style.height = `${to}px`;
105
- inFlight = true;
106
- resizing.value = true;
107
- clearTimeout(settleTimer);
108
- settleTimer = setTimeout(() => {
109
- inFlight = false;
110
- resizing.value = false;
111
- el.style.height = "";
112
- lastHeight = el.offsetHeight;
113
- }, TWEEN_MS);
114
- };
85
+ const {
86
+ el: sizedEl,
87
+ tweening,
88
+ resizing
89
+ } = useShift({ axis: "height", enabled: () => props.open });
115
90
  watch(
116
- () => props.open,
117
- (isOpen) => {
118
- ro?.disconnect();
119
- mo?.disconnect();
120
- ro = void 0;
121
- mo = void 0;
122
- cancelAnimationFrame(raf);
123
- clearTimeout(settleTimer);
124
- tweening.value = false;
125
- resizing.value = false;
126
- lastHeight = 0;
127
- inFlight = false;
128
- const el = panelRef.value?.$el;
129
- if (!isOpen || !(el instanceof HTMLElement)) return;
130
- lastHeight = el.offsetHeight;
131
- el.style.height = `${el.offsetHeight}px`;
132
- raf = requestAnimationFrame(() => {
133
- tweening.value = true;
134
- el.style.height = "";
135
- });
136
- const watchChildren = () => {
137
- if (!ro) return;
138
- ro.disconnect();
139
- for (const child of Array.from(el.children)) ro.observe(child);
140
- };
141
- if (typeof ResizeObserver !== "undefined") {
142
- ro = new ResizeObserver(() => retune(el));
143
- watchChildren();
144
- }
145
- if (typeof MutationObserver !== "undefined") {
146
- mo = new MutationObserver(() => {
147
- watchChildren();
148
- retune(el);
149
- });
150
- mo.observe(el, { childList: true, subtree: true, characterData: true });
151
- }
91
+ () => props.open ? panelRef.value : null,
92
+ (panel) => {
93
+ const el = panel?.$el;
94
+ sizedEl.value = el instanceof HTMLElement ? el : null;
152
95
  },
153
96
  { flush: "post" }
154
97
  );
155
- onBeforeUnmount(() => {
156
- ro?.disconnect();
157
- mo?.disconnect();
158
- cancelAnimationFrame(raf);
159
- clearTimeout(settleTimer);
160
- });
161
98
  return (_ctx, _cache) => {
162
99
  return openBlock(), createBlock(unref(DialogRoot), {
163
100
  open: __props.open,
@@ -171,7 +108,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
171
108
  createVNode(unref(DialogContent), mergeProps({
172
109
  ref_key: "panelRef",
173
110
  ref: panelRef,
174
- class: ["pointer-events-auto flex max-h-[min(90vh,calc(100dvh-2rem))] min-h-0 flex-col overflow-hidden rounded-card border border-line bg-surface-raised shadow-panel outline-none data-[state=open]:animate-[rise-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[rise-out_120ms_cubic-bezier(0.4,0,1,1)]", [widthClass.value, tweening.value ? "transition-[height] duration-fast ease-[var(--ease-emphasized)] motion-reduce:transition-none" : ""]],
111
+ class: ["pointer-events-auto flex max-h-[min(90vh,calc(100dvh-2rem))] min-h-0 flex-col overflow-hidden rounded-card border border-line bg-surface-raised shadow-panel outline-none data-[state=open]:animate-[rise-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[rise-out_120ms_cubic-bezier(0.4,0,1,1)]", [widthClass.value, unref(tweening) ? "transition-[height] duration-fast ease-[var(--ease-emphasized)] motion-reduce:transition-none" : ""]],
175
112
  style: __props.width ? { width: __props.width } : void 0
176
113
  }, describedByAttrs.value, { onOpenAutoFocus }), {
177
114
  default: withCtx(() => [
@@ -217,7 +154,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
217
154
  renderSlot(_ctx.$slots, "default")
218
155
  ], 2)) : (openBlock(), createBlock(_sfc_main$2, {
219
156
  key: 2,
220
- class: normalizeClass(["min-h-0 flex-1 text-sm text-ink/90", resizing.value ? "[&_[data-scrollbarimpl]]:invisible" : ""]),
157
+ class: normalizeClass(["min-h-0 flex-1 text-sm text-ink/90", unref(resizing) ? "[&_[data-scrollbarimpl]]:invisible" : ""]),
221
158
  "content-class": bodyPad.value
222
159
  }, {
223
160
  default: withCtx(() => [