luxen-ui 0.21.5 → 0.22.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/cdn/custom-elements.json +24 -1
- package/cdn/elements/alert-dialog/alert-dialog.d.ts +1 -0
- package/cdn/elements/alert-dialog/alert-dialog.d.ts.map +1 -1
- package/cdn/elements/alert-dialog/alert-dialog.js.map +1 -1
- package/cdn/elements/dialog/dialog.d.ts +1 -0
- package/cdn/elements/dialog/dialog.d.ts.map +1 -1
- package/cdn/elements/dialog/dialog.js.map +1 -1
- package/cdn/elements/dialog/dialog.styles.js +1 -1
- package/cdn/elements/dialog/dialog.styles.js.map +1 -1
- package/cdn/elements/drawer/drawer.d.ts +2 -1
- package/cdn/elements/drawer/drawer.d.ts.map +1 -1
- package/cdn/elements/drawer/drawer.js +1 -1
- package/cdn/elements/drawer/drawer.js.map +1 -1
- package/dist/custom-elements.json +24 -1
- package/dist/elements/alert-dialog/alert-dialog.d.ts +1 -0
- package/dist/elements/alert-dialog/alert-dialog.d.ts.map +1 -1
- package/dist/elements/alert-dialog/alert-dialog.js +1 -0
- package/dist/elements/dialog/dialog.css +18 -1
- package/dist/elements/dialog/dialog.d.ts +1 -0
- package/dist/elements/dialog/dialog.d.ts.map +1 -1
- package/dist/elements/dialog/dialog.js +1 -0
- package/dist/elements/drawer/drawer.css +11 -0
- package/dist/elements/drawer/drawer.d.ts +2 -1
- package/dist/elements/drawer/drawer.d.ts.map +1 -1
- package/dist/elements/drawer/drawer.js +2 -1
- package/dist/metadata/alert-dialog.json +5 -0
- package/dist/metadata/dialog.json +5 -0
- package/dist/metadata/drawer.json +5 -0
- package/dist/metadata/index.json +16 -1
- package/dist/templates/elements/alert-dialog.md +1 -0
- package/dist/templates/elements/dialog.md +1 -0
- package/dist/templates/elements/drawer.md +1 -0
- package/package.json +1 -1
- package/templates/SKILL.md.tpl +2 -1
package/cdn/custom-elements.json
CHANGED
|
@@ -419,6 +419,15 @@
|
|
|
419
419
|
"module": "src/html/elements/dialog/dialog.ts"
|
|
420
420
|
}
|
|
421
421
|
},
|
|
422
|
+
{
|
|
423
|
+
"description": "Timing function of the open and close transitions, backdrop included.",
|
|
424
|
+
"name": "--easing",
|
|
425
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)",
|
|
426
|
+
"inheritedFrom": {
|
|
427
|
+
"name": "Dialog",
|
|
428
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
429
|
+
}
|
|
430
|
+
},
|
|
422
431
|
{
|
|
423
432
|
"description": "Backdrop color.",
|
|
424
433
|
"name": "--backdrop",
|
|
@@ -2743,6 +2752,11 @@
|
|
|
2743
2752
|
"name": "--hide-duration",
|
|
2744
2753
|
"default": "200ms"
|
|
2745
2754
|
},
|
|
2755
|
+
{
|
|
2756
|
+
"description": "Timing function of the open and close transitions, backdrop included.",
|
|
2757
|
+
"name": "--easing",
|
|
2758
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)"
|
|
2759
|
+
},
|
|
2746
2760
|
{
|
|
2747
2761
|
"description": "Backdrop color.",
|
|
2748
2762
|
"name": "--backdrop"
|
|
@@ -3202,7 +3216,7 @@
|
|
|
3202
3216
|
"name": "--shadow"
|
|
3203
3217
|
},
|
|
3204
3218
|
{
|
|
3205
|
-
"description": "Open transition duration. Default `
|
|
3219
|
+
"description": "Open transition duration. Default `300ms`.",
|
|
3206
3220
|
"name": "--show-duration",
|
|
3207
3221
|
"default": "200ms",
|
|
3208
3222
|
"inheritedFrom": {
|
|
@@ -3219,6 +3233,15 @@
|
|
|
3219
3233
|
"module": "src/html/elements/dialog/dialog.ts"
|
|
3220
3234
|
}
|
|
3221
3235
|
},
|
|
3236
|
+
{
|
|
3237
|
+
"description": "Timing function of the open and close transitions, backdrop included. Default `cubic-bezier(0.32, 0.72, 0, 1)`.",
|
|
3238
|
+
"name": "--easing",
|
|
3239
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)",
|
|
3240
|
+
"inheritedFrom": {
|
|
3241
|
+
"name": "Dialog",
|
|
3242
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
3243
|
+
}
|
|
3244
|
+
},
|
|
3222
3245
|
{
|
|
3223
3246
|
"description": "Backdrop color.",
|
|
3224
3247
|
"name": "--backdrop",
|
|
@@ -47,6 +47,7 @@ export declare class CancelEvent extends Event {
|
|
|
47
47
|
* @cssproperty [--padding=1.5rem] - Padding applied to the header, footer, and inline-padding of the body.
|
|
48
48
|
* @cssproperty [--show-duration=200ms] - Open transition duration.
|
|
49
49
|
* @cssproperty [--hide-duration=200ms] - Close transition duration.
|
|
50
|
+
* @cssproperty [--easing=cubic-bezier(0.32, 0.72, 0, 1)] - Timing function of the open and close transitions, backdrop included.
|
|
50
51
|
* @cssproperty --backdrop - Backdrop color.
|
|
51
52
|
* @cssproperty [--backdrop-blur=0] - Backdrop blur amount (any CSS length).
|
|
52
53
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert-dialog.d.ts","sourceRoot":"","sources":["../../../src/html/elements/alert-dialog/alert-dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAUpE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAI7C,OAAO,qBAAqB,CAAC;AAU7B;;;;;;GAMG;AACH,qBAAa,YAAa,SAAQ,KAAK;;CAItC;AAED;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,KAAK;;CAIrC;AAED
|
|
1
|
+
{"version":3,"file":"alert-dialog.d.ts","sourceRoot":"","sources":["../../../src/html/elements/alert-dialog/alert-dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAUpE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAI7C,OAAO,qBAAqB,CAAC;AAU7B;;;;;;GAMG;AACH,qBAAa,YAAa,SAAQ,KAAK;;CAItC;AAED;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,KAAK;;CAIrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,qBAAa,WAAY,SAAQ,MAAM;IACrC,OAAgB,MAAM,4BAAyD;IAE/E,oCAAoC;IAEpC,WAAW,SAAa;IAExB,mCAAmC;IAEnC,UAAU,SAAY;IAEtB,uEAAuE;IAEvE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAEhB;2DACuD;IAEvD,OAAO,UAAS;IAEhB,cAAuB,KAAK,WAE3B;IAID,OAAO,CAAC,YAAY,CAA4C;IAChE,cAAuB,OAAO,uBAE7B;cAKkB,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC;cAOxC,SAAS,CAAC,CAAC,EAAE,KAAK;cAUlB,aAAa;IAehC,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,cAAc,CASpB;cAEiB,YAAY;CAqChC;AAMD,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CACd,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,KAAK,IAAI,EACvD,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,gBAAgB,CACd,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,KAAK,IAAI,EACtD,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,KAAK,IAAI,EACvD,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,KAAK,IAAI,EACtD,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert-dialog.js","names":[],"sources":["../../../src/html/elements/alert-dialog/alert-dialog.css?inline","../../../src/html/elements/alert-dialog/alert-dialog.ts"],"sourcesContent":["/*\n * Layout for l-alert-dialog. Unlayered to match dialog.css (the inherited\n * shared styles) so these overrides win — inside a shadow root there's no host\n * cascade to guard against, and layered rules can't override dialog.css's\n * unlayered ones. The `.l-button` appearance comes from the shared button-core\n * (imported in alert-dialog.ts), not from here.\n *\n * Visual rhythm: a confirmation reads better with the title and description\n * grouped tight and the actions set off in their own bar.\n */\n\n/* Interruptive by nature: a stronger backdrop (the token meant for immersive\n overlays) plus a touch of blur pulls focus firmly onto the confirmation.\n Consumers can still retune --backdrop / --backdrop-blur. */\n:host {\n --backdrop: var(--l-backdrop-strong);\n --backdrop-blur: 2px;\n}\n\n/* Pull the description up close under the title (title keeps the inherited\n 1.125rem / 600 from dialog.css). */\n[part='header'] {\n padding-block-end: 0.5rem;\n}\n\n/* Muted, smaller description with a comfortable reading measure, plus its own\n block-end gap so the footer divider isn't crowded. */\n[part='body'] {\n padding-block-end: var(--padding);\n color: var(--l-color-text-secondary);\n font-size: var(--l-text-sm);\n line-height: 1.5;\n}\n\n/* Footer as a distinct action bar: subtle fill + top divider, corners rounded\n to match the dialog (which doesn't clip its overflow). */\n[part='footer'] {\n padding: 1rem var(--padding);\n border-top: 1px solid var(--l-color-border);\n background: var(--l-color-bg-fill-neutral-subtle);\n border-end-start-radius: var(--border-radius);\n border-end-end-radius: var(--border-radius);\n}\n","import { html, nothing, unsafeCSS, type PropertyValues } from 'lit';\n// Only the spinner fragment needs the static tag function; the outer template\n// stays on lit's `html` so `renderFooter()` keeps the return type `Dialog`\n// declares. A static-html result nests inside a regular one just fine.\nimport { html as staticHtml } from 'lit/static-html.js';\nimport { property } from 'lit/decorators.js';\nimport { cls } from '../../registry.js';\nimport { staticTag } from '../../static-tag.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport { HasSlotController } from '../../shared/controllers/has-slot-controller.js';\nimport { Dialog } from '../dialog/dialog.js';\nimport dialogStyles from '../dialog/dialog.styles.js';\nimport buttonStyles from '../../shared/styles/button-core.styles.js';\nimport rawAlertStyles from './alert-dialog.css?inline';\nimport '../spinner/index.js';\n\n// The built-in actions render as `.l-button`, styled inside the shadow root from\n// the SAME shared button-core as the light-DOM `.l-button` (single source of\n// truth — no copy to drift). alert-dialog.css adds only the dialog layout.\n// The class is emitted through `cls('button')` so it tracks a renamed\n// `cssPrefix` — button-core.css ships as a real CSS file the consumer's postcss\n// re-prefixes, and a static literal would desync from it (see button-core.css).\nconst alertStyles = unsafeCSS(rawAlertStyles);\n\n/**\n * Fired when the user accepts an alert dialog (the confirm action). Cancelable —\n * call `event.preventDefault()` to keep the dialog open (e.g. to await an async\n * task); close it yourself afterwards by setting `open = false`.\n *\n * Does not bubble and is not composed: listen on the element itself.\n */\nexport class ConfirmEvent extends Event {\n constructor() {\n super('confirm', { bubbles: false, composed: false, cancelable: true });\n }\n}\n\n/**\n * Fired when the user dismisses an alert dialog (the cancel action, Escape, or a\n * close request). Cancelable — call `event.preventDefault()` to keep it open.\n *\n * Does not bubble and is not composed: listen on the element itself.\n */\nexport class CancelEvent extends Event {\n constructor() {\n super('cancel', { bubbles: false, composed: false, cancelable: true });\n }\n}\n\n/**\n * An interruptive confirmation dialog built on `<l-dialog>`. Renders its own\n * cancel/confirm actions and exposes `role=\"alertdialog\"`. Use it to confirm a\n * consequential action (delete, publish, discard) — not for generic content.\n *\n * Open and close by toggling the `open` property (or the `--show` / `--hide`\n * Invoker commands). The dialog closes automatically when the user picks an\n * action, unless the matching `confirm` / `cancel` event is canceled.\n *\n * @slot - Description text. Provides the dialog's accessible description.\n * @slot title - Custom heading element. Overrides the default `<h2>` rendered from the `title` property. Also provides the dialog's accessible name.\n * @slot cancel - Replaces the built-in cancel action (e.g. a link). Keep it focusable.\n * @slot confirm - Replaces the built-in confirm action.\n *\n * @csspart dialog - The native `<dialog>` element.\n * @csspart header - The header wrapper containing the title.\n * @csspart title - The dialog title heading.\n * @csspart body - The body wrapper around the description.\n * @csspart footer - The footer wrapper around the actions.\n * @csspart button - Both built-in action buttons.\n * @csspart cancel - The built-in cancel button.\n * @csspart confirm - The built-in confirm button.\n *\n * @cssproperty [--width=31rem] - Dialog width.\n * @cssproperty [--border-radius=6px] - Dialog border radius.\n * @cssproperty [--padding=1.5rem] - Padding applied to the header, footer, and inline-padding of the body.\n * @cssproperty [--show-duration=200ms] - Open transition duration.\n * @cssproperty [--hide-duration=200ms] - Close transition duration.\n * @cssproperty --backdrop - Backdrop color.\n * @cssproperty [--backdrop-blur=0] - Backdrop blur amount (any CSS length).\n *\n * @event confirm - Fired when the user accepts. Cancelable — `preventDefault()` keeps it open for async work.\n * @event cancel - Fired when the user dismisses (cancel action, Escape). Cancelable — `preventDefault()` keeps it open.\n * @event show - Fired when the dialog is about to open. Cancelable.\n * @event hide - Fired when the dialog is about to close via the `open` property. Cancelable. (The confirm, cancel, and Escape paths close natively and emit `confirm`/`cancel` instead of `hide`.)\n * @event after-show - Fired after the open animation completes. Not cancelable.\n * @event after-hide - Fired after the close animation completes. Not cancelable.\n *\n * @command --show - Sets `open = true`.\n * @command --hide - Sets `open = false`.\n *\n * @customElement l-alert-dialog\n */\n// oxlint-disable-next-line typescript/no-unsafe-declaration-merging -- typed addEventListener overloads merged below.\nexport class AlertDialog extends Dialog {\n static override styles = [hostStyles, dialogStyles, buttonStyles, alertStyles];\n\n /** Label for the confirm action. */\n @property({ attribute: 'confirm-text' })\n confirmText = 'Confirm';\n\n /** Label for the cancel action. */\n @property({ attribute: 'cancel-text' })\n cancelText = 'Cancel';\n\n /** Visual tone. `danger` renders the confirm action as destructive. */\n @property({ reflect: true })\n tone?: 'danger';\n\n /** Show a busy state on the confirm action (spinner + `aria-disabled`); the\n * cancel action stays operable as an escape hatch. */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n protected override get _role() {\n return 'alertdialog';\n }\n\n // Wire aria-describedby to the body only when it actually has content, so a\n // title-only confirmation doesn't advertise an empty description.\n private _bodyContent = new HasSlotController(this, '[default]');\n protected override get _bodyId() {\n return this._bodyContent.test('[default]') ? 'description' : '';\n }\n\n // Alert dialogs are interruptive: they are never dismissable by clicking\n // outside, so the inherited `light-dismiss` is forced off (a vetoed dismissal\n // gesture must go through an explicit action).\n protected override willUpdate(changed: PropertyValues<this>) {\n super.willUpdate(changed);\n if (this.lightDismiss) this.lightDismiss = false;\n }\n\n // Native Escape / close request → cancel intent. A vetoed `cancel` keeps the\n // dialog open; otherwise the native close proceeds (emitting `after-hide`).\n protected override _onCancel(e: Event) {\n if (!this.dispatchEvent(new CancelEvent())) e.preventDefault();\n }\n\n // Focus the least destructive action on open: an author `[autofocus]`, else\n // the slotted cancel action, else the built-in cancel button (in shadow DOM,\n // so the base light-DOM lookup can't reach it). Try each in order and keep the\n // first that actually takes focus — this skips a non-focusable slotted cancel\n // without rejecting a focusable one that reports `tabIndex === -1` (a custom\n // element with `delegatesFocus`, `<div role=\"button\" tabindex=\"0\">`, etc.).\n protected override _focusInitial() {\n const candidates = [\n this.querySelector<HTMLElement>('[autofocus]'),\n this.querySelector<HTMLElement>('[slot=\"cancel\"]'),\n this.renderRoot.querySelector<HTMLElement>('[data-cancel]'),\n ];\n for (const el of candidates) {\n if (!el || el.matches('[disabled], [aria-disabled=\"true\"]')) continue;\n el.focus({ preventScroll: true });\n // `document.activeElement` resolves to the shadow host when focus lands\n // inside an open shadow root, so this also covers delegatesFocus.\n if (el === document.activeElement || el.contains(document.activeElement)) return;\n }\n }\n\n private _close() {\n // Close natively rather than via `open = false` so we don't also emit the\n // inherited cancelable `hide` — `confirm` / `cancel` are the intent events.\n if (this.dialog.open) this.dialog.close();\n }\n\n // Activate an action unless its control is disabled. The built-in confirm also\n // respects `loading` via the property — immune to render timing, so a fast\n // second click in the window before `aria-disabled` is flushed can't fire a\n // duplicate confirm mid-async. A slotted action the consumer drives carries no\n // disabled state unless the author adds one, so it stays operable.\n private _activate(el: Element, event: ConfirmEvent | CancelEvent) {\n if (el.hasAttribute('data-confirm') && this.loading) return;\n if (el.matches('[disabled], [aria-disabled=\"true\"]')) return;\n if (this.dispatchEvent(event)) this._close();\n }\n\n // Single delegated handler covering both the built-in buttons (marked with\n // `data-confirm` / `data-cancel`) and slotted replacements (`slot=\"confirm\"` /\n // `slot=\"cancel\"`). `composedPath()` flattens across the slot boundary, so a\n // click on light-DOM slotted content still resolves here.\n private _onFooterClick = (e: Event) => {\n for (const node of e.composedPath()) {\n if (node === e.currentTarget) break;\n if (!(node instanceof Element)) continue;\n if (node.matches('[slot=\"confirm\"], [data-confirm]'))\n return this._activate(node, new ConfirmEvent());\n if (node.matches('[slot=\"cancel\"], [data-cancel]'))\n return this._activate(node, new CancelEvent());\n }\n };\n\n protected override renderFooter() {\n const confirmVariant = this.tone === 'danger' ? 'destructive' : 'primary';\n const spinnerTag = staticTag('spinner');\n return html`\n <footer\n part=\"footer\"\n @click=${this._onFooterClick}\n >\n <slot name=\"cancel\">\n <button\n part=\"button cancel\"\n class=${cls('button')}\n type=\"button\"\n data-cancel\n >\n ${this.cancelText}\n </button>\n </slot>\n <slot name=\"confirm\">\n <button\n part=\"button confirm\"\n class=${cls('button')}\n type=\"button\"\n data-confirm\n data-variant=${confirmVariant}\n aria-disabled=${this.loading ? 'true' : nothing}\n aria-busy=${this.loading ? 'true' : nothing}\n >\n ${this.loading\n ? staticHtml`<${spinnerTag} aria-hidden=\"true\"></${spinnerTag}>`\n : nothing}\n ${this.confirmText}\n </button>\n </slot>\n </footer>\n `;\n }\n}\n\n// `confirm` and `cancel` collide with lib.dom's event maps, so we cannot augment\n// the global map (as the shared lifecycle events do). Declaration-merge typed\n// listener overloads onto the element instead — must come after the class so the\n// CEM analyzer reads the class first.\nexport interface AlertDialog {\n addEventListener(\n type: 'confirm',\n listener: (this: AlertDialog, ev: ConfirmEvent) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: 'cancel',\n listener: (this: AlertDialog, ev: CancelEvent) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n removeEventListener(\n type: 'confirm',\n listener: (this: AlertDialog, ev: ConfirmEvent) => void,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: 'cancel',\n listener: (this: AlertDialog, ev: CancelEvent) => void,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n}\n"],"mappings":"8iBCsBA,IAAM,EAAc,EAAU,gcAAc,EAS/B,EAAb,cAAkC,KAAM,CACtC,aAAc,CACZ,MAAM,UAAW,CAAE,QAAS,GAAO,SAAU,GAAO,WAAY,EAAK,CAAC,CACxE,CACF,EAQa,EAAb,cAAiC,KAAM,CACrC,aAAc,CACZ,MAAM,SAAU,CAAE,QAAS,GAAO,SAAU,GAAO,WAAY,EAAK,CAAC,CACvE,CACF,EA8Ca,EAAb,cAAiC,CAAO,gDAKxB,0BAID,sBASH,qBAQa,IAAI,EAAkB,KAAM,WAAW,sBA6DpC,GAAa,CACrC,IAAK,IAAM,KAAQ,EAAE,aAAa,EAAG,CACnC,GAAI,IAAS,EAAE,cAAe,MACxB,gBAAgB,QACtB,IAAI,EAAK,QAAQ,kCAAkC,EACjD,OAAO,KAAK,UAAU,EAAM,IAAI,CAAc,EAChD,GAAI,EAAK,QAAQ,gCAAgC,EAC/C,OAAO,KAAK,UAAU,EAAM,IAAI,CAAa,CAFC,CAGlD,CACF,qBA/FyB,CAAC,EAAY,EAAc,EAAc,CAAW,EAmB7E,IAAuB,OAAQ,CAC7B,MAAO,aACT,CAKA,IAAuB,SAAU,CAC/B,OAAO,KAAK,aAAa,KAAK,WAAW,EAAI,cAAgB,EAC/D,CAKA,WAA8B,EAA+B,CAC3D,MAAM,WAAW,CAAO,EACxB,AAAuB,KAAK,eAAe,EAC7C,CAIA,UAA6B,EAAU,CAChC,KAAK,cAAc,IAAI,CAAa,GAAG,EAAE,eAAe,CAC/D,CAQA,eAAmC,CACjC,IAAM,EAAa,CACjB,KAAK,cAA2B,aAAa,EAC7C,KAAK,cAA2B,iBAAiB,EACjD,KAAK,WAAW,cAA2B,eAAe,CAC5D,EACA,IAAK,IAAM,KAAM,EACX,MAAC,GAAM,EAAG,QAAQ,oCAAoC,KAC1D,EAAG,MAAM,CAAE,cAAe,EAAK,CAAC,EAG5B,IAAO,SAAS,eAAiB,EAAG,SAAS,SAAS,aAAa,GAAG,MAE9E,CAEA,QAAiB,CAGX,KAAK,OAAO,MAAM,KAAK,OAAO,MAAM,CAC1C,CAOA,UAAkB,EAAa,EAAmC,CAC5D,EAAG,aAAa,cAAc,GAAK,KAAK,SACxC,EAAG,QAAQ,oCAAoC,GAC/C,KAAK,cAAc,CAAK,GAAG,KAAK,OAAO,CAC7C,CAiBA,cAAkC,CAChC,IAAM,EAAiB,KAAK,OAAS,SAAW,cAAgB,UAC1D,EAAa,EAAU,SAAS,EACtC,MAAO,EAAI;;;iBAGE,KAAK,eAAe;;;;;oBAKjB,EAAI,QAAQ,EAAE;;;;cAIpB,KAAK,WAAW;;;;;;oBAMV,EAAI,QAAQ,EAAE;;;2BAGP,EAAe;4BACd,KAAK,QAAU,OAAS,EAAQ;wBACpC,KAAK,QAAU,OAAS,EAAQ;;cAE1C,KAAK,QACH,CAAU,IAAI,EAAW,wBAAwB,EAAW,GAC5D,EAAQ;cACV,KAAK,YAAY;;;;KAK7B,CACF,KAnIG,EAAS,CAAE,UAAW,cAAe,CAAC,CAAA,EAAA,EAAA,UAAA,cAAA,IAAA,EAAA,KAItC,EAAS,CAAE,UAAW,aAAc,CAAC,CAAA,EAAA,EAAA,UAAA,aAAA,IAAA,EAAA,KAIrC,EAAS,CAAE,QAAS,EAAK,CAAC,CAAA,EAAA,EAAA,UAAA,OAAA,IAAA,EAAA,KAK1B,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,CAAA,EAAA,EAAA,UAAA,UAAA,IAAA,EAAA"}
|
|
1
|
+
{"version":3,"file":"alert-dialog.js","names":[],"sources":["../../../src/html/elements/alert-dialog/alert-dialog.css?inline","../../../src/html/elements/alert-dialog/alert-dialog.ts"],"sourcesContent":["/*\n * Layout for l-alert-dialog. Unlayered to match dialog.css (the inherited\n * shared styles) so these overrides win — inside a shadow root there's no host\n * cascade to guard against, and layered rules can't override dialog.css's\n * unlayered ones. The `.l-button` appearance comes from the shared button-core\n * (imported in alert-dialog.ts), not from here.\n *\n * Visual rhythm: a confirmation reads better with the title and description\n * grouped tight and the actions set off in their own bar.\n */\n\n/* Interruptive by nature: a stronger backdrop (the token meant for immersive\n overlays) plus a touch of blur pulls focus firmly onto the confirmation.\n Consumers can still retune --backdrop / --backdrop-blur. */\n:host {\n --backdrop: var(--l-backdrop-strong);\n --backdrop-blur: 2px;\n}\n\n/* Pull the description up close under the title (title keeps the inherited\n 1.125rem / 600 from dialog.css). */\n[part='header'] {\n padding-block-end: 0.5rem;\n}\n\n/* Muted, smaller description with a comfortable reading measure, plus its own\n block-end gap so the footer divider isn't crowded. */\n[part='body'] {\n padding-block-end: var(--padding);\n color: var(--l-color-text-secondary);\n font-size: var(--l-text-sm);\n line-height: 1.5;\n}\n\n/* Footer as a distinct action bar: subtle fill + top divider, corners rounded\n to match the dialog (which doesn't clip its overflow). */\n[part='footer'] {\n padding: 1rem var(--padding);\n border-top: 1px solid var(--l-color-border);\n background: var(--l-color-bg-fill-neutral-subtle);\n border-end-start-radius: var(--border-radius);\n border-end-end-radius: var(--border-radius);\n}\n","import { html, nothing, unsafeCSS, type PropertyValues } from 'lit';\n// Only the spinner fragment needs the static tag function; the outer template\n// stays on lit's `html` so `renderFooter()` keeps the return type `Dialog`\n// declares. A static-html result nests inside a regular one just fine.\nimport { html as staticHtml } from 'lit/static-html.js';\nimport { property } from 'lit/decorators.js';\nimport { cls } from '../../registry.js';\nimport { staticTag } from '../../static-tag.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport { HasSlotController } from '../../shared/controllers/has-slot-controller.js';\nimport { Dialog } from '../dialog/dialog.js';\nimport dialogStyles from '../dialog/dialog.styles.js';\nimport buttonStyles from '../../shared/styles/button-core.styles.js';\nimport rawAlertStyles from './alert-dialog.css?inline';\nimport '../spinner/index.js';\n\n// The built-in actions render as `.l-button`, styled inside the shadow root from\n// the SAME shared button-core as the light-DOM `.l-button` (single source of\n// truth — no copy to drift). alert-dialog.css adds only the dialog layout.\n// The class is emitted through `cls('button')` so it tracks a renamed\n// `cssPrefix` — button-core.css ships as a real CSS file the consumer's postcss\n// re-prefixes, and a static literal would desync from it (see button-core.css).\nconst alertStyles = unsafeCSS(rawAlertStyles);\n\n/**\n * Fired when the user accepts an alert dialog (the confirm action). Cancelable —\n * call `event.preventDefault()` to keep the dialog open (e.g. to await an async\n * task); close it yourself afterwards by setting `open = false`.\n *\n * Does not bubble and is not composed: listen on the element itself.\n */\nexport class ConfirmEvent extends Event {\n constructor() {\n super('confirm', { bubbles: false, composed: false, cancelable: true });\n }\n}\n\n/**\n * Fired when the user dismisses an alert dialog (the cancel action, Escape, or a\n * close request). Cancelable — call `event.preventDefault()` to keep it open.\n *\n * Does not bubble and is not composed: listen on the element itself.\n */\nexport class CancelEvent extends Event {\n constructor() {\n super('cancel', { bubbles: false, composed: false, cancelable: true });\n }\n}\n\n/**\n * An interruptive confirmation dialog built on `<l-dialog>`. Renders its own\n * cancel/confirm actions and exposes `role=\"alertdialog\"`. Use it to confirm a\n * consequential action (delete, publish, discard) — not for generic content.\n *\n * Open and close by toggling the `open` property (or the `--show` / `--hide`\n * Invoker commands). The dialog closes automatically when the user picks an\n * action, unless the matching `confirm` / `cancel` event is canceled.\n *\n * @slot - Description text. Provides the dialog's accessible description.\n * @slot title - Custom heading element. Overrides the default `<h2>` rendered from the `title` property. Also provides the dialog's accessible name.\n * @slot cancel - Replaces the built-in cancel action (e.g. a link). Keep it focusable.\n * @slot confirm - Replaces the built-in confirm action.\n *\n * @csspart dialog - The native `<dialog>` element.\n * @csspart header - The header wrapper containing the title.\n * @csspart title - The dialog title heading.\n * @csspart body - The body wrapper around the description.\n * @csspart footer - The footer wrapper around the actions.\n * @csspart button - Both built-in action buttons.\n * @csspart cancel - The built-in cancel button.\n * @csspart confirm - The built-in confirm button.\n *\n * @cssproperty [--width=31rem] - Dialog width.\n * @cssproperty [--border-radius=6px] - Dialog border radius.\n * @cssproperty [--padding=1.5rem] - Padding applied to the header, footer, and inline-padding of the body.\n * @cssproperty [--show-duration=200ms] - Open transition duration.\n * @cssproperty [--hide-duration=200ms] - Close transition duration.\n * @cssproperty [--easing=cubic-bezier(0.32, 0.72, 0, 1)] - Timing function of the open and close transitions, backdrop included.\n * @cssproperty --backdrop - Backdrop color.\n * @cssproperty [--backdrop-blur=0] - Backdrop blur amount (any CSS length).\n *\n * @event confirm - Fired when the user accepts. Cancelable — `preventDefault()` keeps it open for async work.\n * @event cancel - Fired when the user dismisses (cancel action, Escape). Cancelable — `preventDefault()` keeps it open.\n * @event show - Fired when the dialog is about to open. Cancelable.\n * @event hide - Fired when the dialog is about to close via the `open` property. Cancelable. (The confirm, cancel, and Escape paths close natively and emit `confirm`/`cancel` instead of `hide`.)\n * @event after-show - Fired after the open animation completes. Not cancelable.\n * @event after-hide - Fired after the close animation completes. Not cancelable.\n *\n * @command --show - Sets `open = true`.\n * @command --hide - Sets `open = false`.\n *\n * @customElement l-alert-dialog\n */\n// oxlint-disable-next-line typescript/no-unsafe-declaration-merging -- typed addEventListener overloads merged below.\nexport class AlertDialog extends Dialog {\n static override styles = [hostStyles, dialogStyles, buttonStyles, alertStyles];\n\n /** Label for the confirm action. */\n @property({ attribute: 'confirm-text' })\n confirmText = 'Confirm';\n\n /** Label for the cancel action. */\n @property({ attribute: 'cancel-text' })\n cancelText = 'Cancel';\n\n /** Visual tone. `danger` renders the confirm action as destructive. */\n @property({ reflect: true })\n tone?: 'danger';\n\n /** Show a busy state on the confirm action (spinner + `aria-disabled`); the\n * cancel action stays operable as an escape hatch. */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n protected override get _role() {\n return 'alertdialog';\n }\n\n // Wire aria-describedby to the body only when it actually has content, so a\n // title-only confirmation doesn't advertise an empty description.\n private _bodyContent = new HasSlotController(this, '[default]');\n protected override get _bodyId() {\n return this._bodyContent.test('[default]') ? 'description' : '';\n }\n\n // Alert dialogs are interruptive: they are never dismissable by clicking\n // outside, so the inherited `light-dismiss` is forced off (a vetoed dismissal\n // gesture must go through an explicit action).\n protected override willUpdate(changed: PropertyValues<this>) {\n super.willUpdate(changed);\n if (this.lightDismiss) this.lightDismiss = false;\n }\n\n // Native Escape / close request → cancel intent. A vetoed `cancel` keeps the\n // dialog open; otherwise the native close proceeds (emitting `after-hide`).\n protected override _onCancel(e: Event) {\n if (!this.dispatchEvent(new CancelEvent())) e.preventDefault();\n }\n\n // Focus the least destructive action on open: an author `[autofocus]`, else\n // the slotted cancel action, else the built-in cancel button (in shadow DOM,\n // so the base light-DOM lookup can't reach it). Try each in order and keep the\n // first that actually takes focus — this skips a non-focusable slotted cancel\n // without rejecting a focusable one that reports `tabIndex === -1` (a custom\n // element with `delegatesFocus`, `<div role=\"button\" tabindex=\"0\">`, etc.).\n protected override _focusInitial() {\n const candidates = [\n this.querySelector<HTMLElement>('[autofocus]'),\n this.querySelector<HTMLElement>('[slot=\"cancel\"]'),\n this.renderRoot.querySelector<HTMLElement>('[data-cancel]'),\n ];\n for (const el of candidates) {\n if (!el || el.matches('[disabled], [aria-disabled=\"true\"]')) continue;\n el.focus({ preventScroll: true });\n // `document.activeElement` resolves to the shadow host when focus lands\n // inside an open shadow root, so this also covers delegatesFocus.\n if (el === document.activeElement || el.contains(document.activeElement)) return;\n }\n }\n\n private _close() {\n // Close natively rather than via `open = false` so we don't also emit the\n // inherited cancelable `hide` — `confirm` / `cancel` are the intent events.\n if (this.dialog.open) this.dialog.close();\n }\n\n // Activate an action unless its control is disabled. The built-in confirm also\n // respects `loading` via the property — immune to render timing, so a fast\n // second click in the window before `aria-disabled` is flushed can't fire a\n // duplicate confirm mid-async. A slotted action the consumer drives carries no\n // disabled state unless the author adds one, so it stays operable.\n private _activate(el: Element, event: ConfirmEvent | CancelEvent) {\n if (el.hasAttribute('data-confirm') && this.loading) return;\n if (el.matches('[disabled], [aria-disabled=\"true\"]')) return;\n if (this.dispatchEvent(event)) this._close();\n }\n\n // Single delegated handler covering both the built-in buttons (marked with\n // `data-confirm` / `data-cancel`) and slotted replacements (`slot=\"confirm\"` /\n // `slot=\"cancel\"`). `composedPath()` flattens across the slot boundary, so a\n // click on light-DOM slotted content still resolves here.\n private _onFooterClick = (e: Event) => {\n for (const node of e.composedPath()) {\n if (node === e.currentTarget) break;\n if (!(node instanceof Element)) continue;\n if (node.matches('[slot=\"confirm\"], [data-confirm]'))\n return this._activate(node, new ConfirmEvent());\n if (node.matches('[slot=\"cancel\"], [data-cancel]'))\n return this._activate(node, new CancelEvent());\n }\n };\n\n protected override renderFooter() {\n const confirmVariant = this.tone === 'danger' ? 'destructive' : 'primary';\n const spinnerTag = staticTag('spinner');\n return html`\n <footer\n part=\"footer\"\n @click=${this._onFooterClick}\n >\n <slot name=\"cancel\">\n <button\n part=\"button cancel\"\n class=${cls('button')}\n type=\"button\"\n data-cancel\n >\n ${this.cancelText}\n </button>\n </slot>\n <slot name=\"confirm\">\n <button\n part=\"button confirm\"\n class=${cls('button')}\n type=\"button\"\n data-confirm\n data-variant=${confirmVariant}\n aria-disabled=${this.loading ? 'true' : nothing}\n aria-busy=${this.loading ? 'true' : nothing}\n >\n ${this.loading\n ? staticHtml`<${spinnerTag} aria-hidden=\"true\"></${spinnerTag}>`\n : nothing}\n ${this.confirmText}\n </button>\n </slot>\n </footer>\n `;\n }\n}\n\n// `confirm` and `cancel` collide with lib.dom's event maps, so we cannot augment\n// the global map (as the shared lifecycle events do). Declaration-merge typed\n// listener overloads onto the element instead — must come after the class so the\n// CEM analyzer reads the class first.\nexport interface AlertDialog {\n addEventListener(\n type: 'confirm',\n listener: (this: AlertDialog, ev: ConfirmEvent) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: 'cancel',\n listener: (this: AlertDialog, ev: CancelEvent) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n removeEventListener(\n type: 'confirm',\n listener: (this: AlertDialog, ev: ConfirmEvent) => void,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: 'cancel',\n listener: (this: AlertDialog, ev: CancelEvent) => void,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n}\n"],"mappings":"8iBCsBA,IAAM,EAAc,EAAU,gcAAc,EAS/B,EAAb,cAAkC,KAAM,CACtC,aAAc,CACZ,MAAM,UAAW,CAAE,QAAS,GAAO,SAAU,GAAO,WAAY,EAAK,CAAC,CACxE,CACF,EAQa,EAAb,cAAiC,KAAM,CACrC,aAAc,CACZ,MAAM,SAAU,CAAE,QAAS,GAAO,SAAU,GAAO,WAAY,EAAK,CAAC,CACvE,CACF,EA+Ca,EAAb,cAAiC,CAAO,gDAKxB,0BAID,sBASH,qBAQa,IAAI,EAAkB,KAAM,WAAW,sBA6DpC,GAAa,CACrC,IAAK,IAAM,KAAQ,EAAE,aAAa,EAAG,CACnC,GAAI,IAAS,EAAE,cAAe,MACxB,gBAAgB,QACtB,IAAI,EAAK,QAAQ,kCAAkC,EACjD,OAAO,KAAK,UAAU,EAAM,IAAI,CAAc,EAChD,GAAI,EAAK,QAAQ,gCAAgC,EAC/C,OAAO,KAAK,UAAU,EAAM,IAAI,CAAa,CAFC,CAGlD,CACF,qBA/FyB,CAAC,EAAY,EAAc,EAAc,CAAW,EAmB7E,IAAuB,OAAQ,CAC7B,MAAO,aACT,CAKA,IAAuB,SAAU,CAC/B,OAAO,KAAK,aAAa,KAAK,WAAW,EAAI,cAAgB,EAC/D,CAKA,WAA8B,EAA+B,CAC3D,MAAM,WAAW,CAAO,EACxB,AAAuB,KAAK,eAAe,EAC7C,CAIA,UAA6B,EAAU,CAChC,KAAK,cAAc,IAAI,CAAa,GAAG,EAAE,eAAe,CAC/D,CAQA,eAAmC,CACjC,IAAM,EAAa,CACjB,KAAK,cAA2B,aAAa,EAC7C,KAAK,cAA2B,iBAAiB,EACjD,KAAK,WAAW,cAA2B,eAAe,CAC5D,EACA,IAAK,IAAM,KAAM,EACX,MAAC,GAAM,EAAG,QAAQ,oCAAoC,KAC1D,EAAG,MAAM,CAAE,cAAe,EAAK,CAAC,EAG5B,IAAO,SAAS,eAAiB,EAAG,SAAS,SAAS,aAAa,GAAG,MAE9E,CAEA,QAAiB,CAGX,KAAK,OAAO,MAAM,KAAK,OAAO,MAAM,CAC1C,CAOA,UAAkB,EAAa,EAAmC,CAC5D,EAAG,aAAa,cAAc,GAAK,KAAK,SACxC,EAAG,QAAQ,oCAAoC,GAC/C,KAAK,cAAc,CAAK,GAAG,KAAK,OAAO,CAC7C,CAiBA,cAAkC,CAChC,IAAM,EAAiB,KAAK,OAAS,SAAW,cAAgB,UAC1D,EAAa,EAAU,SAAS,EACtC,MAAO,EAAI;;;iBAGE,KAAK,eAAe;;;;;oBAKjB,EAAI,QAAQ,EAAE;;;;cAIpB,KAAK,WAAW;;;;;;oBAMV,EAAI,QAAQ,EAAE;;;2BAGP,EAAe;4BACd,KAAK,QAAU,OAAS,EAAQ;wBACpC,KAAK,QAAU,OAAS,EAAQ;;cAE1C,KAAK,QACH,CAAU,IAAI,EAAW,wBAAwB,EAAW,GAC5D,EAAQ;cACV,KAAK,YAAY;;;;KAK7B,CACF,KAnIG,EAAS,CAAE,UAAW,cAAe,CAAC,CAAA,EAAA,EAAA,UAAA,cAAA,IAAA,EAAA,KAItC,EAAS,CAAE,UAAW,aAAc,CAAC,CAAA,EAAA,EAAA,UAAA,aAAA,IAAA,EAAA,KAIrC,EAAS,CAAE,QAAS,EAAK,CAAC,CAAA,EAAA,EAAA,UAAA,OAAA,IAAA,EAAA,KAK1B,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,CAAA,EAAA,EAAA,UAAA,UAAA,IAAA,EAAA"}
|
|
@@ -22,6 +22,7 @@ import { LuxenElement } from '../../shared/luxen-element.js';
|
|
|
22
22
|
* @cssproperty [--padding=1.5rem] - Padding applied to the header, footer, and inline-padding of the body. Set to `0` to remove all internal spacing (e.g. for edge-to-edge media).
|
|
23
23
|
* @cssproperty [--show-duration=200ms] - Open transition duration.
|
|
24
24
|
* @cssproperty [--hide-duration=200ms] - Close transition duration.
|
|
25
|
+
* @cssproperty [--easing=cubic-bezier(0.32, 0.72, 0, 1)] - Timing function of the open and close transitions, backdrop included.
|
|
25
26
|
* @cssproperty --backdrop - Backdrop color.
|
|
26
27
|
* @cssproperty [--backdrop-blur=0] - Backdrop blur amount (any CSS length). `0` means no blur; set e.g. `4px` for a subtle frost.
|
|
27
28
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/html/elements/dialog/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkC7D
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/html/elements/dialog/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkC7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,MAAO,SAAQ,YAAY;IACtC,MAAM,CAAC,MAAM,4BAAwB;IAErC,oFAAoF;IAEpF,KAAK,SAAM;IAEX,kCAAkC;IAElC,IAAI,UAAS;IAEb,0CAA0C;IAE1C,YAAY,UAAS;IAErB,uDAAuD;IAEvD,aAAa,UAAS;IAMtB,OAAO,CAAC,MAAM,CAAyC;IAGvD,MAAM,EAAG,iBAAiB,CAAC;IAI3B,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAAc;IAMvD,SAAS,KAAK,KAAK,IAAI,MAAM,CAE5B;IACD,SAAS,KAAK,OAAO,IAAI,MAAM,CAE9B;IAED,OAAO,CAAC,gBAAgB,CAA4B;IAEpD,OAAO,CAAC,gBAAgB,CAEtB;IAIF,iBAAiB;IAKjB,oBAAoB;IAKpB,YAAY;IASZ,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC;IAqCrC,OAAO,CAAC,UAAU;IAclB,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK;IAM5B,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,eAAe,CAAC,CAAY;IAEpC,OAAO,CAAC,aAAa;YAcP,UAAU;IAWxB,SAAS,CAAC,aAAa;IAKvB,MAAM;IAqCN,SAAS,CAAC,YAAY;CAUvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.js","names":[],"sources":["../../../src/html/elements/dialog/dialog.ts"],"sourcesContent":["import { html, nothing, type PropertyValues } from 'lit';\nimport { property, query } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { HasSlotController } from '../../shared/controllers/has-slot-controller.js';\nimport { ShowEvent, AfterShowEvent, HideEvent, AfterHideEvent } from '../../events/index.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport styles from './dialog.styles.js';\n\ninterface CommandEventLike extends Event {\n command: string;\n source: Element | null;\n}\n\nconst supportsClosedBy =\n typeof HTMLDialogElement !== 'undefined' && 'closedBy' in HTMLDialogElement.prototype;\n\n// Native <dialog> doesn't lock body scroll. Inject a global rule that uses\n// `:has()` to freeze the root scroll container whenever any modal l-dialog\n// is open. Purely declarative — no manual lock/unlock bookkeeping.\n// Symbol guard makes the injection idempotent across HMR reloads.\n//\n// `scrollbar-gutter: stable` only applies to centered modals — it prevents\n// the page behind from shifting horizontally when the scrollbar disappears.\n// Edge-attached modals (drawers) opt out via `data-modal=\"edge\"`: a reserved\n// gutter would push the drawer off the actual viewport edge.\nconst SCROLL_LOCK_SHEET = Symbol.for('luxen-dialog-scroll-lock');\nif (typeof document !== 'undefined' && !(SCROLL_LOCK_SHEET in document)) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(`\n html:has([data-modal]) { overflow: hidden; }\n html:has([data-modal=\"centered\"]) { scrollbar-gutter: stable; }\n `);\n document.adoptedStyleSheets.push(sheet);\n Object.defineProperty(document, SCROLL_LOCK_SHEET, { value: sheet });\n}\n\n/**\n * A modal dialog rendered in the top layer via the native `<dialog>` element.\n *\n * Open and close by toggling the `open` property (or the `--show` / `--hide`\n * Invoker commands). There are no public `show()` / `close()` methods.\n *\n * @slot - Body content.\n * @slot title - Custom heading element. Overrides the default `<h2>` rendered from the `title` property. Also provides the dialog's accessible name.\n * @slot close - Close button (typically `<button class=\"l-close\">`).\n * @slot footer - Footer actions.\n *\n * @csspart dialog - The native `<dialog>` element.\n * @csspart header - The header wrapper containing the title and close slot.\n * @csspart title - The dialog title heading.\n * @csspart body - The body wrapper around the default slot.\n * @csspart footer - The footer wrapper around the footer slot.\n *\n * @cssproperty [--width=31rem] - Dialog width.\n * @cssproperty [--border-radius=6px] - Dialog border radius.\n * @cssproperty [--padding=1.5rem] - Padding applied to the header, footer, and inline-padding of the body. Set to `0` to remove all internal spacing (e.g. for edge-to-edge media).\n * @cssproperty [--show-duration=200ms] - Open transition duration.\n * @cssproperty [--hide-duration=200ms] - Close transition duration.\n * @cssproperty --backdrop - Backdrop color.\n * @cssproperty [--backdrop-blur=0] - Backdrop blur amount (any CSS length). `0` means no blur; set e.g. `4px` for a subtle frost.\n *\n * @event show - Fired when the dialog is about to open. Cancelable — call `event.preventDefault()` to keep it closed.\n * @event after-show - Fired after the open animation completes. Not cancelable.\n * @event hide - Fired when the dialog is about to close. Cancelable — call `event.preventDefault()` to keep it open.\n * @event after-hide - Fired after the close animation completes. Not cancelable.\n *\n * @command --show - Sets `open = true`.\n * @command --hide - Sets `open = false`.\n *\n * @customElement l-dialog\n */\nexport class Dialog extends LuxenElement {\n static styles = [hostStyles, styles];\n\n /** Dialog title rendered in the header and used as the dialog's accessible name. */\n @property()\n title = '';\n\n /** Whether the dialog is open. */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /** Close when the backdrop is clicked. */\n @property({ type: Boolean, reflect: true, attribute: 'light-dismiss' })\n lightDismiss = false;\n\n /** Hide the header entirely (title and close slot). */\n @property({ type: Boolean, reflect: true, attribute: 'without-header' })\n withoutHeader = false;\n\n // Tracks whether the footer slot has content, so the footer row can collapse\n // when empty (toggles `data-empty` below). A controller drives this because\n // `:host(:has(> [slot='footer']))` is invalid — `:has()` can't be nested in\n // `:host()`, so browsers drop the whole rule.\n private _slots = new HasSlotController(this, 'footer');\n\n @query('dialog')\n dialog!: HTMLDialogElement;\n\n // Drives the scroll-lock stylesheet: `centered` reserves the scrollbar\n // gutter (no page shift); `edge` skips it (drawers sit flush to the edge).\n protected _modalKind: 'centered' | 'edge' = 'centered';\n\n // Subclass seams (defaults keep `l-dialog` unchanged). `alert-dialog`\n // overrides these to expose `role=\"alertdialog\"` and wire `aria-describedby`\n // to the body. `_bodyId` drives both the body's `id` and `aria-describedby`,\n // so the association can't drift; an empty string emits neither.\n protected get _role(): string {\n return '';\n }\n protected get _bodyId(): string {\n return '';\n }\n\n private _mouseDownTarget: EventTarget | null = null;\n\n private _commandListener: EventListenerObject = {\n handleEvent: (e: Event) => this._onCommand(e as CommandEventLike),\n };\n\n // --- Lifecycle ---\n\n connectedCallback() {\n super.connectedCallback();\n this.addEventListener('command', this._commandListener);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener('command', this._commandListener);\n }\n\n firstUpdated() {\n this.dialog.addEventListener('cancel', (e) => this._onCancel(e));\n this.dialog.addEventListener('close', () => this._onNativeClose());\n this.dialog.addEventListener('mousedown', (e) => {\n this._mouseDownTarget = e.target;\n });\n this.dialog.addEventListener('click', (e) => this._onDialogClick(e));\n }\n\n updated(changed: PropertyValues<this>) {\n if (!changed.has('open')) return;\n\n if (this.open && !this.dialog.open) {\n // Opening — cancelable. Revert the property if consumer prevents.\n if (!this.dispatchEvent(new ShowEvent())) {\n // Defer the revert so it lands outside the current update cycle and\n // doesn't schedule a new update from inside updated().\n queueMicrotask(() => {\n this.open = false;\n });\n return;\n }\n this.setAttribute('data-modal', this._modalKind);\n this.dialog.showModal();\n this._focusInitial();\n void this._emitAfter('after-show');\n } else if (!this.open && this.dialog.open) {\n // Closing — cancelable. Revert the property if consumer prevents.\n if (!this.dispatchEvent(new HideEvent())) {\n // Defer the revert so it lands outside the current update cycle and\n // doesn't schedule a new update from inside updated().\n queueMicrotask(() => {\n this.open = true;\n });\n return;\n }\n this.dialog.close();\n // `after-hide` is emitted from `_onNativeClose` (runs for every close path).\n }\n }\n\n // --- Event handlers ---\n\n // Custom commands on a custom element must start with `--`.\n // Built-in commands like \"close\" are reserved for native elements\n // and won't fire here.\n private _onCommand(e: CommandEventLike) {\n switch (e.command) {\n case '--hide':\n this.open = false;\n break;\n case '--show':\n this.open = true;\n break;\n }\n }\n\n // Fires on Escape and on `closedby=\"any\"` close requests.\n // Does NOT fire when script calls `.close()`, so `updated()`'s cancelable\n // `hide` emit doesn't collide with this one.\n protected _onCancel(e: Event) {\n if (!this.dispatchEvent(new HideEvent())) {\n e.preventDefault();\n }\n }\n\n private _onNativeClose() {\n this.open = false;\n this.removeAttribute('data-modal');\n void this._emitAfter('after-hide');\n }\n\n private _onDialogClick(e: MouseEvent) {\n // With `dialog { padding: 0 }`, `e.target === this.dialog` only fires\n // for backdrop clicks. The mousedown guard prevents drag-out dismissal.\n const clickedBackdrop = e.target === this.dialog && this._mouseDownTarget === this.dialog;\n this._mouseDownTarget = null;\n if (!clickedBackdrop) return;\n\n if (this.lightDismiss) {\n // When `supportsClosedBy`, the native `closedby=\"any\"` already closed.\n if (!supportsClosedBy) this.open = false;\n return;\n }\n this._nudgeDismiss();\n }\n\n private _nudgeAnimation?: Animation;\n\n private _nudgeDismiss() {\n if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n this._nudgeAnimation?.cancel();\n this._nudgeAnimation = this.dialog.animate(\n [{ transform: 'scale(1)' }, { transform: 'scale(1.02)' }, { transform: 'scale(1)' }],\n { duration: 250, easing: 'ease-in-out' },\n );\n }\n\n // Awaits every active animation on the dialog (transitions + @keyframes)\n // and then emits. Resolves immediately when no animations are running,\n // which covers `prefers-reduced-motion` and consumers that zero the\n // duration custom properties — cases where `transitionend` never fires.\n // Waits one frame first so @starting-style transitions have registered.\n private async _emitAfter(name: 'after-show' | 'after-hide') {\n await new Promise((r) => requestAnimationFrame(() => r(null)));\n const anims = this.dialog.getAnimations({ subtree: false });\n await Promise.all(anims.map((a) => a.finished.catch(() => {})));\n if ((name === 'after-show') !== this.open) return;\n this.dispatchEvent(name === 'after-show' ? new AfterShowEvent() : new AfterHideEvent());\n }\n\n // Firefox/Safari don't reliably resolve `[autofocus]` when `<dialog>`\n // is in shadow DOM and the target is in light DOM. Resolve it manually.\n // Subclasses (alert-dialog) override to fall back to a shadow-DOM target.\n protected _focusInitial() {\n const target = this.querySelector<HTMLElement>('[autofocus]');\n target?.focus({ preventScroll: true });\n }\n\n render() {\n const closedby = this.lightDismiss && supportsClosedBy ? 'any' : nothing;\n return html`\n <dialog\n part=\"dialog\"\n role=${this._role || nothing}\n closedby=${closedby}\n aria-labelledby=${this.withoutHeader ? nothing : 'title-area'}\n aria-label=${this.title || nothing}\n aria-describedby=${this._bodyId || nothing}\n >\n ${this.withoutHeader\n ? nothing\n : html`\n <header part=\"header\">\n <slot\n name=\"title\"\n id=\"title-area\"\n >\n ${this.title ? html`<h2 part=\"title\">${this.title}</h2>` : nothing}\n </slot>\n <slot name=\"close\"></slot>\n </header>\n `}\n <div\n part=\"body\"\n id=${this._bodyId || nothing}\n >\n <slot></slot>\n </div>\n ${this.renderFooter()}\n </dialog>\n `;\n }\n\n // Footer row. Overridden by subclasses (alert-dialog) to render their own\n // actions in place of the default `footer` slot.\n protected renderFooter() {\n return html`\n <footer\n part=\"footer\"\n ?data-empty=${!this._slots.test('footer')}\n >\n <slot name=\"footer\"></slot>\n </footer>\n `;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dialog.js","names":[],"sources":["../../../src/html/elements/dialog/dialog.ts"],"sourcesContent":["import { html, nothing, type PropertyValues } from 'lit';\nimport { property, query } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { HasSlotController } from '../../shared/controllers/has-slot-controller.js';\nimport { ShowEvent, AfterShowEvent, HideEvent, AfterHideEvent } from '../../events/index.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport styles from './dialog.styles.js';\n\ninterface CommandEventLike extends Event {\n command: string;\n source: Element | null;\n}\n\nconst supportsClosedBy =\n typeof HTMLDialogElement !== 'undefined' && 'closedBy' in HTMLDialogElement.prototype;\n\n// Native <dialog> doesn't lock body scroll. Inject a global rule that uses\n// `:has()` to freeze the root scroll container whenever any modal l-dialog\n// is open. Purely declarative — no manual lock/unlock bookkeeping.\n// Symbol guard makes the injection idempotent across HMR reloads.\n//\n// `scrollbar-gutter: stable` only applies to centered modals — it prevents\n// the page behind from shifting horizontally when the scrollbar disappears.\n// Edge-attached modals (drawers) opt out via `data-modal=\"edge\"`: a reserved\n// gutter would push the drawer off the actual viewport edge.\nconst SCROLL_LOCK_SHEET = Symbol.for('luxen-dialog-scroll-lock');\nif (typeof document !== 'undefined' && !(SCROLL_LOCK_SHEET in document)) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(`\n html:has([data-modal]) { overflow: hidden; }\n html:has([data-modal=\"centered\"]) { scrollbar-gutter: stable; }\n `);\n document.adoptedStyleSheets.push(sheet);\n Object.defineProperty(document, SCROLL_LOCK_SHEET, { value: sheet });\n}\n\n/**\n * A modal dialog rendered in the top layer via the native `<dialog>` element.\n *\n * Open and close by toggling the `open` property (or the `--show` / `--hide`\n * Invoker commands). There are no public `show()` / `close()` methods.\n *\n * @slot - Body content.\n * @slot title - Custom heading element. Overrides the default `<h2>` rendered from the `title` property. Also provides the dialog's accessible name.\n * @slot close - Close button (typically `<button class=\"l-close\">`).\n * @slot footer - Footer actions.\n *\n * @csspart dialog - The native `<dialog>` element.\n * @csspart header - The header wrapper containing the title and close slot.\n * @csspart title - The dialog title heading.\n * @csspart body - The body wrapper around the default slot.\n * @csspart footer - The footer wrapper around the footer slot.\n *\n * @cssproperty [--width=31rem] - Dialog width.\n * @cssproperty [--border-radius=6px] - Dialog border radius.\n * @cssproperty [--padding=1.5rem] - Padding applied to the header, footer, and inline-padding of the body. Set to `0` to remove all internal spacing (e.g. for edge-to-edge media).\n * @cssproperty [--show-duration=200ms] - Open transition duration.\n * @cssproperty [--hide-duration=200ms] - Close transition duration.\n * @cssproperty [--easing=cubic-bezier(0.32, 0.72, 0, 1)] - Timing function of the open and close transitions, backdrop included.\n * @cssproperty --backdrop - Backdrop color.\n * @cssproperty [--backdrop-blur=0] - Backdrop blur amount (any CSS length). `0` means no blur; set e.g. `4px` for a subtle frost.\n *\n * @event show - Fired when the dialog is about to open. Cancelable — call `event.preventDefault()` to keep it closed.\n * @event after-show - Fired after the open animation completes. Not cancelable.\n * @event hide - Fired when the dialog is about to close. Cancelable — call `event.preventDefault()` to keep it open.\n * @event after-hide - Fired after the close animation completes. Not cancelable.\n *\n * @command --show - Sets `open = true`.\n * @command --hide - Sets `open = false`.\n *\n * @customElement l-dialog\n */\nexport class Dialog extends LuxenElement {\n static styles = [hostStyles, styles];\n\n /** Dialog title rendered in the header and used as the dialog's accessible name. */\n @property()\n title = '';\n\n /** Whether the dialog is open. */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /** Close when the backdrop is clicked. */\n @property({ type: Boolean, reflect: true, attribute: 'light-dismiss' })\n lightDismiss = false;\n\n /** Hide the header entirely (title and close slot). */\n @property({ type: Boolean, reflect: true, attribute: 'without-header' })\n withoutHeader = false;\n\n // Tracks whether the footer slot has content, so the footer row can collapse\n // when empty (toggles `data-empty` below). A controller drives this because\n // `:host(:has(> [slot='footer']))` is invalid — `:has()` can't be nested in\n // `:host()`, so browsers drop the whole rule.\n private _slots = new HasSlotController(this, 'footer');\n\n @query('dialog')\n dialog!: HTMLDialogElement;\n\n // Drives the scroll-lock stylesheet: `centered` reserves the scrollbar\n // gutter (no page shift); `edge` skips it (drawers sit flush to the edge).\n protected _modalKind: 'centered' | 'edge' = 'centered';\n\n // Subclass seams (defaults keep `l-dialog` unchanged). `alert-dialog`\n // overrides these to expose `role=\"alertdialog\"` and wire `aria-describedby`\n // to the body. `_bodyId` drives both the body's `id` and `aria-describedby`,\n // so the association can't drift; an empty string emits neither.\n protected get _role(): string {\n return '';\n }\n protected get _bodyId(): string {\n return '';\n }\n\n private _mouseDownTarget: EventTarget | null = null;\n\n private _commandListener: EventListenerObject = {\n handleEvent: (e: Event) => this._onCommand(e as CommandEventLike),\n };\n\n // --- Lifecycle ---\n\n connectedCallback() {\n super.connectedCallback();\n this.addEventListener('command', this._commandListener);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener('command', this._commandListener);\n }\n\n firstUpdated() {\n this.dialog.addEventListener('cancel', (e) => this._onCancel(e));\n this.dialog.addEventListener('close', () => this._onNativeClose());\n this.dialog.addEventListener('mousedown', (e) => {\n this._mouseDownTarget = e.target;\n });\n this.dialog.addEventListener('click', (e) => this._onDialogClick(e));\n }\n\n updated(changed: PropertyValues<this>) {\n if (!changed.has('open')) return;\n\n if (this.open && !this.dialog.open) {\n // Opening — cancelable. Revert the property if consumer prevents.\n if (!this.dispatchEvent(new ShowEvent())) {\n // Defer the revert so it lands outside the current update cycle and\n // doesn't schedule a new update from inside updated().\n queueMicrotask(() => {\n this.open = false;\n });\n return;\n }\n this.setAttribute('data-modal', this._modalKind);\n this.dialog.showModal();\n this._focusInitial();\n void this._emitAfter('after-show');\n } else if (!this.open && this.dialog.open) {\n // Closing — cancelable. Revert the property if consumer prevents.\n if (!this.dispatchEvent(new HideEvent())) {\n // Defer the revert so it lands outside the current update cycle and\n // doesn't schedule a new update from inside updated().\n queueMicrotask(() => {\n this.open = true;\n });\n return;\n }\n this.dialog.close();\n // `after-hide` is emitted from `_onNativeClose` (runs for every close path).\n }\n }\n\n // --- Event handlers ---\n\n // Custom commands on a custom element must start with `--`.\n // Built-in commands like \"close\" are reserved for native elements\n // and won't fire here.\n private _onCommand(e: CommandEventLike) {\n switch (e.command) {\n case '--hide':\n this.open = false;\n break;\n case '--show':\n this.open = true;\n break;\n }\n }\n\n // Fires on Escape and on `closedby=\"any\"` close requests.\n // Does NOT fire when script calls `.close()`, so `updated()`'s cancelable\n // `hide` emit doesn't collide with this one.\n protected _onCancel(e: Event) {\n if (!this.dispatchEvent(new HideEvent())) {\n e.preventDefault();\n }\n }\n\n private _onNativeClose() {\n this.open = false;\n this.removeAttribute('data-modal');\n void this._emitAfter('after-hide');\n }\n\n private _onDialogClick(e: MouseEvent) {\n // With `dialog { padding: 0 }`, `e.target === this.dialog` only fires\n // for backdrop clicks. The mousedown guard prevents drag-out dismissal.\n const clickedBackdrop = e.target === this.dialog && this._mouseDownTarget === this.dialog;\n this._mouseDownTarget = null;\n if (!clickedBackdrop) return;\n\n if (this.lightDismiss) {\n // When `supportsClosedBy`, the native `closedby=\"any\"` already closed.\n if (!supportsClosedBy) this.open = false;\n return;\n }\n this._nudgeDismiss();\n }\n\n private _nudgeAnimation?: Animation;\n\n private _nudgeDismiss() {\n if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n this._nudgeAnimation?.cancel();\n this._nudgeAnimation = this.dialog.animate(\n [{ transform: 'scale(1)' }, { transform: 'scale(1.02)' }, { transform: 'scale(1)' }],\n { duration: 250, easing: 'ease-in-out' },\n );\n }\n\n // Awaits every active animation on the dialog (transitions + @keyframes)\n // and then emits. Resolves immediately when no animations are running,\n // which covers `prefers-reduced-motion` and consumers that zero the\n // duration custom properties — cases where `transitionend` never fires.\n // Waits one frame first so @starting-style transitions have registered.\n private async _emitAfter(name: 'after-show' | 'after-hide') {\n await new Promise((r) => requestAnimationFrame(() => r(null)));\n const anims = this.dialog.getAnimations({ subtree: false });\n await Promise.all(anims.map((a) => a.finished.catch(() => {})));\n if ((name === 'after-show') !== this.open) return;\n this.dispatchEvent(name === 'after-show' ? new AfterShowEvent() : new AfterHideEvent());\n }\n\n // Firefox/Safari don't reliably resolve `[autofocus]` when `<dialog>`\n // is in shadow DOM and the target is in light DOM. Resolve it manually.\n // Subclasses (alert-dialog) override to fall back to a shadow-DOM target.\n protected _focusInitial() {\n const target = this.querySelector<HTMLElement>('[autofocus]');\n target?.focus({ preventScroll: true });\n }\n\n render() {\n const closedby = this.lightDismiss && supportsClosedBy ? 'any' : nothing;\n return html`\n <dialog\n part=\"dialog\"\n role=${this._role || nothing}\n closedby=${closedby}\n aria-labelledby=${this.withoutHeader ? nothing : 'title-area'}\n aria-label=${this.title || nothing}\n aria-describedby=${this._bodyId || nothing}\n >\n ${this.withoutHeader\n ? nothing\n : html`\n <header part=\"header\">\n <slot\n name=\"title\"\n id=\"title-area\"\n >\n ${this.title ? html`<h2 part=\"title\">${this.title}</h2>` : nothing}\n </slot>\n <slot name=\"close\"></slot>\n </header>\n `}\n <div\n part=\"body\"\n id=${this._bodyId || nothing}\n >\n <slot></slot>\n </div>\n ${this.renderFooter()}\n </dialog>\n `;\n }\n\n // Footer row. Overridden by subclasses (alert-dialog) to render their own\n // actions in place of the default `footer` slot.\n protected renderFooter() {\n return html`\n <footer\n part=\"footer\"\n ?data-empty=${!this._slots.test('footer')}\n >\n <slot name=\"footer\"></slot>\n </footer>\n `;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{i as e}from"../../chunks/lit.js";var t=e(`:host{--width:31rem;--border-radius:6px;--padding:1.5rem;--header-padding:var(--padding);--footer-padding:var(--padding);--show-duration:.2s;--hide-duration:.2s;--backdrop:var(--l-backdrop);--backdrop-blur:0;display:contents}dialog{box-sizing:border-box;width:var(--width);max-inline-size:min(90vw, var(--width));border-radius:var(--border-radius);background-color:var(--l-color-surface-overlay);max-block-size:min(80dvb,100%);color:var(--l-color-text-primary);opacity:0;transition-property:opacity,display,overlay;transition-duration:var(--hide-duration);transition-behavior:allow-discrete;border:0;margin:auto;padding:0;position:fixed;inset:0}dialog::backdrop{background:var(--backdrop);-webkit-backdrop-filter:blur(var(--backdrop-blur));backdrop-filter:blur(var(--backdrop-blur))}dialog[open]{opacity:1;transition-duration:var(--show-duration);grid-template-rows:auto minmax(0,1fr) auto;display:grid}@starting-style{dialog[open]{opacity:0}}[part=header]{padding:var(--header-padding);justify-content:space-between;align-items:center;gap:1rem;display:flex}[part=title]{font-size:1.125rem;font-weight:var(--l-font-weight-semibold);margin:0;line-height:1.4}[part=body]{padding-inline:var(--padding);grid-row:2;overflow-y:auto}[part=footer]{padding:var(--footer-padding);grid-row:3;place-content:end;gap:.5rem;display:flex}[part=footer][data-empty]{display:none}[part=body]:has(~[part=footer][data-empty]){padding-block-end:var(--padding)}:host([without-header]) [part=body]{padding-block-start:var(--padding)}::slotted(menu[slot=footer]){display:contents}@media (prefers-reduced-motion:reduce){:host{--show-duration:0s;--hide-duration:0s}}`);export{t as default};
|
|
1
|
+
import{i as e}from"../../chunks/lit.js";var t=e(`:host{--width:31rem;--border-radius:6px;--padding:1.5rem;--header-padding:var(--padding);--footer-padding:var(--padding);--show-duration:.2s;--hide-duration:.2s;--easing:cubic-bezier(.32, .72, 0, 1);--backdrop:var(--l-backdrop);--backdrop-blur:0;display:contents}dialog{box-sizing:border-box;width:var(--width);max-inline-size:min(90vw, var(--width));border-radius:var(--border-radius);background-color:var(--l-color-surface-overlay);max-block-size:min(80dvb,100%);color:var(--l-color-text-primary);opacity:0;transition-property:opacity,display,overlay;transition-duration:var(--hide-duration);transition-timing-function:var(--easing);transition-behavior:allow-discrete;border:0;margin:auto;padding:0;position:fixed;inset:0}dialog::backdrop{background:var(--backdrop);-webkit-backdrop-filter:blur(var(--backdrop-blur));backdrop-filter:blur(var(--backdrop-blur));opacity:0;transition-property:opacity,display,overlay;transition-duration:var(--hide-duration);transition-timing-function:var(--easing);transition-behavior:allow-discrete}dialog[open]{opacity:1;transition-duration:var(--show-duration);grid-template-rows:auto minmax(0,1fr) auto;display:grid}dialog[open]::backdrop{opacity:1;transition-duration:var(--show-duration)}@starting-style{dialog[open],dialog[open]::backdrop{opacity:0}}[part=header]{padding:var(--header-padding);justify-content:space-between;align-items:center;gap:1rem;display:flex}[part=title]{font-size:1.125rem;font-weight:var(--l-font-weight-semibold);margin:0;line-height:1.4}[part=body]{padding-inline:var(--padding);grid-row:2;overflow-y:auto}[part=footer]{padding:var(--footer-padding);grid-row:3;place-content:end;gap:.5rem;display:flex}[part=footer][data-empty]{display:none}[part=body]:has(~[part=footer][data-empty]){padding-block-end:var(--padding)}:host([without-header]) [part=body]{padding-block-start:var(--padding)}::slotted(menu[slot=footer]){display:contents}@media (prefers-reduced-motion:reduce){:host{--show-duration:0s;--hide-duration:0s}}`);export{t as default};
|
|
2
2
|
//# sourceMappingURL=dialog.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.styles.js","names":[],"sources":["../../../src/html/elements/dialog/dialog.css?inline","../../../src/html/elements/dialog/dialog.styles.ts"],"sourcesContent":[":host {\n --width: 31rem;\n --border-radius: 6px;\n --padding: 1.5rem;\n --header-padding: var(--padding);\n --footer-padding: var(--padding);\n --show-duration: 200ms;\n --hide-duration: 200ms;\n --backdrop: var(--l-backdrop);\n --backdrop-blur: 0;\n\n display: contents;\n}\n\ndialog {\n position: fixed;\n inset: 0;\n box-sizing: border-box;\n width: var(--width);\n max-inline-size: min(90vw, var(--width));\n max-block-size: min(80dvb, 100%);\n margin: auto;\n padding: 0;\n border: 0;\n border-radius: var(--border-radius);\n background-color: var(--l-color-surface-overlay);\n color: var(--l-color-text-primary);\n\n /* EXIT STATE */\n opacity: 0;\n\n transition-property: opacity, display, overlay;\n transition-duration: var(--hide-duration);\n transition-behavior: allow-discrete;\n\n &::backdrop {\n background: var(--backdrop);\n backdrop-filter: blur(var(--backdrop-blur));\n }\n\n /* OPEN STATE */\n /* grid layout pins header/footer; the middle row (body) scrolls via\n overflow on [part='body'] and minmax(0, 1fr) allowing it to shrink. */\n &[open] {\n display: grid;\n grid-template-rows: auto minmax(0, 1fr) auto;\n opacity: 1;\n transition-duration: var(--show-duration);\n }\n\n /* BEFORE-OPEN STATE */\n @starting-style {\n &[open] {\n opacity: 0;\n }\n }\n}\n\n[part='header'] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n padding: var(--header-padding);\n}\n\n[part='title'] {\n margin: 0;\n font-size: 1.125rem;\n font-weight: var(--l-font-weight-semibold);\n line-height: 1.4;\n}\n\n/* Pin body and footer so the layout stays correct when [without-header]\n removes the header and only two children auto-place into the grid. */\n[part='body'] {\n grid-row: 2;\n padding-inline: var(--padding);\n overflow-y: auto;\n}\n\n[part='footer'] {\n grid-row: 3;\n display: flex;\n place-content: end;\n gap: 0.5rem;\n padding: var(--footer-padding);\n}\n\n/* Collapse the footer row when nothing is slotted into it, so an empty\n dialog/drawer reserves no space at the bottom. `data-empty` is toggled by the\n HasSlotController in dialog.ts: `:host(:has(...))` can't be used because\n `:has()` is invalid inside `:host()` and the whole rule is dropped by the\n browser. */\n[part='footer'][data-empty] {\n display: none;\n}\n\n/* With the footer collapsed, the body has to provide its own block-end padding\n (normally inherited visually from the footer padding below it). */\n[part='body']:has(~ [part='footer'][data-empty]) {\n padding-block-end: var(--padding);\n}\n\n/* Without a header, the body has to provide its own block-start padding\n (normally inherited visually from the header padding above it). */\n:host([without-header]) [part='body'] {\n padding-block-start: var(--padding);\n}\n\n::slotted(menu[slot='footer']) {\n display: contents;\n}\n\n@media (prefers-reduced-motion: reduce) {\n :host {\n --show-duration: 0ms;\n --hide-duration: 0ms;\n }\n}\n","import { unsafeCSS } from 'lit';\nimport raw from './dialog.css?inline';\n\n/**\n * Wrapper module: imported by both `dialog.ts` and `drawer.ts`.\n * `unsafeCSS()` is called once here so both importers share the same\n * `CSSResult` instance (one constructed `CSSStyleSheet`, not two).\n */\nexport default unsafeCSS(raw);\n"],"mappings":"wCCQA,IAAA,EAAe,EAAU,
|
|
1
|
+
{"version":3,"file":"dialog.styles.js","names":[],"sources":["../../../src/html/elements/dialog/dialog.css?inline","../../../src/html/elements/dialog/dialog.styles.ts"],"sourcesContent":[":host {\n --width: 31rem;\n --border-radius: 6px;\n --padding: 1.5rem;\n --header-padding: var(--padding);\n --footer-padding: var(--padding);\n --show-duration: 200ms;\n --hide-duration: 200ms;\n /* Fast start, soft landing: the surface is nearly in place early, the\n tail only settles it. */\n --easing: cubic-bezier(0.32, 0.72, 0, 1);\n --backdrop: var(--l-backdrop);\n --backdrop-blur: 0;\n\n display: contents;\n}\n\ndialog {\n position: fixed;\n inset: 0;\n box-sizing: border-box;\n width: var(--width);\n max-inline-size: min(90vw, var(--width));\n max-block-size: min(80dvb, 100%);\n margin: auto;\n padding: 0;\n border: 0;\n border-radius: var(--border-radius);\n background-color: var(--l-color-surface-overlay);\n color: var(--l-color-text-primary);\n\n /* EXIT STATE */\n opacity: 0;\n\n transition-property: opacity, display, overlay;\n transition-duration: var(--hide-duration);\n transition-timing-function: var(--easing);\n transition-behavior: allow-discrete;\n\n /* The backdrop does not inherit the dialog's opacity: without its own\n transition it pops in and out at full strength. */\n &::backdrop {\n background: var(--backdrop);\n backdrop-filter: blur(var(--backdrop-blur));\n opacity: 0;\n transition-property: opacity, display, overlay;\n transition-duration: var(--hide-duration);\n transition-timing-function: var(--easing);\n transition-behavior: allow-discrete;\n }\n\n /* OPEN STATE */\n /* grid layout pins header/footer; the middle row (body) scrolls via\n overflow on [part='body'] and minmax(0, 1fr) allowing it to shrink. */\n &[open] {\n display: grid;\n grid-template-rows: auto minmax(0, 1fr) auto;\n opacity: 1;\n transition-duration: var(--show-duration);\n }\n\n &[open]::backdrop {\n opacity: 1;\n transition-duration: var(--show-duration);\n }\n\n /* BEFORE-OPEN STATE */\n @starting-style {\n &[open],\n &[open]::backdrop {\n opacity: 0;\n }\n }\n}\n\n[part='header'] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n padding: var(--header-padding);\n}\n\n[part='title'] {\n margin: 0;\n font-size: 1.125rem;\n font-weight: var(--l-font-weight-semibold);\n line-height: 1.4;\n}\n\n/* Pin body and footer so the layout stays correct when [without-header]\n removes the header and only two children auto-place into the grid. */\n[part='body'] {\n grid-row: 2;\n padding-inline: var(--padding);\n overflow-y: auto;\n}\n\n[part='footer'] {\n grid-row: 3;\n display: flex;\n place-content: end;\n gap: 0.5rem;\n padding: var(--footer-padding);\n}\n\n/* Collapse the footer row when nothing is slotted into it, so an empty\n dialog/drawer reserves no space at the bottom. `data-empty` is toggled by the\n HasSlotController in dialog.ts: `:host(:has(...))` can't be used because\n `:has()` is invalid inside `:host()` and the whole rule is dropped by the\n browser. */\n[part='footer'][data-empty] {\n display: none;\n}\n\n/* With the footer collapsed, the body has to provide its own block-end padding\n (normally inherited visually from the footer padding below it). */\n[part='body']:has(~ [part='footer'][data-empty]) {\n padding-block-end: var(--padding);\n}\n\n/* Without a header, the body has to provide its own block-start padding\n (normally inherited visually from the header padding above it). */\n:host([without-header]) [part='body'] {\n padding-block-start: var(--padding);\n}\n\n::slotted(menu[slot='footer']) {\n display: contents;\n}\n\n@media (prefers-reduced-motion: reduce) {\n :host {\n --show-duration: 0ms;\n --hide-duration: 0ms;\n }\n}\n","import { unsafeCSS } from 'lit';\nimport raw from './dialog.css?inline';\n\n/**\n * Wrapper module: imported by both `dialog.ts` and `drawer.ts`.\n * `unsafeCSS()` is called once here so both importers share the same\n * `CSSResult` instance (one constructed `CSSStyleSheet`, not two).\n */\nexport default unsafeCSS(raw);\n"],"mappings":"wCCQA,IAAA,EAAe,EAAU,o8DAAG"}
|
|
@@ -20,8 +20,9 @@ import { Dialog } from '../dialog/dialog.js';
|
|
|
20
20
|
* @cssproperty --border-radius - Drawer border radius on the inner edges (all corners when `inset`). Default `0.375rem`.
|
|
21
21
|
* @cssproperty --inset-gap - Gap between the drawer and the viewport edges when `inset` is set. Default `1rem`.
|
|
22
22
|
* @cssproperty --shadow - Drop shadow applied to the floating panel when `inset` is set. Set to `none` to remove it.
|
|
23
|
-
* @cssproperty --show-duration - Open transition duration. Default `
|
|
23
|
+
* @cssproperty --show-duration - Open transition duration. Default `300ms`.
|
|
24
24
|
* @cssproperty --hide-duration - Close transition duration. Default `200ms`.
|
|
25
|
+
* @cssproperty --easing - Timing function of the open and close transitions, backdrop included. Default `cubic-bezier(0.32, 0.72, 0, 1)`.
|
|
25
26
|
* @cssproperty --backdrop - Backdrop color.
|
|
26
27
|
*
|
|
27
28
|
* @event show - Fired when the drawer is about to open. Cancelable — call `event.preventDefault()` to keep it closed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../../src/html/elements/drawer/drawer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAM7C
|
|
1
|
+
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../../src/html/elements/drawer/drawer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAM7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,MAAO,SAAQ,MAAM;IAChC,OAAgB,MAAM,4BAA4C;IAIlE,UAAmB,UAAU,EAAG,MAAM,CAAU;IAEhD,iFAAiF;IAEjF,SAAS,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;IAE/C,qGAAqG;IAErG,KAAK,UAAS;CACf"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{i as e}from"../../chunks/lit.js";import{i as t,t as n}from"../../chunks/decorate.js";import r from"../../shared/styles/host.styles.js";import i from"../dialog/dialog.styles.js";import{Dialog as a}from"../dialog/dialog.js";var o=e(`:host{--size:320px;--border-radius:.375rem;--inset-gap:1rem;--shadow:var(--l-shadow-lg)}dialog{width:min(var(--size), 100dvw);max-inline-size:100dvw;height:100dvh;border-radius:0 var(--border-radius) var(--border-radius) 0;opacity:1;max-block-size:100dvh;margin:0;transition-property:translate,display,overlay;inset:0;translate:-100%}dialog[open]{translate:0}@starting-style{dialog[open]{translate:-100%}}:host([placement=end]) dialog{border-radius:var(--border-radius) 0 0 var(--border-radius);margin-inline-start:auto;translate:100%}:host([placement=end]) dialog[open]{translate:0}@starting-style{:host([placement=end]) dialog[open]{translate:100%}}:host([placement=bottom]) dialog{width:100dvw;max-inline-size:100dvw;height:min(var(--size), 100dvh);border-radius:var(--border-radius) var(--border-radius) 0 0;max-block-size:100dvh;margin-block-start:auto;translate:0 100%}:host([placement=bottom]) dialog[open]{translate:0}@starting-style{:host([placement=bottom]) dialog[open]{translate:0 100%}}:host([placement=top]) dialog{width:100dvw;max-inline-size:100dvw;height:min(var(--size), 100dvh);border-radius:0 0 var(--border-radius) var(--border-radius);max-block-size:100dvh;translate:0 -100%}:host([placement=top]) dialog[open]{translate:0}@starting-style{:host([placement=top]) dialog[open]{translate:0 -100%}}:host([inset]) dialog{border-radius:var(--border-radius);box-shadow:var(--shadow)}:host([inset]:not([placement])) dialog,:host([inset][placement=start]) dialog,:host([inset][placement=end]) dialog{height:calc(100dvh - 2 * var(--inset-gap));inset-block:var(--inset-gap)}:host([inset][placement=top]) dialog,:host([inset][placement=bottom]) dialog{width:calc(100dvw - 2 * var(--inset-gap));inset-inline:var(--inset-gap)}:host([inset]:not([placement])) dialog,:host([inset][placement=start]) dialog{inset-inline-start:var(--inset-gap)}:host([inset]:not([placement])) dialog:not([open]),:host([inset][placement=start]) dialog:not([open]){translate:calc(-100% - var(--inset-gap)) 0}@starting-style{:host([inset]:not([placement])) dialog[open],:host([inset][placement=start]) dialog[open]{translate:calc(-100% - var(--inset-gap)) 0}}:host([inset][placement=end]) dialog{margin-inline-start:0;inset-inline-start:auto;inset-inline-end:var(--inset-gap)}:host([inset][placement=end]) dialog:not([open]){translate:calc(100% + var(--inset-gap)) 0}@starting-style{:host([inset][placement=end]) dialog[open]{translate:calc(100% + var(--inset-gap)) 0}}:host([inset][placement=top]) dialog{inset-block-start:var(--inset-gap)}:host([inset][placement=top]) dialog:not([open]){translate:0 calc(-100% - var(--inset-gap))}@starting-style{:host([inset][placement=top]) dialog[open]{translate:0 calc(-100% - var(--inset-gap))}}:host([inset][placement=bottom]) dialog{margin-block-start:0;inset-block-start:auto;inset-block-end:var(--inset-gap)}:host([inset][placement=bottom]) dialog:not([open]){translate:0 calc(100% + var(--inset-gap))}@starting-style{:host([inset][placement=bottom]) dialog[open]{translate:0 calc(100% + var(--inset-gap))}}`),s=class extends a{constructor(...e){super(...e),this._modalKind=`edge`,this.inset=!1}static{this.styles=[r,i,o]}};n([t({reflect:!0})],s.prototype,`placement`,void 0),n([t({type:Boolean,reflect:!0})],s.prototype,`inset`,void 0);export{s as Drawer};
|
|
1
|
+
import{i as e}from"../../chunks/lit.js";import{i as t,t as n}from"../../chunks/decorate.js";import r from"../../shared/styles/host.styles.js";import i from"../dialog/dialog.styles.js";import{Dialog as a}from"../dialog/dialog.js";var o=e(`:host{--size:320px;--border-radius:.375rem;--inset-gap:1rem;--shadow:var(--l-shadow-lg);--show-duration:.3s}@media (prefers-reduced-motion:reduce){:host{--show-duration:0s;--hide-duration:0s}}dialog{width:min(var(--size), 100dvw);max-inline-size:100dvw;height:100dvh;border-radius:0 var(--border-radius) var(--border-radius) 0;opacity:1;max-block-size:100dvh;margin:0;transition-property:translate,display,overlay;inset:0;translate:-100%}dialog[open]{translate:0}@starting-style{dialog[open]{translate:-100%}}:host([placement=end]) dialog{border-radius:var(--border-radius) 0 0 var(--border-radius);margin-inline-start:auto;translate:100%}:host([placement=end]) dialog[open]{translate:0}@starting-style{:host([placement=end]) dialog[open]{translate:100%}}:host([placement=bottom]) dialog{width:100dvw;max-inline-size:100dvw;height:min(var(--size), 100dvh);border-radius:var(--border-radius) var(--border-radius) 0 0;max-block-size:100dvh;margin-block-start:auto;translate:0 100%}:host([placement=bottom]) dialog[open]{translate:0}@starting-style{:host([placement=bottom]) dialog[open]{translate:0 100%}}:host([placement=top]) dialog{width:100dvw;max-inline-size:100dvw;height:min(var(--size), 100dvh);border-radius:0 0 var(--border-radius) var(--border-radius);max-block-size:100dvh;translate:0 -100%}:host([placement=top]) dialog[open]{translate:0}@starting-style{:host([placement=top]) dialog[open]{translate:0 -100%}}:host([inset]) dialog{border-radius:var(--border-radius);box-shadow:var(--shadow)}:host([inset]:not([placement])) dialog,:host([inset][placement=start]) dialog,:host([inset][placement=end]) dialog{height:calc(100dvh - 2 * var(--inset-gap));inset-block:var(--inset-gap)}:host([inset][placement=top]) dialog,:host([inset][placement=bottom]) dialog{width:calc(100dvw - 2 * var(--inset-gap));inset-inline:var(--inset-gap)}:host([inset]:not([placement])) dialog,:host([inset][placement=start]) dialog{inset-inline-start:var(--inset-gap)}:host([inset]:not([placement])) dialog:not([open]),:host([inset][placement=start]) dialog:not([open]){translate:calc(-100% - var(--inset-gap)) 0}@starting-style{:host([inset]:not([placement])) dialog[open],:host([inset][placement=start]) dialog[open]{translate:calc(-100% - var(--inset-gap)) 0}}:host([inset][placement=end]) dialog{margin-inline-start:0;inset-inline-start:auto;inset-inline-end:var(--inset-gap)}:host([inset][placement=end]) dialog:not([open]){translate:calc(100% + var(--inset-gap)) 0}@starting-style{:host([inset][placement=end]) dialog[open]{translate:calc(100% + var(--inset-gap)) 0}}:host([inset][placement=top]) dialog{inset-block-start:var(--inset-gap)}:host([inset][placement=top]) dialog:not([open]){translate:0 calc(-100% - var(--inset-gap))}@starting-style{:host([inset][placement=top]) dialog[open]{translate:0 calc(-100% - var(--inset-gap))}}:host([inset][placement=bottom]) dialog{margin-block-start:0;inset-block-start:auto;inset-block-end:var(--inset-gap)}:host([inset][placement=bottom]) dialog:not([open]){translate:0 calc(100% + var(--inset-gap))}@starting-style{:host([inset][placement=bottom]) dialog[open]{translate:0 calc(100% + var(--inset-gap))}}`),s=class extends a{constructor(...e){super(...e),this._modalKind=`edge`,this.inset=!1}static{this.styles=[r,i,o]}};n([t({reflect:!0})],s.prototype,`placement`,void 0),n([t({type:Boolean,reflect:!0})],s.prototype,`inset`,void 0);export{s as Drawer};
|
|
2
2
|
//# sourceMappingURL=drawer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.js","names":[],"sources":["../../../src/html/elements/drawer/drawer.css?inline","../../../src/html/elements/drawer/drawer.ts"],"sourcesContent":[":host {\n --size: 320px;\n --border-radius: 0.375rem;\n --inset-gap: 1rem;\n --shadow: var(--l-shadow-lg);\n}\n\n/* Override dialog's opacity fade with a slide from the inline-start edge. */\ndialog {\n inset: 0;\n margin: 0;\n width: min(var(--size), 100dvw);\n max-inline-size: 100dvw;\n height: 100dvh;\n max-block-size: 100dvh;\n border-radius: 0 var(--border-radius) var(--border-radius) 0;\n opacity: 1;\n translate: -100% 0;\n transition-property: translate, display, overlay;\n}\n\ndialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n dialog[open] {\n translate: -100% 0;\n }\n}\n\n/* Inline-end edge */\n:host([placement='end']) dialog {\n border-radius: var(--border-radius) 0 0 var(--border-radius);\n margin-inline-start: auto;\n translate: 100% 0;\n}\n\n:host([placement='end']) dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n :host([placement='end']) dialog[open] {\n translate: 100% 0;\n }\n}\n\n/* Block-end (bottom) edge */\n:host([placement='bottom']) dialog {\n width: 100dvw;\n max-inline-size: 100dvw;\n height: min(var(--size), 100dvh);\n max-block-size: 100dvh;\n margin-block-start: auto;\n border-radius: var(--border-radius) var(--border-radius) 0 0;\n translate: 0 100%;\n}\n\n:host([placement='bottom']) dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n :host([placement='bottom']) dialog[open] {\n translate: 0 100%;\n }\n}\n\n/* Block-start (top) edge */\n:host([placement='top']) dialog {\n width: 100dvw;\n max-inline-size: 100dvw;\n height: min(var(--size), 100dvh);\n max-block-size: 100dvh;\n border-radius: 0 0 var(--border-radius) var(--border-radius);\n translate: 0 -100%;\n}\n\n:host([placement='top']) dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n :host([placement='top']) dialog[open] {\n translate: 0 -100%;\n }\n}\n\n/* Inset: float the drawer away from the viewport edges with a uniform gap and\n round every corner. The off-screen translate grows by the gap so the panel\n still clears the viewport edge during the slide (it no longer sits flush). */\n:host([inset]) dialog {\n border-radius: var(--border-radius);\n box-shadow: var(--shadow);\n}\n\n/* Inline-edge drawers (start/end): inset the block edges, shrink height to fit. */\n:host([inset]:not([placement])) dialog,\n:host([inset][placement='start']) dialog,\n:host([inset][placement='end']) dialog {\n height: calc(100dvh - 2 * var(--inset-gap));\n inset-block: var(--inset-gap);\n}\n\n/* Block-edge drawers (top/bottom): inset the inline edges, shrink width to fit. */\n:host([inset][placement='top']) dialog,\n:host([inset][placement='bottom']) dialog {\n width: calc(100dvw - 2 * var(--inset-gap));\n inset-inline: var(--inset-gap);\n}\n\n/* Inline-start edge: gap on the start side. */\n:host([inset]:not([placement])) dialog,\n:host([inset][placement='start']) dialog {\n inset-inline-start: var(--inset-gap);\n}\n\n:host([inset]:not([placement])) dialog:not([open]),\n:host([inset][placement='start']) dialog:not([open]) {\n translate: calc(-100% - var(--inset-gap)) 0;\n}\n\n@starting-style {\n :host([inset]:not([placement])) dialog[open],\n :host([inset][placement='start']) dialog[open] {\n translate: calc(-100% - var(--inset-gap)) 0;\n }\n}\n\n/* Inline-end edge: gap on the end side (override the base auto margin). */\n:host([inset][placement='end']) dialog {\n inset-inline-start: auto;\n inset-inline-end: var(--inset-gap);\n margin-inline-start: 0;\n}\n\n:host([inset][placement='end']) dialog:not([open]) {\n translate: calc(100% + var(--inset-gap)) 0;\n}\n\n@starting-style {\n :host([inset][placement='end']) dialog[open] {\n translate: calc(100% + var(--inset-gap)) 0;\n }\n}\n\n/* Block-start (top) edge: gap on the top side. */\n:host([inset][placement='top']) dialog {\n inset-block-start: var(--inset-gap);\n}\n\n:host([inset][placement='top']) dialog:not([open]) {\n translate: 0 calc(-100% - var(--inset-gap));\n}\n\n@starting-style {\n :host([inset][placement='top']) dialog[open] {\n translate: 0 calc(-100% - var(--inset-gap));\n }\n}\n\n/* Block-end (bottom) edge: gap on the bottom side (override the base auto margin). */\n:host([inset][placement='bottom']) dialog {\n inset-block-start: auto;\n inset-block-end: var(--inset-gap);\n margin-block-start: 0;\n}\n\n:host([inset][placement='bottom']) dialog:not([open]) {\n translate: 0 calc(100% + var(--inset-gap));\n}\n\n@starting-style {\n :host([inset][placement='bottom']) dialog[open] {\n translate: 0 calc(100% + var(--inset-gap));\n }\n}\n","import { unsafeCSS } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport { Dialog } from '../dialog/dialog.js';\nimport dialogStyles from '../dialog/dialog.styles.js';\nimport rawDrawerStyles from './drawer.css?inline';\n\nconst drawerStyles = unsafeCSS(rawDrawerStyles);\n\n/**\n * A drawer that slides in from a screen edge. Extends `<l-dialog>`.\n *\n * Open and close by toggling the `open` property (or the `--show` / `--hide`\n * Invoker commands). Always opens as modal.\n *\n * @slot - Body content.\n * @slot title - Custom heading element. Overrides the default `<h2>` rendered from the `title` property. Also provides the dialog's accessible name.\n * @slot close - Close button (typically `<button class=\"l-close\">`).\n * @slot footer - Footer actions.\n *\n * @csspart dialog - The native `<dialog>` element.\n * @csspart header - The header wrapper containing the title and close slot.\n * @csspart title - The drawer title heading.\n * @csspart body - The body wrapper around the default slot.\n * @csspart footer - The footer wrapper around the footer slot.\n *\n * @cssproperty --size - Drawer size on the axis perpendicular to its edge (width for `start`/`end`, height for `top`/`bottom`). Default `320px`.\n * @cssproperty --border-radius - Drawer border radius on the inner edges (all corners when `inset`). Default `0.375rem`.\n * @cssproperty --inset-gap - Gap between the drawer and the viewport edges when `inset` is set. Default `1rem`.\n * @cssproperty --shadow - Drop shadow applied to the floating panel when `inset` is set. Set to `none` to remove it.\n * @cssproperty --show-duration - Open transition duration. Default `
|
|
1
|
+
{"version":3,"file":"drawer.js","names":[],"sources":["../../../src/html/elements/drawer/drawer.css?inline","../../../src/html/elements/drawer/drawer.ts"],"sourcesContent":[":host {\n --size: 320px;\n --border-radius: 0.375rem;\n --inset-gap: 1rem;\n --shadow: var(--l-shadow-lg);\n /* A slide travels much further than the dialog's fade. */\n --show-duration: 300ms;\n}\n\n/* Restated: this sheet comes after dialog.css, so the default above would\n otherwise win over its reduced-motion override. */\n@media (prefers-reduced-motion: reduce) {\n :host {\n --show-duration: 0ms;\n --hide-duration: 0ms;\n }\n}\n\n/* Override dialog's opacity fade with a slide from the inline-start edge. */\ndialog {\n inset: 0;\n margin: 0;\n width: min(var(--size), 100dvw);\n max-inline-size: 100dvw;\n height: 100dvh;\n max-block-size: 100dvh;\n border-radius: 0 var(--border-radius) var(--border-radius) 0;\n opacity: 1;\n translate: -100% 0;\n transition-property: translate, display, overlay;\n}\n\ndialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n dialog[open] {\n translate: -100% 0;\n }\n}\n\n/* Inline-end edge */\n:host([placement='end']) dialog {\n border-radius: var(--border-radius) 0 0 var(--border-radius);\n margin-inline-start: auto;\n translate: 100% 0;\n}\n\n:host([placement='end']) dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n :host([placement='end']) dialog[open] {\n translate: 100% 0;\n }\n}\n\n/* Block-end (bottom) edge */\n:host([placement='bottom']) dialog {\n width: 100dvw;\n max-inline-size: 100dvw;\n height: min(var(--size), 100dvh);\n max-block-size: 100dvh;\n margin-block-start: auto;\n border-radius: var(--border-radius) var(--border-radius) 0 0;\n translate: 0 100%;\n}\n\n:host([placement='bottom']) dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n :host([placement='bottom']) dialog[open] {\n translate: 0 100%;\n }\n}\n\n/* Block-start (top) edge */\n:host([placement='top']) dialog {\n width: 100dvw;\n max-inline-size: 100dvw;\n height: min(var(--size), 100dvh);\n max-block-size: 100dvh;\n border-radius: 0 0 var(--border-radius) var(--border-radius);\n translate: 0 -100%;\n}\n\n:host([placement='top']) dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n :host([placement='top']) dialog[open] {\n translate: 0 -100%;\n }\n}\n\n/* Inset: float the drawer away from the viewport edges with a uniform gap and\n round every corner. The off-screen translate grows by the gap so the panel\n still clears the viewport edge during the slide (it no longer sits flush). */\n:host([inset]) dialog {\n border-radius: var(--border-radius);\n box-shadow: var(--shadow);\n}\n\n/* Inline-edge drawers (start/end): inset the block edges, shrink height to fit. */\n:host([inset]:not([placement])) dialog,\n:host([inset][placement='start']) dialog,\n:host([inset][placement='end']) dialog {\n height: calc(100dvh - 2 * var(--inset-gap));\n inset-block: var(--inset-gap);\n}\n\n/* Block-edge drawers (top/bottom): inset the inline edges, shrink width to fit. */\n:host([inset][placement='top']) dialog,\n:host([inset][placement='bottom']) dialog {\n width: calc(100dvw - 2 * var(--inset-gap));\n inset-inline: var(--inset-gap);\n}\n\n/* Inline-start edge: gap on the start side. */\n:host([inset]:not([placement])) dialog,\n:host([inset][placement='start']) dialog {\n inset-inline-start: var(--inset-gap);\n}\n\n:host([inset]:not([placement])) dialog:not([open]),\n:host([inset][placement='start']) dialog:not([open]) {\n translate: calc(-100% - var(--inset-gap)) 0;\n}\n\n@starting-style {\n :host([inset]:not([placement])) dialog[open],\n :host([inset][placement='start']) dialog[open] {\n translate: calc(-100% - var(--inset-gap)) 0;\n }\n}\n\n/* Inline-end edge: gap on the end side (override the base auto margin). */\n:host([inset][placement='end']) dialog {\n inset-inline-start: auto;\n inset-inline-end: var(--inset-gap);\n margin-inline-start: 0;\n}\n\n:host([inset][placement='end']) dialog:not([open]) {\n translate: calc(100% + var(--inset-gap)) 0;\n}\n\n@starting-style {\n :host([inset][placement='end']) dialog[open] {\n translate: calc(100% + var(--inset-gap)) 0;\n }\n}\n\n/* Block-start (top) edge: gap on the top side. */\n:host([inset][placement='top']) dialog {\n inset-block-start: var(--inset-gap);\n}\n\n:host([inset][placement='top']) dialog:not([open]) {\n translate: 0 calc(-100% - var(--inset-gap));\n}\n\n@starting-style {\n :host([inset][placement='top']) dialog[open] {\n translate: 0 calc(-100% - var(--inset-gap));\n }\n}\n\n/* Block-end (bottom) edge: gap on the bottom side (override the base auto margin). */\n:host([inset][placement='bottom']) dialog {\n inset-block-start: auto;\n inset-block-end: var(--inset-gap);\n margin-block-start: 0;\n}\n\n:host([inset][placement='bottom']) dialog:not([open]) {\n translate: 0 calc(100% + var(--inset-gap));\n}\n\n@starting-style {\n :host([inset][placement='bottom']) dialog[open] {\n translate: 0 calc(100% + var(--inset-gap));\n }\n}\n","import { unsafeCSS } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport { Dialog } from '../dialog/dialog.js';\nimport dialogStyles from '../dialog/dialog.styles.js';\nimport rawDrawerStyles from './drawer.css?inline';\n\nconst drawerStyles = unsafeCSS(rawDrawerStyles);\n\n/**\n * A drawer that slides in from a screen edge. Extends `<l-dialog>`.\n *\n * Open and close by toggling the `open` property (or the `--show` / `--hide`\n * Invoker commands). Always opens as modal.\n *\n * @slot - Body content.\n * @slot title - Custom heading element. Overrides the default `<h2>` rendered from the `title` property. Also provides the dialog's accessible name.\n * @slot close - Close button (typically `<button class=\"l-close\">`).\n * @slot footer - Footer actions.\n *\n * @csspart dialog - The native `<dialog>` element.\n * @csspart header - The header wrapper containing the title and close slot.\n * @csspart title - The drawer title heading.\n * @csspart body - The body wrapper around the default slot.\n * @csspart footer - The footer wrapper around the footer slot.\n *\n * @cssproperty --size - Drawer size on the axis perpendicular to its edge (width for `start`/`end`, height for `top`/`bottom`). Default `320px`.\n * @cssproperty --border-radius - Drawer border radius on the inner edges (all corners when `inset`). Default `0.375rem`.\n * @cssproperty --inset-gap - Gap between the drawer and the viewport edges when `inset` is set. Default `1rem`.\n * @cssproperty --shadow - Drop shadow applied to the floating panel when `inset` is set. Set to `none` to remove it.\n * @cssproperty --show-duration - Open transition duration. Default `300ms`.\n * @cssproperty --hide-duration - Close transition duration. Default `200ms`.\n * @cssproperty --easing - Timing function of the open and close transitions, backdrop included. Default `cubic-bezier(0.32, 0.72, 0, 1)`.\n * @cssproperty --backdrop - Backdrop color.\n *\n * @event show - Fired when the drawer is about to open. Cancelable — call `event.preventDefault()` to keep it closed.\n * @event after-show - Fired after the open animation completes. Not cancelable.\n * @event hide - Fired when the drawer is about to close. Cancelable — call `event.preventDefault()` to keep it open.\n * @event after-hide - Fired after the close animation completes. Not cancelable.\n *\n * @command --show - Sets `open = true`.\n * @command --hide - Sets `open = false`.\n *\n * @customElement l-drawer\n */\nexport class Drawer extends Dialog {\n static override styles = [hostStyles, dialogStyles, drawerStyles];\n\n // Edge-attached: opt out of the centered modal's stable scrollbar gutter,\n // which would otherwise push the drawer off the actual viewport edge.\n protected override _modalKind = 'edge' as const;\n\n /** Edge the drawer slides in from. Defaults to the start (inline-start) edge. */\n @property({ reflect: true })\n placement?: 'start' | 'end' | 'top' | 'bottom';\n\n /** Detach the drawer from the viewport edges, floating it with a uniform gap and rounded corners. */\n @property({ type: Boolean, reflect: true })\n inset = false;\n}\n"],"mappings":"qOCOA,IAAM,EAAe,EAAU,skGAAe,EAsCjC,EAAb,cAA4B,CAAO,+CAKD,kBAQxB,sBAZiB,CAAC,EAAY,EAAc,CAAY,EAalE,KANG,EAAS,CAAE,QAAS,EAAK,CAAC,CAAA,EAAA,EAAA,UAAA,YAAA,IAAA,EAAA,KAI1B,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,CAAA,EAAA,EAAA,UAAA,QAAA,IAAA,EAAA"}
|
|
@@ -419,6 +419,15 @@
|
|
|
419
419
|
"module": "src/html/elements/dialog/dialog.ts"
|
|
420
420
|
}
|
|
421
421
|
},
|
|
422
|
+
{
|
|
423
|
+
"description": "Timing function of the open and close transitions, backdrop included.",
|
|
424
|
+
"name": "--easing",
|
|
425
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)",
|
|
426
|
+
"inheritedFrom": {
|
|
427
|
+
"name": "Dialog",
|
|
428
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
429
|
+
}
|
|
430
|
+
},
|
|
422
431
|
{
|
|
423
432
|
"description": "Backdrop color.",
|
|
424
433
|
"name": "--backdrop",
|
|
@@ -2743,6 +2752,11 @@
|
|
|
2743
2752
|
"name": "--hide-duration",
|
|
2744
2753
|
"default": "200ms"
|
|
2745
2754
|
},
|
|
2755
|
+
{
|
|
2756
|
+
"description": "Timing function of the open and close transitions, backdrop included.",
|
|
2757
|
+
"name": "--easing",
|
|
2758
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)"
|
|
2759
|
+
},
|
|
2746
2760
|
{
|
|
2747
2761
|
"description": "Backdrop color.",
|
|
2748
2762
|
"name": "--backdrop"
|
|
@@ -3202,7 +3216,7 @@
|
|
|
3202
3216
|
"name": "--shadow"
|
|
3203
3217
|
},
|
|
3204
3218
|
{
|
|
3205
|
-
"description": "Open transition duration. Default `
|
|
3219
|
+
"description": "Open transition duration. Default `300ms`.",
|
|
3206
3220
|
"name": "--show-duration",
|
|
3207
3221
|
"default": "200ms",
|
|
3208
3222
|
"inheritedFrom": {
|
|
@@ -3219,6 +3233,15 @@
|
|
|
3219
3233
|
"module": "src/html/elements/dialog/dialog.ts"
|
|
3220
3234
|
}
|
|
3221
3235
|
},
|
|
3236
|
+
{
|
|
3237
|
+
"description": "Timing function of the open and close transitions, backdrop included. Default `cubic-bezier(0.32, 0.72, 0, 1)`.",
|
|
3238
|
+
"name": "--easing",
|
|
3239
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)",
|
|
3240
|
+
"inheritedFrom": {
|
|
3241
|
+
"name": "Dialog",
|
|
3242
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
3243
|
+
}
|
|
3244
|
+
},
|
|
3222
3245
|
{
|
|
3223
3246
|
"description": "Backdrop color.",
|
|
3224
3247
|
"name": "--backdrop",
|
|
@@ -48,6 +48,7 @@ export declare class CancelEvent extends Event {
|
|
|
48
48
|
* @cssproperty [--padding=1.5rem] - Padding applied to the header, footer, and inline-padding of the body.
|
|
49
49
|
* @cssproperty [--show-duration=200ms] - Open transition duration.
|
|
50
50
|
* @cssproperty [--hide-duration=200ms] - Close transition duration.
|
|
51
|
+
* @cssproperty [--easing=cubic-bezier(0.32, 0.72, 0, 1)] - Timing function of the open and close transitions, backdrop included.
|
|
51
52
|
* @cssproperty --backdrop - Backdrop color.
|
|
52
53
|
* @cssproperty [--backdrop-blur=0] - Backdrop blur amount (any CSS length).
|
|
53
54
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert-dialog.d.ts","sourceRoot":"","sources":["../../../src/html/elements/alert-dialog/alert-dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAUpE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAI7C,OAAO,qBAAqB,CAAC;AAU7B;;;;;;GAMG;AACH,qBAAa,YAAa,SAAQ,KAAK;;CAItC;AAED;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,KAAK;;CAIrC;AAED
|
|
1
|
+
{"version":3,"file":"alert-dialog.d.ts","sourceRoot":"","sources":["../../../src/html/elements/alert-dialog/alert-dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAUpE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAI7C,OAAO,qBAAqB,CAAC;AAU7B;;;;;;GAMG;AACH,qBAAa,YAAa,SAAQ,KAAK;;CAItC;AAED;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,KAAK;;CAIrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,qBAAa,WAAY,SAAQ,MAAM;IACrC,OAAgB,MAAM,4BAAyD;IAE/E,oCAAoC;IAEpC,WAAW,SAAa;IAExB,mCAAmC;IAEnC,UAAU,SAAY;IAEtB,uEAAuE;IAEvE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAEhB;2DACuD;IAEvD,OAAO,UAAS;IAEhB,cAAuB,KAAK,WAE3B;IAID,OAAO,CAAC,YAAY,CAA4C;IAChE,cAAuB,OAAO,uBAE7B;cAKkB,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC;cAOxC,SAAS,CAAC,CAAC,EAAE,KAAK;cAUlB,aAAa;IAehC,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,cAAc,CASpB;cAEiB,YAAY;CAqChC;AAMD,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CACd,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,KAAK,IAAI,EACvD,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,gBAAgB,CACd,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,KAAK,IAAI,EACtD,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,KAAK,IAAI,EACvD,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,KAAK,IAAI,EACtD,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;CACT"}
|
|
@@ -77,6 +77,7 @@ export class CancelEvent extends Event {
|
|
|
77
77
|
* @cssproperty [--padding=1.5rem] - Padding applied to the header, footer, and inline-padding of the body.
|
|
78
78
|
* @cssproperty [--show-duration=200ms] - Open transition duration.
|
|
79
79
|
* @cssproperty [--hide-duration=200ms] - Close transition duration.
|
|
80
|
+
* @cssproperty [--easing=cubic-bezier(0.32, 0.72, 0, 1)] - Timing function of the open and close transitions, backdrop included.
|
|
80
81
|
* @cssproperty --backdrop - Backdrop color.
|
|
81
82
|
* @cssproperty [--backdrop-blur=0] - Backdrop blur amount (any CSS length).
|
|
82
83
|
*
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
--footer-padding: var(--padding);
|
|
7
7
|
--show-duration: 200ms;
|
|
8
8
|
--hide-duration: 200ms;
|
|
9
|
+
/* Fast start, soft landing: the surface is nearly in place early, the
|
|
10
|
+
tail only settles it. */
|
|
11
|
+
--easing: cubic-bezier(0.32, 0.72, 0, 1);
|
|
9
12
|
--backdrop: var(--l-backdrop);
|
|
10
13
|
--backdrop-blur: 0;
|
|
11
14
|
|
|
@@ -31,11 +34,19 @@ dialog {
|
|
|
31
34
|
|
|
32
35
|
transition-property: opacity, display, overlay;
|
|
33
36
|
transition-duration: var(--hide-duration);
|
|
37
|
+
transition-timing-function: var(--easing);
|
|
34
38
|
transition-behavior: allow-discrete;
|
|
35
39
|
|
|
40
|
+
/* The backdrop does not inherit the dialog's opacity: without its own
|
|
41
|
+
transition it pops in and out at full strength. */
|
|
36
42
|
&::backdrop {
|
|
37
43
|
background: var(--backdrop);
|
|
38
44
|
backdrop-filter: blur(var(--backdrop-blur));
|
|
45
|
+
opacity: 0;
|
|
46
|
+
transition-property: opacity, display, overlay;
|
|
47
|
+
transition-duration: var(--hide-duration);
|
|
48
|
+
transition-timing-function: var(--easing);
|
|
49
|
+
transition-behavior: allow-discrete;
|
|
39
50
|
}
|
|
40
51
|
|
|
41
52
|
/* OPEN STATE */
|
|
@@ -48,9 +59,15 @@ dialog {
|
|
|
48
59
|
transition-duration: var(--show-duration);
|
|
49
60
|
}
|
|
50
61
|
|
|
62
|
+
&[open]::backdrop {
|
|
63
|
+
opacity: 1;
|
|
64
|
+
transition-duration: var(--show-duration);
|
|
65
|
+
}
|
|
66
|
+
|
|
51
67
|
/* BEFORE-OPEN STATE */
|
|
52
68
|
@starting-style {
|
|
53
|
-
&[open]
|
|
69
|
+
&[open],
|
|
70
|
+
&[open]::backdrop {
|
|
54
71
|
opacity: 0;
|
|
55
72
|
}
|
|
56
73
|
}
|
|
@@ -22,6 +22,7 @@ import { LuxenElement } from '../../shared/luxen-element.js';
|
|
|
22
22
|
* @cssproperty [--padding=1.5rem] - Padding applied to the header, footer, and inline-padding of the body. Set to `0` to remove all internal spacing (e.g. for edge-to-edge media).
|
|
23
23
|
* @cssproperty [--show-duration=200ms] - Open transition duration.
|
|
24
24
|
* @cssproperty [--hide-duration=200ms] - Close transition duration.
|
|
25
|
+
* @cssproperty [--easing=cubic-bezier(0.32, 0.72, 0, 1)] - Timing function of the open and close transitions, backdrop included.
|
|
25
26
|
* @cssproperty --backdrop - Backdrop color.
|
|
26
27
|
* @cssproperty [--backdrop-blur=0] - Backdrop blur amount (any CSS length). `0` means no blur; set e.g. `4px` for a subtle frost.
|
|
27
28
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/html/elements/dialog/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkC7D
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/html/elements/dialog/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkC7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,MAAO,SAAQ,YAAY;IACtC,MAAM,CAAC,MAAM,4BAAwB;IAErC,oFAAoF;IAEpF,KAAK,SAAM;IAEX,kCAAkC;IAElC,IAAI,UAAS;IAEb,0CAA0C;IAE1C,YAAY,UAAS;IAErB,uDAAuD;IAEvD,aAAa,UAAS;IAMtB,OAAO,CAAC,MAAM,CAAyC;IAGvD,MAAM,EAAG,iBAAiB,CAAC;IAI3B,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAAc;IAMvD,SAAS,KAAK,KAAK,IAAI,MAAM,CAE5B;IACD,SAAS,KAAK,OAAO,IAAI,MAAM,CAE9B;IAED,OAAO,CAAC,gBAAgB,CAA4B;IAEpD,OAAO,CAAC,gBAAgB,CAEtB;IAIF,iBAAiB;IAKjB,oBAAoB;IAKpB,YAAY;IASZ,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC;IAqCrC,OAAO,CAAC,UAAU;IAclB,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK;IAM5B,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,eAAe,CAAC,CAAY;IAEpC,OAAO,CAAC,aAAa;YAcP,UAAU;IAWxB,SAAS,CAAC,aAAa;IAKvB,MAAM;IAqCN,SAAS,CAAC,YAAY;CAUvB"}
|
|
@@ -53,6 +53,7 @@ if (typeof document !== 'undefined' && !(SCROLL_LOCK_SHEET in document)) {
|
|
|
53
53
|
* @cssproperty [--padding=1.5rem] - Padding applied to the header, footer, and inline-padding of the body. Set to `0` to remove all internal spacing (e.g. for edge-to-edge media).
|
|
54
54
|
* @cssproperty [--show-duration=200ms] - Open transition duration.
|
|
55
55
|
* @cssproperty [--hide-duration=200ms] - Close transition duration.
|
|
56
|
+
* @cssproperty [--easing=cubic-bezier(0.32, 0.72, 0, 1)] - Timing function of the open and close transitions, backdrop included.
|
|
56
57
|
* @cssproperty --backdrop - Backdrop color.
|
|
57
58
|
* @cssproperty [--backdrop-blur=0] - Backdrop blur amount (any CSS length). `0` means no blur; set e.g. `4px` for a subtle frost.
|
|
58
59
|
*
|
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
--border-radius: 0.375rem;
|
|
4
4
|
--inset-gap: 1rem;
|
|
5
5
|
--shadow: var(--l-shadow-lg);
|
|
6
|
+
/* A slide travels much further than the dialog's fade. */
|
|
7
|
+
--show-duration: 300ms;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* Restated: this sheet comes after dialog.css, so the default above would
|
|
11
|
+
otherwise win over its reduced-motion override. */
|
|
12
|
+
@media (prefers-reduced-motion: reduce) {
|
|
13
|
+
:host {
|
|
14
|
+
--show-duration: 0ms;
|
|
15
|
+
--hide-duration: 0ms;
|
|
16
|
+
}
|
|
6
17
|
}
|
|
7
18
|
|
|
8
19
|
/* Override dialog's opacity fade with a slide from the inline-start edge. */
|
|
@@ -20,8 +20,9 @@ import { Dialog } from '../dialog/dialog.js';
|
|
|
20
20
|
* @cssproperty --border-radius - Drawer border radius on the inner edges (all corners when `inset`). Default `0.375rem`.
|
|
21
21
|
* @cssproperty --inset-gap - Gap between the drawer and the viewport edges when `inset` is set. Default `1rem`.
|
|
22
22
|
* @cssproperty --shadow - Drop shadow applied to the floating panel when `inset` is set. Set to `none` to remove it.
|
|
23
|
-
* @cssproperty --show-duration - Open transition duration. Default `
|
|
23
|
+
* @cssproperty --show-duration - Open transition duration. Default `300ms`.
|
|
24
24
|
* @cssproperty --hide-duration - Close transition duration. Default `200ms`.
|
|
25
|
+
* @cssproperty --easing - Timing function of the open and close transitions, backdrop included. Default `cubic-bezier(0.32, 0.72, 0, 1)`.
|
|
25
26
|
* @cssproperty --backdrop - Backdrop color.
|
|
26
27
|
*
|
|
27
28
|
* @event show - Fired when the drawer is about to open. Cancelable — call `event.preventDefault()` to keep it closed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../../src/html/elements/drawer/drawer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAM7C
|
|
1
|
+
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../../src/html/elements/drawer/drawer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAM7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,MAAO,SAAQ,MAAM;IAChC,OAAgB,MAAM,4BAA4C;IAIlE,UAAmB,UAAU,EAAG,MAAM,CAAU;IAEhD,iFAAiF;IAEjF,SAAS,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;IAE/C,qGAAqG;IAErG,KAAK,UAAS;CACf"}
|
|
@@ -32,8 +32,9 @@ const drawerStyles = unsafeCSS(rawDrawerStyles);
|
|
|
32
32
|
* @cssproperty --border-radius - Drawer border radius on the inner edges (all corners when `inset`). Default `0.375rem`.
|
|
33
33
|
* @cssproperty --inset-gap - Gap between the drawer and the viewport edges when `inset` is set. Default `1rem`.
|
|
34
34
|
* @cssproperty --shadow - Drop shadow applied to the floating panel when `inset` is set. Set to `none` to remove it.
|
|
35
|
-
* @cssproperty --show-duration - Open transition duration. Default `
|
|
35
|
+
* @cssproperty --show-duration - Open transition duration. Default `300ms`.
|
|
36
36
|
* @cssproperty --hide-duration - Close transition duration. Default `200ms`.
|
|
37
|
+
* @cssproperty --easing - Timing function of the open and close transitions, backdrop included. Default `cubic-bezier(0.32, 0.72, 0, 1)`.
|
|
37
38
|
* @cssproperty --backdrop - Backdrop color.
|
|
38
39
|
*
|
|
39
40
|
* @event show - Fired when the drawer is about to open. Cancelable — call `event.preventDefault()` to keep it closed.
|
|
@@ -201,6 +201,11 @@
|
|
|
201
201
|
"default": "200ms",
|
|
202
202
|
"description": "Close transition duration."
|
|
203
203
|
},
|
|
204
|
+
{
|
|
205
|
+
"name": "--easing",
|
|
206
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)",
|
|
207
|
+
"description": "Timing function of the open and close transitions, backdrop included."
|
|
208
|
+
},
|
|
204
209
|
{
|
|
205
210
|
"name": "--backdrop",
|
|
206
211
|
"default": null,
|
|
@@ -139,6 +139,11 @@
|
|
|
139
139
|
"default": "200ms",
|
|
140
140
|
"description": "Close transition duration."
|
|
141
141
|
},
|
|
142
|
+
{
|
|
143
|
+
"name": "--easing",
|
|
144
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)",
|
|
145
|
+
"description": "Timing function of the open and close transitions, backdrop included."
|
|
146
|
+
},
|
|
142
147
|
{
|
|
143
148
|
"name": "--backdrop",
|
|
144
149
|
"default": null,
|
|
@@ -160,6 +160,11 @@
|
|
|
160
160
|
"default": "200ms",
|
|
161
161
|
"description": "Close transition duration."
|
|
162
162
|
},
|
|
163
|
+
{
|
|
164
|
+
"name": "--easing",
|
|
165
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)",
|
|
166
|
+
"description": "Timing function of the open and close transitions, backdrop included."
|
|
167
|
+
},
|
|
163
168
|
{
|
|
164
169
|
"name": "--backdrop",
|
|
165
170
|
"default": null,
|
package/dist/metadata/index.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.22.0",
|
|
3
3
|
"elements": [
|
|
4
4
|
{
|
|
5
5
|
"name": "alert",
|
|
@@ -310,6 +310,11 @@
|
|
|
310
310
|
"default": "200ms",
|
|
311
311
|
"description": "Close transition duration."
|
|
312
312
|
},
|
|
313
|
+
{
|
|
314
|
+
"name": "--easing",
|
|
315
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)",
|
|
316
|
+
"description": "Timing function of the open and close transitions, backdrop included."
|
|
317
|
+
},
|
|
313
318
|
{
|
|
314
319
|
"name": "--backdrop",
|
|
315
320
|
"default": null,
|
|
@@ -1727,6 +1732,11 @@
|
|
|
1727
1732
|
"default": "200ms",
|
|
1728
1733
|
"description": "Close transition duration."
|
|
1729
1734
|
},
|
|
1735
|
+
{
|
|
1736
|
+
"name": "--easing",
|
|
1737
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)",
|
|
1738
|
+
"description": "Timing function of the open and close transitions, backdrop included."
|
|
1739
|
+
},
|
|
1730
1740
|
{
|
|
1731
1741
|
"name": "--backdrop",
|
|
1732
1742
|
"default": null,
|
|
@@ -2076,6 +2086,11 @@
|
|
|
2076
2086
|
"default": "200ms",
|
|
2077
2087
|
"description": "Close transition duration."
|
|
2078
2088
|
},
|
|
2089
|
+
{
|
|
2090
|
+
"name": "--easing",
|
|
2091
|
+
"default": "cubic-bezier(0.32, 0.72, 0, 1)",
|
|
2092
|
+
"description": "Timing function of the open and close transitions, backdrop included."
|
|
2093
|
+
},
|
|
2079
2094
|
{
|
|
2080
2095
|
"name": "--backdrop",
|
|
2081
2096
|
"default": null,
|
|
@@ -248,5 +248,6 @@ Open and close the dialog by toggling its `open` property, or via the [Invoker C
|
|
|
248
248
|
- `--padding` (default: `1.5rem`) — Padding applied to the header, footer, and inline-padding of the body.
|
|
249
249
|
- `--show-duration` (default: `200ms`) — Open transition duration.
|
|
250
250
|
- `--hide-duration` (default: `200ms`) — Close transition duration.
|
|
251
|
+
- `--easing` (default: `cubic-bezier(0.32, 0.72, 0, 1)`) — Timing function of the open and close transitions, backdrop included.
|
|
251
252
|
- `--backdrop` — Backdrop color.
|
|
252
253
|
- `--backdrop-blur` (default: `0`) — Backdrop blur amount (any CSS length).
|
|
@@ -528,5 +528,6 @@ Open and close the dialog by toggling its `open` property, or via the [Invoker C
|
|
|
528
528
|
- `--padding` (default: `1.5rem`) — Padding applied to the header, footer, and inline-padding of the body. Set to `0` to remove all internal spacing (e.g. for edge-to-edge media).
|
|
529
529
|
- `--show-duration` (default: `200ms`) — Open transition duration.
|
|
530
530
|
- `--hide-duration` (default: `200ms`) — Close transition duration.
|
|
531
|
+
- `--easing` (default: `cubic-bezier(0.32, 0.72, 0, 1)`) — Timing function of the open and close transitions, backdrop included.
|
|
531
532
|
- `--backdrop` — Backdrop color.
|
|
532
533
|
- `--backdrop-blur` (default: `0`) — Backdrop blur amount (any CSS length). `0` means no blur; set e.g. `4px` for a subtle frost.
|
|
@@ -584,6 +584,7 @@ Open and close the drawer by toggling its `open` property, or via the [Invoker C
|
|
|
584
584
|
- `--shadow` — Drop shadow applied to the floating panel when `inset` is set. Set to `none` to remove it.
|
|
585
585
|
- `--show-duration` (default: `200ms`) — Open transition duration.
|
|
586
586
|
- `--hide-duration` (default: `200ms`) — Close transition duration.
|
|
587
|
+
- `--easing` (default: `cubic-bezier(0.32, 0.72, 0, 1)`) — Timing function of the open and close transitions, backdrop included.
|
|
587
588
|
- `--backdrop` — Backdrop color.
|
|
588
589
|
- `--width` (default: `31rem`) — Dialog width.
|
|
589
590
|
- `--padding` (default: `1.5rem`) — Padding applied to the header, footer, and inline-padding of the body. Set to `0` to remove all internal spacing (e.g. for edge-to-edge media).
|
package/package.json
CHANGED
package/templates/SKILL.md.tpl
CHANGED
|
@@ -42,6 +42,7 @@ These rules apply across all elements; element-specific detail lives in the per-
|
|
|
42
42
|
- **Variants and state use `data-*` attributes** (`data-variant`, `data-appearance`), not modifier classes.
|
|
43
43
|
- **Show/hide overlays with the invoker pattern**: `command="--show"` / `command="--hide"` + `commandfor="<id>"` for dialog and drawer.
|
|
44
44
|
- **Colors, spacing, and typography come from design tokens** — see [references/tokens.md](references/tokens.md). Use the semantic tokens and utility classes listed there rather than arbitrary values.
|
|
45
|
+
- **Customize through the documented surface** — CSS custom properties, CSS parts, events. Before overriding an element's styles through `::part()` or working around one of its behaviours (motion, event timing), check its spec: the knob usually exists. When it does not, that is a gap in {{name}} — report it upstream rather than shipping a local workaround.
|
|
45
46
|
|
|
46
47
|
## Choosing an element
|
|
47
48
|
|
|
@@ -49,7 +50,7 @@ These rules apply across all elements; element-specific detail lives in the per-
|
|
|
49
50
|
|
|
50
51
|
## Per-element specs
|
|
51
52
|
|
|
52
|
-
**ALWAYS read `references/<element>.md` before emitting that element** (e.g. `references/dialog.md`) — attribute conventions differ per element, so guessing from memory is unsafe. Each file describes attributes, slots, events, and CSS custom properties.
|
|
53
|
+
**ALWAYS read `references/<element>.md` before emitting, styling, or working around that element** (e.g. `references/dialog.md`) — attribute conventions differ per element, so guessing from memory is unsafe. Each file describes attributes, slots, events, and CSS custom properties.
|
|
53
54
|
|
|
54
55
|
## Available elements
|
|
55
56
|
|