@expressivecss/expressive 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/css/expressive.css +1088 -356
- package/dist/css/expressive.css.map +1 -1
- package/dist/css/expressive.min.css +1 -1
- package/dist/css/expressive.min.css.map +1 -1
- package/dist/js/expressive.cjs +778 -746
- package/dist/js/expressive.cjs.map +4 -4
- package/dist/js/expressive.js +778 -746
- package/dist/js/expressive.js.map +4 -4
- package/dist/js/expressive.min.js +10 -10
- package/dist/js/expressive.min.js.map +4 -4
- package/dist/js/expressive.mjs +778 -746
- package/dist/js/expressive.mjs.map +4 -4
- package/dist/types/behaviors/dialogs.d.ts +25 -0
- package/dist/types/components/buttons.d.ts +17 -41
- package/dist/types/components/carousel.d.ts +40 -46
- package/dist/types/components/chips.d.ts +2 -2
- package/dist/types/components/collapsible.d.ts +35 -13
- package/dist/types/components/parallax.d.ts +7 -31
- package/dist/types/components/tapTarget.d.ts +23 -24
- package/dist/types/index.d.ts +2 -1
- package/package.json +1 -1
- package/src/sass/README.md +4 -3
- package/src/sass/components/_badges.scss +5 -4
- package/src/sass/components/_breadcrumb.scss +93 -16
- package/src/sass/components/_buttons.scss +195 -96
- package/src/sass/components/_carousel.scss +130 -63
- package/src/sass/components/_chips.scss +1 -1
- package/src/sass/components/_collapsible.scss +160 -60
- package/src/sass/components/_collection.scss +161 -77
- package/src/sass/components/_icons-material-design.scss +77 -4
- package/src/sass/components/_lightbox.scss +4 -0
- package/src/sass/components/_modal.scss +67 -3
- package/src/sass/components/_navbar.scss +15 -0
- package/src/sass/components/_pagination.scss +131 -25
- package/src/sass/components/_parallax.scss +116 -20
- package/src/sass/components/_sidenav.scss +10 -5
- package/src/sass/components/_slider.scss +8 -0
- package/src/sass/components/_tapTarget.scss +134 -47
- package/src/sass/utilities/_helpers.scss +10 -0
package/dist/js/expressive.cjs
CHANGED
|
@@ -33,6 +33,7 @@ __export(index_exports, {
|
|
|
33
33
|
Chips: () => Chips,
|
|
34
34
|
Collapsible: () => Collapsible,
|
|
35
35
|
Datepicker: () => Datepicker,
|
|
36
|
+
Dialogs: () => Dialogs,
|
|
36
37
|
Dropdown: () => Dropdown,
|
|
37
38
|
FloatingActionButton: () => FloatingActionButton,
|
|
38
39
|
FormSelect: () => FormSelect,
|
|
@@ -1475,7 +1476,7 @@ var _defaults4 = {
|
|
|
1475
1476
|
data: [],
|
|
1476
1477
|
placeholder: "",
|
|
1477
1478
|
secondaryPlaceholder: "",
|
|
1478
|
-
closeIconClass: "material-
|
|
1479
|
+
closeIconClass: "material-symbols",
|
|
1479
1480
|
autocompleteOptions: {},
|
|
1480
1481
|
autocompleteOnly: false,
|
|
1481
1482
|
limit: Infinity,
|
|
@@ -1892,6 +1893,74 @@ var Range = class _Range extends Component {
|
|
|
1892
1893
|
}
|
|
1893
1894
|
};
|
|
1894
1895
|
|
|
1896
|
+
// src/ts/behaviors/dialogs.ts
|
|
1897
|
+
var _Dialogs = class _Dialogs {
|
|
1898
|
+
static Init() {
|
|
1899
|
+
Utils.onDocumentReady(() => {
|
|
1900
|
+
document.addEventListener("pointerdown", _Dialogs._onPointerDown, { passive: true });
|
|
1901
|
+
document.addEventListener("pointerup", _Dialogs._onPointerUp, { passive: true });
|
|
1902
|
+
document.addEventListener("pointercancel", _Dialogs._onPointerCancel, { passive: true });
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
static _onPointerDown(event) {
|
|
1906
|
+
if (!_Dialogs._isPrimaryPress(event)) {
|
|
1907
|
+
_Dialogs._down = null;
|
|
1908
|
+
return;
|
|
1909
|
+
}
|
|
1910
|
+
const dialog = _Dialogs._backdropDialog(event);
|
|
1911
|
+
if (!dialog || !_Dialogs._lightDismissible(dialog) || !_Dialogs._outside(event, dialog)) {
|
|
1912
|
+
_Dialogs._down = null;
|
|
1913
|
+
return;
|
|
1914
|
+
}
|
|
1915
|
+
_Dialogs._down = { dialog, pointerId: event.pointerId };
|
|
1916
|
+
}
|
|
1917
|
+
static _onPointerUp(event) {
|
|
1918
|
+
const started = _Dialogs._down;
|
|
1919
|
+
_Dialogs._down = null;
|
|
1920
|
+
if (!started || started.pointerId !== event.pointerId) return;
|
|
1921
|
+
if (!event.isPrimary) return;
|
|
1922
|
+
if (!started.dialog.isConnected || !started.dialog.open) return;
|
|
1923
|
+
if (!_Dialogs._lightDismissible(started.dialog)) return;
|
|
1924
|
+
if (_Dialogs._backdropDialog(event) !== started.dialog) return;
|
|
1925
|
+
if (_Dialogs._outside(event, started.dialog)) {
|
|
1926
|
+
started.dialog.close();
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
static _onPointerCancel() {
|
|
1930
|
+
_Dialogs._down = null;
|
|
1931
|
+
}
|
|
1932
|
+
/** Backdrop hits retarget to the dialog itself, never a child. */
|
|
1933
|
+
static _backdropDialog(event) {
|
|
1934
|
+
const target = event.target;
|
|
1935
|
+
if (!(target instanceof HTMLDialogElement) || !target.open) return null;
|
|
1936
|
+
return target;
|
|
1937
|
+
}
|
|
1938
|
+
static _outside(event, dialog) {
|
|
1939
|
+
const rect = dialog.getBoundingClientRect();
|
|
1940
|
+
return event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom;
|
|
1941
|
+
}
|
|
1942
|
+
static _isPrimaryPress(event) {
|
|
1943
|
+
if (!event.isPrimary) return false;
|
|
1944
|
+
return event.pointerType !== "mouse" || event.button === 0;
|
|
1945
|
+
}
|
|
1946
|
+
static _lightDismissible(dialog) {
|
|
1947
|
+
const value = _Dialogs._closedBy(dialog);
|
|
1948
|
+
if (value === "none" || value === "closerequest") return false;
|
|
1949
|
+
if (value === "any" && "closedBy" in HTMLDialogElement.prototype) return false;
|
|
1950
|
+
return true;
|
|
1951
|
+
}
|
|
1952
|
+
// Read the attribute only. The IDL default for an unset closedby is
|
|
1953
|
+
// "closerequest" (Escape, no light dismiss) — treating that as an
|
|
1954
|
+
// author opt-out made every dialog undismissable from the scrim.
|
|
1955
|
+
static _closedBy(dialog) {
|
|
1956
|
+
const attr = dialog.getAttribute("closedby");
|
|
1957
|
+
if (attr === "any" || attr === "closerequest" || attr === "none") return attr;
|
|
1958
|
+
return null;
|
|
1959
|
+
}
|
|
1960
|
+
};
|
|
1961
|
+
_Dialogs._down = null;
|
|
1962
|
+
var Dialogs = _Dialogs;
|
|
1963
|
+
|
|
1895
1964
|
// src/ts/behaviors/forms.ts
|
|
1896
1965
|
var Forms = class _Forms {
|
|
1897
1966
|
/**
|
|
@@ -2046,83 +2115,76 @@ var _defaults6 = {
|
|
|
2046
2115
|
var FloatingActionButton = class _FloatingActionButton extends Component {
|
|
2047
2116
|
constructor(el, options) {
|
|
2048
2117
|
super(el, options, _FloatingActionButton);
|
|
2049
|
-
/** Toolbar-mode backdrop, kept so closing can take it back out. */
|
|
2050
|
-
this._backdrop = null;
|
|
2051
|
-
this._handleFABClick = () => {
|
|
2052
|
-
this._handleFABToggle();
|
|
2053
|
-
};
|
|
2054
|
-
this._handleFABKeyPress = (e) => {
|
|
2055
|
-
if (Utils.keys.ENTER.includes(e.key)) {
|
|
2056
|
-
this._handleFABToggle();
|
|
2057
|
-
}
|
|
2058
|
-
};
|
|
2059
|
-
this._handleFABToggle = () => {
|
|
2060
|
-
if (this.isOpen) {
|
|
2061
|
-
this.close();
|
|
2062
|
-
} else {
|
|
2063
|
-
this.open();
|
|
2064
|
-
}
|
|
2065
|
-
};
|
|
2066
|
-
this._handleDocumentClick = (e) => {
|
|
2067
|
-
const elem = e.target;
|
|
2068
|
-
if (elem !== this._menu) this.close();
|
|
2069
|
-
};
|
|
2070
2118
|
/**
|
|
2071
2119
|
* Open FAB.
|
|
2072
2120
|
*/
|
|
2073
2121
|
this.open = () => {
|
|
2074
2122
|
if (this.isOpen) return;
|
|
2075
|
-
if (this.options.toolbarEnabled) this._animateInToolbar();
|
|
2076
|
-
else this._animateInFAB();
|
|
2077
2123
|
this.isOpen = true;
|
|
2124
|
+
this.el.classList.add("active");
|
|
2125
|
+
this._anchor?.setAttribute("aria-expanded", "true");
|
|
2126
|
+
document.addEventListener("click", this._handleDocumentClick);
|
|
2127
|
+
document.addEventListener("keydown", this._handleDocumentKeydown);
|
|
2078
2128
|
};
|
|
2079
2129
|
/**
|
|
2080
2130
|
* Close FAB.
|
|
2081
2131
|
*/
|
|
2082
2132
|
this.close = () => {
|
|
2083
2133
|
if (!this.isOpen) return;
|
|
2084
|
-
if (this.options.toolbarEnabled) {
|
|
2085
|
-
window.removeEventListener("scroll", this.close, true);
|
|
2086
|
-
document.body.removeEventListener("click", this._handleDocumentClick, true);
|
|
2087
|
-
this._animateOutToolbar();
|
|
2088
|
-
} else {
|
|
2089
|
-
this._animateOutFAB();
|
|
2090
|
-
}
|
|
2091
2134
|
this.isOpen = false;
|
|
2135
|
+
this.el.classList.remove("active");
|
|
2136
|
+
this._anchor?.setAttribute("aria-expanded", "false");
|
|
2137
|
+
document.removeEventListener("click", this._handleDocumentClick);
|
|
2138
|
+
document.removeEventListener("keydown", this._handleDocumentKeydown);
|
|
2139
|
+
};
|
|
2140
|
+
this._handleFABClick = (e) => {
|
|
2141
|
+
e.stopPropagation();
|
|
2142
|
+
this._toggle();
|
|
2143
|
+
};
|
|
2144
|
+
this._handleAnchorKeydown = (e) => {
|
|
2145
|
+
if (Utils.keys.ENTER.includes(e.key) || e.key === " ") {
|
|
2146
|
+
e.preventDefault();
|
|
2147
|
+
this._toggle();
|
|
2148
|
+
}
|
|
2149
|
+
};
|
|
2150
|
+
this._handleDocumentKeydown = (e) => {
|
|
2151
|
+
if (Utils.keys.ESC.includes(e.key)) this.close();
|
|
2152
|
+
};
|
|
2153
|
+
this._handleDocumentClick = (e) => {
|
|
2154
|
+
const target = e.target;
|
|
2155
|
+
if (!(target instanceof Node) || this.el.contains(target)) return;
|
|
2156
|
+
this.close();
|
|
2092
2157
|
};
|
|
2093
2158
|
this.el["Expressive_FloatingActionButton"] = this;
|
|
2159
|
+
const fromMarkup = this._directionFromClass();
|
|
2160
|
+
const toolbar = el.classList.contains("toolbar") || options.toolbarEnabled === true;
|
|
2161
|
+
const clickToToggle = el.classList.contains("click-to-toggle") || options.hoverEnabled === false;
|
|
2094
2162
|
this.options = {
|
|
2095
2163
|
..._FloatingActionButton.defaults,
|
|
2096
|
-
...options
|
|
2164
|
+
...options,
|
|
2165
|
+
direction: options.direction ?? fromMarkup ?? _FloatingActionButton.defaults.direction,
|
|
2166
|
+
hoverEnabled: !clickToToggle,
|
|
2167
|
+
toolbarEnabled: toolbar
|
|
2097
2168
|
};
|
|
2098
2169
|
this.isOpen = false;
|
|
2099
|
-
this._anchor = this.el.querySelector("a, button");
|
|
2100
|
-
this._menu = this.el.querySelector("ul");
|
|
2101
|
-
this._floatingBtns = Array.from(this.el.querySelectorAll("ul .btn-floating"));
|
|
2102
|
-
this._floatingBtnsReverse = this._floatingBtns.reverse();
|
|
2103
|
-
this.offsetY = 0;
|
|
2104
|
-
this.offsetX = 0;
|
|
2170
|
+
this._anchor = this.el.querySelector(":scope > a, :scope > button");
|
|
2171
|
+
this._menu = this.el.querySelector("ul, menu");
|
|
2105
2172
|
this.el.classList.add(`direction-${this.options.direction}`);
|
|
2106
|
-
if (
|
|
2107
|
-
if (
|
|
2108
|
-
if (this.
|
|
2109
|
-
this.
|
|
2110
|
-
|
|
2111
|
-
this.
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2173
|
+
if (clickToToggle) this.el.classList.add("click-to-toggle");
|
|
2174
|
+
if (toolbar) this.el.classList.add("toolbar");
|
|
2175
|
+
if (this._anchor) {
|
|
2176
|
+
this._anchor.setAttribute("aria-haspopup", "menu");
|
|
2177
|
+
this._anchor.setAttribute("aria-expanded", "false");
|
|
2178
|
+
if (this._anchor instanceof HTMLAnchorElement && !this._anchor.hasAttribute("href") && this._anchor.tabIndex < 0) {
|
|
2179
|
+
this._anchor.tabIndex = 0;
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
if (this._menu) this._menu.setAttribute("role", "menu");
|
|
2116
2183
|
this._setupEventHandlers();
|
|
2117
2184
|
}
|
|
2118
2185
|
static get defaults() {
|
|
2119
2186
|
return _defaults6;
|
|
2120
2187
|
}
|
|
2121
|
-
/**
|
|
2122
|
-
* Initializes instances of FloatingActionButton.
|
|
2123
|
-
* @param els HTML elements.
|
|
2124
|
-
* @param options Component options.
|
|
2125
|
-
*/
|
|
2126
2188
|
static init(els, options = {}) {
|
|
2127
2189
|
return super.init(els, options, _FloatingActionButton);
|
|
2128
2190
|
}
|
|
@@ -2130,229 +2192,109 @@ var FloatingActionButton = class _FloatingActionButton extends Component {
|
|
|
2130
2192
|
return el["Expressive_FloatingActionButton"];
|
|
2131
2193
|
}
|
|
2132
2194
|
destroy() {
|
|
2133
|
-
this._removeEventHandlers();
|
|
2134
2195
|
this.close();
|
|
2196
|
+
this._removeEventHandlers();
|
|
2135
2197
|
this.el["Expressive_FloatingActionButton"] = void 0;
|
|
2136
2198
|
}
|
|
2199
|
+
_directionFromClass() {
|
|
2200
|
+
const match = [...this.el.classList].find((c) => c.startsWith("direction-"));
|
|
2201
|
+
const value = match?.slice("direction-".length);
|
|
2202
|
+
if (value === "top" || value === "right" || value === "bottom" || value === "left") {
|
|
2203
|
+
return value;
|
|
2204
|
+
}
|
|
2205
|
+
return null;
|
|
2206
|
+
}
|
|
2137
2207
|
_setupEventHandlers() {
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
this.
|
|
2141
|
-
} else {
|
|
2142
|
-
this.el.addEventListener("click", this._handleFABClick);
|
|
2208
|
+
this.el.addEventListener("click", this._handleFABClick);
|
|
2209
|
+
if (this._anchor instanceof HTMLAnchorElement && !this._anchor.hasAttribute("href")) {
|
|
2210
|
+
this._anchor.addEventListener("keydown", this._handleAnchorKeydown);
|
|
2143
2211
|
}
|
|
2144
|
-
this.el.addEventListener("keypress", this._handleFABKeyPress);
|
|
2145
2212
|
}
|
|
2146
2213
|
_removeEventHandlers() {
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
this.el.removeEventListener("mouseleave", this.close);
|
|
2150
|
-
} else {
|
|
2151
|
-
this.el.removeEventListener("click", this._handleFABClick);
|
|
2152
|
-
}
|
|
2153
|
-
this.el.removeEventListener("keypress", this._handleFABKeyPress);
|
|
2154
|
-
}
|
|
2155
|
-
_animateInFAB() {
|
|
2156
|
-
this.el.classList.add("active");
|
|
2157
|
-
if (this._menu) this._menu.ariaExpanded = "true";
|
|
2158
|
-
const delayIncrement = 40;
|
|
2159
|
-
const duration = 275;
|
|
2160
|
-
this._floatingBtnsReverse.forEach((el, index) => {
|
|
2161
|
-
const delay = delayIncrement * index;
|
|
2162
|
-
el.style.transition = "none";
|
|
2163
|
-
el.style.opacity = "0";
|
|
2164
|
-
el.style.transform = `translate(${this.offsetX}px, ${this.offsetY}px) scale(0.4)`;
|
|
2165
|
-
setTimeout(() => {
|
|
2166
|
-
el.style.opacity = "0.4";
|
|
2167
|
-
setTimeout(() => {
|
|
2168
|
-
el.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
|
|
2169
|
-
el.style.opacity = "1";
|
|
2170
|
-
el.style.transform = "translate(0, 0) scale(1)";
|
|
2171
|
-
el.tabIndex = 0;
|
|
2172
|
-
}, 1);
|
|
2173
|
-
}, delay);
|
|
2174
|
-
});
|
|
2175
|
-
}
|
|
2176
|
-
_animateOutFAB() {
|
|
2177
|
-
const duration = 175;
|
|
2178
|
-
setTimeout(() => {
|
|
2179
|
-
this.el.classList.remove("active");
|
|
2180
|
-
if (this._menu) this._menu.ariaExpanded = "false";
|
|
2181
|
-
}, duration);
|
|
2182
|
-
this._floatingBtnsReverse.forEach((el) => {
|
|
2183
|
-
el.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
|
|
2184
|
-
el.style.opacity = "0";
|
|
2185
|
-
el.style.transform = `translate(${this.offsetX}px, ${this.offsetY}px) scale(0.4)`;
|
|
2186
|
-
el.tabIndex = -1;
|
|
2187
|
-
});
|
|
2188
|
-
}
|
|
2189
|
-
_animateInToolbar() {
|
|
2190
|
-
const windowWidth = window.innerWidth;
|
|
2191
|
-
const windowHeight = window.innerHeight;
|
|
2192
|
-
const btnRect = this.el.getBoundingClientRect();
|
|
2193
|
-
const fabColor = getComputedStyle(this._anchor).backgroundColor;
|
|
2194
|
-
const backdrop = document.createElement("div");
|
|
2195
|
-
backdrop.classList.add("fab-backdrop");
|
|
2196
|
-
backdrop.style.backgroundColor = fabColor;
|
|
2197
|
-
this._anchor.append(backdrop);
|
|
2198
|
-
this._backdrop = backdrop;
|
|
2199
|
-
const backdropWidth = backdrop.clientWidth;
|
|
2200
|
-
const scaleFactor = backdropWidth > 0 ? windowWidth / backdropWidth : 1;
|
|
2201
|
-
this.offsetX = btnRect.left - windowWidth / 2 + btnRect.width / 2;
|
|
2202
|
-
this.offsetY = windowHeight - btnRect.bottom;
|
|
2203
|
-
this.btnBottom = btnRect.bottom;
|
|
2204
|
-
this.btnLeft = btnRect.left;
|
|
2205
|
-
this.btnWidth = btnRect.width;
|
|
2206
|
-
this.el.classList.add("active");
|
|
2207
|
-
this.el.style.textAlign = "center";
|
|
2208
|
-
this.el.style.width = "100%";
|
|
2209
|
-
this.el.style.bottom = "0";
|
|
2210
|
-
this.el.style.left = "0";
|
|
2211
|
-
this.el.style.transform = "translateX(" + this.offsetX + "px)";
|
|
2212
|
-
this.el.style.transition = "none";
|
|
2213
|
-
if (this._menu) this._menu.ariaExpanded = "true";
|
|
2214
|
-
this._anchor.style.transform = `translateY(${this.offsetY}px)`;
|
|
2215
|
-
this._anchor.style.transition = "none";
|
|
2216
|
-
setTimeout(() => {
|
|
2217
|
-
this.el.style.transform = "";
|
|
2218
|
-
this.el.style.transition = "transform .2s cubic-bezier(0.550, 0.085, 0.680, 0.530), background-color 0s linear .2s";
|
|
2219
|
-
this._anchor.style.overflow = "visible";
|
|
2220
|
-
this._anchor.style.transform = "";
|
|
2221
|
-
this._anchor.style.transition = "transform .2s";
|
|
2222
|
-
setTimeout(() => {
|
|
2223
|
-
this.el.style.overflow = "hidden";
|
|
2224
|
-
this.el.style.backgroundColor = fabColor;
|
|
2225
|
-
backdrop.style.transform = "scale(" + scaleFactor + ")";
|
|
2226
|
-
backdrop.style.transition = "transform .2s cubic-bezier(0.550, 0.055, 0.675, 0.190)";
|
|
2227
|
-
this._menu.querySelectorAll("li > a").forEach((a) => {
|
|
2228
|
-
a.style.opacity = "1";
|
|
2229
|
-
a.tabIndex = 0;
|
|
2230
|
-
});
|
|
2231
|
-
window.addEventListener("scroll", this.close, true);
|
|
2232
|
-
document.body.addEventListener("click", this._handleDocumentClick, true);
|
|
2233
|
-
}, 100);
|
|
2234
|
-
}, 0);
|
|
2214
|
+
this.el.removeEventListener("click", this._handleFABClick);
|
|
2215
|
+
this._anchor?.removeEventListener("keydown", this._handleAnchorKeydown);
|
|
2235
2216
|
}
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
* Closing used to only unbind the listeners, leaving the FAB stretched
|
|
2240
|
-
* across the viewport with its backdrop still in the DOM - and a fresh
|
|
2241
|
-
* backdrop appended on every subsequent open.
|
|
2242
|
-
*/
|
|
2243
|
-
_animateOutToolbar() {
|
|
2244
|
-
const backdrop = this._backdrop;
|
|
2245
|
-
this._backdrop = null;
|
|
2246
|
-
this._menu?.querySelectorAll("li > a").forEach((a) => {
|
|
2247
|
-
a.style.opacity = "";
|
|
2248
|
-
a.tabIndex = -1;
|
|
2249
|
-
});
|
|
2250
|
-
if (backdrop) {
|
|
2251
|
-
backdrop.style.transition = "transform .2s";
|
|
2252
|
-
backdrop.style.transform = "scale(0)";
|
|
2253
|
-
}
|
|
2254
|
-
this.el.style.overflow = "";
|
|
2255
|
-
this.el.style.backgroundColor = "";
|
|
2256
|
-
this.el.style.transition = "transform .2s";
|
|
2257
|
-
this.el.style.transform = `translateX(${this.offsetX}px)`;
|
|
2258
|
-
this._anchor.style.transition = "transform .2s";
|
|
2259
|
-
this._anchor.style.transform = `translateY(${this.offsetY}px)`;
|
|
2260
|
-
setTimeout(() => {
|
|
2261
|
-
backdrop?.remove();
|
|
2262
|
-
this.el.classList.remove("active");
|
|
2263
|
-
if (this._menu) this._menu.ariaExpanded = "false";
|
|
2264
|
-
this.el.style.textAlign = "";
|
|
2265
|
-
this.el.style.width = "";
|
|
2266
|
-
this.el.style.bottom = "";
|
|
2267
|
-
this.el.style.left = "";
|
|
2268
|
-
this.el.style.transform = "";
|
|
2269
|
-
this.el.style.transition = "";
|
|
2270
|
-
this._anchor.style.overflow = "";
|
|
2271
|
-
this._anchor.style.transform = "";
|
|
2272
|
-
this._anchor.style.transition = "";
|
|
2273
|
-
}, 200);
|
|
2217
|
+
_toggle() {
|
|
2218
|
+
if (this.isOpen) this.close();
|
|
2219
|
+
else this.open();
|
|
2274
2220
|
}
|
|
2275
2221
|
};
|
|
2276
2222
|
|
|
2277
2223
|
// src/ts/components/carousel.ts
|
|
2278
2224
|
var _defaults7 = {
|
|
2279
2225
|
duration: 200,
|
|
2280
|
-
// ms
|
|
2281
2226
|
dist: -100,
|
|
2282
|
-
// zoom scale TODO: make this more intuitive as an option
|
|
2283
2227
|
shift: 0,
|
|
2284
|
-
// spacing for center image
|
|
2285
2228
|
padding: 0,
|
|
2286
|
-
// Padding between non center items
|
|
2287
2229
|
numVisible: 5,
|
|
2288
|
-
// Number of visible items in carousel
|
|
2289
2230
|
fullWidth: false,
|
|
2290
|
-
// Change to full width styles
|
|
2291
2231
|
indicators: false,
|
|
2292
|
-
// Toggle indicators
|
|
2293
2232
|
noWrap: false,
|
|
2294
|
-
// Don't wrap around and cycle through items.
|
|
2295
2233
|
onCycleTo: null
|
|
2296
|
-
// Callback for when a new slide is cycled to.
|
|
2297
2234
|
};
|
|
2298
|
-
var
|
|
2235
|
+
var _Carousel = class _Carousel extends Component {
|
|
2299
2236
|
constructor(el, options) {
|
|
2300
2237
|
super(el, options, _Carousel);
|
|
2301
|
-
/** The index of the center carousel item. */
|
|
2302
2238
|
this.center = 0;
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2239
|
+
this._ownIndicators = false;
|
|
2240
|
+
this._trackEl = null;
|
|
2241
|
+
this._ignoreScroll = false;
|
|
2242
|
+
this._trackRaf = null;
|
|
2243
|
+
this._started = false;
|
|
2306
2244
|
this._handleThrottledResize = Utils.throttle(() => this._handleResize(), 200);
|
|
2307
2245
|
this._handleCarouselTap = (e) => {
|
|
2308
|
-
if (e.
|
|
2246
|
+
if (e.pointerType === "mouse" && e.button !== 0) return;
|
|
2247
|
+
if (e.target instanceof HTMLElement && e.target.tagName === "IMG") {
|
|
2309
2248
|
e.preventDefault();
|
|
2310
2249
|
}
|
|
2311
2250
|
this.pressed = true;
|
|
2312
2251
|
this.dragged = false;
|
|
2313
2252
|
this.verticalDragged = false;
|
|
2314
|
-
this.reference =
|
|
2315
|
-
this.referenceY =
|
|
2253
|
+
this.reference = e.clientX;
|
|
2254
|
+
this.referenceY = e.clientY;
|
|
2316
2255
|
this.velocity = this.amplitude = 0;
|
|
2317
2256
|
this.frame = this.offset;
|
|
2318
2257
|
this.timestamp = Date.now();
|
|
2319
|
-
|
|
2320
|
-
|
|
2258
|
+
try {
|
|
2259
|
+
this.el.setPointerCapture(e.pointerId);
|
|
2260
|
+
} catch {
|
|
2261
|
+
}
|
|
2262
|
+
if (this._trackRaf !== null) cancelAnimationFrame(this._trackRaf);
|
|
2263
|
+
const loop = () => {
|
|
2264
|
+
this._track();
|
|
2265
|
+
if (this.pressed) this._trackRaf = requestAnimationFrame(loop);
|
|
2266
|
+
else this._trackRaf = null;
|
|
2267
|
+
};
|
|
2268
|
+
this._trackRaf = requestAnimationFrame(loop);
|
|
2321
2269
|
};
|
|
2322
2270
|
this._handleCarouselDrag = (e) => {
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
delta
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
this.dragged = true;
|
|
2332
|
-
this.reference = x;
|
|
2333
|
-
this._scroll(this.offset + delta);
|
|
2334
|
-
}
|
|
2335
|
-
} else if (this.dragged) {
|
|
2336
|
-
e.preventDefault();
|
|
2337
|
-
e.stopPropagation();
|
|
2338
|
-
return false;
|
|
2339
|
-
} else {
|
|
2340
|
-
this.verticalDragged = true;
|
|
2271
|
+
if (!this.pressed) return;
|
|
2272
|
+
const delta = this.reference - e.clientX;
|
|
2273
|
+
const deltaY = Math.abs(this.referenceY - e.clientY);
|
|
2274
|
+
if (deltaY < 30 && !this.verticalDragged) {
|
|
2275
|
+
if (delta > 2 || delta < -2) {
|
|
2276
|
+
this.dragged = true;
|
|
2277
|
+
this.reference = e.clientX;
|
|
2278
|
+
this._scroll(this.offset + delta);
|
|
2341
2279
|
}
|
|
2342
|
-
}
|
|
2343
|
-
if (this.dragged) {
|
|
2280
|
+
} else if (this.dragged) {
|
|
2344
2281
|
e.preventDefault();
|
|
2345
|
-
|
|
2346
|
-
|
|
2282
|
+
} else {
|
|
2283
|
+
this.verticalDragged = true;
|
|
2347
2284
|
}
|
|
2285
|
+
if (this.dragged) e.preventDefault();
|
|
2348
2286
|
};
|
|
2349
2287
|
this._handleCarouselRelease = (e) => {
|
|
2350
|
-
if (this.pressed)
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2288
|
+
if (!this.pressed) return;
|
|
2289
|
+
this.pressed = false;
|
|
2290
|
+
if (this._trackRaf !== null) {
|
|
2291
|
+
cancelAnimationFrame(this._trackRaf);
|
|
2292
|
+
this._trackRaf = null;
|
|
2293
|
+
}
|
|
2294
|
+
try {
|
|
2295
|
+
this.el.releasePointerCapture(e.pointerId);
|
|
2296
|
+
} catch {
|
|
2354
2297
|
}
|
|
2355
|
-
clearInterval(this.ticker);
|
|
2356
2298
|
this.target = this.offset;
|
|
2357
2299
|
if (this.velocity > 10 || this.velocity < -10) {
|
|
2358
2300
|
this.amplitude = 0.9 * this.velocity;
|
|
@@ -2369,86 +2311,91 @@ var Carousel = class _Carousel extends Component {
|
|
|
2369
2311
|
this.amplitude = this.target - this.offset;
|
|
2370
2312
|
this.timestamp = Date.now();
|
|
2371
2313
|
requestAnimationFrame(this._autoScroll);
|
|
2314
|
+
if (this.dragged) e.preventDefault();
|
|
2315
|
+
};
|
|
2316
|
+
this._handleCarouselClick = (e) => {
|
|
2372
2317
|
if (this.dragged) {
|
|
2373
2318
|
e.preventDefault();
|
|
2374
2319
|
e.stopPropagation();
|
|
2320
|
+
return;
|
|
2375
2321
|
}
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2322
|
+
const clickedElem = e.target.closest(".carousel-item");
|
|
2323
|
+
if (!clickedElem || !this.el.contains(clickedElem)) return;
|
|
2324
|
+
const clickedIndex = this.images.indexOf(clickedElem);
|
|
2325
|
+
const diff = this._wrap(this.center) - clickedIndex;
|
|
2326
|
+
if (diff !== 0) {
|
|
2380
2327
|
e.preventDefault();
|
|
2381
2328
|
e.stopPropagation();
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
const clickedIndex = [...clickedElem.parentNode.children].indexOf(clickedElem);
|
|
2387
|
-
const diff = this._wrap(this.center) - clickedIndex;
|
|
2388
|
-
if (diff !== 0) {
|
|
2389
|
-
e.preventDefault();
|
|
2390
|
-
e.stopPropagation();
|
|
2391
|
-
}
|
|
2392
|
-
if (clickedIndex < 0) {
|
|
2393
|
-
if (e.clientX - e.target.getBoundingClientRect().left > this.el.clientWidth / 2) {
|
|
2394
|
-
this.next();
|
|
2395
|
-
} else {
|
|
2396
|
-
this.prev();
|
|
2397
|
-
}
|
|
2329
|
+
}
|
|
2330
|
+
if (clickedIndex < 0) {
|
|
2331
|
+
if (e.clientX - e.target.getBoundingClientRect().left > this.el.clientWidth / 2) {
|
|
2332
|
+
this.next();
|
|
2398
2333
|
} else {
|
|
2399
|
-
this.
|
|
2334
|
+
this.prev();
|
|
2400
2335
|
}
|
|
2336
|
+
} else {
|
|
2337
|
+
this._cycleTo(clickedIndex);
|
|
2401
2338
|
}
|
|
2402
2339
|
};
|
|
2403
2340
|
this._handleIndicatorClick = (e) => {
|
|
2404
2341
|
e.stopPropagation();
|
|
2405
|
-
|
|
2342
|
+
const indicator = e.target.closest(".indicator-item");
|
|
2343
|
+
if (!indicator || !this._indicators.contains(indicator)) return;
|
|
2344
|
+
const index = [...this._indicators.children].indexOf(indicator);
|
|
2345
|
+
if (index < 0) return;
|
|
2346
|
+
this._cycleTo(index);
|
|
2406
2347
|
};
|
|
2407
|
-
this.
|
|
2408
|
-
e.
|
|
2409
|
-
if (
|
|
2410
|
-
|
|
2348
|
+
this._handleKeydown = (e) => {
|
|
2349
|
+
const target = e.target;
|
|
2350
|
+
if (target.closest('input, textarea, select, [contenteditable="true"]')) return;
|
|
2351
|
+
if (Utils.keys.ARROW_RIGHT.includes(e.key)) {
|
|
2352
|
+
e.preventDefault();
|
|
2353
|
+
this.next();
|
|
2354
|
+
} else if (Utils.keys.ARROW_LEFT.includes(e.key)) {
|
|
2355
|
+
e.preventDefault();
|
|
2356
|
+
this.prev();
|
|
2411
2357
|
}
|
|
2412
2358
|
};
|
|
2413
|
-
this.
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
this._cycleTo(index);
|
|
2418
|
-
}
|
|
2359
|
+
this._handleFlatScroll = () => {
|
|
2360
|
+
if (this._ignoreScroll) return;
|
|
2361
|
+
const index = this._nearestIndex();
|
|
2362
|
+
if (index !== this.center) this._syncActive(index, this.dragged);
|
|
2419
2363
|
};
|
|
2420
2364
|
this._handleResize = () => {
|
|
2365
|
+
if (!this.images.length) return;
|
|
2366
|
+
if (this._flat) {
|
|
2367
|
+
this._scrollToIndex(this.center, false);
|
|
2368
|
+
return;
|
|
2369
|
+
}
|
|
2421
2370
|
if (this.options.fullWidth) {
|
|
2422
|
-
const firstItem = this.
|
|
2423
|
-
|
|
2424
|
-
if (!firstItem || !activeItem) return;
|
|
2371
|
+
const firstItem = this.images[0];
|
|
2372
|
+
if (!firstItem) return;
|
|
2425
2373
|
this.itemWidth = firstItem.clientWidth;
|
|
2426
|
-
this.imageHeight = activeItem.clientHeight;
|
|
2427
2374
|
this.dim = this.itemWidth * 2 + this.options.padding;
|
|
2428
2375
|
this.offset = this.center * 2 * this.itemWidth;
|
|
2429
2376
|
this.target = this.offset;
|
|
2430
|
-
this._setCarouselHeight(true);
|
|
2431
2377
|
} else {
|
|
2432
2378
|
this._scroll();
|
|
2433
2379
|
}
|
|
2434
2380
|
};
|
|
2435
2381
|
this._track = () => {
|
|
2436
|
-
const now = Date.now()
|
|
2382
|
+
const now = Date.now();
|
|
2383
|
+
const elapsed = now - this.timestamp;
|
|
2384
|
+
const delta = this.offset - this.frame;
|
|
2385
|
+
const v = 1e3 * delta / (1 + elapsed);
|
|
2437
2386
|
this.timestamp = now;
|
|
2438
2387
|
this.frame = this.offset;
|
|
2439
2388
|
this.velocity = 0.8 * v + 0.2 * this.velocity;
|
|
2440
2389
|
};
|
|
2441
2390
|
this._autoScroll = () => {
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
this._scroll(this.target);
|
|
2451
|
-
}
|
|
2391
|
+
if (!this.amplitude) return;
|
|
2392
|
+
const elapsed = Date.now() - this.timestamp;
|
|
2393
|
+
const delta = this.amplitude * Math.exp(-elapsed / this.options.duration);
|
|
2394
|
+
if (delta > 2 || delta < -2) {
|
|
2395
|
+
this._scroll(this.target - delta);
|
|
2396
|
+
requestAnimationFrame(this._autoScroll);
|
|
2397
|
+
} else {
|
|
2398
|
+
this._scroll(this.target);
|
|
2452
2399
|
}
|
|
2453
2400
|
};
|
|
2454
2401
|
this.el["Expressive_Carousel"] = this;
|
|
@@ -2456,56 +2403,58 @@ var Carousel = class _Carousel extends Component {
|
|
|
2456
2403
|
..._Carousel.defaults,
|
|
2457
2404
|
...options
|
|
2458
2405
|
};
|
|
2459
|
-
this.
|
|
2460
|
-
|
|
2461
|
-
|
|
2406
|
+
this._flat = this.options.fullWidth || this.el.classList.contains("flat") || this.el.classList.contains("carousel-slider");
|
|
2407
|
+
if (this._flat) {
|
|
2408
|
+
this.el.classList.add("flat");
|
|
2409
|
+
this.options.fullWidth = true;
|
|
2410
|
+
this.options.dist = 0;
|
|
2411
|
+
}
|
|
2412
|
+
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
|
2413
|
+
this.options.duration = 1;
|
|
2414
|
+
if (!this._flat) this.options.dist = 0;
|
|
2415
|
+
}
|
|
2462
2416
|
this.pressed = false;
|
|
2463
2417
|
this.dragged = false;
|
|
2464
2418
|
this.offset = this.target = 0;
|
|
2465
|
-
this.images =
|
|
2466
|
-
|
|
2467
|
-
if (!firstItem) {
|
|
2419
|
+
this.images = this._collectItems();
|
|
2420
|
+
if (!this.images.length) {
|
|
2468
2421
|
console.error("Carousel: no .carousel-item elements to show");
|
|
2469
2422
|
return;
|
|
2470
2423
|
}
|
|
2471
|
-
this.
|
|
2472
|
-
this.
|
|
2473
|
-
this.
|
|
2474
|
-
if (this.options.fullWidth) {
|
|
2475
|
-
this.options.dist = 0;
|
|
2476
|
-
this._setCarouselHeight();
|
|
2477
|
-
if (this.showIndicators) {
|
|
2478
|
-
this.el.querySelector(".carousel-fixed-item")?.classList.add("with-indicators");
|
|
2479
|
-
}
|
|
2480
|
-
}
|
|
2481
|
-
this._indicators = document.createElement("ul");
|
|
2482
|
-
this._indicators.classList.add("indicators");
|
|
2483
|
-
this.el.querySelectorAll(".carousel-item").forEach((item, i) => {
|
|
2484
|
-
this.images.push(item);
|
|
2485
|
-
if (this.showIndicators) {
|
|
2486
|
-
const indicator = document.createElement("li");
|
|
2487
|
-
indicator.classList.add("indicator-item");
|
|
2488
|
-
indicator.tabIndex = 0;
|
|
2489
|
-
if (i === 0) {
|
|
2490
|
-
indicator.classList.add("active");
|
|
2491
|
-
}
|
|
2492
|
-
this._indicators.appendChild(indicator);
|
|
2493
|
-
}
|
|
2494
|
-
});
|
|
2495
|
-
if (this.showIndicators) this.el.appendChild(this._indicators);
|
|
2424
|
+
this.hasMultipleSlides = this.images.length > 1;
|
|
2425
|
+
this.showIndicators = this.options.indicators && this.hasMultipleSlides;
|
|
2426
|
+
this.noWrap = this.options.noWrap || !this.hasMultipleSlides || this._flat;
|
|
2496
2427
|
this.count = this.images.length;
|
|
2497
2428
|
this.options.numVisible = Math.min(this.count, this.options.numVisible);
|
|
2429
|
+
this.images.forEach((item) => item.classList.add("carousel-item"));
|
|
2430
|
+
if (this._flat) this._wrapTrack();
|
|
2431
|
+
const firstItem = this.images[0];
|
|
2432
|
+
this.itemWidth = firstItem.clientWidth || this.el.clientWidth || 1;
|
|
2433
|
+
this.itemHeight = firstItem.clientHeight || this.el.clientHeight || 1;
|
|
2434
|
+
this.dim = this.itemWidth * 2 + this.options.padding || 1;
|
|
2435
|
+
if (this.showIndicators) this._setupIndicators();
|
|
2436
|
+
this.el.tabIndex = this.el.tabIndex >= 0 ? this.el.tabIndex : 0;
|
|
2437
|
+
this.el.setAttribute("aria-roledescription", "carousel");
|
|
2498
2438
|
this._setupEventHandlers();
|
|
2499
|
-
this.
|
|
2439
|
+
this._started = true;
|
|
2440
|
+
if (this._flat) {
|
|
2441
|
+
const start = Math.max(
|
|
2442
|
+
0,
|
|
2443
|
+
this.images.findIndex((el2) => el2.classList.contains("active"))
|
|
2444
|
+
);
|
|
2445
|
+
this.center = start;
|
|
2446
|
+
this._syncActive(start, false);
|
|
2447
|
+
this._scrollToIndex(start, false);
|
|
2448
|
+
} else {
|
|
2449
|
+
this._scroll(this.offset);
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
get _scroller() {
|
|
2453
|
+
return this._trackEl ?? this.el;
|
|
2500
2454
|
}
|
|
2501
2455
|
static get defaults() {
|
|
2502
2456
|
return _defaults7;
|
|
2503
2457
|
}
|
|
2504
|
-
/**
|
|
2505
|
-
* Initializes instances of Carousel.
|
|
2506
|
-
* @param els HTML elements.
|
|
2507
|
-
* @param options Component options.
|
|
2508
|
-
*/
|
|
2509
2458
|
static init(els, options = {}) {
|
|
2510
2459
|
return super.init(els, options, _Carousel);
|
|
2511
2460
|
}
|
|
@@ -2513,81 +2462,104 @@ var Carousel = class _Carousel extends Component {
|
|
|
2513
2462
|
return el["Expressive_Carousel"];
|
|
2514
2463
|
}
|
|
2515
2464
|
destroy() {
|
|
2516
|
-
this.
|
|
2465
|
+
if (this._started) this._teardown();
|
|
2517
2466
|
this.el["Expressive_Carousel"] = void 0;
|
|
2518
2467
|
}
|
|
2468
|
+
_collectItems() {
|
|
2469
|
+
const explicit = Array.from(this.el.children).filter(
|
|
2470
|
+
(el) => el instanceof HTMLElement && el.classList.contains("carousel-item")
|
|
2471
|
+
);
|
|
2472
|
+
if (explicit.length) return explicit;
|
|
2473
|
+
return Array.from(this.el.children).filter((el) => {
|
|
2474
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
2475
|
+
if (el.classList.contains("indicators") || el.classList.contains("carousel-fixed-item")) {
|
|
2476
|
+
return false;
|
|
2477
|
+
}
|
|
2478
|
+
return el.tagName !== "NAV";
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2481
|
+
_setupIndicators() {
|
|
2482
|
+
const existing = Array.from(this.el.children).find(
|
|
2483
|
+
(el) => el instanceof HTMLElement && el.classList.contains("indicators")
|
|
2484
|
+
);
|
|
2485
|
+
this._indicators = existing ?? document.createElement("nav");
|
|
2486
|
+
this._ownIndicators = !existing;
|
|
2487
|
+
this._indicators.classList.add("indicators");
|
|
2488
|
+
this._indicators.setAttribute("aria-label", "Slides");
|
|
2489
|
+
this._indicators.replaceChildren();
|
|
2490
|
+
this.images.forEach((_, i) => {
|
|
2491
|
+
const button = document.createElement("button");
|
|
2492
|
+
button.type = "button";
|
|
2493
|
+
button.classList.add("indicator-item");
|
|
2494
|
+
if (i === 0) {
|
|
2495
|
+
button.classList.add("active");
|
|
2496
|
+
button.setAttribute("aria-current", "true");
|
|
2497
|
+
}
|
|
2498
|
+
button.setAttribute("aria-label", `Slide ${i + 1}`);
|
|
2499
|
+
this._indicators.appendChild(button);
|
|
2500
|
+
});
|
|
2501
|
+
if (this._ownIndicators) this.el.appendChild(this._indicators);
|
|
2502
|
+
if (this._flat) {
|
|
2503
|
+
this.el.querySelector(".carousel-fixed-item")?.classList.add("with-indicators");
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2519
2506
|
_setupEventHandlers() {
|
|
2520
|
-
|
|
2521
|
-
this.el.addEventListener("touchstart", this._handleCarouselTap);
|
|
2522
|
-
this.el.addEventListener("touchmove", this._handleCarouselDrag);
|
|
2523
|
-
this.el.addEventListener("touchend", this._handleCarouselRelease);
|
|
2524
|
-
}
|
|
2525
|
-
this.el.addEventListener("mousedown", this._handleCarouselTap);
|
|
2526
|
-
this.el.addEventListener("mousemove", this._handleCarouselDrag);
|
|
2527
|
-
this.el.addEventListener("mouseup", this._handleCarouselRelease);
|
|
2528
|
-
this.el.addEventListener("mouseleave", this._handleCarouselRelease);
|
|
2529
|
-
this.el.addEventListener("click", this._handleCarouselClick);
|
|
2507
|
+
this.el.addEventListener("keydown", this._handleKeydown);
|
|
2530
2508
|
if (this.showIndicators && this._indicators) {
|
|
2531
|
-
this._indicators.
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2509
|
+
this._indicators.addEventListener("click", this._handleIndicatorClick);
|
|
2510
|
+
}
|
|
2511
|
+
_Carousel._live.add(this);
|
|
2512
|
+
if (!_Carousel._resizeListening) {
|
|
2513
|
+
window.addEventListener("resize", _Carousel._onResize, { passive: true });
|
|
2514
|
+
_Carousel._resizeListening = true;
|
|
2535
2515
|
}
|
|
2536
|
-
|
|
2516
|
+
if (this._flat) {
|
|
2517
|
+
this._scroller.addEventListener("scroll", this._handleFlatScroll, { passive: true });
|
|
2518
|
+
return;
|
|
2519
|
+
}
|
|
2520
|
+
this.el.addEventListener("pointerdown", this._handleCarouselTap);
|
|
2521
|
+
this.el.addEventListener("pointermove", this._handleCarouselDrag);
|
|
2522
|
+
this.el.addEventListener("pointerup", this._handleCarouselRelease);
|
|
2523
|
+
this.el.addEventListener("pointercancel", this._handleCarouselRelease);
|
|
2524
|
+
this.el.addEventListener("click", this._handleCarouselClick);
|
|
2537
2525
|
}
|
|
2538
2526
|
_removeEventHandlers() {
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
this.
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
this.el.removeEventListener("
|
|
2545
|
-
this.el.removeEventListener("
|
|
2546
|
-
this.el.removeEventListener("
|
|
2547
|
-
this.el.removeEventListener("
|
|
2527
|
+
this.el.removeEventListener("keydown", this._handleKeydown);
|
|
2528
|
+
if (this._indicators) {
|
|
2529
|
+
this._indicators.removeEventListener("click", this._handleIndicatorClick);
|
|
2530
|
+
}
|
|
2531
|
+
this._scroller.removeEventListener("scroll", this._handleFlatScroll);
|
|
2532
|
+
this.el.removeEventListener("pointerdown", this._handleCarouselTap);
|
|
2533
|
+
this.el.removeEventListener("pointermove", this._handleCarouselDrag);
|
|
2534
|
+
this.el.removeEventListener("pointerup", this._handleCarouselRelease);
|
|
2535
|
+
this.el.removeEventListener("pointercancel", this._handleCarouselRelease);
|
|
2548
2536
|
this.el.removeEventListener("click", this._handleCarouselClick);
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2537
|
+
_Carousel._live.delete(this);
|
|
2538
|
+
if (_Carousel._live.size === 0 && _Carousel._resizeListening) {
|
|
2539
|
+
window.removeEventListener("resize", _Carousel._onResize);
|
|
2540
|
+
_Carousel._resizeListening = false;
|
|
2553
2541
|
}
|
|
2554
|
-
window.removeEventListener("resize", this._handleThrottledResize);
|
|
2555
2542
|
}
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
this.el.style.height = adjustedHeight + "px";
|
|
2569
|
-
}
|
|
2570
|
-
} else {
|
|
2571
|
-
firstImage.addEventListener("load", () => {
|
|
2572
|
-
this.el.style.height = firstImage.offsetHeight + "px";
|
|
2573
|
-
});
|
|
2574
|
-
}
|
|
2575
|
-
} else if (!imageOnly) {
|
|
2576
|
-
const slideHeight = firstSlide.clientHeight;
|
|
2577
|
-
this.el.style.height = slideHeight + "px";
|
|
2578
|
-
}
|
|
2543
|
+
_teardown() {
|
|
2544
|
+
this._removeEventHandlers();
|
|
2545
|
+
if (this._trackRaf !== null) cancelAnimationFrame(this._trackRaf);
|
|
2546
|
+
window.clearTimeout(this.scrollingTimeout);
|
|
2547
|
+
if (this._ownIndicators) this._indicators?.remove();
|
|
2548
|
+
this._unwrapTrack();
|
|
2549
|
+
this.images.forEach((el) => {
|
|
2550
|
+
el.style.transform = "";
|
|
2551
|
+
el.style.zIndex = "";
|
|
2552
|
+
el.style.opacity = "";
|
|
2553
|
+
el.style.visibility = "";
|
|
2554
|
+
});
|
|
2579
2555
|
}
|
|
2580
2556
|
_xpos(e) {
|
|
2581
|
-
if (
|
|
2582
|
-
|
|
2583
|
-
}
|
|
2584
|
-
return e.clientX;
|
|
2557
|
+
if ("clientX" in e) return e.clientX;
|
|
2558
|
+
return 0;
|
|
2585
2559
|
}
|
|
2586
2560
|
_ypos(e) {
|
|
2587
|
-
if (
|
|
2588
|
-
|
|
2589
|
-
}
|
|
2590
|
-
return e.clientY;
|
|
2561
|
+
if ("clientY" in e) return e.clientY;
|
|
2562
|
+
return 0;
|
|
2591
2563
|
}
|
|
2592
2564
|
_wrap(x) {
|
|
2593
2565
|
return x >= this.count ? x % this.count : x < 0 ? this._wrap(this.count + x % this.count) : x;
|
|
@@ -2596,18 +2568,20 @@ var Carousel = class _Carousel extends Component {
|
|
|
2596
2568
|
if (!this.el.classList.contains("scrolling")) {
|
|
2597
2569
|
this.el.classList.add("scrolling");
|
|
2598
2570
|
}
|
|
2599
|
-
|
|
2600
|
-
clearTimeout(this.scrollingTimeout);
|
|
2601
|
-
}
|
|
2571
|
+
window.clearTimeout(this.scrollingTimeout);
|
|
2602
2572
|
this.scrollingTimeout = setTimeout(() => {
|
|
2603
2573
|
this.el.classList.remove("scrolling");
|
|
2604
2574
|
}, this.options.duration);
|
|
2605
2575
|
this.offset = typeof x === "number" ? x : this.offset;
|
|
2606
2576
|
this.center = Math.floor((this.offset + this.dim / 2) / this.dim);
|
|
2607
|
-
const half = this.count >> 1
|
|
2608
|
-
|
|
2577
|
+
const half = this.count >> 1;
|
|
2578
|
+
const delta = this.offset - this.center * this.dim;
|
|
2579
|
+
const dir = delta < 0 ? 1 : -1;
|
|
2580
|
+
const tween = -dir * delta * 2 / this.dim;
|
|
2609
2581
|
const lastCenter = this.center;
|
|
2610
2582
|
const numVisibleOffset = 1 / this.options.numVisible;
|
|
2583
|
+
let alignment;
|
|
2584
|
+
let centerTweenedOpacity;
|
|
2611
2585
|
if (this.options.fullWidth) {
|
|
2612
2586
|
alignment = "translateX(0)";
|
|
2613
2587
|
centerTweenedOpacity = 1;
|
|
@@ -2616,26 +2590,17 @@ var Carousel = class _Carousel extends Component {
|
|
|
2616
2590
|
alignment += "translateY(" + (this.el.clientHeight - this.itemHeight) / 2 + "px)";
|
|
2617
2591
|
centerTweenedOpacity = 1 - numVisibleOffset * tween;
|
|
2618
2592
|
}
|
|
2619
|
-
|
|
2620
|
-
const diff = this.center % this.count;
|
|
2621
|
-
const activeIndicator = this._indicators.querySelector(".indicator-item.active");
|
|
2622
|
-
const activeIndicatorIndex = [...activeIndicator.parentNode.children].indexOf(
|
|
2623
|
-
activeIndicator
|
|
2624
|
-
);
|
|
2625
|
-
if (activeIndicatorIndex !== diff) {
|
|
2626
|
-
activeIndicator.classList.remove("active");
|
|
2627
|
-
const pos = diff < 0 ? this.count + diff : diff;
|
|
2628
|
-
this._indicators.querySelectorAll(".indicator-item")[pos].classList.add("active");
|
|
2629
|
-
}
|
|
2630
|
-
}
|
|
2593
|
+
this._paintIndicators(this.center);
|
|
2631
2594
|
if (!this.noWrap || this.center >= 0 && this.center < this.count) {
|
|
2632
|
-
el = this.images[this._wrap(this.center)];
|
|
2633
|
-
if (!el.classList.contains("active")) {
|
|
2595
|
+
const el = this.images[this._wrap(this.center)];
|
|
2596
|
+
if (el && !el.classList.contains("active")) {
|
|
2634
2597
|
this.el.querySelector(".carousel-item.active")?.classList.remove("active");
|
|
2635
2598
|
el.classList.add("active");
|
|
2636
2599
|
}
|
|
2637
2600
|
}
|
|
2638
|
-
for (i = 1; i <= half; ++i) {
|
|
2601
|
+
for (let i = 1; i <= half; ++i) {
|
|
2602
|
+
let zTranslation;
|
|
2603
|
+
let tweenedOpacity;
|
|
2639
2604
|
if (this.options.fullWidth) {
|
|
2640
2605
|
zTranslation = this.options.dist;
|
|
2641
2606
|
tweenedOpacity = i === half && delta < 0 ? 1 - tween : 1;
|
|
@@ -2644,7 +2609,7 @@ var Carousel = class _Carousel extends Component {
|
|
|
2644
2609
|
tweenedOpacity = 1 - numVisibleOffset * (i * 2 + tween * dir);
|
|
2645
2610
|
}
|
|
2646
2611
|
if (!this.noWrap || this.center + i < this.count) {
|
|
2647
|
-
el = this.images[this._wrap(this.center + i)];
|
|
2612
|
+
const el = this.images[this._wrap(this.center + i)];
|
|
2648
2613
|
const transformString = `${alignment} translateX(${this.options.shift + (this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
|
|
2649
2614
|
this._updateItemStyle(el, tweenedOpacity, -i, transformString);
|
|
2650
2615
|
}
|
|
@@ -2656,32 +2621,113 @@ var Carousel = class _Carousel extends Component {
|
|
|
2656
2621
|
tweenedOpacity = 1 - numVisibleOffset * (i * 2 - tween * dir);
|
|
2657
2622
|
}
|
|
2658
2623
|
if (!this.noWrap || this.center - i >= 0) {
|
|
2659
|
-
el = this.images[this._wrap(this.center - i)];
|
|
2624
|
+
const el = this.images[this._wrap(this.center - i)];
|
|
2660
2625
|
const transformString = `${alignment} translateX(${-this.options.shift + (-this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
|
|
2661
2626
|
this._updateItemStyle(el, tweenedOpacity, -i, transformString);
|
|
2662
2627
|
}
|
|
2663
2628
|
}
|
|
2664
2629
|
if (!this.noWrap || this.center >= 0 && this.center < this.count) {
|
|
2665
|
-
el = this.images[this._wrap(this.center)];
|
|
2630
|
+
const el = this.images[this._wrap(this.center)];
|
|
2666
2631
|
const transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir * this.options.shift * tween}px) translateZ(${this.options.dist * tween}px)`;
|
|
2667
2632
|
this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
|
|
2668
2633
|
}
|
|
2669
|
-
const
|
|
2634
|
+
const currItem = this.images[this._wrap(this.center)];
|
|
2635
|
+
this._syncA11y(this._wrap(this.center));
|
|
2670
2636
|
if (lastCenter !== this.center && typeof this.options.onCycleTo === "function") {
|
|
2671
|
-
this.options.onCycleTo.call(this,
|
|
2637
|
+
this.options.onCycleTo.call(this, currItem, this.dragged);
|
|
2672
2638
|
}
|
|
2673
2639
|
if (typeof this.oneTimeCallback === "function") {
|
|
2674
|
-
this.oneTimeCallback.call(this,
|
|
2640
|
+
this.oneTimeCallback.call(this, currItem, this.dragged);
|
|
2675
2641
|
this.oneTimeCallback = null;
|
|
2676
2642
|
}
|
|
2677
2643
|
}
|
|
2678
2644
|
_updateItemStyle(el, opacity, zIndex, transform) {
|
|
2645
|
+
if (!el) return;
|
|
2679
2646
|
el.style.transform = transform;
|
|
2680
2647
|
el.style.zIndex = zIndex.toString();
|
|
2681
2648
|
el.style.opacity = opacity.toString();
|
|
2682
2649
|
el.style.visibility = "visible";
|
|
2683
2650
|
}
|
|
2651
|
+
_paintIndicators(center) {
|
|
2652
|
+
if (!this.showIndicators || !this._indicators) return;
|
|
2653
|
+
const pos = (center % this.count + this.count) % this.count;
|
|
2654
|
+
this._indicators.querySelectorAll(".indicator-item").forEach((el, i) => {
|
|
2655
|
+
const on = i === pos;
|
|
2656
|
+
el.classList.toggle("active", on);
|
|
2657
|
+
if (on) el.setAttribute("aria-current", "true");
|
|
2658
|
+
else el.removeAttribute("aria-current");
|
|
2659
|
+
});
|
|
2660
|
+
}
|
|
2661
|
+
_syncA11y(index) {
|
|
2662
|
+
this.images.forEach((el, i) => {
|
|
2663
|
+
if (i === index) el.removeAttribute("aria-hidden");
|
|
2664
|
+
else el.setAttribute("aria-hidden", "true");
|
|
2665
|
+
});
|
|
2666
|
+
}
|
|
2667
|
+
_syncActive(index, dragged) {
|
|
2668
|
+
const prev = this.center;
|
|
2669
|
+
this.center = index;
|
|
2670
|
+
this.images.forEach((el, i) => el.classList.toggle("active", i === index));
|
|
2671
|
+
this._paintIndicators(index);
|
|
2672
|
+
this._syncA11y(index);
|
|
2673
|
+
const curr = this.images[index];
|
|
2674
|
+
if (prev !== index && typeof this.options.onCycleTo === "function") {
|
|
2675
|
+
this.options.onCycleTo.call(this, curr, dragged);
|
|
2676
|
+
}
|
|
2677
|
+
if (typeof this.oneTimeCallback === "function") {
|
|
2678
|
+
this.oneTimeCallback.call(this, curr, dragged);
|
|
2679
|
+
this.oneTimeCallback = null;
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
_wrapTrack() {
|
|
2683
|
+
const track = document.createElement("div");
|
|
2684
|
+
track.className = "carousel-track";
|
|
2685
|
+
this.images[0].before(track);
|
|
2686
|
+
this.images.forEach((el) => track.appendChild(el));
|
|
2687
|
+
this._trackEl = track;
|
|
2688
|
+
}
|
|
2689
|
+
_unwrapTrack() {
|
|
2690
|
+
if (!this._trackEl) return;
|
|
2691
|
+
this.images.forEach((el) => this.el.insertBefore(el, this._trackEl));
|
|
2692
|
+
this._trackEl.remove();
|
|
2693
|
+
this._trackEl = null;
|
|
2694
|
+
}
|
|
2695
|
+
_nearestIndex() {
|
|
2696
|
+
const left = this._scroller.scrollLeft;
|
|
2697
|
+
let best = 0;
|
|
2698
|
+
let bestDist = Infinity;
|
|
2699
|
+
this.images.forEach((el, i) => {
|
|
2700
|
+
const dist = Math.abs(el.offsetLeft - left);
|
|
2701
|
+
if (dist < bestDist) {
|
|
2702
|
+
bestDist = dist;
|
|
2703
|
+
best = i;
|
|
2704
|
+
}
|
|
2705
|
+
});
|
|
2706
|
+
return best;
|
|
2707
|
+
}
|
|
2708
|
+
_scrollToIndex(n, smooth = true) {
|
|
2709
|
+
const el = this.images[n];
|
|
2710
|
+
if (!el) return;
|
|
2711
|
+
const left = el.offsetLeft;
|
|
2712
|
+
if (Math.abs(this._scroller.scrollLeft - left) < 1) {
|
|
2713
|
+
this._syncActive(n, false);
|
|
2714
|
+
return;
|
|
2715
|
+
}
|
|
2716
|
+
this._ignoreScroll = true;
|
|
2717
|
+
this._scroller.scrollTo({ left, behavior: smooth ? "smooth" : "auto" });
|
|
2718
|
+
const done = () => {
|
|
2719
|
+
this._ignoreScroll = false;
|
|
2720
|
+
};
|
|
2721
|
+
this._scroller.addEventListener("scrollend", done, { once: true });
|
|
2722
|
+
window.setTimeout(done, this.options.duration + 350);
|
|
2723
|
+
}
|
|
2684
2724
|
_cycleTo(n, callback = null) {
|
|
2725
|
+
if (this._flat) {
|
|
2726
|
+
if (typeof callback === "function") this.oneTimeCallback = callback;
|
|
2727
|
+
this._syncActive(n, false);
|
|
2728
|
+
this._scrollToIndex(n);
|
|
2729
|
+
return;
|
|
2730
|
+
}
|
|
2685
2731
|
let diff = this.center % this.count - n;
|
|
2686
2732
|
if (!this.noWrap) {
|
|
2687
2733
|
if (diff < 0) {
|
|
@@ -2709,14 +2755,8 @@ var Carousel = class _Carousel extends Component {
|
|
|
2709
2755
|
requestAnimationFrame(this._autoScroll);
|
|
2710
2756
|
}
|
|
2711
2757
|
}
|
|
2712
|
-
/**
|
|
2713
|
-
* Move carousel to next slide or go forward a given amount of slides.
|
|
2714
|
-
* @param n How many times the carousel slides.
|
|
2715
|
-
*/
|
|
2716
2758
|
next(n = 1) {
|
|
2717
|
-
if (n === void 0 || isNaN(n))
|
|
2718
|
-
n = 1;
|
|
2719
|
-
}
|
|
2759
|
+
if (n === void 0 || isNaN(n)) n = 1;
|
|
2720
2760
|
let index = this.center + n;
|
|
2721
2761
|
if (index >= this.count || index < 0) {
|
|
2722
2762
|
if (this.noWrap) return;
|
|
@@ -2724,14 +2764,8 @@ var Carousel = class _Carousel extends Component {
|
|
|
2724
2764
|
}
|
|
2725
2765
|
this._cycleTo(index);
|
|
2726
2766
|
}
|
|
2727
|
-
/**
|
|
2728
|
-
* Move carousel to previous slide or go back a given amount of slides.
|
|
2729
|
-
* @param n How many times the carousel slides.
|
|
2730
|
-
*/
|
|
2731
2767
|
prev(n = 1) {
|
|
2732
|
-
if (n === void 0 || isNaN(n))
|
|
2733
|
-
n = 1;
|
|
2734
|
-
}
|
|
2768
|
+
if (n === void 0 || isNaN(n)) n = 1;
|
|
2735
2769
|
let index = this.center - n;
|
|
2736
2770
|
if (index >= this.count || index < 0) {
|
|
2737
2771
|
if (this.noWrap) return;
|
|
@@ -2739,15 +2773,8 @@ var Carousel = class _Carousel extends Component {
|
|
|
2739
2773
|
}
|
|
2740
2774
|
this._cycleTo(index);
|
|
2741
2775
|
}
|
|
2742
|
-
/**
|
|
2743
|
-
* Move carousel to nth slide.
|
|
2744
|
-
* @param n Index of slide.
|
|
2745
|
-
* @param callback "onCycleTo" optional callback.
|
|
2746
|
-
*/
|
|
2747
2776
|
set(n, callback) {
|
|
2748
|
-
if (n === void 0 || isNaN(n))
|
|
2749
|
-
n = 0;
|
|
2750
|
-
}
|
|
2777
|
+
if (n === void 0 || isNaN(n)) n = 0;
|
|
2751
2778
|
if (n > this.count || n < 0) {
|
|
2752
2779
|
if (this.noWrap) return;
|
|
2753
2780
|
n = this._wrap(n);
|
|
@@ -2755,6 +2782,12 @@ var Carousel = class _Carousel extends Component {
|
|
|
2755
2782
|
this._cycleTo(n, callback);
|
|
2756
2783
|
}
|
|
2757
2784
|
};
|
|
2785
|
+
_Carousel._live = /* @__PURE__ */ new Set();
|
|
2786
|
+
_Carousel._resizeListening = false;
|
|
2787
|
+
_Carousel._onResize = Utils.throttle(() => {
|
|
2788
|
+
_Carousel._live.forEach((c) => c._handleResize());
|
|
2789
|
+
}, 200);
|
|
2790
|
+
var Carousel = _Carousel;
|
|
2758
2791
|
|
|
2759
2792
|
// src/ts/components/characterCounter.ts
|
|
2760
2793
|
var _defaults8 = Object.freeze({});
|
|
@@ -2844,77 +2877,75 @@ var _defaults9 = {
|
|
|
2844
2877
|
var Collapsible = class _Collapsible extends Component {
|
|
2845
2878
|
constructor(el, options) {
|
|
2846
2879
|
super(el, options, _Collapsible);
|
|
2847
|
-
this.
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
const collapsible = header.closest(".collapsible");
|
|
2851
|
-
if (collapsible !== this.el) return;
|
|
2852
|
-
const li = header.closest("li");
|
|
2853
|
-
const isActive = li.classList.contains("active");
|
|
2854
|
-
const index = [...li.parentNode.children].indexOf(li);
|
|
2855
|
-
if (isActive) this.close(index);
|
|
2856
|
-
else this.open(index);
|
|
2857
|
-
}
|
|
2858
|
-
};
|
|
2859
|
-
this._handleCollapsibleKeydown = (e) => {
|
|
2860
|
-
if (Utils.keys.ENTER.includes(e.key)) {
|
|
2861
|
-
this._handleCollapsibleClick(e);
|
|
2862
|
-
}
|
|
2863
|
-
};
|
|
2880
|
+
this._items = [];
|
|
2881
|
+
this._endTimers = [];
|
|
2882
|
+
this._wrappedBodies = [];
|
|
2864
2883
|
/**
|
|
2865
2884
|
* Open collapsible section.
|
|
2866
|
-
* @param
|
|
2885
|
+
* @param index 0-based index of the section to open.
|
|
2867
2886
|
*/
|
|
2868
2887
|
this.open = (index) => {
|
|
2869
|
-
const
|
|
2870
|
-
|
|
2871
|
-
if (
|
|
2872
|
-
|
|
2873
|
-
this.
|
|
2874
|
-
}
|
|
2875
|
-
if (this.options.accordion) {
|
|
2876
|
-
const activeLis = listItems.filter((li2) => li2.classList.contains("active"));
|
|
2877
|
-
activeLis.forEach((activeLi) => {
|
|
2878
|
-
const index2 = listItems.indexOf(activeLi);
|
|
2879
|
-
this.close(index2);
|
|
2880
|
-
});
|
|
2881
|
-
}
|
|
2882
|
-
li.classList.add("active");
|
|
2883
|
-
this._animateIn(index);
|
|
2888
|
+
const item = this._items[index];
|
|
2889
|
+
if (!item || this._isOpen(item)) return;
|
|
2890
|
+
if (this.options.accordion) {
|
|
2891
|
+
this._items.forEach((other, i) => {
|
|
2892
|
+
if (i !== index && this._isOpen(other)) this.close(i);
|
|
2893
|
+
});
|
|
2884
2894
|
}
|
|
2895
|
+
this._setOpen(item, true);
|
|
2885
2896
|
};
|
|
2886
2897
|
/**
|
|
2887
2898
|
* Close collapsible section.
|
|
2888
|
-
* @param
|
|
2899
|
+
* @param index 0-based index of the section to close.
|
|
2889
2900
|
*/
|
|
2890
2901
|
this.close = (index) => {
|
|
2891
|
-
const
|
|
2892
|
-
if (
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2902
|
+
const item = this._items[index];
|
|
2903
|
+
if (!item || !this._isOpen(item)) return;
|
|
2904
|
+
this._setOpen(item, false);
|
|
2905
|
+
};
|
|
2906
|
+
this._handleClick = (e) => {
|
|
2907
|
+
const header = e.target.closest(".collapsible-header");
|
|
2908
|
+
if (!header || header.closest(".collapsible") !== this.el) return;
|
|
2909
|
+
if (header.closest("details")) return;
|
|
2910
|
+
const item = header.closest("li");
|
|
2911
|
+
if (!item) return;
|
|
2912
|
+
const index = this._items.indexOf(item);
|
|
2913
|
+
if (index < 0) return;
|
|
2914
|
+
if (this._isOpen(item)) this.close(index);
|
|
2915
|
+
else this.open(index);
|
|
2916
|
+
};
|
|
2917
|
+
this._handleKeydown = (e) => {
|
|
2918
|
+
if (!Utils.keys.ENTER.includes(e.key) && e.key !== " ") return;
|
|
2919
|
+
const header = e.target.closest(".collapsible-header");
|
|
2920
|
+
if (!header || header.closest(".collapsible") !== this.el) return;
|
|
2921
|
+
if (header.closest("details")) return;
|
|
2922
|
+
if (header.matches("a, button")) return;
|
|
2923
|
+
e.preventDefault();
|
|
2924
|
+
const item = header.closest("li");
|
|
2925
|
+
if (!item) return;
|
|
2926
|
+
const index = this._items.indexOf(item);
|
|
2927
|
+
if (index < 0) return;
|
|
2928
|
+
if (this._isOpen(item)) this.close(index);
|
|
2929
|
+
else this.open(index);
|
|
2930
|
+
};
|
|
2931
|
+
this._handleToggle = (e) => {
|
|
2932
|
+
const item = e.target;
|
|
2933
|
+
if (!(item instanceof HTMLDetailsElement)) return;
|
|
2934
|
+
if (!this._items.includes(item)) return;
|
|
2935
|
+
this._notify(item, item.open);
|
|
2899
2936
|
};
|
|
2900
2937
|
this.el["Expressive_Collapsible"] = this;
|
|
2938
|
+
const accordion = options.accordion !== void 0 ? options.accordion : !el.classList.contains("expandable");
|
|
2901
2939
|
this.options = {
|
|
2902
2940
|
..._Collapsible.defaults,
|
|
2903
|
-
...options
|
|
2941
|
+
...options,
|
|
2942
|
+
accordion
|
|
2904
2943
|
};
|
|
2905
|
-
this.
|
|
2906
|
-
this.
|
|
2944
|
+
this._groupName = el.id ? `collapsible-${el.id}` : `collapsible-${Utils.guid()}`;
|
|
2945
|
+
this._items = this._collectItems();
|
|
2946
|
+
this._wrapDetailsBodies();
|
|
2947
|
+
this._setupItems();
|
|
2907
2948
|
this._setupEventHandlers();
|
|
2908
|
-
const activeBodies = Array.from(
|
|
2909
|
-
this.el.querySelectorAll("li.active > .collapsible-body")
|
|
2910
|
-
);
|
|
2911
|
-
if (this.options.accordion) {
|
|
2912
|
-
if (activeBodies.length > 0) {
|
|
2913
|
-
this._setExpanded(activeBodies[0]);
|
|
2914
|
-
}
|
|
2915
|
-
} else {
|
|
2916
|
-
activeBodies.forEach((el2) => this._setExpanded(el2));
|
|
2917
|
-
}
|
|
2918
2949
|
}
|
|
2919
2950
|
static get defaults() {
|
|
2920
2951
|
return _defaults9;
|
|
@@ -2932,48 +2963,130 @@ var Collapsible = class _Collapsible extends Component {
|
|
|
2932
2963
|
}
|
|
2933
2964
|
destroy() {
|
|
2934
2965
|
this._removeEventHandlers();
|
|
2966
|
+
this._endTimers.forEach((id) => clearTimeout(id));
|
|
2967
|
+
this._endTimers = [];
|
|
2968
|
+
this._unwrapDetailsBodies();
|
|
2935
2969
|
this.el["Expressive_Collapsible"] = void 0;
|
|
2936
2970
|
}
|
|
2937
|
-
|
|
2938
|
-
this.el.
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
);
|
|
2971
|
+
_collectItems() {
|
|
2972
|
+
const details = Array.from(this.el.querySelectorAll(":scope > details"));
|
|
2973
|
+
if (details.length) return details;
|
|
2974
|
+
return Array.from(this.el.children).filter((c) => c.tagName === "LI");
|
|
2942
2975
|
}
|
|
2943
|
-
|
|
2944
|
-
this.
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2976
|
+
_setupItems() {
|
|
2977
|
+
if (this.options.accordion) {
|
|
2978
|
+
this._items.forEach((item) => {
|
|
2979
|
+
if (item instanceof HTMLDetailsElement && !item.getAttribute("name")) {
|
|
2980
|
+
item.setAttribute("name", this._groupName);
|
|
2981
|
+
}
|
|
2982
|
+
});
|
|
2983
|
+
}
|
|
2984
|
+
const opened = this._items.filter((item) => this._isOpen(item));
|
|
2985
|
+
if (this.options.accordion && opened.length > 1) {
|
|
2986
|
+
opened.slice(1).forEach((item) => {
|
|
2987
|
+
if (item instanceof HTMLDetailsElement) item.open = false;
|
|
2988
|
+
else item.classList.remove("active");
|
|
2989
|
+
});
|
|
2990
|
+
}
|
|
2991
|
+
this._items.forEach((item) => this._syncAria(item));
|
|
2948
2992
|
}
|
|
2949
|
-
|
|
2950
|
-
|
|
2993
|
+
_isOpen(item) {
|
|
2994
|
+
if (item instanceof HTMLDetailsElement) return item.open;
|
|
2995
|
+
return item.classList.contains("active");
|
|
2951
2996
|
}
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
this.
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2997
|
+
_setOpen(item, open) {
|
|
2998
|
+
if (item instanceof HTMLDetailsElement) {
|
|
2999
|
+
item.open = open;
|
|
3000
|
+
return;
|
|
3001
|
+
}
|
|
3002
|
+
item.classList.toggle("active", open);
|
|
3003
|
+
this._syncAria(item);
|
|
3004
|
+
this._notify(item, open);
|
|
3005
|
+
}
|
|
3006
|
+
_headerOf(item) {
|
|
3007
|
+
if (item instanceof HTMLDetailsElement) {
|
|
3008
|
+
return item.querySelector(":scope > summary");
|
|
3009
|
+
}
|
|
3010
|
+
return item.querySelector(":scope > .collapsible-header");
|
|
3011
|
+
}
|
|
3012
|
+
_wrapDetailsBodies() {
|
|
3013
|
+
this._items.forEach((item) => {
|
|
3014
|
+
if (!(item instanceof HTMLDetailsElement)) return;
|
|
3015
|
+
if (item.querySelector(":scope > .collapsible-body")) return;
|
|
3016
|
+
const body = document.createElement("div");
|
|
3017
|
+
body.className = "collapsible-body";
|
|
3018
|
+
Array.from(item.childNodes).forEach((node) => {
|
|
3019
|
+
if (node instanceof HTMLElement && node.tagName === "SUMMARY") return;
|
|
3020
|
+
body.appendChild(node);
|
|
3021
|
+
});
|
|
3022
|
+
item.appendChild(body);
|
|
3023
|
+
this._wrappedBodies.push(body);
|
|
3024
|
+
});
|
|
2964
3025
|
}
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
3026
|
+
_unwrapDetailsBodies() {
|
|
3027
|
+
this._wrappedBodies.forEach((body) => {
|
|
3028
|
+
const parent = body.parentNode;
|
|
3029
|
+
if (!parent) return;
|
|
3030
|
+
while (body.firstChild) parent.insertBefore(body.firstChild, body);
|
|
3031
|
+
body.remove();
|
|
3032
|
+
});
|
|
3033
|
+
this._wrappedBodies = [];
|
|
3034
|
+
}
|
|
3035
|
+
_bodyOf(item) {
|
|
3036
|
+
return item.querySelector(":scope > .collapsible-body");
|
|
3037
|
+
}
|
|
3038
|
+
_syncAria(item) {
|
|
3039
|
+
if (item instanceof HTMLDetailsElement) return;
|
|
3040
|
+
const header = this._headerOf(item);
|
|
3041
|
+
const body = this._bodyOf(item);
|
|
3042
|
+
if (!header) return;
|
|
3043
|
+
header.setAttribute("aria-expanded", String(this._isOpen(item)));
|
|
3044
|
+
if (body) {
|
|
3045
|
+
if (!body.id) body.id = `collapsible-body-${Utils.guid()}`;
|
|
3046
|
+
header.setAttribute("aria-controls", body.id);
|
|
3047
|
+
}
|
|
3048
|
+
if (!header.matches("a, button, summary")) {
|
|
3049
|
+
header.setAttribute("role", "button");
|
|
3050
|
+
if (header.tabIndex < 0) header.tabIndex = 0;
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
_setupEventHandlers() {
|
|
3054
|
+
this.el.addEventListener("click", this._handleClick);
|
|
3055
|
+
this.el.addEventListener("keydown", this._handleKeydown);
|
|
3056
|
+
this.el.addEventListener("toggle", this._handleToggle, true);
|
|
3057
|
+
}
|
|
3058
|
+
_removeEventHandlers() {
|
|
3059
|
+
this.el.removeEventListener("click", this._handleClick);
|
|
3060
|
+
this.el.removeEventListener("keydown", this._handleKeydown);
|
|
3061
|
+
this.el.removeEventListener("toggle", this._handleToggle, true);
|
|
3062
|
+
}
|
|
3063
|
+
_notify(item, opening) {
|
|
3064
|
+
const start = opening ? this.options.onOpenStart : this.options.onCloseStart;
|
|
3065
|
+
if (typeof start === "function") start.call(this, item);
|
|
3066
|
+
const end = opening ? this.options.onOpenEnd : this.options.onCloseEnd;
|
|
3067
|
+
if (typeof end !== "function") return;
|
|
3068
|
+
const target = this._bodyOf(item) ?? item;
|
|
3069
|
+
let done = false;
|
|
3070
|
+
const finish = () => {
|
|
3071
|
+
if (done) return;
|
|
3072
|
+
done = true;
|
|
3073
|
+
target.removeEventListener("transitionend", onEnd);
|
|
3074
|
+
end.call(this, item);
|
|
3075
|
+
};
|
|
3076
|
+
const onEnd = (ev) => {
|
|
3077
|
+
if (ev.target !== target) return;
|
|
3078
|
+
finish();
|
|
3079
|
+
};
|
|
3080
|
+
target.addEventListener("transitionend", onEnd);
|
|
3081
|
+
this._endTimers.push(window.setTimeout(finish, this._durationMs() + 50));
|
|
3082
|
+
}
|
|
3083
|
+
_durationMs() {
|
|
3084
|
+
const raw = getComputedStyle(this.el).getPropertyValue("--md-comp-collapsible-duration").trim();
|
|
3085
|
+
if (!raw) return 500;
|
|
3086
|
+
if (raw.endsWith("ms")) return parseFloat(raw);
|
|
3087
|
+
if (raw.endsWith("s")) return parseFloat(raw) * 1e3;
|
|
3088
|
+
const n = parseFloat(raw);
|
|
3089
|
+
return Number.isFinite(n) ? n : 500;
|
|
2977
3090
|
}
|
|
2978
3091
|
};
|
|
2979
3092
|
|
|
@@ -4773,38 +4886,22 @@ var Modal = _Modal;
|
|
|
4773
4886
|
// src/ts/components/parallax.ts
|
|
4774
4887
|
var _defaults15 = {
|
|
4775
4888
|
responsiveThreshold: 0
|
|
4776
|
-
// breakpoint for swipeable
|
|
4777
4889
|
};
|
|
4778
|
-
var
|
|
4890
|
+
var Parallax = class _Parallax extends Component {
|
|
4779
4891
|
constructor(el, options) {
|
|
4780
4892
|
super(el, options, _Parallax);
|
|
4781
|
-
this._handleImageLoad = () => {
|
|
4782
|
-
this._updateParallax();
|
|
4783
|
-
};
|
|
4784
4893
|
this.el["Expressive_Parallax"] = this;
|
|
4785
4894
|
this.options = {
|
|
4786
4895
|
..._Parallax.defaults,
|
|
4787
4896
|
...options
|
|
4788
4897
|
};
|
|
4789
|
-
this.
|
|
4790
|
-
|
|
4791
|
-
if (!this._img) {
|
|
4792
|
-
console.error("Parallax: no <img> to move inside the .parallax element");
|
|
4793
|
-
return;
|
|
4898
|
+
if (!this.el.querySelector("img, video")) {
|
|
4899
|
+
console.error("Parallax: no <img> or <video> to move inside the .parallax element");
|
|
4794
4900
|
}
|
|
4795
|
-
this._updateParallax();
|
|
4796
|
-
this._setupEventHandlers();
|
|
4797
|
-
this._setupStyles();
|
|
4798
|
-
_Parallax._parallaxes.push(this);
|
|
4799
4901
|
}
|
|
4800
4902
|
static get defaults() {
|
|
4801
4903
|
return _defaults15;
|
|
4802
4904
|
}
|
|
4803
|
-
/**
|
|
4804
|
-
* Initializes instances of Parallax.
|
|
4805
|
-
* @param els HTML elements.
|
|
4806
|
-
* @param options Component options.
|
|
4807
|
-
*/
|
|
4808
4905
|
static init(els, options = {}) {
|
|
4809
4906
|
return super.init(els, options, _Parallax);
|
|
4810
4907
|
}
|
|
@@ -4812,84 +4909,9 @@ var _Parallax = class _Parallax extends Component {
|
|
|
4812
4909
|
return el["Expressive_Parallax"];
|
|
4813
4910
|
}
|
|
4814
4911
|
destroy() {
|
|
4815
|
-
const index = _Parallax._parallaxes.indexOf(this);
|
|
4816
|
-
if (index >= 0) _Parallax._parallaxes.splice(index, 1);
|
|
4817
|
-
if (this._img) this._img.style.transform = "";
|
|
4818
|
-
this._removeEventHandlers();
|
|
4819
4912
|
this.el["Expressive_Parallax"] = void 0;
|
|
4820
4913
|
}
|
|
4821
|
-
static _handleScroll() {
|
|
4822
|
-
for (let i = 0; i < _Parallax._parallaxes.length; i++) {
|
|
4823
|
-
const parallaxInstance = _Parallax._parallaxes[i];
|
|
4824
|
-
parallaxInstance._updateParallax.call(parallaxInstance);
|
|
4825
|
-
}
|
|
4826
|
-
}
|
|
4827
|
-
static _handleWindowResize() {
|
|
4828
|
-
for (let i = 0; i < _Parallax._parallaxes.length; i++) {
|
|
4829
|
-
const parallaxInstance = _Parallax._parallaxes[i];
|
|
4830
|
-
parallaxInstance._enabled = window.innerWidth > parallaxInstance.options.responsiveThreshold;
|
|
4831
|
-
}
|
|
4832
|
-
}
|
|
4833
|
-
_setupEventHandlers() {
|
|
4834
|
-
this._img?.addEventListener("load", this._handleImageLoad);
|
|
4835
|
-
if (_Parallax._parallaxes.length === 0) {
|
|
4836
|
-
if (!_Parallax._handleWindowResizeThrottled) {
|
|
4837
|
-
_Parallax._handleWindowResizeThrottled = Utils.throttle(_Parallax._handleWindowResize, 100);
|
|
4838
|
-
}
|
|
4839
|
-
window.addEventListener("scroll", _Parallax._requestScrollUpdate, { passive: true });
|
|
4840
|
-
window.addEventListener("resize", _Parallax._handleWindowResizeThrottled, { passive: true });
|
|
4841
|
-
}
|
|
4842
|
-
}
|
|
4843
|
-
_removeEventHandlers() {
|
|
4844
|
-
this._img?.removeEventListener("load", this._handleImageLoad);
|
|
4845
|
-
if (_Parallax._parallaxes.length === 0) {
|
|
4846
|
-
window.removeEventListener("scroll", _Parallax._requestScrollUpdate);
|
|
4847
|
-
window.removeEventListener("resize", _Parallax._handleWindowResizeThrottled);
|
|
4848
|
-
if (_Parallax._scrollFrame !== null) {
|
|
4849
|
-
cancelAnimationFrame(_Parallax._scrollFrame);
|
|
4850
|
-
_Parallax._scrollFrame = null;
|
|
4851
|
-
}
|
|
4852
|
-
}
|
|
4853
|
-
}
|
|
4854
|
-
_setupStyles() {
|
|
4855
|
-
if (this._img) this._img.style.opacity = "1";
|
|
4856
|
-
}
|
|
4857
|
-
_updateParallax() {
|
|
4858
|
-
const rect = this.el.getBoundingClientRect();
|
|
4859
|
-
const containerHeight = rect.height > 0 ? this.el.parentElement.offsetHeight : 500;
|
|
4860
|
-
const imgHeight = this._img.offsetHeight;
|
|
4861
|
-
const parallaxDist = imgHeight - containerHeight;
|
|
4862
|
-
const top = rect.top + window.scrollY - document.documentElement.clientTop;
|
|
4863
|
-
const bottom = top + containerHeight;
|
|
4864
|
-
const scrollTop = Utils.getDocumentScrollTop();
|
|
4865
|
-
const windowHeight = window.innerHeight;
|
|
4866
|
-
const windowBottom = scrollTop + windowHeight;
|
|
4867
|
-
const percentScrolled = (windowBottom - top) / (containerHeight + windowHeight);
|
|
4868
|
-
const parallax = parallaxDist * percentScrolled;
|
|
4869
|
-
if (!this._enabled) {
|
|
4870
|
-
this._img.style.transform = "";
|
|
4871
|
-
} else if (bottom > scrollTop && top < scrollTop + windowHeight) {
|
|
4872
|
-
this._img.style.transform = `translate3D(-50%, ${parallax}px, 0)`;
|
|
4873
|
-
}
|
|
4874
|
-
}
|
|
4875
4914
|
};
|
|
4876
|
-
_Parallax._parallaxes = [];
|
|
4877
|
-
_Parallax._scrollFrame = null;
|
|
4878
|
-
/**
|
|
4879
|
-
* Coalesce scroll events onto animation frames.
|
|
4880
|
-
*
|
|
4881
|
-
* The handler reads layout and then writes a transform, so running it more
|
|
4882
|
-
* than once per frame is wasted work - and the 5ms throttle it replaces was
|
|
4883
|
-
* short enough to let several run per frame anyway.
|
|
4884
|
-
*/
|
|
4885
|
-
_Parallax._requestScrollUpdate = () => {
|
|
4886
|
-
if (_Parallax._scrollFrame !== null) return;
|
|
4887
|
-
_Parallax._scrollFrame = requestAnimationFrame(() => {
|
|
4888
|
-
_Parallax._scrollFrame = null;
|
|
4889
|
-
_Parallax._handleScroll();
|
|
4890
|
-
});
|
|
4891
|
-
};
|
|
4892
|
-
var Parallax = _Parallax;
|
|
4893
4915
|
|
|
4894
4916
|
// src/ts/components/pushpin.ts
|
|
4895
4917
|
var _defaults16 = {
|
|
@@ -6129,60 +6151,96 @@ var _defaults21 = {
|
|
|
6129
6151
|
var _TapTarget = class _TapTarget extends Component {
|
|
6130
6152
|
constructor(el, options) {
|
|
6131
6153
|
super(el, options, _TapTarget);
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
this.
|
|
6135
|
-
this.
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
this._handleTargetToggle = () => {
|
|
6141
|
-
if (!this.isOpen) this.open();
|
|
6142
|
-
else this.close();
|
|
6143
|
-
};
|
|
6144
|
-
/*_handleOriginClick = () => {
|
|
6145
|
-
this.close();
|
|
6146
|
-
}*/
|
|
6147
|
-
this._handleResize = () => {
|
|
6148
|
-
this._calculatePositioning();
|
|
6149
|
-
};
|
|
6150
|
-
this._handleDocumentClick = (e) => {
|
|
6151
|
-
const target = e.target;
|
|
6152
|
-
if (!(target instanceof Element)) return;
|
|
6153
|
-
if (!this.originEl.contains(target) && !target.closest(".tap-target-wrapper")) {
|
|
6154
|
-
this.close();
|
|
6155
|
-
}
|
|
6156
|
-
};
|
|
6154
|
+
this.wrapper = null;
|
|
6155
|
+
this.waveEl = null;
|
|
6156
|
+
this.contentEl = null;
|
|
6157
|
+
this._createdWrapper = false;
|
|
6158
|
+
this._createdWave = false;
|
|
6159
|
+
this._usePopover = false;
|
|
6160
|
+
this._liftedStatic = false;
|
|
6161
|
+
this._opening = false;
|
|
6157
6162
|
/**
|
|
6158
6163
|
* Open Tap Target.
|
|
6159
6164
|
*/
|
|
6160
6165
|
this.open = () => {
|
|
6161
|
-
if (this.isOpen) return;
|
|
6166
|
+
if (this.isOpen || !this.originEl || !this.wrapper) return;
|
|
6167
|
+
_TapTarget._taptargets.forEach((other) => {
|
|
6168
|
+
if (other !== this) other.close();
|
|
6169
|
+
});
|
|
6170
|
+
this._calculatePositioning();
|
|
6162
6171
|
if (typeof this.options.onOpen === "function") {
|
|
6163
6172
|
this.options.onOpen.call(this, this.originEl);
|
|
6164
6173
|
}
|
|
6165
6174
|
this.isOpen = true;
|
|
6166
6175
|
this.wrapper.classList.add("open");
|
|
6167
|
-
this.
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6176
|
+
this.originEl.setAttribute("aria-expanded", "true");
|
|
6177
|
+
if (!this._usePopover) {
|
|
6178
|
+
this.originEl.classList.add("tap-target-origin");
|
|
6179
|
+
if (getComputedStyle(this.originEl).position === "static") {
|
|
6180
|
+
this.originEl.style.position = "relative";
|
|
6181
|
+
this._liftedStatic = true;
|
|
6182
|
+
}
|
|
6183
|
+
}
|
|
6184
|
+
if (this._usePopover) {
|
|
6185
|
+
this._opening = true;
|
|
6186
|
+
try {
|
|
6187
|
+
this.wrapper.showPopover();
|
|
6188
|
+
} catch {
|
|
6189
|
+
}
|
|
6190
|
+
requestAnimationFrame(() => {
|
|
6191
|
+
this._opening = false;
|
|
6192
|
+
});
|
|
6193
|
+
}
|
|
6171
6194
|
};
|
|
6172
6195
|
/**
|
|
6173
6196
|
* Close Tap Target.
|
|
6174
6197
|
*/
|
|
6175
6198
|
this.close = () => {
|
|
6176
6199
|
if (!this.isOpen) return;
|
|
6177
|
-
if (typeof this.options.onClose === "function") {
|
|
6200
|
+
if (typeof this.options.onClose === "function" && this.originEl) {
|
|
6178
6201
|
this.options.onClose.call(this, this.originEl);
|
|
6179
6202
|
}
|
|
6180
6203
|
this.isOpen = false;
|
|
6181
|
-
this.wrapper
|
|
6182
|
-
this.
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6204
|
+
this.wrapper?.classList.remove("open");
|
|
6205
|
+
this.originEl?.setAttribute("aria-expanded", "false");
|
|
6206
|
+
this.originEl?.classList.remove("tap-target-origin");
|
|
6207
|
+
if (this._liftedStatic && this.originEl) {
|
|
6208
|
+
this.originEl.style.position = "";
|
|
6209
|
+
this._liftedStatic = false;
|
|
6210
|
+
}
|
|
6211
|
+
if (this._usePopover && this.wrapper) {
|
|
6212
|
+
try {
|
|
6213
|
+
this.wrapper.hidePopover();
|
|
6214
|
+
} catch {
|
|
6215
|
+
}
|
|
6216
|
+
}
|
|
6217
|
+
};
|
|
6218
|
+
// Built once per instance; a fresh throttle per event never fires.
|
|
6219
|
+
this._handleThrottledResize = Utils.throttle(() => this._handleResize(), 200);
|
|
6220
|
+
this._handleOriginKeydown = (e) => {
|
|
6221
|
+
if (Utils.keys.ENTER.includes(e.key) || e.key === " ") {
|
|
6222
|
+
e.preventDefault();
|
|
6223
|
+
this._handleTargetToggle();
|
|
6224
|
+
}
|
|
6225
|
+
};
|
|
6226
|
+
this._handleTargetToggle = () => {
|
|
6227
|
+
if (!this.isOpen) this.open();
|
|
6228
|
+
else this.close();
|
|
6229
|
+
};
|
|
6230
|
+
this._handleResize = () => {
|
|
6231
|
+
if (this.isOpen) this._calculatePositioning();
|
|
6232
|
+
};
|
|
6233
|
+
this._handlePopoverToggle = (e) => {
|
|
6234
|
+
const state = "newState" in e ? String(e.newState) : "";
|
|
6235
|
+
if (state === "open") return;
|
|
6236
|
+
if (this._opening) {
|
|
6237
|
+
try {
|
|
6238
|
+
this.wrapper?.showPopover();
|
|
6239
|
+
} catch {
|
|
6240
|
+
}
|
|
6241
|
+
return;
|
|
6242
|
+
}
|
|
6243
|
+
if (this.isOpen) this.close();
|
|
6186
6244
|
};
|
|
6187
6245
|
this.el["Expressive_TapTarget"] = this;
|
|
6188
6246
|
this.options = {
|
|
@@ -6195,7 +6253,6 @@ var _TapTarget = class _TapTarget extends Component {
|
|
|
6195
6253
|
console.error(`TapTarget: no element with id "${el.dataset.target ?? ""}" to attach to`);
|
|
6196
6254
|
return;
|
|
6197
6255
|
}
|
|
6198
|
-
this.originEl.tabIndex = 0;
|
|
6199
6256
|
this._setup();
|
|
6200
6257
|
this._calculatePositioning();
|
|
6201
6258
|
this._setupEventHandlers();
|
|
@@ -6204,11 +6261,6 @@ var _TapTarget = class _TapTarget extends Component {
|
|
|
6204
6261
|
static get defaults() {
|
|
6205
6262
|
return _defaults21;
|
|
6206
6263
|
}
|
|
6207
|
-
/**
|
|
6208
|
-
* Initializes instances of TapTarget.
|
|
6209
|
-
* @param els HTML elements.
|
|
6210
|
-
* @param options Component options.
|
|
6211
|
-
*/
|
|
6212
6264
|
static init(els, options = {}) {
|
|
6213
6265
|
return super.init(els, options, _TapTarget);
|
|
6214
6266
|
}
|
|
@@ -6218,116 +6270,95 @@ var _TapTarget = class _TapTarget extends Component {
|
|
|
6218
6270
|
destroy() {
|
|
6219
6271
|
this.close();
|
|
6220
6272
|
this._removeEventHandlers();
|
|
6273
|
+
this._teardownDom();
|
|
6221
6274
|
this.el["Expressive_TapTarget"] = void 0;
|
|
6222
6275
|
const index = _TapTarget._taptargets.indexOf(this);
|
|
6223
|
-
if (index >= 0)
|
|
6224
|
-
_TapTarget._taptargets.splice(index, 1);
|
|
6225
|
-
}
|
|
6226
|
-
}
|
|
6227
|
-
_setupEventHandlers() {
|
|
6228
|
-
if (!this.originEl) return;
|
|
6229
|
-
this.originEl.addEventListener("click", this._handleTargetToggle);
|
|
6230
|
-
this.originEl.addEventListener("keypress", this._handleKeyboardInteraction, true);
|
|
6231
|
-
window.addEventListener("resize", this._handleThrottledResize);
|
|
6232
|
-
}
|
|
6233
|
-
_removeEventHandlers() {
|
|
6234
|
-
if (!this.originEl) return;
|
|
6235
|
-
this.originEl.removeEventListener("click", this._handleTargetToggle);
|
|
6236
|
-
this.originEl.removeEventListener("keypress", this._handleKeyboardInteraction, true);
|
|
6237
|
-
window.removeEventListener("resize", this._handleThrottledResize);
|
|
6276
|
+
if (index >= 0) _TapTarget._taptargets.splice(index, 1);
|
|
6238
6277
|
}
|
|
6239
6278
|
_setup() {
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
this.contentEl = this.el.querySelector(".tap-target-content");
|
|
6245
|
-
if (!this.wrapper.classList.contains(".tap-target-wrapper")) {
|
|
6279
|
+
const parent = this.el.parentElement;
|
|
6280
|
+
if (parent?.classList.contains("tap-target-wrapper")) {
|
|
6281
|
+
this.wrapper = parent;
|
|
6282
|
+
} else {
|
|
6246
6283
|
this.wrapper = document.createElement("div");
|
|
6247
6284
|
this.wrapper.classList.add("tap-target-wrapper");
|
|
6248
6285
|
this.el.before(this.wrapper);
|
|
6249
6286
|
this.wrapper.append(this.el);
|
|
6287
|
+
this._createdWrapper = true;
|
|
6250
6288
|
}
|
|
6289
|
+
this.contentEl = this.el.querySelector(".tap-target-content");
|
|
6251
6290
|
if (!this.contentEl) {
|
|
6252
6291
|
this.contentEl = document.createElement("div");
|
|
6253
|
-
this.contentEl.
|
|
6292
|
+
this.contentEl.className = "tap-target-content";
|
|
6293
|
+
while (this.el.firstChild) this.contentEl.append(this.el.firstChild);
|
|
6254
6294
|
this.el.append(this.contentEl);
|
|
6255
6295
|
}
|
|
6296
|
+
this.waveEl = this.el.querySelector(".tap-target-wave") ?? this.wrapper.querySelector(".tap-target-wave");
|
|
6256
6297
|
if (!this.waveEl) {
|
|
6257
6298
|
this.waveEl = document.createElement("div");
|
|
6258
|
-
this.waveEl.
|
|
6259
|
-
this.
|
|
6299
|
+
this.waveEl.className = "tap-target-wave";
|
|
6300
|
+
this._createdWave = true;
|
|
6301
|
+
}
|
|
6302
|
+
this.el.prepend(this.waveEl);
|
|
6303
|
+
this.el.setAttribute("role", "dialog");
|
|
6304
|
+
this._labelFromHeading();
|
|
6305
|
+
const origin = this.originEl;
|
|
6306
|
+
origin.setAttribute("aria-expanded", "false");
|
|
6307
|
+
origin.setAttribute("aria-controls", this.el.id || this._ensureId());
|
|
6308
|
+
this._usePopover = typeof this.wrapper.showPopover === "function";
|
|
6309
|
+
if (this._usePopover) {
|
|
6310
|
+
this.wrapper.setAttribute("popover", "auto");
|
|
6311
|
+
}
|
|
6312
|
+
}
|
|
6313
|
+
_ensureId() {
|
|
6314
|
+
if (!this.el.id) this.el.id = `tap-target-${Utils.guid()}`;
|
|
6315
|
+
return this.el.id;
|
|
6316
|
+
}
|
|
6317
|
+
_labelFromHeading() {
|
|
6318
|
+
const heading = this.contentEl?.querySelector("h1, h2, h3, h4, h5, h6");
|
|
6319
|
+
if (!heading) return;
|
|
6320
|
+
if (!heading.id) heading.id = `tap-target-title-${Utils.guid()}`;
|
|
6321
|
+
this.el.setAttribute("aria-labelledby", heading.id);
|
|
6322
|
+
}
|
|
6323
|
+
_teardownDom() {
|
|
6324
|
+
if (this._createdWave) this.waveEl?.remove();
|
|
6325
|
+
if (this._createdWrapper && this.wrapper) {
|
|
6326
|
+
this.wrapper.before(this.el);
|
|
6327
|
+
this.wrapper.remove();
|
|
6328
|
+
}
|
|
6329
|
+
this.wrapper = null;
|
|
6330
|
+
this.waveEl = null;
|
|
6331
|
+
}
|
|
6332
|
+
_setupEventHandlers() {
|
|
6333
|
+
if (!this.originEl) return;
|
|
6334
|
+
this.originEl.addEventListener("click", this._handleTargetToggle);
|
|
6335
|
+
if (!this.originEl.matches('button, a, [tabindex], .btn, [role="button"]')) {
|
|
6336
|
+
this.originEl.tabIndex = 0;
|
|
6337
|
+
this.originEl.addEventListener("keydown", this._handleOriginKeydown);
|
|
6260
6338
|
}
|
|
6339
|
+
this.wrapper?.addEventListener("toggle", this._handlePopoverToggle);
|
|
6340
|
+
window.addEventListener("resize", this._handleThrottledResize, { passive: true });
|
|
6261
6341
|
}
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
};
|
|
6342
|
+
_removeEventHandlers() {
|
|
6343
|
+
if (!this.originEl) return;
|
|
6344
|
+
this.originEl.removeEventListener("click", this._handleTargetToggle);
|
|
6345
|
+
this.originEl.removeEventListener("keydown", this._handleOriginKeydown);
|
|
6346
|
+
this.wrapper?.removeEventListener("toggle", this._handlePopoverToggle);
|
|
6347
|
+
window.removeEventListener("resize", this._handleThrottledResize);
|
|
6269
6348
|
}
|
|
6270
6349
|
_calculatePositioning() {
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
const originHeight = this.originEl.offsetHeight;
|
|
6284
|
-
const originOffset = this._offset(this.originEl);
|
|
6285
|
-
const originTop = isFixed ? originOffset.top - Utils.getDocumentScrollTop() : originOffset.top;
|
|
6286
|
-
const originLeft = isFixed ? originOffset.left - Utils.getDocumentScrollLeft() : originOffset.left;
|
|
6287
|
-
const windowWidth = window.innerWidth;
|
|
6288
|
-
const windowHeight = window.innerHeight;
|
|
6289
|
-
const scrollBarWidth = windowWidth - document.documentElement.clientWidth;
|
|
6290
|
-
const centerX = windowWidth / 2;
|
|
6291
|
-
const centerY = windowHeight / 2;
|
|
6292
|
-
const isLeft = originLeft <= centerX;
|
|
6293
|
-
const isRight = originLeft > centerX;
|
|
6294
|
-
const isTop = originTop <= centerY;
|
|
6295
|
-
const isBottom = originTop > centerY;
|
|
6296
|
-
const isCenterX = originLeft >= windowWidth * 0.25 && originLeft <= windowWidth * 0.75;
|
|
6297
|
-
const tapTargetWidth = this.el.offsetWidth;
|
|
6298
|
-
const tapTargetHeight = this.el.offsetHeight;
|
|
6299
|
-
const tapTargetTop = originTop + originHeight / 2 - tapTargetHeight / 2;
|
|
6300
|
-
const tapTargetLeft = originLeft + originWidth / 2 - tapTargetWidth / 2;
|
|
6301
|
-
const tapTargetPosition = isFixed ? "fixed" : "absolute";
|
|
6302
|
-
const tapTargetTextWidth = isCenterX ? tapTargetWidth : tapTargetWidth / 2 + originWidth;
|
|
6303
|
-
const tapTargetTextHeight = tapTargetHeight / 2;
|
|
6304
|
-
const tapTargetTextTop = isTop ? tapTargetHeight / 2 : 0;
|
|
6305
|
-
const tapTargetTextBottom = 0;
|
|
6306
|
-
const tapTargetTextLeft = isLeft && !isCenterX ? tapTargetWidth / 2 - originWidth : 0;
|
|
6307
|
-
const tapTargetTextRight = 0;
|
|
6308
|
-
const tapTargetTextPadding = originWidth;
|
|
6309
|
-
const tapTargetTextAlign = isBottom ? "bottom" : "top";
|
|
6310
|
-
const tapTargetWaveWidth = originWidth > originHeight ? originWidth * 2 : originWidth * 2;
|
|
6311
|
-
const tapTargetWaveHeight = tapTargetWaveWidth;
|
|
6312
|
-
const tapTargetWaveTop = tapTargetHeight / 2 - tapTargetWaveHeight / 2;
|
|
6313
|
-
const tapTargetWaveLeft = tapTargetWidth / 2 - tapTargetWaveWidth / 2;
|
|
6314
|
-
this.wrapper.style.top = isTop ? tapTargetTop + "px" : "";
|
|
6315
|
-
this.wrapper.style.right = isRight ? windowWidth - tapTargetLeft - tapTargetWidth - scrollBarWidth + "px" : "";
|
|
6316
|
-
this.wrapper.style.bottom = isBottom ? windowHeight - tapTargetTop - tapTargetHeight + "px" : "";
|
|
6317
|
-
this.wrapper.style.left = isLeft ? tapTargetLeft + "px" : "";
|
|
6318
|
-
this.wrapper.style.position = tapTargetPosition;
|
|
6319
|
-
this.contentEl.style.width = tapTargetTextWidth + "px";
|
|
6320
|
-
this.contentEl.style.height = tapTargetTextHeight + "px";
|
|
6321
|
-
this.contentEl.style.top = tapTargetTextTop + "px";
|
|
6322
|
-
this.contentEl.style.right = tapTargetTextRight + "px";
|
|
6323
|
-
this.contentEl.style.bottom = tapTargetTextBottom + "px";
|
|
6324
|
-
this.contentEl.style.left = tapTargetTextLeft + "px";
|
|
6325
|
-
this.contentEl.style.padding = tapTargetTextPadding + "px";
|
|
6326
|
-
this.contentEl.style.verticalAlign = tapTargetTextAlign;
|
|
6327
|
-
this.waveEl.style.top = tapTargetWaveTop + "px";
|
|
6328
|
-
this.waveEl.style.left = tapTargetWaveLeft + "px";
|
|
6329
|
-
this.waveEl.style.width = tapTargetWaveWidth + "px";
|
|
6330
|
-
this.waveEl.style.height = tapTargetWaveHeight + "px";
|
|
6350
|
+
if (!this.originEl || !this.wrapper) return;
|
|
6351
|
+
const rect = this.originEl.getBoundingClientRect();
|
|
6352
|
+
const x = rect.left + rect.width / 2;
|
|
6353
|
+
const y = rect.top + rect.height / 2;
|
|
6354
|
+
const size = Math.max(rect.width, rect.height, 1);
|
|
6355
|
+
this.wrapper.style.setProperty("--md-comp-tap-target-x", `${x}px`);
|
|
6356
|
+
this.wrapper.style.setProperty("--md-comp-tap-target-y", `${y}px`);
|
|
6357
|
+
this.wrapper.style.setProperty("--md-comp-tap-target-origin-size", `${size}px`);
|
|
6358
|
+
const vertical = y <= window.innerHeight / 2 ? "top" : "bottom";
|
|
6359
|
+
const onCenter = x >= window.innerWidth * 0.25 && x <= window.innerWidth * 0.75;
|
|
6360
|
+
const horizontal = onCenter ? "center" : x <= window.innerWidth / 2 ? "left" : "right";
|
|
6361
|
+
this.wrapper.dataset.edge = `${vertical}-${horizontal}`;
|
|
6331
6362
|
}
|
|
6332
6363
|
};
|
|
6333
6364
|
_TapTarget._taptargets = [];
|
|
@@ -7071,7 +7102,7 @@ var _Toast = class _Toast {
|
|
|
7071
7102
|
close.className = "circle";
|
|
7072
7103
|
close.setAttribute("aria-label", "Dismiss");
|
|
7073
7104
|
const icon = document.createElement("i");
|
|
7074
|
-
icon.className = "material-
|
|
7105
|
+
icon.className = "material-symbols";
|
|
7075
7106
|
icon.setAttribute("aria-hidden", "true");
|
|
7076
7107
|
icon.textContent = "close";
|
|
7077
7108
|
close.appendChild(icon);
|
|
@@ -7436,7 +7467,7 @@ function AutoInit(context = document.body, options) {
|
|
|
7436
7467
|
}
|
|
7437
7468
|
|
|
7438
7469
|
// src/ts/index.ts
|
|
7439
|
-
var version = "0.
|
|
7470
|
+
var version = "0.3.0";
|
|
7440
7471
|
if (typeof document !== "undefined") {
|
|
7441
7472
|
document.addEventListener("keydown", Utils.docHandleKeydown, true);
|
|
7442
7473
|
document.addEventListener("keyup", Utils.docHandleKeyup, true);
|
|
@@ -7448,4 +7479,5 @@ Chips.Init();
|
|
|
7448
7479
|
Waves.Init();
|
|
7449
7480
|
Range.Init();
|
|
7450
7481
|
Cards.Init();
|
|
7482
|
+
Dialogs.Init();
|
|
7451
7483
|
//# sourceMappingURL=expressive.cjs.map
|