@surdeddd/bottom-sheet 0.23.4 → 0.24.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 (80) hide show
  1. package/README.md +513 -527
  2. package/README.ru.md +533 -545
  3. package/dist/{BottomSheetCore-C5tJYVMY.d.cts → BottomSheetCore-B_r4KCQL.d.cts} +48 -13
  4. package/dist/{BottomSheetCore-DxSrC4QC.d.ts → BottomSheetCore-B_r4KCQL.d.ts} +48 -13
  5. package/dist/{BottomSheetEngine-B3F9qukX.d.cts → BottomSheetEngine-0F7mjyvF.d.cts} +1 -1
  6. package/dist/{BottomSheetEngine-BchzgqGG.d.ts → BottomSheetEngine-CJV_DDrM.d.ts} +1 -1
  7. package/dist/core.cjs +810 -436
  8. package/dist/core.d.cts +2 -3
  9. package/dist/core.d.ts +2 -3
  10. package/dist/core.js +810 -436
  11. package/dist/debug.d.cts +0 -1
  12. package/dist/debug.d.ts +0 -1
  13. package/dist/{default-features-DwVTzDwP.d.ts → default-features-4Xwv6aVt.d.ts} +4 -2
  14. package/dist/{default-features-BGiCSmV1.d.cts → default-features-DX2NOxP6.d.cts} +4 -2
  15. package/dist/element.cjs +1421 -697
  16. package/dist/element.d.cts +11 -3
  17. package/dist/element.d.ts +11 -3
  18. package/dist/element.iife.global.js +2 -2
  19. package/dist/element.js +1421 -697
  20. package/dist/features.cjs +334 -190
  21. package/dist/features.d.cts +3 -4
  22. package/dist/features.d.ts +3 -4
  23. package/dist/features.js +334 -191
  24. package/dist/{index-C7TSQkVK.d.cts → index-2shlxhcG.d.cts} +1 -1
  25. package/dist/{index-CdM1tke5.d.ts → index-CNCRQnpc.d.ts} +1 -1
  26. package/dist/index.cjs +1129 -631
  27. package/dist/index.d.cts +11 -6
  28. package/dist/index.d.ts +11 -6
  29. package/dist/index.js +1129 -632
  30. package/dist/integrations/formik.cjs +21 -10
  31. package/dist/integrations/formik.d.cts +0 -1
  32. package/dist/integrations/formik.d.ts +0 -1
  33. package/dist/integrations/formik.js +22 -11
  34. package/dist/integrations/react-hook-form.cjs +21 -12
  35. package/dist/integrations/react-hook-form.d.cts +0 -1
  36. package/dist/integrations/react-hook-form.d.ts +0 -1
  37. package/dist/integrations/react-hook-form.js +21 -12
  38. package/dist/option-keys-DItuAjUw.d.cts +6 -0
  39. package/dist/option-keys-a5DYNwwO.d.ts +6 -0
  40. package/dist/overlay.cjs +386 -189
  41. package/dist/overlay.d.cts +1 -3
  42. package/dist/overlay.d.ts +1 -3
  43. package/dist/overlay.js +386 -189
  44. package/dist/preact.d.cts +3 -4
  45. package/dist/preact.d.ts +3 -4
  46. package/dist/qwik-lib/index.qwik.cjs +1306 -671
  47. package/dist/qwik-lib/index.qwik.mjs +1306 -671
  48. package/dist/qwik.cjs +1326 -701
  49. package/dist/qwik.d.cts +12 -30
  50. package/dist/qwik.d.ts +12 -30
  51. package/dist/qwik.js +1326 -701
  52. package/dist/react.cjs +1373 -750
  53. package/dist/react.d.cts +26 -12
  54. package/dist/react.d.ts +26 -12
  55. package/dist/react.js +1375 -752
  56. package/dist/solid.cjs +1332 -727
  57. package/dist/solid.d.cts +13 -438
  58. package/dist/solid.d.ts +13 -438
  59. package/dist/solid.js +1334 -729
  60. package/dist/solid.source.jsx +1374 -751
  61. package/dist/styles.css +20 -6
  62. package/dist/svelte-core.cjs +1209 -676
  63. package/dist/svelte-core.js +1207 -677
  64. package/dist/svelte-src/BottomSheet.svelte +101 -58
  65. package/dist/svelte.cjs +1323 -705
  66. package/dist/svelte.d.cts +45 -25
  67. package/dist/svelte.d.ts +45 -25
  68. package/dist/svelte.js +1323 -705
  69. package/dist/vue.cjs +1354 -773
  70. package/dist/vue.d.cts +20 -3
  71. package/dist/vue.d.ts +20 -3
  72. package/dist/vue.js +1354 -773
  73. package/dist/webgl.cjs +38 -7
  74. package/dist/webgl.d.cts +0 -1
  75. package/dist/webgl.d.ts +0 -1
  76. package/dist/webgl.js +38 -7
  77. package/llms.txt +330 -0
  78. package/package.json +41 -19
  79. package/dist/transform-jVfAikE9.d.cts +0 -3
  80. package/dist/transform-jVfAikE9.d.ts +0 -3
