luxen-ui 0.6.1 → 0.6.2
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 +132 -89
- 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 +4 -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/cdn/standalone.css +0 -5
- package/cdn/standalone.js +13 -5
- package/cdn/standalone.js.map +1 -1
- package/cdn/styles/elements/close-button/square.css +0 -5
- package/dist/css/elements/close-button/square.css +0 -5
- package/dist/custom-elements.json +132 -89
- package/dist/elements/dialog/dialog.css +4 -2
- 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 +13 -2
- package/dist/elements/drawer/drawer.css +1 -1
- 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 +7 -1
- package/dist/templates/elements/close-button.md +24 -3
- package/package.json +1 -1
package/cdn/custom-elements.json
CHANGED
|
@@ -2322,6 +2322,14 @@
|
|
|
2322
2322
|
"description": "Hide the header entirely (title and close slot).",
|
|
2323
2323
|
"default": "false"
|
|
2324
2324
|
},
|
|
2325
|
+
{
|
|
2326
|
+
"kind": "field",
|
|
2327
|
+
"name": "_modalKind",
|
|
2328
|
+
"type": {
|
|
2329
|
+
"text": "string"
|
|
2330
|
+
},
|
|
2331
|
+
"default": "'centered'"
|
|
2332
|
+
},
|
|
2325
2333
|
{
|
|
2326
2334
|
"kind": "field",
|
|
2327
2335
|
"name": "_mouseDownTarget",
|
|
@@ -2547,7 +2555,7 @@
|
|
|
2547
2555
|
"name": "--size"
|
|
2548
2556
|
},
|
|
2549
2557
|
{
|
|
2550
|
-
"description": "Drawer border radius on the inner edges. Default `0.
|
|
2558
|
+
"description": "Drawer border radius on the inner edges. Default `0.375rem`.",
|
|
2551
2559
|
"name": "--border-radius",
|
|
2552
2560
|
"inheritedFrom": {
|
|
2553
2561
|
"name": "Dialog",
|
|
@@ -2679,99 +2687,20 @@
|
|
|
2679
2687
|
}
|
|
2680
2688
|
}
|
|
2681
2689
|
],
|
|
2682
|
-
"
|
|
2683
|
-
{
|
|
2684
|
-
"description": "Fired when the drawer opens. Not cancelable.",
|
|
2685
|
-
"name": "show",
|
|
2686
|
-
"inheritedFrom": {
|
|
2687
|
-
"name": "Dialog",
|
|
2688
|
-
"module": "src/html/elements/dialog/dialog.ts"
|
|
2689
|
-
}
|
|
2690
|
-
},
|
|
2691
|
-
{
|
|
2692
|
-
"description": "Fired after the open animation completes.",
|
|
2693
|
-
"name": "after-show",
|
|
2694
|
-
"inheritedFrom": {
|
|
2695
|
-
"name": "Dialog",
|
|
2696
|
-
"module": "src/html/elements/dialog/dialog.ts"
|
|
2697
|
-
}
|
|
2698
|
-
},
|
|
2699
|
-
{
|
|
2700
|
-
"description": "Fired when the drawer is about to close. Cancelable — call `event.preventDefault()` to keep it open.",
|
|
2701
|
-
"name": "hide",
|
|
2702
|
-
"inheritedFrom": {
|
|
2703
|
-
"name": "Dialog",
|
|
2704
|
-
"module": "src/html/elements/dialog/dialog.ts"
|
|
2705
|
-
}
|
|
2706
|
-
},
|
|
2707
|
-
{
|
|
2708
|
-
"description": "Fired after the close animation completes.",
|
|
2709
|
-
"name": "after-hide",
|
|
2710
|
-
"inheritedFrom": {
|
|
2711
|
-
"name": "Dialog",
|
|
2712
|
-
"module": "src/html/elements/dialog/dialog.ts"
|
|
2713
|
-
}
|
|
2714
|
-
}
|
|
2715
|
-
],
|
|
2716
|
-
"superclass": {
|
|
2717
|
-
"name": "Dialog",
|
|
2718
|
-
"module": "/dist/elements/dialog/dialog.js"
|
|
2719
|
-
},
|
|
2720
|
-
"attributes": [
|
|
2721
|
-
{
|
|
2722
|
-
"name": "title",
|
|
2723
|
-
"type": {
|
|
2724
|
-
"text": "string"
|
|
2725
|
-
},
|
|
2726
|
-
"default": "''",
|
|
2727
|
-
"description": "Dialog title rendered in the header.",
|
|
2728
|
-
"fieldName": "title",
|
|
2729
|
-
"inheritedFrom": {
|
|
2730
|
-
"name": "Dialog",
|
|
2731
|
-
"module": "src/html/elements/dialog/dialog.ts"
|
|
2732
|
-
}
|
|
2733
|
-
},
|
|
2734
|
-
{
|
|
2735
|
-
"name": "open",
|
|
2736
|
-
"type": {
|
|
2737
|
-
"text": "boolean"
|
|
2738
|
-
},
|
|
2739
|
-
"default": "false",
|
|
2740
|
-
"description": "Whether the dialog is open.",
|
|
2741
|
-
"fieldName": "open",
|
|
2742
|
-
"inheritedFrom": {
|
|
2743
|
-
"name": "Dialog",
|
|
2744
|
-
"module": "src/html/elements/dialog/dialog.ts"
|
|
2745
|
-
}
|
|
2746
|
-
},
|
|
2690
|
+
"members": [
|
|
2747
2691
|
{
|
|
2748
|
-
"
|
|
2692
|
+
"kind": "field",
|
|
2693
|
+
"name": "_modalKind",
|
|
2749
2694
|
"type": {
|
|
2750
|
-
"text": "
|
|
2695
|
+
"text": "'centered' | 'edge'"
|
|
2751
2696
|
},
|
|
2752
|
-
"
|
|
2753
|
-
"
|
|
2754
|
-
"fieldName": "lightDismiss",
|
|
2697
|
+
"privacy": "protected",
|
|
2698
|
+
"default": "'edge'",
|
|
2755
2699
|
"inheritedFrom": {
|
|
2756
2700
|
"name": "Dialog",
|
|
2757
2701
|
"module": "src/html/elements/dialog/dialog.ts"
|
|
2758
2702
|
}
|
|
2759
2703
|
},
|
|
2760
|
-
{
|
|
2761
|
-
"name": "without-header",
|
|
2762
|
-
"type": {
|
|
2763
|
-
"text": "boolean"
|
|
2764
|
-
},
|
|
2765
|
-
"default": "false",
|
|
2766
|
-
"description": "Hide the header entirely (title and close slot).",
|
|
2767
|
-
"fieldName": "withoutHeader",
|
|
2768
|
-
"inheritedFrom": {
|
|
2769
|
-
"name": "Dialog",
|
|
2770
|
-
"module": "src/html/elements/dialog/dialog.ts"
|
|
2771
|
-
}
|
|
2772
|
-
}
|
|
2773
|
-
],
|
|
2774
|
-
"members": [
|
|
2775
2704
|
{
|
|
2776
2705
|
"kind": "field",
|
|
2777
2706
|
"name": "title",
|
|
@@ -3006,6 +2935,98 @@
|
|
|
3006
2935
|
"module": "src/html/shared/luxen-element.ts"
|
|
3007
2936
|
}
|
|
3008
2937
|
}
|
|
2938
|
+
],
|
|
2939
|
+
"events": [
|
|
2940
|
+
{
|
|
2941
|
+
"description": "Fired when the drawer opens. Not cancelable.",
|
|
2942
|
+
"name": "show",
|
|
2943
|
+
"inheritedFrom": {
|
|
2944
|
+
"name": "Dialog",
|
|
2945
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
2946
|
+
}
|
|
2947
|
+
},
|
|
2948
|
+
{
|
|
2949
|
+
"description": "Fired after the open animation completes.",
|
|
2950
|
+
"name": "after-show",
|
|
2951
|
+
"inheritedFrom": {
|
|
2952
|
+
"name": "Dialog",
|
|
2953
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
2954
|
+
}
|
|
2955
|
+
},
|
|
2956
|
+
{
|
|
2957
|
+
"description": "Fired when the drawer is about to close. Cancelable — call `event.preventDefault()` to keep it open.",
|
|
2958
|
+
"name": "hide",
|
|
2959
|
+
"inheritedFrom": {
|
|
2960
|
+
"name": "Dialog",
|
|
2961
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
2962
|
+
}
|
|
2963
|
+
},
|
|
2964
|
+
{
|
|
2965
|
+
"description": "Fired after the close animation completes.",
|
|
2966
|
+
"name": "after-hide",
|
|
2967
|
+
"inheritedFrom": {
|
|
2968
|
+
"name": "Dialog",
|
|
2969
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
],
|
|
2973
|
+
"superclass": {
|
|
2974
|
+
"name": "Dialog",
|
|
2975
|
+
"module": "/dist/elements/dialog/dialog.js"
|
|
2976
|
+
},
|
|
2977
|
+
"attributes": [
|
|
2978
|
+
{
|
|
2979
|
+
"name": "title",
|
|
2980
|
+
"type": {
|
|
2981
|
+
"text": "string"
|
|
2982
|
+
},
|
|
2983
|
+
"default": "''",
|
|
2984
|
+
"description": "Dialog title rendered in the header.",
|
|
2985
|
+
"fieldName": "title",
|
|
2986
|
+
"inheritedFrom": {
|
|
2987
|
+
"name": "Dialog",
|
|
2988
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
2989
|
+
}
|
|
2990
|
+
},
|
|
2991
|
+
{
|
|
2992
|
+
"name": "open",
|
|
2993
|
+
"type": {
|
|
2994
|
+
"text": "boolean"
|
|
2995
|
+
},
|
|
2996
|
+
"default": "false",
|
|
2997
|
+
"description": "Whether the dialog is open.",
|
|
2998
|
+
"fieldName": "open",
|
|
2999
|
+
"inheritedFrom": {
|
|
3000
|
+
"name": "Dialog",
|
|
3001
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
3002
|
+
}
|
|
3003
|
+
},
|
|
3004
|
+
{
|
|
3005
|
+
"name": "light-dismiss",
|
|
3006
|
+
"type": {
|
|
3007
|
+
"text": "boolean"
|
|
3008
|
+
},
|
|
3009
|
+
"default": "false",
|
|
3010
|
+
"description": "Close when the backdrop is clicked.",
|
|
3011
|
+
"fieldName": "lightDismiss",
|
|
3012
|
+
"inheritedFrom": {
|
|
3013
|
+
"name": "Dialog",
|
|
3014
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
3015
|
+
}
|
|
3016
|
+
},
|
|
3017
|
+
{
|
|
3018
|
+
"name": "without-header",
|
|
3019
|
+
"type": {
|
|
3020
|
+
"text": "boolean"
|
|
3021
|
+
},
|
|
3022
|
+
"default": "false",
|
|
3023
|
+
"description": "Hide the header entirely (title and close slot).",
|
|
3024
|
+
"fieldName": "withoutHeader",
|
|
3025
|
+
"inheritedFrom": {
|
|
3026
|
+
"name": "Dialog",
|
|
3027
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3009
3030
|
]
|
|
3010
3031
|
}
|
|
3011
3032
|
],
|
|
@@ -8049,7 +8070,7 @@
|
|
|
8049
8070
|
{
|
|
8050
8071
|
"kind": "variable",
|
|
8051
8072
|
"name": "u",
|
|
8052
|
-
"default": "class extends n{constructor(...e){super(...e),this.title=``,this.open=!1,this.lightDismiss=!1,this.withoutHeader=!1,this._mouseDownTarget=null,this._commandListener={handleEvent:e=>this._onCommand(e)}}static{this.styles=[o,s]}connectedCallback(){super.connectedCallback(),this.addEventListener(`command`,this._commandListener)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener(`command`,this._commandListener)}firstUpdated(){this.dialog.addEventListener(`cancel`,e=>this._onCancel(e)),this.dialog.addEventListener(`close`,()=>this._onNativeClose()),this.dialog.addEventListener(`mousedown`,e=>{this._mouseDownTarget=e.target}),this.dialog.addEventListener(`click`,e=>this._onDialogClick(e))}updated(e){if(e.has(`open`)){if(this.open&&!this.dialog.open)this.emit(`show`),this.
|
|
8073
|
+
"default": "class extends n{constructor(...e){super(...e),this.title=``,this.open=!1,this.lightDismiss=!1,this.withoutHeader=!1,this._modalKind=`centered`,this._mouseDownTarget=null,this._commandListener={handleEvent:e=>this._onCommand(e)}}static{this.styles=[o,s]}connectedCallback(){super.connectedCallback(),this.addEventListener(`command`,this._commandListener)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener(`command`,this._commandListener)}firstUpdated(){this.dialog.addEventListener(`cancel`,e=>this._onCancel(e)),this.dialog.addEventListener(`close`,()=>this._onNativeClose()),this.dialog.addEventListener(`mousedown`,e=>{this._mouseDownTarget=e.target}),this.dialog.addEventListener(`click`,e=>this._onDialogClick(e))}updated(e){if(e.has(`open`)){if(this.open&&!this.dialog.open)this.emit(`show`),this.setAttribute(`data-modal`,this._modalKind),this.dialog.showModal(),this._focusAutofocusTarget(),this._emitAfter(`after-show`);else if(!this.open&&this.dialog.open){if(!this.emit(`hide`,{cancelable:!0})){this.open=!0;return}this.dialog.close()}}}_onCommand(e){switch(e.command){case`--hide`:this.open=!1;break;case`--show`:this.open=!0;break}}_onCancel(e){this.emit(`hide`,{cancelable:!0})||e.preventDefault()}_onNativeClose(){this.open=!1,this.removeAttribute(`data-modal`),this._emitAfter(`after-hide`)}_onDialogClick(e){let t=e.target===this.dialog&&this._mouseDownTarget===this.dialog;if(this._mouseDownTarget=null,t){if(this.lightDismiss){c||(this.open=!1);return}this._nudgeDismiss()}}_nudgeDismiss(){matchMedia(`(prefers-reduced-motion: reduce)`).matches||(this._nudgeAnimation?.cancel(),this._nudgeAnimation=this.dialog.animate([{transform:`scale(1)`},{transform:`scale(1.02)`},{transform:`scale(1)`}],{duration:250,easing:`ease-in-out`}))}async _emitAfter(e){await new Promise(e=>requestAnimationFrame(()=>e(null)));let t=this.dialog.getAnimations({subtree:!1});await Promise.all(t.map(e=>e.finished.catch(()=>{}))),e===`after-show`===this.open&&this.emit(e)}_focusAutofocusTarget(){this.querySelector(`[autofocus]`)?.focus({preventScroll:!0})}render(){return e` <dialog part=\"dialog\" closedby=${this.lightDismiss&&c?`any`:t} > ${this.withoutHeader?t:e` <header part=\"header\"> <slot name=\"title\"> ${this.title?e`<h2 part=\"title\">${this.title}</h2>`:t} </slot> <slot name=\"close\"></slot> </header> `} <div part=\"body\"> <slot></slot> </div> <footer part=\"footer\"> <slot name=\"footer\"></slot> </footer> </dialog> `}}"
|
|
8053
8074
|
}
|
|
8054
8075
|
],
|
|
8055
8076
|
"exports": [
|
|
@@ -8123,7 +8144,7 @@
|
|
|
8123
8144
|
{
|
|
8124
8145
|
"kind": "variable",
|
|
8125
8146
|
"name": "s",
|
|
8126
|
-
"default": "class extends a{static{this.styles=[r,i,o]}}"
|
|
8147
|
+
"default": "class extends a{constructor(...e){super(...e),this._modalKind=`edge`}static{this.styles=[r,i,o]}}"
|
|
8127
8148
|
}
|
|
8128
8149
|
],
|
|
8129
8150
|
"exports": [
|
|
@@ -10390,6 +10411,15 @@
|
|
|
10390
10411
|
"text": "HTMLDialogElement"
|
|
10391
10412
|
}
|
|
10392
10413
|
},
|
|
10414
|
+
{
|
|
10415
|
+
"kind": "field",
|
|
10416
|
+
"name": "_modalKind",
|
|
10417
|
+
"type": {
|
|
10418
|
+
"text": "'centered' | 'edge'"
|
|
10419
|
+
},
|
|
10420
|
+
"privacy": "protected",
|
|
10421
|
+
"default": "'centered'"
|
|
10422
|
+
},
|
|
10393
10423
|
{
|
|
10394
10424
|
"kind": "field",
|
|
10395
10425
|
"name": "_mouseDownTarget",
|
|
@@ -10747,7 +10777,7 @@
|
|
|
10747
10777
|
"name": "--size"
|
|
10748
10778
|
},
|
|
10749
10779
|
{
|
|
10750
|
-
"description": "Drawer border radius on the inner edges. Default `0.
|
|
10780
|
+
"description": "Drawer border radius on the inner edges. Default `0.375rem`.",
|
|
10751
10781
|
"name": "--border-radius",
|
|
10752
10782
|
"inheritedFrom": {
|
|
10753
10783
|
"name": "Dialog",
|
|
@@ -10880,6 +10910,19 @@
|
|
|
10880
10910
|
}
|
|
10881
10911
|
],
|
|
10882
10912
|
"members": [
|
|
10913
|
+
{
|
|
10914
|
+
"kind": "field",
|
|
10915
|
+
"name": "_modalKind",
|
|
10916
|
+
"type": {
|
|
10917
|
+
"text": "'centered' | 'edge'"
|
|
10918
|
+
},
|
|
10919
|
+
"privacy": "protected",
|
|
10920
|
+
"default": "'edge'",
|
|
10921
|
+
"inheritedFrom": {
|
|
10922
|
+
"name": "Dialog",
|
|
10923
|
+
"module": "src/html/elements/dialog/dialog.ts"
|
|
10924
|
+
}
|
|
10925
|
+
},
|
|
10883
10926
|
{
|
|
10884
10927
|
"kind": "field",
|
|
10885
10928
|
"name": "placement",
|
|
@@ -41,6 +41,7 @@ export declare class Dialog extends LuxenElement {
|
|
|
41
41
|
/** Hide the header entirely (title and close slot). */
|
|
42
42
|
withoutHeader: boolean;
|
|
43
43
|
dialog: HTMLDialogElement;
|
|
44
|
+
protected _modalKind: 'centered' | 'edge';
|
|
44
45
|
private _mouseDownTarget;
|
|
45
46
|
private _commandListener;
|
|
46
47
|
connectedCallback(): void;
|
|
@@ -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;
|
|
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;AAgC7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,MAAO,SAAQ,YAAY;IACtC,MAAM,CAAC,MAAM,4BAAwB;IAErC,2CAA2C;IAE3C,KAAK,SAAM;IAEX,kCAAkC;IAElC,IAAI,UAAS;IAEb,0CAA0C;IAE1C,YAAY,UAAS;IAErB,uDAAuD;IAEvD,aAAa,UAAS;IAGtB,MAAM,EAAG,iBAAiB,CAAC;IAI3B,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAAc;IAEvD,OAAO,CAAC,gBAAgB,CAA4B;IAEpD,OAAO,CAAC,gBAAgB,CAEtB;IAIF,iBAAiB;IAKjB,oBAAoB;IAKpB,YAAY;IASZ,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC;IA0BrC,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,eAAe,CAAC,CAAY;IAEpC,OAAO,CAAC,aAAa;YAcP,UAAU;IAUxB,OAAO,CAAC,qBAAqB;IAK7B,MAAM;CA0BP"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import{i as e,n as t}from"../../chunks/lit.js";import{LuxenElement as n}from"../../shared/luxen-element.js";import{i as r,n as i,t as a}from"../../chunks/decorate.js";import o from"../../shared/styles/host.styles.js";import s from"./dialog.styles.js";var c=typeof HTMLDialogElement<`u`&&`closedBy`in HTMLDialogElement.prototype,l=Symbol.for(`luxen-dialog-scroll-lock`);if(typeof document<`u`&&!(l in document)){let e=new CSSStyleSheet;e.replaceSync(`
|
|
1
|
+
import{i as e,n as t}from"../../chunks/lit.js";import{LuxenElement as n}from"../../shared/luxen-element.js";import{i as r,n as i,t as a}from"../../chunks/decorate.js";import o from"../../shared/styles/host.styles.js";import s from"./dialog.styles.js";var c=typeof HTMLDialogElement<`u`&&`closedBy`in HTMLDialogElement.prototype,l=Symbol.for(`luxen-dialog-scroll-lock`);if(typeof document<`u`&&!(l in document)){let e=new CSSStyleSheet;e.replaceSync(`
|
|
2
|
+
html:has([data-modal]) { overflow: hidden; }
|
|
3
|
+
html:has([data-modal="centered"]) { scrollbar-gutter: stable; }
|
|
4
|
+
`),document.adoptedStyleSheets.push(e),Object.defineProperty(document,l,{value:e})}var u=class extends n{constructor(...e){super(...e),this.title=``,this.open=!1,this.lightDismiss=!1,this.withoutHeader=!1,this._modalKind=`centered`,this._mouseDownTarget=null,this._commandListener={handleEvent:e=>this._onCommand(e)}}static{this.styles=[o,s]}connectedCallback(){super.connectedCallback(),this.addEventListener(`command`,this._commandListener)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener(`command`,this._commandListener)}firstUpdated(){this.dialog.addEventListener(`cancel`,e=>this._onCancel(e)),this.dialog.addEventListener(`close`,()=>this._onNativeClose()),this.dialog.addEventListener(`mousedown`,e=>{this._mouseDownTarget=e.target}),this.dialog.addEventListener(`click`,e=>this._onDialogClick(e))}updated(e){if(e.has(`open`)){if(this.open&&!this.dialog.open)this.emit(`show`),this.setAttribute(`data-modal`,this._modalKind),this.dialog.showModal(),this._focusAutofocusTarget(),this._emitAfter(`after-show`);else if(!this.open&&this.dialog.open){if(!this.emit(`hide`,{cancelable:!0})){this.open=!0;return}this.dialog.close()}}}_onCommand(e){switch(e.command){case`--hide`:this.open=!1;break;case`--show`:this.open=!0;break}}_onCancel(e){this.emit(`hide`,{cancelable:!0})||e.preventDefault()}_onNativeClose(){this.open=!1,this.removeAttribute(`data-modal`),this._emitAfter(`after-hide`)}_onDialogClick(e){let t=e.target===this.dialog&&this._mouseDownTarget===this.dialog;if(this._mouseDownTarget=null,t){if(this.lightDismiss){c||(this.open=!1);return}this._nudgeDismiss()}}_nudgeDismiss(){matchMedia(`(prefers-reduced-motion: reduce)`).matches||(this._nudgeAnimation?.cancel(),this._nudgeAnimation=this.dialog.animate([{transform:`scale(1)`},{transform:`scale(1.02)`},{transform:`scale(1)`}],{duration:250,easing:`ease-in-out`}))}async _emitAfter(e){await new Promise(e=>requestAnimationFrame(()=>e(null)));let t=this.dialog.getAnimations({subtree:!1});await Promise.all(t.map(e=>e.finished.catch(()=>{}))),e===`after-show`===this.open&&this.emit(e)}_focusAutofocusTarget(){this.querySelector(`[autofocus]`)?.focus({preventScroll:!0})}render(){return e`
|
|
2
5
|
<dialog
|
|
3
6
|
part="dialog"
|
|
4
7
|
closedby=${this.lightDismiss&&c?`any`:t}
|
|
@@ -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 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.\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(`html:has([data-modal]) { overflow: hidden; scrollbar-gutter: stable; }`);\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.\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 - Dialog width. Default `31rem`.\n * @cssproperty --border-radius - Dialog border radius. Default `6px`.\n * @cssproperty --padding - Padding applied to the header, footer, and inline-padding of the body. Default `1.5rem`. Set to `0` to remove all internal spacing (e.g. for edge-to-edge media).\n * @cssproperty --show-duration - Open transition duration. Default `200ms`.\n * @cssproperty --hide-duration - Close transition duration. Default `200ms`.\n * @cssproperty --backdrop - Backdrop color.\n * @cssproperty --backdrop-blur - Backdrop blur amount (any CSS length). Default `0` (no blur). Set to e.g. `4px` for a subtle frost.\n *\n * @event show - Fired when the dialog opens. Not cancelable.\n * @event after-show - Fired after the open animation completes.\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.\n */\nexport class Dialog extends LuxenElement {\n static styles = [hostStyles, styles];\n\n /** Dialog title rendered in the header. */\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 @query('dialog')\n dialog!: HTMLDialogElement;\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 — not cancelable.\n this.emit('show');\n this.toggleAttribute('data-modal', true);\n this.dialog.showModal();\n this._focusAutofocusTarget();\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.emit('hide', { cancelable: true })) {\n this.open = true;\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 private _onCancel(e: Event) {\n if (!this.emit('hide', { cancelable: true })) {\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.emit(name);\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 private _focusAutofocusTarget() {\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 closedby=${closedby}\n >\n ${this.withoutHeader\n ? nothing\n : html`\n <header part=\"header\">\n <slot name=\"title\">\n ${this.title ? html`<h2 part=\"title\">${this.title}</h2>` : nothing}\n </slot>\n <slot name=\"close\"></slot>\n </header>\n `}\n <div part=\"body\">\n <slot></slot>\n </div>\n <footer part=\"footer\">\n <slot name=\"footer\"></slot>\n </footer>\n </dialog>\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 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.\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 - Dialog width. Default `31rem`.\n * @cssproperty --border-radius - Dialog border radius. Default `6px`.\n * @cssproperty --padding - Padding applied to the header, footer, and inline-padding of the body. Default `1.5rem`. Set to `0` to remove all internal spacing (e.g. for edge-to-edge media).\n * @cssproperty --show-duration - Open transition duration. Default `200ms`.\n * @cssproperty --hide-duration - Close transition duration. Default `200ms`.\n * @cssproperty --backdrop - Backdrop color.\n * @cssproperty --backdrop-blur - Backdrop blur amount (any CSS length). Default `0` (no blur). Set to e.g. `4px` for a subtle frost.\n *\n * @event show - Fired when the dialog opens. Not cancelable.\n * @event after-show - Fired after the open animation completes.\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.\n */\nexport class Dialog extends LuxenElement {\n static styles = [hostStyles, styles];\n\n /** Dialog title rendered in the header. */\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 @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 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 — not cancelable.\n this.emit('show');\n this.setAttribute('data-modal', this._modalKind);\n this.dialog.showModal();\n this._focusAutofocusTarget();\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.emit('hide', { cancelable: true })) {\n this.open = true;\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 private _onCancel(e: Event) {\n if (!this.emit('hide', { cancelable: true })) {\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.emit(name);\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 private _focusAutofocusTarget() {\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 closedby=${closedby}\n >\n ${this.withoutHeader\n ? nothing\n : html`\n <header part=\"header\">\n <slot name=\"title\">\n ${this.title ? html`<h2 part=\"title\">${this.title}</h2>` : nothing}\n </slot>\n <slot name=\"close\"></slot>\n </header>\n `}\n <div part=\"body\">\n <slot></slot>\n </div>\n <footer part=\"footer\">\n <slot name=\"footer\"></slot>\n </footer>\n </dialog>\n `;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{c as e}from"../../chunks/lit.js";var t=e(`:host{--width:31rem;--border-radius:6px;--padding:1.5rem;--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(--padding);justify-content:space-between;align-items:center;gap:1rem;display:flex}[part=title]{margin:0;font-size:1.125rem;font-weight:600;line-height:1.4}[part=body]{padding-inline:var(--padding);grid-row:2;overflow-y:auto}[part=footer]{padding:var(--padding);grid-row:3;place-content:end;gap:.5rem;display:flex}: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{c 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]{margin:0;font-size:1.125rem;font-weight:600;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}: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 --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(--padding);\n}\n\n[part='title'] {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\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(--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 --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: 600;\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/* 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,49CAAI"}
|
|
@@ -16,7 +16,7 @@ import { Dialog } from '../dialog/dialog.js';
|
|
|
16
16
|
* @csspart footer - The footer wrapper around the footer slot.
|
|
17
17
|
*
|
|
18
18
|
* @cssproperty --size - Drawer size on the axis perpendicular to its edge (width for `start`/`end`, height for `bottom`). Default `320px`.
|
|
19
|
-
* @cssproperty --border-radius - Drawer border radius on the inner edges. Default `0.
|
|
19
|
+
* @cssproperty --border-radius - Drawer border radius on the inner edges. Default `0.375rem`.
|
|
20
20
|
* @cssproperty --show-duration - Open transition duration. Default `200ms`.
|
|
21
21
|
* @cssproperty --hide-duration - Close transition duration. Default `200ms`.
|
|
22
22
|
* @cssproperty --backdrop - Backdrop color.
|
|
@@ -28,6 +28,7 @@ import { Dialog } from '../dialog/dialog.js';
|
|
|
28
28
|
*/
|
|
29
29
|
export declare class Drawer extends Dialog {
|
|
30
30
|
static styles: import('lit').CSSResult[];
|
|
31
|
+
protected _modalKind: "edge";
|
|
31
32
|
/** Edge the drawer slides in from. Defaults to the start (inline-start) edge. */
|
|
32
33
|
placement?: 'start' | 'end' | 'bottom';
|
|
33
34
|
}
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,MAAO,SAAQ,MAAM;IAChC,OAAgB,MAAM,4BAA4C;
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;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,QAAQ,CAAC;CACxC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{c 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:.
|
|
1
|
+
import{c 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}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%}}`),s=class extends a{constructor(...e){super(...e),this._modalKind=`edge`}static{this.styles=[r,i,o]}};n([t({reflect:!0})],s.prototype,`placement`,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.
|
|
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}\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","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 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 `bottom`). Default `320px`.\n * @cssproperty --border-radius - Drawer border radius on the inner edges. Default `0.375rem`.\n * @cssproperty --show-duration - Open transition duration. Default `200ms`.\n * @cssproperty --hide-duration - Close transition duration. Default `200ms`.\n * @cssproperty --backdrop - Backdrop color.\n *\n * @event show - Fired when the drawer opens. Not cancelable.\n * @event after-show - Fired after the open animation completes.\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.\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' | 'bottom';\n}\n"],"mappings":"qOCOA,IAAM,EAAe,EAAU,67BAAgB,CA6BlC,EAAb,cAA4B,CAAO,+CAKD,0BAJP,CAAC,EAAY,EAAc,EAAa,MAOhE,EAAS,CAAE,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,YAAA,IAAA,GAAA"}
|
package/cdn/standalone.css
CHANGED
|
@@ -1529,11 +1529,6 @@ In dark mode, mixes the base color with black (default 15% black).
|
|
|
1529
1529
|
--background-color: transparent;
|
|
1530
1530
|
--background-color-hover: light-dark(var(--l-color-gray-100), var(--l-color-gray-700));
|
|
1531
1531
|
|
|
1532
|
-
/*
|
|
1533
|
-
Accessibility: the overall size should be at least 44 pixels in height and width
|
|
1534
|
-
https://www.benjystanton.co.uk/blog/accessible-close-buttons/
|
|
1535
|
-
*/
|
|
1536
|
-
padding: var(--l-spacing-2);
|
|
1537
1532
|
border-radius: var(--l-radius-sm);
|
|
1538
1533
|
background-color: var(--background-color);
|
|
1539
1534
|
|
package/cdn/standalone.js
CHANGED
|
@@ -2930,14 +2930,17 @@ define("carousel-item", CarouselItem);
|
|
|
2930
2930
|
* `unsafeCSS()` is called once here so both importers share the same
|
|
2931
2931
|
* `CSSResult` instance (one constructed `CSSStyleSheet`, not two).
|
|
2932
2932
|
*/
|
|
2933
|
-
var dialog_styles_default = r$6(":host {\n --width: 31rem;\n --border-radius: 6px;\n --padding: 1.5rem;\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(--padding);\n}\n\n[part='title'] {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\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\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(--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\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");
|
|
2933
|
+
var dialog_styles_default = r$6(":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: 600;\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\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/* Without a header, the body has to provide its own block-start padding\n (normally inherited visually from the header padding above it). */\n\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");
|
|
2934
2934
|
//#endregion
|
|
2935
2935
|
//#region src/html/elements/dialog/dialog.ts
|
|
2936
2936
|
var supportsClosedBy = typeof HTMLDialogElement !== "undefined" && "closedBy" in HTMLDialogElement.prototype;
|
|
2937
2937
|
var SCROLL_LOCK_SHEET = Symbol.for("luxen-dialog-scroll-lock");
|
|
2938
2938
|
if (typeof document !== "undefined" && !(SCROLL_LOCK_SHEET in document)) {
|
|
2939
2939
|
const sheet = new CSSStyleSheet();
|
|
2940
|
-
sheet.replaceSync(`
|
|
2940
|
+
sheet.replaceSync(`
|
|
2941
|
+
html:has([data-modal]) { overflow: hidden; }
|
|
2942
|
+
html:has([data-modal="centered"]) { scrollbar-gutter: stable; }
|
|
2943
|
+
`);
|
|
2941
2944
|
document.adoptedStyleSheets.push(sheet);
|
|
2942
2945
|
Object.defineProperty(document, SCROLL_LOCK_SHEET, { value: sheet });
|
|
2943
2946
|
}
|
|
@@ -2978,6 +2981,7 @@ var Dialog = class extends LuxenElement {
|
|
|
2978
2981
|
this.open = false;
|
|
2979
2982
|
this.lightDismiss = false;
|
|
2980
2983
|
this.withoutHeader = false;
|
|
2984
|
+
this._modalKind = "centered";
|
|
2981
2985
|
this._mouseDownTarget = null;
|
|
2982
2986
|
this._commandListener = { handleEvent: (e) => this._onCommand(e) };
|
|
2983
2987
|
}
|
|
@@ -3004,7 +3008,7 @@ var Dialog = class extends LuxenElement {
|
|
|
3004
3008
|
if (!changed.has("open")) return;
|
|
3005
3009
|
if (this.open && !this.dialog.open) {
|
|
3006
3010
|
this.emit("show");
|
|
3007
|
-
this.
|
|
3011
|
+
this.setAttribute("data-modal", this._modalKind);
|
|
3008
3012
|
this.dialog.showModal();
|
|
3009
3013
|
this._focusAutofocusTarget();
|
|
3010
3014
|
this._emitAfter("after-show");
|
|
@@ -3146,7 +3150,7 @@ __decorate([n$1({ reflect: true })], Divider.prototype, "label", void 0);
|
|
|
3146
3150
|
define("divider", Divider);
|
|
3147
3151
|
//#endregion
|
|
3148
3152
|
//#region src/html/elements/drawer/drawer.ts
|
|
3149
|
-
var drawerStyles = r$6(":host {\n --size: 320px;\n --border-radius: 0.
|
|
3153
|
+
var drawerStyles = r$6(":host {\n --size: 320px;\n --border-radius: 0.375rem;\n}\n\n/* Override dialog's opacity fade with a slide from the inline-start edge. */\n\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\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\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");
|
|
3150
3154
|
/**
|
|
3151
3155
|
* A drawer that slides in from a screen edge. Extends `<l-dialog>`.
|
|
3152
3156
|
*
|
|
@@ -3164,7 +3168,7 @@ var drawerStyles = r$6(":host {\n --size: 320px;\n --border-radius: 0.75rem;\n
|
|
|
3164
3168
|
* @csspart footer - The footer wrapper around the footer slot.
|
|
3165
3169
|
*
|
|
3166
3170
|
* @cssproperty --size - Drawer size on the axis perpendicular to its edge (width for `start`/`end`, height for `bottom`). Default `320px`.
|
|
3167
|
-
* @cssproperty --border-radius - Drawer border radius on the inner edges. Default `0.
|
|
3171
|
+
* @cssproperty --border-radius - Drawer border radius on the inner edges. Default `0.375rem`.
|
|
3168
3172
|
* @cssproperty --show-duration - Open transition duration. Default `200ms`.
|
|
3169
3173
|
* @cssproperty --hide-duration - Close transition duration. Default `200ms`.
|
|
3170
3174
|
* @cssproperty --backdrop - Backdrop color.
|
|
@@ -3175,6 +3179,10 @@ var drawerStyles = r$6(":host {\n --size: 320px;\n --border-radius: 0.75rem;\n
|
|
|
3175
3179
|
* @event after-hide - Fired after the close animation completes.
|
|
3176
3180
|
*/
|
|
3177
3181
|
var Drawer = class extends Dialog {
|
|
3182
|
+
constructor(..._args) {
|
|
3183
|
+
super(..._args);
|
|
3184
|
+
this._modalKind = "edge";
|
|
3185
|
+
}
|
|
3178
3186
|
static {
|
|
3179
3187
|
this.styles = [
|
|
3180
3188
|
host_styles_default,
|