@capgo/capacitor-sheets 8.0.11 → 8.0.12

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 (49) hide show
  1. package/README.md +29 -1
  2. package/dist/angular/index.d.mts +18 -2
  3. package/dist/angular/index.d.ts +18 -2
  4. package/dist/angular/index.js +157 -16
  5. package/dist/angular/index.js.map +1 -1
  6. package/dist/angular/index.mjs +157 -16
  7. package/dist/angular/index.mjs.map +1 -1
  8. package/dist/{chunk-LY2DKBXN.mjs → chunk-7DYTSFX3.mjs} +27 -10
  9. package/dist/chunk-7DYTSFX3.mjs.map +1 -0
  10. package/dist/{chunk-FHGK4I6L.mjs → chunk-AXGC7BLW.mjs} +133 -9
  11. package/dist/chunk-AXGC7BLW.mjs.map +1 -0
  12. package/dist/{components-YSGBN2YD.mjs → components-STHKYCFN.mjs} +3 -3
  13. package/dist/index.d.mts +19 -3
  14. package/dist/index.d.ts +19 -3
  15. package/dist/index.js +158 -17
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +4 -4
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/react/index.d.mts +23 -2
  20. package/dist/react/index.d.ts +23 -2
  21. package/dist/react/index.js +157 -16
  22. package/dist/react/index.js.map +1 -1
  23. package/dist/react/index.mjs +157 -16
  24. package/dist/react/index.mjs.map +1 -1
  25. package/dist/solid/index.d.mts +23 -2
  26. package/dist/solid/index.d.ts +23 -2
  27. package/dist/solid/index.js +157 -16
  28. package/dist/solid/index.js.map +1 -1
  29. package/dist/solid/index.mjs +157 -16
  30. package/dist/solid/index.mjs.map +1 -1
  31. package/dist/{styles-VAFNQKVC.mjs → styles-P4J3AKBN.mjs} +2 -2
  32. package/dist/svelte/index.d.mts +18 -2
  33. package/dist/svelte/index.d.ts +18 -2
  34. package/dist/svelte/index.js +157 -16
  35. package/dist/svelte/index.js.map +1 -1
  36. package/dist/svelte/index.mjs +157 -16
  37. package/dist/svelte/index.mjs.map +1 -1
  38. package/dist/vue/index.d.mts +18 -2
  39. package/dist/vue/index.d.ts +18 -2
  40. package/dist/vue/index.js +157 -16
  41. package/dist/vue/index.js.map +1 -1
  42. package/dist/vue/index.mjs +157 -16
  43. package/dist/vue/index.mjs.map +1 -1
  44. package/docs/demos/ios-fullscreen-real-demo.webp +0 -0
  45. package/package.json +1 -1
  46. package/dist/chunk-FHGK4I6L.mjs.map +0 -1
  47. package/dist/chunk-LY2DKBXN.mjs.map +0 -1
  48. /package/dist/{components-YSGBN2YD.mjs.map → components-STHKYCFN.mjs.map} +0 -0
  49. /package/dist/{styles-VAFNQKVC.mjs.map → styles-P4J3AKBN.mjs.map} +0 -0
package/README.md CHANGED
@@ -183,6 +183,20 @@ Create the Capgo app once before the first upload. GitHub Actions also include a
183
183
 
184
184
  ## Installation
185
185
 
186
+ You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command:
187
+
188
+ ```bash
189
+ npx skills add https://github.com/cap-go/capacitor-skills --skill capacitor-plugins
190
+ ```
191
+
192
+ Then use the following prompt:
193
+
194
+ ```text
195
+ Use the `capacitor-plugins` skill from `cap-go/capacitor-skills` to install the `@capgo/capacitor-sheets` plugin in my project.
196
+ ```
197
+
198
+ If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:
199
+
186
200
  ```bash
187
201
  npm install @capgo/capacitor-sheets
188
202
  npx cap sync
@@ -196,13 +210,27 @@ Add `viewport-fit=cover` so iOS exposes safe-area insets to CSS:
196
210
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
197
211
  ```
