@ds-gn/ui 0.7.0 → 0.9.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/custom-elements.json +141 -3
- package/dist/common/props/motion/motion.props.d.ts +10 -0
- package/dist/components/Background/src/Background.js +1 -13
- package/dist/components/FeatureTabs/src/FeatureTabs.d.ts +28 -0
- package/dist/components/FeatureTabs/src/FeatureTabs.js +98 -42
- package/dist/components/FeatureTabs/src/FeatureTabs.props.d.ts +1 -1
- package/dist/components/FeatureTabs/src/FeatureTabs.styles.d.ts +1 -1
- package/dist/components/Heading/src/Heading.js +1 -13
- package/dist/components/Hero/src/Hero.d.ts +11 -0
- package/dist/components/Hero/src/Hero.js +39 -0
- package/dist/components/Modal/src/Modal.d.ts +4 -1
- package/dist/components/Modal/src/Modal.js +49 -264
- package/dist/components/Modal/src/Modal.props.d.ts +3 -0
- package/dist/components/Modal/src/Modal.props.js +9 -0
- package/dist/components/Modal/src/Modal.styles.d.ts +3 -7
- package/dist/styles/hero-fallback.css +5 -0
- package/package.json +6 -5
- package/dist/common/helpers/motion.d.ts +0 -9
package/custom-elements.json
CHANGED
|
@@ -1505,6 +1505,30 @@
|
|
|
1505
1505
|
"privacy": "private",
|
|
1506
1506
|
"default": "new AutoRotateController( this, DEFAULT_DURATION, () => this._inView.value === true, )"
|
|
1507
1507
|
},
|
|
1508
|
+
{
|
|
1509
|
+
"kind": "field",
|
|
1510
|
+
"name": "_motion",
|
|
1511
|
+
"privacy": "private",
|
|
1512
|
+
"default": "new MotionController(this)"
|
|
1513
|
+
},
|
|
1514
|
+
{
|
|
1515
|
+
"kind": "field",
|
|
1516
|
+
"name": "_shownIndex",
|
|
1517
|
+
"type": {
|
|
1518
|
+
"text": "number | undefined"
|
|
1519
|
+
},
|
|
1520
|
+
"privacy": "private",
|
|
1521
|
+
"description": "The feature whose detail last faded in; the fade replays when it changes."
|
|
1522
|
+
},
|
|
1523
|
+
{
|
|
1524
|
+
"kind": "field",
|
|
1525
|
+
"name": "_motionState",
|
|
1526
|
+
"type": {
|
|
1527
|
+
"text": "'static' | 'held' | 'played' | undefined"
|
|
1528
|
+
},
|
|
1529
|
+
"privacy": "private",
|
|
1530
|
+
"description": "Motion progress, decided by the first visibility report."
|
|
1531
|
+
},
|
|
1508
1532
|
{
|
|
1509
1533
|
"kind": "field",
|
|
1510
1534
|
"name": "surface",
|
|
@@ -1591,6 +1615,38 @@
|
|
|
1591
1615
|
"description": "Accessible label for the tab list.",
|
|
1592
1616
|
"attribute": "tabs-aria-label"
|
|
1593
1617
|
},
|
|
1618
|
+
{
|
|
1619
|
+
"kind": "field",
|
|
1620
|
+
"name": "motion",
|
|
1621
|
+
"type": {
|
|
1622
|
+
"text": "MotionType"
|
|
1623
|
+
},
|
|
1624
|
+
"description": "Animate the section in when it scrolls into view: the header's heading\nletter by letter, then its description, then the tabs as a whole. The\neyebrow stays static. A section already in view when it loads, and\nreduced motion, stay static.",
|
|
1625
|
+
"attribute": "motion",
|
|
1626
|
+
"reflects": true
|
|
1627
|
+
},
|
|
1628
|
+
{
|
|
1629
|
+
"kind": "method",
|
|
1630
|
+
"name": "_updateMotion",
|
|
1631
|
+
"privacy": "private",
|
|
1632
|
+
"description": "Decide the motion from the first visibility report: a section already\non screen stays static; one off screen holds its parts hidden (from\nscript, so nothing is hidden when scripts do not run) and plays when it\ncomes into view, so even a jump to it shows no unanimated frame."
|
|
1633
|
+
},
|
|
1634
|
+
{
|
|
1635
|
+
"kind": "method",
|
|
1636
|
+
"name": "_motionParts",
|
|
1637
|
+
"privacy": "private"
|
|
1638
|
+
},
|
|
1639
|
+
{
|
|
1640
|
+
"kind": "method",
|
|
1641
|
+
"name": "_playMotion",
|
|
1642
|
+
"privacy": "private"
|
|
1643
|
+
},
|
|
1644
|
+
{
|
|
1645
|
+
"kind": "method",
|
|
1646
|
+
"name": "_fadeInDetail",
|
|
1647
|
+
"privacy": "private",
|
|
1648
|
+
"description": "Fade the detail in whenever the active feature changes. `keyed` renders a\nfresh element per feature, so each change animates a new node. This runs\nafter render and before paint, so the new detail never shows unfaded."
|
|
1649
|
+
},
|
|
1594
1650
|
{
|
|
1595
1651
|
"kind": "method",
|
|
1596
1652
|
"name": "_handleTabClick",
|
|
@@ -1841,6 +1897,14 @@
|
|
|
1841
1897
|
},
|
|
1842
1898
|
"default": "DEFAULT_TABS_ARIA_LABEL",
|
|
1843
1899
|
"description": "Accessible label for the tab list."
|
|
1900
|
+
},
|
|
1901
|
+
{
|
|
1902
|
+
"name": "motion",
|
|
1903
|
+
"fieldName": "motion",
|
|
1904
|
+
"type": {
|
|
1905
|
+
"text": "MotionType"
|
|
1906
|
+
},
|
|
1907
|
+
"description": "Animate the section in when it scrolls into view: the header's heading\nletter by letter, then its description, then the tabs as a whole. The\neyebrow stays static. A section already in view when it loads, and\nreduced motion, stay static."
|
|
1844
1908
|
}
|
|
1845
1909
|
]
|
|
1846
1910
|
}
|
|
@@ -2621,6 +2685,32 @@
|
|
|
2621
2685
|
"description": "Space below the section. Unset follows the inherited section space.",
|
|
2622
2686
|
"attribute": "padding-bottom",
|
|
2623
2687
|
"reflects": true
|
|
2688
|
+
},
|
|
2689
|
+
{
|
|
2690
|
+
"kind": "field",
|
|
2691
|
+
"name": "motion",
|
|
2692
|
+
"type": {
|
|
2693
|
+
"text": "MotionType"
|
|
2694
|
+
},
|
|
2695
|
+
"description": "Animate the content's eyebrow in letter by letter once the hero loads,\neach letter fading in with a small rise.\nEverything else stays static, so the hero's largest text paints at once.\nUnder reduced motion the eyebrow is static too.",
|
|
2696
|
+
"attribute": "motion",
|
|
2697
|
+
"reflects": true
|
|
2698
|
+
},
|
|
2699
|
+
{
|
|
2700
|
+
"kind": "field",
|
|
2701
|
+
"name": "_motion",
|
|
2702
|
+
"privacy": "private",
|
|
2703
|
+
"default": "new MotionController(this)"
|
|
2704
|
+
},
|
|
2705
|
+
{
|
|
2706
|
+
"kind": "method",
|
|
2707
|
+
"name": "_eyebrows",
|
|
2708
|
+
"privacy": "private",
|
|
2709
|
+
"return": {
|
|
2710
|
+
"type": {
|
|
2711
|
+
"text": "Element[]"
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2624
2714
|
}
|
|
2625
2715
|
],
|
|
2626
2716
|
"superclass": {
|
|
@@ -2677,6 +2767,14 @@
|
|
|
2677
2767
|
"text": "SectionSpaceType | undefined"
|
|
2678
2768
|
},
|
|
2679
2769
|
"description": "Space below the section. Unset follows the inherited section space."
|
|
2770
|
+
},
|
|
2771
|
+
{
|
|
2772
|
+
"name": "motion",
|
|
2773
|
+
"fieldName": "motion",
|
|
2774
|
+
"type": {
|
|
2775
|
+
"text": "MotionType"
|
|
2776
|
+
},
|
|
2777
|
+
"description": "Animate the content's eyebrow in letter by letter once the hero loads,\neach letter fading in with a small rise.\nEverything else stays static, so the hero's largest text paints at once.\nUnder reduced motion the eyebrow is static too."
|
|
2680
2778
|
}
|
|
2681
2779
|
]
|
|
2682
2780
|
}
|
|
@@ -3620,6 +3718,13 @@
|
|
|
3620
3718
|
"attribute": "no-escape-dismiss",
|
|
3621
3719
|
"reflects": true
|
|
3622
3720
|
},
|
|
3721
|
+
{
|
|
3722
|
+
"kind": "field",
|
|
3723
|
+
"name": "_motion",
|
|
3724
|
+
"privacy": "private",
|
|
3725
|
+
"readonly": true,
|
|
3726
|
+
"default": "new MotionController(this)"
|
|
3727
|
+
},
|
|
3623
3728
|
{
|
|
3624
3729
|
"kind": "field",
|
|
3625
3730
|
"name": "_closing",
|
|
@@ -3627,8 +3732,17 @@
|
|
|
3627
3732
|
"text": "boolean"
|
|
3628
3733
|
},
|
|
3629
3734
|
"privacy": "private",
|
|
3630
|
-
"default": "false"
|
|
3631
|
-
|
|
3735
|
+
"default": "false"
|
|
3736
|
+
},
|
|
3737
|
+
{
|
|
3738
|
+
"kind": "field",
|
|
3739
|
+
"name": "_closeRun",
|
|
3740
|
+
"type": {
|
|
3741
|
+
"text": "number"
|
|
3742
|
+
},
|
|
3743
|
+
"privacy": "private",
|
|
3744
|
+
"default": "0",
|
|
3745
|
+
"description": "Invalidates an exit when reopened, disconnected, or closed externally."
|
|
3632
3746
|
},
|
|
3633
3747
|
{
|
|
3634
3748
|
"kind": "field",
|
|
@@ -3724,7 +3838,7 @@
|
|
|
3724
3838
|
"kind": "field",
|
|
3725
3839
|
"name": "_motionOrigin",
|
|
3726
3840
|
"type": {
|
|
3727
|
-
"text": "
|
|
3841
|
+
"text": "Exclude<ModalMotionType, 'inherit'>"
|
|
3728
3842
|
},
|
|
3729
3843
|
"privacy": "private",
|
|
3730
3844
|
"description": "The resolved animation origin, with `inherit` folded into `placement`.",
|
|
@@ -3800,6 +3914,30 @@
|
|
|
3800
3914
|
],
|
|
3801
3915
|
"description": "Play the exit animation, then leave the top layer. The dialog stays in the\ntop layer for the whole animation because `dialog.close()` is what removes\nit, and that is deliberately the last step — no timers involved, the wait is\non the animations' own `finished` promises."
|
|
3802
3916
|
},
|
|
3917
|
+
{
|
|
3918
|
+
"kind": "method",
|
|
3919
|
+
"name": "_animateDialog",
|
|
3920
|
+
"privacy": "private",
|
|
3921
|
+
"return": {
|
|
3922
|
+
"type": {
|
|
3923
|
+
"text": "Promise<void>"
|
|
3924
|
+
}
|
|
3925
|
+
},
|
|
3926
|
+
"parameters": [
|
|
3927
|
+
{
|
|
3928
|
+
"name": "dialog",
|
|
3929
|
+
"type": {
|
|
3930
|
+
"text": "HTMLDialogElement"
|
|
3931
|
+
}
|
|
3932
|
+
},
|
|
3933
|
+
{
|
|
3934
|
+
"name": "entering",
|
|
3935
|
+
"type": {
|
|
3936
|
+
"text": "boolean"
|
|
3937
|
+
}
|
|
3938
|
+
}
|
|
3939
|
+
]
|
|
3940
|
+
},
|
|
3803
3941
|
{
|
|
3804
3942
|
"kind": "method",
|
|
3805
3943
|
"name": "_focusInitialElement",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a section animates in. Components with their own motion
|
|
3
|
+
* vocabulary (Modal's direction values) declare their own `motion` values.
|
|
4
|
+
*/
|
|
5
|
+
export declare const motionValues: {
|
|
6
|
+
readonly ON: "on";
|
|
7
|
+
readonly OFF: "off";
|
|
8
|
+
};
|
|
9
|
+
export declare const motionProps: import("lit").PropertyDeclaration<unknown, unknown>;
|
|
10
|
+
export type MotionType = (typeof motionValues)[keyof typeof motionValues];
|
|
@@ -156,20 +156,8 @@ class Base extends LitElement {
|
|
|
156
156
|
}
|
|
157
157
|
defineElement("dsgn-base", Base);
|
|
158
158
|
|
|
159
|
-
// common/helpers/motion.ts
|
|
160
|
-
var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
161
|
-
var cachedMatchMedia;
|
|
162
|
-
var cachedQuery = null;
|
|
163
|
-
function prefersReducedMotion() {
|
|
164
|
-
const mm = typeof matchMedia === "function" ? matchMedia : undefined;
|
|
165
|
-
if (mm !== cachedMatchMedia) {
|
|
166
|
-
cachedMatchMedia = mm;
|
|
167
|
-
cachedQuery = mm ? mm(REDUCED_MOTION_QUERY) : null;
|
|
168
|
-
}
|
|
169
|
-
return cachedQuery?.matches ?? false;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
159
|
// common/controllers/AuroraMeshController.ts
|
|
160
|
+
import { prefersReducedMotion } from "@ds-gn/motion";
|
|
173
161
|
var X_MIN = -15;
|
|
174
162
|
var X_MAX = 70;
|
|
175
163
|
var Y_MIN = -20;
|
|
@@ -8,6 +8,7 @@ import '../../Icon/src/Icon.js';
|
|
|
8
8
|
import { Base } from '../../../common/Base/Base.js';
|
|
9
9
|
import { type SurfaceType } from '../../../common/props/surface/surface.props.js';
|
|
10
10
|
import { type CSSResultGroup } from 'lit';
|
|
11
|
+
import { type MotionType } from '../../../common/props/motion/motion.props.js';
|
|
11
12
|
import { type SectionSpaceType } from '../../Container/src/Container.props.js';
|
|
12
13
|
import { type FeatureTabData } from './FeatureTabs.props.js';
|
|
13
14
|
/** @slot header - Optional content above the tab interface. */
|
|
@@ -19,6 +20,11 @@ export declare class FeatureTabs extends Base {
|
|
|
19
20
|
paddingBottom?: SectionSpaceType;
|
|
20
21
|
private _inView;
|
|
21
22
|
private _rotate;
|
|
23
|
+
private _motion;
|
|
24
|
+
/** The feature whose detail last faded in; the fade replays when it changes. */
|
|
25
|
+
private _shownIndex?;
|
|
26
|
+
/** Motion progress, decided by the first visibility report. */
|
|
27
|
+
private _motionState?;
|
|
22
28
|
surface: SurfaceType;
|
|
23
29
|
features: FeatureTabData[];
|
|
24
30
|
duration: number;
|
|
@@ -34,9 +40,31 @@ export declare class FeatureTabs extends Base {
|
|
|
34
40
|
resumeAriaLabel: string;
|
|
35
41
|
/** Accessible label for the tab list. */
|
|
36
42
|
tabsAriaLabel: string;
|
|
43
|
+
/**
|
|
44
|
+
* Animate the section in when it scrolls into view: the header's heading
|
|
45
|
+
* letter by letter, then its description, then the tabs as a whole. The
|
|
46
|
+
* eyebrow stays static. A section already in view when it loads, and
|
|
47
|
+
* reduced motion, stay static.
|
|
48
|
+
*/
|
|
49
|
+
motion: MotionType;
|
|
37
50
|
constructor();
|
|
38
51
|
firstUpdated(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Decide the motion from the first visibility report: a section already
|
|
54
|
+
* on screen stays static; one off screen holds its parts hidden (from
|
|
55
|
+
* script, so nothing is hidden when scripts do not run) and plays when it
|
|
56
|
+
* comes into view, so even a jump to it shows no unanimated frame.
|
|
57
|
+
*/
|
|
58
|
+
private _updateMotion;
|
|
59
|
+
private _motionParts;
|
|
60
|
+
private _playMotion;
|
|
39
61
|
updated(changedProperties: Map<string | number | symbol, unknown>): void;
|
|
62
|
+
/**
|
|
63
|
+
* Fade the detail in whenever the active feature changes. `keyed` renders a
|
|
64
|
+
* fresh element per feature, so each change animates a new node. This runs
|
|
65
|
+
* after render and before paint, so the new detail never shows unfaded.
|
|
66
|
+
*/
|
|
67
|
+
private _fadeInDetail;
|
|
40
68
|
private _handleTabClick;
|
|
41
69
|
private _handleTabKeyDown;
|
|
42
70
|
private _handlePauseResume;
|
|
@@ -95,20 +95,8 @@ class Base extends LitElement {
|
|
|
95
95
|
}
|
|
96
96
|
defineElement("dsgn-base", Base);
|
|
97
97
|
|
|
98
|
-
// common/helpers/motion.ts
|
|
99
|
-
var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
100
|
-
var cachedMatchMedia;
|
|
101
|
-
var cachedQuery = null;
|
|
102
|
-
function prefersReducedMotion() {
|
|
103
|
-
const mm = typeof matchMedia === "function" ? matchMedia : undefined;
|
|
104
|
-
if (mm !== cachedMatchMedia) {
|
|
105
|
-
cachedMatchMedia = mm;
|
|
106
|
-
cachedQuery = mm ? mm(REDUCED_MOTION_QUERY) : null;
|
|
107
|
-
}
|
|
108
|
-
return cachedQuery?.matches ?? false;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
98
|
// common/controllers/AutoRotateController.ts
|
|
99
|
+
import { prefersReducedMotion } from "@ds-gn/motion";
|
|
112
100
|
var TICK_MS = 32;
|
|
113
101
|
|
|
114
102
|
class AutoRotateController {
|
|
@@ -229,6 +217,13 @@ var surfaceValues = {
|
|
|
229
217
|
};
|
|
230
218
|
var surfaceProps = enumCreator(Object.values(surfaceValues), "surface", String, { reflect: true });
|
|
231
219
|
|
|
220
|
+
// components/FeatureTabs/src/FeatureTabs.ts
|
|
221
|
+
import {
|
|
222
|
+
prefersReducedMotion as prefersReducedMotion2,
|
|
223
|
+
splitText
|
|
224
|
+
} from "@ds-gn/motion";
|
|
225
|
+
import { MotionController } from "@ds-gn/motion/lit";
|
|
226
|
+
|
|
232
227
|
// ../../node_modules/.bun/lit-html@3.3.3/node_modules/lit-html/development/is-server.js
|
|
233
228
|
var NODE_MODE = false;
|
|
234
229
|
var isServer = NODE_MODE;
|
|
@@ -303,6 +298,15 @@ import {
|
|
|
303
298
|
import { property } from "lit/decorators.js";
|
|
304
299
|
import { keyed } from "lit/directives/keyed.js";
|
|
305
300
|
import { styleMap } from "lit/directives/style-map.js";
|
|
301
|
+
|
|
302
|
+
// common/props/motion/motion.props.ts
|
|
303
|
+
var motionValues = {
|
|
304
|
+
ON: "on",
|
|
305
|
+
OFF: "off"
|
|
306
|
+
};
|
|
307
|
+
var motionProps = enumCreator(Object.values(motionValues), "motion", String, { reflect: true });
|
|
308
|
+
|
|
309
|
+
// components/FeatureTabs/src/FeatureTabs.ts
|
|
306
310
|
import {
|
|
307
311
|
containerSizeValues,
|
|
308
312
|
paddingBottomProps,
|
|
@@ -338,8 +342,6 @@ var styles2 = css2`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.co
|
|
|
338
342
|
--color-text-primary: inherit;
|
|
339
343
|
--color-text-secondary: inherit;
|
|
340
344
|
--color-text-tertiary: inherit;
|
|
341
|
-
--animate-fade-in-a: fade-in-a 0.3s ease-in;
|
|
342
|
-
--animate-fade-in-b: fade-in-b 0.3s ease-in;
|
|
343
345
|
}
|
|
344
346
|
}
|
|
345
347
|
@layer utilities {
|
|
@@ -463,12 +465,6 @@ var styles2 = css2`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.co
|
|
|
463
465
|
.shrink-0 {
|
|
464
466
|
flex-shrink: 0;
|
|
465
467
|
}
|
|
466
|
-
.animate-fade-in-a {
|
|
467
|
-
animation: var(--animate-fade-in-a);
|
|
468
|
-
}
|
|
469
|
-
.animate-fade-in-b {
|
|
470
|
-
animation: var(--animate-fade-in-b);
|
|
471
|
-
}
|
|
472
468
|
.cursor-pointer {
|
|
473
469
|
cursor: pointer;
|
|
474
470
|
}
|
|
@@ -850,22 +846,6 @@ var styles2 = css2`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.co
|
|
|
850
846
|
syntax: "*";
|
|
851
847
|
inherits: false;
|
|
852
848
|
}
|
|
853
|
-
@keyframes fade-in-a {
|
|
854
|
-
from {
|
|
855
|
-
opacity: 0;
|
|
856
|
-
}
|
|
857
|
-
to {
|
|
858
|
-
opacity: 1;
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
@keyframes fade-in-b {
|
|
862
|
-
from {
|
|
863
|
-
opacity: 0;
|
|
864
|
-
}
|
|
865
|
-
to {
|
|
866
|
-
opacity: 1;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
849
|
@layer properties {
|
|
870
850
|
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
|
871
851
|
*, ::before, ::after, ::backdrop {
|
|
@@ -1019,7 +999,7 @@ var patternOverlayStyles = () => ({
|
|
|
1019
999
|
maskImage: PATTERN_MASK,
|
|
1020
1000
|
WebkitMaskImage: PATTERN_MASK
|
|
1021
1001
|
});
|
|
1022
|
-
var detailContentClassNames = (
|
|
1002
|
+
var detailContentClassNames = () => clsx_default("relative", "flex", "flex-col", "flex-1");
|
|
1023
1003
|
var detailHeaderClassNames = () => clsx_default("flex", "items-center", "gap-3", "mb-6");
|
|
1024
1004
|
var detailEyebrowClassNames = () => clsx_default("font-mono", "text-[11px]", "tracking-[0.06em]", "uppercase", "text-text-tertiary");
|
|
1025
1005
|
var detailCounterClassNames = () => clsx_default("ml-auto", "font-mono", "text-[12px]", "text-text-tertiary");
|
|
@@ -1036,13 +1016,20 @@ var dotPipInnerClassNames = (active) => clsx_default("block", "rounded-full", "h
|
|
|
1036
1016
|
var playPauseClassNames = () => clsx_default("appearance-none", "border-0", "outline-none", "bg-transparent", "cursor-pointer", "text-accent", "py-[10px]", "px-[8px]", "flex", "items-center", "justify-center", "rounded-full", "transition-colors", "duration-150");
|
|
1037
1017
|
|
|
1038
1018
|
// components/FeatureTabs/src/FeatureTabs.ts
|
|
1019
|
+
var holdHidden = (el) => el.style.setProperty("opacity", "0");
|
|
1020
|
+
var releaseHidden = (el) => el.style.removeProperty("opacity");
|
|
1021
|
+
var HEADING_STAGGER = 20;
|
|
1022
|
+
var HEADING_MAX_SPREAD = 500;
|
|
1023
|
+
var HEADING_RISE = 4;
|
|
1024
|
+
var MOTION_OVERLAP = 160;
|
|
1039
1025
|
var FEATURE_TAB_ICONS = {
|
|
1040
1026
|
terminal: svg`<polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/>`,
|
|
1041
1027
|
brain: svg`<path d="M9 4.5a2.5 2.5 0 0 0-2.5 2.5v.5a2.5 2.5 0 0 0-2 4 2.5 2.5 0 0 0 2 4v.5A2.5 2.5 0 0 0 9 18.5a2.5 2.5 0 0 0 3-2.5V6a2.5 2.5 0 0 0-3-1.5z"/><path d="M15 4.5A2.5 2.5 0 0 1 17.5 7v.5a2.5 2.5 0 0 1 2 4 2.5 2.5 0 0 1-2 4v.5A2.5 2.5 0 0 1 15 18.5a2.5 2.5 0 0 1-3-2.5V6a2.5 2.5 0 0 1 3-1.5z"/>`,
|
|
1042
1028
|
cpu: svg`<rect x="5" y="5" width="14" height="14" rx="2"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="2" x2="9" y2="5"/><line x1="15" y1="2" x2="15" y2="5"/><line x1="9" y1="19" x2="9" y2="22"/><line x1="15" y1="19" x2="15" y2="22"/><line x1="2" y1="9" x2="5" y2="9"/><line x1="2" y1="15" x2="5" y2="15"/><line x1="19" y1="9" x2="22" y2="9"/><line x1="19" y1="15" x2="22" y2="15"/>`,
|
|
1043
1029
|
palette: svg`<circle cx="12" cy="12" r="9"/><circle cx="7.5" cy="10.5" r="1" fill="currentColor"/><circle cx="12" cy="7.5" r="1" fill="currentColor"/><circle cx="16.5" cy="10.5" r="1" fill="currentColor"/><path d="M12 21a3 3 0 0 1-3-3c0-1.5 1-2 1-3a2 2 0 0 0-2-2"/>`,
|
|
1044
1030
|
plug: svg`<path d="M9 2v6"/><path d="M15 2v6"/><path d="M7 8h10v3a5 5 0 0 1-5 5 5 5 0 0 1-5-5z"/><path d="M12 16v6"/>`,
|
|
1045
|
-
shield: svg`<path d="M12 3l8 3v5c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6z"/><path d="M9 12l2 2 4-4"
|
|
1031
|
+
shield: svg`<path d="M12 3l8 3v5c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6z"/><path d="M9 12l2 2 4-4"/>`,
|
|
1032
|
+
zap: svg`<path d="M13 2 4 14h7l-1 8 9-12h-7z"/>`
|
|
1046
1033
|
};
|
|
1047
1034
|
var nextTabIndex = (key, index, lastIndex) => {
|
|
1048
1035
|
switch (key) {
|
|
@@ -1069,6 +1056,7 @@ class FeatureTabs extends Base {
|
|
|
1069
1056
|
config: { threshold: 0 },
|
|
1070
1057
|
callback: (entries) => entries[entries.length - 1]?.isIntersecting ?? false
|
|
1071
1058
|
});
|
|
1059
|
+
this._motion = new MotionController(this);
|
|
1072
1060
|
this.surface = surfaceValues.DARK;
|
|
1073
1061
|
this.features = DEFAULT_FEATURES;
|
|
1074
1062
|
this.duration = DEFAULT_DURATION;
|
|
@@ -1078,17 +1066,82 @@ class FeatureTabs extends Base {
|
|
|
1078
1066
|
this.pauseAriaLabel = DEFAULT_PAUSE_ARIA_LABEL;
|
|
1079
1067
|
this.resumeAriaLabel = DEFAULT_RESUME_ARIA_LABEL;
|
|
1080
1068
|
this.tabsAriaLabel = DEFAULT_TABS_ARIA_LABEL;
|
|
1069
|
+
this.motion = motionValues.OFF;
|
|
1081
1070
|
this._rotate = new AutoRotateController(this, DEFAULT_DURATION, () => this._inView.value === true);
|
|
1082
1071
|
}
|
|
1083
1072
|
firstUpdated() {
|
|
1084
1073
|
this._rotate.resume(this.features.length);
|
|
1085
1074
|
}
|
|
1075
|
+
_updateMotion() {
|
|
1076
|
+
const inView = this._inView.value;
|
|
1077
|
+
if (inView === undefined)
|
|
1078
|
+
return;
|
|
1079
|
+
if (this._motionState === undefined) {
|
|
1080
|
+
const play = this.motion === motionValues.ON && !inView && !prefersReducedMotion2();
|
|
1081
|
+
this._motionState = play ? "held" : "static";
|
|
1082
|
+
if (play)
|
|
1083
|
+
this._motionParts().forEach(holdHidden);
|
|
1084
|
+
}
|
|
1085
|
+
if (this._motionState === "held" && inView) {
|
|
1086
|
+
this._motionState = "played";
|
|
1087
|
+
this._playMotion();
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
_motionParts() {
|
|
1091
|
+
const header = Array.from(this.children).filter((el) => el.slot === "header");
|
|
1092
|
+
const find = (slot) => header.map((el) => el.querySelector(`[slot="${slot}"]`)).find((el) => el !== null);
|
|
1093
|
+
return [
|
|
1094
|
+
find("heading"),
|
|
1095
|
+
find("description"),
|
|
1096
|
+
...this.renderRoot.querySelectorAll("[data-motion-body]")
|
|
1097
|
+
].filter((el) => el !== undefined);
|
|
1098
|
+
}
|
|
1099
|
+
_playMotion() {
|
|
1100
|
+
const parts = this._motionParts();
|
|
1101
|
+
parts.forEach(releaseHidden);
|
|
1102
|
+
const heading = parts.find((el) => el.slot === "heading");
|
|
1103
|
+
const description = parts.find((el) => el.slot === "description");
|
|
1104
|
+
const split = heading ? splitText(heading) : undefined;
|
|
1105
|
+
const steps = [
|
|
1106
|
+
...split ? [
|
|
1107
|
+
{
|
|
1108
|
+
targets: split.chars,
|
|
1109
|
+
preset: "fade",
|
|
1110
|
+
y: HEADING_RISE,
|
|
1111
|
+
stagger: HEADING_STAGGER,
|
|
1112
|
+
maxDuration: HEADING_MAX_SPREAD
|
|
1113
|
+
}
|
|
1114
|
+
] : [],
|
|
1115
|
+
...description ? [
|
|
1116
|
+
{
|
|
1117
|
+
el: description,
|
|
1118
|
+
preset: "fade",
|
|
1119
|
+
overlap: MOTION_OVERLAP
|
|
1120
|
+
}
|
|
1121
|
+
] : [],
|
|
1122
|
+
{
|
|
1123
|
+
targets: parts.filter((el) => el.hasAttribute("data-motion-body")),
|
|
1124
|
+
preset: "fade",
|
|
1125
|
+
overlap: MOTION_OVERLAP
|
|
1126
|
+
}
|
|
1127
|
+
];
|
|
1128
|
+
this._motion.timeline(steps).finished.then(() => split?.revert());
|
|
1129
|
+
}
|
|
1086
1130
|
updated(changedProperties) {
|
|
1087
1131
|
super.updated(changedProperties);
|
|
1088
1132
|
this.updateTheme(changedProperties, this.surface);
|
|
1089
1133
|
if (changedProperties.has("duration")) {
|
|
1090
1134
|
this._rotate.setDuration(this.duration);
|
|
1091
1135
|
}
|
|
1136
|
+
this._fadeInDetail();
|
|
1137
|
+
this._updateMotion();
|
|
1138
|
+
}
|
|
1139
|
+
_fadeInDetail() {
|
|
1140
|
+
const index = this._rotate.activeIndex;
|
|
1141
|
+
if (index === this._shownIndex)
|
|
1142
|
+
return;
|
|
1143
|
+
this._shownIndex = index;
|
|
1144
|
+
this.renderRoot.querySelectorAll("[data-detail-content]").forEach((detail) => void this._motion.enter(detail, "fade"));
|
|
1092
1145
|
}
|
|
1093
1146
|
_handleTabClick(index) {
|
|
1094
1147
|
this._rotate.goTo(index);
|
|
@@ -1148,7 +1201,7 @@ class FeatureTabs extends Base {
|
|
|
1148
1201
|
<div aria-hidden="true" style=${styleMap(patternOverlayStyles())}></div>
|
|
1149
1202
|
|
|
1150
1203
|
${keyed(idx, html2`
|
|
1151
|
-
<div class="${detailContentClassNames(
|
|
1204
|
+
<div class="${detailContentClassNames()}" data-detail-content>
|
|
1152
1205
|
<div class="${detailHeaderClassNames()}">
|
|
1153
1206
|
<span class="${iconBadgeClassNames(true, true)}">
|
|
1154
1207
|
${this._renderIcon(feature.icon, "lg")}
|
|
@@ -1286,12 +1339,12 @@ class FeatureTabs extends Base {
|
|
|
1286
1339
|
</div>
|
|
1287
1340
|
|
|
1288
1341
|
<!-- Mobile: detail panel only, no grid -->
|
|
1289
|
-
<div class="lg:hidden">
|
|
1342
|
+
<div class="lg:hidden" data-motion-body>
|
|
1290
1343
|
${this._renderDetailPanel(idx, activeFeature, progress, total, paused, features)}
|
|
1291
1344
|
</div>
|
|
1292
1345
|
|
|
1293
1346
|
<!-- Desktop: full grid with tabs + detail -->
|
|
1294
|
-
<div class="hidden lg:block">
|
|
1347
|
+
<div class="hidden lg:block" data-motion-body>
|
|
1295
1348
|
<dsgn-grid cols="7-5" gap="xl" ?reverse=${true}>
|
|
1296
1349
|
${this._renderTabList(features, idx, progress, paused, "col-2")}
|
|
1297
1350
|
${this._renderDetailPanel(idx, activeFeature, progress, total, paused, features, "col-1")}
|
|
@@ -1335,6 +1388,9 @@ __legacyDecorateClassTS([
|
|
|
1335
1388
|
__legacyDecorateClassTS([
|
|
1336
1389
|
property({ type: String, attribute: "tabs-aria-label" })
|
|
1337
1390
|
], FeatureTabs.prototype, "tabsAriaLabel", undefined);
|
|
1391
|
+
__legacyDecorateClassTS([
|
|
1392
|
+
property({ ...motionProps })
|
|
1393
|
+
], FeatureTabs.prototype, "motion", undefined);
|
|
1338
1394
|
defineElement("dsgn-feature-tabs", FeatureTabs);
|
|
1339
1395
|
export {
|
|
1340
1396
|
FeatureTabs
|
|
@@ -18,7 +18,7 @@ export declare const controlBtnClassNames: () => string;
|
|
|
18
18
|
export declare const controlDotClassNames: (rotating: boolean) => string;
|
|
19
19
|
export declare const detailClassNames: () => string;
|
|
20
20
|
export declare const patternOverlayStyles: () => Record<string, string>;
|
|
21
|
-
export declare const detailContentClassNames: (
|
|
21
|
+
export declare const detailContentClassNames: () => string;
|
|
22
22
|
export declare const detailHeaderClassNames: () => string;
|
|
23
23
|
export declare const detailEyebrowClassNames: () => string;
|
|
24
24
|
export declare const detailCounterClassNames: () => string;
|
|
@@ -157,20 +157,8 @@ class Base extends LitElement {
|
|
|
157
157
|
}
|
|
158
158
|
defineElement("dsgn-base", Base);
|
|
159
159
|
|
|
160
|
-
// common/helpers/motion.ts
|
|
161
|
-
var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
162
|
-
var cachedMatchMedia;
|
|
163
|
-
var cachedQuery = null;
|
|
164
|
-
function prefersReducedMotion() {
|
|
165
|
-
const mm = typeof matchMedia === "function" ? matchMedia : undefined;
|
|
166
|
-
if (mm !== cachedMatchMedia) {
|
|
167
|
-
cachedMatchMedia = mm;
|
|
168
|
-
cachedQuery = mm ? mm(REDUCED_MOTION_QUERY) : null;
|
|
169
|
-
}
|
|
170
|
-
return cachedQuery?.matches ?? false;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
160
|
// common/controllers/WordCycleController.ts
|
|
161
|
+
import { prefersReducedMotion } from "@ds-gn/motion";
|
|
174
162
|
var DEFAULT_INTERVAL = 1000;
|
|
175
163
|
|
|
176
164
|
class WordCycleController {
|
|
@@ -5,6 +5,7 @@ import '../../Grid/src/Grid.js';
|
|
|
5
5
|
import '../../HeadingBlock/src/HeadingBlock.js';
|
|
6
6
|
import { type CSSResultGroup } from 'lit';
|
|
7
7
|
import { Base } from '../../../common/Base/Base.js';
|
|
8
|
+
import { type MotionType } from '../../../common/props/motion/motion.props.js';
|
|
8
9
|
import { type SurfaceType } from '../../../common/props/surface/surface.props.js';
|
|
9
10
|
import { type SectionSpaceType } from '../../Container/src/Container.props.js';
|
|
10
11
|
import { type HeroContentAlignType, type HeroLayoutType, type HeroMinHeightType } from './Hero.props.js';
|
|
@@ -37,6 +38,16 @@ export declare class Hero extends Base {
|
|
|
37
38
|
paddingTop?: SectionSpaceType;
|
|
38
39
|
/** Space below the section. Unset follows the inherited section space. */
|
|
39
40
|
paddingBottom?: SectionSpaceType;
|
|
41
|
+
/**
|
|
42
|
+
* Animate the content's eyebrow in letter by letter once the hero loads,
|
|
43
|
+
* each letter fading in with a small rise.
|
|
44
|
+
* Everything else stays static, so the hero's largest text paints at once.
|
|
45
|
+
* Under reduced motion the eyebrow is static too.
|
|
46
|
+
*/
|
|
47
|
+
motion: MotionType;
|
|
48
|
+
private _motion;
|
|
49
|
+
firstUpdated(): void;
|
|
50
|
+
private _eyebrows;
|
|
40
51
|
updated(changedProperties: Map<string | number | symbol, unknown>): void;
|
|
41
52
|
render(): import("lit").TemplateResult<1>;
|
|
42
53
|
}
|
|
@@ -14,6 +14,8 @@ import"../../Container/src/Container.js";
|
|
|
14
14
|
import"../../FormBlock/src/FormBlock.js";
|
|
15
15
|
import"../../Grid/src/Grid.js";
|
|
16
16
|
import"../../HeadingBlock/src/HeadingBlock.js";
|
|
17
|
+
import { prefersReducedMotion, splitText } from "@ds-gn/motion";
|
|
18
|
+
import { MotionController } from "@ds-gn/motion/lit";
|
|
17
19
|
import { html as html2 } from "lit";
|
|
18
20
|
import { property } from "lit/decorators.js";
|
|
19
21
|
|
|
@@ -118,6 +120,13 @@ var enumCreator = (acceptableValues, propName, type, other = {}) => {
|
|
|
118
120
|
};
|
|
119
121
|
};
|
|
120
122
|
|
|
123
|
+
// common/props/motion/motion.props.ts
|
|
124
|
+
var motionValues = {
|
|
125
|
+
ON: "on",
|
|
126
|
+
OFF: "off"
|
|
127
|
+
};
|
|
128
|
+
var motionProps = enumCreator(Object.values(motionValues), "motion", String, { reflect: true });
|
|
129
|
+
|
|
121
130
|
// common/props/surface/surface.props.ts
|
|
122
131
|
var surfaceValues = {
|
|
123
132
|
LIGHT: "light",
|
|
@@ -189,6 +198,9 @@ var styles2 = css2`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.co
|
|
|
189
198
|
.grid {
|
|
190
199
|
display: grid;
|
|
191
200
|
}
|
|
201
|
+
.hidden {
|
|
202
|
+
display: none;
|
|
203
|
+
}
|
|
192
204
|
.h-64 {
|
|
193
205
|
height: calc(var(--spacing) * 64);
|
|
194
206
|
}
|
|
@@ -412,6 +424,11 @@ var centeredFormClassNames = (contentAlign) => {
|
|
|
412
424
|
};
|
|
413
425
|
|
|
414
426
|
// components/Hero/src/Hero.ts
|
|
427
|
+
var EYEBROW_DELAY = 500;
|
|
428
|
+
var EYEBROW_STAGGER = 30;
|
|
429
|
+
var EYEBROW_MAX_SPREAD = 600;
|
|
430
|
+
var EYEBROW_RISE = 4;
|
|
431
|
+
|
|
415
432
|
class Hero extends Base {
|
|
416
433
|
constructor() {
|
|
417
434
|
super(...arguments);
|
|
@@ -419,8 +436,27 @@ class Hero extends Base {
|
|
|
419
436
|
this.layout = heroLayoutValues.ASSET_RIGHT;
|
|
420
437
|
this.minHeight = heroMinHeightValues.MD;
|
|
421
438
|
this.contentAlign = heroContentAlignValues.START;
|
|
439
|
+
this.motion = motionValues.OFF;
|
|
440
|
+
this._motion = new MotionController(this);
|
|
422
441
|
}
|
|
423
442
|
static styles = [Base.styles, Hero_default];
|
|
443
|
+
firstUpdated() {
|
|
444
|
+
if (this.motion !== motionValues.ON || prefersReducedMotion())
|
|
445
|
+
return;
|
|
446
|
+
this._eyebrows().forEach((eyebrow) => {
|
|
447
|
+
const split = splitText(eyebrow);
|
|
448
|
+
this._motion.sequence(split.chars, {
|
|
449
|
+
preset: "fade",
|
|
450
|
+
y: EYEBROW_RISE,
|
|
451
|
+
delay: EYEBROW_DELAY,
|
|
452
|
+
stagger: EYEBROW_STAGGER,
|
|
453
|
+
maxDuration: EYEBROW_MAX_SPREAD
|
|
454
|
+
}).finished.then(split.revert);
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
_eyebrows() {
|
|
458
|
+
return Array.from(this.children).filter((el) => el.slot === "content").flatMap((el) => Array.from(el.querySelectorAll('[slot="eyebrow"]')));
|
|
459
|
+
}
|
|
424
460
|
updated(changedProperties) {
|
|
425
461
|
super.updated(changedProperties);
|
|
426
462
|
this.updateTheme(changedProperties, this.surface);
|
|
@@ -526,6 +562,9 @@ __legacyDecorateClassTS([
|
|
|
526
562
|
__legacyDecorateClassTS([
|
|
527
563
|
property({ ...paddingBottomProps })
|
|
528
564
|
], Hero.prototype, "paddingBottom", undefined);
|
|
565
|
+
__legacyDecorateClassTS([
|
|
566
|
+
property({ ...motionProps })
|
|
567
|
+
], Hero.prototype, "motion", undefined);
|
|
529
568
|
defineElement("dsgn-hero", Hero);
|
|
530
569
|
export {
|
|
531
570
|
Hero
|
|
@@ -72,8 +72,10 @@ export declare class Modal extends Base {
|
|
|
72
72
|
* keyboard users are stuck.
|
|
73
73
|
*/
|
|
74
74
|
noEscapeDismiss: boolean;
|
|
75
|
-
|
|
75
|
+
private readonly _motion;
|
|
76
76
|
private _closing;
|
|
77
|
+
/** Invalidates an exit when reopened, disconnected, or closed externally. */
|
|
78
|
+
private _closeRun;
|
|
77
79
|
private _hasHeading;
|
|
78
80
|
private _hasDescription;
|
|
79
81
|
private _hasFooter;
|
|
@@ -118,6 +120,7 @@ export declare class Modal extends Base {
|
|
|
118
120
|
* on the animations' own `finished` promises.
|
|
119
121
|
*/
|
|
120
122
|
private _runCloseSequence;
|
|
123
|
+
private _animateDialog;
|
|
121
124
|
/**
|
|
122
125
|
* Deliberate initial focus: an author-marked `[autofocus]` (light DOM first,
|
|
123
126
|
* since that is where the modal's content lives), otherwise the dialog itself.
|
|
@@ -11,6 +11,8 @@ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
|
|
|
11
11
|
|
|
12
12
|
// components/Modal/src/Modal.ts
|
|
13
13
|
import"../../Button/src/Button.js";
|
|
14
|
+
import { cancel } from "@ds-gn/motion";
|
|
15
|
+
import { MotionController } from "@ds-gn/motion/lit";
|
|
14
16
|
import { html as html2, nothing } from "lit";
|
|
15
17
|
import { property, query, state } from "lit/decorators.js";
|
|
16
18
|
|
|
@@ -146,9 +148,6 @@ var styles2 = css2`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.co
|
|
|
146
148
|
--font-weight-semibold: 600;
|
|
147
149
|
--default-transition-duration: 150ms;
|
|
148
150
|
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
149
|
-
--duration-moderate: var(--dsgn-src-duration-moderate, 240ms);
|
|
150
|
-
--duration-quick: var(--dsgn-src-duration-quick, 180ms);
|
|
151
|
-
--ease-emphasized: var(--dsgn-src-ease-emphasized, cubic-bezier(0.16, 1, 0.3, 1));
|
|
152
151
|
--radius-surface: var(--dsgn-src-radius-surface, 1rem);
|
|
153
152
|
--color-accent: inherit;
|
|
154
153
|
--color-focus: inherit;
|
|
@@ -156,29 +155,6 @@ var styles2 = css2`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.co
|
|
|
156
155
|
--color-text-primary: inherit;
|
|
157
156
|
--color-text-secondary: inherit;
|
|
158
157
|
--shadow-card: inherit;
|
|
159
|
-
--animate-fade-in: fade-in var(--duration-moderate) var(--ease-emphasized)
|
|
160
|
-
both;
|
|
161
|
-
--animate-fade-out: fade-out var(--duration-quick) var(--ease-emphasized) both;
|
|
162
|
-
--animate-scale-in: scale-in var(--duration-moderate) var(--ease-emphasized)
|
|
163
|
-
both;
|
|
164
|
-
--animate-scale-out: scale-out var(--duration-quick) var(--ease-emphasized)
|
|
165
|
-
both;
|
|
166
|
-
--animate-slide-in-left: slide-in-left var(--duration-moderate)
|
|
167
|
-
var(--ease-emphasized) both;
|
|
168
|
-
--animate-slide-out-left: slide-out-left var(--duration-quick)
|
|
169
|
-
var(--ease-emphasized) both;
|
|
170
|
-
--animate-slide-in-right: slide-in-right var(--duration-moderate)
|
|
171
|
-
var(--ease-emphasized) both;
|
|
172
|
-
--animate-slide-out-right: slide-out-right var(--duration-quick)
|
|
173
|
-
var(--ease-emphasized) both;
|
|
174
|
-
--animate-slide-in-top: slide-in-top var(--duration-moderate)
|
|
175
|
-
var(--ease-emphasized) both;
|
|
176
|
-
--animate-slide-out-top: slide-out-top var(--duration-quick)
|
|
177
|
-
var(--ease-emphasized) both;
|
|
178
|
-
--animate-slide-in-bottom: slide-in-bottom var(--duration-moderate)
|
|
179
|
-
var(--ease-emphasized) both;
|
|
180
|
-
--animate-slide-out-bottom: slide-out-bottom var(--duration-quick)
|
|
181
|
-
var(--ease-emphasized) both;
|
|
182
158
|
}
|
|
183
159
|
}
|
|
184
160
|
@layer utilities {
|
|
@@ -640,122 +616,6 @@ var styles2 = css2`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.co
|
|
|
640
616
|
--dsgn-modal-size: 56rem;
|
|
641
617
|
}
|
|
642
618
|
}
|
|
643
|
-
.data-\\[state\\=closed\\]\\:backdrop\\:animate-fade-out {
|
|
644
|
-
&[data-state="closed"] {
|
|
645
|
-
&::backdrop {
|
|
646
|
-
animation: var(--animate-fade-out);
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
.data-\\[motion\\=bottom\\]\\:data-\\[state\\=closed\\]\\:animate-slide-out-bottom {
|
|
651
|
-
&[data-motion="bottom"] {
|
|
652
|
-
&[data-state="closed"] {
|
|
653
|
-
animation: var(--animate-slide-out-bottom);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
.data-\\[motion\\=center\\]\\:data-\\[state\\=closed\\]\\:animate-scale-out {
|
|
658
|
-
&[data-motion="center"] {
|
|
659
|
-
&[data-state="closed"] {
|
|
660
|
-
animation: var(--animate-scale-out);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
.data-\\[motion\\=left\\]\\:data-\\[state\\=closed\\]\\:animate-slide-out-left {
|
|
665
|
-
&[data-motion="left"] {
|
|
666
|
-
&[data-state="closed"] {
|
|
667
|
-
animation: var(--animate-slide-out-left);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
.data-\\[motion\\=none\\]\\:data-\\[state\\=closed\\]\\:animate-fade-out {
|
|
672
|
-
&[data-motion="none"] {
|
|
673
|
-
&[data-state="closed"] {
|
|
674
|
-
animation: var(--animate-fade-out);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
.data-\\[motion\\=right\\]\\:data-\\[state\\=closed\\]\\:animate-slide-out-right {
|
|
679
|
-
&[data-motion="right"] {
|
|
680
|
-
&[data-state="closed"] {
|
|
681
|
-
animation: var(--animate-slide-out-right);
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
.data-\\[motion\\=top\\]\\:data-\\[state\\=closed\\]\\:animate-slide-out-top {
|
|
686
|
-
&[data-motion="top"] {
|
|
687
|
-
&[data-state="closed"] {
|
|
688
|
-
animation: var(--animate-slide-out-top);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
.data-\\[state\\=open\\]\\:backdrop\\:animate-fade-in {
|
|
693
|
-
&[data-state="open"] {
|
|
694
|
-
&::backdrop {
|
|
695
|
-
animation: var(--animate-fade-in);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
.data-\\[motion\\=bottom\\]\\:data-\\[state\\=open\\]\\:animate-slide-in-bottom {
|
|
700
|
-
&[data-motion="bottom"] {
|
|
701
|
-
&[data-state="open"] {
|
|
702
|
-
animation: var(--animate-slide-in-bottom);
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
.data-\\[motion\\=center\\]\\:data-\\[state\\=open\\]\\:animate-scale-in {
|
|
707
|
-
&[data-motion="center"] {
|
|
708
|
-
&[data-state="open"] {
|
|
709
|
-
animation: var(--animate-scale-in);
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
.data-\\[motion\\=left\\]\\:data-\\[state\\=open\\]\\:animate-slide-in-left {
|
|
714
|
-
&[data-motion="left"] {
|
|
715
|
-
&[data-state="open"] {
|
|
716
|
-
animation: var(--animate-slide-in-left);
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
.data-\\[motion\\=none\\]\\:data-\\[state\\=open\\]\\:animate-fade-in {
|
|
721
|
-
&[data-motion="none"] {
|
|
722
|
-
&[data-state="open"] {
|
|
723
|
-
animation: var(--animate-fade-in);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
.data-\\[motion\\=right\\]\\:data-\\[state\\=open\\]\\:animate-slide-in-right {
|
|
728
|
-
&[data-motion="right"] {
|
|
729
|
-
&[data-state="open"] {
|
|
730
|
-
animation: var(--animate-slide-in-right);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
.data-\\[motion\\=top\\]\\:data-\\[state\\=open\\]\\:animate-slide-in-top {
|
|
735
|
-
&[data-motion="top"] {
|
|
736
|
-
&[data-state="open"] {
|
|
737
|
-
animation: var(--animate-slide-in-top);
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
.motion-reduce\\:data-\\[motion\\]\\:data-\\[state\\=closed\\]\\:animate-fade-out {
|
|
742
|
-
@media (prefers-reduced-motion: reduce) {
|
|
743
|
-
&[data-motion] {
|
|
744
|
-
&[data-state="closed"] {
|
|
745
|
-
animation: var(--animate-fade-out);
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
.motion-reduce\\:data-\\[motion\\]\\:data-\\[state\\=open\\]\\:animate-fade-in {
|
|
751
|
-
@media (prefers-reduced-motion: reduce) {
|
|
752
|
-
&[data-motion] {
|
|
753
|
-
&[data-state="open"] {
|
|
754
|
-
animation: var(--animate-fade-in);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
619
|
}
|
|
760
620
|
@property --dsgn-border-sweep-angle {
|
|
761
621
|
syntax: '<angle>';
|
|
@@ -877,106 +737,6 @@ var styles2 = css2`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.co
|
|
|
877
737
|
inherits: false;
|
|
878
738
|
initial-value: solid;
|
|
879
739
|
}
|
|
880
|
-
@keyframes fade-in {
|
|
881
|
-
from {
|
|
882
|
-
opacity: 0;
|
|
883
|
-
}
|
|
884
|
-
to {
|
|
885
|
-
opacity: 1;
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
@keyframes fade-out {
|
|
889
|
-
from {
|
|
890
|
-
opacity: 1;
|
|
891
|
-
}
|
|
892
|
-
to {
|
|
893
|
-
opacity: 0;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
@keyframes scale-in {
|
|
897
|
-
from {
|
|
898
|
-
opacity: 0;
|
|
899
|
-
transform: scale(0.96);
|
|
900
|
-
}
|
|
901
|
-
to {
|
|
902
|
-
opacity: 1;
|
|
903
|
-
transform: none;
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
@keyframes scale-out {
|
|
907
|
-
from {
|
|
908
|
-
opacity: 1;
|
|
909
|
-
transform: none;
|
|
910
|
-
}
|
|
911
|
-
to {
|
|
912
|
-
opacity: 0;
|
|
913
|
-
transform: scale(0.96);
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
@keyframes slide-in-left {
|
|
917
|
-
from {
|
|
918
|
-
transform: translateX(-100%);
|
|
919
|
-
}
|
|
920
|
-
to {
|
|
921
|
-
transform: none;
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
@keyframes slide-out-left {
|
|
925
|
-
from {
|
|
926
|
-
transform: none;
|
|
927
|
-
}
|
|
928
|
-
to {
|
|
929
|
-
transform: translateX(-100%);
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
@keyframes slide-in-right {
|
|
933
|
-
from {
|
|
934
|
-
transform: translateX(100%);
|
|
935
|
-
}
|
|
936
|
-
to {
|
|
937
|
-
transform: none;
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
@keyframes slide-out-right {
|
|
941
|
-
from {
|
|
942
|
-
transform: none;
|
|
943
|
-
}
|
|
944
|
-
to {
|
|
945
|
-
transform: translateX(100%);
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
@keyframes slide-in-top {
|
|
949
|
-
from {
|
|
950
|
-
transform: translateY(-100%);
|
|
951
|
-
}
|
|
952
|
-
to {
|
|
953
|
-
transform: none;
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
@keyframes slide-out-top {
|
|
957
|
-
from {
|
|
958
|
-
transform: none;
|
|
959
|
-
}
|
|
960
|
-
to {
|
|
961
|
-
transform: translateY(-100%);
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
@keyframes slide-in-bottom {
|
|
965
|
-
from {
|
|
966
|
-
transform: translateY(100%);
|
|
967
|
-
}
|
|
968
|
-
to {
|
|
969
|
-
transform: none;
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
@keyframes slide-out-bottom {
|
|
973
|
-
from {
|
|
974
|
-
transform: none;
|
|
975
|
-
}
|
|
976
|
-
to {
|
|
977
|
-
transform: translateY(100%);
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
740
|
@layer properties {
|
|
981
741
|
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
|
982
742
|
*, ::before, ::after, ::backdrop {
|
|
@@ -1031,6 +791,14 @@ var modalMotionValues = {
|
|
|
1031
791
|
TOP: "top",
|
|
1032
792
|
BOTTOM: "bottom"
|
|
1033
793
|
};
|
|
794
|
+
var modalMotionPresets = {
|
|
795
|
+
center: "scaleIn",
|
|
796
|
+
left: "slideInLeft",
|
|
797
|
+
right: "slideInRight",
|
|
798
|
+
top: "slideInTop",
|
|
799
|
+
bottom: "slideInBottom",
|
|
800
|
+
none: "fade"
|
|
801
|
+
};
|
|
1034
802
|
var modalMotionProps = enumCreator(Object.values(modalMotionValues), "motion", String, { reflect: true });
|
|
1035
803
|
var modalSizeValues = {
|
|
1036
804
|
SM: "sm",
|
|
@@ -1077,7 +845,7 @@ var hostStyles = css3`
|
|
|
1077
845
|
display: contents;
|
|
1078
846
|
}
|
|
1079
847
|
`;
|
|
1080
|
-
var dialogClasses = () => clsx_default("box-border", "p-0", "border-0", "overflow-hidden", "flex-col", "open:flex", "text-text-primary", "bg-surface-elevated", "rounded-[var(--radius-surface)]", "shadow-[var(--shadow-card),0_0_18px_color-mix(in_oklab,var(--color-accent)_14.625%,transparent)]", "focus-visible:outline-2", "focus-visible:outline-focus", "focus-visible:outline-offset-2", "[--dsgn-modal-size:32rem]", "[--dsgn-modal-gutter:1rem]", "data-[size=sm]:[--dsgn-modal-size:24rem]", "data-[size=md]:[--dsgn-modal-size:32rem]", "data-[size=lg]:[--dsgn-modal-size:42rem]", "data-[size=xl]:[--dsgn-modal-size:56rem]", "data-[placement=center]:m-auto", "data-[placement=center]:w-[min(var(--dsgn-modal-size),calc(100vw-2*var(--dsgn-modal-gutter)))]", "data-[placement=center]:max-h-[calc(100dvh-2*var(--dsgn-modal-gutter))]", "data-[placement=left]:m-0", "data-[placement=left]:top-0", "data-[placement=left]:bottom-0", "data-[placement=left]:h-dvh", "data-[placement=left]:max-h-dvh", "data-[placement=left]:w-[min(var(--dsgn-modal-size),calc(100vw-var(--dsgn-modal-gutter)))]", "data-[placement=left]:left-0", "data-[placement=left]:right-auto", "data-[placement=left]:rounded-ss-none", "data-[placement=left]:rounded-es-none", "data-[placement=right]:m-0", "data-[placement=right]:top-0", "data-[placement=right]:bottom-0", "data-[placement=right]:h-dvh", "data-[placement=right]:max-h-dvh", "data-[placement=right]:w-[min(var(--dsgn-modal-size),calc(100vw-var(--dsgn-modal-gutter)))]", "data-[placement=right]:left-auto", "data-[placement=right]:right-0", "data-[placement=right]:rounded-se-none", "data-[placement=right]:rounded-ee-none", "data-[placement=top]:m-0", "data-[placement=top]:left-0", "data-[placement=top]:right-0", "data-[placement=top]:w-screen", "data-[placement=top]:max-w-screen", "data-[placement=top]:max-h-[min(var(--dsgn-modal-size),calc(100dvh-var(--dsgn-modal-gutter)))]", "data-[placement=top]:top-0", "data-[placement=top]:bottom-auto", "data-[placement=top]:rounded-ss-none", "data-[placement=top]:rounded-se-none", "data-[placement=bottom]:m-0", "data-[placement=bottom]:left-0", "data-[placement=bottom]:right-0", "data-[placement=bottom]:w-screen", "data-[placement=bottom]:max-w-screen", "data-[placement=bottom]:max-h-[min(var(--dsgn-modal-size),calc(100dvh-var(--dsgn-modal-gutter)))]", "data-[placement=bottom]:top-auto", "data-[placement=bottom]:bottom-0", "data-[placement=bottom]:rounded-es-none", "data-[placement=bottom]:rounded-ee-none", "data-[size=full]:inset-0", "data-[size=full]:m-0", "data-[size=full]:w-screen", "data-[size=full]:max-w-screen", "data-[size=full]:h-dvh", "data-[size=full]:max-h-dvh", "data-[size=full]:rounded-none", "backdrop:bg-[rgb(2_6_23/0.6)]", "backdrop:backdrop-blur-[12px]"
|
|
848
|
+
var dialogClasses = () => clsx_default("box-border", "p-0", "border-0", "overflow-hidden", "flex-col", "open:flex", "text-text-primary", "bg-surface-elevated", "rounded-[var(--radius-surface)]", "shadow-[var(--shadow-card),0_0_18px_color-mix(in_oklab,var(--color-accent)_14.625%,transparent)]", "focus-visible:outline-2", "focus-visible:outline-focus", "focus-visible:outline-offset-2", "[--dsgn-modal-size:32rem]", "[--dsgn-modal-gutter:1rem]", "data-[size=sm]:[--dsgn-modal-size:24rem]", "data-[size=md]:[--dsgn-modal-size:32rem]", "data-[size=lg]:[--dsgn-modal-size:42rem]", "data-[size=xl]:[--dsgn-modal-size:56rem]", "data-[placement=center]:m-auto", "data-[placement=center]:w-[min(var(--dsgn-modal-size),calc(100vw-2*var(--dsgn-modal-gutter)))]", "data-[placement=center]:max-h-[calc(100dvh-2*var(--dsgn-modal-gutter))]", "data-[placement=left]:m-0", "data-[placement=left]:top-0", "data-[placement=left]:bottom-0", "data-[placement=left]:h-dvh", "data-[placement=left]:max-h-dvh", "data-[placement=left]:w-[min(var(--dsgn-modal-size),calc(100vw-var(--dsgn-modal-gutter)))]", "data-[placement=left]:left-0", "data-[placement=left]:right-auto", "data-[placement=left]:rounded-ss-none", "data-[placement=left]:rounded-es-none", "data-[placement=right]:m-0", "data-[placement=right]:top-0", "data-[placement=right]:bottom-0", "data-[placement=right]:h-dvh", "data-[placement=right]:max-h-dvh", "data-[placement=right]:w-[min(var(--dsgn-modal-size),calc(100vw-var(--dsgn-modal-gutter)))]", "data-[placement=right]:left-auto", "data-[placement=right]:right-0", "data-[placement=right]:rounded-se-none", "data-[placement=right]:rounded-ee-none", "data-[placement=top]:m-0", "data-[placement=top]:left-0", "data-[placement=top]:right-0", "data-[placement=top]:w-screen", "data-[placement=top]:max-w-screen", "data-[placement=top]:max-h-[min(var(--dsgn-modal-size),calc(100dvh-var(--dsgn-modal-gutter)))]", "data-[placement=top]:top-0", "data-[placement=top]:bottom-auto", "data-[placement=top]:rounded-ss-none", "data-[placement=top]:rounded-se-none", "data-[placement=bottom]:m-0", "data-[placement=bottom]:left-0", "data-[placement=bottom]:right-0", "data-[placement=bottom]:w-screen", "data-[placement=bottom]:max-w-screen", "data-[placement=bottom]:max-h-[min(var(--dsgn-modal-size),calc(100dvh-var(--dsgn-modal-gutter)))]", "data-[placement=bottom]:top-auto", "data-[placement=bottom]:bottom-0", "data-[placement=bottom]:rounded-es-none", "data-[placement=bottom]:rounded-ee-none", "data-[size=full]:inset-0", "data-[size=full]:m-0", "data-[size=full]:w-screen", "data-[size=full]:max-w-screen", "data-[size=full]:h-dvh", "data-[size=full]:max-h-dvh", "data-[size=full]:rounded-none", "backdrop:bg-[rgb(2_6_23/0.6)]", "backdrop:backdrop-blur-[12px]");
|
|
1081
849
|
var panelClasses = () => clsx_default("flex", "flex-col", "flex-auto", "min-h-0", "font-sans");
|
|
1082
850
|
var headerClasses = (visible) => clsx_default("shrink-0", "items-start", "justify-between", "gap-4", "px-6", "pt-6", "pb-2", visible ? "flex" : "hidden");
|
|
1083
851
|
var headingClasses = () => clsx_default("min-w-0", "text-lg", "font-semibold", "text-text-primary");
|
|
@@ -1118,17 +886,6 @@ var unlockBodyScroll = () => {
|
|
|
1118
886
|
document.body.style.removeProperty("overflow");
|
|
1119
887
|
}
|
|
1120
888
|
};
|
|
1121
|
-
var whenAnimationsSettle = async (dialog) => {
|
|
1122
|
-
if (typeof dialog.getAnimations !== "function")
|
|
1123
|
-
return;
|
|
1124
|
-
const animations = dialog.getAnimations({ subtree: true }).filter((animation) => {
|
|
1125
|
-
const effect = animation.effect;
|
|
1126
|
-
return effect?.target === dialog;
|
|
1127
|
-
});
|
|
1128
|
-
if (animations.length === 0)
|
|
1129
|
-
return;
|
|
1130
|
-
await Promise.allSettled(animations.map((animation) => animation.finished));
|
|
1131
|
-
};
|
|
1132
889
|
var isInTopLayer = (dialog) => {
|
|
1133
890
|
try {
|
|
1134
891
|
return dialog.matches(":modal");
|
|
@@ -1150,7 +907,9 @@ class Modal extends Base {
|
|
|
1150
907
|
this.noCloseControl = false;
|
|
1151
908
|
this.noBackdropDismiss = false;
|
|
1152
909
|
this.noEscapeDismiss = false;
|
|
910
|
+
this._motion = new MotionController(this);
|
|
1153
911
|
this._closing = false;
|
|
912
|
+
this._closeRun = 0;
|
|
1154
913
|
this._hasHeading = false;
|
|
1155
914
|
this._hasDescription = false;
|
|
1156
915
|
this._hasFooter = false;
|
|
@@ -1191,11 +950,13 @@ class Modal extends Base {
|
|
|
1191
950
|
}
|
|
1192
951
|
connectedCallback() {
|
|
1193
952
|
super.connectedCallback();
|
|
1194
|
-
if (this.open) {
|
|
953
|
+
if (this.open || this._dialog?.open) {
|
|
1195
954
|
this.updateComplete.then(() => this._syncDialogState());
|
|
1196
955
|
}
|
|
1197
956
|
}
|
|
1198
957
|
disconnectedCallback() {
|
|
958
|
+
this._closeRun += 1;
|
|
959
|
+
this._closing = false;
|
|
1199
960
|
super.disconnectedCallback();
|
|
1200
961
|
this._releaseScrollLock();
|
|
1201
962
|
}
|
|
@@ -1208,11 +969,23 @@ class Modal extends Base {
|
|
|
1208
969
|
}
|
|
1209
970
|
_syncDialogState() {
|
|
1210
971
|
const dialog = this._dialog;
|
|
1211
|
-
if (!dialog)
|
|
972
|
+
if (!dialog || !this.isConnected)
|
|
1212
973
|
return;
|
|
1213
974
|
if (this.open) {
|
|
1214
|
-
|
|
975
|
+
this._closeReason = modalCloseReasonValues.API;
|
|
976
|
+
this._returnValue = "";
|
|
977
|
+
if (this._closing) {
|
|
978
|
+
this._closing = false;
|
|
979
|
+
this._closeRun += 1;
|
|
980
|
+
if (isInTopLayer(dialog)) {
|
|
981
|
+
this._animateDialog(dialog, true);
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
if (isInTopLayer(dialog)) {
|
|
986
|
+
this._acquireScrollLock();
|
|
1215
987
|
return;
|
|
988
|
+
}
|
|
1216
989
|
this._openDialog(dialog);
|
|
1217
990
|
} else if (dialog.open) {
|
|
1218
991
|
this._runCloseSequence(dialog);
|
|
@@ -1222,25 +995,38 @@ class Modal extends Base {
|
|
|
1222
995
|
if (dialog.open)
|
|
1223
996
|
dialog.close();
|
|
1224
997
|
this._closing = false;
|
|
1225
|
-
this._previouslyFocused
|
|
998
|
+
this._previouslyFocused ??= deepActiveElement();
|
|
1226
999
|
dialog.returnValue = "";
|
|
1227
1000
|
dialog.showModal();
|
|
1228
1001
|
this._acquireScrollLock();
|
|
1229
1002
|
this._focusInitialElement(dialog);
|
|
1003
|
+
this._animateDialog(dialog, true);
|
|
1230
1004
|
this.emit("dsgn-modal-open");
|
|
1231
1005
|
}
|
|
1232
1006
|
async _runCloseSequence(dialog) {
|
|
1233
1007
|
if (this._closing)
|
|
1234
1008
|
return;
|
|
1235
1009
|
this._closing = true;
|
|
1236
|
-
|
|
1237
|
-
await
|
|
1010
|
+
const run = ++this._closeRun;
|
|
1011
|
+
await this._animateDialog(dialog, false);
|
|
1012
|
+
if (run !== this._closeRun || !this.isConnected)
|
|
1013
|
+
return;
|
|
1238
1014
|
if (!dialog.open || this.open) {
|
|
1239
1015
|
this._closing = false;
|
|
1240
1016
|
return;
|
|
1241
1017
|
}
|
|
1242
1018
|
dialog.close(this._returnValue);
|
|
1243
1019
|
}
|
|
1020
|
+
_animateDialog(dialog, entering) {
|
|
1021
|
+
const preset = modalMotionPresets[this._motionOrigin];
|
|
1022
|
+
const play = entering ? this._motion.enter.bind(this._motion) : this._motion.exit.bind(this._motion);
|
|
1023
|
+
return Promise.all([
|
|
1024
|
+
play(dialog, preset),
|
|
1025
|
+
play(dialog, "fade", { pseudoElement: "::backdrop" })
|
|
1026
|
+
]).then(() => {
|
|
1027
|
+
return;
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1244
1030
|
_focusInitialElement(dialog) {
|
|
1245
1031
|
const target = this.querySelector("[autofocus]") ?? dialog.querySelector("[autofocus]") ?? dialog;
|
|
1246
1032
|
target.focus();
|
|
@@ -1266,7 +1052,10 @@ class Modal extends Base {
|
|
|
1266
1052
|
_handleNativeClose() {
|
|
1267
1053
|
if (this._dialog?.open)
|
|
1268
1054
|
return;
|
|
1055
|
+
this._closeRun += 1;
|
|
1269
1056
|
this._closing = false;
|
|
1057
|
+
if (this._dialog)
|
|
1058
|
+
cancel(this._dialog);
|
|
1270
1059
|
this.open = false;
|
|
1271
1060
|
this._releaseScrollLock();
|
|
1272
1061
|
this._restoreFocus();
|
|
@@ -1325,7 +1114,6 @@ class Modal extends Base {
|
|
|
1325
1114
|
data-placement=${this.placement}
|
|
1326
1115
|
data-motion=${this._motionOrigin}
|
|
1327
1116
|
data-size=${this.size}
|
|
1328
|
-
data-state=${this._closing ? "closed" : "open"}
|
|
1329
1117
|
aria-label=${!this._hasHeading && this.ariaLabel ? this.ariaLabel : nothing}
|
|
1330
1118
|
aria-labelledby=${this._hasHeading ? "modal-heading" : nothing}
|
|
1331
1119
|
aria-describedby=${this._hasDescription ? "modal-description" : nothing}
|
|
@@ -1412,9 +1200,6 @@ __legacyDecorateClassTS([
|
|
|
1412
1200
|
__legacyDecorateClassTS([
|
|
1413
1201
|
property({ type: Boolean, reflect: true, attribute: "no-escape-dismiss" })
|
|
1414
1202
|
], Modal.prototype, "noEscapeDismiss", undefined);
|
|
1415
|
-
__legacyDecorateClassTS([
|
|
1416
|
-
state()
|
|
1417
|
-
], Modal.prototype, "_closing", undefined);
|
|
1418
1203
|
__legacyDecorateClassTS([
|
|
1419
1204
|
state()
|
|
1420
1205
|
], Modal.prototype, "_hasHeading", undefined);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PresetName } from '@ds-gn/motion';
|
|
1
2
|
/**
|
|
2
3
|
* Where the dialog sits in the viewport. `center` is a classic modal; the four
|
|
3
4
|
* edges are sheets/drawers that span that edge.
|
|
@@ -28,6 +29,8 @@ export declare const modalMotionValues: {
|
|
|
28
29
|
readonly BOTTOM: "bottom";
|
|
29
30
|
};
|
|
30
31
|
export type ModalMotionType = (typeof modalMotionValues)[keyof typeof modalMotionValues];
|
|
32
|
+
/** Motion names select an enter/exit pair; placement remains independent. */
|
|
33
|
+
export declare const modalMotionPresets: Record<Exclude<ModalMotionType, 'inherit'>, PresetName>;
|
|
31
34
|
export declare const modalMotionProps: import("lit").PropertyDeclaration<unknown, unknown>;
|
|
32
35
|
/**
|
|
33
36
|
* Size along the axis the placement grows on: width for `center`/`left`/`right`,
|
|
@@ -39,6 +39,14 @@ var modalMotionValues = {
|
|
|
39
39
|
TOP: "top",
|
|
40
40
|
BOTTOM: "bottom"
|
|
41
41
|
};
|
|
42
|
+
var modalMotionPresets = {
|
|
43
|
+
center: "scaleIn",
|
|
44
|
+
left: "slideInLeft",
|
|
45
|
+
right: "slideInRight",
|
|
46
|
+
top: "slideInTop",
|
|
47
|
+
bottom: "slideInBottom",
|
|
48
|
+
none: "fade"
|
|
49
|
+
};
|
|
42
50
|
var modalMotionProps = enumCreator(Object.values(modalMotionValues), "motion", String, { reflect: true });
|
|
43
51
|
var modalSizeValues = {
|
|
44
52
|
SM: "sm",
|
|
@@ -56,6 +64,7 @@ var modalCloseReasonValues = {
|
|
|
56
64
|
};
|
|
57
65
|
export {
|
|
58
66
|
modalCloseReasonValues,
|
|
67
|
+
modalMotionPresets,
|
|
59
68
|
modalMotionProps,
|
|
60
69
|
modalMotionValues,
|
|
61
70
|
modalPlacementProps,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `:host` is the only rule with no utility equivalent — the host is the
|
|
3
3
|
* consumer's own `<dsgn-modal>` element, so there is no class we can put on it.
|
|
4
|
-
*
|
|
5
|
-
* the enter/exit motion, is expressed as Tailwind utilities in
|
|
4
|
+
* Layout and backdrop styling are expressed as Tailwind utilities in
|
|
6
5
|
* `dialogClasses()` below.
|
|
7
6
|
*/
|
|
8
7
|
export declare const hostStyles: import("lit").CSSResult;
|
|
@@ -10,14 +9,11 @@ export declare const hostStyles: import("lit").CSSResult;
|
|
|
10
9
|
* Every style the `<dialog>` needs, as one static utility list.
|
|
11
10
|
*
|
|
12
11
|
* Nothing here is conditional: the dialog carries `data-placement`,
|
|
13
|
-
* `data-size`,
|
|
12
|
+
* `data-size`, and the `data-[…]:` variants
|
|
14
13
|
* select which rules apply at runtime. That is also a requirement rather than a
|
|
15
14
|
* preference — Tailwind only generates classes it finds as *literal* strings in
|
|
16
15
|
* the source, so these cannot be composed or interpolated.
|
|
17
|
-
*
|
|
18
|
-
* Ordering note: `motion-reduce:` is emitted after the `data-motion` rules and
|
|
19
|
-
* matches their specificity, so it wins — the reduced-motion cross-fade
|
|
20
|
-
* overrides whichever spatial animation the placement selected.
|
|
16
|
+
* Motion is played by MotionController, independently of these styles.
|
|
21
17
|
*/
|
|
22
18
|
export declare const dialogClasses: () => string;
|
|
23
19
|
export declare const panelClasses: () => string;
|
|
@@ -489,6 +489,11 @@ dsgn-hero:not(:defined)[layout='asset-background']:not(:has(> [slot='features'])
|
|
|
489
489
|
padding-bottom: calc(var(--spacing) * 6);
|
|
490
490
|
grid-row: 3;
|
|
491
491
|
}
|
|
492
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
493
|
+
dsgn-hero:not(:defined)[motion='on'] > [slot='content'] [slot='eyebrow'] {
|
|
494
|
+
opacity: 0;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
492
497
|
@property --tw-tracking {
|
|
493
498
|
syntax: "*";
|
|
494
499
|
inherits: false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ds-gn/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "UI components for the DS-GN Design System",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -308,11 +308,11 @@
|
|
|
308
308
|
"generate:playground": "bun build/generate-playground-manifest.ts",
|
|
309
309
|
"check:playground-manifest": "bun build/generate-playground-manifest.ts --check",
|
|
310
310
|
"generate:react": "bun run generate:cem && bun run generate:playground && bun build/generate-react.ts",
|
|
311
|
-
"build": "bun run --cwd ../tokens build && bun build/build-all-components.ts",
|
|
311
|
+
"build": "bun run --cwd ../tokens build && bun run --cwd ../motion build && bun build/build-all-components.ts",
|
|
312
312
|
"build:css": "bun run --cwd ../tokens build && bun build/generate-component-css.ts",
|
|
313
313
|
"test": "bun run build && bun test --conditions=browser",
|
|
314
|
-
"build:dev": "bun run --cwd ../tokens build && cross-env NODE_ENV=development bun build/build-all-components.ts",
|
|
315
|
-
"build:prod": "bun run --cwd ../tokens build && cross-env NODE_ENV=production bun build/build-all-components.ts",
|
|
314
|
+
"build:dev": "bun run --cwd ../tokens build && bun run --cwd ../motion build && cross-env NODE_ENV=development bun build/build-all-components.ts",
|
|
315
|
+
"build:prod": "bun run --cwd ../tokens build && bun run --cwd ../motion build && cross-env NODE_ENV=production bun build/build-all-components.ts",
|
|
316
316
|
"watch": "cross-env NODE_ENV=development bun build/watch.ts",
|
|
317
317
|
"update:hash": "bun build/update-package-hash.ts"
|
|
318
318
|
},
|
|
@@ -346,7 +346,8 @@
|
|
|
346
346
|
"react-dom": "19.2.4"
|
|
347
347
|
},
|
|
348
348
|
"dependencies": {
|
|
349
|
-
"@ds-gn/
|
|
349
|
+
"@ds-gn/motion": "0.9.0",
|
|
350
|
+
"@ds-gn/tokens": "0.8.0",
|
|
350
351
|
"@lit-labs/observers": "^2.0.5",
|
|
351
352
|
"@lit/react": "^1.0.7",
|
|
352
353
|
"clsx": "^2.1.1"
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Whether the user has requested reduced motion via the OS/browser setting.
|
|
3
|
-
*
|
|
4
|
-
* Used as a gate for auto-animating controllers (e.g. AutoRotateController,
|
|
5
|
-
* WordCycleController) so motion respects `prefers-reduced-motion: reduce`.
|
|
6
|
-
* Guarded for environments without `matchMedia` (SSR, test DOMs), where it
|
|
7
|
-
* reports `false` (motion allowed) rather than throwing.
|
|
8
|
-
*/
|
|
9
|
-
export declare function prefersReducedMotion(): boolean;
|