@m3e/web 2.5.13 → 2.5.15
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/dist/all.js +410 -168
- package/dist/all.js.map +1 -1
- package/dist/all.min.js +64 -64
- package/dist/all.min.js.map +1 -1
- package/dist/avatar.js +1 -1
- package/dist/avatar.js.map +1 -1
- package/dist/avatar.min.js +1 -1
- package/dist/avatar.min.js.map +1 -1
- package/dist/badge.js +29 -8
- package/dist/badge.js.map +1 -1
- package/dist/badge.min.js +1 -1
- package/dist/badge.min.js.map +1 -1
- package/dist/bottom-sheet.js +1 -1
- package/dist/bottom-sheet.js.map +1 -1
- package/dist/bottom-sheet.min.js +1 -1
- package/dist/bottom-sheet.min.js.map +1 -1
- package/dist/calendar.js +1 -1
- package/dist/calendar.js.map +1 -1
- package/dist/calendar.min.js +1 -1
- package/dist/calendar.min.js.map +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.js.map +1 -1
- package/dist/checkbox.min.js +1 -1
- package/dist/checkbox.min.js.map +1 -1
- package/dist/core-anchoring.js +40 -10
- package/dist/core-anchoring.js.map +1 -1
- package/dist/core-anchoring.min.js +1 -1
- package/dist/core-anchoring.min.js.map +1 -1
- package/dist/core.js +56 -17
- package/dist/core.js.map +1 -1
- package/dist/core.min.js +1 -1
- package/dist/core.min.js.map +1 -1
- package/dist/css-custom-data.json +20 -0
- package/dist/custom-elements.json +290 -46
- package/dist/datepicker.js +23 -10
- package/dist/datepicker.js.map +1 -1
- package/dist/datepicker.min.js +1 -1
- package/dist/datepicker.min.js.map +1 -1
- package/dist/dialog.js +1 -1
- package/dist/dialog.js.map +1 -1
- package/dist/dialog.min.js +1 -1
- package/dist/dialog.min.js.map +1 -1
- package/dist/divider.js +1 -1
- package/dist/divider.js.map +1 -1
- package/dist/divider.min.js +1 -1
- package/dist/divider.min.js.map +1 -1
- package/dist/drawer-container.js +2 -2
- package/dist/drawer-container.js.map +1 -1
- package/dist/drawer-container.min.js +1 -1
- package/dist/drawer-container.min.js.map +1 -1
- package/dist/expansion-panel.js +6 -3
- package/dist/expansion-panel.js.map +1 -1
- package/dist/expansion-panel.min.js +1 -1
- package/dist/expansion-panel.min.js.map +1 -1
- package/dist/fab-menu.js +1 -1
- package/dist/fab-menu.js.map +1 -1
- package/dist/fab-menu.min.js +1 -1
- package/dist/fab-menu.min.js.map +1 -1
- package/dist/form-field.js +1 -1
- package/dist/form-field.js.map +1 -1
- package/dist/form-field.min.js +1 -1
- package/dist/form-field.min.js.map +1 -1
- package/dist/html-custom-data.json +3 -3
- package/dist/icon.js +7 -8
- package/dist/icon.js.map +1 -1
- package/dist/icon.min.js +1 -1
- package/dist/icon.min.js.map +1 -1
- package/dist/menu.js +20 -7
- package/dist/menu.js.map +1 -1
- package/dist/menu.min.js +1 -1
- package/dist/menu.min.js.map +1 -1
- package/dist/nav-bar.js +4 -2
- package/dist/nav-bar.js.map +1 -1
- package/dist/nav-bar.min.js +1 -1
- package/dist/nav-bar.min.js.map +1 -1
- package/dist/nav-menu.js +2 -2
- package/dist/nav-menu.js.map +1 -1
- package/dist/nav-menu.min.js +1 -1
- package/dist/nav-menu.min.js.map +1 -1
- package/dist/nav-rail.js +1 -1
- package/dist/nav-rail.js.map +1 -1
- package/dist/nav-rail.min.js +1 -1
- package/dist/nav-rail.min.js.map +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.js.map +1 -1
- package/dist/radio-group.min.js +1 -1
- package/dist/radio-group.min.js.map +1 -1
- package/dist/search.js +31 -11
- package/dist/search.js.map +1 -1
- package/dist/search.min.js +1 -1
- package/dist/search.min.js.map +1 -1
- package/dist/skeleton.js +106 -45
- package/dist/skeleton.js.map +1 -1
- package/dist/skeleton.min.js +1 -1
- package/dist/skeleton.min.js.map +1 -1
- package/dist/slide-group.js +1 -1
- package/dist/slide-group.js.map +1 -1
- package/dist/slide-group.min.js +1 -1
- package/dist/slide-group.min.js.map +1 -1
- package/dist/slider.js +3 -2
- package/dist/slider.js.map +1 -1
- package/dist/slider.min.js +1 -1
- package/dist/slider.min.js.map +1 -1
- package/dist/snackbar.js +1 -1
- package/dist/snackbar.js.map +1 -1
- package/dist/snackbar.min.js +1 -1
- package/dist/snackbar.min.js.map +1 -1
- package/dist/split-pane.js +1 -1
- package/dist/split-pane.js.map +1 -1
- package/dist/split-pane.min.js +1 -1
- package/dist/split-pane.min.js.map +1 -1
- package/dist/src/avatar/AvatarElement.d.ts.map +1 -1
- package/dist/src/badge/BadgeElement.d.ts +1 -0
- package/dist/src/badge/BadgeElement.d.ts.map +1 -1
- package/dist/src/bottom-sheet/BottomSheetElement.d.ts.map +1 -1
- package/dist/src/calendar/CalendarElement.d.ts.map +1 -1
- package/dist/src/checkbox/CheckboxElement.d.ts.map +1 -1
- package/dist/src/core/anchoring/FloatingPanelElement.d.ts.map +1 -1
- package/dist/src/core/anchoring/positionAnchor.d.ts.map +1 -1
- package/dist/src/core/shared/mixins/AttachInternals.d.ts.map +1 -1
- package/dist/src/core/shared/primitives/CollapsibleElement.d.ts +1 -1
- package/dist/src/core/shared/primitives/CollapsibleElement.d.ts.map +1 -1
- package/dist/src/core/shared/primitives/CollapsibleOrientation.d.ts +1 -1
- package/dist/src/core/shared/primitives/CollapsibleOrientation.d.ts.map +1 -1
- package/dist/src/core/shared/primitives/FocusRingElement.d.ts.map +1 -1
- package/dist/src/core/shared/primitives/PseudoCheckboxElement.d.ts.map +1 -1
- package/dist/src/core/shared/primitives/PseudoRadioElement.d.ts.map +1 -1
- package/dist/src/core/shared/primitives/RippleElement.d.ts.map +1 -1
- package/dist/src/core/shared/primitives/StateLayerElement.d.ts.map +1 -1
- package/dist/src/datepicker/DatepickerElement.d.ts.map +1 -1
- package/dist/src/dialog/DialogElement.d.ts.map +1 -1
- package/dist/src/divider/DividerElement.d.ts.map +1 -1
- package/dist/src/drawer-container/styles/DrawerContainerStyle.d.ts.map +1 -1
- package/dist/src/expansion-panel/ExpansionPanelElement.d.ts.map +1 -1
- package/dist/src/expansion-panel/styles/ExpansionHeaderStyle.d.ts.map +1 -1
- package/dist/src/expansion-panel/styles/ExpansionPanelStyle.d.ts.map +1 -1
- package/dist/src/fab-menu/FabMenuElement.d.ts.map +1 -1
- package/dist/src/form-field/FormFieldElement.d.ts.map +1 -1
- package/dist/src/menu/MenuElement.d.ts.map +1 -1
- package/dist/src/nav-bar/NavBarElement.d.ts +2 -0
- package/dist/src/nav-bar/NavBarElement.d.ts.map +1 -1
- package/dist/src/nav-bar/NavItemElement.d.ts.map +1 -1
- package/dist/src/nav-menu/NavMenuElement.d.ts.map +1 -1
- package/dist/src/nav-menu/NavMenuItemElement.d.ts.map +1 -1
- package/dist/src/nav-rail/NavRailElement.d.ts.map +1 -1
- package/dist/src/radio-group/RadioElement.d.ts.map +1 -1
- package/dist/src/search/SearchViewElement.d.ts.map +1 -1
- package/dist/src/search/styles/SearchBarStyle.d.ts.map +1 -1
- package/dist/src/search/styles/SearchViewStyle.d.ts.map +1 -1
- package/dist/src/skeleton/SkeletonElement.d.ts +17 -1
- package/dist/src/skeleton/SkeletonElement.d.ts.map +1 -1
- package/dist/src/slide-group/SlideGroupElement.d.ts.map +1 -1
- package/dist/src/slider/SliderElement.d.ts.map +1 -1
- package/dist/src/slider/SliderThumbElement.d.ts.map +1 -1
- package/dist/src/snackbar/SnackbarElement.d.ts.map +1 -1
- package/dist/src/split-pane/SplitPaneElement.d.ts.map +1 -1
- package/dist/src/stepper/StepElement.d.ts.map +1 -1
- package/dist/src/stepper/StepPanelElement.d.ts.map +1 -1
- package/dist/src/stepper/StepperElement.d.ts.map +1 -1
- package/dist/src/switch/styles/SwitchStyle.d.ts.map +1 -1
- package/dist/src/switch/styles/SwitchTrackStyle.d.ts.map +1 -1
- package/dist/src/tabs/TabElement.d.ts.map +1 -1
- package/dist/src/tabs/TabPanelElement.d.ts.map +1 -1
- package/dist/src/tabs/TabsElement.d.ts.map +1 -1
- package/dist/src/toc/TocElement.d.ts.map +1 -1
- package/dist/src/toc/TocItemElement.d.ts.map +1 -1
- package/dist/src/tooltip/RichTooltipElement.d.ts +2 -0
- package/dist/src/tooltip/RichTooltipElement.d.ts.map +1 -1
- package/dist/src/tooltip/TooltipElement.d.ts +4 -0
- package/dist/src/tooltip/TooltipElement.d.ts.map +1 -1
- package/dist/src/tree/TreeElement.d.ts.map +1 -1
- package/dist/src/tree/TreeItemElement.d.ts.map +1 -1
- package/dist/stepper.js +3 -3
- package/dist/stepper.js.map +1 -1
- package/dist/stepper.min.js +1 -1
- package/dist/stepper.min.js.map +1 -1
- package/dist/switch.js +2 -2
- package/dist/switch.js.map +1 -1
- package/dist/switch.min.js +1 -1
- package/dist/switch.min.js.map +1 -1
- package/dist/tabs.js +3 -3
- package/dist/tabs.js.map +1 -1
- package/dist/tabs.min.js +1 -1
- package/dist/tabs.min.js.map +1 -1
- package/dist/toc.js +2 -2
- package/dist/toc.js.map +1 -1
- package/dist/toc.min.js +1 -1
- package/dist/toc.min.js.map +1 -1
- package/dist/tooltip.js +58 -18
- package/dist/tooltip.js.map +1 -1
- package/dist/tooltip.min.js +1 -1
- package/dist/tooltip.min.js.map +1 -1
- package/dist/tree.js +2 -2
- package/dist/tree.js.map +1 -1
- package/dist/tree.min.js +1 -1
- package/dist/tree.min.js.map +1 -1
- package/package.json +1 -1
package/dist/skeleton.js
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
* Copyright (c) 2025–2026 matraic
|
|
4
4
|
* See LICENSE file in the project root for full license text.
|
|
5
5
|
*/
|
|
6
|
-
import { __classPrivateFieldGet, __decorate } from 'tslib';
|
|
6
|
+
import { __classPrivateFieldGet, __classPrivateFieldSet, __decorate } from 'tslib';
|
|
7
7
|
import { LitElement, html, css, unsafeCSS } from 'lit';
|
|
8
8
|
import { property } from 'lit/decorators.js';
|
|
9
9
|
import { ReconnectedCallback, waitForUpgrade, registerStyleSheet, DesignToken, customElement } from '@m3e/web/core';
|
|
10
10
|
import { positionAnchor } from '@m3e/web/core/anchoring';
|
|
11
11
|
|
|
12
|
-
var _M3eSkeletonElement_instances, _M3eSkeletonElement_anchoringCleanupMap, _M3eSkeletonElement_handleSlotChange, _M3eSkeletonElement_clearShapes, _M3eSkeletonElement_createShapes, _M3eSkeletonElement_createShape;
|
|
12
|
+
var _M3eSkeletonElement_instances, _M3eSkeletonElement_anchoringCleanupMap, _M3eSkeletonElement_animation, _M3eSkeletonElement_animationMode, _M3eSkeletonElement_handleSlotChange, _M3eSkeletonElement_clearShapes, _M3eSkeletonElement_createShapes, _M3eSkeletonElement_createShape, _M3eSkeletonElement_updateLoading, _M3eSkeletonElement_startMotion, _M3eSkeletonElement_stopMotion, _M3eSkeletonElement_syncMotionState;
|
|
13
|
+
var M3eSkeletonElement_1;
|
|
13
14
|
/**
|
|
14
15
|
* A visual placeholder that mimics the layout of content while it's still loading.
|
|
15
16
|
* @description
|
|
@@ -46,12 +47,16 @@ var _M3eSkeletonElement_instances, _M3eSkeletonElement_anchoringCleanupMap, _M3e
|
|
|
46
47
|
* @cssprop --m3e-skeleton-square-shape - Corner radius for the square skeleton shape.
|
|
47
48
|
* @cssprop --m3e-skeleton-shape - Corner radius for the skeleton shape.
|
|
48
49
|
*/
|
|
49
|
-
let M3eSkeletonElement = class M3eSkeletonElement extends ReconnectedCallback(LitElement) {
|
|
50
|
+
let M3eSkeletonElement = M3eSkeletonElement_1 = class M3eSkeletonElement extends ReconnectedCallback(LitElement) {
|
|
50
51
|
constructor() {
|
|
51
52
|
super(...arguments);
|
|
52
53
|
_M3eSkeletonElement_instances.add(this);
|
|
53
54
|
/** @private */
|
|
54
55
|
_M3eSkeletonElement_anchoringCleanupMap.set(this, new Map());
|
|
56
|
+
/** @private */
|
|
57
|
+
_M3eSkeletonElement_animation.set(this, null);
|
|
58
|
+
/** The animation mode `#animation` was created for, so mode changes recreate it. @private */
|
|
59
|
+
_M3eSkeletonElement_animationMode.set(this, null);
|
|
55
60
|
/**
|
|
56
61
|
* The shape of the skeleton.
|
|
57
62
|
* @default "auto"
|
|
@@ -72,18 +77,43 @@ let M3eSkeletonElement = class M3eSkeletonElement extends ReconnectedCallback(Li
|
|
|
72
77
|
disconnectedCallback() {
|
|
73
78
|
super.disconnectedCallback();
|
|
74
79
|
__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_clearShapes).call(this);
|
|
80
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_stopMotion).call(this);
|
|
75
81
|
}
|
|
76
82
|
/** @inheritdoc */
|
|
77
83
|
reconnectedCallback() {
|
|
78
84
|
super.reconnectedCallback();
|
|
79
85
|
__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_createShapes).call(this);
|
|
86
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_updateLoading).call(this);
|
|
87
|
+
}
|
|
88
|
+
/** @inheritdoc */
|
|
89
|
+
willUpdate(_changedProperties) {
|
|
90
|
+
super.willUpdate(_changedProperties);
|
|
91
|
+
if (_changedProperties.has("loaded") || _changedProperties.has("animation")) {
|
|
92
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_updateLoading).call(this);
|
|
93
|
+
}
|
|
80
94
|
}
|
|
81
95
|
/** @inheritdoc */
|
|
82
96
|
render() {
|
|
83
97
|
return html`<slot ?inert="${!this.loaded}" @slotchange="${__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_handleSlotChange)}"></slot>`;
|
|
84
98
|
}
|
|
99
|
+
/** Whether motion is currently suppressed for accessibility or forced-colors reasons. @private */
|
|
100
|
+
static __motionDisabled() {
|
|
101
|
+
return M3eSkeletonElement_1.__reducedMediaQuery.matches || M3eSkeletonElement_1.__forcedColorsMediaQuery.matches;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Re-applies the current motion preference to every animating skeleton. Invoked when
|
|
105
|
+
* the reduced-motion or forced-colors preference changes.
|
|
106
|
+
* @private
|
|
107
|
+
*/
|
|
108
|
+
static __updateMotion() {
|
|
109
|
+
for (const skeleton of M3eSkeletonElement_1.__animating) {
|
|
110
|
+
__classPrivateFieldGet(skeleton, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_syncMotionState).call(skeleton);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
85
113
|
};
|
|
86
114
|
_M3eSkeletonElement_anchoringCleanupMap = new WeakMap();
|
|
115
|
+
_M3eSkeletonElement_animation = new WeakMap();
|
|
116
|
+
_M3eSkeletonElement_animationMode = new WeakMap();
|
|
87
117
|
_M3eSkeletonElement_instances = new WeakSet();
|
|
88
118
|
_M3eSkeletonElement_handleSlotChange = /** @private */
|
|
89
119
|
async function _M3eSkeletonElement_handleSlotChange() {
|
|
@@ -135,52 +165,83 @@ async function _M3eSkeletonElement_createShape(element) {
|
|
|
135
165
|
__classPrivateFieldGet(this, _M3eSkeletonElement_anchoringCleanupMap, "f").set(shape, anchoringCleanup);
|
|
136
166
|
this.shadowRoot?.appendChild(shape);
|
|
137
167
|
};
|
|
168
|
+
_M3eSkeletonElement_updateLoading = function _M3eSkeletonElement_updateLoading() {
|
|
169
|
+
if (this.isConnected && !this.loaded && (this.animation === "wave" || this.animation === "pulse")) {
|
|
170
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_startMotion).call(this);
|
|
171
|
+
} else {
|
|
172
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_stopMotion).call(this);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
_M3eSkeletonElement_startMotion = function _M3eSkeletonElement_startMotion() {
|
|
176
|
+
if (__classPrivateFieldGet(this, _M3eSkeletonElement_animation, "f")) {
|
|
177
|
+
if (__classPrivateFieldGet(this, _M3eSkeletonElement_animationMode, "f") === this.animation) {
|
|
178
|
+
// Already running for the current mode; nothing to do but re-sync motion state.
|
|
179
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_syncMotionState).call(this);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
// Effect mode changed (wave <-> pulse); tear down and recreate below.
|
|
183
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_stopMotion).call(this);
|
|
184
|
+
}
|
|
185
|
+
M3eSkeletonElement_1.__motionOrigin ??= document.timeline.currentTime ?? 0;
|
|
186
|
+
const animation = this.animation === "pulse" ? this.animate([{
|
|
187
|
+
["--_m3e-skeleton-pulse-norm"]: 0
|
|
188
|
+
}, {
|
|
189
|
+
["--_m3e-skeleton-pulse-norm"]: 1
|
|
190
|
+
}, {
|
|
191
|
+
["--_m3e-skeleton-pulse-norm"]: 0
|
|
192
|
+
}], {
|
|
193
|
+
duration: 1200,
|
|
194
|
+
iterations: Infinity,
|
|
195
|
+
easing: "ease-in-out"
|
|
196
|
+
}) : this.animate([{
|
|
197
|
+
["--_m3e-skeleton-wave-pct"]: 0
|
|
198
|
+
}, {
|
|
199
|
+
["--_m3e-skeleton-wave-pct"]: 1
|
|
200
|
+
}], {
|
|
201
|
+
duration: 2100,
|
|
202
|
+
iterations: Infinity,
|
|
203
|
+
easing: "linear"
|
|
204
|
+
});
|
|
205
|
+
animation.startTime = M3eSkeletonElement_1.__motionOrigin;
|
|
206
|
+
__classPrivateFieldSet(this, _M3eSkeletonElement_animation, animation, "f");
|
|
207
|
+
__classPrivateFieldSet(this, _M3eSkeletonElement_animationMode, this.animation, "f");
|
|
208
|
+
M3eSkeletonElement_1.__animating.add(this);
|
|
209
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_instances, "m", _M3eSkeletonElement_syncMotionState).call(this);
|
|
210
|
+
};
|
|
211
|
+
_M3eSkeletonElement_stopMotion = function _M3eSkeletonElement_stopMotion() {
|
|
212
|
+
if (!__classPrivateFieldGet(this, _M3eSkeletonElement_animation, "f")) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_animation, "f").cancel();
|
|
216
|
+
__classPrivateFieldSet(this, _M3eSkeletonElement_animation, null, "f");
|
|
217
|
+
__classPrivateFieldSet(this, _M3eSkeletonElement_animationMode, null, "f");
|
|
218
|
+
M3eSkeletonElement_1.__animating.delete(this);
|
|
219
|
+
};
|
|
220
|
+
_M3eSkeletonElement_syncMotionState = function _M3eSkeletonElement_syncMotionState() {
|
|
221
|
+
if (!__classPrivateFieldGet(this, _M3eSkeletonElement_animation, "f")) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (M3eSkeletonElement_1.__motionDisabled()) {
|
|
225
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_animation, "f").pause();
|
|
226
|
+
} else {
|
|
227
|
+
__classPrivateFieldGet(this, _M3eSkeletonElement_animation, "f").play();
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
/** Skeletons with a live per-instance animation, so preference changes re-sync them all. @private */
|
|
231
|
+
M3eSkeletonElement.__animating = new Set();
|
|
232
|
+
/** Shared timeline origin so every skeleton's wave/pulse stays in phase. @private */
|
|
233
|
+
M3eSkeletonElement.__motionOrigin = null;
|
|
138
234
|
(() => {
|
|
139
|
-
if (window !== undefined) {
|
|
235
|
+
if (typeof window !== "undefined") {
|
|
140
236
|
registerStyleSheet(css`@property --_m3e-skeleton-wave-pct { syntax: "<number>"; inherits: true; initial-value: 0; } @property --_m3e-skeleton-pulse-norm { syntax: "<number>"; inherits: true; initial-value: 0; } :root { --_m3e-skeleton-wave-span: 40vw; --_m3e-skeleton-pulse-min: 0.06; }</number></number>`);
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
function startAnimations() {
|
|
146
|
-
waveAnimation = document.documentElement.animate([{
|
|
147
|
-
["--_m3e-skeleton-wave-pct"]: 0
|
|
148
|
-
}, {
|
|
149
|
-
["--_m3e-skeleton-wave-pct"]: 1
|
|
150
|
-
}], {
|
|
151
|
-
duration: 2100,
|
|
152
|
-
iterations: Infinity,
|
|
153
|
-
easing: "linear"
|
|
154
|
-
});
|
|
155
|
-
pulseAnimation = document.documentElement.animate([{
|
|
156
|
-
["--_m3e-skeleton-pulse-norm"]: 0
|
|
157
|
-
}, {
|
|
158
|
-
["--_m3e-skeleton-pulse-norm"]: 1
|
|
159
|
-
}, {
|
|
160
|
-
["--_m3e-skeleton-pulse-norm"]: 0
|
|
161
|
-
}], {
|
|
162
|
-
duration: 1200,
|
|
163
|
-
iterations: Infinity,
|
|
164
|
-
easing: "ease-in-out"
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
function applyMotionState() {
|
|
168
|
-
if (reducedMediaQuery.matches || forcedColorsMediaQuery.matches) {
|
|
169
|
-
waveAnimation?.pause();
|
|
170
|
-
pulseAnimation?.pause();
|
|
171
|
-
} else {
|
|
172
|
-
waveAnimation?.play();
|
|
173
|
-
pulseAnimation?.play();
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
startAnimations();
|
|
177
|
-
applyMotionState();
|
|
178
|
-
reducedMediaQuery.addEventListener("change", applyMotionState);
|
|
179
|
-
forcedColorsMediaQuery.addEventListener("change", applyMotionState);
|
|
237
|
+
M3eSkeletonElement_1.__reducedMediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
238
|
+
M3eSkeletonElement_1.__forcedColorsMediaQuery = window.matchMedia("(forced-colors: active)");
|
|
239
|
+
M3eSkeletonElement_1.__reducedMediaQuery.addEventListener("change", () => M3eSkeletonElement_1.__updateMotion());
|
|
240
|
+
M3eSkeletonElement_1.__forcedColorsMediaQuery.addEventListener("change", () => M3eSkeletonElement_1.__updateMotion());
|
|
180
241
|
}
|
|
181
242
|
})();
|
|
182
243
|
/** The styles of the element. */
|
|
183
|
-
M3eSkeletonElement.styles = css`:host { display: contents; } .shape { position: absolute; overflow: hidden; pointer-events: none; opacity: 1; background-color: var(--m3e-skeleton-color, ${DesignToken.color.surface}); } .shape::before { content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: color-mix( in srgb, var(--m3e-skeleton-tint-color, ${DesignToken.color.onSurface}) var(--m3e-skeleton-tint-opacity, 8%), transparent ); } :host(:not([loaded])) slot { visibility: hidden; } :host([loaded]) .shape { opacity: 0; transition: ${unsafeCSS(`opacity ${DesignToken.motion.duration.short3} ${DesignToken.motion.easing.standard}`)}; } :host([shape="rounded"]) .shape { border-radius: var(--m3e-skeleton-rounded-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.large})); } :host([shape="circular"]) .shape { border-radius: var(--m3e-skeleton-circular-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.full})); } :host([shape="square"]) .shape { border-radius: var(--m3e-skeleton-square-shape, var(--m3e-skeleton-shape, 0px)); } :host([animation="pulse"]:not([loaded])) .shape::after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: calc( var(--m3e-skeleton-accent-opacity, 0.06) + (1 - var(--m3e-skeleton-accent-opacity, 0.06)) * var(--_m3e-skeleton-pulse-norm) ); background-color: var(--m3e-skeleton-tint-color, ${DesignToken.color.surfaceDim}); } :host([animation="wave"]:not([loaded])) .shape::after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: linear-gradient( 90deg, transparent 0%, transparent 35%, var(--m3e-skeleton-accent-color, ${DesignToken.color.onSurface}) 50%, transparent 65%, transparent 100% ); background-attachment: fixed; background-size: calc(100vw + var(--_m3e-skeleton-wave-span) * 2) 100%; background-position-x: calc( var(--_m3e-skeleton-wave-pct) * (100vw + var(--_m3e-skeleton-wave-span) * 2) - var(--_m3e-skeleton-wave-span) ); opacity: var(--m3e-skeleton-accent-opacity, 0.06); } @media (forced-colors: active) { :host([loaded]) .shape { transition: none; } .shape::after { display: none; } .shape { background-color: GrayText; } } @media (prefers-reduced-motion) { :host([loaded]) .shape { transition: none; } .shape::after { display: none; } }`;
|
|
244
|
+
M3eSkeletonElement.styles = css`:host { display: contents; } .shape { position: absolute; overflow: hidden; pointer-events: none; opacity: 1; background-color: var(--m3e-skeleton-color, ${DesignToken.color.surface}); } .shape::before { content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: color-mix( in srgb, var(--m3e-skeleton-tint-color, ${DesignToken.color.onSurface}) var(--m3e-skeleton-tint-opacity, 8%), transparent ); } :host(:not([loaded])) { contain: layout style paint; } :host(:not([loaded])) slot { visibility: hidden; } :host([loaded]) .shape { opacity: 0; transition: ${unsafeCSS(`opacity ${DesignToken.motion.duration.short3} ${DesignToken.motion.easing.standard}`)}; } :host([shape="rounded"]) .shape { border-radius: var(--m3e-skeleton-rounded-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.large})); } :host([shape="circular"]) .shape { border-radius: var(--m3e-skeleton-circular-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.full})); } :host([shape="square"]) .shape { border-radius: var(--m3e-skeleton-square-shape, var(--m3e-skeleton-shape, 0px)); } :host([animation="pulse"]:not([loaded])) .shape::after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: calc( var(--m3e-skeleton-accent-opacity, 0.06) + (1 - var(--m3e-skeleton-accent-opacity, 0.06)) * var(--_m3e-skeleton-pulse-norm) ); background-color: var(--m3e-skeleton-tint-color, ${DesignToken.color.surfaceDim}); } :host([animation="wave"]:not([loaded])) .shape::after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: linear-gradient( 90deg, transparent 0%, transparent 35%, var(--m3e-skeleton-accent-color, ${DesignToken.color.onSurface}) 50%, transparent 65%, transparent 100% ); background-attachment: fixed; background-size: calc(100vw + var(--_m3e-skeleton-wave-span) * 2) 100%; background-position-x: calc( var(--_m3e-skeleton-wave-pct) * (100vw + var(--_m3e-skeleton-wave-span) * 2) - var(--_m3e-skeleton-wave-span) ); opacity: var(--m3e-skeleton-accent-opacity, 0.06); } @media (forced-colors: active) { :host([loaded]) .shape { transition: none; } .shape::after { display: none; } .shape { background-color: GrayText; } } @media (prefers-reduced-motion) { :host([loaded]) .shape { transition: none; } .shape::after { display: none; } }`;
|
|
184
245
|
__decorate([property({
|
|
185
246
|
reflect: true
|
|
186
247
|
})], M3eSkeletonElement.prototype, "shape", void 0);
|
|
@@ -191,7 +252,7 @@ __decorate([property({
|
|
|
191
252
|
type: Boolean,
|
|
192
253
|
reflect: true
|
|
193
254
|
})], M3eSkeletonElement.prototype, "loaded", void 0);
|
|
194
|
-
M3eSkeletonElement = __decorate([customElement("m3e-skeleton")], M3eSkeletonElement);
|
|
255
|
+
M3eSkeletonElement = M3eSkeletonElement_1 = __decorate([customElement("m3e-skeleton")], M3eSkeletonElement);
|
|
195
256
|
|
|
196
257
|
export { M3eSkeletonElement };
|
|
197
258
|
//# sourceMappingURL=skeleton.js.map
|
package/dist/skeleton.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skeleton.js","sources":["../../src/skeleton/SkeletonElement.ts"],"sourcesContent":["import { css, CSSResultGroup, html, LitElement, unsafeCSS } from \"lit\";\r\nimport { property } from \"lit/decorators.js\";\r\n\r\nimport { customElement, DesignToken, ReconnectedCallback, registerStyleSheet, waitForUpgrade } from \"@m3e/web/core\";\r\nimport { positionAnchor } from \"@m3e/web/core/anchoring\";\r\n\r\nimport { SkeletonShape } from \"./SkeletonShape\";\r\nimport { SkeletonAnimation } from \"./SkeletonAnimation\";\r\n\r\n/**\r\n * A visual placeholder that mimics the layout of content while it's still loading.\r\n * @description\r\n * The `m3e-skeleton` component provides a loading placeholder surface with flexible shape variants and\r\n * motion-based animations that communicate loading state while preserving layout stability. It mimics\r\n * the layout of content while it's still loading, ensuring a smooth user experience during data fetching\r\n * or rendering delays. The component supports different animation effects (`pulse`, `wave`, `none`) and\r\n * shape variants (`circular`, `rounded`, `square`, `auto`) to adapt to various content types. When the\r\n * content is loaded, the skeleton fades out with a smooth transition.\r\n *\r\n * @example\r\n * The following example illustrates a skeleton shaped and sized by the slotted `m3e-card`.\r\n * ```html\r\n * <m3e-skeleton>\r\n * <m3e-card></m3e-card>\r\n * </m3e-skeleton>\r\n * ```\r\n *\r\n * @tag m3e-skeleton\r\n *\r\n * @attr animation - The animation effect of the skeleton.\r\n * @attr shape - The shape of the skeleton.\r\n * @attr loaded - Whether the content of the skeleton has been loaded.\r\n *\r\n * @slot - Renders the content to be mimicked by the skeleton.\r\n *\r\n * @cssprop --m3e-skeleton-color - Base fill color for the skeleton surface.\r\n * @cssprop --m3e-skeleton-tint-color - Tint fill color for the skeleton surface.\r\n * @cssprop --m3e-skeleton-tint-opacity - Tint Opacity applied when the skeleton animation is not pulsating.\r\n * @cssprop --m3e-skeleton-accent-color - Accent color used in wave animation.\r\n * @cssprop --m3e-skeleton-accent-opacity - Opacity of the accent effect in animations.\r\n * @cssprop --m3e-skeleton-rounded-shape - Corner radius for the rounded skeleton shape.\r\n * @cssprop --m3e-skeleton-circular-shape - Corner radius for the circular skeleton shape.\r\n * @cssprop --m3e-skeleton-square-shape - Corner radius for the square skeleton shape.\r\n * @cssprop --m3e-skeleton-shape - Corner radius for the skeleton shape.\r\n */\r\n@customElement(\"m3e-skeleton\")\r\nexport class M3eSkeletonElement extends ReconnectedCallback(LitElement) {\r\n static {\r\n if (window !== undefined) {\r\n registerStyleSheet(css`\r\n @property --_m3e-skeleton-wave-pct {\r\n syntax: \"<number>\";\r\n inherits: true;\r\n initial-value: 0;\r\n }\r\n @property --_m3e-skeleton-pulse-norm {\r\n syntax: \"<number>\";\r\n inherits: true;\r\n initial-value: 0;\r\n }\r\n :root {\r\n --_m3e-skeleton-wave-span: 40vw;\r\n --_m3e-skeleton-pulse-min: 0.06;\r\n }\r\n `);\r\n\r\n const reducedMediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\r\n const forcedColorsMediaQuery = window.matchMedia(\"(forced-colors: active)\");\r\n\r\n let waveAnimation: Animation | null = null;\r\n let pulseAnimation: Animation | null = null;\r\n\r\n function startAnimations(): void {\r\n waveAnimation = document.documentElement.animate(\r\n [{ [\"--_m3e-skeleton-wave-pct\"]: 0 }, { [\"--_m3e-skeleton-wave-pct\"]: 1 }],\r\n {\r\n duration: 2100,\r\n iterations: Infinity,\r\n easing: \"linear\",\r\n },\r\n );\r\n\r\n pulseAnimation = document.documentElement.animate(\r\n [\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 0 },\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 1 },\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 0 },\r\n ],\r\n {\r\n duration: 1200,\r\n iterations: Infinity,\r\n easing: \"ease-in-out\",\r\n },\r\n );\r\n }\r\n\r\n function applyMotionState(): void {\r\n if (reducedMediaQuery.matches || forcedColorsMediaQuery.matches) {\r\n waveAnimation?.pause();\r\n pulseAnimation?.pause();\r\n } else {\r\n waveAnimation?.play();\r\n pulseAnimation?.play();\r\n }\r\n }\r\n\r\n startAnimations();\r\n applyMotionState();\r\n\r\n reducedMediaQuery.addEventListener(\"change\", applyMotionState);\r\n forcedColorsMediaQuery.addEventListener(\"change\", applyMotionState);\r\n }\r\n }\r\n\r\n /** The styles of the element. */\r\n static override styles: CSSResultGroup = css`\r\n :host {\r\n display: contents;\r\n }\r\n .shape {\r\n position: absolute;\r\n overflow: hidden;\r\n pointer-events: none;\r\n opacity: 1;\r\n background-color: var(--m3e-skeleton-color, ${DesignToken.color.surface});\r\n }\r\n .shape::before {\r\n content: \"\";\r\n position: absolute;\r\n left: 0;\r\n top: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-color: color-mix(\r\n in srgb,\r\n var(--m3e-skeleton-tint-color, ${DesignToken.color.onSurface}) var(--m3e-skeleton-tint-opacity, 8%),\r\n transparent\r\n );\r\n }\r\n :host(:not([loaded])) slot {\r\n visibility: hidden;\r\n }\r\n :host([loaded]) .shape {\r\n opacity: 0;\r\n transition: ${unsafeCSS(`opacity ${DesignToken.motion.duration.short3} ${DesignToken.motion.easing.standard}`)};\r\n }\r\n :host([shape=\"rounded\"]) .shape {\r\n border-radius: var(--m3e-skeleton-rounded-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.large}));\r\n }\r\n :host([shape=\"circular\"]) .shape {\r\n border-radius: var(--m3e-skeleton-circular-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.full}));\r\n }\r\n :host([shape=\"square\"]) .shape {\r\n border-radius: var(--m3e-skeleton-square-shape, var(--m3e-skeleton-shape, 0px));\r\n }\r\n :host([animation=\"pulse\"]:not([loaded])) .shape::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n opacity: calc(\r\n var(--m3e-skeleton-accent-opacity, 0.06) + (1 - var(--m3e-skeleton-accent-opacity, 0.06)) *\r\n var(--_m3e-skeleton-pulse-norm)\r\n );\r\n background-color: var(--m3e-skeleton-tint-color, ${DesignToken.color.surfaceDim});\r\n }\r\n :host([animation=\"wave\"]:not([loaded])) .shape::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-image: linear-gradient(\r\n 90deg,\r\n transparent 0%,\r\n transparent 35%,\r\n var(--m3e-skeleton-accent-color, ${DesignToken.color.onSurface}) 50%,\r\n transparent 65%,\r\n transparent 100%\r\n );\r\n background-attachment: fixed;\r\n background-size: calc(100vw + var(--_m3e-skeleton-wave-span) * 2) 100%;\r\n background-position-x: calc(\r\n var(--_m3e-skeleton-wave-pct) * (100vw + var(--_m3e-skeleton-wave-span) * 2) - var(--_m3e-skeleton-wave-span)\r\n );\r\n\r\n opacity: var(--m3e-skeleton-accent-opacity, 0.06);\r\n }\r\n @media (forced-colors: active) {\r\n :host([loaded]) .shape {\r\n transition: none;\r\n }\r\n .shape::after {\r\n display: none;\r\n }\r\n .shape {\r\n background-color: GrayText;\r\n }\r\n }\r\n @media (prefers-reduced-motion) {\r\n :host([loaded]) .shape {\r\n transition: none;\r\n }\r\n .shape::after {\r\n display: none;\r\n }\r\n }\r\n `;\r\n\r\n /** @private */ readonly #anchoringCleanupMap = new Map<HTMLElement, () => void>();\r\n\r\n /**\r\n * The shape of the skeleton.\r\n * @default \"auto\"\r\n */\r\n @property({ reflect: true }) shape: SkeletonShape = \"auto\";\r\n\r\n /**\r\n * The animation effect of the skeleton.\r\n * @default \"wave\"\r\n */\r\n @property({ reflect: true }) animation: SkeletonAnimation = \"wave\";\r\n\r\n /**\r\n * Whether the content of the skeleton has been loaded.\r\n * @default false\r\n */\r\n @property({ type: Boolean, reflect: true }) loaded = false;\r\n\r\n /** @inheritdoc */\r\n override disconnectedCallback(): void {\r\n super.disconnectedCallback();\r\n this.#clearShapes();\r\n }\r\n\r\n /** @inheritdoc */\r\n override reconnectedCallback(): void {\r\n super.reconnectedCallback();\r\n this.#createShapes();\r\n }\r\n\r\n /** @inheritdoc */\r\n protected override render(): unknown {\r\n return html`<slot ?inert=\"${!this.loaded}\" @slotchange=\"${this.#handleSlotChange}\"></slot>`;\r\n }\r\n\r\n /** @private */\r\n async #handleSlotChange(): Promise<void> {\r\n this.#createShapes();\r\n }\r\n\r\n /** @private */\r\n #clearShapes(): void {\r\n for (const item of this.#anchoringCleanupMap) {\r\n item[0].remove();\r\n item[1]();\r\n }\r\n this.#anchoringCleanupMap.clear();\r\n }\r\n\r\n /** @private */\r\n async #createShapes(): Promise<void> {\r\n this.#clearShapes();\r\n\r\n const slot = this.shadowRoot?.querySelector(\"slot\");\r\n if (!slot) return;\r\n\r\n for (const element of slot.assignedElements({ flatten: true }).filter((x) => x instanceof HTMLElement)) {\r\n await this.#createShape(element);\r\n }\r\n }\r\n\r\n /** @private */\r\n async #createShape(element: HTMLElement): Promise<void> {\r\n await waitForUpgrade(element);\r\n\r\n const shape = document.createElement(\"div\");\r\n shape.classList.add(\"shape\");\r\n\r\n if (this.shape === \"auto\") {\r\n let borderRadius = getComputedStyle(element).borderRadius;\r\n if (!borderRadius || borderRadius === \"0px\") {\r\n const firstElement = element.shadowRoot?.firstElementChild;\r\n if (firstElement && !firstElement.nextElementSibling) {\r\n borderRadius = getComputedStyle(firstElement).borderRadius;\r\n }\r\n }\r\n\r\n if (borderRadius && borderRadius !== \"0px\") {\r\n shape.style.borderRadius = borderRadius;\r\n }\r\n }\r\n\r\n const anchoringCleanup = await positionAnchor(\r\n shape,\r\n element,\r\n {\r\n position: \"bottom\",\r\n },\r\n (x, y) => {\r\n shape.style.left = `${x}px`;\r\n shape.style.top = `${y - element.clientHeight}px`;\r\n shape.style.width = `${element.clientWidth}px`;\r\n shape.style.height = `${element.clientHeight}px`;\r\n },\r\n );\r\n\r\n this.#anchoringCleanupMap.set(shape, anchoringCleanup);\r\n this.shadowRoot?.appendChild(shape);\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n \"m3e-skeleton\": M3eSkeletonElement;\r\n }\r\n}\r\n"],"names":["M3eSkeletonElement","ReconnectedCallback","LitElement","constructor","_M3eSkeletonElement_anchoringCleanupMap","set","Map","shape","animation","loaded","disconnectedCallback","__classPrivateFieldGet","_M3eSkeletonElement_instances","_M3eSkeletonElement_clearShapes","call","reconnectedCallback","_M3eSkeletonElement_createShapes","render","html","_M3eSkeletonElement_handleSlotChange","item","remove","clear","slot","shadowRoot","querySelector","element","assignedElements","flatten","filter","x","HTMLElement","_M3eSkeletonElement_createShape","waitForUpgrade","document","createElement","classList","add","borderRadius","getComputedStyle","firstElement","firstElementChild","nextElementSibling","style","anchoringCleanup","positionAnchor","position","y","left","top","clientHeight","width","clientWidth","height","appendChild","window","undefined","registerStyleSheet","css","reducedMediaQuery","matchMedia","forcedColorsMediaQuery","waveAnimation","pulseAnimation","startAnimations","documentElement","animate","duration","iterations","Infinity","easing","applyMotionState","matches","pause","play","addEventListener","styles","DesignToken","color","surface","onSurface","unsafeCSS","motion","short3","standard","corner","large","full","surfaceDim","__decorate","property","reflect","prototype","type","Boolean","customElement"],"mappings":";;;;;;;;;;;;AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCG;AAEI,IAAMA,kBAAkB,GAAxB,MAAMA,kBAAmB,SAAQC,mBAAmB,CAACC,UAAU,CAAC,CAAA;AAAhEC,EAAAA,WAAAA,GAAA;;;AAsKL;IAAyBC,uCAAA,CAAAC,GAAA,CAAA,IAAA,EAAuB,IAAIC,GAAG,EAA2B,CAAA;AAElF;;;AAGG;IAC0B,IAAA,CAAAC,KAAK,GAAkB,MAAM;AAE1D;;;AAGG;IAC0B,IAAA,CAAAC,SAAS,GAAsB,MAAM;AAElE;;;AAGG;IACyC,IAAA,CAAAC,MAAM,GAAG,KAAK;AAmF5D,EAAA;AAjFE;AACSC,EAAAA,oBAAoBA,GAAA;IAC3B,KAAK,CAACA,oBAAoB,EAAE;AAC5BC,IAAAA,sBAAA,CAAA,IAAI,EAAAC,6BAAA,EAAA,GAAA,EAAAC,+BAAA,CAAa,CAAAC,IAAA,CAAjB,IAAI,CAAe;AACrB,EAAA;AAEA;AACSC,EAAAA,mBAAmBA,GAAA;IAC1B,KAAK,CAACA,mBAAmB,EAAE;AAC3BJ,IAAAA,sBAAA,CAAA,IAAI,EAAAC,6BAAA,EAAA,GAAA,EAAAI,gCAAA,CAAc,CAAAF,IAAA,CAAlB,IAAI,CAAgB;AACtB,EAAA;AAEA;AACmBG,EAAAA,MAAMA,GAAA;AACvB,IAAA,OAAOC,IAAI,CAAA,cAAA,EAAiB,CAAC,IAAI,CAACT,MAAM,CAAA,eAAA,EAAkBE,sBAAA,CAAA,IAAI,EAAAC,6BAAA,EAAA,GAAA,EAAAO,oCAAA,CAAkB,CAAA,SAAA,CAAW;AAC7F,EAAA;;;;;AAGA,eAAKA,oCAAAA,GAAA;AACHR,EAAAA,sBAAA,CAAA,IAAI,EAAAC,6BAAA,EAAA,GAAA,EAAAI,gCAAA,CAAc,CAAAF,IAAA,CAAlB,IAAI,CAAgB;AACtB,CAAC;;EAIC,KAAK,MAAMM,IAAI,IAAIT,uBAAA,IAAI,EAAAP,uCAAA,EAAA,GAAA,CAAqB,EAAE;AAC5CgB,IAAAA,IAAI,CAAC,CAAC,CAAC,CAACC,MAAM,EAAE;AAChBD,IAAAA,IAAI,CAAC,CAAC,CAAC,EAAE;AACX,EAAA;EACAT,sBAAA,CAAA,IAAI,EAAAP,uCAAA,EAAA,GAAA,CAAqB,CAACkB,KAAK,EAAE;AACnC,CAAC;;AAGD,eAAKN,gCAAAA,GAAA;AACHL,EAAAA,sBAAA,CAAA,IAAI,EAAAC,6BAAA,EAAA,GAAA,EAAAC,+BAAA,CAAa,CAAAC,IAAA,CAAjB,IAAI,CAAe;EAEnB,MAAMS,IAAI,GAAG,IAAI,CAACC,UAAU,EAAEC,aAAa,CAAC,MAAM,CAAC;EACnD,IAAI,CAACF,IAAI,EAAE;AAEX,EAAA,KAAK,MAAMG,OAAO,IAAIH,IAAI,CAACI,gBAAgB,CAAC;AAAEC,IAAAA,OAAO,EAAE;GAAM,CAAC,CAACC,MAAM,CAAEC,CAAC,IAAKA,CAAC,YAAYC,WAAW,CAAC,EAAE;AACtG,IAAA,MAAMpB,sBAAA,CAAA,IAAI,EAAAC,6BAAA,EAAA,GAAA,EAAAoB,+BAAA,CAAa,CAAAlB,IAAA,CAAjB,IAAI,EAAcY,OAAO,CAAC;AAClC,EAAA;AACF,CAAC;;AAGD,+CAAmBA,OAAoB,EAAA;EACrC,MAAMO,cAAc,CAACP,OAAO,CAAC;AAE7B,EAAA,MAAMnB,KAAK,GAAG2B,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;AAC3C5B,EAAAA,KAAK,CAAC6B,SAAS,CAACC,GAAG,CAAC,OAAO,CAAC;AAE5B,EAAA,IAAI,IAAI,CAAC9B,KAAK,KAAK,MAAM,EAAE;AACzB,IAAA,IAAI+B,YAAY,GAAGC,gBAAgB,CAACb,OAAO,CAAC,CAACY,YAAY;AACzD,IAAA,IAAI,CAACA,YAAY,IAAIA,YAAY,KAAK,KAAK,EAAE;AAC3C,MAAA,MAAME,YAAY,GAAGd,OAAO,CAACF,UAAU,EAAEiB,iBAAiB;AAC1D,MAAA,IAAID,YAAY,IAAI,CAACA,YAAY,CAACE,kBAAkB,EAAE;AACpDJ,QAAAA,YAAY,GAAGC,gBAAgB,CAACC,YAAY,CAAC,CAACF,YAAY;AAC5D,MAAA;AACF,IAAA;AAEA,IAAA,IAAIA,YAAY,IAAIA,YAAY,KAAK,KAAK,EAAE;AAC1C/B,MAAAA,KAAK,CAACoC,KAAK,CAACL,YAAY,GAAGA,YAAY;AACzC,IAAA;AACF,EAAA;EAEA,MAAMM,gBAAgB,GAAG,MAAMC,cAAc,CAC3CtC,KAAK,EACLmB,OAAO,EACP;AACEoB,IAAAA,QAAQ,EAAE;AACX,GAAA,EACD,CAAChB,CAAC,EAAEiB,CAAC,KAAI;AACPxC,IAAAA,KAAK,CAACoC,KAAK,CAACK,IAAI,GAAG,CAAA,EAAGlB,CAAC,CAAA,EAAA,CAAI;IAC3BvB,KAAK,CAACoC,KAAK,CAACM,GAAG,GAAG,CAAA,EAAGF,CAAC,GAAGrB,OAAO,CAACwB,YAAY,CAAA,EAAA,CAAI;IACjD3C,KAAK,CAACoC,KAAK,CAACQ,KAAK,GAAG,CAAA,EAAGzB,OAAO,CAAC0B,WAAW,CAAA,EAAA,CAAI;IAC9C7C,KAAK,CAACoC,KAAK,CAACU,MAAM,GAAG,CAAA,EAAG3B,OAAO,CAACwB,YAAY,CAAA,EAAA,CAAI;AAClD,EAAA,CAAC,CACF;AAEDvC,EAAAA,sBAAA,CAAA,IAAI,+CAAqB,CAACN,GAAG,CAACE,KAAK,EAAEqC,gBAAgB,CAAC;AACtD,EAAA,IAAI,CAACpB,UAAU,EAAE8B,WAAW,CAAC/C,KAAK,CAAC;AACrC,CAAC;AAzQD,CAAA,MAAA;EACE,IAAIgD,MAAM,KAAKC,SAAS,EAAE;IACxBC,kBAAkB,CAACC,GAAG,CAAA,yRAAA,CAerB,CAAC;AAEF,IAAA,MAAMC,iBAAiB,GAAGJ,MAAM,CAACK,UAAU,CAAC,kCAAkC,CAAC;AAC/E,IAAA,MAAMC,sBAAsB,GAAGN,MAAM,CAACK,UAAU,CAAC,yBAAyB,CAAC;IAE3E,IAAIE,aAAa,GAAqB,IAAI;IAC1C,IAAIC,cAAc,GAAqB,IAAI;IAE3C,SAASC,eAAeA,GAAA;AACtBF,MAAAA,aAAa,GAAG5B,QAAQ,CAAC+B,eAAe,CAACC,OAAO,CAC9C,CAAC;AAAE,QAAA,CAAC,0BAA0B,GAAG;AAAC,OAAE,EAAE;AAAE,QAAA,CAAC,0BAA0B,GAAG;AAAC,OAAE,CAAC,EAC1E;AACEC,QAAAA,QAAQ,EAAE,IAAI;AACdC,QAAAA,UAAU,EAAEC,QAAQ;AACpBC,QAAAA,MAAM,EAAE;AACT,OAAA,CACF;AAEDP,MAAAA,cAAc,GAAG7B,QAAQ,CAAC+B,eAAe,CAACC,OAAO,CAC/C,CACE;AAAE,QAAA,CAAC,4BAA4B,GAAG;AAAC,OAAE,EACrC;AAAE,QAAA,CAAC,4BAA4B,GAAG;AAAC,OAAE,EACrC;AAAE,QAAA,CAAC,4BAA4B,GAAG;AAAC,OAAE,CACtC,EACD;AACEC,QAAAA,QAAQ,EAAE,IAAI;AACdC,QAAAA,UAAU,EAAEC,QAAQ;AACpBC,QAAAA,MAAM,EAAE;AACT,OAAA,CACF;AACH,IAAA;IAEA,SAASC,gBAAgBA,GAAA;AACvB,MAAA,IAAIZ,iBAAiB,CAACa,OAAO,IAAIX,sBAAsB,CAACW,OAAO,EAAE;QAC/DV,aAAa,EAAEW,KAAK,EAAE;QACtBV,cAAc,EAAEU,KAAK,EAAE;AACzB,MAAA,CAAC,MAAM;QACLX,aAAa,EAAEY,IAAI,EAAE;QACrBX,cAAc,EAAEW,IAAI,EAAE;AACxB,MAAA;AACF,IAAA;AAEAV,IAAAA,eAAe,EAAE;AACjBO,IAAAA,gBAAgB,EAAE;AAElBZ,IAAAA,iBAAiB,CAACgB,gBAAgB,CAAC,QAAQ,EAAEJ,gBAAgB,CAAC;AAC9DV,IAAAA,sBAAsB,CAACc,gBAAgB,CAAC,QAAQ,EAAEJ,gBAAgB,CAAC;AACrE,EAAA;AACF,CAAC,GAAA;AAED;AACgBvE,kBAAA,CAAA4E,MAAM,GAAmBlB,GAAG,CAAA,0JAAA,EASMmB,WAAW,CAACC,KAAK,CAACC,OAAO,CAAA,wKAAA,EAWpCF,WAAW,CAACC,KAAK,CAACE,SAAS,CAAA,6JAAA,EAShDC,SAAS,CAAC,CAAA,QAAA,EAAWJ,WAAW,CAACK,MAAM,CAACf,QAAQ,CAACgB,MAAM,CAAA,CAAA,EAAIN,WAAW,CAACK,MAAM,CAACZ,MAAM,CAACc,QAAQ,CAAA,CAAE,CAAC,CAAA,iHAAA,EAGjCP,WAAW,CAACtE,KAAK,CAAC8E,MAAM,CAACC,KAAK,CAAA,qHAAA,EAG7BT,WAAW,CAACtE,KAAK,CAAC8E,MAAM,CAACE,IAAI,CAAA,+bAAA,EAgBxDV,WAAW,CAACC,KAAK,CAACU,UAAU,CAAA,sPAAA,EAa1CX,WAAW,CAACC,KAAK,CAACE,SAAS,CAAA,8lBAAA,CAhE9C;AAuGOS,UAAA,CAAA,CAA5BC,QAAQ,CAAC;AAAEC,EAAAA,OAAO,EAAE;CAAM,CAAC,CAA+B,EAAA3F,kBAAA,CAAA4F,SAAA,EAAA,OAAA,EAAA,MAAA,CAAA;AAM9BH,UAAA,CAAA,CAA5BC,QAAQ,CAAC;AAAEC,EAAAA,OAAO,EAAE;CAAM,CAAC,CAAuC,EAAA3F,kBAAA,CAAA4F,SAAA,EAAA,WAAA,EAAA,MAAA,CAAA;AAMvBH,UAAA,CAAA,CAA3CC,QAAQ,CAAC;AAAEG,EAAAA,IAAI,EAAEC,OAAO;AAAEH,EAAAA,OAAO,EAAE;AAAI,CAAE,CAAC,CAAgB,EAAA3F,kBAAA,CAAA4F,SAAA,EAAA,QAAA,EAAA,MAAA,CAAA;AAxLhD5F,kBAAkB,GAAAyF,UAAA,CAAA,CAD9BM,aAAa,CAAC,cAAc,CAAC,CACjB,EAAA/F,kBAAkB,CA2Q9B;;;;"}
|
|
1
|
+
{"version":3,"file":"skeleton.js","sources":["../../src/skeleton/SkeletonElement.ts"],"sourcesContent":["import { css, CSSResultGroup, html, LitElement, PropertyValues, unsafeCSS } from \"lit\";\r\nimport { property } from \"lit/decorators.js\";\r\n\r\nimport { customElement, DesignToken, ReconnectedCallback, registerStyleSheet, waitForUpgrade } from \"@m3e/web/core\";\r\nimport { positionAnchor } from \"@m3e/web/core/anchoring\";\r\n\r\nimport { SkeletonShape } from \"./SkeletonShape\";\r\nimport { SkeletonAnimation } from \"./SkeletonAnimation\";\r\n\r\n/**\r\n * A visual placeholder that mimics the layout of content while it's still loading.\r\n * @description\r\n * The `m3e-skeleton` component provides a loading placeholder surface with flexible shape variants and\r\n * motion-based animations that communicate loading state while preserving layout stability. It mimics\r\n * the layout of content while it's still loading, ensuring a smooth user experience during data fetching\r\n * or rendering delays. The component supports different animation effects (`pulse`, `wave`, `none`) and\r\n * shape variants (`circular`, `rounded`, `square`, `auto`) to adapt to various content types. When the\r\n * content is loaded, the skeleton fades out with a smooth transition.\r\n *\r\n * @example\r\n * The following example illustrates a skeleton shaped and sized by the slotted `m3e-card`.\r\n * ```html\r\n * <m3e-skeleton>\r\n * <m3e-card></m3e-card>\r\n * </m3e-skeleton>\r\n * ```\r\n *\r\n * @tag m3e-skeleton\r\n *\r\n * @attr animation - The animation effect of the skeleton.\r\n * @attr shape - The shape of the skeleton.\r\n * @attr loaded - Whether the content of the skeleton has been loaded.\r\n *\r\n * @slot - Renders the content to be mimicked by the skeleton.\r\n *\r\n * @cssprop --m3e-skeleton-color - Base fill color for the skeleton surface.\r\n * @cssprop --m3e-skeleton-tint-color - Tint fill color for the skeleton surface.\r\n * @cssprop --m3e-skeleton-tint-opacity - Tint Opacity applied when the skeleton animation is not pulsating.\r\n * @cssprop --m3e-skeleton-accent-color - Accent color used in wave animation.\r\n * @cssprop --m3e-skeleton-accent-opacity - Opacity of the accent effect in animations.\r\n * @cssprop --m3e-skeleton-rounded-shape - Corner radius for the rounded skeleton shape.\r\n * @cssprop --m3e-skeleton-circular-shape - Corner radius for the circular skeleton shape.\r\n * @cssprop --m3e-skeleton-square-shape - Corner radius for the square skeleton shape.\r\n * @cssprop --m3e-skeleton-shape - Corner radius for the skeleton shape.\r\n */\r\n@customElement(\"m3e-skeleton\")\r\nexport class M3eSkeletonElement extends ReconnectedCallback(LitElement) {\r\n /** Skeletons with a live per-instance animation, so preference changes re-sync them all. @private */\r\n private static __animating = new Set<M3eSkeletonElement>();\r\n\r\n /** Shared timeline origin so every skeleton's wave/pulse stays in phase. @private */\r\n private static __motionOrigin: number | null = null;\r\n\r\n /** @private */ private static __reducedMediaQuery: MediaQueryList;\r\n /** @private */ private static __forcedColorsMediaQuery: MediaQueryList;\r\n\r\n static {\r\n if (typeof window !== \"undefined\") {\r\n registerStyleSheet(css`\r\n @property --_m3e-skeleton-wave-pct {\r\n syntax: \"<number>\";\r\n inherits: true;\r\n initial-value: 0;\r\n }\r\n @property --_m3e-skeleton-pulse-norm {\r\n syntax: \"<number>\";\r\n inherits: true;\r\n initial-value: 0;\r\n }\r\n :root {\r\n --_m3e-skeleton-wave-span: 40vw;\r\n --_m3e-skeleton-pulse-min: 0.06;\r\n }\r\n `);\r\n\r\n M3eSkeletonElement.__reducedMediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\r\n M3eSkeletonElement.__forcedColorsMediaQuery = window.matchMedia(\"(forced-colors: active)\");\r\n M3eSkeletonElement.__reducedMediaQuery.addEventListener(\"change\", () => M3eSkeletonElement.__updateMotion());\r\n M3eSkeletonElement.__forcedColorsMediaQuery.addEventListener(\"change\", () => M3eSkeletonElement.__updateMotion());\r\n }\r\n }\r\n\r\n /** The styles of the element. */\r\n static override styles: CSSResultGroup = css`\r\n :host {\r\n display: contents;\r\n }\r\n .shape {\r\n position: absolute;\r\n overflow: hidden;\r\n pointer-events: none;\r\n opacity: 1;\r\n background-color: var(--m3e-skeleton-color, ${DesignToken.color.surface});\r\n }\r\n .shape::before {\r\n content: \"\";\r\n position: absolute;\r\n left: 0;\r\n top: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-color: color-mix(\r\n in srgb,\r\n var(--m3e-skeleton-tint-color, ${DesignToken.color.onSurface}) var(--m3e-skeleton-tint-opacity, 8%),\r\n transparent\r\n );\r\n }\r\n :host(:not([loaded])) {\r\n contain: layout style paint;\r\n }\r\n :host(:not([loaded])) slot {\r\n visibility: hidden;\r\n }\r\n :host([loaded]) .shape {\r\n opacity: 0;\r\n transition: ${unsafeCSS(`opacity ${DesignToken.motion.duration.short3} ${DesignToken.motion.easing.standard}`)};\r\n }\r\n :host([shape=\"rounded\"]) .shape {\r\n border-radius: var(--m3e-skeleton-rounded-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.large}));\r\n }\r\n :host([shape=\"circular\"]) .shape {\r\n border-radius: var(--m3e-skeleton-circular-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.full}));\r\n }\r\n :host([shape=\"square\"]) .shape {\r\n border-radius: var(--m3e-skeleton-square-shape, var(--m3e-skeleton-shape, 0px));\r\n }\r\n :host([animation=\"pulse\"]:not([loaded])) .shape::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n opacity: calc(\r\n var(--m3e-skeleton-accent-opacity, 0.06) + (1 - var(--m3e-skeleton-accent-opacity, 0.06)) *\r\n var(--_m3e-skeleton-pulse-norm)\r\n );\r\n background-color: var(--m3e-skeleton-tint-color, ${DesignToken.color.surfaceDim});\r\n }\r\n :host([animation=\"wave\"]:not([loaded])) .shape::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-image: linear-gradient(\r\n 90deg,\r\n transparent 0%,\r\n transparent 35%,\r\n var(--m3e-skeleton-accent-color, ${DesignToken.color.onSurface}) 50%,\r\n transparent 65%,\r\n transparent 100%\r\n );\r\n background-attachment: fixed;\r\n background-size: calc(100vw + var(--_m3e-skeleton-wave-span) * 2) 100%;\r\n background-position-x: calc(\r\n var(--_m3e-skeleton-wave-pct) * (100vw + var(--_m3e-skeleton-wave-span) * 2) - var(--_m3e-skeleton-wave-span)\r\n );\r\n\r\n opacity: var(--m3e-skeleton-accent-opacity, 0.06);\r\n }\r\n @media (forced-colors: active) {\r\n :host([loaded]) .shape {\r\n transition: none;\r\n }\r\n .shape::after {\r\n display: none;\r\n }\r\n .shape {\r\n background-color: GrayText;\r\n }\r\n }\r\n @media (prefers-reduced-motion) {\r\n :host([loaded]) .shape {\r\n transition: none;\r\n }\r\n .shape::after {\r\n display: none;\r\n }\r\n }\r\n `;\r\n\r\n /** @private */ readonly #anchoringCleanupMap = new Map<HTMLElement, () => void>();\r\n\r\n /** @private */ #animation: Animation | null = null;\r\n\r\n /** The animation mode `#animation` was created for, so mode changes recreate it. @private */\r\n #animationMode: SkeletonAnimation | null = null;\r\n\r\n /**\r\n * The shape of the skeleton.\r\n * @default \"auto\"\r\n */\r\n @property({ reflect: true }) shape: SkeletonShape = \"auto\";\r\n\r\n /**\r\n * The animation effect of the skeleton.\r\n * @default \"wave\"\r\n */\r\n @property({ reflect: true }) animation: SkeletonAnimation = \"wave\";\r\n\r\n /**\r\n * Whether the content of the skeleton has been loaded.\r\n * @default false\r\n */\r\n @property({ type: Boolean, reflect: true }) loaded = false;\r\n\r\n /** @inheritdoc */\r\n override disconnectedCallback(): void {\r\n super.disconnectedCallback();\r\n this.#clearShapes();\r\n this.#stopMotion();\r\n }\r\n\r\n /** @inheritdoc */\r\n override reconnectedCallback(): void {\r\n super.reconnectedCallback();\r\n this.#createShapes();\r\n this.#updateLoading();\r\n }\r\n\r\n /** @inheritdoc */\r\n protected override willUpdate(_changedProperties: PropertyValues<this>): void {\r\n super.willUpdate(_changedProperties);\r\n\r\n if (_changedProperties.has(\"loaded\") || _changedProperties.has(\"animation\")) {\r\n this.#updateLoading();\r\n }\r\n }\r\n\r\n /** @inheritdoc */\r\n protected override render(): unknown {\r\n return html`<slot ?inert=\"${!this.loaded}\" @slotchange=\"${this.#handleSlotChange}\"></slot>`;\r\n }\r\n\r\n /** @private */\r\n async #handleSlotChange(): Promise<void> {\r\n this.#createShapes();\r\n }\r\n\r\n /** @private */\r\n #clearShapes(): void {\r\n for (const item of this.#anchoringCleanupMap) {\r\n item[0].remove();\r\n item[1]();\r\n }\r\n this.#anchoringCleanupMap.clear();\r\n }\r\n\r\n /** @private */\r\n async #createShapes(): Promise<void> {\r\n this.#clearShapes();\r\n\r\n const slot = this.shadowRoot?.querySelector(\"slot\");\r\n if (!slot) return;\r\n\r\n for (const element of slot.assignedElements({ flatten: true }).filter((x) => x instanceof HTMLElement)) {\r\n await this.#createShape(element);\r\n }\r\n }\r\n\r\n /** @private */\r\n async #createShape(element: HTMLElement): Promise<void> {\r\n await waitForUpgrade(element);\r\n\r\n const shape = document.createElement(\"div\");\r\n shape.classList.add(\"shape\");\r\n\r\n if (this.shape === \"auto\") {\r\n let borderRadius = getComputedStyle(element).borderRadius;\r\n if (!borderRadius || borderRadius === \"0px\") {\r\n const firstElement = element.shadowRoot?.firstElementChild;\r\n if (firstElement && !firstElement.nextElementSibling) {\r\n borderRadius = getComputedStyle(firstElement).borderRadius;\r\n }\r\n }\r\n\r\n if (borderRadius && borderRadius !== \"0px\") {\r\n shape.style.borderRadius = borderRadius;\r\n }\r\n }\r\n\r\n const anchoringCleanup = await positionAnchor(\r\n shape,\r\n element,\r\n {\r\n position: \"bottom\",\r\n },\r\n (x, y) => {\r\n shape.style.left = `${x}px`;\r\n shape.style.top = `${y - element.clientHeight}px`;\r\n shape.style.width = `${element.clientWidth}px`;\r\n shape.style.height = `${element.clientHeight}px`;\r\n },\r\n );\r\n\r\n this.#anchoringCleanupMap.set(shape, anchoringCleanup);\r\n this.shadowRoot?.appendChild(shape);\r\n }\r\n\r\n /**\r\n * Starts or stops this skeleton's own wave/pulse animation to reflect its current\r\n * loaded/animation/connected state, then aligns its play/pause with the active\r\n * accessibility and forced-colors preferences.\r\n * @private\r\n */\r\n #updateLoading(): void {\r\n if (this.isConnected && !this.loaded && (this.animation === \"wave\" || this.animation === \"pulse\")) {\r\n this.#startMotion();\r\n } else {\r\n this.#stopMotion();\r\n }\r\n }\r\n\r\n /**\r\n * Starts the wave/pulse animation on this skeleton itself rather than on\r\n * `document.documentElement`. The `--_m3e-skeleton-*` properties are registered\r\n * `inherits: true`, so animating them on the document root recalculates style for the\r\n * whole document every frame; scoping to the instance limits that to its own subtree.\r\n * Aligned to a shared timeline origin so multiple skeletons animate in phase, and\r\n * re-created when the effect mode (wave vs pulse) changes.\r\n * @private\r\n */\r\n #startMotion(): void {\r\n if (this.#animation) {\r\n if (this.#animationMode === this.animation) {\r\n // Already running for the current mode; nothing to do but re-sync motion state.\r\n this.#syncMotionState();\r\n return;\r\n }\r\n // Effect mode changed (wave <-> pulse); tear down and recreate below.\r\n this.#stopMotion();\r\n }\r\n\r\n M3eSkeletonElement.__motionOrigin ??= (document.timeline.currentTime as number | null) ?? 0;\r\n\r\n const animation =\r\n this.animation === \"pulse\"\r\n ? this.animate(\r\n [\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 0 },\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 1 },\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 0 },\r\n ],\r\n {\r\n duration: 1200,\r\n iterations: Infinity,\r\n easing: \"ease-in-out\",\r\n },\r\n )\r\n : this.animate([{ [\"--_m3e-skeleton-wave-pct\"]: 0 }, { [\"--_m3e-skeleton-wave-pct\"]: 1 }], {\r\n duration: 2100,\r\n iterations: Infinity,\r\n easing: \"linear\",\r\n });\r\n\r\n animation.startTime = M3eSkeletonElement.__motionOrigin;\r\n\r\n this.#animation = animation;\r\n this.#animationMode = this.animation;\r\n M3eSkeletonElement.__animating.add(this);\r\n this.#syncMotionState();\r\n }\r\n\r\n /** @private */\r\n #stopMotion(): void {\r\n if (!this.#animation) {\r\n return;\r\n }\r\n this.#animation.cancel();\r\n this.#animation = null;\r\n this.#animationMode = null;\r\n M3eSkeletonElement.__animating.delete(this);\r\n }\r\n\r\n /** Whether motion is currently suppressed for accessibility or forced-colors reasons. @private */\r\n private static __motionDisabled(): boolean {\r\n return M3eSkeletonElement.__reducedMediaQuery.matches || M3eSkeletonElement.__forcedColorsMediaQuery.matches;\r\n }\r\n\r\n /**\r\n * Re-applies the current motion preference to every animating skeleton. Invoked when\r\n * the reduced-motion or forced-colors preference changes.\r\n * @private\r\n */\r\n private static __updateMotion(): void {\r\n for (const skeleton of M3eSkeletonElement.__animating) {\r\n skeleton.#syncMotionState();\r\n }\r\n }\r\n\r\n /**\r\n * Aligns this skeleton's animation play state with the current reduced-motion and\r\n * forced-colors preferences.\r\n * @private\r\n */\r\n #syncMotionState(): void {\r\n if (!this.#animation) {\r\n return;\r\n }\r\n if (M3eSkeletonElement.__motionDisabled()) {\r\n this.#animation.pause();\r\n } else {\r\n this.#animation.play();\r\n }\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n \"m3e-skeleton\": M3eSkeletonElement;\r\n }\r\n}\r\n"],"names":["M3eSkeletonElement","ReconnectedCallback","LitElement","constructor","_M3eSkeletonElement_anchoringCleanupMap","set","Map","_M3eSkeletonElement_animation","_M3eSkeletonElement_animationMode","shape","animation","loaded","disconnectedCallback","__classPrivateFieldGet","_M3eSkeletonElement_instances","_M3eSkeletonElement_clearShapes","call","_M3eSkeletonElement_stopMotion","reconnectedCallback","_M3eSkeletonElement_createShapes","_M3eSkeletonElement_updateLoading","willUpdate","_changedProperties","has","render","html","_M3eSkeletonElement_handleSlotChange","__motionDisabled","M3eSkeletonElement_1","__reducedMediaQuery","matches","__forcedColorsMediaQuery","__updateMotion","skeleton","__animating","_M3eSkeletonElement_syncMotionState","item","remove","clear","slot","shadowRoot","querySelector","element","assignedElements","flatten","filter","x","HTMLElement","_M3eSkeletonElement_createShape","waitForUpgrade","document","createElement","classList","add","borderRadius","getComputedStyle","firstElement","firstElementChild","nextElementSibling","style","anchoringCleanup","positionAnchor","position","y","left","top","clientHeight","width","clientWidth","height","appendChild","isConnected","_M3eSkeletonElement_startMotion","__motionOrigin","timeline","currentTime","animate","duration","iterations","Infinity","easing","startTime","__classPrivateFieldSet","cancel","delete","pause","play","Set","window","registerStyleSheet","css","matchMedia","addEventListener","styles","DesignToken","color","surface","onSurface","unsafeCSS","motion","short3","standard","corner","large","full","surfaceDim","__decorate","property","reflect","prototype","type","Boolean","customElement"],"mappings":"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"}
|
package/dist/skeleton.min.js
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Copyright (c) 2025–2026 matraic
|
|
4
4
|
* See LICENSE file in the project root for full license text.
|
|
5
5
|
*/
|
|
6
|
-
import{__classPrivateFieldGet as e,__decorate as
|
|
6
|
+
import{__classPrivateFieldGet as e,__classPrivateFieldSet as t,__decorate as o}from"tslib";import{LitElement as a,html as i,css as n,unsafeCSS as s}from"lit";import{property as r}from"lit/decorators.js";import{ReconnectedCallback as l,waitForUpgrade as c,registerStyleSheet as d,DesignToken as h,customElement as p}from"@m3e/web/core";import{positionAnchor as m}from"@m3e/web/core/anchoring";var u,f,_,v,k,y,w,g,b,x,M,$,C;let S=C=class extends(l(a)){constructor(){super(...arguments),u.add(this),f.set(this,new Map),_.set(this,null),v.set(this,null),this.shape="auto",this.animation="wave",this.loaded=!1}disconnectedCallback(){super.disconnectedCallback(),e(this,u,"m",y).call(this),e(this,u,"m",M).call(this)}reconnectedCallback(){super.reconnectedCallback(),e(this,u,"m",w).call(this),e(this,u,"m",b).call(this)}willUpdate(t){super.willUpdate(t),(t.has("loaded")||t.has("animation"))&&e(this,u,"m",b).call(this)}render(){return i`<slot ?inert="${!this.loaded}" @slotchange="${e(this,u,"m",k)}"></slot>`}static __motionDisabled(){return C.__reducedMediaQuery.matches||C.__forcedColorsMediaQuery.matches}static __updateMotion(){for(const t of C.__animating)e(t,u,"m",$).call(t)}};f=new WeakMap,_=new WeakMap,v=new WeakMap,u=new WeakSet,k=async function(){e(this,u,"m",w).call(this)},y=function(){for(const t of e(this,f,"f"))t[0].remove(),t[1]();e(this,f,"f").clear()},w=async function(){e(this,u,"m",y).call(this);const t=this.shadowRoot?.querySelector("slot");if(t)for(const o of t.assignedElements({flatten:!0}).filter(e=>e instanceof HTMLElement))await e(this,u,"m",g).call(this,o)},g=async function(t){await c(t);const o=document.createElement("div");if(o.classList.add("shape"),"auto"===this.shape){let e=getComputedStyle(t).borderRadius;if(!e||"0px"===e){const o=t.shadowRoot?.firstElementChild;o&&!o.nextElementSibling&&(e=getComputedStyle(o).borderRadius)}e&&"0px"!==e&&(o.style.borderRadius=e)}const a=await m(o,t,{position:"bottom"},(e,a)=>{o.style.left=`${e}px`,o.style.top=a-t.clientHeight+"px",o.style.width=`${t.clientWidth}px`,o.style.height=`${t.clientHeight}px`});e(this,f,"f").set(o,a),this.shadowRoot?.appendChild(o)},b=function(){!this.isConnected||this.loaded||"wave"!==this.animation&&"pulse"!==this.animation?e(this,u,"m",M).call(this):e(this,u,"m",x).call(this)},x=function(){if(e(this,_,"f")){if(e(this,v,"f")===this.animation)return void e(this,u,"m",$).call(this);e(this,u,"m",M).call(this)}C.__motionOrigin??=document.timeline.currentTime??0;const o="pulse"===this.animation?this.animate([{"--_m3e-skeleton-pulse-norm":0},{"--_m3e-skeleton-pulse-norm":1},{"--_m3e-skeleton-pulse-norm":0}],{duration:1200,iterations:1/0,easing:"ease-in-out"}):this.animate([{"--_m3e-skeleton-wave-pct":0},{"--_m3e-skeleton-wave-pct":1}],{duration:2100,iterations:1/0,easing:"linear"});o.startTime=C.__motionOrigin,t(this,_,o,"f"),t(this,v,this.animation,"f"),C.__animating.add(this),e(this,u,"m",$).call(this)},M=function(){e(this,_,"f")&&(e(this,_,"f").cancel(),t(this,_,null,"f"),t(this,v,null,"f"),C.__animating.delete(this))},$=function(){e(this,_,"f")&&(C.__motionDisabled()?e(this,_,"f").pause():e(this,_,"f").play())},S.__animating=new Set,S.__motionOrigin=null,"undefined"!=typeof window&&(d(n`@property --_m3e-skeleton-wave-pct { syntax: "<number>"; inherits: true; initial-value: 0; } @property --_m3e-skeleton-pulse-norm { syntax: "<number>"; inherits: true; initial-value: 0; } :root { --_m3e-skeleton-wave-span: 40vw; --_m3e-skeleton-pulse-min: 0.06; }</number></number>`),C.__reducedMediaQuery=window.matchMedia("(prefers-reduced-motion: reduce)"),C.__forcedColorsMediaQuery=window.matchMedia("(forced-colors: active)"),C.__reducedMediaQuery.addEventListener("change",()=>C.__updateMotion()),C.__forcedColorsMediaQuery.addEventListener("change",()=>C.__updateMotion())),S.styles=n`:host { display: contents; } .shape { position: absolute; overflow: hidden; pointer-events: none; opacity: 1; background-color: var(--m3e-skeleton-color, ${h.color.surface}); } .shape::before { content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: color-mix( in srgb, var(--m3e-skeleton-tint-color, ${h.color.onSurface}) var(--m3e-skeleton-tint-opacity, 8%), transparent ); } :host(:not([loaded])) { contain: layout style paint; } :host(:not([loaded])) slot { visibility: hidden; } :host([loaded]) .shape { opacity: 0; transition: ${s(`opacity ${h.motion.duration.short3} ${h.motion.easing.standard}`)}; } :host([shape="rounded"]) .shape { border-radius: var(--m3e-skeleton-rounded-shape, var(--m3e-skeleton-shape, ${h.shape.corner.large})); } :host([shape="circular"]) .shape { border-radius: var(--m3e-skeleton-circular-shape, var(--m3e-skeleton-shape, ${h.shape.corner.full})); } :host([shape="square"]) .shape { border-radius: var(--m3e-skeleton-square-shape, var(--m3e-skeleton-shape, 0px)); } :host([animation="pulse"]:not([loaded])) .shape::after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: calc( var(--m3e-skeleton-accent-opacity, 0.06) + (1 - var(--m3e-skeleton-accent-opacity, 0.06)) * var(--_m3e-skeleton-pulse-norm) ); background-color: var(--m3e-skeleton-tint-color, ${h.color.surfaceDim}); } :host([animation="wave"]:not([loaded])) .shape::after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: linear-gradient( 90deg, transparent 0%, transparent 35%, var(--m3e-skeleton-accent-color, ${h.color.onSurface}) 50%, transparent 65%, transparent 100% ); background-attachment: fixed; background-size: calc(100vw + var(--_m3e-skeleton-wave-span) * 2) 100%; background-position-x: calc( var(--_m3e-skeleton-wave-pct) * (100vw + var(--_m3e-skeleton-wave-span) * 2) - var(--_m3e-skeleton-wave-span) ); opacity: var(--m3e-skeleton-accent-opacity, 0.06); } @media (forced-colors: active) { :host([loaded]) .shape { transition: none; } .shape::after { display: none; } .shape { background-color: GrayText; } } @media (prefers-reduced-motion) { :host([loaded]) .shape { transition: none; } .shape::after { display: none; } }`,o([r({reflect:!0})],S.prototype,"shape",void 0),o([r({reflect:!0})],S.prototype,"animation",void 0),o([r({type:Boolean,reflect:!0})],S.prototype,"loaded",void 0),S=C=o([p("m3e-skeleton")],S);export{S as M3eSkeletonElement};
|
|
7
7
|
//# sourceMappingURL=skeleton.min.js.map
|
package/dist/skeleton.min.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skeleton.min.js","sources":["../../src/skeleton/SkeletonElement.ts"],"sourcesContent":["import { css, CSSResultGroup, html, LitElement, unsafeCSS } from \"lit\";\r\nimport { property } from \"lit/decorators.js\";\r\n\r\nimport { customElement, DesignToken, ReconnectedCallback, registerStyleSheet, waitForUpgrade } from \"@m3e/web/core\";\r\nimport { positionAnchor } from \"@m3e/web/core/anchoring\";\r\n\r\nimport { SkeletonShape } from \"./SkeletonShape\";\r\nimport { SkeletonAnimation } from \"./SkeletonAnimation\";\r\n\r\n/**\r\n * A visual placeholder that mimics the layout of content while it's still loading.\r\n * @description\r\n * The `m3e-skeleton` component provides a loading placeholder surface with flexible shape variants and\r\n * motion-based animations that communicate loading state while preserving layout stability. It mimics\r\n * the layout of content while it's still loading, ensuring a smooth user experience during data fetching\r\n * or rendering delays. The component supports different animation effects (`pulse`, `wave`, `none`) and\r\n * shape variants (`circular`, `rounded`, `square`, `auto`) to adapt to various content types. When the\r\n * content is loaded, the skeleton fades out with a smooth transition.\r\n *\r\n * @example\r\n * The following example illustrates a skeleton shaped and sized by the slotted `m3e-card`.\r\n * ```html\r\n * <m3e-skeleton>\r\n * <m3e-card></m3e-card>\r\n * </m3e-skeleton>\r\n * ```\r\n *\r\n * @tag m3e-skeleton\r\n *\r\n * @attr animation - The animation effect of the skeleton.\r\n * @attr shape - The shape of the skeleton.\r\n * @attr loaded - Whether the content of the skeleton has been loaded.\r\n *\r\n * @slot - Renders the content to be mimicked by the skeleton.\r\n *\r\n * @cssprop --m3e-skeleton-color - Base fill color for the skeleton surface.\r\n * @cssprop --m3e-skeleton-tint-color - Tint fill color for the skeleton surface.\r\n * @cssprop --m3e-skeleton-tint-opacity - Tint Opacity applied when the skeleton animation is not pulsating.\r\n * @cssprop --m3e-skeleton-accent-color - Accent color used in wave animation.\r\n * @cssprop --m3e-skeleton-accent-opacity - Opacity of the accent effect in animations.\r\n * @cssprop --m3e-skeleton-rounded-shape - Corner radius for the rounded skeleton shape.\r\n * @cssprop --m3e-skeleton-circular-shape - Corner radius for the circular skeleton shape.\r\n * @cssprop --m3e-skeleton-square-shape - Corner radius for the square skeleton shape.\r\n * @cssprop --m3e-skeleton-shape - Corner radius for the skeleton shape.\r\n */\r\n@customElement(\"m3e-skeleton\")\r\nexport class M3eSkeletonElement extends ReconnectedCallback(LitElement) {\r\n static {\r\n if (window !== undefined) {\r\n registerStyleSheet(css`\r\n @property --_m3e-skeleton-wave-pct {\r\n syntax: \"<number>\";\r\n inherits: true;\r\n initial-value: 0;\r\n }\r\n @property --_m3e-skeleton-pulse-norm {\r\n syntax: \"<number>\";\r\n inherits: true;\r\n initial-value: 0;\r\n }\r\n :root {\r\n --_m3e-skeleton-wave-span: 40vw;\r\n --_m3e-skeleton-pulse-min: 0.06;\r\n }\r\n `);\r\n\r\n const reducedMediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\r\n const forcedColorsMediaQuery = window.matchMedia(\"(forced-colors: active)\");\r\n\r\n let waveAnimation: Animation | null = null;\r\n let pulseAnimation: Animation | null = null;\r\n\r\n function startAnimations(): void {\r\n waveAnimation = document.documentElement.animate(\r\n [{ [\"--_m3e-skeleton-wave-pct\"]: 0 }, { [\"--_m3e-skeleton-wave-pct\"]: 1 }],\r\n {\r\n duration: 2100,\r\n iterations: Infinity,\r\n easing: \"linear\",\r\n },\r\n );\r\n\r\n pulseAnimation = document.documentElement.animate(\r\n [\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 0 },\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 1 },\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 0 },\r\n ],\r\n {\r\n duration: 1200,\r\n iterations: Infinity,\r\n easing: \"ease-in-out\",\r\n },\r\n );\r\n }\r\n\r\n function applyMotionState(): void {\r\n if (reducedMediaQuery.matches || forcedColorsMediaQuery.matches) {\r\n waveAnimation?.pause();\r\n pulseAnimation?.pause();\r\n } else {\r\n waveAnimation?.play();\r\n pulseAnimation?.play();\r\n }\r\n }\r\n\r\n startAnimations();\r\n applyMotionState();\r\n\r\n reducedMediaQuery.addEventListener(\"change\", applyMotionState);\r\n forcedColorsMediaQuery.addEventListener(\"change\", applyMotionState);\r\n }\r\n }\r\n\r\n /** The styles of the element. */\r\n static override styles: CSSResultGroup = css`\r\n :host {\r\n display: contents;\r\n }\r\n .shape {\r\n position: absolute;\r\n overflow: hidden;\r\n pointer-events: none;\r\n opacity: 1;\r\n background-color: var(--m3e-skeleton-color, ${DesignToken.color.surface});\r\n }\r\n .shape::before {\r\n content: \"\";\r\n position: absolute;\r\n left: 0;\r\n top: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-color: color-mix(\r\n in srgb,\r\n var(--m3e-skeleton-tint-color, ${DesignToken.color.onSurface}) var(--m3e-skeleton-tint-opacity, 8%),\r\n transparent\r\n );\r\n }\r\n :host(:not([loaded])) slot {\r\n visibility: hidden;\r\n }\r\n :host([loaded]) .shape {\r\n opacity: 0;\r\n transition: ${unsafeCSS(`opacity ${DesignToken.motion.duration.short3} ${DesignToken.motion.easing.standard}`)};\r\n }\r\n :host([shape=\"rounded\"]) .shape {\r\n border-radius: var(--m3e-skeleton-rounded-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.large}));\r\n }\r\n :host([shape=\"circular\"]) .shape {\r\n border-radius: var(--m3e-skeleton-circular-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.full}));\r\n }\r\n :host([shape=\"square\"]) .shape {\r\n border-radius: var(--m3e-skeleton-square-shape, var(--m3e-skeleton-shape, 0px));\r\n }\r\n :host([animation=\"pulse\"]:not([loaded])) .shape::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n opacity: calc(\r\n var(--m3e-skeleton-accent-opacity, 0.06) + (1 - var(--m3e-skeleton-accent-opacity, 0.06)) *\r\n var(--_m3e-skeleton-pulse-norm)\r\n );\r\n background-color: var(--m3e-skeleton-tint-color, ${DesignToken.color.surfaceDim});\r\n }\r\n :host([animation=\"wave\"]:not([loaded])) .shape::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-image: linear-gradient(\r\n 90deg,\r\n transparent 0%,\r\n transparent 35%,\r\n var(--m3e-skeleton-accent-color, ${DesignToken.color.onSurface}) 50%,\r\n transparent 65%,\r\n transparent 100%\r\n );\r\n background-attachment: fixed;\r\n background-size: calc(100vw + var(--_m3e-skeleton-wave-span) * 2) 100%;\r\n background-position-x: calc(\r\n var(--_m3e-skeleton-wave-pct) * (100vw + var(--_m3e-skeleton-wave-span) * 2) - var(--_m3e-skeleton-wave-span)\r\n );\r\n\r\n opacity: var(--m3e-skeleton-accent-opacity, 0.06);\r\n }\r\n @media (forced-colors: active) {\r\n :host([loaded]) .shape {\r\n transition: none;\r\n }\r\n .shape::after {\r\n display: none;\r\n }\r\n .shape {\r\n background-color: GrayText;\r\n }\r\n }\r\n @media (prefers-reduced-motion) {\r\n :host([loaded]) .shape {\r\n transition: none;\r\n }\r\n .shape::after {\r\n display: none;\r\n }\r\n }\r\n `;\r\n\r\n /** @private */ readonly #anchoringCleanupMap = new Map<HTMLElement, () => void>();\r\n\r\n /**\r\n * The shape of the skeleton.\r\n * @default \"auto\"\r\n */\r\n @property({ reflect: true }) shape: SkeletonShape = \"auto\";\r\n\r\n /**\r\n * The animation effect of the skeleton.\r\n * @default \"wave\"\r\n */\r\n @property({ reflect: true }) animation: SkeletonAnimation = \"wave\";\r\n\r\n /**\r\n * Whether the content of the skeleton has been loaded.\r\n * @default false\r\n */\r\n @property({ type: Boolean, reflect: true }) loaded = false;\r\n\r\n /** @inheritdoc */\r\n override disconnectedCallback(): void {\r\n super.disconnectedCallback();\r\n this.#clearShapes();\r\n }\r\n\r\n /** @inheritdoc */\r\n override reconnectedCallback(): void {\r\n super.reconnectedCallback();\r\n this.#createShapes();\r\n }\r\n\r\n /** @inheritdoc */\r\n protected override render(): unknown {\r\n return html`<slot ?inert=\"${!this.loaded}\" @slotchange=\"${this.#handleSlotChange}\"></slot>`;\r\n }\r\n\r\n /** @private */\r\n async #handleSlotChange(): Promise<void> {\r\n this.#createShapes();\r\n }\r\n\r\n /** @private */\r\n #clearShapes(): void {\r\n for (const item of this.#anchoringCleanupMap) {\r\n item[0].remove();\r\n item[1]();\r\n }\r\n this.#anchoringCleanupMap.clear();\r\n }\r\n\r\n /** @private */\r\n async #createShapes(): Promise<void> {\r\n this.#clearShapes();\r\n\r\n const slot = this.shadowRoot?.querySelector(\"slot\");\r\n if (!slot) return;\r\n\r\n for (const element of slot.assignedElements({ flatten: true }).filter((x) => x instanceof HTMLElement)) {\r\n await this.#createShape(element);\r\n }\r\n }\r\n\r\n /** @private */\r\n async #createShape(element: HTMLElement): Promise<void> {\r\n await waitForUpgrade(element);\r\n\r\n const shape = document.createElement(\"div\");\r\n shape.classList.add(\"shape\");\r\n\r\n if (this.shape === \"auto\") {\r\n let borderRadius = getComputedStyle(element).borderRadius;\r\n if (!borderRadius || borderRadius === \"0px\") {\r\n const firstElement = element.shadowRoot?.firstElementChild;\r\n if (firstElement && !firstElement.nextElementSibling) {\r\n borderRadius = getComputedStyle(firstElement).borderRadius;\r\n }\r\n }\r\n\r\n if (borderRadius && borderRadius !== \"0px\") {\r\n shape.style.borderRadius = borderRadius;\r\n }\r\n }\r\n\r\n const anchoringCleanup = await positionAnchor(\r\n shape,\r\n element,\r\n {\r\n position: \"bottom\",\r\n },\r\n (x, y) => {\r\n shape.style.left = `${x}px`;\r\n shape.style.top = `${y - element.clientHeight}px`;\r\n shape.style.width = `${element.clientWidth}px`;\r\n shape.style.height = `${element.clientHeight}px`;\r\n },\r\n );\r\n\r\n this.#anchoringCleanupMap.set(shape, anchoringCleanup);\r\n this.shadowRoot?.appendChild(shape);\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n \"m3e-skeleton\": M3eSkeletonElement;\r\n }\r\n}\r\n"],"names":["M3eSkeletonElement","ReconnectedCallback","LitElement","constructor","_M3eSkeletonElement_anchoringCleanupMap","set","this","Map","shape","animation","loaded","disconnectedCallback","super","__classPrivateFieldGet","_M3eSkeletonElement_instances","_M3eSkeletonElement_clearShapes","call","reconnectedCallback","_M3eSkeletonElement_createShapes","render","html","_M3eSkeletonElement_handleSlotChange","async","item","remove","clear","slot","shadowRoot","querySelector","element","assignedElements","flatten","filter","x","HTMLElement","_M3eSkeletonElement_createShape","waitForUpgrade","document","createElement","classList","add","borderRadius","getComputedStyle","firstElement","firstElementChild","nextElementSibling","style","anchoringCleanup","positionAnchor","position","y","left","top","clientHeight","width","clientWidth","height","appendChild","undefined","window","registerStyleSheet","css","reducedMediaQuery","matchMedia","forcedColorsMediaQuery","waveAnimation","pulseAnimation","startAnimations","documentElement","animate","duration","iterations","Infinity","easing","applyMotionState","matches","pause","play","addEventListener","styles","DesignToken","color","surface","onSurface","unsafeCSS","motion","short3","standard","corner","large","full","surfaceDim","__decorate","property","reflect","prototype","type","Boolean","customElement"],"mappings":";;;;;4XA8CO,IAAMA,EAAN,cAAiCC,EAAoBC,IAArDC,WAAAA,mCAsKoBC,EAAAC,IAAAC,KAAuB,IAAIC,KAMvBD,KAAAE,MAAuB,OAMvBF,KAAAG,UAA+B,OAMhBH,KAAAI,QAAS,CAmFvD,CAhFWC,oBAAAA,GACPC,MAAMD,uBACNE,EAAAP,KAAIQ,EAAA,IAAAC,GAAaC,KAAjBV,KACF,CAGSW,mBAAAA,GACPL,MAAMK,sBACNJ,EAAAP,KAAIQ,EAAA,IAAAI,GAAcF,KAAlBV,KACF,CAGmBa,MAAAA,GACjB,OAAOC,CAAI,kBAAkBd,KAAKI,wBAAwBG,EAAAP,KAAIQ,EAAA,IAAAO,aAChE,iCAGAC,iBACET,EAAAP,KAAIQ,EAAA,IAAAI,GAAcF,KAAlBV,KACF,eAIE,IAAK,MAAMiB,KAAQV,EAAAP,KAAIF,EAAA,KACrBmB,EAAK,GAAGC,SACRD,EAAK,KAEPV,EAAAP,KAAIF,EAAA,KAAsBqB,OAC5B,IAGAH,iBACET,EAAAP,KAAIQ,EAAA,IAAAC,GAAaC,KAAjBV,MAEA,MAAMoB,EAAOpB,KAAKqB,YAAYC,cAAc,QAC5C,GAAKF,EAEL,IAAK,MAAMG,KAAWH,EAAKI,iBAAiB,CAAEC,SAAS,IAAQC,OAAQC,GAAMA,aAAaC,mBAClFrB,EAAAP,KAAIQ,EAAA,IAAAqB,GAAanB,KAAjBV,KAAkBuB,EAE5B,IAGAP,eAAmBO,SACXO,EAAeP,GAErB,MAAMrB,EAAQ6B,SAASC,cAAc,OAGrC,GAFA9B,EAAM+B,UAAUC,IAAI,SAED,SAAflC,KAAKE,MAAkB,CACzB,IAAIiC,EAAeC,iBAAiBb,GAASY,aAC7C,IAAKA,GAAiC,QAAjBA,EAAwB,CAC3C,MAAME,EAAed,EAAQF,YAAYiB,kBACrCD,IAAiBA,EAAaE,qBAChCJ,EAAeC,iBAAiBC,GAAcF,aAElD,CAEIA,GAAiC,QAAjBA,IAClBjC,EAAMsC,MAAML,aAAeA,EAE/B,CAEA,MAAMM,QAAyBC,EAC7BxC,EACAqB,EACA,CACEoB,SAAU,UAEZ,CAAChB,EAAGiB,KACF1C,EAAMsC,MAAMK,KAAO,GAAGlB,MACtBzB,EAAMsC,MAAMM,IAASF,EAAIrB,EAAQwB,aAAf,KAClB7C,EAAMsC,MAAMQ,MAAQ,GAAGzB,EAAQ0B,gBAC/B/C,EAAMsC,MAAMU,OAAS,GAAG3B,EAAQwB,mBAIpCxC,EAAAP,YAA0BD,IAAIG,EAAOuC,GACrCzC,KAAKqB,YAAY8B,YAAYjD,EAC/B,EAzQA,MACE,QAAekD,IAAXC,OAAsB,CACxBC,EAAmBC,CAAG,6RAiBtB,MAAMC,EAAoBH,OAAOI,WAAW,oCACtCC,EAAyBL,OAAOI,WAAW,2BAEjD,IAAIE,EAAkC,KAClCC,EAAmC,KAEvC,SAASC,IACPF,EAAgB5B,SAAS+B,gBAAgBC,QACvC,CAAC,CAAE,2BAA8B,GAAK,CAAE,2BAA8B,IACtE,CACEC,SAAU,KACVC,WAAYC,IACZC,OAAQ,WAIZP,EAAiB7B,SAAS+B,gBAAgBC,QACxC,CACE,CAAE,6BAAgC,GAClC,CAAE,6BAAgC,GAClC,CAAE,6BAAgC,IAEpC,CACEC,SAAU,KACVC,WAAYC,IACZC,OAAQ,eAGd,CAEA,SAASC,IACHZ,EAAkBa,SAAWX,EAAuBW,SACtDV,GAAeW,QACfV,GAAgBU,UAEhBX,GAAeY,OACfX,GAAgBW,OAEpB,CAEAV,IACAO,IAEAZ,EAAkBgB,iBAAiB,SAAUJ,GAC7CV,EAAuBc,iBAAiB,SAAUJ,EACpD,CACD,EAjED,GAoEgB1E,EAAA+E,OAAyBlB,CAAG,6JASMmB,EAAYC,MAAMC,kLAW7BF,EAAYC,MAAME,yKASvCC,EAAU,WAAWJ,EAAYK,OAAOf,SAASgB,UAAUN,EAAYK,OAAOZ,OAAOc,+HAGtBP,EAAYxE,MAAMgF,OAAOC,6HAGxBT,EAAYxE,MAAMgF,OAAOE,scAgBpDV,EAAYC,MAAMU,mQAahCX,EAAYC,MAAME,0mBAuC9BS,EAAA,CAA5BC,EAAS,CAAEC,SAAS,KAAsC9F,EAAA+F,UAAA,aAAA,GAM9BH,EAAA,CAA5BC,EAAS,CAAEC,SAAS,KAA8C9F,EAAA+F,UAAA,iBAAA,GAMvBH,EAAA,CAA3CC,EAAS,CAAEG,KAAMC,QAASH,SAAS,KAAuB9F,EAAA+F,UAAA,cAAA,GAxLhD/F,EAAkB4F,EAAA,CAD9BM,EAAc,iBACFlG"}
|
|
1
|
+
{"version":3,"file":"skeleton.min.js","sources":["../../src/skeleton/SkeletonElement.ts"],"sourcesContent":["import { css, CSSResultGroup, html, LitElement, PropertyValues, unsafeCSS } from \"lit\";\r\nimport { property } from \"lit/decorators.js\";\r\n\r\nimport { customElement, DesignToken, ReconnectedCallback, registerStyleSheet, waitForUpgrade } from \"@m3e/web/core\";\r\nimport { positionAnchor } from \"@m3e/web/core/anchoring\";\r\n\r\nimport { SkeletonShape } from \"./SkeletonShape\";\r\nimport { SkeletonAnimation } from \"./SkeletonAnimation\";\r\n\r\n/**\r\n * A visual placeholder that mimics the layout of content while it's still loading.\r\n * @description\r\n * The `m3e-skeleton` component provides a loading placeholder surface with flexible shape variants and\r\n * motion-based animations that communicate loading state while preserving layout stability. It mimics\r\n * the layout of content while it's still loading, ensuring a smooth user experience during data fetching\r\n * or rendering delays. The component supports different animation effects (`pulse`, `wave`, `none`) and\r\n * shape variants (`circular`, `rounded`, `square`, `auto`) to adapt to various content types. When the\r\n * content is loaded, the skeleton fades out with a smooth transition.\r\n *\r\n * @example\r\n * The following example illustrates a skeleton shaped and sized by the slotted `m3e-card`.\r\n * ```html\r\n * <m3e-skeleton>\r\n * <m3e-card></m3e-card>\r\n * </m3e-skeleton>\r\n * ```\r\n *\r\n * @tag m3e-skeleton\r\n *\r\n * @attr animation - The animation effect of the skeleton.\r\n * @attr shape - The shape of the skeleton.\r\n * @attr loaded - Whether the content of the skeleton has been loaded.\r\n *\r\n * @slot - Renders the content to be mimicked by the skeleton.\r\n *\r\n * @cssprop --m3e-skeleton-color - Base fill color for the skeleton surface.\r\n * @cssprop --m3e-skeleton-tint-color - Tint fill color for the skeleton surface.\r\n * @cssprop --m3e-skeleton-tint-opacity - Tint Opacity applied when the skeleton animation is not pulsating.\r\n * @cssprop --m3e-skeleton-accent-color - Accent color used in wave animation.\r\n * @cssprop --m3e-skeleton-accent-opacity - Opacity of the accent effect in animations.\r\n * @cssprop --m3e-skeleton-rounded-shape - Corner radius for the rounded skeleton shape.\r\n * @cssprop --m3e-skeleton-circular-shape - Corner radius for the circular skeleton shape.\r\n * @cssprop --m3e-skeleton-square-shape - Corner radius for the square skeleton shape.\r\n * @cssprop --m3e-skeleton-shape - Corner radius for the skeleton shape.\r\n */\r\n@customElement(\"m3e-skeleton\")\r\nexport class M3eSkeletonElement extends ReconnectedCallback(LitElement) {\r\n /** Skeletons with a live per-instance animation, so preference changes re-sync them all. @private */\r\n private static __animating = new Set<M3eSkeletonElement>();\r\n\r\n /** Shared timeline origin so every skeleton's wave/pulse stays in phase. @private */\r\n private static __motionOrigin: number | null = null;\r\n\r\n /** @private */ private static __reducedMediaQuery: MediaQueryList;\r\n /** @private */ private static __forcedColorsMediaQuery: MediaQueryList;\r\n\r\n static {\r\n if (typeof window !== \"undefined\") {\r\n registerStyleSheet(css`\r\n @property --_m3e-skeleton-wave-pct {\r\n syntax: \"<number>\";\r\n inherits: true;\r\n initial-value: 0;\r\n }\r\n @property --_m3e-skeleton-pulse-norm {\r\n syntax: \"<number>\";\r\n inherits: true;\r\n initial-value: 0;\r\n }\r\n :root {\r\n --_m3e-skeleton-wave-span: 40vw;\r\n --_m3e-skeleton-pulse-min: 0.06;\r\n }\r\n `);\r\n\r\n M3eSkeletonElement.__reducedMediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\r\n M3eSkeletonElement.__forcedColorsMediaQuery = window.matchMedia(\"(forced-colors: active)\");\r\n M3eSkeletonElement.__reducedMediaQuery.addEventListener(\"change\", () => M3eSkeletonElement.__updateMotion());\r\n M3eSkeletonElement.__forcedColorsMediaQuery.addEventListener(\"change\", () => M3eSkeletonElement.__updateMotion());\r\n }\r\n }\r\n\r\n /** The styles of the element. */\r\n static override styles: CSSResultGroup = css`\r\n :host {\r\n display: contents;\r\n }\r\n .shape {\r\n position: absolute;\r\n overflow: hidden;\r\n pointer-events: none;\r\n opacity: 1;\r\n background-color: var(--m3e-skeleton-color, ${DesignToken.color.surface});\r\n }\r\n .shape::before {\r\n content: \"\";\r\n position: absolute;\r\n left: 0;\r\n top: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-color: color-mix(\r\n in srgb,\r\n var(--m3e-skeleton-tint-color, ${DesignToken.color.onSurface}) var(--m3e-skeleton-tint-opacity, 8%),\r\n transparent\r\n );\r\n }\r\n :host(:not([loaded])) {\r\n contain: layout style paint;\r\n }\r\n :host(:not([loaded])) slot {\r\n visibility: hidden;\r\n }\r\n :host([loaded]) .shape {\r\n opacity: 0;\r\n transition: ${unsafeCSS(`opacity ${DesignToken.motion.duration.short3} ${DesignToken.motion.easing.standard}`)};\r\n }\r\n :host([shape=\"rounded\"]) .shape {\r\n border-radius: var(--m3e-skeleton-rounded-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.large}));\r\n }\r\n :host([shape=\"circular\"]) .shape {\r\n border-radius: var(--m3e-skeleton-circular-shape, var(--m3e-skeleton-shape, ${DesignToken.shape.corner.full}));\r\n }\r\n :host([shape=\"square\"]) .shape {\r\n border-radius: var(--m3e-skeleton-square-shape, var(--m3e-skeleton-shape, 0px));\r\n }\r\n :host([animation=\"pulse\"]:not([loaded])) .shape::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n opacity: calc(\r\n var(--m3e-skeleton-accent-opacity, 0.06) + (1 - var(--m3e-skeleton-accent-opacity, 0.06)) *\r\n var(--_m3e-skeleton-pulse-norm)\r\n );\r\n background-color: var(--m3e-skeleton-tint-color, ${DesignToken.color.surfaceDim});\r\n }\r\n :host([animation=\"wave\"]:not([loaded])) .shape::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-image: linear-gradient(\r\n 90deg,\r\n transparent 0%,\r\n transparent 35%,\r\n var(--m3e-skeleton-accent-color, ${DesignToken.color.onSurface}) 50%,\r\n transparent 65%,\r\n transparent 100%\r\n );\r\n background-attachment: fixed;\r\n background-size: calc(100vw + var(--_m3e-skeleton-wave-span) * 2) 100%;\r\n background-position-x: calc(\r\n var(--_m3e-skeleton-wave-pct) * (100vw + var(--_m3e-skeleton-wave-span) * 2) - var(--_m3e-skeleton-wave-span)\r\n );\r\n\r\n opacity: var(--m3e-skeleton-accent-opacity, 0.06);\r\n }\r\n @media (forced-colors: active) {\r\n :host([loaded]) .shape {\r\n transition: none;\r\n }\r\n .shape::after {\r\n display: none;\r\n }\r\n .shape {\r\n background-color: GrayText;\r\n }\r\n }\r\n @media (prefers-reduced-motion) {\r\n :host([loaded]) .shape {\r\n transition: none;\r\n }\r\n .shape::after {\r\n display: none;\r\n }\r\n }\r\n `;\r\n\r\n /** @private */ readonly #anchoringCleanupMap = new Map<HTMLElement, () => void>();\r\n\r\n /** @private */ #animation: Animation | null = null;\r\n\r\n /** The animation mode `#animation` was created for, so mode changes recreate it. @private */\r\n #animationMode: SkeletonAnimation | null = null;\r\n\r\n /**\r\n * The shape of the skeleton.\r\n * @default \"auto\"\r\n */\r\n @property({ reflect: true }) shape: SkeletonShape = \"auto\";\r\n\r\n /**\r\n * The animation effect of the skeleton.\r\n * @default \"wave\"\r\n */\r\n @property({ reflect: true }) animation: SkeletonAnimation = \"wave\";\r\n\r\n /**\r\n * Whether the content of the skeleton has been loaded.\r\n * @default false\r\n */\r\n @property({ type: Boolean, reflect: true }) loaded = false;\r\n\r\n /** @inheritdoc */\r\n override disconnectedCallback(): void {\r\n super.disconnectedCallback();\r\n this.#clearShapes();\r\n this.#stopMotion();\r\n }\r\n\r\n /** @inheritdoc */\r\n override reconnectedCallback(): void {\r\n super.reconnectedCallback();\r\n this.#createShapes();\r\n this.#updateLoading();\r\n }\r\n\r\n /** @inheritdoc */\r\n protected override willUpdate(_changedProperties: PropertyValues<this>): void {\r\n super.willUpdate(_changedProperties);\r\n\r\n if (_changedProperties.has(\"loaded\") || _changedProperties.has(\"animation\")) {\r\n this.#updateLoading();\r\n }\r\n }\r\n\r\n /** @inheritdoc */\r\n protected override render(): unknown {\r\n return html`<slot ?inert=\"${!this.loaded}\" @slotchange=\"${this.#handleSlotChange}\"></slot>`;\r\n }\r\n\r\n /** @private */\r\n async #handleSlotChange(): Promise<void> {\r\n this.#createShapes();\r\n }\r\n\r\n /** @private */\r\n #clearShapes(): void {\r\n for (const item of this.#anchoringCleanupMap) {\r\n item[0].remove();\r\n item[1]();\r\n }\r\n this.#anchoringCleanupMap.clear();\r\n }\r\n\r\n /** @private */\r\n async #createShapes(): Promise<void> {\r\n this.#clearShapes();\r\n\r\n const slot = this.shadowRoot?.querySelector(\"slot\");\r\n if (!slot) return;\r\n\r\n for (const element of slot.assignedElements({ flatten: true }).filter((x) => x instanceof HTMLElement)) {\r\n await this.#createShape(element);\r\n }\r\n }\r\n\r\n /** @private */\r\n async #createShape(element: HTMLElement): Promise<void> {\r\n await waitForUpgrade(element);\r\n\r\n const shape = document.createElement(\"div\");\r\n shape.classList.add(\"shape\");\r\n\r\n if (this.shape === \"auto\") {\r\n let borderRadius = getComputedStyle(element).borderRadius;\r\n if (!borderRadius || borderRadius === \"0px\") {\r\n const firstElement = element.shadowRoot?.firstElementChild;\r\n if (firstElement && !firstElement.nextElementSibling) {\r\n borderRadius = getComputedStyle(firstElement).borderRadius;\r\n }\r\n }\r\n\r\n if (borderRadius && borderRadius !== \"0px\") {\r\n shape.style.borderRadius = borderRadius;\r\n }\r\n }\r\n\r\n const anchoringCleanup = await positionAnchor(\r\n shape,\r\n element,\r\n {\r\n position: \"bottom\",\r\n },\r\n (x, y) => {\r\n shape.style.left = `${x}px`;\r\n shape.style.top = `${y - element.clientHeight}px`;\r\n shape.style.width = `${element.clientWidth}px`;\r\n shape.style.height = `${element.clientHeight}px`;\r\n },\r\n );\r\n\r\n this.#anchoringCleanupMap.set(shape, anchoringCleanup);\r\n this.shadowRoot?.appendChild(shape);\r\n }\r\n\r\n /**\r\n * Starts or stops this skeleton's own wave/pulse animation to reflect its current\r\n * loaded/animation/connected state, then aligns its play/pause with the active\r\n * accessibility and forced-colors preferences.\r\n * @private\r\n */\r\n #updateLoading(): void {\r\n if (this.isConnected && !this.loaded && (this.animation === \"wave\" || this.animation === \"pulse\")) {\r\n this.#startMotion();\r\n } else {\r\n this.#stopMotion();\r\n }\r\n }\r\n\r\n /**\r\n * Starts the wave/pulse animation on this skeleton itself rather than on\r\n * `document.documentElement`. The `--_m3e-skeleton-*` properties are registered\r\n * `inherits: true`, so animating them on the document root recalculates style for the\r\n * whole document every frame; scoping to the instance limits that to its own subtree.\r\n * Aligned to a shared timeline origin so multiple skeletons animate in phase, and\r\n * re-created when the effect mode (wave vs pulse) changes.\r\n * @private\r\n */\r\n #startMotion(): void {\r\n if (this.#animation) {\r\n if (this.#animationMode === this.animation) {\r\n // Already running for the current mode; nothing to do but re-sync motion state.\r\n this.#syncMotionState();\r\n return;\r\n }\r\n // Effect mode changed (wave <-> pulse); tear down and recreate below.\r\n this.#stopMotion();\r\n }\r\n\r\n M3eSkeletonElement.__motionOrigin ??= (document.timeline.currentTime as number | null) ?? 0;\r\n\r\n const animation =\r\n this.animation === \"pulse\"\r\n ? this.animate(\r\n [\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 0 },\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 1 },\r\n { [\"--_m3e-skeleton-pulse-norm\"]: 0 },\r\n ],\r\n {\r\n duration: 1200,\r\n iterations: Infinity,\r\n easing: \"ease-in-out\",\r\n },\r\n )\r\n : this.animate([{ [\"--_m3e-skeleton-wave-pct\"]: 0 }, { [\"--_m3e-skeleton-wave-pct\"]: 1 }], {\r\n duration: 2100,\r\n iterations: Infinity,\r\n easing: \"linear\",\r\n });\r\n\r\n animation.startTime = M3eSkeletonElement.__motionOrigin;\r\n\r\n this.#animation = animation;\r\n this.#animationMode = this.animation;\r\n M3eSkeletonElement.__animating.add(this);\r\n this.#syncMotionState();\r\n }\r\n\r\n /** @private */\r\n #stopMotion(): void {\r\n if (!this.#animation) {\r\n return;\r\n }\r\n this.#animation.cancel();\r\n this.#animation = null;\r\n this.#animationMode = null;\r\n M3eSkeletonElement.__animating.delete(this);\r\n }\r\n\r\n /** Whether motion is currently suppressed for accessibility or forced-colors reasons. @private */\r\n private static __motionDisabled(): boolean {\r\n return M3eSkeletonElement.__reducedMediaQuery.matches || M3eSkeletonElement.__forcedColorsMediaQuery.matches;\r\n }\r\n\r\n /**\r\n * Re-applies the current motion preference to every animating skeleton. Invoked when\r\n * the reduced-motion or forced-colors preference changes.\r\n * @private\r\n */\r\n private static __updateMotion(): void {\r\n for (const skeleton of M3eSkeletonElement.__animating) {\r\n skeleton.#syncMotionState();\r\n }\r\n }\r\n\r\n /**\r\n * Aligns this skeleton's animation play state with the current reduced-motion and\r\n * forced-colors preferences.\r\n * @private\r\n */\r\n #syncMotionState(): void {\r\n if (!this.#animation) {\r\n return;\r\n }\r\n if (M3eSkeletonElement.__motionDisabled()) {\r\n this.#animation.pause();\r\n } else {\r\n this.#animation.play();\r\n }\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n \"m3e-skeleton\": M3eSkeletonElement;\r\n }\r\n}\r\n"],"names":["M3eSkeletonElement","ReconnectedCallback","LitElement","constructor","_M3eSkeletonElement_anchoringCleanupMap","set","this","Map","_M3eSkeletonElement_animation","_M3eSkeletonElement_animationMode","shape","animation","loaded","disconnectedCallback","super","__classPrivateFieldGet","_M3eSkeletonElement_instances","_M3eSkeletonElement_clearShapes","call","_M3eSkeletonElement_stopMotion","reconnectedCallback","_M3eSkeletonElement_createShapes","_M3eSkeletonElement_updateLoading","willUpdate","_changedProperties","has","render","html","_M3eSkeletonElement_handleSlotChange","__motionDisabled","M3eSkeletonElement_1","__reducedMediaQuery","matches","__forcedColorsMediaQuery","__updateMotion","skeleton","__animating","_M3eSkeletonElement_syncMotionState","async","item","remove","clear","slot","shadowRoot","querySelector","element","assignedElements","flatten","filter","x","HTMLElement","_M3eSkeletonElement_createShape","waitForUpgrade","document","createElement","classList","add","borderRadius","getComputedStyle","firstElement","firstElementChild","nextElementSibling","style","anchoringCleanup","positionAnchor","position","y","left","top","clientHeight","width","clientWidth","height","appendChild","isConnected","_M3eSkeletonElement_startMotion","__motionOrigin","timeline","currentTime","animate","duration","iterations","Infinity","easing","startTime","__classPrivateFieldSet","cancel","delete","pause","play","Set","window","registerStyleSheet","css","matchMedia","addEventListener","styles","DesignToken","color","surface","onSurface","unsafeCSS","motion","short3","standard","corner","large","full","surfaceDim","__decorate","property","reflect","prototype","type","Boolean","customElement"],"mappings":"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"}
|
package/dist/slide-group.js
CHANGED
|
@@ -192,7 +192,7 @@ _M3eSlideGroupElement_pageEnd = function _M3eSlideGroupElement_pageEnd() {
|
|
|
192
192
|
}
|
|
193
193
|
};
|
|
194
194
|
/** The styles of the element. */
|
|
195
|
-
M3eSlideGroupElement.styles = css`:host { display: flex; flex-wrap: nowrap; } :host([vertical]) { flex-direction: column; } .prev-button, .next-button { flex: none; --m3e-icon-button-small-shape-round: 0px; --m3e-icon-button-small-shape-square: 0px; --m3e-icon-button-small-shape-pressed-morph: 0px; --m3e-focus-ring-visibility: hidden; } ::slotted(prev-icon), ::slotted(next-icon), .icon { width: 1em; font-size: var(--m3e-slide-group-button-icon-size, var(--m3e-icon-button-small-icon-size, 1.5rem)) !important; } :host(:not([vertical])) .prev-button, :host(:not([vertical])) .next-button { --m3e-icon-button-small-container-height: 100%; width: var(--m3e-slide-group-button-size, 2.5rem); } :host([vertical]) .prev-button, :host([vertical]) .next-button { width: unset; --m3e-icon-button-small-container-height: var(--m3e-slide-group-button-size, 2.5rem); } :host([vertical]) .prev-button .icon, :host([vertical]) .next-button .icon { transform: rotate(90deg); } .content { flex: 1 1 auto; display: inherit; flex-wrap: inherit; flex-direction: inherit; position: relative; border-top: var(--m3e-slide-group-divider-top); border-bottom: var(--m3e-slide-group-divider-bottom); scrollbar-width: none; } .content::-webkit-scrollbar { display: none; } :host([vertical]) .content { overflow-x: hidden; overflow-y: auto; } :host(:not([vertical])) .content { overflow-x: auto; overflow-y: hidden; }`;
|
|
195
|
+
M3eSlideGroupElement.styles = css`:host { display: flex; flex-wrap: nowrap; } :host([vertical]) { flex-direction: column; } .prev-button, .next-button { flex: none; --m3e-icon-button-small-shape-round: 0px; --m3e-icon-button-small-shape-square: 0px; --m3e-icon-button-small-shape-pressed-morph: 0px; --m3e-focus-ring-visibility: hidden; } ::slotted(prev-icon), ::slotted(next-icon), .icon { width: 1em; font-size: var(--m3e-slide-group-button-icon-size, var(--m3e-icon-button-small-icon-size, 1.5rem)) !important; } :host(:not([vertical])) .prev-button, :host(:not([vertical])) .next-button { --m3e-icon-button-small-container-height: 100%; width: var(--m3e-slide-group-button-size, 2.5rem); } :host([vertical]) .prev-button, :host([vertical]) .next-button { width: unset; --m3e-icon-button-small-container-height: var(--m3e-slide-group-button-size, 2.5rem); } :host([vertical]) .prev-button .icon, :host([vertical]) .next-button .icon { transform: rotate(90deg); } .content { contain: layout style; flex: 1 1 auto; display: inherit; flex-wrap: inherit; flex-direction: inherit; position: relative; border-top: var(--m3e-slide-group-divider-top); border-bottom: var(--m3e-slide-group-divider-bottom); scrollbar-width: none; } .content::-webkit-scrollbar { display: none; } :host([vertical]) .content { overflow-x: hidden; overflow-y: auto; } :host(:not([vertical])) .content { overflow-x: auto; overflow-y: hidden; }`;
|
|
196
196
|
__decorate([query(".content")], M3eSlideGroupElement.prototype, "scrollContainer", void 0);
|
|
197
197
|
__decorate([state()], M3eSlideGroupElement.prototype, "_canPage", void 0);
|
|
198
198
|
__decorate([state()], M3eSlideGroupElement.prototype, "_canPageStart", void 0);
|
package/dist/slide-group.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slide-group.js","sources":["../../src/slide-group/SlideGroupElement.ts"],"sourcesContent":["import { css, CSSResultGroup, html, LitElement, nothing, PropertyValues } from \"lit\";\r\nimport { property, query, state } from \"lit/decorators.js\";\r\n\r\nimport { customElement, debounce, ReconnectedCallback, ResizeController } from \"@m3e/web/core\";\r\nimport { M3eDirectionality } from \"@m3e/web/core/bidi\";\r\n\r\nimport \"@m3e/web/icon-button\";\r\n\r\n/**\r\n * Presents pagination controls used to scroll overflowing content.\r\n *\r\n * @description\r\n * The `m3e-slide-group` component presents directional pagination controls for navigating overflowing content.\r\n * It orchestrates scrollable layouts with expressive slot-based icons and adaptive orientation, revealing navigation\r\n * affordances only when content exceeds a defined threshold. It supports both horizontal and vertical flows, and\r\n * encodes accessibility through customizable labels and interaction states.\r\n *\r\n * @example\r\n * The following example illustrates a horizontally scrollable group of items with directional pagination buttons.\r\n * The scroll controls appear when content exceeds the `48px` threshold.\r\n * ```html\r\n * <m3e-slide-group threshold=\"48\">\r\n * <div>Item 1</div>\r\n * <div>Item 2</div>\r\n * <div>Item 3</div>\r\n * <div>Item 4</div>\r\n * <div>Item 5</div>\r\n * </m3e-slide-group>\r\n * ```\r\n *\r\n * @tag m3e-slide-group\r\n *\r\n * @slot - Renders the content to paginate.\r\n * @slot next-icon - Renders the icon to present for the next button.\r\n * @slot prev-icon - Renders the icon to present for the previous button.\r\n *\r\n * @attr disabled - Whether scroll buttons are disabled.\r\n * @attr next-page-label - The accessible label given to the button used to move to the previous page.\r\n * @attr previous-page-label - The accessible label given to the button used to move to the next page.\r\n * @attr threshold - A value, in pixels, indicating the scroll threshold at which to begin showing pagination controls.\r\n * @attr vertical - Whether content is oriented vertically.\r\n *\r\n * @cssprop --m3e-slide-group-button-icon-size - Sets icon size for scroll buttons; overrides default small icon size.\r\n * @cssprop --m3e-slide-group-button-size - Defines scroll button size; used for width (horizontal) or height (vertical).\r\n * @cssprop --m3e-slide-group-divider-top - Adds top border to content container for visual separation.\r\n * @cssprop --m3e-slide-group-divider-bottom - Adds bottom border to content container for visual separation.\r\n */\r\n@customElement(\"m3e-slide-group\")\r\nexport class M3eSlideGroupElement extends ReconnectedCallback(LitElement) {\r\n /** The styles of the element. */\r\n static override styles: CSSResultGroup = css`\r\n :host {\r\n display: flex;\r\n flex-wrap: nowrap;\r\n }\r\n :host([vertical]) {\r\n flex-direction: column;\r\n }\r\n .prev-button,\r\n .next-button {\r\n flex: none;\r\n --m3e-icon-button-small-shape-round: 0px;\r\n --m3e-icon-button-small-shape-square: 0px;\r\n --m3e-icon-button-small-shape-pressed-morph: 0px;\r\n --m3e-focus-ring-visibility: hidden;\r\n }\r\n ::slotted(prev-icon),\r\n ::slotted(next-icon),\r\n .icon {\r\n width: 1em;\r\n font-size: var(--m3e-slide-group-button-icon-size, var(--m3e-icon-button-small-icon-size, 1.5rem)) !important;\r\n }\r\n :host(:not([vertical])) .prev-button,\r\n :host(:not([vertical])) .next-button {\r\n --m3e-icon-button-small-container-height: 100%;\r\n width: var(--m3e-slide-group-button-size, 2.5rem);\r\n }\r\n :host([vertical]) .prev-button,\r\n :host([vertical]) .next-button {\r\n width: unset;\r\n --m3e-icon-button-small-container-height: var(--m3e-slide-group-button-size, 2.5rem);\r\n }\r\n :host([vertical]) .prev-button .icon,\r\n :host([vertical]) .next-button .icon {\r\n transform: rotate(90deg);\r\n }\r\n .content {\r\n flex: 1 1 auto;\r\n display: inherit;\r\n flex-wrap: inherit;\r\n flex-direction: inherit;\r\n position: relative;\r\n border-top: var(--m3e-slide-group-divider-top);\r\n border-bottom: var(--m3e-slide-group-divider-bottom);\r\n scrollbar-width: none;\r\n }\r\n .content::-webkit-scrollbar {\r\n display: none;\r\n }\r\n :host([vertical]) .content {\r\n overflow-x: hidden;\r\n overflow-y: auto;\r\n }\r\n :host(:not([vertical])) .content {\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n }\r\n `;\r\n\r\n /** @private */ #directionalitySubscription?: () => void;\r\n\r\n /** @private */\r\n readonly #resizeController = new ResizeController(this, {\r\n target: null,\r\n callback: () => this._updatePaging(),\r\n });\r\n\r\n /** @internal A reference to the container used to scroll content. */\r\n @query(\".content\") scrollContainer!: HTMLElement;\r\n\r\n /** @private */ @state() private _canPage = false;\r\n /** @private */ @state() private _canPageStart = false;\r\n /** @private */ @state() private _canPageEnd = false;\r\n\r\n /**\r\n * Whether scroll buttons are disabled.\r\n * @default false\r\n */\r\n @property({ type: Boolean, reflect: true }) disabled = false;\r\n\r\n /**\r\n * Whether content is oriented vertically.\r\n * @default false\r\n */\r\n @property({ type: Boolean, reflect: true }) vertical = false;\r\n\r\n /**\r\n * A value, in pixels, indicating the scroll threshold at which to begin showing pagination controls.\r\n * @default 0\r\n */\r\n @property({ type: Number }) threshold = 0;\r\n\r\n /**\r\n * The accessible label given to the button used to move to the previous page.\r\n * @default \"Previous page\"\r\n */\r\n @property({ attribute: \"previous-page-label\" }) previousPageLabel = \"Previous page\";\r\n\r\n /**\r\n * The accessible label given to the button used to move to the next page.\r\n * @default \"Next page\"\r\n */\r\n @property({ attribute: \"next-page-label\" }) nextPageLabel = \"Next page\";\r\n\r\n /** @inheritdoc */\r\n override connectedCallback(): void {\r\n super.connectedCallback();\r\n this.#directionalitySubscription = M3eDirectionality.observe(() => this.requestUpdate());\r\n }\r\n\r\n /** @inheritdoc */\r\n override disconnectedCallback(): void {\r\n super.disconnectedCallback();\r\n this.#directionalitySubscription?.();\r\n }\r\n\r\n /** @inheritdoc */\r\n override reconnectedCallback(): void {\r\n super.reconnectedCallback();\r\n this.#resizeController.observe(this.scrollContainer);\r\n }\r\n\r\n /** @inheritdoc */\r\n protected override firstUpdated(_changedProperties: PropertyValues): void {\r\n super.firstUpdated(_changedProperties);\r\n this.#resizeController.observe(this.scrollContainer);\r\n }\r\n\r\n /** @inheritdoc */\r\n protected override render(): unknown {\r\n const prevButton = html`<m3e-icon-button\r\n class=\"prev-button\"\r\n tabindex=\"-1\"\r\n aria-label=\"${this.previousPageLabel}\"\r\n ?disabled=\"${!this._canPageStart}\"\r\n @click=\"${this.#pageStart}\"\r\n >\r\n <slot name=\"prev-icon\">\r\n ${M3eDirectionality.current === \"ltr\" || this.vertical\r\n ? html`<svg class=\"icon\" viewBox=\"0 -960 960 960\" fill=\"currentColor\">\r\n <path d=\"M640-80 240-480l400-400 71 71-329 329 329 329-71 71Z\" />\r\n </svg>`\r\n : html`<svg class=\"icon\" viewBox=\"0 -960 960 960\" fill=\"currentColor\">\r\n <path d=\"m321-80-71-71 329-329-329-329 71-71 400 400L321-80Z\" />\r\n </svg>`}\r\n </slot>\r\n </m3e-icon-button>`;\r\n\r\n const nextButton = html`<m3e-icon-button\r\n class=\"next-button\"\r\n tabindex=\"-1\"\r\n aria-label=\"${this.nextPageLabel}\"\r\n ?disabled=\"${!this._canPageEnd}\"\r\n @click=\"${this.#pageEnd}\"\r\n >\r\n <slot name=\"next-icon\">\r\n ${M3eDirectionality.current === \"ltr\" || this.vertical\r\n ? html`<svg class=\"icon\" viewBox=\"0 -960 960 960\" fill=\"currentColor\">\r\n <path d=\"m321-80-71-71 329-329-329-329 71-71 400 400L321-80Z\" />\r\n </svg>`\r\n : html`<svg class=\"icon\" viewBox=\"0 -960 960 960\" fill=\"currentColor\">\r\n <path d=\"M640-80 240-480l400-400 71 71-329 329 329 329-71 71Z\" />\r\n </svg>`}\r\n </slot>\r\n </m3e-icon-button>`;\r\n\r\n return html`${this._canPage ? prevButton : nothing}\r\n <div class=\"content\" @scroll=\"${this._updatePaging}\"><slot></slot></div>\r\n ${this._canPage ? nextButton : nothing}`;\r\n }\r\n\r\n /** @private */\r\n #pageStart(): void {\r\n if (!this.vertical) {\r\n let left = this.scrollContainer.scrollLeft - this.scrollContainer.clientWidth;\r\n if (left <= this.threshold) {\r\n left = 0;\r\n }\r\n this.scrollContainer.scrollTo({ left, behavior: \"smooth\" });\r\n } else {\r\n let top = this.scrollContainer.scrollTop - this.scrollContainer.clientHeight;\r\n if (top <= this.threshold) {\r\n top = 0;\r\n }\r\n this.scrollContainer.scrollTo({ top, behavior: \"smooth\" });\r\n }\r\n }\r\n\r\n /** @private */\r\n #pageEnd(): void {\r\n if (!this.vertical) {\r\n let left = this.scrollContainer.scrollLeft + this.scrollContainer.clientWidth;\r\n if (left >= this.scrollContainer.scrollWidth - this.scrollContainer.clientWidth - this.threshold) {\r\n left = this.scrollContainer.scrollWidth - this.scrollContainer.clientWidth;\r\n }\r\n this.scrollContainer.scrollTo({ left, behavior: \"smooth\" });\r\n } else {\r\n let top = this.scrollContainer.scrollTop + this.scrollContainer.clientHeight;\r\n if (top >= this.scrollContainer.scrollHeight - this.scrollContainer.clientHeight - this.threshold) {\r\n top = this.scrollContainer.scrollHeight - this.scrollContainer.clientHeight;\r\n }\r\n this.scrollContainer.scrollTo({ top, behavior: \"smooth\" });\r\n }\r\n }\r\n\r\n /** @private */\r\n @debounce(40)\r\n private _updatePaging(): void {\r\n const canPage = this._canPage;\r\n if (this.disabled) {\r\n this._canPage = false;\r\n } else if (!this.vertical) {\r\n this._canPage =\r\n Math.round(this.scrollContainer.scrollWidth) > Math.round(this.scrollContainer.clientWidth) + this.threshold;\r\n if (this._canPage) {\r\n this._canPageStart = Math.round(this.scrollContainer.scrollLeft) > this.threshold;\r\n this._canPageEnd =\r\n Math.round(this.scrollContainer.scrollLeft) + this.threshold <\r\n Math.round(this.scrollContainer.scrollWidth - this.scrollContainer.clientWidth);\r\n }\r\n } else {\r\n this._canPage =\r\n Math.round(this.scrollContainer.scrollHeight) > Math.round(this.scrollContainer.clientHeight) + this.threshold;\r\n if (this._canPage) {\r\n this._canPageStart = Math.round(this.scrollContainer.scrollTop) > this.threshold;\r\n this._canPageEnd =\r\n Math.round(this.scrollContainer.scrollTop) + +this.threshold <\r\n Math.round(this.scrollContainer.scrollHeight - this.scrollContainer.clientHeight);\r\n }\r\n }\r\n\r\n if (!this._canPage) {\r\n this._canPageStart = this._canPageEnd = false;\r\n }\r\n\r\n if (canPage != this._canPage) {\r\n // Emit internal (undocumented) event for use with tabs.\r\n this[\"dispatchEvent\"](new CustomEvent(\"pagination-changed\"));\r\n }\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n \"m3e-slide-group\": M3eSlideGroupElement;\r\n }\r\n}\r\n"],"names":["M3eSlideGroupElement","ReconnectedCallback","LitElement","constructor","_M3eSlideGroupElement_directionalitySubscription","set","_M3eSlideGroupElement_resizeController","ResizeController","target","callback","_updatePaging","_canPage","_canPageStart","_canPageEnd","disabled","vertical","threshold","previousPageLabel","nextPageLabel","connectedCallback","__classPrivateFieldSet","M3eDirectionality","observe","requestUpdate","disconnectedCallback","__classPrivateFieldGet","call","reconnectedCallback","scrollContainer","firstUpdated","_changedProperties","render","prevButton","html","_M3eSlideGroupElement_instances","_M3eSlideGroupElement_pageStart","current","nextButton","_M3eSlideGroupElement_pageEnd","nothing","canPage","Math","round","scrollWidth","clientWidth","scrollLeft","scrollHeight","clientHeight","scrollTop","CustomEvent","left","scrollTo","behavior","top","styles","css","__decorate","query","prototype","state","property","type","Boolean","reflect","Number","attribute","debounce","customElement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"slide-group.js","sources":["../../src/slide-group/SlideGroupElement.ts"],"sourcesContent":["import { css, CSSResultGroup, html, LitElement, nothing, PropertyValues } from \"lit\";\r\nimport { property, query, state } from \"lit/decorators.js\";\r\n\r\nimport { customElement, debounce, ReconnectedCallback, ResizeController } from \"@m3e/web/core\";\r\nimport { M3eDirectionality } from \"@m3e/web/core/bidi\";\r\n\r\nimport \"@m3e/web/icon-button\";\r\n\r\n/**\r\n * Presents pagination controls used to scroll overflowing content.\r\n *\r\n * @description\r\n * The `m3e-slide-group` component presents directional pagination controls for navigating overflowing content.\r\n * It orchestrates scrollable layouts with expressive slot-based icons and adaptive orientation, revealing navigation\r\n * affordances only when content exceeds a defined threshold. It supports both horizontal and vertical flows, and\r\n * encodes accessibility through customizable labels and interaction states.\r\n *\r\n * @example\r\n * The following example illustrates a horizontally scrollable group of items with directional pagination buttons.\r\n * The scroll controls appear when content exceeds the `48px` threshold.\r\n * ```html\r\n * <m3e-slide-group threshold=\"48\">\r\n * <div>Item 1</div>\r\n * <div>Item 2</div>\r\n * <div>Item 3</div>\r\n * <div>Item 4</div>\r\n * <div>Item 5</div>\r\n * </m3e-slide-group>\r\n * ```\r\n *\r\n * @tag m3e-slide-group\r\n *\r\n * @slot - Renders the content to paginate.\r\n * @slot next-icon - Renders the icon to present for the next button.\r\n * @slot prev-icon - Renders the icon to present for the previous button.\r\n *\r\n * @attr disabled - Whether scroll buttons are disabled.\r\n * @attr next-page-label - The accessible label given to the button used to move to the previous page.\r\n * @attr previous-page-label - The accessible label given to the button used to move to the next page.\r\n * @attr threshold - A value, in pixels, indicating the scroll threshold at which to begin showing pagination controls.\r\n * @attr vertical - Whether content is oriented vertically.\r\n *\r\n * @cssprop --m3e-slide-group-button-icon-size - Sets icon size for scroll buttons; overrides default small icon size.\r\n * @cssprop --m3e-slide-group-button-size - Defines scroll button size; used for width (horizontal) or height (vertical).\r\n * @cssprop --m3e-slide-group-divider-top - Adds top border to content container for visual separation.\r\n * @cssprop --m3e-slide-group-divider-bottom - Adds bottom border to content container for visual separation.\r\n */\r\n@customElement(\"m3e-slide-group\")\r\nexport class M3eSlideGroupElement extends ReconnectedCallback(LitElement) {\r\n /** The styles of the element. */\r\n static override styles: CSSResultGroup = css`\r\n :host {\r\n display: flex;\r\n flex-wrap: nowrap;\r\n }\r\n :host([vertical]) {\r\n flex-direction: column;\r\n }\r\n .prev-button,\r\n .next-button {\r\n flex: none;\r\n --m3e-icon-button-small-shape-round: 0px;\r\n --m3e-icon-button-small-shape-square: 0px;\r\n --m3e-icon-button-small-shape-pressed-morph: 0px;\r\n --m3e-focus-ring-visibility: hidden;\r\n }\r\n ::slotted(prev-icon),\r\n ::slotted(next-icon),\r\n .icon {\r\n width: 1em;\r\n font-size: var(--m3e-slide-group-button-icon-size, var(--m3e-icon-button-small-icon-size, 1.5rem)) !important;\r\n }\r\n :host(:not([vertical])) .prev-button,\r\n :host(:not([vertical])) .next-button {\r\n --m3e-icon-button-small-container-height: 100%;\r\n width: var(--m3e-slide-group-button-size, 2.5rem);\r\n }\r\n :host([vertical]) .prev-button,\r\n :host([vertical]) .next-button {\r\n width: unset;\r\n --m3e-icon-button-small-container-height: var(--m3e-slide-group-button-size, 2.5rem);\r\n }\r\n :host([vertical]) .prev-button .icon,\r\n :host([vertical]) .next-button .icon {\r\n transform: rotate(90deg);\r\n }\r\n .content {\r\n contain: layout style;\r\n flex: 1 1 auto;\r\n display: inherit;\r\n flex-wrap: inherit;\r\n flex-direction: inherit;\r\n position: relative;\r\n border-top: var(--m3e-slide-group-divider-top);\r\n border-bottom: var(--m3e-slide-group-divider-bottom);\r\n scrollbar-width: none;\r\n }\r\n .content::-webkit-scrollbar {\r\n display: none;\r\n }\r\n :host([vertical]) .content {\r\n overflow-x: hidden;\r\n overflow-y: auto;\r\n }\r\n :host(:not([vertical])) .content {\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n }\r\n `;\r\n\r\n /** @private */ #directionalitySubscription?: () => void;\r\n\r\n /** @private */\r\n readonly #resizeController = new ResizeController(this, {\r\n target: null,\r\n callback: () => this._updatePaging(),\r\n });\r\n\r\n /** @internal A reference to the container used to scroll content. */\r\n @query(\".content\") scrollContainer!: HTMLElement;\r\n\r\n /** @private */ @state() private _canPage = false;\r\n /** @private */ @state() private _canPageStart = false;\r\n /** @private */ @state() private _canPageEnd = false;\r\n\r\n /**\r\n * Whether scroll buttons are disabled.\r\n * @default false\r\n */\r\n @property({ type: Boolean, reflect: true }) disabled = false;\r\n\r\n /**\r\n * Whether content is oriented vertically.\r\n * @default false\r\n */\r\n @property({ type: Boolean, reflect: true }) vertical = false;\r\n\r\n /**\r\n * A value, in pixels, indicating the scroll threshold at which to begin showing pagination controls.\r\n * @default 0\r\n */\r\n @property({ type: Number }) threshold = 0;\r\n\r\n /**\r\n * The accessible label given to the button used to move to the previous page.\r\n * @default \"Previous page\"\r\n */\r\n @property({ attribute: \"previous-page-label\" }) previousPageLabel = \"Previous page\";\r\n\r\n /**\r\n * The accessible label given to the button used to move to the next page.\r\n * @default \"Next page\"\r\n */\r\n @property({ attribute: \"next-page-label\" }) nextPageLabel = \"Next page\";\r\n\r\n /** @inheritdoc */\r\n override connectedCallback(): void {\r\n super.connectedCallback();\r\n this.#directionalitySubscription = M3eDirectionality.observe(() => this.requestUpdate());\r\n }\r\n\r\n /** @inheritdoc */\r\n override disconnectedCallback(): void {\r\n super.disconnectedCallback();\r\n this.#directionalitySubscription?.();\r\n }\r\n\r\n /** @inheritdoc */\r\n override reconnectedCallback(): void {\r\n super.reconnectedCallback();\r\n this.#resizeController.observe(this.scrollContainer);\r\n }\r\n\r\n /** @inheritdoc */\r\n protected override firstUpdated(_changedProperties: PropertyValues): void {\r\n super.firstUpdated(_changedProperties);\r\n this.#resizeController.observe(this.scrollContainer);\r\n }\r\n\r\n /** @inheritdoc */\r\n protected override render(): unknown {\r\n const prevButton = html`<m3e-icon-button\r\n class=\"prev-button\"\r\n tabindex=\"-1\"\r\n aria-label=\"${this.previousPageLabel}\"\r\n ?disabled=\"${!this._canPageStart}\"\r\n @click=\"${this.#pageStart}\"\r\n >\r\n <slot name=\"prev-icon\">\r\n ${M3eDirectionality.current === \"ltr\" || this.vertical\r\n ? html`<svg class=\"icon\" viewBox=\"0 -960 960 960\" fill=\"currentColor\">\r\n <path d=\"M640-80 240-480l400-400 71 71-329 329 329 329-71 71Z\" />\r\n </svg>`\r\n : html`<svg class=\"icon\" viewBox=\"0 -960 960 960\" fill=\"currentColor\">\r\n <path d=\"m321-80-71-71 329-329-329-329 71-71 400 400L321-80Z\" />\r\n </svg>`}\r\n </slot>\r\n </m3e-icon-button>`;\r\n\r\n const nextButton = html`<m3e-icon-button\r\n class=\"next-button\"\r\n tabindex=\"-1\"\r\n aria-label=\"${this.nextPageLabel}\"\r\n ?disabled=\"${!this._canPageEnd}\"\r\n @click=\"${this.#pageEnd}\"\r\n >\r\n <slot name=\"next-icon\">\r\n ${M3eDirectionality.current === \"ltr\" || this.vertical\r\n ? html`<svg class=\"icon\" viewBox=\"0 -960 960 960\" fill=\"currentColor\">\r\n <path d=\"m321-80-71-71 329-329-329-329 71-71 400 400L321-80Z\" />\r\n </svg>`\r\n : html`<svg class=\"icon\" viewBox=\"0 -960 960 960\" fill=\"currentColor\">\r\n <path d=\"M640-80 240-480l400-400 71 71-329 329 329 329-71 71Z\" />\r\n </svg>`}\r\n </slot>\r\n </m3e-icon-button>`;\r\n\r\n return html`${this._canPage ? prevButton : nothing}\r\n <div class=\"content\" @scroll=\"${this._updatePaging}\"><slot></slot></div>\r\n ${this._canPage ? nextButton : nothing}`;\r\n }\r\n\r\n /** @private */\r\n #pageStart(): void {\r\n if (!this.vertical) {\r\n let left = this.scrollContainer.scrollLeft - this.scrollContainer.clientWidth;\r\n if (left <= this.threshold) {\r\n left = 0;\r\n }\r\n this.scrollContainer.scrollTo({ left, behavior: \"smooth\" });\r\n } else {\r\n let top = this.scrollContainer.scrollTop - this.scrollContainer.clientHeight;\r\n if (top <= this.threshold) {\r\n top = 0;\r\n }\r\n this.scrollContainer.scrollTo({ top, behavior: \"smooth\" });\r\n }\r\n }\r\n\r\n /** @private */\r\n #pageEnd(): void {\r\n if (!this.vertical) {\r\n let left = this.scrollContainer.scrollLeft + this.scrollContainer.clientWidth;\r\n if (left >= this.scrollContainer.scrollWidth - this.scrollContainer.clientWidth - this.threshold) {\r\n left = this.scrollContainer.scrollWidth - this.scrollContainer.clientWidth;\r\n }\r\n this.scrollContainer.scrollTo({ left, behavior: \"smooth\" });\r\n } else {\r\n let top = this.scrollContainer.scrollTop + this.scrollContainer.clientHeight;\r\n if (top >= this.scrollContainer.scrollHeight - this.scrollContainer.clientHeight - this.threshold) {\r\n top = this.scrollContainer.scrollHeight - this.scrollContainer.clientHeight;\r\n }\r\n this.scrollContainer.scrollTo({ top, behavior: \"smooth\" });\r\n }\r\n }\r\n\r\n /** @private */\r\n @debounce(40)\r\n private _updatePaging(): void {\r\n const canPage = this._canPage;\r\n if (this.disabled) {\r\n this._canPage = false;\r\n } else if (!this.vertical) {\r\n this._canPage =\r\n Math.round(this.scrollContainer.scrollWidth) > Math.round(this.scrollContainer.clientWidth) + this.threshold;\r\n if (this._canPage) {\r\n this._canPageStart = Math.round(this.scrollContainer.scrollLeft) > this.threshold;\r\n this._canPageEnd =\r\n Math.round(this.scrollContainer.scrollLeft) + this.threshold <\r\n Math.round(this.scrollContainer.scrollWidth - this.scrollContainer.clientWidth);\r\n }\r\n } else {\r\n this._canPage =\r\n Math.round(this.scrollContainer.scrollHeight) > Math.round(this.scrollContainer.clientHeight) + this.threshold;\r\n if (this._canPage) {\r\n this._canPageStart = Math.round(this.scrollContainer.scrollTop) > this.threshold;\r\n this._canPageEnd =\r\n Math.round(this.scrollContainer.scrollTop) + +this.threshold <\r\n Math.round(this.scrollContainer.scrollHeight - this.scrollContainer.clientHeight);\r\n }\r\n }\r\n\r\n if (!this._canPage) {\r\n this._canPageStart = this._canPageEnd = false;\r\n }\r\n\r\n if (canPage != this._canPage) {\r\n // Emit internal (undocumented) event for use with tabs.\r\n this[\"dispatchEvent\"](new CustomEvent(\"pagination-changed\"));\r\n }\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n \"m3e-slide-group\": M3eSlideGroupElement;\r\n }\r\n}\r\n"],"names":["M3eSlideGroupElement","ReconnectedCallback","LitElement","constructor","_M3eSlideGroupElement_directionalitySubscription","set","_M3eSlideGroupElement_resizeController","ResizeController","target","callback","_updatePaging","_canPage","_canPageStart","_canPageEnd","disabled","vertical","threshold","previousPageLabel","nextPageLabel","connectedCallback","__classPrivateFieldSet","M3eDirectionality","observe","requestUpdate","disconnectedCallback","__classPrivateFieldGet","call","reconnectedCallback","scrollContainer","firstUpdated","_changedProperties","render","prevButton","html","_M3eSlideGroupElement_instances","_M3eSlideGroupElement_pageStart","current","nextButton","_M3eSlideGroupElement_pageEnd","nothing","canPage","Math","round","scrollWidth","clientWidth","scrollLeft","scrollHeight","clientHeight","scrollTop","CustomEvent","left","scrollTo","behavior","top","styles","css","__decorate","query","prototype","state","property","type","Boolean","reflect","Number","attribute","debounce","customElement"],"mappings":"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"}
|