@surdeddd/bottom-sheet 0.23.4 → 0.24.1

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