@leavepulse/ui 0.19.1 → 0.19.2

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.
@@ -6,7 +6,7 @@ import { _ as _sfc_main$3 } from "./LpButton-5VXXCjwF.js";
6
6
  import { _ as _sfc_main$1 } from "./LpFormField-Bn-ZwC6z.js";
7
7
  import { _ as _sfc_main$4 } from "./LpIcon-CCnX5_2j.js";
8
8
  import { _ as _sfc_main$5 } from "./LpInput-BauZRyzm.js";
9
- import { _ as _sfc_main$7 } from "./LpModal-vlrgcEY_.js";
9
+ import { _ as _sfc_main$7 } from "./LpModal-g2dGpF7l.js";
10
10
  import { _ as _sfc_main$6 } from "./LpSelect-D5mU4cZO.js";
11
11
  const _hoisted_1 = { class: "flex flex-col gap-3" };
12
12
  const _hoisted_2 = { class: "flex items-stretch gap-2" };
@@ -1,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-vlrgcEY_.js";
3
+ import { _ as _sfc_main$1 } from "./LpModal-g2dGpF7l.js";
4
4
  const _sfc_main = /* @__PURE__ */ defineComponent({
5
5
  __name: "LpConfirmDialog",
6
6
  props: {
@@ -60,12 +60,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
60
60
  const retune = (el) => {
61
61
  const from = el.offsetHeight;
62
62
  el.style.height = "";
63
+ el.style.maxHeight = "none";
63
64
  const to = el.offsetHeight;
64
- if (to === 0) return;
65
- if (to === from) {
66
- el.style.height = `${to}px`;
67
- return;
68
- }
65
+ el.style.maxHeight = "";
66
+ if (to === 0 || to === from) return;
69
67
  el.style.height = `${from}px`;
70
68
  void el.offsetHeight;
71
69
  el.style.height = `${to}px`;
@@ -73,6 +71,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
73
71
  clearTimeout(settleTimer);
74
72
  settleTimer = setTimeout(() => {
75
73
  resizing.value = false;
74
+ el.style.height = "";
76
75
  }, TWEEN_MS);
77
76
  };
78
77
  watch(
@@ -91,6 +90,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
91
90
  el.style.height = `${el.offsetHeight}px`;
92
91
  raf = requestAnimationFrame(() => {
93
92
  tweening.value = true;
93
+ el.style.height = "";
94
94
  });
95
95
  const watchChildren = () => {
96
96
  if (!ro) return;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAddressInput-N8O-LtCS.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAddressInput-CCtskgfZ.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpConfirmDialog-B-amVJsM.js";
1
+ import { _ as _sfc_main } from "../chunks/LpConfirmDialog-Z9hsfm2D.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpModal-vlrgcEY_.js";
1
+ import { _ as _sfc_main } from "../chunks/LpModal-g2dGpF7l.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -62,10 +62,11 @@ function fileIcon(node, expanded = false) {
62
62
  const ext = dot > 0 ? lower.slice(dot + 1) : "";
63
63
  return EXT_ICONS[ext] ?? "lucide:file";
64
64
  }
65
+ const NAME_COLLATOR = new Intl.Collator(void 0, { numeric: true, sensitivity: "base" });
65
66
  function sortNodes(nodes) {
66
67
  return [...nodes].sort((a, b) => {
67
68
  if (a.kind !== b.kind) return a.kind === "dir" ? -1 : 1;
68
- return a.name.localeCompare(b.name, void 0, { numeric: true, sensitivity: "base" });
69
+ return NAME_COLLATOR.compare(a.name, b.name);
69
70
  });
70
71
  }
71
72
  function formatSize(bytes) {
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { _ } from "./chunks/LayoutCanvas-Dd20boUG.js";
2
- import { _ as _2 } from "./chunks/LpAddressInput-N8O-LtCS.js";
2
+ import { _ as _2 } from "./chunks/LpAddressInput-CCtskgfZ.js";
3
3
  import { _ as _3 } from "./chunks/LpMapPicker-DFKrd1Ne.js";
4
4
  import { OSM_TILES, createNominatimProvider, emptyAddress, formatAddress, project, tileUrl, unproject } from "./components/address.js";
5
5
  import { _ as _4 } from "./chunks/LpAlert-BAYHDSS1.js";
@@ -14,7 +14,7 @@ import { _ as _12 } from "./chunks/LpCard-BmrTvWOe.js";
14
14
  import { _ as _13 } from "./chunks/LpCheckbox-BO0zuuPh.js";
15
15
  import { _ as _14 } from "./chunks/LpCodeBlock-CSiOSPs8.js";
16
16
  import { default as default2 } from "./components/LpCommandPalette.vue.js";
17
- import { _ as _15 } from "./chunks/LpConfirmDialog-B-amVJsM.js";
17
+ import { _ as _15 } from "./chunks/LpConfirmDialog-Z9hsfm2D.js";
18
18
  import { _ as _16 } from "./chunks/LpContextMenu-D0mzXqA7.js";
19
19
  import { _ as _17 } from "./chunks/LpDatePicker-dY2q4dr4.js";
20
20
  import { _ as _18 } from "./chunks/LpDisclosure-DP6yfgfM.js";
@@ -32,7 +32,7 @@ import { _ as _28 } from "./chunks/LpLightbox-CzhFe9wZ.js";
32
32
  import { fileNameOf } from "./components/lightbox.js";
33
33
  import { _ as _29 } from "./chunks/LpLink-DHwOEp4e.js";
34
34
  import { _ as _30 } from "./chunks/LpLogViewer-tmKPNTuU.js";
35
- import { _ as _31 } from "./chunks/LpModal-vlrgcEY_.js";
35
+ import { _ as _31 } from "./chunks/LpModal-g2dGpF7l.js";
36
36
  import { _ as _32 } from "./chunks/LpNotificationBell-DHze8wYN.js";
37
37
  import { _ as _33 } from "./chunks/LpNumberField-C5ar-OwE.js";
38
38
  import { _ as _34 } from "./chunks/LpOtpInput-DqaT0Z75.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leavepulse/ui",
3
- "version": "0.19.1",
3
+ "version": "0.19.2",
4
4
  "type": "module",
5
5
  "description": "LeavePulse token-driven Vue component kit.",
6
6
  "repository": {
@@ -108,12 +108,16 @@ let settleTimer: ReturnType<typeof setTimeout> | undefined
108
108
  const retune = (el: HTMLElement) => {
109
109
  const from = el.offsetHeight
110
110
  el.style.height = ""
111
+ // `max-h` comes from a class, so the panel already reports the clipped figure
112
+ // once the cap bites. Pinning that would leave a short panel sitting over
113
+ // content it can no longer grow to fit, so the natural height is measured with
114
+ // the cap lifted and the clamp is left to CSS afterwards.
115
+ el.style.maxHeight = "none"
111
116
  const to = el.offsetHeight
112
- if (to === 0) return
113
- if (to === from) {
114
- el.style.height = `${to}px`
115
- return
116
- }
117
+ el.style.maxHeight = ""
118
+ // Nothing moved, so there is nothing to ease — and leaving the height unset
119
+ // keeps the panel free to size itself.
120
+ if (to === 0 || to === from) return
117
121
  el.style.height = `${from}px`
118
122
  void el.offsetHeight
119
123
  el.style.height = `${to}px`
@@ -125,6 +129,10 @@ const retune = (el: HTMLElement) => {
125
129
  clearTimeout(settleTimer)
126
130
  settleTimer = setTimeout(() => {
127
131
  resizing.value = false
132
+ // Released once the panel has arrived. A height left pinned in pixels stops
133
+ // being a starting point and becomes a cap: content that grows afterwards
134
+ // is clipped, and `max-h` can no longer size the panel itself.
135
+ el.style.height = ""
128
136
  }, TWEEN_MS)
129
137
  }
130
138
 
@@ -147,9 +155,12 @@ watch(
147
155
 
148
156
  el.style.height = `${el.offsetHeight}px`
149
157
  // The opening panel must not animate its height in from the pre-content box,
150
- // so the transition only arms once that first pin has painted.
158
+ // so the transition only arms once that first pin has painted. The pin is
159
+ // dropped in the same frame: it exists to give the first `retune` something
160
+ // to start from, and holding it would cap the panel at its opening size.
151
161
  raf = requestAnimationFrame(() => {
152
162
  tweening.value = true
163
+ el.style.height = ""
153
164
  })
154
165
 
155
166
  // Two triggers, since either can move the height alone: the resize observer
@@ -104,11 +104,18 @@ export function fileIcon(node: FileNode, expanded = false): string {
104
104
  return EXT_ICONS[ext] ?? "lucide:file"
105
105
  }
106
106
 
107
+ /*
108
+ * Built once. `String.localeCompare` with options constructs a collator on every
109
+ * call, which on a few thousand nodes costs tens of milliseconds — enough to
110
+ * drop frames while a dialog is animating open.
111
+ */
112
+ const NAME_COLLATOR = new Intl.Collator(undefined, { numeric: true, sensitivity: "base" })
113
+
107
114
  /** Directories first, then case-insensitive by name — the file-manager order. */
108
115
  export function sortNodes(nodes: FileNode[]): FileNode[] {
109
116
  return [...nodes].sort((a, b) => {
110
117
  if (a.kind !== b.kind) return a.kind === "dir" ? -1 : 1
111
- return a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: "base" })
118
+ return NAME_COLLATOR.compare(a.name, b.name)
112
119
  })
113
120
  }
114
121