lutra 0.1.49 → 0.1.51

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.
@@ -63,16 +63,17 @@
63
63
  padding: 0;
64
64
  border: var(--modal-border-size) var(--modal-border-style) var(--modal-border-color);
65
65
  width: var(--modal-width, fit-content);
66
+ min-width: var(--modal-min-width, auto);
66
67
  border-radius: var(--modal-border-radius, var(--surface-border-radius));
67
68
  background: var(--modal-background, var(--surface-background));
68
69
  color: var(--text-color-p);
69
70
  max-width: min(
70
71
  var(--modal-max-width, 40rem),
71
- calc(100vw - 2rem - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px))
72
+ calc(100svw - 2rem - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px))
72
73
  );
73
74
  max-height: min(
74
- var(--modal-max-height, 80vh),
75
- calc(100vh - 2rem - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px))
75
+ var(--modal-max-height, 80svh),
76
+ calc(100svh - 2rem - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px))
76
77
  );
77
78
  box-shadow: var(--modal-shadow, var(--surface-shadow));
78
79
  }
@@ -82,11 +83,6 @@
82
83
  grid-template-rows: auto 1fr;
83
84
  }
84
85
 
85
- .Dialog::backdrop {
86
- background: var(--scrim-background);
87
- backdrop-filter: var(--scrim-backdrop-filter);
88
- }
89
-
90
86
  .DialogHeader {
91
87
  padding: var(--modal-padding-block) var(--modal-padding-inline);
92
88
  border-bottom: var(--modal-border-size) var(--modal-border-style) var(--modal-border-color);
@@ -45,6 +45,7 @@
45
45
  closeOnScrim = true,
46
46
  dismissOnEsc = true,
47
47
  width,
48
+ minWidth,
48
49
  maxWidth,
49
50
  maxHeight,
50
51
  onclose,
@@ -78,6 +79,8 @@
78
79
  dismissOnEsc?: boolean;
79
80
  /** Width of the modal */
80
81
  width?: string;
82
+ /** Minimum width of the modal */
83
+ minWidth?: string;
81
84
  /** Maximum width of the modal */
82
85
  maxWidth?: string;
83
86
  /** Maximum height of the modal */
@@ -178,6 +181,7 @@
178
181
  oncancel={handleDialogCancel}
179
182
  onclick={handleBackdropClick}
180
183
  style:--modal-width={width}
184
+ style:--modal-min-width={minWidth}
181
185
  style:--modal-max-width={maxWidth}
182
186
  style:--modal-max-height={maxHeight}
183
187
  >
@@ -221,13 +225,14 @@
221
225
  border-radius: var(--modal-border-radius, var(--surface-border-radius));
222
226
  box-shadow: var(--modal-shadow, var(--surface-shadow));
223
227
  width: var(--modal-width, fit-content);
228
+ min-width: var(--modal-min-width, auto);
224
229
  max-width: min(
225
230
  var(--modal-max-width, 40rem),
226
- calc(100vw - 2rem - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px))
231
+ calc(100svw - 2rem - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px))
227
232
  );
228
233
  max-height: min(
229
- var(--modal-max-height, 80vh),
230
- calc(100vh - 2rem - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px))
234
+ var(--modal-max-height, 80svh),
235
+ calc(100svh - 2rem - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px))
231
236
  );
232
237
  overflow: hidden;
233
238
  gap: var(--modal-gap);
