@juspay/svelte-ui-components 2.85.0 → 2.86.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.
@@ -1,3 +1,24 @@
1
+ <script lang="ts" module>
2
+ // Reference-counted so two Sheets open at once (or a Sheet nested inside
3
+ // another scroll-locking surface) don't have the second one's close clobber
4
+ // the first one's still-needed lock.
5
+ let scrollLockCount = 0;
6
+
7
+ function lockScroll() {
8
+ if (scrollLockCount === 0) {
9
+ document.body.style.overflow = 'hidden';
10
+ }
11
+ scrollLockCount += 1;
12
+ }
13
+
14
+ function unlockScroll() {
15
+ scrollLockCount = Math.max(0, scrollLockCount - 1);
16
+ if (scrollLockCount === 0) {
17
+ document.body.style.overflow = '';
18
+ }
19
+ }
20
+ </script>
21
+
1
22
  <script lang="ts">
2
23
  import type { SheetProperties } from './properties';
3
24
  import { fly, fade } from 'svelte/transition';
@@ -9,6 +30,7 @@
9
30
  side = 'right',
10
31
  title,
11
32
  showOverlay = true,
33
+ dismissOnOutsideClick = showOverlay,
12
34
  showCloseButton = true,
13
35
  testId,
14
36
  content,
@@ -41,7 +63,10 @@
41
63
  }
42
64
 
43
65
  function handleOverlayClick(event: MouseEvent) {
44
- if (event.target === overlayDiv) {
66
+ // Gate dismissal on dismissOnOutsideClick explicitly, not on the overlay's
67
+ // pointer-events alone: a visible-but-non-dismissible overlay still needs to
68
+ // catch (and swallow) the click to block the page underneath, without closing.
69
+ if (event.target === overlayDiv && dismissOnOutsideClick) {
45
70
  close();
46
71
  }
47
72
  }
@@ -71,14 +96,6 @@
71
96
  }
72
97
  }
73
98
 
74
- function lockScroll() {
75
- document.body.style.overflow = 'hidden';
76
- }
77
-
78
- function unlockScroll() {
79
- document.body.style.overflow = '';
80
- }
81
-
82
99
  function scrollLockAction(_node: HTMLElement) {
83
100
  lockScroll();
84
101
  tick().then(() => {
@@ -110,7 +127,10 @@
110
127
  <div
111
128
  bind:this={overlayDiv}
112
129
  use:scrollLockAction
113
- class="sheet-overlay {showOverlay ? 'overlay-active' : 'overlay-inactive'} {classes ?? ''}"
130
+ class="sheet-overlay {showOverlay ? 'overlay-visible' : 'overlay-invisible'} {showOverlay ||
131
+ dismissOnOutsideClick
132
+ ? 'overlay-interactive'
133
+ : 'overlay-noninteractive'} {classes ?? ''}"
114
134
  onclick={handleOverlayClick}
115
135
  onkeydown={handleKeyDown}
116
136
  role="button"
@@ -170,12 +190,19 @@
170
190
  -webkit-tap-highlight-color: transparent;
171
191
  }
172
192
 
173
- .overlay-active {
193
+ .overlay-visible {
174
194
  background-color: var(--sheet-overlay-background, #00000066);
195
+ }
196
+
197
+ .overlay-invisible {
198
+ background-color: transparent;
199
+ }
200
+
201
+ .overlay-interactive {
175
202
  pointer-events: auto;
176
203
  }
177
204
 
178
- .overlay-inactive {
205
+ .overlay-noninteractive {
179
206
  pointer-events: none;
180
207
  }
181
208
 
@@ -190,39 +217,44 @@
190
217
  outline: none;
191
218
  }
192
219
 
220
+ /* --sheet-top/-right/-bottom/-left all default to the previous hardcoded
221
+ edge-to-edge values below, so an unconfigured Sheet renders unchanged.
222
+ Overriding one (e.g. --sheet-top to clear a fixed header, or --sheet-bottom:
223
+ auto to size to content) turns the panel from an edge-to-edge slide-in into
224
+ an anchored floating panel, without needing a different component. */
193
225
  .sheet-panel.left,
194
226
  .sheet-panel.right {
195
- top: 0;
196
- bottom: 0;
227
+ top: var(--sheet-top, 0);
228
+ bottom: var(--sheet-bottom, 0);
197
229
  width: var(--sheet-width, 400px);
198
230
  max-width: var(--sheet-max-width, 100vw);
199
231
  }
200
232
 
201
233
  .sheet-panel.left {
202
- left: 0;
234
+ left: var(--sheet-left, 0);
203
235
  border-right: var(--sheet-border, none);
204
236
  }
205
237
 
206
238
  .sheet-panel.right {
207
- right: 0;
239
+ right: var(--sheet-right, 0);
208
240
  border-left: var(--sheet-border, none);
209
241
  }
210
242
 
211
243
  .sheet-panel.top,
212
244
  .sheet-panel.bottom {
213
- left: 0;
214
- right: 0;
245
+ left: var(--sheet-left, 0);
246
+ right: var(--sheet-right, 0);
215
247
  height: var(--sheet-height, 300px);
216
248
  max-height: var(--sheet-max-height, 100vh);
217
249
  }
218
250
 
219
251
  .sheet-panel.top {
220
- top: 0;
252
+ top: var(--sheet-top, 0);
221
253
  border-bottom: var(--sheet-border, none);
222
254
  }
223
255
 
224
256
  .sheet-panel.bottom {
225
- bottom: 0;
257
+ bottom: var(--sheet-bottom, 0);
226
258
  border-top: var(--sheet-border, none);
227
259
  }
228
260
 
@@ -9,6 +9,14 @@ export type OptionalSheetProperties = {
9
9
  side?: SheetSide;
10
10
  title?: string;
11
11
  showOverlay?: boolean;
12
+ /**
13
+ * Whether clicking outside the panel dismisses the sheet, independent of
14
+ * `showOverlay`'s visual tint. Defaults to mirroring `showOverlay`, so
15
+ * existing behavior is unchanged unless this is set explicitly. Set this to
16
+ * `true` alongside `showOverlay={false}` for a dismissible sheet with no
17
+ * dimming backdrop — e.g. an anchored dropdown-style panel.
18
+ */
19
+ dismissOnOutsideClick?: boolean;
12
20
  showCloseButton?: boolean;
13
21
  testId?: string;
14
22
  footer?: Snippet;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/svelte-ui-components",
3
- "version": "2.85.0",
3
+ "version": "2.86.0",
4
4
  "description": "A themeable Svelte 5 UI component library with CSS custom property driven styling",
5
5
  "keywords": [
6
6
  "svelte",