198
212
 
199
- Safe areas are enabled by default. `cap-sheet-view` reads standard `env(safe-area-inset-*)` values and Capacitor SystemBars fallback variables such as `--safe-area-inset-bottom`, then applies them to the sheet viewport in `em`-based layout. You can opt out or choose edges per sheet:
213
+ Safe areas are enabled by default. In `auto`, edge-attached sheets protect the attached edge and side edges while leaving the opposite edge available for fullscreen detents. `cap-sheet-view` reads standard `env(safe-area-inset-*)` values and Capacitor SystemBars fallback variables such as `--safe-area-inset-bottom`, then applies them to the sheet viewport in `em`-based layout. You can opt out or choose edges per sheet:
200
214
 
201
215
  ```text
202
216
  <cap-sheet safe-area="none"></cap-sheet>
203
217
  <cap-sheet safe-area="bottom left right"></cap-sheet>
204
218
  ```
205
219
 
220
+ Detached sheets can use Gorhom-style container spacing without CSS margins. Use `detached` for full edge rounding, `top-inset` / `bottom-inset` / `left-inset` / `right-inset` for one-off offsets, or `containerOffset` from framework setup helpers for per-edge offsets:
221
+
222
+ ```html
223
+ <cap-sheet detached bottom-inset="1rem" detents="18em" content-placement="bottom"></cap-sheet>
224
+ ```
225
+
226
+ ```ts
227
+ setupSheet(sheet, {
228
+ detached: true,
229
+ bottomInset: '1rem',
230
+ containerOffset: { left: '1rem', right: '1rem' },
231
+ });
232
+ ```
233
+
206
234
  For Capacitor apps with overlay status/system bars, keep the platform plugins responsible for exposing correct insets:
207
235
 