@@ -30,6 +30,8 @@ type $$ComponentProps = {
30
30
  dismissOnEsc?: boolean;
31
31
  /** Width of the modal */
32
32
  width?: string;
33
+ /** Minimum width of the modal */
34
+ minWidth?: string;
33
35
  /** Maximum width of the modal */
34
36
  maxWidth?: string;
35
37
  /** Maximum height of the modal */
@@ -66,8 +66,6 @@
66
66
  class="ModalContent {shape}"
67
67
  class:contained
68
68
  class:unstyled
69
- role="dialog"
70
- aria-modal="true"
71
69
  aria-labelledby={titleId}
72
70
  >
73
71
  <div class="ModalContentArea">
@@ -112,6 +110,7 @@
112
110
  grid-template-rows: 1fr auto;
113
111
  gap: var(--modal-gap);
114
112
  width: var(--modal-width, fit-content);
113
+ min-width: var(--modal-min-width, auto);
115
114
  max-width: min(
116
115
  var(--modal-max-width, 40rem),
117
116
  calc(100svw - 2rem - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px))
@@ -24,6 +24,8 @@ export type ModalOptions = {
24
24
  buttons?: ModalButton[] | 'ok-cancel' | 'none';
25
25
  /** Width of the modal */
26
26
  width?: string;
27
+ /** Minimum width of the modal */
28
+ minWidth?: string;
27
29
  /** Maximum width of the modal */
28
30
  maxWidth?: string;
29
31
  /** Maximum height of the modal */
@@ -38,14 +40,12 @@ export type ModalOptions = {
38
40
  showScrim?: boolean;
39
41
  /** Whether clicking the scrim closes the modal */
40
42
  closeOnScrim?: boolean;
41
- /** Whether to trap focus within the modal */
42
- trapFocus?: boolean;
43
43
  /** Whether pressing Escape closes the modal */
44
44
  dismissOnEsc?: boolean;
45
45
  /** Callback when the modal closes */
46
- onClose?: () => void;
46
+ onclose?: () => void;
47
47
  /** Callback when the modal opens */
48
- onOpen?: () => void;
48
+ onopen?: () => void;
49
49
  };
50
50
  export declare const cancelButton: ModalButton;
51
51
  export declare const okButton: ModalButton;
@@ -78,21 +78,23 @@
78
78
  display: grid;
79
79
  grid-template-columns: 1fr;
80
80
  gap: var(--toast-gap, var(--space-sm));
81
-
82
- /* Surface styling - consistent with Popover and Modal */
83
81
  background: var(--toast-background, var(--surface-background));
84
82
  border: var(--toast-border, var(--surface-border));
85
83
  border-radius: var(--toast-border-radius, var(--surface-border-radius));
86
84
  box-shadow: var(--toast-shadow, var(--surface-shadow));
87
-
88
85
  padding-block: var(--toast-padding-block, var(--space-md));
89
86
  padding-inline: var(--toast-padding-inline, var(--space-lg));
90
87
  min-width: var(--toast-min-width, 20rem);
91
88
  max-width: var(--toast-max-width, 28rem);
92
-
93
89
  animation: toast-enter 0.2s ease-out;
94
90
  }
95
91
 
92
+ @media (prefers-reduced-motion: reduce) {
93
+ .Toast {
94
+ animation: none;
95
+ }
96
+ }
97
+
96
98
  .Toast.has-icon {
97
99
  grid-template-columns: auto 1fr;
98
100
  }
@@ -135,21 +137,4 @@
135
137
  align-items: center;
136
138
  gap: var(--space-xs);
137
139
  }
138
-
139
- @keyframes toast-enter {
140
- from {
141
- opacity: 0;
142
- translate: 0 0.5rem;
143
- }
144
- to {
145
- opacity: 1;
146
- translate: 0 0;
147
- }
148
- }
149
-
150
- @media (prefers-reduced-motion: reduce) {
151
- .Toast {
152
- animation: none;
153
- }
154
- }
155
140
  </style>
@@ -108,17 +108,6 @@
108
108
  animation: toast-enter 0.2s ease-out;
109
109
  }
110
110
 
