@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
@@ -6,49 +6,48 @@
6
6
  teleportElements,
7
7
  type TeleportTarget,
8
8
  } from "../svelte-core.js";
9
+ import { guessPhysicalMode } from "../svelte-core.js";
10
+ import { startsClosed } from "../svelte-core.js";
11
+ import { closedSnapId } from "../svelte-core.js";
12
+ import type { AnchorOptions } from "@surdeddd/bottom-sheet";
13
+ import type { ScrimStagesOptions } from "@surdeddd/bottom-sheet";
9
14
  import type {
15
+ CloseReason,
10
16
  EngineState,
17
+ PhysicalSheetMode,
11
18
  SnapPointDef,
12
- SheetMode,
13
19
  ScrimUpdate,
14
20
  ScrimOverlayOptions,
15
21
  EngineOptions,
16
22
  SheetEventMap,
17
23
  } from "@surdeddd/bottom-sheet";
18
24
 
19
- type Props = {
25
+ type Props = Omit<
26
+ Partial<EngineOptions>,
27
+ | "element"
28
+ | "handle"
29
+ | "scrollContainer"
30
+ | "backdrop"
31
+ | "scrim"
32
+ | "screenComponent"
33
+ | "snapPoints"
34
+ | "allowed"
35
+ | "initial"
36
+ > & {
20
37
  snapPoints: SnapPointDef<TId>[];
21
38
  allowed?: TId[];
22
39
  initial?: TId;
23
- mode?: SheetMode;
24
- animation?: "spring" | "tween";
25
- spring?: { stiffness?: number; damping?: number; mass?: number };
26
- focusTrap?: boolean;
27
- closeOnEscape?: boolean;
28
- closeOnBack?: boolean;
29
- lockBodyScroll?: boolean;
30
- rubberBand?: boolean;
31
- backdropRange?: [number, number];
32
40
  backdrop?: boolean;
33
41
  closeOnBackdrop?: boolean;
34
- persistent?: boolean;
35
- disableClose?: boolean;
36
- disableDrag?: boolean;
37
- dragFrom?: EngineOptions["dragFrom"];
38
- dragFromContent?: boolean;
39
- fitContentToSnap?: boolean;
40
- closeOnRouteChange?: boolean;
41
- stackEffect?: boolean;
42
42
  teleport?: boolean;
43
43
  teleportTo?: TeleportTarget;
44
- radius?: string | number;
45
- maxHeight?: string | number;
46
44
  backdropColor?: string;
47
45
  backdropOpacity?: number;
48
46
  open?: boolean;
49
47
  snap?: TId;
50
- returnFocusTo?: HTMLElement | string | (() => HTMLElement | null);
51
48
  ariaLabel?: string;
49
+ handleLabel?: string;
50
+ contentLabel?: string;
52
51
  header?: Snippet<[EngineState & { activeId: TId }]>;
53
52
  footer?: Snippet<[EngineState & { activeId: TId }]>;
54
53
  leftButton?: Snippet;
@@ -62,8 +61,8 @@
62
61
  onbeforeclose?: (payload: SheetEventMap["before-close"]) => void;
63
62
  onopened?: (id: TId) => void;
64
63
  onclosed?: () => void;
65
- ondragstart?: () => void;
66
- ondragend?: () => void;
64
+ ondragstart?: (payload: SheetEventMap["dragstart"]) => void;
65
+ ondragend?: (payload: SheetEventMap["dragend"]) => void;
67
66
  ondrag?: (payload: SheetEventMap["drag"]) => void;
68
67
  onprogress?: (payload: SheetEventMap["progress"]) => void;
69
68
  onchange?: (state: EngineState & { activeId: TId }) => void;
@@ -92,7 +91,7 @@
92
91
  fitContentToSnap,
93
92
  closeOnRouteChange = false,
94
93
  stackEffect = false,
95
- teleport = false,
94
+ teleport,
96
95
  teleportTo,
97
96
  radius,
98
97
  maxHeight,
@@ -102,6 +101,8 @@
102
101
  snap = $bindable(),
103
102
  returnFocusTo,
104
103
  ariaLabel = "Bottom sheet",
104
+ handleLabel = "Resize sheet",
105
+ contentLabel = "Sheet content",
105
106
  header,
106
107
  footer,
107
108
  leftButton,
@@ -120,6 +121,7 @@
120
121
  ondrag,
121
122
  onprogress,
122
123
  onchange,
124
+ ...engineRest
123
125
  }: Props = $props();
124
126
 
125
127
  let sheetEl: HTMLElement | undefined = $state();
@@ -128,11 +130,21 @@
128
130
  let backdropEl: HTMLElement | undefined = $state();
129
131
  let screenEl: HTMLElement | undefined = $state();
130
132
 
133
+ const startAt = untrack(
134
+ () =>
135
+ initial ??
136
+ (openProp === false
137
+ ? (closedSnapId(snapPoints) as TId | undefined)
138
+ : undefined) ??
139
+ snap,
140
+ );
141
+
131
142
  let viewState: EngineState & { activeId: TId } = $state({
132
143
  size: 0,
133
144
  activeId: untrack(
134
- () => (initial ?? snapPoints[0]?.id ?? "default") as TId,
145
+ () => (startAt ?? snapPoints[0]?.id ?? "default") as TId,
135
146
  ),
147
+ phase: "closed",
136
148
  isDragging: false,
137
149
  isAnimating: false,
138
150
  progress: 0,
@@ -140,10 +152,25 @@
140
152
 
141
153
  let engine: BottomSheetEngine | null = null;
142
154
  let restoreTeleport: (() => void) | null = null;
155
+ let physicalMode: PhysicalSheetMode = $state(
156
+ untrack(() => guessPhysicalMode(mode)),
157
+ );
158
+ const restAtStart = untrack(() =>
159
+ startsClosed(snapPoints, startAt, allowed) ? "closed" : undefined,
160
+ );
143
161
 
144
162
  onMount(() => {
145
163
  if (!sheetEl) return;
164
+ const teleportTarget =
165
+ teleport === false ? null : resolveTeleportTarget(teleportTo);
166
+ if (teleportTarget) {
167
+ restoreTeleport = teleportElements(
168
+ [backdropEl, screenEl, sheetEl],
169
+ teleportTarget,
170
+ );
171
+ }
146
172
  engine = new BottomSheetEngine({
173
+ ...engineRest,
147
174
  element: sheetEl,
148
175
  handle: handleEl,
149
176
  scrollContainer: contentEl,
@@ -152,7 +179,7 @@
152
179
  mode,
153
180
  snapPoints,
154
181
  allowed,
155
- initial,
182
+ initial: startAt,
156
183
  animation,
157
184
  spring,
158
185
  focusTrap,
@@ -172,48 +199,51 @@
172
199
  radius,
173
200
  maxHeight,
174
201
  returnFocusTo,
202
+ backdropColor,
203
+ backdropOpacity,
175
204
  });
176
- const teleportTarget =
177
- teleport === false ? null : resolveTeleportTarget(teleportTo);
178
- if (teleportTarget) {
179
- restoreTeleport = teleportElements(
180
- [backdropEl, screenEl, sheetEl],
181
- teleportTarget,
182
- );
183
- }
184
205
  const sync = () => {
185
206
  if (!engine) return;
186
207
  viewState = { ...engine.state } as EngineState & { activeId: TId };
187
208
  onchange?.(viewState);
188
209
  };
210
+ physicalMode = engine.getMode();
189
211
  sync();
190
- if (backdropColor !== undefined) engine.setScrimColor(backdropColor);
191
- if (backdropOpacity !== undefined)
192
- engine.setBackdropRange([0, backdropOpacity]);
212
+ if (snap !== undefined && snap !== engine.state.activeId) {
213
+ snap = engine.state.activeId as TId;
214
+ }
193
215
  engine.on("snap", payload => {
194
216
  sync();
195
217
  snap = payload.id as TId;
196
218
  onsnap?.(payload.id as TId);
197
219
  });
198
220
  engine.on("open", payload => {
221
+ sync();
199
222
  openProp = true;
200
223
  onopen?.(payload.id as TId);
201
224
  });
202
225
  engine.on("close", () => {
226
+ sync();
203
227
  openProp = false;
204
228
  onclose?.();
205
229
  });
206
230
  engine.on("before-close", payload => onbeforeclose?.(payload));
207
231
  engine.on("before-snap", payload => onbeforesnap?.(payload));
208
- engine.on("opened", payload => onopened?.(payload.id as TId));
209
- engine.on("closed", () => onclosed?.());
210
- engine.on("dragstart", () => {
232
+ engine.on("opened", payload => {
233
+ sync();
234
+ onopened?.(payload.id as TId);
235
+ });
236
+ engine.on("closed", () => {
237
+ sync();
238
+ onclosed?.();
239
+ });
240
+ engine.on("dragstart", payload => {
211
241
  sync();
212
- ondragstart?.();
242
+ ondragstart?.(payload);
213
243
  });
214
- engine.on("dragend", () => {
244
+ engine.on("dragend", payload => {
215
245
  sync();
216
- ondragend?.();
246
+ ondragend?.(payload);
217
247
  });
218
248
  if (ondrag) engine.on("drag", payload => ondrag(payload));
219
249
  if (onprogress) engine.on("progress", payload => onprogress(payload));
@@ -230,7 +260,8 @@
230
260
  engine?.snapTo(id) ?? Promise.resolve();
231
261
  export const open = (id?: TId) =>
232
262
  engine?.open(id) ?? Promise.resolve();
233
- export const close = () => engine?.close() ?? Promise.resolve();
263
+ export const close = (reason?: CloseReason) =>
264
+ engine?.close(reason) ?? Promise.resolve();
234
265
  export const expand = () => engine?.expand() ?? Promise.resolve();
235
266
  export const collapse = () => engine?.collapse() ?? Promise.resolve();
236
267
  export const isTop = (): boolean => engine?.isTop() ?? false;
@@ -244,6 +275,12 @@
244
275
  export const setScrim = (opts: ScrimUpdate) => engine?.setScrim(opts);
245
276
  export const setScrimOverlay = (opts: ScrimOverlayOptions): (() => void) =>
246
277
  engine?.setScrimOverlay(opts) ?? (() => {});
278
+ export const addAnchor = (opts: AnchorOptions): (() => void) =>
279
+ engine?.addAnchor(opts) ?? (() => {});
280
+ export const setScrimStages = (
281
+ opts: ScrimStagesOptions | null,
282
+ ): (() => void) => engine?.setScrimStages(opts) ?? (() => {});
283
+ export const recompute = () => engine?.recompute();
247
284
  export const setRadius = (r: string | number) => engine?.setRadius(r);
248
285
  export const setMaxHeight = (h: string | number) => engine?.setMaxHeight(h);
249
286
  export const canDismiss = (): boolean => engine?.canDismiss() ?? false;
@@ -290,7 +327,9 @@
290
327
  if (dragFrom !== undefined) engine?.setDragFrom(dragFrom);
291
328
  });
292
329
  $effect(() => {
293
- if (mode !== undefined) engine?.setMode(mode);
330
+ const next = mode;
331
+ if (next !== undefined) engine?.setMode(next);
332
+ physicalMode = engine ? engine.getMode() : guessPhysicalMode(next);
294
333
  });
295
334
  $effect(() => {
296
335
  if (radius !== undefined) engine?.setRadius(radius);
@@ -299,28 +338,31 @@
299
338
  if (maxHeight !== undefined) engine?.setMaxHeight(maxHeight);
300
339
  });
301
340
  $effect(() => {
302
- if (backdropColor !== undefined) engine?.setScrimColor(backdropColor);
341
+ if (backdropColor !== undefined) engine?.setBackdropColor(backdropColor);
303
342
  });
304
343
  $effect(() => {
305
344
  if (backdropOpacity !== undefined)
306
- engine?.setBackdropRange([0, backdropOpacity]);
345
+ engine?.setBackdropOpacity(backdropOpacity);
307
346
  });
308
347
  $effect(() => {
309
348
  if (snap === undefined) return;
310
349
  const next = snap;
311
- if (!engine || untrack(() => viewState.activeId) === next) return;
350
+ if (!engine || engine.state.activeId === next) return;
312
351
  void engine.snapTo(next);
313
352
  });
314
353
  $effect(() => {
315
354
  if (openProp === undefined) return;
316
355
  const next = openProp;
317
356
  if (!engine) return;
318
- const isOpen = untrack(() => viewState.size) > 0;
319
- if (next && !isOpen) void engine.open();
320
- else if (!next && isOpen) void engine.close();
357
+ const phase = engine.state.phase;
358
+ const opening = phase === "open" || phase === "opening";
359
+ if (next && !opening) void engine.open();
360
+ else if (!next && opening) void engine.close();
321
361
  });
322
362
 
323
- let isVerticalAxis = $derived(mode === "bottom" || mode === "top");
363
+ let isVerticalAxis = $derived(
364
+ physicalMode === "bottom" || physicalMode === "top",
365
+ );
324
366
  </script>
325
367
 
326
368
  <div class="bs-root">
@@ -345,7 +387,8 @@
345
387
  <section
346
388
  class="bs-sheet"
347
389
  bind:this={sheetEl}
348
- data-mode={mode}
390
+ data-mode={physicalMode}
391
+ data-bs-rest={restAtStart}
349
392
  data-active={viewState.activeId}
350
393
  role="dialog"
351
394
  aria-modal={focusTrap ? "true" : undefined}
@@ -356,7 +399,7 @@
356
399
  bind:this={handleEl}
357
400
  role="slider"
358
401
  tabindex="0"
359
- aria-label="Resize sheet"
402
+ aria-label={handleLabel}
360
403
  aria-orientation={isVerticalAxis ? "vertical" : "horizontal"}
361
404
  aria-valuemin="0"
362
405
  aria-valuemax="0"
@@ -364,7 +407,7 @@
364
407
  ></div>
365
408
  {#if header}<div class="bs-header">{@render header(viewState)}</div>{/if}
366
409
  <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
367
- <div class="bs-content" bind:this={contentEl} tabindex="0" role="region" aria-label="Sheet content">
410
+ <div class="bs-content" bind:this={contentEl} tabindex="0" role="region" aria-label={contentLabel}>
368
411
  {#if children}{@render children()}{/if}
369
412
  </div>
370
413
  {#if footer}<div class="bs-footer">{@render footer(viewState)}</div>{/if}
@@ -373,12 +416,12 @@
373
416
  </span>
374
417
  </section>
375
418
  {#if leftButton}
376
- <div class="bs-button-slot" data-side="left" data-mode={mode}>
419
+ <div class="bs-button-slot" data-side="left" data-mode={physicalMode}>
377
420
  {@render leftButton()}
378
421
  </div>
379
422
  {/if}
380
423
  {#if rightButton}
381
- <div class="bs-button-slot" data-side="right" data-mode={mode}>
424
+ <div class="bs-button-slot" data-side="right" data-mode={physicalMode}>
382
425
  {@render rightButton()}
383
426
  </div>
384
427
  {/if}