208
236
  ```ts
@@ -5,7 +5,11 @@ type SheetTrack = Exclude<SheetPlacement, 'center'>;
5
5
  /** Viewport edges protected by safe-area insets. */
6
6
  type SheetSafeAreaEdge = 'top' | 'bottom' | 'left' | 'right';
7
7
  /** Safe-area behavior for Capacitor WebViews and mobile browsers. */
8
- type SheetSafeAreaMode = boolean | 'auto' | 'none' | SheetSafeAreaEdge[];
8
+ type SheetSafeAreaMode = boolean | 'auto' | 'all' | 'none' | SheetSafeAreaEdge[];
9
+ /** CSS length or pixel number used for sheet container insets. */
10
+ type SheetInsetValue = string | number;
11
+ /** Extra container offsets applied around the sheet viewport. */
12
+ type SheetContainerOffset = Partial<Record<SheetSafeAreaEdge, SheetInsetValue>>;
9
13
  /** Runtime travel state emitted by sheet lifecycle events. */
10
14
  type SheetTravelStatus = 'idle' | 'entering' | 'exiting' | 'dragging' | 'settling';
11
15
  /** Built-in animation presets tuned for mobile WebViews. */
@@ -49,6 +53,18 @@ interface SheetOptions {
49
53
  contentPlacement?: SheetPlacement;
50
54
  /** Safe-area edges protected by the sheet viewport. Defaults to `auto`. */
51
55
  safeArea?: SheetSafeAreaMode;
56
+ /** Render as a floating sheet with detached edge rounding. */
57
+ detached?: boolean;
58
+ /** Extra top inset added to the sheet viewport, equivalent to Gorhom `topInset`. */
59
+ topInset?: SheetInsetValue;
60
+ /** Extra bottom inset added to the sheet viewport, equivalent to Gorhom `bottomInset`. */
61
+ bottomInset?: SheetInsetValue;
62
+ /** Extra left inset added to the sheet viewport. */
63
+ leftInset?: SheetInsetValue;
64
+ /** Extra right inset added to the sheet viewport. */
65
+ rightInset?: SheetInsetValue;
66
+ /** Extra per-edge container offsets, equivalent to Gorhom `containerOffset`. */
67
+ containerOffset?: SheetContainerOffset;
52
68
  /** Edge tracks that can dismiss the sheet. */
53
69
  tracks?: SheetTrack | SheetTrack[];
54
70
  /** Enables pointer, touch, trackpad, and wheel travel gestures. */
@@ -111,4 +127,4 @@ declare function setupSheet(element: HTMLElement, options?: Partial<SheetOptions
111
127
  onTravel?: (event: SheetTravelEvent) => void;
112
128
  }): () => void;
113
129
 
114
- export { type SheetActiveDetentChangeEvent, type SheetOptions, type SheetPresentedChangeEvent, type SheetSafeAreaEdge, type SheetSafeAreaMode, type SheetTravelEvent, setupSheet };
130
+ export { type SheetActiveDetentChangeEvent, type SheetContainerOffset, type SheetInsetValue, type SheetOptions, type SheetPresentedChangeEvent, type SheetSafeAreaEdge, type SheetSafeAreaMode, type SheetTravelEvent, setupSheet };
@@ -5,7 +5,11 @@ type SheetTrack = Exclude<SheetPlacement, 'center'>;
5
5
  /** Viewport edges protected by safe-area insets. */
6
6
  type SheetSafeAreaEdge = 'top' | 'bottom' | 'left' | 'right';
7
7
  /** Safe-area behavior for Capacitor WebViews and mobile browsers. */
8
- type SheetSafeAreaMode = boolean | 'auto' | 'none' | SheetSafeAreaEdge[];
8
+ type SheetSafeAreaMode = boolean | 'auto' | 'all' | 'none' | SheetSafeAreaEdge[];
9
+ /** CSS length or pixel number used for sheet container insets. */
10
+ type SheetInsetValue = string | number;
11
+ /** Extra container offsets applied around the sheet viewport. */
12
+ type SheetContainerOffset = Partial<Record<SheetSafeAreaEdge, SheetInsetValue>>;
9
13
  /** Runtime travel state emitted by sheet lifecycle events. */
10
14
  type SheetTravelStatus = 'idle' | 'entering' | 'exiting' | 'dragging' | 'settling';
11
15
  /** Built-in animation presets tuned for mobile WebViews. */
@@ -49,6 +53,18 @@ interface SheetOptions {
49
53
  contentPlacement?: SheetPlacement;
50
54
  /** Safe-area edges protected by the sheet viewport. Defaults to `auto`. */
51
55
  safeArea?: SheetSafeAreaMode;
56
+ /** Render as a floating sheet with detached edge rounding. */
57
+ detached?: boolean;
58
+ /** Extra top inset added to the sheet viewport, equivalent to Gorhom `topInset`. */
59
+ topInset?: SheetInsetValue;
60
+ /** Extra bottom inset added to the sheet viewport, equivalent to Gorhom `bottomInset`. */
61
+ bottomInset?: SheetInsetValue;
62
+ /** Extra left inset added to the sheet viewport. */
63
+ leftInset?: SheetInsetValue;
64
+ /** Extra right inset added to the sheet viewport. */
65
+ rightInset?: SheetInsetValue;
66
+ /** Extra per-edge container offsets, equivalent to Gorhom `containerOffset`. */
67
+ containerOffset?: SheetContainerOffset;
52
68
  /** Edge tracks that can dismiss the sheet. */
53
69
  tracks?: SheetTrack | SheetTrack[];
54
70
  /** Enables pointer, touch, trackpad, and wheel travel gestures. */
@@ -111,4 +127,4 @@ declare function setupSheet(element: HTMLElement, options?: Partial<SheetOptions
111
127
  onTravel?: (event: SheetTravelEvent) => void;
112
128
  }): () => void;
113
129
 
114
- export { type SheetActiveDetentChangeEvent, type SheetOptions, type SheetPresentedChangeEvent, type SheetSafeAreaEdge, type SheetSafeAreaMode, type SheetTravelEvent, setupSheet };
130
+ export { type SheetActiveDetentChangeEvent, type SheetContainerOffset, type SheetInsetValue, type SheetOptions, type SheetPresentedChangeEvent, type SheetSafeAreaEdge, type SheetSafeAreaMode, type SheetTravelEvent, setupSheet };
@@ -147,6 +147,11 @@ var CSS = `
147
147
  --cap-sheet-applied-safe-area-bottom: var(--cap-sheet-safe-area-bottom);