111
- @keyframes toast-enter {
112
- from {
113
- opacity: 0;
114
- translate: 0 0.5rem;
115
- }
116
- to {
117
- opacity: 1;
118
- translate: 0 0;
119
- }
120
- }
121
-
122
111
  @media (prefers-reduced-motion: reduce) {
123
112
  .ToastItem {
124
113
  animation: none;
@@ -3,13 +3,13 @@ import ModalContent from './ModalContent.svelte';
3
3
  import { cancelButton, okButton } from './ModalTypes.js';
4
4
  let modalCount = $state(0);
5
5
  let activeElement = null;
6
- function lockScroll() {
6
+ function trackModalOpen() {
7
7
  if (modalCount === 0) {
8
8
  activeElement = document.activeElement;
9
9
  }
10
10
  modalCount++;
11
11
  }
12
- function unlockScroll() {
12
+ function trackModalClose() {
13
13
  modalCount--;
14
14
  if (modalCount === 0) {
15
15
  activeElement?.focus();
@@ -56,6 +56,8 @@ export function openModal(opts) {
56
56
  // Apply custom styles
57
57
  if (opts.width)
58
58
  dialog.style.setProperty('--modal-width', opts.width);
59
+ if (opts.minWidth)
60
+ dialog.style.setProperty('--modal-min-width', opts.minWidth);
59
61
  if (opts.maxWidth)
60
62
  dialog.style.setProperty('--modal-max-width', opts.maxWidth);
61
63
  if (opts.maxHeight)
@@ -99,8 +101,8 @@ export function openModal(opts) {
99
101
  dialog.addEventListener('close', () => {
100
102
  unmount(component);
101
103
  dialog.remove();
102
- unlockScroll();
103
- opts.onClose?.();
104
+ trackModalClose();
105
+ opts.onclose?.();
104
106
  });
105
107
  dialog.addEventListener('cancel', (e) => {
106
108
  if (opts.dismissOnEsc === false) {
@@ -114,8 +116,8 @@ export function openModal(opts) {
114
116
  });
115
117
  // Add to DOM and show
116
118
  document.body.appendChild(dialog);
117
- lockScroll();
118
- opts.onOpen?.();
119
+ trackModalOpen();
120
+ opts.onopen?.();
119
121
  dialog.showModal();
120
122
  return { id, close };
121
123
  }
@@ -483,6 +483,7 @@
483
483
  @property --modal-padding-inline { syntax: "<length>"; inherits: true; initial-value: 24px; }
484
484
  @property --modal-padding-block { syntax: "<length>"; inherits: true; initial-value: 24px; }
485
485
  @property --modal-width { syntax: "*"; inherits: true; initial-value: fit-content; }
486
+ @property --modal-min-width { syntax: "*"; inherits: true; initial-value: auto; }
486
487
  @property --modal-max-width { syntax: "*"; inherits: true; initial-value: 40rem; }
487
488
  @property --modal-max-height { syntax: "*"; inherits: true; initial-value: 80svh; }
488
489
  @property --modal-gap { syntax: "<length>"; inherits: true; initial-value: 0px; }
@@ -362,13 +362,15 @@ input:disabled, textarea:disabled, select:disabled {
362
362
  * Dialog Backdrop (shared by Modal and ProgrammaticModal)
363
363
  */
364
364
  dialog.Modal::backdrop,
365
- dialog.ProgrammaticModal::backdrop {
365
+ dialog.ProgrammaticModal::backdrop,
366
+ dialog.Dialog::backdrop {
366
367
  background: var(--scrim-background);
367
368
  backdrop-filter: var(--scrim-backdrop-filter);
368
369
  }
369
370
 
370
371
  dialog.Modal.noScrim::backdrop,
371
- dialog.ProgrammaticModal.noScrim::backdrop {
372
+ dialog.ProgrammaticModal.noScrim::backdrop,
373
+ dialog.Dialog.noScrim::backdrop {
372
374
  background: transparent;
373
375
  backdrop-filter: none;
374
376
  }
@@ -389,3 +391,17 @@ dialog.ProgrammaticModal {
389
391
  dialog.ProgrammaticModal .ModalContentWrapper {
390
392
  display: contents;
391
393
  }
394
+
395
+ /**
396
+ * Toast Animation (shared)
397
+ */
398
+ @keyframes toast-enter {
399
+ from {
400
+ opacity: 0;
401
+ translate: 0 0.5rem;
402
+ }
403
+ to {
404
+ opacity: 1;
405
+ translate: 0 0;
406
+ }
407
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lutra",
3
- "version": "0.1.49",
3
+ "version": "0.1.51",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "bump-and-publish:patch": "pnpm version:patch && pnpm build && npm publish",