@rcarls/rc-dialog 0.3.1 → 0.4.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.
- package/README.md +68 -21
- package/dist/custom-elements.json +187 -31
- package/dist/{rc-dialog-Dpj3ERfv.js → rc-dialog-D9jUBKJn.js} +111 -49
- package/dist/rc-dialog-D9jUBKJn.js.map +1 -0
- package/dist/rc-dialog-define.js +1 -1
- package/dist/rc-dialog.js +1 -1
- package/dist/types/packages/rc-dialog/src/rc-dialog.d.ts +49 -6
- package/package.json +1 -1
- package/dist/rc-dialog-Dpj3ERfv.js.map +0 -1
package/README.md
CHANGED
|
@@ -23,7 +23,9 @@ import { RCDialog } from '@rcarls/rc-dialog'; // named class export
|
|
|
23
23
|
|
|
24
24
|
## Basic usage
|
|
25
25
|
|
|
26
|
-
Place a `<dialog>` element directly inside `<rc-dialog>`. The inner `<dialog>` must have
|
|
26
|
+
Place a `<dialog>` element directly inside `<rc-dialog>`. The inner `<dialog>` must have
|
|
27
|
+
`aria-labelledby` or `aria-label` to satisfy the
|
|
28
|
+
[WAI-ARIA Dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/).
|
|
27
29
|
|
|
28
30
|
```html
|
|
29
31
|
<rc-dialog id="my-dialog">
|
|
@@ -45,15 +47,17 @@ Place a `<dialog>` element directly inside `<rc-dialog>`. The inner `<dialog>` m
|
|
|
45
47
|
|
|
46
48
|
| Property | Attribute | Type | Default | Description |
|
|
47
49
|
|---|---|---|---|---|
|
|
48
|
-
| `open` | `open` | `boolean` |
|
|
50
|
+
| `open` | `open` | `boolean` | None | Controlled open state. Setting to `true`/`false` opens/closes the dialog silently (no `rc-dialog-toggle` event). Reads the inner `<dialog>.open` value. |
|
|
49
51
|
| `defaultOpen` | `default-open` | `boolean` | `false` | Uncontrolled initial open state. The component takes ownership after initialization. |
|
|
50
|
-
| `modal` |
|
|
52
|
+
| `modal` | None | `boolean` | `true` | Whether controlled `open` / `defaultOpen` opens as modal (`showModal`) or non-modal (`show`). No effect on direct `showModal()` / `show()` calls. JS property only; no attribute. |
|
|
51
53
|
| `movable` | `movable` | `boolean` | `false` | Enable drag-to-move. Named `movable` (not `draggable`) to avoid colliding with the HTML `draggable` attribute. |
|
|
52
|
-
| `moveHandle` | `move-handle` | `string` | `''` | CSS selector for the drag handle within the inner `<dialog>` (
|
|
54
|
+
| `moveHandle` | `move-handle` | `string` | `''` | CSS selector for the drag handle within the inner `<dialog>` (for example, `'.titlebar'`). Defaults to the whole dialog. |
|
|
53
55
|
| `moveBounds` | `move-bounds` | `'viewport' \| 'parent'` | `'viewport'` | Constrains drag within the viewport or the nearest positioned ancestor. |
|
|
54
56
|
| `moveStep` | `move-step` | `number` | `4` | Keyboard arrow-key step in px when moving. Shift multiplies by 10×. |
|
|
55
57
|
| `resize` | `resize` | `'none' \| 'both' \| 'horizontal' \| 'vertical'` | `'none'` | Enables edge/corner resizing, mirroring CSS `resize` semantics. |
|
|
56
|
-
| `
|
|
58
|
+
| `resizeOrigin` | `resize-origin` | `'' \| 'top' \| 'right' \| 'bottom' \| 'left' \| 'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right'` | `''` | Constrains fallback edge detection or supplies the default origin for explicit handles. Empty keeps free edge detection. |
|
|
59
|
+
| `resizeHandle` | `resize-handle` | `string` | `''` | CSS selector for explicit resize handles within the inner `<dialog>`. Matching handles receive pointer and keyboard resize behavior. |
|
|
60
|
+
| `resizeThreshold` | `resize-threshold` | `number` | `8` | Edge hit-test band in px (straddles the border, half inside and half outside). |
|
|
57
61
|
| `resizeStep` | `resize-step` | `number` | `4` | Keyboard arrow-key step in px when resizing. Shift multiplies by 10×. |
|
|
58
62
|
| `closedBy` | `closed-by` | `'any' \| 'closerequest' \| 'none' \| ''` | `''` | Proxied to the inner `<dialog closedby="...">` attribute (Chrome 134+, Safari 18.4+, Firefox 139+). `'any'` = Escape or backdrop click; `'closerequest'` = Escape only; `'none'` = programmatic only. |
|
|
59
63
|
| `lightDismiss` | `light-dismiss` | `boolean` | `false` | JS fallback for backdrop-click dismissal. Detects clicks whose target is the `<dialog>` element itself and calls `requestClose()`. Works in all browsers alongside or instead of `closed-by`. |
|
|
@@ -81,14 +85,21 @@ returnValue: string // The return value set when the dialog last closed.
|
|
|
81
85
|
|
|
82
86
|
| Event | Cancelable | Detail | Description |
|
|
83
87
|
|---|---|---|---|
|
|
84
|
-
| `rc-dialog-open` | No |
|
|
88
|
+
| `rc-dialog-open` | No | None | Fired when the dialog opens via `showModal()` or `show()`. |
|
|
85
89
|
| `rc-dialog-toggle` | No | `{ open: boolean, returnValue: string }` | Fired when user or native interaction changes the open state. Not fired on silent host writes (`open` property). |
|
|
86
90
|
| `rc-dialog-request-close` | **Yes** | `{ returnValue: string }` | Fired before close (Escape, backdrop click, or `requestClose()`). Call `preventDefault()` to block. |
|
|
87
|
-
| `rc-dialog-cancel` | No |
|
|
91
|
+
| `rc-dialog-cancel` | No | None | Fired after `rc-dialog-request-close` when the close was not prevented. Backward-compatible alias. |
|
|
88
92
|
| `rc-dialog-close` | No | `{ returnValue: string }` | Fired after the dialog has closed. |
|
|
89
93
|
|
|
90
94
|
---
|
|
91
95
|
|
|
96
|
+
### Theming
|
|
97
|
+
|
|
98
|
+
Set `--rc-dialog-scrim` on `<rc-dialog>` or a theme scope to customize the modal
|
|
99
|
+
backdrop color. Theme packages consume this token in their `::backdrop` styles.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
92
103
|
## Examples
|
|
93
104
|
|
|
94
105
|
### Movable dialog with a drag handle
|
|
@@ -105,7 +116,8 @@ returnValue: string // The return value set when the dialog last closed.
|
|
|
105
116
|
</rc-dialog>
|
|
106
117
|
```
|
|
107
118
|
|
|
108
|
-
Drag the `.titlebar` to reposition. Focus the titlebar and use **Arrow keys** to move it
|
|
119
|
+
Drag the `.titlebar` to reposition. Focus the titlebar and use **Arrow keys** to move it
|
|
120
|
+
(Shift = 10× step).
|
|
109
121
|
|
|
110
122
|
### Movable + resizable
|
|
111
123
|
|
|
@@ -117,7 +129,30 @@ Drag the `.titlebar` to reposition. Focus the titlebar and use **Arrow keys** to
|
|
|
117
129
|
</rc-dialog>
|
|
118
130
|
```
|
|
119
131
|
|
|
120
|
-
All
|
|
132
|
+
All eight resize handles are active (top, right, bottom, left, and the four corners).
|
|
133
|
+
Opposite-edge handles anchor the far side and move `left` or `top`, mirroring OS-window resize
|
|
134
|
+
semantics. A small keyboard-accessible resize button is injected at the bottom-right corner.
|
|
135
|
+
|
|
136
|
+
### Explicit resize handle
|
|
137
|
+
|
|
138
|
+
```html
|
|
139
|
+
<rc-dialog id="sheet-like" resize="vertical" resize-origin="top" resize-handle=".resize-handle">
|
|
140
|
+
<dialog aria-labelledby="sheet-title">
|
|
141
|
+
<button
|
|
142
|
+
type="button"
|
|
143
|
+
class="resize-handle"
|
|
144
|
+
data-rc-dialog-resize-axis="y"
|
|
145
|
+
data-rc-dialog-resize-origin="top"
|
|
146
|
+
aria-label="Resize"
|
|
147
|
+
></button>
|
|
148
|
+
<h2 id="sheet-title">Filters</h2>
|
|
149
|
+
</dialog>
|
|
150
|
+
</rc-dialog>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Use `data-rc-dialog-resize-axis="x|y|both"` and
|
|
154
|
+
`data-rc-dialog-resize-origin="top|right|bottom|left|top-left|..."`
|
|
155
|
+
on individual handles to override the host resize direction or origin.
|
|
121
156
|
|
|
122
157
|
### Minimal / no-header dialog
|
|
123
158
|
|
|
@@ -138,7 +173,8 @@ No titlebar or footer structure is required. Any layout is valid.
|
|
|
138
173
|
|
|
139
174
|
### Alert / confirm dialog
|
|
140
175
|
|
|
141
|
-
Use `role="alertdialog"` with `aria-describedby` pointing to the message text. Assistive
|
|
176
|
+
Use `role="alertdialog"` with `aria-describedby` pointing to the message text. Assistive
|
|
177
|
+
technology treats this with higher urgency.
|
|
142
178
|
|
|
143
179
|
```html
|
|
144
180
|
<rc-dialog id="confirm">
|
|
@@ -157,7 +193,8 @@ Use `role="alertdialog"` with `aria-describedby` pointing to the message text. A
|
|
|
157
193
|
|
|
158
194
|
### Native form integration
|
|
159
195
|
|
|
160
|
-
`<form method="dialog">` submits to the dialog: the submit button's `value` becomes
|
|
196
|
+
`<form method="dialog">` submits to the dialog: the submit button's `value` becomes
|
|
197
|
+
`returnValue`, and the dialog closes without JavaScript.
|
|
161
198
|
|
|
162
199
|
```html
|
|
163
200
|
<rc-dialog id="dlg">
|
|
@@ -189,7 +226,7 @@ Use `role="alertdialog"` with `aria-describedby` pointing to the message text. A
|
|
|
189
226
|
<button onclick="document.querySelector('#dlg').requestClose('cancel')">✕</button>
|
|
190
227
|
</div>
|
|
191
228
|
<textarea id="note" rows="5"></textarea>
|
|
192
|
-
<p id="warning" hidden role="alert">Unsaved changes
|
|
229
|
+
<p id="warning" hidden role="alert">Unsaved changes; save or discard first.</p>
|
|
193
230
|
<div class="footer">
|
|
194
231
|
<button onclick="note.value=''; dlg.close('discard')">Discard</button>
|
|
195
232
|
<button onclick="dlg.close('save')">Save</button>
|
|
@@ -219,7 +256,9 @@ Use `role="alertdialog"` with `aria-describedby` pointing to the message text. A
|
|
|
219
256
|
</rc-dialog>
|
|
220
257
|
```
|
|
221
258
|
|
|
222
|
-
`closed-by="any"` delegates to the browser's native light-dismiss on supporting browsers.
|
|
259
|
+
`closed-by="any"` delegates to the browser's native light-dismiss on supporting browsers.
|
|
260
|
+
`light-dismiss` adds a JS click-on-backdrop fallback that works everywhere and routes through
|
|
261
|
+
`requestClose()`, so close guards still apply.
|
|
223
262
|
|
|
224
263
|
---
|
|
225
264
|
|
|
@@ -227,20 +266,26 @@ Use `role="alertdialog"` with `aria-describedby` pointing to the message text. A
|
|
|
227
266
|
|
|
228
267
|
`<rc-dialog>` delegates entirely to the native `<dialog>` element:
|
|
229
268
|
|
|
230
|
-
- **Focus trapping
|
|
231
|
-
- **Focus restoration
|
|
232
|
-
|
|
233
|
-
|
|
269
|
+
- **Focus trapping:** Built into `showModal()` (Tab/Shift+Tab stays inside the dialog).
|
|
270
|
+
- **Focus restoration:** `rc-dialog` captures the focused element before opening and restores
|
|
271
|
+
focus to it on close. If the opener was removed from the DOM while the dialog was open, focus
|
|
272
|
+
falls back to `document.body`.
|
|
273
|
+
- **Escape to close:** Native behavior routes through `rc-dialog-request-close` so guards still
|
|
274
|
+
apply.
|
|
275
|
+
- **`aria-modal`:** `showModal()` implies `aria-modal="true"` without an explicit attribute.
|
|
234
276
|
|
|
235
|
-
**Required:** The inner `<dialog>` must have `aria-labelledby` or `aria-label`. In development
|
|
277
|
+
**Required:** The inner `<dialog>` must have `aria-labelledby` or `aria-label`. In development
|
|
278
|
+
mode the component logs a console warning if either is absent.
|
|
236
279
|
|
|
237
|
-
**Alert dialogs:** When `role="alertdialog"` is set, add `aria-describedby` pointing to the
|
|
280
|
+
**Alert dialogs:** When `role="alertdialog"` is set, add `aria-describedby` pointing to the
|
|
281
|
+
message text. A dev-mode warning fires if it is missing.
|
|
238
282
|
|
|
239
283
|
---
|
|
240
284
|
|
|
241
285
|
## CSS layout for scrollable dialogs
|
|
242
286
|
|
|
243
|
-
When the dialog needs scrollable body content (especially when resizable), use flex layout so
|
|
287
|
+
When the dialog needs scrollable body content (especially when resizable), use flex layout so
|
|
288
|
+
the body grows and the header/footer stay fixed:
|
|
244
289
|
|
|
245
290
|
```css
|
|
246
291
|
dialog[open] {
|
|
@@ -261,7 +306,9 @@ dialog[open] {
|
|
|
261
306
|
}
|
|
262
307
|
```
|
|
263
308
|
|
|
264
|
-
> **Note:** `display: flex` must be scoped to `dialog[open]`, not `dialog`. Author styles take
|
|
309
|
+
> **Note:** `display: flex` must be scoped to `dialog[open]`, not `dialog`. Author styles take
|
|
310
|
+
> precedence over the UA `dialog:not([open]) { display: none }` rule. Scoping to `[open]`
|
|
311
|
+
> prevents all dialogs from being visible on page load.
|
|
265
312
|
|
|
266
313
|
---
|
|
267
314
|
|
|
@@ -48,6 +48,13 @@
|
|
|
48
48
|
"kind": "class",
|
|
49
49
|
"description": "Draggable, resizable wrapper for a native <dialog>, following the WAI-ARIA Dialog Modal\npattern.",
|
|
50
50
|
"name": "RCDialog",
|
|
51
|
+
"cssProperties": [
|
|
52
|
+
{
|
|
53
|
+
"description": "Modal backdrop color.",
|
|
54
|
+
"name": "--rc-dialog-scrim",
|
|
55
|
+
"default": "color-mix(in srgb, CanvasText 32%, transparent)"
|
|
56
|
+
}
|
|
57
|
+
],
|
|
51
58
|
"slots": [
|
|
52
59
|
{
|
|
53
60
|
"description": "Place a `<dialog>` element with your content here.",
|
|
@@ -107,6 +114,26 @@
|
|
|
107
114
|
"attribute": "resize",
|
|
108
115
|
"reflects": true
|
|
109
116
|
},
|
|
117
|
+
{
|
|
118
|
+
"kind": "field",
|
|
119
|
+
"name": "resizeOrigin",
|
|
120
|
+
"type": {
|
|
121
|
+
"text": "ResizeOrigin"
|
|
122
|
+
},
|
|
123
|
+
"default": "''",
|
|
124
|
+
"description": "Origin for resize edge hit-testing or explicit handles.\n\nEmpty preserves the historical free edge-detection behavior.",
|
|
125
|
+
"attribute": "resize-origin"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"kind": "field",
|
|
129
|
+
"name": "resizeHandle",
|
|
130
|
+
"type": {
|
|
131
|
+
"text": "string"
|
|
132
|
+
},
|
|
133
|
+
"default": "''",
|
|
134
|
+
"description": "CSS selector, scoped to the inner `<dialog>`, for one or more explicit\nresize handles.\n\nHandles may override host behavior with:\n- `data-rc-dialog-resize-axis=\"x|y|both\"`\n- `data-rc-dialog-resize-origin=\"top|right|bottom|left|top-left|...\"`",
|
|
135
|
+
"attribute": "resize-handle"
|
|
136
|
+
},
|
|
110
137
|
{
|
|
111
138
|
"kind": "field",
|
|
112
139
|
"name": "resizeThreshold",
|
|
@@ -188,7 +215,7 @@
|
|
|
188
215
|
{
|
|
189
216
|
"kind": "field",
|
|
190
217
|
"name": "_dialogController",
|
|
191
|
-
"privacy": "
|
|
218
|
+
"privacy": "protected",
|
|
192
219
|
"readonly": true,
|
|
193
220
|
"default": "new NativeChildController<HTMLDialogElement>(this, { selector: ':scope > dialog', observe: true, onChange: ($dialog) => this._setupDialog($dialog), onMissing: () => { if (import.meta.env.DEV) { warnMissingDirectChild(this, { selector: ':scope > dialog', message: '[rc-dialog] No direct child <dialog> found. Place a native <dialog> inside <rc-dialog>.', }); } }, })"
|
|
194
221
|
},
|
|
@@ -198,7 +225,7 @@
|
|
|
198
225
|
"type": {
|
|
199
226
|
"text": "WeakRef<HTMLDialogElement> | null"
|
|
200
227
|
},
|
|
201
|
-
"privacy": "
|
|
228
|
+
"privacy": "protected",
|
|
202
229
|
"default": "null"
|
|
203
230
|
},
|
|
204
231
|
{
|
|
@@ -207,7 +234,7 @@
|
|
|
207
234
|
"type": {
|
|
208
235
|
"text": "boolean"
|
|
209
236
|
},
|
|
210
|
-
"privacy": "
|
|
237
|
+
"privacy": "protected",
|
|
211
238
|
"default": "false"
|
|
212
239
|
},
|
|
213
240
|
{
|
|
@@ -349,6 +376,117 @@
|
|
|
349
376
|
"privacy": "protected",
|
|
350
377
|
"description": "Detects backdrop clicks."
|
|
351
378
|
},
|
|
379
|
+
{
|
|
380
|
+
"kind": "method",
|
|
381
|
+
"name": "_onResizeStart",
|
|
382
|
+
"privacy": "protected",
|
|
383
|
+
"return": {
|
|
384
|
+
"type": {
|
|
385
|
+
"text": "void"
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
"parameters": [
|
|
389
|
+
{
|
|
390
|
+
"name": "_detail",
|
|
391
|
+
"type": {
|
|
392
|
+
"text": "ResizeLifecycleDetail"
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
],
|
|
396
|
+
"description": "Hook for subclasses to respond when a resize gesture begins."
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
"kind": "method",
|
|
400
|
+
"name": "_onResize",
|
|
401
|
+
"privacy": "protected",
|
|
402
|
+
"return": {
|
|
403
|
+
"type": {
|
|
404
|
+
"text": "void"
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
"parameters": [
|
|
408
|
+
{
|
|
409
|
+
"name": "_detail",
|
|
410
|
+
"type": {
|
|
411
|
+
"text": "ResizeLifecycleDetail"
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
],
|
|
415
|
+
"description": "Hook for subclasses to respond to each resize update during an active gesture."
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
"kind": "method",
|
|
419
|
+
"name": "_onResizeEnd",
|
|
420
|
+
"privacy": "protected",
|
|
421
|
+
"return": {
|
|
422
|
+
"type": {
|
|
423
|
+
"text": "void"
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
"parameters": [
|
|
427
|
+
{
|
|
428
|
+
"name": "_detail",
|
|
429
|
+
"type": {
|
|
430
|
+
"text": "ResizeLifecycleDetail"
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
],
|
|
434
|
+
"description": "Hook for subclasses to respond after a resize gesture has settled."
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"kind": "method",
|
|
438
|
+
"name": "_resizeHandles",
|
|
439
|
+
"privacy": "protected",
|
|
440
|
+
"return": {
|
|
441
|
+
"type": {
|
|
442
|
+
"text": "Element[]"
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
"parameters": [
|
|
446
|
+
{
|
|
447
|
+
"name": "$dialog",
|
|
448
|
+
"type": {
|
|
449
|
+
"text": "HTMLDialogElement"
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
]
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
"kind": "method",
|
|
456
|
+
"name": "_resizeDirectionForHandle",
|
|
457
|
+
"privacy": "protected",
|
|
458
|
+
"return": {
|
|
459
|
+
"type": {
|
|
460
|
+
"text": "ResizeDirection"
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
"parameters": [
|
|
464
|
+
{
|
|
465
|
+
"name": "$handle",
|
|
466
|
+
"type": {
|
|
467
|
+
"text": "Element"
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
]
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"kind": "method",
|
|
474
|
+
"name": "_resizeOriginForHandle",
|
|
475
|
+
"privacy": "protected",
|
|
476
|
+
"return": {
|
|
477
|
+
"type": {
|
|
478
|
+
"text": "ResizeOrigin"
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
"parameters": [
|
|
482
|
+
{
|
|
483
|
+
"name": "$handle",
|
|
484
|
+
"type": {
|
|
485
|
+
"text": "Element"
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
]
|
|
489
|
+
},
|
|
352
490
|
{
|
|
353
491
|
"kind": "method",
|
|
354
492
|
"name": "_applyOpen",
|
|
@@ -364,19 +502,19 @@
|
|
|
364
502
|
"type": {
|
|
365
503
|
"text": "boolean"
|
|
366
504
|
},
|
|
367
|
-
"description": "
|
|
505
|
+
"description": "whether to open (`true`) or close (`false`)"
|
|
368
506
|
},
|
|
369
507
|
{
|
|
370
508
|
"name": "silent",
|
|
371
509
|
"type": {
|
|
372
510
|
"text": "boolean"
|
|
373
511
|
},
|
|
374
|
-
"description": "
|
|
512
|
+
"description": "when `true`, suppresses the outgoing `rc-dialog-toggle` event"
|
|
375
513
|
},
|
|
376
514
|
{
|
|
377
515
|
"name": "modal",
|
|
378
516
|
"default": "true",
|
|
379
|
-
"description": "
|
|
517
|
+
"description": "whether to call `showModal()` (`true`) or `show()` (`false`)"
|
|
380
518
|
}
|
|
381
519
|
],
|
|
382
520
|
"description": "Opens or closes the inner `<dialog>` and returns `true` if state actually changed."
|
|
@@ -431,101 +569,119 @@
|
|
|
431
569
|
],
|
|
432
570
|
"attributes": [
|
|
433
571
|
{
|
|
572
|
+
"description": "Whether the inner `<dialog>` is currently open. Host writes update silently.",
|
|
573
|
+
"name": "open",
|
|
574
|
+
"type": {
|
|
575
|
+
"text": "boolean"
|
|
576
|
+
},
|
|
577
|
+
"fieldName": "open"
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
"description": "Initial uncontrolled open state.",
|
|
581
|
+
"name": "default-open",
|
|
582
|
+
"type": {
|
|
583
|
+
"text": "boolean"
|
|
584
|
+
},
|
|
585
|
+
"fieldName": "defaultOpen"
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
"description": "Allow the dialog to be moved by dragging.\n\nUse `move-handle` to restrict dragging to a specific child\nelement (e.g. a titlebar).",
|
|
434
589
|
"name": "movable",
|
|
435
590
|
"type": {
|
|
436
591
|
"text": "boolean"
|
|
437
592
|
},
|
|
438
593
|
"default": "false",
|
|
439
|
-
"description": "Allow the dialog to be moved by dragging.\n\nUse `move-handle` to restrict dragging to a specific child\nelement (e.g. a titlebar).",
|
|
440
594
|
"fieldName": "movable"
|
|
441
595
|
},
|
|
442
596
|
{
|
|
597
|
+
"description": "CSS selector (within the inner `<dialog>`) for the drag handle element.",
|
|
443
598
|
"name": "move-handle",
|
|
444
599
|
"type": {
|
|
445
600
|
"text": "string"
|
|
446
601
|
},
|
|
447
602
|
"default": "''",
|
|
448
|
-
"description": "CSS selector (within the inner `<dialog>`) for the drag handle element.",
|
|
449
603
|
"fieldName": "moveHandle"
|
|
450
604
|
},
|
|
451
605
|
{
|
|
606
|
+
"description": "Bounds constraint for movement.",
|
|
452
607
|
"name": "move-bounds",
|
|
453
608
|
"type": {
|
|
454
609
|
"text": "'viewport' | 'parent'"
|
|
455
610
|
},
|
|
456
611
|
"default": "'viewport'",
|
|
457
|
-
"description": "Bounds constraint for movement.",
|
|
458
612
|
"fieldName": "moveBounds"
|
|
459
613
|
},
|
|
460
614
|
{
|
|
615
|
+
"description": "Keyboard arrow-key step in px for moving.",
|
|
461
616
|
"name": "move-step",
|
|
462
617
|
"type": {
|
|
463
618
|
"text": "number"
|
|
464
619
|
},
|
|
465
620
|
"default": "4",
|
|
466
|
-
"description": "Keyboard arrow-key step in px for moving.",
|
|
467
621
|
"fieldName": "moveStep"
|
|
468
622
|
},
|
|
469
623
|
{
|
|
624
|
+
"description": "Enable resizing, mirroring the CSS `resize` property values.",
|
|
470
625
|
"name": "resize",
|
|
471
626
|
"type": {
|
|
472
627
|
"text": "'none' | 'both' | 'horizontal' | 'vertical'"
|
|
473
628
|
},
|
|
474
629
|
"default": "'none'",
|
|
475
|
-
"description": "Enable resizing, mirroring the CSS `resize` property values.",
|
|
476
630
|
"fieldName": "resize"
|
|
477
631
|
},
|
|
478
632
|
{
|
|
633
|
+
"description": "Origin for resize edge hit-testing or explicit handles.\n\nEmpty preserves the historical free edge-detection behavior.",
|
|
634
|
+
"name": "resize-origin",
|
|
635
|
+
"type": {
|
|
636
|
+
"text": "ResizeOrigin"
|
|
637
|
+
},
|
|
638
|
+
"default": "''",
|
|
639
|
+
"fieldName": "resizeOrigin"
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
"description": "CSS selector, scoped to the inner `<dialog>`, for one or more explicit\nresize handles.\n\nHandles may override host behavior with:\n- `data-rc-dialog-resize-axis=\"x|y|both\"`\n- `data-rc-dialog-resize-origin=\"top|right|bottom|left|top-left|...\"`",
|
|
643
|
+
"name": "resize-handle",
|
|
644
|
+
"type": {
|
|
645
|
+
"text": "string"
|
|
646
|
+
},
|
|
647
|
+
"default": "''",
|
|
648
|
+
"fieldName": "resizeHandle"
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
"description": "Edge hit-test thickness in px for resize detection.",
|
|
479
652
|
"name": "resize-threshold",
|
|
480
653
|
"type": {
|
|
481
654
|
"text": "number"
|
|
482
655
|
},
|
|
483
656
|
"default": "8",
|
|
484
|
-
"description": "Edge hit-test thickness in px for resize detection.",
|
|
485
657
|
"fieldName": "resizeThreshold"
|
|
486
658
|
},
|
|
487
659
|
{
|
|
660
|
+
"description": "Keyboard arrow-key step in px for resizing.",
|
|
488
661
|
"name": "resize-step",
|
|
489
662
|
"type": {
|
|
490
663
|
"text": "number"
|
|
491
664
|
},
|
|
492
665
|
"default": "4",
|
|
493
|
-
"description": "Keyboard arrow-key step in px for resizing.",
|
|
494
666
|
"fieldName": "resizeStep"
|
|
495
667
|
},
|
|
496
668
|
{
|
|
669
|
+
"description": "Proxied to the inner `<dialog closedby=\"...\">` attribute.\n\nProgressive enhancement, no-op in older browsers.\n\n- `'any'` — Escape OR backdrop click closes the dialog.\n- `'closerequest'` — Escape only (browser default for modal dialogs).\n- `'none'` — Only programmatic `close()` / `requestClose()`.\n- `''` — Attribute absent; use `light-dismiss` for JS fallback.",
|
|
497
670
|
"name": "closed-by",
|
|
498
671
|
"type": {
|
|
499
672
|
"text": "'any' | 'closerequest' | 'none' | ''"
|
|
500
673
|
},
|
|
501
674
|
"default": "''",
|
|
502
|
-
"description": "Proxied to the inner `<dialog closedby=\"...\">` attribute.\n\nProgressive enhancement, no-op in older browsers.\n\n- `'any'` — Escape OR backdrop click closes the dialog.\n- `'closerequest'` — Escape only (browser default for modal dialogs).\n- `'none'` — Only programmatic `close()` / `requestClose()`.\n- `''` — Attribute absent; use `light-dismiss` for JS fallback.",
|
|
503
675
|
"fieldName": "closedBy"
|
|
504
676
|
},
|
|
505
677
|
{
|
|
678
|
+
"description": "When true and the dialog is modal, a click on the backdrop area calls\n`requestClose()`.",
|
|
506
679
|
"name": "light-dismiss",
|
|
507
680
|
"type": {
|
|
508
681
|
"text": "boolean"
|
|
509
682
|
},
|
|
510
683
|
"default": "false",
|
|
511
|
-
"description": "When true and the dialog is modal, a click on the backdrop area calls\n`requestClose()`.",
|
|
512
684
|
"fieldName": "lightDismiss"
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
"name": "open",
|
|
516
|
-
"type": {
|
|
517
|
-
"text": "boolean"
|
|
518
|
-
},
|
|
519
|
-
"description": "Whether the inner `<dialog>` is currently open. Host writes update silently.",
|
|
520
|
-
"fieldName": "open"
|
|
521
|
-
},
|
|
522
|
-
{
|
|
523
|
-
"name": "default-open",
|
|
524
|
-
"type": {
|
|
525
|
-
"text": "boolean"
|
|
526
|
-
},
|
|
527
|
-
"description": "Initial uncontrolled open state.",
|
|
528
|
-
"fieldName": "defaultOpen"
|
|
529
685
|
}
|
|
530
686
|
],
|
|
531
687
|
"superclass": {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { LitElement as
|
|
2
|
-
import { property as
|
|
3
|
-
import { NativeChildController as
|
|
4
|
-
var
|
|
5
|
-
for (var s =
|
|
6
|
-
(h =
|
|
7
|
-
return
|
|
1
|
+
import { LitElement as p, nothing as u } from "lit";
|
|
2
|
+
import { property as r } from "lit/decorators.js";
|
|
3
|
+
import { NativeChildController as c, DragController as _, ResizeController as d } from "@rcarls/rc-common";
|
|
4
|
+
var f = Object.defineProperty, g = Object.getOwnPropertyDescriptor, o = (l, e, t, i) => {
|
|
5
|
+
for (var s = i > 1 ? void 0 : i ? g(e, t) : e, a = l.length - 1, h; a >= 0; a--)
|
|
6
|
+
(h = l[a]) && (s = (i ? h(e, t, s) : h(s)) || s);
|
|
7
|
+
return i && s && f(e, t, s), s;
|
|
8
8
|
};
|
|
9
|
-
class
|
|
9
|
+
class n extends p {
|
|
10
10
|
constructor() {
|
|
11
|
-
super(...arguments), this.movable = !1, this.moveHandle = "", this.moveBounds = "viewport", this.moveStep = 4, this.resize = "none", this.resizeThreshold = 8, this.resizeStep = 4, this.closedBy = "", this.lightDismiss = !1, this.modal = !0, this._controlledOpen = void 0, this._defaultOpen = !1, this._dialogController = new
|
|
11
|
+
super(...arguments), this.movable = !1, this.moveHandle = "", this.moveBounds = "viewport", this.moveStep = 4, this.resize = "none", this.resizeOrigin = "", this.resizeHandle = "", this.resizeThreshold = 8, this.resizeStep = 4, this.closedBy = "", this.lightDismiss = !1, this.modal = !0, this._controlledOpen = void 0, this._defaultOpen = !1, this._dialogController = new c(this, {
|
|
12
12
|
selector: ":scope > dialog",
|
|
13
13
|
observe: !0,
|
|
14
14
|
onChange: (e) => this._setupDialog(e),
|
|
@@ -83,12 +83,12 @@ class r extends a {
|
|
|
83
83
|
if ("requestClose" in t && typeof t.requestClose == "function")
|
|
84
84
|
t.requestClose(e);
|
|
85
85
|
else {
|
|
86
|
-
const
|
|
87
|
-
!t.dispatchEvent(
|
|
86
|
+
const i = new Event("cancel", { cancelable: !0, bubbles: !1 });
|
|
87
|
+
!t.dispatchEvent(i) || t.close(e);
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
render() {
|
|
91
|
-
return
|
|
91
|
+
return u;
|
|
92
92
|
}
|
|
93
93
|
firstUpdated() {
|
|
94
94
|
this._dialogController.sync();
|
|
@@ -102,20 +102,43 @@ class r extends a {
|
|
|
102
102
|
if (this._$wired?.deref() !== e) {
|
|
103
103
|
if (this._teardownDialog(), this._$wired = new WeakRef(e), e.addEventListener("close", this._onClose), e.addEventListener("cancel", this._onCancel), this.lightDismiss && "closedBy" in HTMLDialogElement.prototype ? e.setAttribute("closedby", "any") : this.lightDismiss ? e.addEventListener("click", this._onBackdropClick) : this.closedBy && e.setAttribute("closedby", this.closedBy), this.movable || this.moveHandle) {
|
|
104
104
|
const t = this.moveHandle ? e.querySelector(this.moveHandle) ?? e : e;
|
|
105
|
-
new
|
|
105
|
+
new _(this, {
|
|
106
106
|
target: e,
|
|
107
107
|
handle: t,
|
|
108
108
|
bounds: this.moveBounds,
|
|
109
109
|
step: this.moveStep
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
|
-
this.resize !== "none"
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
if (this.resize !== "none") {
|
|
113
|
+
const t = this._resizeHandles(e);
|
|
114
|
+
if (t.length > 0)
|
|
115
|
+
for (const i of t)
|
|
116
|
+
new d(this, {
|
|
117
|
+
target: e,
|
|
118
|
+
direction: this._resizeDirectionForHandle(i),
|
|
119
|
+
handle: i,
|
|
120
|
+
origin: this._resizeOriginForHandle(i),
|
|
121
|
+
threshold: this.resizeThreshold,
|
|
122
|
+
step: this.resizeStep,
|
|
123
|
+
bounds: this.moveBounds,
|
|
124
|
+
onResizeStart: (s) => this._onResizeStart(s),
|
|
125
|
+
onResize: (s) => this._onResize(s),
|
|
126
|
+
onResizeEnd: (s) => this._onResizeEnd(s)
|
|
127
|
+
});
|
|
128
|
+
else
|
|
129
|
+
new d(this, {
|
|
130
|
+
target: e,
|
|
131
|
+
direction: this.resize,
|
|
132
|
+
origin: this.resizeOrigin,
|
|
133
|
+
threshold: this.resizeThreshold,
|
|
134
|
+
step: this.resizeStep,
|
|
135
|
+
bounds: this.moveBounds,
|
|
136
|
+
onResizeStart: (i) => this._onResizeStart(i),
|
|
137
|
+
onResize: (i) => this._onResize(i),
|
|
138
|
+
onResizeEnd: (i) => this._onResizeEnd(i)
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
this._controlledOpen !== void 0 ? this._applyOpen(this._controlledOpen, !0, this.modal) : this.defaultOpen && this._applyOpen(!0, !0, this.modal);
|
|
119
142
|
}
|
|
120
143
|
}
|
|
121
144
|
updated(e) {
|
|
@@ -130,16 +153,49 @@ class r extends a {
|
|
|
130
153
|
const e = this._$wired?.deref();
|
|
131
154
|
e && (e.removeEventListener("close", this._onClose), e.removeEventListener("cancel", this._onCancel), e.removeEventListener("click", this._onBackdropClick), this._$wired = null, this._$opener = null);
|
|
132
155
|
}
|
|
156
|
+
/** Hook for subclasses to respond when a resize gesture begins. */
|
|
157
|
+
_onResizeStart(e) {
|
|
158
|
+
}
|
|
159
|
+
/** Hook for subclasses to respond to each resize update during an active gesture. */
|
|
160
|
+
_onResize(e) {
|
|
161
|
+
}
|
|
162
|
+
/** Hook for subclasses to respond after a resize gesture has settled. */
|
|
163
|
+
_onResizeEnd(e) {
|
|
164
|
+
}
|
|
165
|
+
_resizeHandles(e) {
|
|
166
|
+
if (!this.resizeHandle)
|
|
167
|
+
return [];
|
|
168
|
+
try {
|
|
169
|
+
return [...e.querySelectorAll(this.resizeHandle)];
|
|
170
|
+
} catch {
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
_resizeDirectionForHandle(e) {
|
|
175
|
+
switch (e.getAttribute("data-rc-dialog-resize-axis")) {
|
|
176
|
+
case "x":
|
|
177
|
+
return "horizontal";
|
|
178
|
+
case "y":
|
|
179
|
+
return "vertical";
|
|
180
|
+
case "both":
|
|
181
|
+
return "both";
|
|
182
|
+
default:
|
|
183
|
+
return this.resize;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
_resizeOriginForHandle(e) {
|
|
187
|
+
return e.getAttribute("data-rc-dialog-resize-origin") ?? this.resizeOrigin;
|
|
188
|
+
}
|
|
133
189
|
/**
|
|
134
190
|
* Opens or closes the inner `<dialog>` and returns `true` if state actually changed.
|
|
135
191
|
*
|
|
136
|
-
* @param open -
|
|
137
|
-
* @param silent -
|
|
138
|
-
* @param modal -
|
|
192
|
+
* @param open - whether to open (`true`) or close (`false`)
|
|
193
|
+
* @param silent - when `true`, suppresses the outgoing `rc-dialog-toggle` event
|
|
194
|
+
* @param modal - whether to call `showModal()` (`true`) or `show()` (`false`)
|
|
139
195
|
*/
|
|
140
|
-
_applyOpen(e, t,
|
|
196
|
+
_applyOpen(e, t, i = !0) {
|
|
141
197
|
const s = this._$dialog;
|
|
142
|
-
return s ? e ? s.open ? !1 : (this._$opener = document.activeElement,
|
|
198
|
+
return s ? e ? s.open ? !1 : (this._$opener = document.activeElement, i ? s.showModal() : s.show(), this.requestUpdate("open"), !0) : s.open ? (this._suppressNextCloseToggle = t, s.close(), this.requestUpdate("open"), !0) : !1 : !1;
|
|
143
199
|
}
|
|
144
200
|
/** Dispatches `rc-dialog-toggle` with the current open state and return value. */
|
|
145
201
|
_dispatchToggle(e) {
|
|
@@ -153,39 +209,45 @@ class r extends a {
|
|
|
153
209
|
}
|
|
154
210
|
}
|
|
155
211
|
o([
|
|
156
|
-
|
|
157
|
-
],
|
|
212
|
+
r({ type: Boolean, reflect: !0 })
|
|
213
|
+
], n.prototype, "movable", 2);
|
|
214
|
+
o([
|
|
215
|
+
r({ type: String, attribute: "move-handle" })
|
|
216
|
+
], n.prototype, "moveHandle", 2);
|
|
217
|
+
o([
|
|
218
|
+
r({ type: String, attribute: "move-bounds" })
|
|
219
|
+
], n.prototype, "moveBounds", 2);
|
|
158
220
|
o([
|
|
159
|
-
|
|
160
|
-
],
|
|
221
|
+
r({ type: Number, attribute: "move-step" })
|
|
222
|
+
], n.prototype, "moveStep", 2);
|
|
161
223
|
o([
|
|
162
|
-
|
|
163
|
-
],
|
|
224
|
+
r({ type: String, reflect: !0 })
|
|
225
|
+
], n.prototype, "resize", 2);
|
|
164
226
|
o([
|
|
165
|
-
|
|
166
|
-
],
|
|
227
|
+
r({ type: String, attribute: "resize-origin" })
|
|
228
|
+
], n.prototype, "resizeOrigin", 2);
|
|
167
229
|
o([
|
|
168
|
-
|
|
169
|
-
],
|
|
230
|
+
r({ type: String, attribute: "resize-handle" })
|
|
231
|
+
], n.prototype, "resizeHandle", 2);
|
|
170
232
|
o([
|
|
171
|
-
|
|
172
|
-
],
|
|
233
|
+
r({ type: Number, attribute: "resize-threshold" })
|
|
234
|
+
], n.prototype, "resizeThreshold", 2);
|
|
173
235
|
o([
|
|
174
|
-
|
|
175
|
-
],
|
|
236
|
+
r({ type: Number, attribute: "resize-step" })
|
|
237
|
+
], n.prototype, "resizeStep", 2);
|
|
176
238
|
o([
|
|
177
|
-
|
|
178
|
-
],
|
|
239
|
+
r({ type: String, attribute: "closed-by", reflect: !0 })
|
|
240
|
+
], n.prototype, "closedBy", 2);
|
|
179
241
|
o([
|
|
180
|
-
|
|
181
|
-
],
|
|
242
|
+
r({ type: Boolean, attribute: "light-dismiss" })
|
|
243
|
+
], n.prototype, "lightDismiss", 2);
|
|
182
244
|
o([
|
|
183
|
-
|
|
184
|
-
],
|
|
245
|
+
r({ type: Boolean, attribute: "open", reflect: !0 })
|
|
246
|
+
], n.prototype, "open", 1);
|
|
185
247
|
o([
|
|
186
|
-
|
|
187
|
-
],
|
|
248
|
+
r({ type: Boolean, attribute: "default-open" })
|
|
249
|
+
], n.prototype, "defaultOpen", 1);
|
|
188
250
|
export {
|
|
189
|
-
|
|
251
|
+
n as R
|
|
190
252
|
};
|
|
191
|
-
//# sourceMappingURL=rc-dialog-
|
|
253
|
+
//# sourceMappingURL=rc-dialog-D9jUBKJn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rc-dialog-D9jUBKJn.js","sources":["../src/rc-dialog.ts"],"sourcesContent":["import { LitElement, nothing, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport {\n DragController,\n NativeChildController,\n ResizeController,\n type ResizeDirection,\n type ResizeLifecycleDetail,\n type ResizeOrigin,\n warnMissingDirectChild,\n} from '@rcarls/rc-common';\n\n/** Detail shape for `rc-dialog-close` and `rc-dialog-request-close`. */\nexport interface RCDialogCloseEvent {\n returnValue: string;\n}\n\n/** Detail shape for `rc-dialog-toggle`. */\nexport interface RCDialogToggleEvent {\n open: boolean;\n returnValue: string;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-dialog': RCDialog;\n }\n\n interface HTMLElementEventMap {\n 'rc-dialog-open': CustomEvent<Record<string, never>>;\n 'rc-dialog-close': CustomEvent<RCDialogCloseEvent>;\n 'rc-dialog-request-close': CustomEvent<RCDialogCloseEvent>;\n 'rc-dialog-cancel': CustomEvent<Record<string, never>>;\n 'rc-dialog-toggle': CustomEvent<RCDialogToggleEvent>;\n }\n}\n\n/**\n * Draggable, resizable wrapper for a native <dialog>, following the WAI-ARIA Dialog Modal\n * pattern.\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-dialog rc-dialog docs}\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/ WAI-ARIA Dialog Modal pattern}\n *\n * @slot - Place a `<dialog>` element with your content here.\n *\n * @fires rc-dialog-open - Fired when the dialog opens via `showModal()` or `show()`.\n * @fires rc-dialog-toggle - Fired when user/native interaction changes open state.\n * @fires rc-dialog-request-close - Fired before the dialog closes (cancellable).\n * @fires rc-dialog-cancel - Mirrors the inner `<dialog>` cancel event when the\n * close was not prevented. Backward-compatible alias for `rc-dialog-request-close`.\n * @fires rc-dialog-close - Mirrors the inner `<dialog>` close event.\n * `detail: { returnValue: string }`\n *\n * @attr open - Controlled open state. Reads the inner `<dialog>.open` value.\n * @attr default-open - Initial uncontrolled open state.\n * @attr movable - Allow the dialog to be moved by dragging.\n * @attr move-handle - CSS selector (within the inner `<dialog>`) for the drag handle element.\n * @attr move-bounds - Bounds constraint for movement: `viewport` or `parent`.\n * @attr move-step - Keyboard arrow-key step in px for moving.\n * @attr resize - Enable resizing, mirroring the CSS `resize` property values.\n * @attr resize-origin - Origin for resize edge hit-testing or explicit handles.\n * @attr resize-handle - CSS selector, scoped to the inner `<dialog>`, for one or more explicit\n * resize handles.\n * @attr resize-threshold - Edge hit-test thickness in px for resize detection.\n * @attr resize-step - Keyboard arrow-key step in px for resizing.\n * @attr closed-by - Proxied to the inner `<dialog closedby=\"...\">` attribute.\n * @attr light-dismiss - When present and the dialog is modal, a click on the backdrop area calls\n * `requestClose()`.\n *\n * @cssprop [--rc-dialog-scrim=color-mix(in srgb, CanvasText 32%, transparent)] - Modal backdrop color.\n *\n */\nexport class RCDialog extends LitElement {\n override createRenderRoot() {\n return this;\n }\n\n /**\n * Allow the dialog to be moved by dragging.\n *\n * Use `move-handle` to restrict dragging to a specific child\n * element (e.g. a titlebar).\n */\n @property({ type: Boolean, reflect: true })\n movable = false;\n\n /** CSS selector (within the inner `<dialog>`) for the drag handle element. */\n @property({ type: String, attribute: 'move-handle' })\n moveHandle = '';\n\n /** Bounds constraint for movement. */\n @property({ type: String, attribute: 'move-bounds' })\n moveBounds: 'viewport' | 'parent' = 'viewport';\n\n /** Keyboard arrow-key step in px for moving. */\n @property({ type: Number, attribute: 'move-step' })\n moveStep = 4;\n\n /** Enable resizing, mirroring the CSS `resize` property values. */\n @property({ type: String, reflect: true })\n resize: 'none' | 'both' | 'horizontal' | 'vertical' = 'none';\n\n /**\n * Origin for resize edge hit-testing or explicit handles.\n *\n * Empty preserves the historical free edge-detection behavior.\n */\n @property({ type: String, attribute: 'resize-origin' })\n resizeOrigin: ResizeOrigin = '';\n\n /**\n * CSS selector, scoped to the inner `<dialog>`, for one or more explicit\n * resize handles.\n *\n * Handles may override host behavior with:\n * - `data-rc-dialog-resize-axis=\"x|y|both\"`\n * - `data-rc-dialog-resize-origin=\"top|right|bottom|left|top-left|...\"`\n */\n @property({ type: String, attribute: 'resize-handle' })\n resizeHandle = '';\n\n /** Edge hit-test thickness in px for resize detection. */\n @property({ type: Number, attribute: 'resize-threshold' })\n resizeThreshold = 8;\n\n /** Keyboard arrow-key step in px for resizing. */\n @property({ type: Number, attribute: 'resize-step' })\n resizeStep = 4;\n\n /**\n * Proxied to the inner `<dialog closedby=\"...\">` attribute.\n *\n * Progressive enhancement, no-op in older browsers.\n *\n * - `'any'` — Escape OR backdrop click closes the dialog.\n * - `'closerequest'` — Escape only (browser default for modal dialogs).\n * - `'none'` — Only programmatic `close()` / `requestClose()`.\n * - `''` — Attribute absent; use `light-dismiss` for JS fallback.\n */\n @property({ type: String, attribute: 'closed-by', reflect: true })\n closedBy: 'any' | 'closerequest' | 'none' | '' = '';\n\n /**\n * When true and the dialog is modal, a click on the backdrop area calls\n * `requestClose()`.\n */\n @property({ type: Boolean, attribute: 'light-dismiss' })\n lightDismiss = false;\n\n /**\n * Whether to open as modal with controlled open. Default: `true`.\n */\n modal = true;\n\n /** The inner `<dialog>` element, resolved from the direct light-DOM child. */\n protected get _$dialog(): HTMLDialogElement | null {\n return this._dialogController.child;\n }\n\n private _controlledOpen: boolean | undefined = undefined;\n private _defaultOpen = false;\n protected readonly _dialogController = new NativeChildController<HTMLDialogElement>(this, {\n selector: ':scope > dialog',\n observe: true,\n onChange: ($dialog) => this._setupDialog($dialog),\n onMissing: () => {\n if (import.meta.env.DEV) {\n warnMissingDirectChild(this, {\n selector: ':scope > dialog',\n message:\n '[rc-dialog] No direct child <dialog> found. Place a native <dialog> inside <rc-dialog>.',\n });\n }\n },\n });\n\n // Tracks which <dialog> has its listeners wired; used by _teardownDialog to\n // remove listeners even after the element is removed from the DOM.\n protected _$wired: WeakRef<HTMLDialogElement> | null = null;\n protected _suppressNextCloseToggle = false;\n\n /** The element that had focus when the dialog was opened; restored on close. */\n protected _$opener: Element | null = null;\n\n /** Whether the inner `<dialog>` is currently open. Host writes update silently. */\n @property({ type: Boolean, attribute: 'open', reflect: true })\n get open(): boolean {\n return this._$dialog?.open ?? false;\n }\n\n set open(value: boolean | undefined) {\n const oldValue = this._controlledOpen;\n\n this._controlledOpen = value;\n\n if (value !== undefined) {\n this._applyOpen(value, true, this.modal);\n }\n\n this.requestUpdate('open', oldValue);\n }\n\n /** Initial uncontrolled open state. */\n @property({ type: Boolean, attribute: 'default-open' })\n get defaultOpen(): boolean {\n return this._defaultOpen;\n }\n\n set defaultOpen(value: boolean) {\n const oldValue = this._defaultOpen;\n\n this._defaultOpen = value;\n\n if (this._controlledOpen === undefined && value && this.isConnected) {\n this._applyOpen(true, true, this.modal);\n }\n\n this.requestUpdate('defaultOpen', oldValue);\n }\n\n /** The return value set when the dialog was closed. */\n get returnValue(): string {\n return this._$dialog?.returnValue ?? '';\n }\n\n /** Opens the inner `<dialog>` as a modal and fires `rc-dialog-open`. */\n showModal(): void {\n if (this._applyOpen(true, false, true)) {\n this.dispatchEvent(new CustomEvent('rc-dialog-open', { bubbles: true, composed: true }));\n this._dispatchToggle(true);\n }\n }\n\n /**\n * Opens the inner `<dialog>` (non-modal) and fires `rc-dialog-open`.\n */\n show(): void {\n if (this._applyOpen(true, false, false)) {\n this.dispatchEvent(new CustomEvent('rc-dialog-open', { bubbles: true, composed: true }));\n this._dispatchToggle(true);\n }\n }\n\n /** Closes the inner `<dialog>`, optionally setting a return value. */\n close(returnValue?: string): void {\n this._$dialog?.close(returnValue);\n }\n\n /**\n * Requests the inner `<dialog>` to close, firing a cancelable `cancel` event\n * first.\n */\n requestClose(returnValue?: string): void {\n const $dialog = this._$dialog;\n\n if (!$dialog) {\n return;\n }\n\n if ('requestClose' in $dialog && typeof $dialog.requestClose === 'function') {\n $dialog.requestClose(returnValue);\n } else {\n // Synthesize a cancelable cancel event; _onCancel fires rc-dialog-request-close.\n // If not prevented, _onCancel does not call $dlg.close() — we do it here.\n const ev = new Event('cancel', { cancelable: true, bubbles: false });\n const prevented = !$dialog.dispatchEvent(ev);\n\n if (!prevented) {\n $dialog.close(returnValue);\n }\n }\n }\n\n override render() {\n return nothing;\n }\n\n override firstUpdated() {\n this._dialogController.sync();\n }\n\n /** Wires event listeners, drag/resize controllers, and initial open state for the inner `<dialog>`. */\n protected _setupDialog($dialog: HTMLDialogElement | null = this._$dialog) {\n if (!$dialog) {\n this._teardownDialog();\n\n return;\n }\n\n if (this._$wired?.deref() === $dialog) {\n return;\n }\n\n this._teardownDialog();\n this._$wired = new WeakRef($dialog);\n\n if (import.meta.env.DEV) {\n const hasLabel =\n $dialog.hasAttribute('aria-labelledby') || $dialog.hasAttribute('aria-label');\n\n if (!hasLabel) {\n console.warn(\n '[rc-dialog] The inner <dialog> is missing aria-labelledby or ' +\n 'aria-label. Add one to satisfy the ARIA dialog pattern.',\n $dialog,\n );\n }\n\n if (\n $dialog.getAttribute('role') === 'alertdialog' &&\n !$dialog.hasAttribute('aria-describedby')\n ) {\n console.warn(\n '[rc-dialog] <dialog role=\"alertdialog\"> should have aria-describedby ' +\n 'pointing to the alert message text.',\n $dialog,\n );\n }\n\n if (!$dialog.querySelector('button:not([disabled])')) {\n console.warn(\n '[rc-dialog] No enabled <button> found inside <dialog>. APG recommends ' +\n 'including a visible close button in the tab sequence.',\n $dialog,\n );\n }\n }\n\n $dialog.addEventListener('close', this._onClose);\n $dialog.addEventListener('cancel', this._onCancel);\n\n if (this.lightDismiss && 'closedBy' in HTMLDialogElement.prototype) {\n $dialog.setAttribute('closedby', 'any');\n } else if (this.lightDismiss) {\n $dialog.addEventListener('click', this._onBackdropClick);\n } else {\n if (this.closedBy) {\n $dialog.setAttribute('closedby', this.closedBy);\n }\n }\n\n if (this.movable || this.moveHandle) {\n const $handle = this.moveHandle\n ? ($dialog.querySelector<Element>(this.moveHandle) ?? $dialog)\n : $dialog;\n\n new DragController(this, {\n target: $dialog,\n handle: $handle,\n bounds: this.moveBounds,\n step: this.moveStep,\n });\n }\n\n if (this.resize !== 'none') {\n const $handles = this._resizeHandles($dialog);\n\n if ($handles.length > 0) {\n for (const $handle of $handles) {\n // TODO: add a separate resize-bounds attribute; moveBounds is a proxy for now.\n new ResizeController(this, {\n target: $dialog,\n direction: this._resizeDirectionForHandle($handle),\n handle: $handle,\n origin: this._resizeOriginForHandle($handle),\n threshold: this.resizeThreshold,\n step: this.resizeStep,\n bounds: this.moveBounds,\n onResizeStart: (detail) => this._onResizeStart(detail),\n onResize: (detail) => this._onResize(detail),\n onResizeEnd: (detail) => this._onResizeEnd(detail),\n });\n }\n } else {\n // TODO: add a separate resize-bounds attribute; moveBounds is a proxy for now.\n new ResizeController(this, {\n target: $dialog,\n direction: this.resize,\n origin: this.resizeOrigin,\n threshold: this.resizeThreshold,\n step: this.resizeStep,\n bounds: this.moveBounds,\n onResizeStart: (detail) => this._onResizeStart(detail),\n onResize: (detail) => this._onResize(detail),\n onResizeEnd: (detail) => this._onResizeEnd(detail),\n });\n }\n }\n\n if (this._controlledOpen !== undefined) {\n this._applyOpen(this._controlledOpen, true, this.modal);\n } else if (this.defaultOpen) {\n this._applyOpen(true, true, this.modal);\n }\n }\n\n override updated(changed: PropertyValues) {\n const $dialog = this._$dialog;\n\n if (!$dialog) {\n return;\n }\n\n if (changed.has('closedBy')) {\n if (this.closedBy) {\n $dialog.setAttribute('closedby', this.closedBy);\n } else {\n $dialog.removeAttribute('closedby');\n }\n }\n\n if (changed.has('lightDismiss')) {\n if (this.lightDismiss && 'closedBy' in HTMLDialogElement.prototype) {\n // Native support available — delegate to closedby=\"any\" instead of JS handler.\n $dialog.setAttribute('closedby', 'any');\n $dialog.removeEventListener('click', this._onBackdropClick);\n } else if (this.lightDismiss) {\n $dialog.addEventListener('click', this._onBackdropClick);\n } else {\n $dialog.removeEventListener('click', this._onBackdropClick);\n\n if (this.closedBy) {\n $dialog.setAttribute('closedby', this.closedBy);\n } else {\n $dialog.removeAttribute('closedby');\n }\n }\n }\n }\n\n override disconnectedCallback() {\n this._teardownDialog();\n\n super.disconnectedCallback();\n }\n\n /** Removes all event listeners attached to the inner `<dialog>` and clears cached state. */\n protected _teardownDialog(): void {\n const $dialog = this._$wired?.deref();\n\n if (!$dialog) {\n return;\n }\n\n $dialog.removeEventListener('close', this._onClose);\n $dialog.removeEventListener('cancel', this._onCancel);\n $dialog.removeEventListener('click', this._onBackdropClick);\n\n this._$wired = null;\n this._$opener = null;\n }\n\n protected _onClose = () => {\n // Restore focus to the element that triggered the open, per APG focus management.\n if (this._$opener instanceof HTMLElement) {\n if (this._$opener.isConnected) {\n this._$opener.focus();\n } else {\n // Opener was removed from the DOM while the dialog was open; fall back\n // to body so focus is not left stranded.\n document.body.focus();\n }\n }\n\n this._$opener = null;\n\n this.dispatchEvent(\n new CustomEvent('rc-dialog-close', {\n bubbles: true,\n composed: true,\n detail: { returnValue: this.returnValue },\n }),\n );\n\n if (!this._suppressNextCloseToggle) {\n this._dispatchToggle(false);\n }\n\n this._suppressNextCloseToggle = false;\n this.requestUpdate('open');\n };\n\n /**\n * Intercepts the native `cancel` event.\n */\n protected _onCancel = (e: Event) => {\n const requestCloseEvent = new CustomEvent('rc-dialog-request-close', {\n bubbles: true,\n composed: true,\n cancelable: true,\n detail: { returnValue: this.returnValue },\n });\n const prevented = !this.dispatchEvent(requestCloseEvent);\n\n if (prevented) {\n e.preventDefault();\n } else {\n this.dispatchEvent(new CustomEvent('rc-dialog-cancel', { bubbles: true, composed: true }));\n }\n };\n\n /**\n * Detects backdrop clicks.\n */\n protected _onBackdropClick = (e: MouseEvent) => {\n if (e.target === this._$dialog) {\n this.requestClose();\n }\n };\n\n /** Hook for subclasses to respond when a resize gesture begins. */\n protected _onResizeStart(_detail: ResizeLifecycleDetail): void {}\n\n /** Hook for subclasses to respond to each resize update during an active gesture. */\n protected _onResize(_detail: ResizeLifecycleDetail): void {}\n\n /** Hook for subclasses to respond after a resize gesture has settled. */\n protected _onResizeEnd(_detail: ResizeLifecycleDetail): void {}\n\n protected _resizeHandles($dialog: HTMLDialogElement): Element[] {\n if (!this.resizeHandle) {\n return [];\n }\n\n try {\n return [...$dialog.querySelectorAll(this.resizeHandle)];\n } catch {\n if (import.meta.env.DEV) {\n console.warn('[rc-dialog] Invalid resize-handle selector.', this.resizeHandle);\n }\n\n return [];\n }\n }\n\n protected _resizeDirectionForHandle($handle: Element): ResizeDirection {\n const axis = $handle.getAttribute('data-rc-dialog-resize-axis');\n\n switch (axis) {\n case 'x':\n return 'horizontal';\n case 'y':\n return 'vertical';\n case 'both':\n return 'both';\n default:\n return this.resize;\n }\n }\n\n protected _resizeOriginForHandle($handle: Element): ResizeOrigin {\n return (\n ($handle.getAttribute('data-rc-dialog-resize-origin') as ResizeOrigin | null) ??\n this.resizeOrigin\n );\n }\n\n /**\n * Opens or closes the inner `<dialog>` and returns `true` if state actually changed.\n *\n * @param open - whether to open (`true`) or close (`false`)\n * @param silent - when `true`, suppresses the outgoing `rc-dialog-toggle` event\n * @param modal - whether to call `showModal()` (`true`) or `show()` (`false`)\n */\n protected _applyOpen(open: boolean, silent: boolean, modal = true): boolean {\n const $dialog = this._$dialog;\n\n if (!$dialog) {\n return false;\n }\n\n if (open) {\n if ($dialog.open) {\n return false;\n }\n\n // Capture focus owner before the dialog steals it, so we can restore on close.\n this._$opener = document.activeElement;\n modal ? $dialog.showModal() : $dialog.show();\n this.requestUpdate('open');\n\n return true;\n }\n\n if (!$dialog.open) {\n return false;\n }\n\n this._suppressNextCloseToggle = silent;\n $dialog.close();\n this.requestUpdate('open');\n\n return true;\n }\n\n /** Dispatches `rc-dialog-toggle` with the current open state and return value. */\n protected _dispatchToggle(open: boolean): void {\n this.dispatchEvent(\n new CustomEvent('rc-dialog-toggle', {\n bubbles: true,\n composed: true,\n detail: { open, returnValue: this.returnValue },\n }),\n );\n }\n}\n\nexport default RCDialog;\n"],"names":["RCDialog","LitElement","NativeChildController","$dialog","requestCloseEvent","value","oldValue","returnValue","ev","nothing","$handle","DragController","$handles","ResizeController","detail","changed","_detail","open","silent","modal","__decorateClass","property"],"mappings":"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"}
|
package/dist/rc-dialog-define.js
CHANGED
package/dist/rc-dialog.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LitElement, PropertyValues } from 'lit';
|
|
2
|
+
import { NativeChildController, ResizeDirection, ResizeLifecycleDetail, ResizeOrigin } from '@rcarls/rc-common';
|
|
2
3
|
/** Detail shape for `rc-dialog-close` and `rc-dialog-request-close`. */
|
|
3
4
|
export interface RCDialogCloseEvent {
|
|
4
5
|
returnValue: string;
|
|
@@ -37,6 +38,24 @@ declare global {
|
|
|
37
38
|
* @fires rc-dialog-close - Mirrors the inner `<dialog>` close event.
|
|
38
39
|
* `detail: { returnValue: string }`
|
|
39
40
|
*
|
|
41
|
+
* @attr open - Controlled open state. Reads the inner `<dialog>.open` value.
|
|
42
|
+
* @attr default-open - Initial uncontrolled open state.
|
|
43
|
+
* @attr movable - Allow the dialog to be moved by dragging.
|
|
44
|
+
* @attr move-handle - CSS selector (within the inner `<dialog>`) for the drag handle element.
|
|
45
|
+
* @attr move-bounds - Bounds constraint for movement: `viewport` or `parent`.
|
|
46
|
+
* @attr move-step - Keyboard arrow-key step in px for moving.
|
|
47
|
+
* @attr resize - Enable resizing, mirroring the CSS `resize` property values.
|
|
48
|
+
* @attr resize-origin - Origin for resize edge hit-testing or explicit handles.
|
|
49
|
+
* @attr resize-handle - CSS selector, scoped to the inner `<dialog>`, for one or more explicit
|
|
50
|
+
* resize handles.
|
|
51
|
+
* @attr resize-threshold - Edge hit-test thickness in px for resize detection.
|
|
52
|
+
* @attr resize-step - Keyboard arrow-key step in px for resizing.
|
|
53
|
+
* @attr closed-by - Proxied to the inner `<dialog closedby="...">` attribute.
|
|
54
|
+
* @attr light-dismiss - When present and the dialog is modal, a click on the backdrop area calls
|
|
55
|
+
* `requestClose()`.
|
|
56
|
+
*
|
|
57
|
+
* @cssprop [--rc-dialog-scrim=color-mix(in srgb, CanvasText 32%, transparent)] - Modal backdrop color.
|
|
58
|
+
*
|
|
40
59
|
*/
|
|
41
60
|
export declare class RCDialog extends LitElement {
|
|
42
61
|
createRenderRoot(): this;
|
|
@@ -55,6 +74,21 @@ export declare class RCDialog extends LitElement {
|
|
|
55
74
|
moveStep: number;
|
|
56
75
|
/** Enable resizing, mirroring the CSS `resize` property values. */
|
|
57
76
|
resize: 'none' | 'both' | 'horizontal' | 'vertical';
|
|
77
|
+
/**
|
|
78
|
+
* Origin for resize edge hit-testing or explicit handles.
|
|
79
|
+
*
|
|
80
|
+
* Empty preserves the historical free edge-detection behavior.
|
|
81
|
+
*/
|
|
82
|
+
resizeOrigin: ResizeOrigin;
|
|
83
|
+
/**
|
|
84
|
+
* CSS selector, scoped to the inner `<dialog>`, for one or more explicit
|
|
85
|
+
* resize handles.
|
|
86
|
+
*
|
|
87
|
+
* Handles may override host behavior with:
|
|
88
|
+
* - `data-rc-dialog-resize-axis="x|y|both"`
|
|
89
|
+
* - `data-rc-dialog-resize-origin="top|right|bottom|left|top-left|..."`
|
|
90
|
+
*/
|
|
91
|
+
resizeHandle: string;
|
|
58
92
|
/** Edge hit-test thickness in px for resize detection. */
|
|
59
93
|
resizeThreshold: number;
|
|
60
94
|
/** Keyboard arrow-key step in px for resizing. */
|
|
@@ -83,9 +117,9 @@ export declare class RCDialog extends LitElement {
|
|
|
83
117
|
protected get _$dialog(): HTMLDialogElement | null;
|
|
84
118
|
private _controlledOpen;
|
|
85
119
|
private _defaultOpen;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
120
|
+
protected readonly _dialogController: NativeChildController<HTMLDialogElement>;
|
|
121
|
+
protected _$wired: WeakRef<HTMLDialogElement> | null;
|
|
122
|
+
protected _suppressNextCloseToggle: boolean;
|
|
89
123
|
/** The element that had focus when the dialog was opened; restored on close. */
|
|
90
124
|
protected _$opener: Element | null;
|
|
91
125
|
/** Whether the inner `<dialog>` is currently open. Host writes update silently. */
|
|
@@ -126,12 +160,21 @@ export declare class RCDialog extends LitElement {
|
|
|
126
160
|
* Detects backdrop clicks.
|
|
127
161
|
*/
|
|
128
162
|
protected _onBackdropClick: (e: MouseEvent) => void;
|
|
163
|
+
/** Hook for subclasses to respond when a resize gesture begins. */
|
|
164
|
+
protected _onResizeStart(_detail: ResizeLifecycleDetail): void;
|
|
165
|
+
/** Hook for subclasses to respond to each resize update during an active gesture. */
|
|
166
|
+
protected _onResize(_detail: ResizeLifecycleDetail): void;
|
|
167
|
+
/** Hook for subclasses to respond after a resize gesture has settled. */
|
|
168
|
+
protected _onResizeEnd(_detail: ResizeLifecycleDetail): void;
|
|
169
|
+
protected _resizeHandles($dialog: HTMLDialogElement): Element[];
|
|
170
|
+
protected _resizeDirectionForHandle($handle: Element): ResizeDirection;
|
|
171
|
+
protected _resizeOriginForHandle($handle: Element): ResizeOrigin;
|
|
129
172
|
/**
|
|
130
173
|
* Opens or closes the inner `<dialog>` and returns `true` if state actually changed.
|
|
131
174
|
*
|
|
132
|
-
* @param open -
|
|
133
|
-
* @param silent -
|
|
134
|
-
* @param modal -
|
|
175
|
+
* @param open - whether to open (`true`) or close (`false`)
|
|
176
|
+
* @param silent - when `true`, suppresses the outgoing `rc-dialog-toggle` event
|
|
177
|
+
* @param modal - whether to call `showModal()` (`true`) or `show()` (`false`)
|
|
135
178
|
*/
|
|
136
179
|
protected _applyOpen(open: boolean, silent: boolean, modal?: boolean): boolean;
|
|
137
180
|
/** Dispatches `rc-dialog-toggle` with the current open state and return value. */
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rc-dialog-Dpj3ERfv.js","sources":["../src/rc-dialog.ts"],"sourcesContent":["import { LitElement, nothing, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport {\n DragController,\n NativeChildController,\n ResizeController,\n warnMissingDirectChild,\n} from '@rcarls/rc-common';\n\n/** Detail shape for `rc-dialog-close` and `rc-dialog-request-close`. */\nexport interface RCDialogCloseEvent {\n returnValue: string;\n}\n\n/** Detail shape for `rc-dialog-toggle`. */\nexport interface RCDialogToggleEvent {\n open: boolean;\n returnValue: string;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-dialog': RCDialog;\n }\n\n interface HTMLElementEventMap {\n 'rc-dialog-open': CustomEvent<Record<string, never>>;\n 'rc-dialog-close': CustomEvent<RCDialogCloseEvent>;\n 'rc-dialog-request-close': CustomEvent<RCDialogCloseEvent>;\n 'rc-dialog-cancel': CustomEvent<Record<string, never>>;\n 'rc-dialog-toggle': CustomEvent<RCDialogToggleEvent>;\n }\n}\n\n/**\n * Draggable, resizable wrapper for a native <dialog>, following the WAI-ARIA Dialog Modal\n * pattern.\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-dialog rc-dialog docs}\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/ WAI-ARIA Dialog Modal pattern}\n *\n * @slot - Place a `<dialog>` element with your content here.\n *\n * @fires rc-dialog-open - Fired when the dialog opens via `showModal()` or `show()`.\n * @fires rc-dialog-toggle - Fired when user/native interaction changes open state.\n * @fires rc-dialog-request-close - Fired before the dialog closes (cancellable).\n * @fires rc-dialog-cancel - Mirrors the inner `<dialog>` cancel event when the\n * close was not prevented. Backward-compatible alias for `rc-dialog-request-close`.\n * @fires rc-dialog-close - Mirrors the inner `<dialog>` close event.\n * `detail: { returnValue: string }`\n *\n */\nexport class RCDialog extends LitElement {\n override createRenderRoot() {\n return this;\n }\n\n /**\n * Allow the dialog to be moved by dragging.\n *\n * Use `move-handle` to restrict dragging to a specific child\n * element (e.g. a titlebar).\n */\n @property({ type: Boolean, reflect: true })\n movable = false;\n\n /** CSS selector (within the inner `<dialog>`) for the drag handle element. */\n @property({ type: String, attribute: 'move-handle' })\n moveHandle = '';\n\n /** Bounds constraint for movement. */\n @property({ type: String, attribute: 'move-bounds' })\n moveBounds: 'viewport' | 'parent' = 'viewport';\n\n /** Keyboard arrow-key step in px for moving. */\n @property({ type: Number, attribute: 'move-step' })\n moveStep = 4;\n\n /** Enable resizing, mirroring the CSS `resize` property values. */\n @property({ type: String, reflect: true })\n resize: 'none' | 'both' | 'horizontal' | 'vertical' = 'none';\n\n /** Edge hit-test thickness in px for resize detection. */\n @property({ type: Number, attribute: 'resize-threshold' })\n resizeThreshold = 8;\n\n /** Keyboard arrow-key step in px for resizing. */\n @property({ type: Number, attribute: 'resize-step' })\n resizeStep = 4;\n\n /**\n * Proxied to the inner `<dialog closedby=\"...\">` attribute.\n *\n * Progressive enhancement, no-op in older browsers.\n *\n * - `'any'` — Escape OR backdrop click closes the dialog.\n * - `'closerequest'` — Escape only (browser default for modal dialogs).\n * - `'none'` — Only programmatic `close()` / `requestClose()`.\n * - `''` — Attribute absent; use `light-dismiss` for JS fallback.\n */\n @property({ type: String, attribute: 'closed-by', reflect: true })\n closedBy: 'any' | 'closerequest' | 'none' | '' = '';\n\n /**\n * When true and the dialog is modal, a click on the backdrop area calls\n * `requestClose()`.\n */\n @property({ type: Boolean, attribute: 'light-dismiss' })\n lightDismiss = false;\n\n /**\n * Whether to open as modal with controlled open. Default: `true`.\n */\n modal = true;\n\n /** The inner `<dialog>` element, resolved from the direct light-DOM child. */\n protected get _$dialog(): HTMLDialogElement | null {\n return this._dialogController.child;\n }\n\n private _controlledOpen: boolean | undefined = undefined;\n private _defaultOpen = false;\n private readonly _dialogController = new NativeChildController<HTMLDialogElement>(this, {\n selector: ':scope > dialog',\n observe: true,\n onChange: ($dialog) => this._setupDialog($dialog),\n onMissing: () => {\n if (import.meta.env.DEV) {\n warnMissingDirectChild(this, {\n selector: ':scope > dialog',\n message:\n '[rc-dialog] No direct child <dialog> found. Place a native <dialog> inside <rc-dialog>.',\n });\n }\n },\n });\n // Tracks which <dialog> has its listeners wired; used by _teardownDialog to\n // remove listeners even after the element is removed from the DOM.\n private _$wired: WeakRef<HTMLDialogElement> | null = null;\n private _suppressNextCloseToggle = false;\n\n /** The element that had focus when the dialog was opened; restored on close. */\n protected _$opener: Element | null = null;\n\n /** Whether the inner `<dialog>` is currently open. Host writes update silently. */\n @property({ type: Boolean, attribute: 'open', reflect: true })\n get open(): boolean {\n return this._$dialog?.open ?? false;\n }\n\n set open(value: boolean | undefined) {\n const oldValue = this._controlledOpen;\n\n this._controlledOpen = value;\n\n if (value !== undefined) {\n this._applyOpen(value, true, this.modal);\n }\n\n this.requestUpdate('open', oldValue);\n }\n\n /** Initial uncontrolled open state. */\n @property({ type: Boolean, attribute: 'default-open' })\n get defaultOpen(): boolean {\n return this._defaultOpen;\n }\n\n set defaultOpen(value: boolean) {\n const oldValue = this._defaultOpen;\n\n this._defaultOpen = value;\n\n if (this._controlledOpen === undefined && value && this.isConnected) {\n this._applyOpen(true, true, this.modal);\n }\n\n this.requestUpdate('defaultOpen', oldValue);\n }\n\n /** The return value set when the dialog was closed. */\n get returnValue(): string {\n return this._$dialog?.returnValue ?? '';\n }\n\n /** Opens the inner `<dialog>` as a modal and fires `rc-dialog-open`. */\n showModal(): void {\n if (this._applyOpen(true, false, true)) {\n this.dispatchEvent(new CustomEvent('rc-dialog-open', { bubbles: true, composed: true }));\n this._dispatchToggle(true);\n }\n }\n\n /**\n * Opens the inner `<dialog>` (non-modal) and fires `rc-dialog-open`.\n */\n show(): void {\n if (this._applyOpen(true, false, false)) {\n this.dispatchEvent(new CustomEvent('rc-dialog-open', { bubbles: true, composed: true }));\n this._dispatchToggle(true);\n }\n }\n\n /** Closes the inner `<dialog>`, optionally setting a return value. */\n close(returnValue?: string): void {\n this._$dialog?.close(returnValue);\n }\n\n /**\n * Requests the inner `<dialog>` to close, firing a cancelable `cancel` event\n * first.\n */\n requestClose(returnValue?: string): void {\n const $dialog = this._$dialog;\n\n if (!$dialog) {\n return;\n }\n\n if ('requestClose' in $dialog && typeof $dialog.requestClose === 'function') {\n $dialog.requestClose(returnValue);\n } else {\n // Synthesize a cancelable cancel event; _onCancel fires rc-dialog-request-close.\n // If not prevented, _onCancel does not call $dlg.close() — we do it here.\n const ev = new Event('cancel', { cancelable: true, bubbles: false });\n const prevented = !$dialog.dispatchEvent(ev);\n\n if (!prevented) {\n $dialog.close(returnValue);\n }\n }\n }\n\n override render() {\n return nothing;\n }\n\n override firstUpdated() {\n this._dialogController.sync();\n }\n\n /** Wires event listeners, drag/resize controllers, and initial open state for the inner `<dialog>`. */\n protected _setupDialog($dialog: HTMLDialogElement | null = this._$dialog) {\n if (!$dialog) {\n this._teardownDialog();\n return;\n }\n\n if (this._$wired?.deref() === $dialog) {\n return;\n }\n\n this._teardownDialog();\n this._$wired = new WeakRef($dialog);\n\n if (import.meta.env.DEV) {\n const hasLabel =\n $dialog.hasAttribute('aria-labelledby') || $dialog.hasAttribute('aria-label');\n\n if (!hasLabel) {\n console.warn(\n '[rc-dialog] The inner <dialog> is missing aria-labelledby or ' +\n 'aria-label. Add one to satisfy the ARIA dialog pattern.',\n $dialog,\n );\n }\n\n if (\n $dialog.getAttribute('role') === 'alertdialog' &&\n !$dialog.hasAttribute('aria-describedby')\n ) {\n console.warn(\n '[rc-dialog] <dialog role=\"alertdialog\"> should have aria-describedby ' +\n 'pointing to the alert message text.',\n $dialog,\n );\n }\n\n if (!$dialog.querySelector('button:not([disabled])')) {\n console.warn(\n '[rc-dialog] No enabled <button> found inside <dialog>. APG recommends ' +\n 'including a visible close button in the tab sequence.',\n $dialog,\n );\n }\n }\n\n $dialog.addEventListener('close', this._onClose);\n $dialog.addEventListener('cancel', this._onCancel);\n\n if (this.lightDismiss && 'closedBy' in HTMLDialogElement.prototype) {\n $dialog.setAttribute('closedby', 'any');\n } else if (this.lightDismiss) {\n $dialog.addEventListener('click', this._onBackdropClick);\n } else {\n if (this.closedBy) {\n $dialog.setAttribute('closedby', this.closedBy);\n }\n }\n\n if (this.movable || this.moveHandle) {\n const $handle = this.moveHandle\n ? ($dialog.querySelector<Element>(this.moveHandle) ?? $dialog)\n : $dialog;\n\n new DragController(this, {\n target: $dialog,\n handle: $handle,\n bounds: this.moveBounds,\n step: this.moveStep,\n });\n }\n\n if (this.resize !== 'none') {\n // TODO: add a separate resize-bounds attribute; moveBounds is a proxy for now.\n new ResizeController(this, {\n target: $dialog,\n direction: this.resize,\n threshold: this.resizeThreshold,\n step: this.resizeStep,\n bounds: this.moveBounds,\n });\n }\n\n if (this._controlledOpen !== undefined) {\n this._applyOpen(this._controlledOpen, true, this.modal);\n } else if (this.defaultOpen) {\n this._applyOpen(true, true, this.modal);\n }\n }\n\n override updated(changed: PropertyValues) {\n const $dialog = this._$dialog;\n\n if (!$dialog) {\n return;\n }\n\n if (changed.has('closedBy')) {\n if (this.closedBy) {\n $dialog.setAttribute('closedby', this.closedBy);\n } else {\n $dialog.removeAttribute('closedby');\n }\n }\n\n if (changed.has('lightDismiss')) {\n if (this.lightDismiss && 'closedBy' in HTMLDialogElement.prototype) {\n // Native support available — delegate to closedby=\"any\" instead of JS handler.\n $dialog.setAttribute('closedby', 'any');\n $dialog.removeEventListener('click', this._onBackdropClick);\n } else if (this.lightDismiss) {\n $dialog.addEventListener('click', this._onBackdropClick);\n } else {\n $dialog.removeEventListener('click', this._onBackdropClick);\n\n if (this.closedBy) {\n $dialog.setAttribute('closedby', this.closedBy);\n } else {\n $dialog.removeAttribute('closedby');\n }\n }\n }\n }\n\n override disconnectedCallback() {\n this._teardownDialog();\n\n super.disconnectedCallback();\n }\n\n /** Removes all event listeners attached to the inner `<dialog>` and clears cached state. */\n protected _teardownDialog(): void {\n const $dialog = this._$wired?.deref();\n\n if (!$dialog) {\n return;\n }\n\n $dialog.removeEventListener('close', this._onClose);\n $dialog.removeEventListener('cancel', this._onCancel);\n $dialog.removeEventListener('click', this._onBackdropClick);\n\n this._$wired = null;\n this._$opener = null;\n }\n\n protected _onClose = () => {\n // Restore focus to the element that triggered the open, per APG focus management.\n if (this._$opener instanceof HTMLElement) {\n if (this._$opener.isConnected) {\n this._$opener.focus();\n } else {\n // Opener was removed from the DOM while the dialog was open; fall back\n // to body so focus is not left stranded.\n document.body.focus();\n }\n }\n\n this._$opener = null;\n\n this.dispatchEvent(\n new CustomEvent('rc-dialog-close', {\n bubbles: true,\n composed: true,\n detail: { returnValue: this.returnValue },\n }),\n );\n\n if (!this._suppressNextCloseToggle) {\n this._dispatchToggle(false);\n }\n\n this._suppressNextCloseToggle = false;\n this.requestUpdate('open');\n };\n\n /**\n * Intercepts the native `cancel` event.\n */\n protected _onCancel = (e: Event) => {\n const requestCloseEvent = new CustomEvent('rc-dialog-request-close', {\n bubbles: true,\n composed: true,\n cancelable: true,\n detail: { returnValue: this.returnValue },\n });\n const prevented = !this.dispatchEvent(requestCloseEvent);\n\n if (prevented) {\n e.preventDefault();\n } else {\n this.dispatchEvent(new CustomEvent('rc-dialog-cancel', { bubbles: true, composed: true }));\n }\n };\n\n /**\n * Detects backdrop clicks.\n */\n protected _onBackdropClick = (e: MouseEvent) => {\n if (e.target === this._$dialog) {\n this.requestClose();\n }\n };\n\n /**\n * Opens or closes the inner `<dialog>` and returns `true` if state actually changed.\n *\n * @param open - Whether to open (`true`) or close (`false`).\n * @param silent - When `true`, suppresses the outgoing `rc-dialog-toggle` event.\n * @param modal - Whether to call `showModal()` (`true`) or `show()` (`false`).\n */\n protected _applyOpen(open: boolean, silent: boolean, modal = true): boolean {\n const $dialog = this._$dialog;\n\n if (!$dialog) {\n return false;\n }\n\n if (open) {\n if ($dialog.open) {\n return false;\n }\n\n // Capture focus owner before the dialog steals it, so we can restore on close.\n this._$opener = document.activeElement;\n modal ? $dialog.showModal() : $dialog.show();\n this.requestUpdate('open');\n\n return true;\n }\n\n if (!$dialog.open) {\n return false;\n }\n\n this._suppressNextCloseToggle = silent;\n $dialog.close();\n this.requestUpdate('open');\n\n return true;\n }\n\n /** Dispatches `rc-dialog-toggle` with the current open state and return value. */\n protected _dispatchToggle(open: boolean): void {\n this.dispatchEvent(\n new CustomEvent('rc-dialog-toggle', {\n bubbles: true,\n composed: true,\n detail: { open, returnValue: this.returnValue },\n }),\n );\n }\n}\n\nexport default RCDialog;\n"],"names":["RCDialog","LitElement","NativeChildController","$dialog","requestCloseEvent","value","oldValue","returnValue","ev","nothing","$handle","DragController","ResizeController","changed","open","silent","modal","__decorateClass","property"],"mappings":"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"}
|