148
148
  --cap-sheet-applied-safe-area-left: var(--cap-sheet-safe-area-left);
149
149
  --cap-sheet-applied-safe-area-right: var(--cap-sheet-safe-area-right);
150
+ --cap-sheet-container-offset-top: 0em;
151
+ --cap-sheet-container-offset-bottom: 0em;
152
+ --cap-sheet-container-offset-left: 0em;
153
+ --cap-sheet-container-offset-right: 0em;
154
+ --cap-sheet-keyboard-offset: 0em;
150
155
  }
151
156
 
152
157
  @supports (height: 1dvh) {
@@ -175,10 +180,13 @@ cap-sheet-view {
175
180
  overscroll-behavior: none;
176
181
  contain: layout style;
177
182
  box-sizing: border-box;
178
- padding-block-start: var(--cap-sheet-applied-safe-area-top, 0em);
179
- padding-block-end: calc(var(--cap-sheet-applied-safe-area-bottom, 0em) + var(--cap-sheet-keyboard-offset, 0em));
180
- padding-inline-start: var(--cap-sheet-applied-safe-area-left, 0em);
181
- padding-inline-end: var(--cap-sheet-applied-safe-area-right, 0em);
183
+ padding-top: calc(var(--cap-sheet-applied-safe-area-top, 0em) + var(--cap-sheet-container-offset-top, 0em));
184
+ padding-bottom: calc(
185
+ var(--cap-sheet-applied-safe-area-bottom, 0em) + var(--cap-sheet-container-offset-bottom, 0em) +
186
+ var(--cap-sheet-keyboard-offset, 0em)
187
+ );
188
+ padding-left: calc(var(--cap-sheet-applied-safe-area-left, 0em) + var(--cap-sheet-container-offset-left, 0em));
189
+ padding-right: calc(var(--cap-sheet-applied-safe-area-right, 0em) + var(--cap-sheet-container-offset-right, 0em));
182
190
  }
183
191
 
184
192
  cap-sheet-view[hidden] {
@@ -223,6 +231,7 @@ cap-sheet-backdrop {
223
231
  }
224
232
 
225
233
  cap-sheet-content {
234
+ --cap-sheet-content-border-radius: var(--cap-sheet-radius) var(--cap-sheet-radius) 0 0;
226
235
  box-sizing: border-box;
227
236
  position: relative;
228
237
  display: block;
@@ -230,7 +239,7 @@ cap-sheet-content {
230
239
  max-height: 100%;
231
240
  color: CanvasText;
232
241
  background: var(--cap-sheet-surface);
233
- border-radius: var(--cap-sheet-radius) var(--cap-sheet-radius) 0 0;
242
+ border-radius: var(--cap-sheet-content-border-radius);
234
243
  box-shadow: var(--cap-sheet-shadow), var(--cap-sheet-edge-bleed-shadow, 0 0 0 0 transparent);
235
244
  overflow: auto;
236
245
  overscroll-behavior: contain;
@@ -241,27 +250,35 @@ cap-sheet-content {
241
250
  }
242
251
 
243
252
  cap-sheet-view[content-placement="top"] cap-sheet-content {
244
- border-radius: 0 0 var(--cap-sheet-radius) var(--cap-sheet-radius);
253
+ --cap-sheet-content-border-radius: 0 0 var(--cap-sheet-radius) var(--cap-sheet-radius);
245
254
  }
246
255
 
247
256
  cap-sheet-view[content-placement="left"] cap-sheet-content {
248
257
  width: min(88%, 28em);
249
258
  height: 100%;
250
259
  max-height: 100%;
251
- border-radius: 0 var(--cap-sheet-radius) var(--cap-sheet-radius) 0;
260
+ --cap-sheet-content-border-radius: 0 var(--cap-sheet-radius) var(--cap-sheet-radius) 0;
252
261
  }
253
262
 
254
263
  cap-sheet-view[content-placement="right"] cap-sheet-content {
255
264
  width: min(88%, 28em);
256
265
  height: 100%;
257
266
  max-height: 100%;
258
- border-radius: var(--cap-sheet-radius) 0 0 var(--cap-sheet-radius);
267
+ --cap-sheet-content-border-radius: var(--cap-sheet-radius) 0 0 var(--cap-sheet-radius);
259
268
  }
260
269
 
261
270
  cap-sheet-view[content-placement="center"] cap-sheet-content {
262
271
  width: min(90%, 30em);
263
272
  max-height: min(90%, 42em);
264
- border-radius: var(--cap-sheet-radius);
273
+ --cap-sheet-content-border-radius: var(--cap-sheet-radius);
274
+ }
275
+
276
+ cap-sheet-view[data-detached="true"] cap-sheet-content {
277
+ --cap-sheet-content-border-radius: var(--cap-sheet-detached-radius, var(--cap-sheet-radius));
278
+ }
279
+
280
+ cap-sheet-view[data-detached="true"] cap-sheet-content[data-cap-sheet-bleeds] {
281
+ --cap-sheet-edge-bleed-shadow: 0 0 0 0 transparent;
265
282
  }
266
283
 
267
284
  cap-sheet-bleeding-background {
@@ -515,6 +532,7 @@ function releaseThemeColorDimmer(documentRef) {
515
532
  var defaultOptions = {
516
533
  contentPlacement: "bottom",
517
534
  sheetRole: "dialog",
535
+ detached: false,
518
536
  safeArea: "auto",
519
537
  swipe: true,
520
538
  swipeDismissal: true,
@@ -545,21 +563,74 @@ function normalizeDetents(value) {
545
563
  if (Array.isArray(value)) return value.filter(Boolean);
546
564
  return parseList(value || null);
547
565
  }
566
+ var unitlessInsetPattern = /^-?(?:\d+(?:\.\d+)?|\.\d+)$/;
567
+ function normalizeInsetValue(value) {
568
+ return unitlessInsetPattern.test(value) ? `${value}px` : value;
569
+ }
570
+ function parseInset(value) {
571
+ const normalized = value?.trim();
572
+ return normalized ? normalizeInsetValue(normalized) : void 0;
573
+ }
574
+ function formatInsetValue(value) {
575
+ if (typeof value === "number") return Number.isFinite(value) ? `${value}px` : "0em";
576
+ const normalized = value?.trim();
577
+ return normalized ? normalizeInsetValue(normalized) : "0em";
578
+ }
579
+ function explicitInsetForEdge(options, edge) {
580
+ switch (edge) {
581
+ case "top":
582
+ return options.topInset;
583
+ case "bottom":
584
+ return options.bottomInset;
585
+ case "left":
586
+ return options.leftInset;
587
+ case "right":
588
+ return options.rightInset;
589
+ }
590
+ }
591
+ function containerInsetForEdge(options, edge) {
592
+ const values = [options.containerOffset?.[edge], explicitInsetForEdge(options, edge)].map(formatInsetValue).filter((value) => value !== "0em");
593
+ if (values.length === 0) return "0em";
594
+ if (values.length === 1) return values[0];
595
+ return `calc(${values.join(" + ")})`;
596
+ }
597
+ function hasOwnOption(options, key) {
598
+ return Object.prototype.hasOwnProperty.call(options, key);
599
+ }
600
+ function affectsDismissedOffset(options) {
601
+ return hasOwnOption(options, "contentPlacement") || hasOwnOption(options, "tracks") || hasOwnOption(options, "detents") || hasOwnOption(options, "safeArea") || hasOwnOption(options, "topInset") || hasOwnOption(options, "bottomInset") || hasOwnOption(options, "leftInset") || hasOwnOption(options, "rightInset") || hasOwnOption(options, "containerOffset");
602
+ }
548
603
  var safeAreaEdges = ["top", "bottom", "left", "right"];
549
604
  function parseSafeArea(value) {
550
605
  if (value === null) return void 0;
551
606
  const normalized = value.trim().toLowerCase();
552
- if (!normalized || normalized === "true" || normalized === "auto" || normalized === "all") return "auto";
607
+ if (!normalized || normalized === "auto") return "auto";
608
+ if (normalized === "true" || normalized === "all") return "all";
553
609
  if (normalized === "false" || normalized === "none" || normalized === "off") return "none";
554
610
  const edges = parseList(normalized).filter(
555
611
  (edge) => safeAreaEdges.includes(edge)
556
612
  );
557
613
  return edges.length > 0 ? edges : "auto";
558
614
  }
559
- function resolveSafeAreaEdges(value) {
615
+ function resolveAutoSafeAreaEdges(placement) {
616
+ switch (placement) {
617
+ case "bottom":
618
+ return ["bottom", "left", "right"];
619
+ case "top":
620
+ return ["top", "left", "right"];
621
+ case "left":
622
+ return ["top", "bottom", "left"];
623
+ case "right":
624
+ return ["top", "bottom", "right"];
625
+ case "center":
626
+ return safeAreaEdges;
627
+ }
628
+ }
629
+ function resolveSafeAreaEdges(value, placement) {
560
630
  if (value === false || value === "none") return [];
631
+ if (value === true || value === "all") return safeAreaEdges;
561
632
  if (Array.isArray(value)) return value.filter((edge) => safeAreaEdges.includes(edge));
562
- return safeAreaEdges;
633
+ return resolveAutoSafeAreaEdges(placement);
563
634
  }
564
635
  function readOptionsFromElement(root) {
565
636
  const placement = parsePlacement(root.getAttribute("content-placement"));
@@ -576,6 +647,11 @@ function readOptionsFromElement(root) {
576
647
  sheetRole: root.getAttribute("sheet-role") || defaultOptions.sheetRole,
577
648
  contentPlacement: placement,
578
649
  safeArea: parseSafeArea(root.getAttribute("safe-area")),
650
+ detached: parseBoolean(root.getAttribute("detached"), defaultOptions.detached),
651
+ topInset: parseInset(root.getAttribute("top-inset")),
652
+ bottomInset: parseInset(root.getAttribute("bottom-inset")),
653
+ leftInset: parseInset(root.getAttribute("left-inset")),
654
+ rightInset: parseInset(root.getAttribute("right-inset")),
579
655
  tracks: parseTracks(root.getAttribute("tracks"), placement === "center" ? "bottom" : placement),
580
656
  swipe: parseBoolean(root.getAttribute("swipe"), defaultOptions.swipe),
581
657
  swipeDismissal: parseBoolean(root.getAttribute("swipe-dismissal"), defaultOptions.swipeDismissal),
@@ -812,6 +888,11 @@ var SheetController = class {
812
888
  this.parts.content.setAttribute("aria-modal", attributeBoolean(this.options.inertOutside !== false));
813
889
  }
814
890
  this.linkAccessibleNames();
891
+ if (this.connected && !this.presented && this.parts.content && affectsDismissedOffset(options)) {
892
+ this.remeasure();
893
+ this.applyOffset(this.detentOffsetsPx[0] || this.hiddenOffsetPx, this.status);
894
+ this.updateDomState(false);
895
+ }
815
896
  this.registerStack();
816
897
  }
817
898
  /** Register a view, backdrop, content, or semantic part. */
@@ -966,12 +1047,29 @@ var SheetController = class {
966
1047
  const sign = trackSign(track);
967
1048
  const axis = isVerticalTrack(track) ? "y" : "x";
968
1049
  const rect = content.getBoundingClientRect();
1050
+ const viewRect = view?.getBoundingClientRect();
969
1051
  const size = axis === "y" ? rect.height : rect.width;
970
- this.hiddenOffsetPx = Math.max(size, 1) * sign;
1052
+ const transformedX = axis === "x" ? this.currentOffsetPx : 0;
1053
+ const transformedY = axis === "y" ? this.currentOffsetPx : 0;
1054
+ const contentRect = {
1055
+ top: rect.top - transformedY,
1056
+ right: rect.right - transformedX,
1057
+ bottom: rect.bottom - transformedY,
1058
+ left: rect.left - transformedX
1059
+ };
1060
+ let hiddenOffsetPx = Math.max(size, 1) * sign;
1061
+ if (viewRect) {
1062
+ if (track === "top") hiddenOffsetPx = viewRect.top - contentRect.bottom;
1063
+ if (track === "bottom") hiddenOffsetPx = viewRect.bottom - contentRect.top;
1064
+ if (track === "left") hiddenOffsetPx = viewRect.left - contentRect.right;
1065
+ if (track === "right") hiddenOffsetPx = viewRect.right - contentRect.left;
1066
+ }
1067
+ this.hiddenOffsetPx = Math.abs(hiddenOffsetPx) > 1 ? hiddenOffsetPx : sign;
971
1068
  const detents = normalizeDetents(this.options.detents);
972
1069
  const offsets = [this.hiddenOffsetPx];
1070
+ const measureContext = content;
973
1071
  for (const detent of detents) {
974
- const visible = measureCssLength(detent, content, axis);
1072
+ const visible = measureCssLength(detent, measureContext, axis);
975
1073
  const offset = Math.max(Math.abs(this.hiddenOffsetPx) - visible, 0) * sign;
976
1074
  offsets.push(offset);
977
1075
  }
@@ -1141,13 +1239,17 @@ var SheetController = class {
1141
1239
  applySafeArea() {
1142
1240
  const view = this.parts.view;
1143
1241
  if (!view) return;
1144
- const edges = new Set(resolveSafeAreaEdges(this.options.safeArea));
1242
+ const edges = new Set(
1243
+ resolveSafeAreaEdges(this.options.safeArea, this.options.contentPlacement || defaultOptions.contentPlacement)
1244
+ );
1145
1245
  view.dataset.safeArea = edges.size > 0 ? Array.from(edges).join(" ") : "none";
1246
+ view.dataset.detached = this.options.detached ? "true" : "false";
1146
1247
  for (const edge of safeAreaEdges) {
1147
1248
  view.style.setProperty(
1148
1249
  `--cap-sheet-applied-safe-area-${edge}`,
1149
1250
  edges.has(edge) ? `var(--cap-sheet-safe-area-${edge})` : "0em"
1150
1251
  );
1252
+ view.style.setProperty(`--cap-sheet-container-offset-${edge}`, containerInsetForEdge(this.options, edge));
1151
1253
  }
1152
1254
  }
1153
1255
  addGlobalListeners() {
@@ -1445,12 +1547,17 @@ var observed = [
1445
1547
  "default-active-detent",
1446
1548
  "default-presented",
1447
1549
  "detents",
1550
+ "detached",
1448
1551
  "focus-trap",
1449
1552
  "inert-outside",
1450
1553
  "native-edge-swipe-prevention",
1451
1554
  "native-focus-scroll-prevention",
1452
1555
  "presented",
1453
1556
  "restore-focus",
1557
+ "top-inset",
1558
+ "bottom-inset",
1559
+ "left-inset",
1560
+ "right-inset",
1454
1561
  "safe-area",
1455
1562
  "sheet-role",
1456
1563
  "stack",
@@ -1565,12 +1672,17 @@ function readChangedOptionsFromElement(element, name) {
1565
1672
  "default-active-detent": ["defaultActiveDetent"],
1566
1673
  "default-presented": ["defaultPresented"],
1567
1674
  detents: ["detents"],
1675
+ detached: ["detached"],
1568
1676
  "focus-trap": ["focusTrap"],
1569
1677
  "inert-outside": ["inertOutside"],
1570
1678
  "native-edge-swipe-prevention": ["nativeEdgeSwipePrevention"],
1571
1679
  "native-focus-scroll-prevention": ["nativeFocusScrollPrevention"],
1572
1680
  presented: ["presented"],
1573
1681
  "restore-focus": ["restoreFocus"],
1682
+ "top-inset": ["topInset"],
1683
+ "bottom-inset": ["bottomInset"],
1684
+ "left-inset": ["leftInset"],
1685
+ "right-inset": ["rightInset"],
1574
1686
  "safe-area": ["safeArea"],
1575
1687
  "sheet-role": ["sheetRole"],
1576
1688
  stack: ["stack"],
@@ -1587,6 +1699,19 @@ function readChangedOptionsFromElement(element, name) {
1587
1699
  }
1588
1700
  return changed;
1589
1701
  }
1702
+ function formatInsetAttribute(value) {
1703
+ if (typeof value === "number") return Number.isFinite(value) ? `${value}px` : void 0;
1704
+ const normalized = value.trim();
1705
+ return normalized || void 0;
1706
+ }
1707
+ function combineInsetAttributes(...values) {
1708
+ const parts = values.flatMap((value) => {
1709
+ const attributeValue = value === void 0 ? void 0 : formatInsetAttribute(value);
1710
+ return attributeValue ? [attributeValue] : [];
1711
+ });
1712
+ if (parts.length === 0) return void 0;
1713
+ return parts.length === 1 ? parts[0] : `calc(${parts.join(" + ")})`;
1714
+ }
1590
1715
  function applySheetOptions(element, options) {
1591
1716
  if (options.contentPlacement) element.setAttribute("content-placement", options.contentPlacement);
1592
1717
  if (options.detents !== void 0) {
@@ -1598,7 +1723,6 @@ function applySheetOptions(element, options) {
1598
1723
  }
1599
1724
  if (options.defaultPresented !== void 0)
1600
1725
  element.setAttribute("default-presented", String(options.defaultPresented));
1601
- if (options.presented !== void 0) element.toggleAttribute("presented", options.presented);
1602
1726
  if (options.sheetRole) element.setAttribute("sheet-role", options.sheetRole);
1603
1727
  if (options.safeArea !== void 0) {
1604
1728
  element.setAttribute(
@@ -1609,7 +1733,23 @@ function applySheetOptions(element, options) {
1609
1733
  if (options.stack) element.setAttribute("stack", options.stack);
1610
1734
  if (options.tracks)
1611
1735
  element.setAttribute("tracks", Array.isArray(options.tracks) ? options.tracks.join(" ") : options.tracks);
1736
+ for (const [key, attr, edge] of [
1737
+ ["topInset", "top-inset", "top"],
1738
+ ["bottomInset", "bottom-inset", "bottom"],
1739
+ ["leftInset", "left-inset", "left"],
1740
+ ["rightInset", "right-inset", "right"]
1741
+ ]) {
1742
+ const hasEdgeInset = Object.prototype.hasOwnProperty.call(options, key);
1743
+ const hasContainerOffset = Object.prototype.hasOwnProperty.call(options, "containerOffset");
1744
+ const attributeValue = combineInsetAttributes(options[key], options.containerOffset?.[edge]);
1745
+ if (attributeValue !== void 0) {
1746
+ element.setAttribute(attr, attributeValue);
1747
+ } else if (hasEdgeInset || hasContainerOffset) {
1748
+ element.removeAttribute(attr);
1749
+ }
1750
+ }
1612
1751
  for (const [key, attr] of [
1752
+ ["detached", "detached"],
1613
1753
  ["swipe", "swipe"],
1614
1754
  ["swipeDismissal", "swipe-dismissal"],
1615
1755
  ["swipeOvershoot", "swipe-overshoot"],
@@ -1628,6 +1768,7 @@ function applySheetOptions(element, options) {
1628
1768
  if (options.themeColorDimming !== void 0) {
1629
1769
  element.setAttribute("theme-color-dimming", options.themeColorDimming === false ? "false" : "auto");
1630
1770
  }
1771
+ if (options.presented !== void 0) element.toggleAttribute("presented", options.presented);
1631
1772
  }
1632
1773
 
1633
1774
  // src/components/sheet-actions.ts