package/dist/features.cjs CHANGED
@@ -4,198 +4,329 @@ var __defProp = Object.defineProperty;
4
4
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
5
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
6
6
 
7
+ // src/core/primitives/shared.ts
8
+ var STORE_KEY = /* @__PURE__ */ Symbol.for("@surdeddd/bottom-sheet/shared/1");
9
+ function shared(name, init) {
10
+ const host = globalThis;
11
+ const store = host[STORE_KEY] ?? (host[STORE_KEY] = {});
12
+ if (!(name in store)) store[name] = init();
13
+ return store[name];
14
+ }
15
+
7
16
  // src/core/features/history-coordinator.ts
8
- var entries = [];
9
- var subscribers = /* @__PURE__ */ new Set();
10
- var suppress = 0;
11
- var internalDepth = 0;
12
- var pendingRebrands = [];
13
- var listenerInstalled = false;
14
- var patchInstalled = false;
15
- var origPushState = null;
16
- var origReplaceState = null;
17
- var patchedPushState = null;
18
- var patchedReplaceState = null;
19
- var hasWindow = () => typeof window !== "undefined";
20
- var hasHistory = () => typeof history !== "undefined";
21
- var brandMarker = (surface) => ({
17
+ var MARKER = "__bs";
18
+ var STACK = "__bsStack";
19
+ var DEPTH = "__bsDepth";
20
+ var ROUTED = "__bsRouted";
21
+ var SETTLE_TIMEOUT_MS = 1e3;
22
+ var state = shared(
23
+ "history",
24
+ () => ({
25
+ live: [],
26
+ stackId: void 0,
27
+ baseUrl: void 0,
28
+ position: null,
29
+ knownLength: 0,
30
+ href: "",
31
+ subscribers: /* @__PURE__ */ new Set(),
32
+ internal: 0,
33
+ pending: [],
34
+ deferred: [],
35
+ waiters: [],
36
+ timer: null,
37
+ listening: false,
38
+ leftovers: false,
39
+ orphanChecked: false,
40
+ push: null,
41
+ replace: null
42
+ })
43
+ );
44
+ var hasHistory = () => typeof window !== "undefined" && typeof history !== "undefined";
45
+ var plain = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
46
+ var depthOf = (value) => {
47
+ const depth = value?.[DEPTH];
48
+ return typeof depth === "number" ? depth : null;
49
+ };
50
+ var isMarker = (value) => value?.[MARKER] === true;
51
+ var inStack = (value) => value !== null && state.stackId !== void 0 && value[STACK] === state.stackId && depthOf(value) !== null;
52
+ var foreignKeys = (value) => {
53
+ const out = {};
54
+ const source = plain(value);
55
+ if (!source) return out;
56
+ for (const key of Object.keys(source)) {
57
+ if (!key.startsWith(MARKER)) out[key] = source[key];
58
+ }
59
+ return out;
60
+ };
61
+ var markerFor = (surface, depth) => ({
62
+ ...foreignKeys(history.state),
22
63
  ...surface.markerState(),
23
- __bs: true
64
+ [MARKER]: true,
65
+ [STACK]: state.stackId,
66
+ [DEPTH]: depth
24
67
  });
68
+ var urlForDepth = (depth) => {
69
+ for (let i = depth - 1; i >= 0; i -= 1) {
70
+ const url = state.live[i]?.surface.url;
71
+ if (url !== void 0) return url;
72
+ }
73
+ return state.baseUrl;
74
+ };
25
75
  var runInternal = (fn) => {
26
- internalDepth += 1;
76
+ state.internal += 1;
27
77
  try {
28
78
  fn();
79
+ return true;
80
+ } catch {
81
+ return false;
29
82
  } finally {
30
- internalDepth -= 1;
83
+ state.internal -= 1;
31
84
  }
32
85
  };
33
86
  var notifyRouteChange = () => {
34
- const snapshot = Array.from(subscribers);
35
- for (const fn of snapshot) fn();
87
+ for (const fn of Array.from(state.subscribers)) {
88
+ try {
89
+ fn();
90
+ } catch (err) {
91
+ queueMicrotask(() => {
92
+ throw err;
93
+ });
94
+ }
95
+ }
36
96
  };
37
97
  var ensureListener = () => {
38
- if (listenerInstalled || !hasWindow()) return;
98
+ if (state.listening || !hasHistory()) return;
39
99
  window.addEventListener("popstate", onPopState);
40
- listenerInstalled = true;
100
+ state.listening = true;
41
101
  };
42
102
  var maybeTeardownListener = () => {
43
- if (!listenerInstalled) return;
44
- if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
45
- if (hasWindow()) window.removeEventListener("popstate", onPopState);
46
- listenerInstalled = false;
47
- };
48
- var installPatch = () => {
49
- if (patchInstalled || !hasHistory()) return;
50
- origPushState = history.pushState;
51
- origReplaceState = history.replaceState;
52
- patchedPushState = function(...args) {
53
- origPushState.apply(this, args);
54
- if (internalDepth === 0) notifyRouteChange();
55
- };
56
- patchedReplaceState = function(...args) {
57
- origReplaceState.apply(this, args);
58
- if (internalDepth === 0) notifyRouteChange();
59
- };
60
- history.pushState = patchedPushState;
61
- history.replaceState = patchedReplaceState;
62
- patchInstalled = true;
63
- };
64
- var removePatch = () => {
65
- if (!patchInstalled) return;
66
- if (history.pushState === patchedPushState && origPushState) {
67
- history.pushState = origPushState;
68
- }
69
- if (history.replaceState === patchedReplaceState && origReplaceState) {
70
- history.replaceState = origReplaceState;
71
- }
72
- origPushState = null;
73
- origReplaceState = null;
74
- patchedPushState = null;
75
- patchedReplaceState = null;
76
- patchInstalled = false;
77
- };
78
- function onPopState() {
79
- if (suppress > 0) {
80
- suppress -= 1;
81
- const rebrand = pendingRebrands.shift();
82
- if (rebrand) rebrand();
83
- maybeTeardownListener();
103
+ if (!state.listening) return;
104
+ if (state.live.length > 0 || state.subscribers.size > 0 || state.pending.length > 0 || state.leftovers) {
84
105
  return;
85
106
  }
86
- if (entries.length === 0) {
87
- notifyRouteChange();
88
- maybeTeardownListener();
89
- return;
90
- }
91
- let target = null;
92
- let targetIdx = -1;
93
- for (let i = entries.length - 1; i >= 0; i -= 1) {
94
- const entry = entries[i];
95
- if (!entry.surface.isOpen()) continue;
96
- if (!target) {
97
- target = entry;
98
- targetIdx = i;
99
- }
100
- if (entry.surface.isTop()) {
101
- target = entry;
102
- targetIdx = i;
103
- break;
104
- }
107
+ if (hasHistory()) window.removeEventListener("popstate", onPopState);
108
+ state.listening = false;
109
+ };
110
+ var settleIfIdle = () => {
111
+ if (state.pending.length > 0) return;
112
+ if (state.timer !== null) {
113
+ clearTimeout(state.timer);
114
+ state.timer = null;
105
115
  }
106
- if (!target) {
107
- const removed = entries.pop();
108
- if (removed) removed.live = false;
116
+ for (const entry of state.deferred.splice(0)) pushEntry(entry);
117
+ for (const resolve of state.waiters.splice(0)) resolve();
118
+ };
119
+ var traverse = (delta, kind) => {
120
+ state.pending.push(kind);
121
+ if (state.timer !== null) clearTimeout(state.timer);
122
+ state.timer = setTimeout(() => {
123
+ state.timer = null;
124
+ state.pending.length = 0;
125
+ settleIfIdle();
109
126
  maybeTeardownListener();
110
- return;
111
- }
112
- target.live = false;
113
- entries.splice(targetIdx, 1);
114
- const settled = target;
115
- void Promise.resolve(settled.surface.close()).then(() => {
116
- if (settled.surface.isOpen()) restore(settled);
127
+ }, SETTLE_TIMEOUT_MS);
128
+ ensureListener();
129
+ const moved = runInternal(() => {
130
+ if (delta < 0) history.back();
131
+ else history.forward();
117
132
  });
118
- maybeTeardownListener();
119
- }
120
- function restore(entry) {
121
- if (!hasWindow() || !hasHistory()) return;
122
- entry.live = true;
133
+ if (!moved) {
134
+ state.pending.pop();
135
+ settleIfIdle();
136
+ }
137
+ };
138
+ var newStackId = () => `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
139
+ var startStack = () => {
140
+ state.stackId = newStackId();
141
+ const current = history.state;
142
+ const leftover = plain(current);
143
+ state.baseUrl = isMarker(leftover) && leftover?.[ROUTED] !== void 0 ? void 0 : location.href;
144
+ if (isMarker(leftover)) return;
145
+ if (current !== null && current !== void 0 && !leftover) return;
123
146
  runInternal(() => {
124
- try {
125
- history.pushState(brandMarker(entry.surface), "", entry.surface.url);
126
- } catch {
127
- entry.live = false;
128
- }
147
+ history.replaceState(
148
+ { ...foreignKeys(current), [STACK]: state.stackId, [DEPTH]: 0 },
149
+ "",
150
+ location.href
151
+ );
129
152
  });
130
- if (entry.live) {
131
- entries.push(entry);
132
- ensureListener();
133
- }
153
+ };
154
+ function pushEntry(entry) {
155
+ const depth = state.live.length + 1;
156
+ if (state.live.length === 0) startStack();
157
+ const written = runInternal(() => {
158
+ history.pushState(markerFor(entry.surface, depth), "", entry.surface.url);
159
+ });
160
+ if (!written) return false;
161
+ state.live.push(entry);
162
+ state.position = depth;
163
+ state.knownLength = history.length;
164
+ state.href = location.href;
165
+ ensureListener();
166
+ return true;
134
167
  }
135
- function pushBackMarker(surface) {
136
- const entry = { surface, priorUrl: void 0, live: false };
137
- if (!hasWindow() || !hasHistory()) {
138
- return entry;
168
+ var enlist = (entry) => {
169
+ if (state.pending.length > 0) state.deferred.push(entry);
170
+ else pushEntry(entry);
171
+ };
172
+ var sameBrand = (a, b) => {
173
+ for (const key of /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)])) {
174
+ if (key.startsWith(MARKER) && a[key] !== b[key]) return false;
139
175
  }
140
- entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
176
+ return true;
177
+ };
178
+ var rebrand = (depth) => {
179
+ const entry = state.live[depth - 1];
180
+ if (!entry) return;
181
+ const url = urlForDepth(depth);
182
+ const marker = markerFor(entry.surface, depth);
183
+ const atUrl = url === void 0 || new URL(url, location.href).href === location.href;
184
+ if (atUrl && sameBrand(plain(history.state) ?? {}, marker)) return;
141
185
  runInternal(() => {
186
+ history.replaceState(marker, "", url);
187
+ });
188
+ state.href = location.href;
189
+ };
190
+ var closeAbove = (depth) => {
191
+ const dropped = state.live.splice(depth);
192
+ for (let i = dropped.length - 1; i >= 0; i -= 1) {
193
+ const entry = dropped[i];
194
+ let closing = void 0;
142
195
  try {
143
- history.pushState(brandMarker(surface), "", surface.url);
144
- entry.live = true;
145
- } catch {
146
- entry.live = false;
196
+ closing = entry.surface.close();
197
+ } catch (err) {
198
+ queueMicrotask(() => {
199
+ throw err;
200
+ });
147
201
  }
148
- });
149
- if (entry.live) {
150
- entries.push(entry);
151
- ensureListener();
202
+ void Promise.resolve(closing).then(() => {
203
+ if (!entry.surface.isOpen()) return;
204
+ const known = (e) => e.surface === entry.surface;
205
+ if (state.live.some(known) || state.deferred.some(known)) return;
206
+ enlist(entry);
207
+ });
208
+ }
209
+ };
210
+ function onPopState(event) {
211
+ const kind = state.pending.shift();
212
+ const byUser = kind !== "pop";
213
+ const landed = plain(event.state);
214
+ const depth = depthOf(landed);
215
+ const from = state.position;
216
+ const liveBefore = state.live.length;
217
+ const grew = history.length > state.knownLength;
218
+ state.knownLength = history.length;
219
+ const within = inStack(landed);
220
+ if (within && depth !== null) {
221
+ state.position = depth;
222
+ if (depth > state.live.length) {
223
+ const forward = from !== null && from < depth;
224
+ traverse(forward ? 1 : -1, byUser ? "skip" : "pop");
225
+ } else if (depth < state.live.length) {
226
+ if (byUser) closeAbove(depth);
227
+ } else {
228
+ rebrand(depth);
229
+ }
230
+ } else if (isMarker(landed)) {
231
+ state.position = null;
232
+ traverse(-1, byUser ? "skip" : "pop");
233
+ } else {
234
+ state.position = null;
235
+ if (byUser && !grew && state.live.length > 0) {
236
+ closeAbove(state.live.length - 1);
237
+ }
238
+ }
239
+ const moved = location.href !== state.href;
240
+ state.href = location.href;
241
+ if (kind === void 0 && moved && (liveBefore === 0 || !within)) {
242
+ notifyRouteChange();
152
243
  }
244
+ settleIfIdle();
245
+ maybeTeardownListener();
246
+ }
247
+ function pushBackMarker(surface) {
248
+ const entry = { surface };
249
+ if (hasHistory()) enlist(entry);
153
250
  return entry;
154
251
  }
155
252
  function popBackMarker(handle) {
156
- if (!hasWindow() || !hasHistory()) return;
253
+ if (!hasHistory()) return Promise.resolve();
157
254
  const entry = handle;
158
- const idx = entries.indexOf(entry);
159
- if (idx === -1 || !entry.live) return;
160
- const last = entries.length - 1;
161
- entry.live = false;
162
- entries.splice(idx, 1);
163
- let rebrand = null;
164
- if (idx !== last) {
165
- const rebrandSurface = entries[entries.length - 1].surface;
166
- const rebrandUrl = entry.priorUrl;
167
- rebrand = () => {
168
- runInternal(() => {
169
- history.replaceState(
170
- brandMarker(rebrandSurface),
171
- "",
172
- rebrandUrl !== void 0 ? rebrandUrl : location.href
173
- );
174
- });
175
- };
255
+ const waiting = state.deferred.indexOf(entry);
256
+ if (waiting !== -1) state.deferred.splice(waiting, 1);
257
+ const idx = state.live.indexOf(entry);
258
+ if (idx === -1) return historySettled();
259
+ const top = state.live.length;
260
+ state.live.splice(idx, 1);
261
+ const current = plain(history.state);
262
+ const onTop = isMarker(current) && inStack(current) && depthOf(current) === top;
263
+ if (onTop && state.pending.length === 0) {
264
+ traverse(-1, "pop");
265
+ } else {
266
+ state.leftovers = true;
267
+ ensureListener();
176
268
  }
177
- pendingRebrands.push(rebrand);
178
- suppress += 1;
179
- runInternal(() => {
180
- try {
181
- history.back();
182
- } catch {
183
- suppress = Math.max(0, suppress - 1);
184
- pendingRebrands.pop();
185
- }
186
- });
187
269
  maybeTeardownListener();
270
+ return historySettled();
271
+ }
272
+ function releaseOrphanMarker() {
273
+ if (!hasHistory() || state.orphanChecked) return;
274
+ state.orphanChecked = true;
275
+ if (state.live.length > 0 || state.pending.length > 0) return;
276
+ if (!isMarker(plain(history.state))) return;
277
+ state.leftovers = true;
278
+ traverse(-1, "pop");
279
+ }
280
+ function historySettled() {
281
+ if (state.pending.length === 0) return Promise.resolve();
282
+ return new Promise((resolve) => {
283
+ state.waiters.push(resolve);
284
+ });
188
285
  }
286
+ var wrap = (original) => function(...args) {
287
+ original.apply(this, args);
288
+ state.knownLength = history.length;
289
+ if (location.href === state.href) return;
290
+ state.href = location.href;
291
+ if (state.internal === 0 && state.subscribers.size > 0) {
292
+ notifyRouteChange();
293
+ }
294
+ };
295
+ var installPatch = () => {
296
+ if (!state.push || history.pushState === state.push.original) {
297
+ const original = history.pushState;
298
+ const wrapper = wrap(original);
299
+ history.pushState = wrapper;
300
+ state.push = { wrapper, original };
301
+ }
302
+ if (!state.replace || history.replaceState === state.replace.original) {
303
+ const original = history.replaceState;
304
+ const wrapper = wrap(original);
305
+ history.replaceState = wrapper;
306
+ state.replace = { wrapper, original };
307
+ }
308
+ };
309
+ var removePatch = () => {
310
+ if (state.push && history.pushState === state.push.wrapper) {
311
+ history.pushState = state.push.original;
312
+ state.push = null;
313
+ }
314
+ if (state.replace && history.replaceState === state.replace.wrapper) {
315
+ history.replaceState = state.replace.original;
316
+ state.replace = null;
317
+ }
318
+ };
189
319
  function subscribeRouteChange(fn) {
190
- if (!hasWindow() || !hasHistory()) return () => {
320
+ if (!hasHistory()) return () => {
191
321
  };
192
- subscribers.add(fn);
193
- if (subscribers.size === 1) installPatch();
322
+ state.subscribers.add(fn);
323
+ state.href = location.href;
324
+ state.knownLength = history.length;
325
+ installPatch();
194
326
  ensureListener();
195
327
  return () => {
196
- if (!subscribers.has(fn)) return;
197
- subscribers.delete(fn);
198
- if (subscribers.size === 0) removePatch();
328
+ if (!state.subscribers.delete(fn)) return;
329
+ if (state.subscribers.size === 0) removePatch();
199
330
  maybeTeardownListener();
200
331
  };
201
332
  }
@@ -211,36 +342,37 @@ function installRoute(deps) {
211
342
  };
212
343
  }
213
344
  let handle = null;
345
+ const surface = {
346
+ isOpen: () => !deps.isDestroyed() && deps.isOpen(),
347
+ close: deps.close,
348
+ markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
349
+ url: deps.routedTo
350
+ };
214
351
  const onOpen = () => {
215
352
  if (handle) return;
216
- handle = pushBackMarker({
217
- isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
218
- isTop: deps.isTopSheet,
219
- close: deps.close,
220
- markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
221
- url: deps.routedTo
222
- });
353
+ handle = pushBackMarker(surface);
223
354
  };
224
355
  const onClose = () => {
225
356
  if (!handle) return;
226
- popBackMarker(handle);
357
+ deps.hold(popBackMarker(handle));
227
358
  handle = null;
228
359
  };
229
360
  const unsubscribeOpen = deps.on("open", onOpen);
230
361
  const unsubscribeClose = deps.on("close", onClose);
231
- if (deps.getSize() > 0) onOpen();
362
+ if (deps.isOpen()) onOpen();
363
+ else releaseOrphanMarker();
232
364
  return () => {
233
365
  unsubscribeOpen();
234
366
  unsubscribeClose();
235
367
  if (handle) {
236
- popBackMarker(handle);
368
+ void popBackMarker(handle);
237
369
  handle = null;
238
370
  }
239
371
  };
240
372
  }
241
373
  function installRouteChange(deps) {
242
374
  return subscribeRouteChange(() => {
243
- if (deps.isDestroyed() || deps.getSize() <= 0) return;
375
+ if (deps.isDestroyed() || !deps.isOpen()) return;
244
376
  void deps.close();
245
377
  });
246
378
  }
@@ -274,7 +406,10 @@ function installAutoCollapse(deps) {
274
406
  };
275
407
  const fire = () => {
276
408
  if (deps.isDestroyed()) return;
277
- if (deps.isDragging()) return;
409
+ if (deps.isDragging() || deps.isAnimating()) {
410
+ reset();
411
+ return;
412
+ }
278
413
  const active = deps.resolveSnap(deps.getActiveId());
279
414
  if (!active || active.size === 0) return;
280
415
  let target = null;
@@ -309,8 +444,22 @@ function installContentDrag(deps) {
309
444
  return () => detach?.();
310
445
  }
311
446
 
447
+ // src/core/primitives/hot-path-thresholds.ts
448
+ var SIZE_WRITE_EPSILON = 0.5;
449
+
450
+ // src/core/features/resize-observer.ts
451
+ var seatOf = (deps) => {
452
+ const snap = deps.resolveActiveSnap();
453
+ const max = deps.getMaxAxisSize();
454
+ return { target: snap ? Math.min(snap.size, max) : null, max };
455
+ };
456
+ var sameSeat = (before, after) => before.target !== null && after.target !== null && Math.abs(after.target - before.target) < SIZE_WRITE_EPSILON && Math.abs(after.max - before.max) < SIZE_WRITE_EPSILON;
457
+
312
458
  // src/core/features/visual-viewport.ts
313
459
  var SAFETY_PAD = 8;
460
+ var KEYBOARD_MIN_INSET = 1;
461
+ var KEYBOARD_MIN_COVER = 60;
462
+ var ZOOMED = 1.01;
314
463
  function installVisualViewport(deps) {
315
464
  if (typeof window === "undefined" || !window.visualViewport) {
316
465
  return () => {
@@ -318,36 +467,36 @@ function installVisualViewport(deps) {
318
467
  }
319
468
  const vv = window.visualViewport;
320
469
  let rafId = null;
470
+ const coveredByKeyboard = () => {
471
+ if ((vv.scale || 1) > ZOOMED) return 0;
472
+ const covered = window.innerHeight - ((vv.offsetTop || 0) + vv.height);
473
+ return covered >= KEYBOARD_MIN_COVER ? Math.round(covered) : 0;
474
+ };
321
475
  const onResize = () => {
322
476
  if (rafId !== null) return;
323
477
  rafId = requestAnimationFrame(() => {
324
478
  rafId = null;
325
479
  if (deps.isDestroyed()) return;
480
+ deps.setKeyboardInset(coveredByKeyboard());
481
+ const before = seatOf(deps);
326
482
  deps.recomputeSnaps();
327
483
  const isVertical = deps.isVerticalAxis();
328
484
  const visible = isVertical ? vv.height : vv.width;
329
485
  const windowSize = isVertical ? window.innerHeight : window.innerWidth;
330
- const clamp = Math.max(0, Math.min(windowSize, visible) - SAFETY_PAD);
486
+ const pad = windowSize - visible > KEYBOARD_MIN_INSET ? SAFETY_PAD : 0;
487
+ const clamp = Math.max(0, Math.min(windowSize, visible) - pad);
331
488
  if (clamp < deps.getMaxAxisSize()) {
332
489
  deps.setMaxAxisSize(clamp);
333
490
  }
334
- const wasAnimating = deps.isAnimating?.() ?? false;
335
- deps.cancelInFlight();
336
- deps.newCycle();
337
- const max = deps.getMaxAxisSize();
338
- deps.setSize(Math.min(deps.getSize(), max));
339
- const current = deps.resolveActiveSnap();
340
- if (current && !deps.isDragging()) {
341
- deps.applySize(Math.min(current.size, max));
342
- if (wasAnimating) deps.resyncAfterCancel?.();
343
- } else {
344
- deps.applySize(deps.getSize());
345
- }
491
+ if (sameSeat(before, seatOf(deps))) return;
492
+ deps.reseat();
346
493
  });
347
494
  };
348
495
  vv.addEventListener("resize", onResize);
496
+ vv.addEventListener("scroll", onResize);
349
497
  return () => {
350
498
  vv.removeEventListener("resize", onResize);
499
+ vv.removeEventListener("scroll", onResize);
351
500
  if (rafId !== null) cancelAnimationFrame(rafId);
352
501
  };
353
502
  }
@@ -383,7 +532,7 @@ function routeFeature() {
383
532
  teardowns.add(
384
533
  installRouteChange({
385
534
  isDestroyed: ctx.isDestroyed,
386
- getSize: ctx.getSize,
535
+ isOpen: () => ctx.getPhase() !== "closed",
387
536
  close: () => ctx.close()
388
537
  })
389
538
  );
@@ -392,10 +541,10 @@ function routeFeature() {
392
541
  installRoute({
393
542
  routedTo: ctx.options.routedTo,
394
543
  closeOnBack: ctx.options.closeOnBack,
395
- isTopSheet: ctx.isTopSheet,
396
- getSize: ctx.getSize,
544
+ isOpen: () => ctx.getPhase() !== "closed",
397
545
  isDestroyed: ctx.isDestroyed,
398
546
  close: () => ctx.close("back"),
547
+ hold: ctx.holdSettle,
399
548
  on: ctx.on,
400
549
  sheetId: ctx.sheetId
401
550
  })
@@ -421,6 +570,7 @@ function autoCollapseFeature() {
421
570
  ms: ctx.options.autoCollapseAfter,
422
571
  isDestroyed: ctx.isDestroyed,
423
572
  isDragging: ctx.isDragging,
573
+ isAnimating: ctx.isAnimating,
424
574
  getAllowedIds: ctx.getAllowedIds,
425
575
  getActiveId: ctx.getActiveId,
426
576
  resolveSnap: ctx.resolveSnap,
@@ -448,21 +598,14 @@ function visualViewportFeature() {
448
598
  install: (ctx) => {
449
599
  if (typeof window === "undefined") return;
450
600
  return installVisualViewport({
451
- element: ctx.element,
452
601
  isVerticalAxis: ctx.isVerticalAxis,
453
602
  isDestroyed: ctx.isDestroyed,
454
- isDragging: ctx.isDragging,
455
603
  recomputeSnaps: ctx.recomputeSnaps,
456
604
  resolveActiveSnap: ctx.resolveActiveSnap,
457
605
  getMaxAxisSize: ctx.getMaxAxisSize,
458
- getSize: ctx.getSize,
459
606
  setMaxAxisSize: ctx.setMaxAxisSize,
460
- setSize: ctx.setSize,
461
- applySize: ctx.applySize,
462
- cancelInFlight: ctx.cancelInFlight,
463
- newCycle: ctx.newCycle,
464
- isAnimating: ctx.isAnimating,
465
- resyncAfterCancel: ctx.resyncAfterResize
607
+ setKeyboardInset: ctx.setKeyboardInset,
608
+ reseat: ctx.reseat
466
609
  });
467
610
  }
468
611
  };
@@ -623,6 +766,7 @@ exports.autoCollapseFeature = autoCollapseFeature;
623
766
  exports.contentFitFeature = contentFitFeature;
624
767
  exports.contentSwipeFeature = contentSwipeFeature;
625
768
  exports.defaultEngineFeatures = defaultEngineFeatures;
769
+ exports.historySettled = historySettled;
626
770
  exports.persistFeature = persistFeature;
627
771
  exports.routeFeature = routeFeature;
628
772
  exports.visualViewportFeature = visualViewportFeature;
@@ -1,7 +1,6 @@
1
- export { a as autoCollapseFeature, c as contentSwipeFeature, d as defaultEngineFeatures, p as persistFeature, r as routeFeature, v as visualViewportFeature } from './default-features-BGiCSmV1.cjs';
2
- import { E as EngineFeature } from './BottomSheetCore-C5tJYVMY.cjs';
3
- export { a as EngineFeatureContext, b as EngineFeatureOptions, c as EngineFeatureStage } from './BottomSheetCore-C5tJYVMY.cjs';
4
- import './transform-jVfAikE9.cjs';
1
+ export { a as autoCollapseFeature, c as contentSwipeFeature, d as defaultEngineFeatures, h as historySettled, p as persistFeature, r as routeFeature, v as visualViewportFeature } from './default-features-DX2NOxP6.cjs';
2
+ import { E as EngineFeature } from './BottomSheetCore-B_r4KCQL.cjs';
3
+ export { a as EngineFeatureContext, b as EngineFeatureOptions, c as EngineFeatureStage } from './BottomSheetCore-B_r4KCQL.cjs';
5
4
 
6
5
  declare function contentFitFeature(): EngineFeature;
7
6