@expressivecss/expressive 0.9.1 → 0.10.1
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/CHANGELOG.md +184 -1
- package/README.md +178 -25
- package/dist/css/expressive.css +428 -1222
- 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/fonts/material-symbols-outlined.woff2 +0 -0
- package/dist/fonts/material-symbols-rounded.woff2 +0 -0
- package/dist/fonts/material-symbols-sharp.woff2 +0 -0
- package/dist/js/chunks/chunk-7MM4VJJO.mjs +509 -0
- package/dist/js/chunks/chunk-7MM4VJJO.mjs.map +7 -0
- package/dist/js/chunks/chunk-7UXHSYIA.mjs +183 -0
- package/dist/js/chunks/chunk-7UXHSYIA.mjs.map +7 -0
- package/dist/js/chunks/chunk-A3BJA7V4.mjs +28 -0
- package/dist/js/chunks/chunk-A3BJA7V4.mjs.map +7 -0
- package/dist/js/chunks/chunk-AOGFNMXS.mjs +691 -0
- package/dist/js/chunks/chunk-AOGFNMXS.mjs.map +7 -0
- package/dist/js/chunks/chunk-D4UZ4HFN.mjs +560 -0
- package/dist/js/chunks/chunk-D4UZ4HFN.mjs.map +7 -0
- package/dist/js/chunks/chunk-EP3CVKB5.mjs +88 -0
- package/dist/js/chunks/chunk-EP3CVKB5.mjs.map +7 -0
- package/dist/js/chunks/chunk-G576EP5O.mjs +459 -0
- package/dist/js/chunks/chunk-G576EP5O.mjs.map +7 -0
- package/dist/js/chunks/chunk-GY2Z5CJ2.mjs +320 -0
- package/dist/js/chunks/chunk-GY2Z5CJ2.mjs.map +7 -0
- package/dist/js/chunks/chunk-JKNPQQWY.mjs +191 -0
- package/dist/js/chunks/chunk-JKNPQQWY.mjs.map +7 -0
- package/dist/js/chunks/chunk-JNPIWFJT.mjs +365 -0
- package/dist/js/chunks/chunk-JNPIWFJT.mjs.map +7 -0
- package/dist/js/chunks/chunk-JODJAGFS.mjs +267 -0
- package/dist/js/chunks/chunk-JODJAGFS.mjs.map +7 -0
- package/dist/js/chunks/chunk-JR24UB4X.mjs +100 -0
- package/dist/js/chunks/chunk-JR24UB4X.mjs.map +7 -0
- package/dist/js/chunks/chunk-KR44BSYQ.mjs +55 -0
- package/dist/js/chunks/chunk-KR44BSYQ.mjs.map +7 -0
- package/dist/js/chunks/chunk-LZVBJ33S.mjs +102 -0
- package/dist/js/chunks/chunk-LZVBJ33S.mjs.map +7 -0
- package/dist/js/chunks/chunk-MISGHDUU.mjs +326 -0
- package/dist/js/chunks/chunk-MISGHDUU.mjs.map +7 -0
- package/dist/js/chunks/chunk-N3UHGN3N.mjs +175 -0
- package/dist/js/chunks/chunk-N3UHGN3N.mjs.map +7 -0
- package/dist/js/chunks/chunk-PIIAEYAJ.mjs +85 -0
- package/dist/js/chunks/chunk-PIIAEYAJ.mjs.map +7 -0
- package/dist/js/chunks/chunk-QSQ24FYT.mjs +59 -0
- package/dist/js/chunks/chunk-QSQ24FYT.mjs.map +7 -0
- package/dist/js/chunks/chunk-QYCYP443.mjs +1111 -0
- package/dist/js/chunks/chunk-QYCYP443.mjs.map +7 -0
- package/dist/js/chunks/chunk-SLFNPY5M.mjs +78 -0
- package/dist/js/chunks/chunk-SLFNPY5M.mjs.map +7 -0
- package/dist/js/chunks/chunk-TK6PX2GC.mjs +663 -0
- package/dist/js/chunks/chunk-TK6PX2GC.mjs.map +7 -0
- package/dist/js/chunks/chunk-TYM6U5DY.mjs +76 -0
- package/dist/js/chunks/chunk-TYM6U5DY.mjs.map +7 -0
- package/dist/js/chunks/chunk-TZZ24ZQS.mjs +154 -0
- package/dist/js/chunks/chunk-TZZ24ZQS.mjs.map +7 -0
- package/dist/js/chunks/chunk-VAS6JQ6P.mjs +94 -0
- package/dist/js/chunks/chunk-VAS6JQ6P.mjs.map +7 -0
- package/dist/js/chunks/chunk-WWPAPHMA.mjs +1 -0
- package/dist/js/chunks/chunk-WWPAPHMA.mjs.map +7 -0
- package/dist/js/chunks/chunk-XDB3G6RL.mjs +114 -0
- package/dist/js/chunks/chunk-XDB3G6RL.mjs.map +7 -0
- package/dist/js/chunks/chunk-XO5WX3TK.mjs +226 -0
- package/dist/js/chunks/chunk-XO5WX3TK.mjs.map +7 -0
- package/dist/js/chunks/chunk-YFXEJ7GR.mjs +286 -0
- package/dist/js/chunks/chunk-YFXEJ7GR.mjs.map +7 -0
- package/dist/js/chunks/chunk-ZAOYQ6SY.mjs +7 -0
- package/dist/js/chunks/chunk-ZAOYQ6SY.mjs.map +7 -0
- package/dist/js/chunks/chunk-ZIZVUWRL.mjs +120 -0
- package/dist/js/chunks/chunk-ZIZVUWRL.mjs.map +7 -0
- package/dist/js/chunks/chunk-ZZBZI2XN.mjs +338 -0
- package/dist/js/chunks/chunk-ZZBZI2XN.mjs.map +7 -0
- package/dist/js/expressive.cjs +747 -754
- package/dist/js/expressive.cjs.map +4 -4
- package/dist/js/expressive.js +747 -754
- package/dist/js/expressive.js.map +4 -4
- package/dist/js/expressive.min.js +11 -15
- package/dist/js/expressive.min.js.map +4 -4
- package/dist/js/expressive.mjs +83 -7490
- package/dist/js/expressive.mjs.map +4 -4
- package/dist/js/internal/behaviors/bottomSheets.mjs +9 -0
- package/dist/js/internal/behaviors/bottomSheets.mjs.map +7 -0
- package/dist/js/internal/behaviors/dialogs.mjs +8 -0
- package/dist/js/internal/behaviors/dialogs.mjs.map +7 -0
- package/dist/js/internal/behaviors/forms.mjs +8 -0
- package/dist/js/internal/behaviors/forms.mjs.map +7 -0
- package/dist/js/internal/behaviors/sheetDrag.mjs +8 -0
- package/dist/js/internal/behaviors/sheetDrag.mjs.map +7 -0
- package/dist/js/internal/behaviors/sideSheets.mjs +9 -0
- package/dist/js/internal/behaviors/sideSheets.mjs.map +7 -0
- package/dist/js/internal/components/appBar.mjs +8 -0
- package/dist/js/internal/components/appBar.mjs.map +7 -0
- package/dist/js/internal/components/autocomplete.mjs +10 -0
- package/dist/js/internal/components/autocomplete.mjs.map +7 -0
- package/dist/js/internal/components/buttonGroup.mjs +8 -0
- package/dist/js/internal/components/buttonGroup.mjs.map +7 -0
- package/dist/js/internal/components/buttons.mjs +9 -0
- package/dist/js/internal/components/buttons.mjs.map +7 -0
- package/dist/js/internal/components/cards.mjs +13 -0
- package/dist/js/internal/components/cards.mjs.map +7 -0
- package/dist/js/internal/components/carousel.mjs +9 -0
- package/dist/js/internal/components/carousel.mjs.map +7 -0
- package/dist/js/internal/components/characterCounter.mjs +8 -0
- package/dist/js/internal/components/characterCounter.mjs.map +7 -0
- package/dist/js/internal/components/chips.mjs +11 -0
- package/dist/js/internal/components/chips.mjs.map +7 -0
- package/dist/js/internal/components/datepicker.mjs +12 -0
- package/dist/js/internal/components/datepicker.mjs.map +7 -0
- package/dist/js/internal/components/expandingCard.mjs +11 -0
- package/dist/js/internal/components/expandingCard.mjs.map +7 -0
- package/dist/js/internal/components/index.mjs +88 -0
- package/dist/js/internal/components/index.mjs.map +7 -0
- package/dist/js/internal/components/lightbox.mjs +9 -0
- package/dist/js/internal/components/lightbox.mjs.map +7 -0
- package/dist/js/internal/components/menu.mjs +9 -0
- package/dist/js/internal/components/menu.mjs.map +7 -0
- package/dist/js/internal/components/navigationRail.mjs +8 -0
- package/dist/js/internal/components/navigationRail.mjs.map +7 -0
- package/dist/js/internal/components/registry.mjs +33 -0
- package/dist/js/internal/components/registry.mjs.map +7 -0
- package/dist/js/internal/components/scrollspy.mjs +8 -0
- package/dist/js/internal/components/scrollspy.mjs.map +7 -0
- package/dist/js/internal/components/select.mjs +10 -0
- package/dist/js/internal/components/select.mjs.map +7 -0
- package/dist/js/internal/components/slider.mjs +9 -0
- package/dist/js/internal/components/slider.mjs.map +7 -0
- package/dist/js/internal/components/snackbar.mjs +8 -0
- package/dist/js/internal/components/snackbar.mjs.map +7 -0
- package/dist/js/internal/components/tabs.mjs +10 -0
- package/dist/js/internal/components/tabs.mjs.map +7 -0
- package/dist/js/internal/components/timepicker.mjs +10 -0
- package/dist/js/internal/components/timepicker.mjs.map +7 -0
- package/dist/js/internal/components/tooltip.mjs +9 -0
- package/dist/js/internal/components/tooltip.mjs.map +7 -0
- package/dist/js/internal/core/component.mjs +7 -0
- package/dist/js/internal/core/component.mjs.map +7 -0
- package/dist/js/internal/core/utils.mjs +7 -0
- package/dist/js/internal/core/utils.mjs.map +7 -0
- package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +8 -0
- package/dist/js/internal/plugins/dockedDisplayPlugin.mjs.map +7 -0
- package/dist/js/modular.mjs +113 -0
- package/dist/js/modular.mjs.map +7 -0
- package/dist/types/behaviors/sheetDrag.d.ts +1 -1
- package/dist/types/components/appBar.d.ts +1 -1
- package/dist/types/components/autocomplete.d.ts +9 -0
- package/dist/types/components/buttons.d.ts +4 -39
- package/dist/types/components/carousel.d.ts +10 -1
- package/dist/types/components/chips.d.ts +1 -0
- package/dist/types/components/datepicker.d.ts +7 -0
- package/dist/types/components/index.d.ts +0 -2
- package/dist/types/components/lightbox.d.ts +12 -0
- package/dist/types/components/menu.d.ts +3 -0
- package/dist/types/components/registry.d.ts +0 -4
- package/dist/types/components/select.d.ts +4 -0
- package/dist/types/components/slider.d.ts +2 -1
- package/dist/types/components/snackbar.d.ts +4 -2
- package/dist/types/components/tabs.d.ts +2 -1
- package/dist/types/components/timepicker.d.ts +5 -3
- package/dist/types/components/tooltip.d.ts +5 -3
- package/dist/types/index.d.ts +1 -8
- package/dist/types/modular.d.ts +28 -0
- package/package.json +16 -4
- package/src/sass/README.md +8 -0
- package/src/sass/components/_badges.scss +1 -6
- package/src/sass/components/_button-groups.scss +5 -1
- package/src/sass/components/_buttons.scss +8 -287
- package/src/sass/components/_chips.scss +17 -2
- package/src/sass/components/_dialog.scss +9 -4
- package/src/sass/components/_fab-menu.scss +11 -9
- package/src/sass/components/_icon-buttons.scss +0 -5
- package/src/sass/components/_index.scss +0 -5
- package/src/sass/components/_menu.scss +2 -2
- package/src/sass/components/_navigation-rail.scss +1 -1
- package/src/sass/components/_panes.scss +50 -78
- package/src/sass/components/_progress.scss +73 -13
- package/src/sass/components/_scrim.scss +4 -4
- package/src/sass/components/_side-sheet.scss +22 -12
- package/src/sass/components/_toolbar.scss +1 -4
- package/src/sass/components/_tooltip.scss +20 -2
- package/src/sass/components/forms/_input-fields.scss +5 -1
- package/src/sass/components/forms/_select.scss +1 -0
- package/src/sass/components/forms/_slider.scss +81 -25
- package/src/sass/custom.scss +38 -0
- package/src/sass/utilities/_helpers.scss +18 -0
- package/src/sass/utilities/_spacing.scss +8 -1
- package/dist/types/components/navigationDrawer.d.ts +0 -110
- package/src/sass/components/_banners.scss +0 -298
- package/src/sass/components/_bottom-app-bar.scss +0 -180
- package/src/sass/components/_floating-sheet.scss +0 -86
- package/src/sass/components/_navigation-drawer.scss +0 -476
- package/src/sass/components/_segmented-buttons.scss +0 -188
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Utils
|
|
3
|
+
} from "./chunk-MISGHDUU.mjs";
|
|
4
|
+
import {
|
|
5
|
+
Component
|
|
6
|
+
} from "./chunk-QSQ24FYT.mjs";
|
|
7
|
+
|
|
8
|
+
// src/ts/components/tooltip.ts
|
|
9
|
+
var _defaults = {
|
|
10
|
+
exitDelay: 200,
|
|
11
|
+
enterDelay: 0,
|
|
12
|
+
text: "",
|
|
13
|
+
margin: 4,
|
|
14
|
+
inDuration: 250,
|
|
15
|
+
outDuration: 200,
|
|
16
|
+
position: "bottom",
|
|
17
|
+
transitionMovement: 10,
|
|
18
|
+
opacity: 1
|
|
19
|
+
};
|
|
20
|
+
var Tooltip = class _Tooltip extends Component {
|
|
21
|
+
constructor(el, options) {
|
|
22
|
+
super(el, options, _Tooltip);
|
|
23
|
+
/**
|
|
24
|
+
* Show tooltip.
|
|
25
|
+
*/
|
|
26
|
+
this.open = (isManual) => {
|
|
27
|
+
if (this.isOpen) return;
|
|
28
|
+
isManual = isManual === void 0 ? true : void 0;
|
|
29
|
+
clearTimeout(this._exitDelayTimeout);
|
|
30
|
+
clearTimeout(this._animationTimeout);
|
|
31
|
+
this.isOpen = true;
|
|
32
|
+
this.options = { ...this.options, ...this._getAttributeOptions() };
|
|
33
|
+
this._updateTooltipContent();
|
|
34
|
+
this._setEnterDelayTimeout(isManual);
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Hide tooltip.
|
|
38
|
+
*/
|
|
39
|
+
this.close = () => {
|
|
40
|
+
if (!this.isOpen) return;
|
|
41
|
+
this.isHovered = false;
|
|
42
|
+
this.isFocused = false;
|
|
43
|
+
this.isOpen = false;
|
|
44
|
+
clearTimeout(this._enterDelayTimeout);
|
|
45
|
+
this._setExitDelayTimeout();
|
|
46
|
+
};
|
|
47
|
+
this._handleMouseEnter = () => {
|
|
48
|
+
this.isHovered = true;
|
|
49
|
+
this.open(false);
|
|
50
|
+
};
|
|
51
|
+
this._handleMouseLeave = (event) => {
|
|
52
|
+
const next = event.relatedTarget;
|
|
53
|
+
if (next && (this.el.contains(next) || this.tooltipEl.contains(next))) return;
|
|
54
|
+
this.isHovered = false;
|
|
55
|
+
if (!this.isFocused) this.close();
|
|
56
|
+
};
|
|
57
|
+
this._handleKeydown = (event) => {
|
|
58
|
+
if (event.key !== "Escape" || !this.isOpen) return;
|
|
59
|
+
event.preventDefault();
|
|
60
|
+
event.stopPropagation();
|
|
61
|
+
this.close();
|
|
62
|
+
clearTimeout(this._exitDelayTimeout);
|
|
63
|
+
this._animateOut();
|
|
64
|
+
};
|
|
65
|
+
// Focus opens the tooltip only when it arrived by keyboard: a pointer press
|
|
66
|
+
// on the trigger also focuses it, and _handleMouseEnter already covers that.
|
|
67
|
+
this._handleFocus = (event) => {
|
|
68
|
+
if (event.target.matches(":focus-visible")) {
|
|
69
|
+
this.isFocused = true;
|
|
70
|
+
this.open(false);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
this._handleBlur = (event) => {
|
|
74
|
+
const next = event.relatedTarget;
|
|
75
|
+
if (next && (this.el.contains(next) || this.tooltipEl.contains(next))) return;
|
|
76
|
+
this.isFocused = false;
|
|
77
|
+
if (!this.isHovered) this.close();
|
|
78
|
+
};
|
|
79
|
+
this.el["Expressive_Tooltip"] = this;
|
|
80
|
+
this.options = {
|
|
81
|
+
..._Tooltip.defaults,
|
|
82
|
+
...this._getAttributeOptions(),
|
|
83
|
+
...options
|
|
84
|
+
};
|
|
85
|
+
this.isOpen = false;
|
|
86
|
+
this.isHovered = false;
|
|
87
|
+
this.isFocused = false;
|
|
88
|
+
this._appendTooltipEl();
|
|
89
|
+
this._setupEventHandlers();
|
|
90
|
+
}
|
|
91
|
+
static get defaults() {
|
|
92
|
+
return _defaults;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Initializes instances of Tooltip.
|
|
96
|
+
* @param els HTML elements.
|
|
97
|
+
* @param options Component options.
|
|
98
|
+
*/
|
|
99
|
+
static init(els, options = {}) {
|
|
100
|
+
return super.init(els, options, _Tooltip);
|
|
101
|
+
}
|
|
102
|
+
static getInstance(el) {
|
|
103
|
+
return el["Expressive_Tooltip"];
|
|
104
|
+
}
|
|
105
|
+
destroy() {
|
|
106
|
+
clearTimeout(this._enterDelayTimeout);
|
|
107
|
+
clearTimeout(this._exitDelayTimeout);
|
|
108
|
+
clearTimeout(this._animationTimeout);
|
|
109
|
+
this.isOpen = false;
|
|
110
|
+
this.isHovered = false;
|
|
111
|
+
this.isFocused = false;
|
|
112
|
+
if (this.el.getAttribute("aria-describedby") === this.tooltipEl.id) {
|
|
113
|
+
this.el.removeAttribute("aria-describedby");
|
|
114
|
+
}
|
|
115
|
+
this.tooltipEl.remove();
|
|
116
|
+
this._removeEventHandlers();
|
|
117
|
+
this.el["Expressive_Tooltip"] = void 0;
|
|
118
|
+
}
|
|
119
|
+
_appendTooltipEl() {
|
|
120
|
+
this.tooltipEl = document.createElement("div");
|
|
121
|
+
this.tooltipEl.classList.add("tooltip");
|
|
122
|
+
this.tooltipEl.id = `tooltip-${Utils.guid()}`;
|
|
123
|
+
this.tooltipEl.setAttribute("role", "tooltip");
|
|
124
|
+
this.el.setAttribute("aria-describedby", this.tooltipEl.id);
|
|
125
|
+
const tooltipContentEl = this.options.tooltipId ? Utils.getElementById(this.el, this.options.tooltipId) : document.createElement("div");
|
|
126
|
+
if (this.options.tooltipId) {
|
|
127
|
+
this.tooltipEl.classList.add("rich");
|
|
128
|
+
}
|
|
129
|
+
tooltipContentEl.style.display = "";
|
|
130
|
+
tooltipContentEl.classList.add("tooltip-content");
|
|
131
|
+
this._setTooltipContent(tooltipContentEl);
|
|
132
|
+
this.tooltipEl.appendChild(tooltipContentEl);
|
|
133
|
+
Utils.portalRoot(this.el).appendChild(this.tooltipEl);
|
|
134
|
+
}
|
|
135
|
+
_setTooltipContent(tooltipContentEl) {
|
|
136
|
+
if (this.options.tooltipId) return;
|
|
137
|
+
tooltipContentEl.innerText = this.options.text;
|
|
138
|
+
}
|
|
139
|
+
_updateTooltipContent() {
|
|
140
|
+
this._setTooltipContent(this.tooltipEl.querySelector(".tooltip-content"));
|
|
141
|
+
}
|
|
142
|
+
_setupEventHandlers() {
|
|
143
|
+
for (const el of [this.el, this.tooltipEl]) {
|
|
144
|
+
el.addEventListener("mouseenter", this._handleMouseEnter);
|
|
145
|
+
el.addEventListener("mouseleave", this._handleMouseLeave);
|
|
146
|
+
el.addEventListener("focus", this._handleFocus, true);
|
|
147
|
+
el.addEventListener("blur", this._handleBlur, true);
|
|
148
|
+
}
|
|
149
|
+
this.el.ownerDocument.addEventListener("keydown", this._handleKeydown, true);
|
|
150
|
+
}
|
|
151
|
+
_removeEventHandlers() {
|
|
152
|
+
for (const el of [this.el, this.tooltipEl]) {
|
|
153
|
+
el.removeEventListener("mouseenter", this._handleMouseEnter);
|
|
154
|
+
el.removeEventListener("mouseleave", this._handleMouseLeave);
|
|
155
|
+
el.removeEventListener("focus", this._handleFocus, true);
|
|
156
|
+
el.removeEventListener("blur", this._handleBlur, true);
|
|
157
|
+
}
|
|
158
|
+
this.el.ownerDocument.removeEventListener("keydown", this._handleKeydown, true);
|
|
159
|
+
}
|
|
160
|
+
_setExitDelayTimeout() {
|
|
161
|
+
clearTimeout(this._exitDelayTimeout);
|
|
162
|
+
this._exitDelayTimeout = setTimeout(() => {
|
|
163
|
+
if (this.isHovered || this.isFocused) return;
|
|
164
|
+
this._animateOut();
|
|
165
|
+
}, this.options.exitDelay);
|
|
166
|
+
}
|
|
167
|
+
_setEnterDelayTimeout(isManual) {
|
|
168
|
+
clearTimeout(this._enterDelayTimeout);
|
|
169
|
+
this._enterDelayTimeout = setTimeout(() => {
|
|
170
|
+
if (!this.isHovered && !this.isFocused && !isManual) return;
|
|
171
|
+
this._animateIn();
|
|
172
|
+
}, this.options.enterDelay);
|
|
173
|
+
}
|
|
174
|
+
_positionTooltip() {
|
|
175
|
+
const tooltip = this.tooltipEl;
|
|
176
|
+
const origin = this.el, originHeight = origin.offsetHeight, originWidth = origin.offsetWidth, tooltipHeight = tooltip.offsetHeight, tooltipWidth = tooltip.offsetWidth, margin = this.options.margin;
|
|
177
|
+
this.xMovement = 0;
|
|
178
|
+
this.yMovement = 0;
|
|
179
|
+
const originRect = origin.getBoundingClientRect();
|
|
180
|
+
let targetTop = originRect.top + Utils.getDocumentScrollTop();
|
|
181
|
+
let targetLeft = originRect.left + Utils.getDocumentScrollLeft();
|
|
182
|
+
if (this.options.position === "top") {
|
|
183
|
+
targetTop += -tooltipHeight - margin;
|
|
184
|
+
targetLeft += originWidth / 2 - tooltipWidth / 2;
|
|
185
|
+
this.yMovement = -this.options.transitionMovement;
|
|
186
|
+
} else if (this.options.position === "right") {
|
|
187
|
+
targetTop += originHeight / 2 - tooltipHeight / 2;
|
|
188
|
+
targetLeft += originWidth + margin;
|
|
189
|
+
this.xMovement = this.options.transitionMovement;
|
|
190
|
+
} else if (this.options.position === "left") {
|
|
191
|
+
targetTop += originHeight / 2 - tooltipHeight / 2;
|
|
192
|
+
targetLeft += -tooltipWidth - margin;
|
|
193
|
+
this.xMovement = -this.options.transitionMovement;
|
|
194
|
+
} else {
|
|
195
|
+
targetTop += originHeight + margin;
|
|
196
|
+
targetLeft += originWidth / 2 - tooltipWidth / 2;
|
|
197
|
+
this.yMovement = this.options.transitionMovement;
|
|
198
|
+
}
|
|
199
|
+
const newCoordinates = this._repositionWithinScreen(
|
|
200
|
+
targetLeft,
|
|
201
|
+
targetTop,
|
|
202
|
+
tooltipWidth,
|
|
203
|
+
tooltipHeight
|
|
204
|
+
);
|
|
205
|
+
tooltip.style.setProperty("--md-comp-tooltip-anchor-gap", `${Math.max(0, margin) + Math.abs(this.options.transitionMovement)}px`);
|
|
206
|
+
tooltip.style.top = newCoordinates.y + "px";
|
|
207
|
+
tooltip.style.left = newCoordinates.x + "px";
|
|
208
|
+
}
|
|
209
|
+
_repositionWithinScreen(x, y, width, height) {
|
|
210
|
+
return Utils._repositionWithinScreen(
|
|
211
|
+
x,
|
|
212
|
+
y,
|
|
213
|
+
width,
|
|
214
|
+
height,
|
|
215
|
+
this.options.margin,
|
|
216
|
+
this.options.transitionMovement,
|
|
217
|
+
"center"
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
_animateIn() {
|
|
221
|
+
this._animate(true);
|
|
222
|
+
}
|
|
223
|
+
_animateOut() {
|
|
224
|
+
this._animate(false);
|
|
225
|
+
}
|
|
226
|
+
_animate(show) {
|
|
227
|
+
const style = this.tooltipEl.style;
|
|
228
|
+
const reduce = this.el.ownerDocument.defaultView.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
229
|
+
const duration = reduce ? 0 : show ? this.options.inDuration : this.options.outDuration;
|
|
230
|
+
if (show) {
|
|
231
|
+
this._positionTooltip();
|
|
232
|
+
style.visibility = "visible";
|
|
233
|
+
style.overflow = "visible";
|
|
234
|
+
}
|
|
235
|
+
style.transition = `transform ${duration}ms ease-out, opacity ${duration}ms ease-out`;
|
|
236
|
+
clearTimeout(this._animationTimeout);
|
|
237
|
+
this._animationTimeout = setTimeout(() => {
|
|
238
|
+
style.transform = show && !reduce ? `translateX(${this.xMovement}px) translateY(${this.yMovement}px)` : "none";
|
|
239
|
+
style.opacity = show ? (this.options.opacity || 1).toString() : "0";
|
|
240
|
+
if (!show) this._animationTimeout = setTimeout(() => {
|
|
241
|
+
style.visibility = "hidden";
|
|
242
|
+
style.overflow = "";
|
|
243
|
+
}, duration);
|
|
244
|
+
}, 1);
|
|
245
|
+
}
|
|
246
|
+
_getAttributeOptions() {
|
|
247
|
+
const attributeOptions = {};
|
|
248
|
+
const tooltipTextOption = this.el.getAttribute("data-tooltip");
|
|
249
|
+
const tooltipId = this.el.getAttribute("data-tooltip-id");
|
|
250
|
+
const positionOption = this.el.getAttribute("data-position");
|
|
251
|
+
if (tooltipTextOption) {
|
|
252
|
+
attributeOptions.text = tooltipTextOption;
|
|
253
|
+
}
|
|
254
|
+
if (positionOption) {
|
|
255
|
+
attributeOptions.position = positionOption;
|
|
256
|
+
}
|
|
257
|
+
if (tooltipId) {
|
|
258
|
+
attributeOptions.tooltipId = tooltipId;
|
|
259
|
+
}
|
|
260
|
+
return attributeOptions;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
export {
|
|
265
|
+
Tooltip
|
|
266
|
+
};
|
|
267
|
+
//# sourceMappingURL=chunk-JODJAGFS.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/components/tooltip.ts"],
|
|
4
|
+
"sourcesContent": ["import { Utils } from '../core/utils';\nimport { Component, BaseOptions, InitElements, InitElement } from '../core/component';\n\nexport type TooltipPosition = 'top' | 'right' | 'bottom' | 'left';\n\nexport interface TooltipOptions extends BaseOptions {\n /**\n * Delay time before tooltip disappears.\n * @default 200\n */\n exitDelay: number;\n /**\n * Delay time before tooltip appears.\n * @default 0\n */\n enterDelay: number;\n /**\n * Element Id for the tooltip.\n * @default \"\"\n */\n tooltipId?: string;\n /**\n * Text string for the tooltip.\n * @default \"\"\n */\n text: string;\n /**\n * Set distance tooltip appears away from its activator\n * excluding transitionMovement.\n * @default 4\n */\n margin: number;\n /**\n * Enter transition duration.\n * @default 300\n */\n inDuration: number;\n /**\n * Opacity of the tooltip.\n * @default 1\n */\n opacity: number;\n /**\n * Exit transition duration.\n * @default 250\n */\n outDuration: number;\n /**\n * Set the direction of the tooltip.\n * @default 'bottom'\n */\n position: TooltipPosition;\n /**\n * Amount in px that the tooltip moves during its transition.\n * @default 10\n */\n transitionMovement: number;\n}\n\nconst _defaults: TooltipOptions = {\n exitDelay: 200,\n enterDelay: 0,\n text: '',\n margin: 4,\n inDuration: 250,\n outDuration: 200,\n position: 'bottom' as TooltipPosition,\n transitionMovement: 10,\n opacity: 1\n};\n\nexport class Tooltip extends Component<TooltipOptions> {\n /**\n * If tooltip is open.\n */\n isOpen: boolean;\n /**\n * If tooltip is hovered.\n */\n isHovered: boolean;\n /**\n * If tooltip is focused.\n */\n isFocused: boolean;\n tooltipEl: HTMLElement;\n private _exitDelayTimeout: ReturnType<typeof setTimeout>;\n private _enterDelayTimeout: ReturnType<typeof setTimeout>;\n private _animationTimeout: ReturnType<typeof setTimeout>;\n xMovement: number;\n yMovement: number;\n\n constructor(el: HTMLElement, options: Partial<TooltipOptions>) {\n super(el, options, Tooltip);\n this.el['Expressive_Tooltip'] = this;\n\n this.options = {\n ...Tooltip.defaults,\n ...this._getAttributeOptions(),\n ...options\n };\n\n this.isOpen = false;\n this.isHovered = false;\n this.isFocused = false;\n this._appendTooltipEl();\n this._setupEventHandlers();\n }\n\n static get defaults(): TooltipOptions {\n return _defaults;\n }\n\n /**\n * Initializes instance of Tooltip.\n * @param el HTML element.\n * @param options Component options.\n */\n static init(el: HTMLElement, options?: Partial<TooltipOptions>): Tooltip;\n /**\n * Initializes instances of Tooltip.\n * @param els HTML elements.\n * @param options Component options.\n */\n static init(els: InitElements<InitElement>, options?: Partial<TooltipOptions>): Tooltip[];\n /**\n * Initializes instances of Tooltip.\n * @param els HTML elements.\n * @param options Component options.\n */\n static init(\n els: HTMLElement | InitElements<InitElement>,\n options: Partial<TooltipOptions> = {}\n ): Tooltip | Tooltip[] {\n return super.init(els, options, Tooltip);\n }\n\n static getInstance(el: HTMLElement): Tooltip {\n return el['Expressive_Tooltip'];\n }\n\n destroy() {\n clearTimeout(this._enterDelayTimeout);\n clearTimeout(this._exitDelayTimeout);\n clearTimeout(this._animationTimeout);\n this.isOpen = false;\n this.isHovered = false;\n this.isFocused = false;\n if (this.el.getAttribute('aria-describedby') === this.tooltipEl.id) {\n this.el.removeAttribute('aria-describedby');\n }\n this.tooltipEl.remove();\n this._removeEventHandlers();\n this.el['Expressive_Tooltip'] = undefined;\n }\n\n _appendTooltipEl() {\n this.tooltipEl = document.createElement('div');\n this.tooltipEl.classList.add('tooltip');\n this.tooltipEl.id = `tooltip-${Utils.guid()}`;\n this.tooltipEl.setAttribute('role', 'tooltip');\n this.el.setAttribute('aria-describedby', this.tooltipEl.id);\n\n const tooltipContentEl = this.options.tooltipId\n ? Utils.getElementById(this.el, this.options.tooltipId)\n : document.createElement('div');\n if (this.options.tooltipId) {\n this.tooltipEl.classList.add('rich');\n }\n tooltipContentEl.style.display = '';\n tooltipContentEl.classList.add('tooltip-content');\n this._setTooltipContent(tooltipContentEl);\n this.tooltipEl.appendChild(tooltipContentEl);\n Utils.portalRoot(this.el).appendChild(this.tooltipEl);\n }\n\n _setTooltipContent(tooltipContentEl: HTMLElement) {\n if (this.options.tooltipId) return;\n tooltipContentEl.innerText = this.options.text;\n }\n\n _updateTooltipContent() {\n this._setTooltipContent(this.tooltipEl.querySelector('.tooltip-content'));\n }\n\n _setupEventHandlers() {\n for (const el of [this.el, this.tooltipEl]) {\n el.addEventListener('mouseenter', this._handleMouseEnter);\n el.addEventListener('mouseleave', this._handleMouseLeave);\n el.addEventListener('focus', this._handleFocus, true);\n el.addEventListener('blur', this._handleBlur, true);\n }\n this.el.ownerDocument.addEventListener('keydown', this._handleKeydown, true);\n }\n\n _removeEventHandlers() {\n for (const el of [this.el, this.tooltipEl]) {\n el.removeEventListener('mouseenter', this._handleMouseEnter);\n el.removeEventListener('mouseleave', this._handleMouseLeave);\n el.removeEventListener('focus', this._handleFocus, true);\n el.removeEventListener('blur', this._handleBlur, true);\n }\n this.el.ownerDocument.removeEventListener('keydown', this._handleKeydown, true);\n }\n\n /**\n * Show tooltip.\n */\n open = (isManual: boolean) => {\n if (this.isOpen) return;\n isManual = isManual === undefined ? true : undefined; // Default value true\n clearTimeout(this._exitDelayTimeout);\n clearTimeout(this._animationTimeout);\n this.isOpen = true;\n // Update tooltip content with HTML attribute options\n this.options = { ...this.options, ...this._getAttributeOptions() };\n this._updateTooltipContent();\n this._setEnterDelayTimeout(isManual);\n };\n\n /**\n * Hide tooltip.\n */\n close = () => {\n if (!this.isOpen) return;\n this.isHovered = false;\n this.isFocused = false;\n this.isOpen = false;\n clearTimeout(this._enterDelayTimeout);\n this._setExitDelayTimeout();\n };\n\n _setExitDelayTimeout() {\n clearTimeout(this._exitDelayTimeout);\n this._exitDelayTimeout = setTimeout(() => {\n if (this.isHovered || this.isFocused) return;\n this._animateOut();\n }, this.options.exitDelay);\n }\n\n _setEnterDelayTimeout(isManual) {\n clearTimeout(this._enterDelayTimeout);\n this._enterDelayTimeout = setTimeout(() => {\n if (!this.isHovered && !this.isFocused && !isManual) return;\n this._animateIn();\n }, this.options.enterDelay);\n }\n\n _positionTooltip() {\n const tooltip: HTMLElement = this.tooltipEl;\n const origin = this.el as HTMLElement,\n originHeight = origin.offsetHeight,\n originWidth = origin.offsetWidth,\n tooltipHeight = tooltip.offsetHeight,\n tooltipWidth = tooltip.offsetWidth,\n margin = this.options.margin;\n\n this.xMovement = 0;\n this.yMovement = 0;\n\n const originRect = origin.getBoundingClientRect();\n let targetTop = originRect.top + Utils.getDocumentScrollTop();\n let targetLeft = originRect.left + Utils.getDocumentScrollLeft();\n if (this.options.position === 'top') {\n targetTop += -tooltipHeight - margin;\n targetLeft += originWidth / 2 - tooltipWidth / 2;\n this.yMovement = -this.options.transitionMovement;\n } else if (this.options.position === 'right') {\n targetTop += originHeight / 2 - tooltipHeight / 2;\n targetLeft += originWidth + margin;\n this.xMovement = this.options.transitionMovement;\n } else if (this.options.position === 'left') {\n targetTop += originHeight / 2 - tooltipHeight / 2;\n targetLeft += -tooltipWidth - margin;\n this.xMovement = -this.options.transitionMovement;\n } else {\n targetTop += originHeight + margin;\n targetLeft += originWidth / 2 - tooltipWidth / 2;\n this.yMovement = this.options.transitionMovement;\n }\n\n const newCoordinates = this._repositionWithinScreen(\n targetLeft,\n targetTop,\n tooltipWidth,\n tooltipHeight\n );\n\n tooltip.style.setProperty('--md-comp-tooltip-anchor-gap', `${Math.max(0, margin) + Math.abs(this.options.transitionMovement)}px`);\n tooltip.style.top = newCoordinates.y + 'px';\n tooltip.style.left = newCoordinates.x + 'px';\n }\n\n _repositionWithinScreen(x: number, y: number, width: number, height: number) {\n return Utils._repositionWithinScreen(\n x, y, width, height, this.options.margin, this.options.transitionMovement, 'center'\n );\n }\n\n _animateIn() { this._animate(true); }\n\n _animateOut() { this._animate(false); }\n\n _animate(show: boolean) {\n const style = this.tooltipEl.style;\n const reduce = this.el.ownerDocument.defaultView.matchMedia('(prefers-reduced-motion: reduce)').matches;\n const duration = reduce ? 0 : show ? this.options.inDuration : this.options.outDuration;\n if (show) {\n this._positionTooltip();\n style.visibility = 'visible';\n style.overflow = 'visible';\n }\n style.transition = `transform ${duration}ms ease-out, opacity ${duration}ms ease-out`;\n clearTimeout(this._animationTimeout);\n this._animationTimeout = setTimeout(() => {\n style.transform = show && !reduce ? `translateX(${this.xMovement}px) translateY(${this.yMovement}px)` : 'none';\n style.opacity = show ? (this.options.opacity || 1).toString() : '0';\n if (!show) this._animationTimeout = setTimeout(() => {\n style.visibility = 'hidden';\n style.overflow = '';\n }, duration);\n }, 1);\n }\n\n _handleMouseEnter = () => {\n this.isHovered = true;\n this.open(false);\n };\n\n _handleMouseLeave = (event: MouseEvent) => {\n const next = event.relatedTarget as Node | null;\n if (next && (this.el.contains(next) || this.tooltipEl.contains(next))) return;\n this.isHovered = false;\n if (!this.isFocused) this.close();\n };\n\n _handleKeydown = (event: KeyboardEvent) => {\n if (event.key !== 'Escape' || !this.isOpen) return;\n event.preventDefault();\n event.stopPropagation();\n this.close();\n clearTimeout(this._exitDelayTimeout);\n this._animateOut();\n };\n\n // Focus opens the tooltip only when it arrived by keyboard: a pointer press\n // on the trigger also focuses it, and _handleMouseEnter already covers that.\n _handleFocus = (event: FocusEvent) => {\n if ((event.target as HTMLElement).matches(':focus-visible')) {\n this.isFocused = true;\n this.open(false);\n }\n };\n\n _handleBlur = (event: FocusEvent) => {\n const next = event.relatedTarget as Node | null;\n if (next && (this.el.contains(next) || this.tooltipEl.contains(next))) return;\n this.isFocused = false;\n if (!this.isHovered) this.close();\n };\n\n _getAttributeOptions(): Partial<TooltipOptions> {\n const attributeOptions: Partial<TooltipOptions> = {};\n const tooltipTextOption = this.el.getAttribute('data-tooltip');\n const tooltipId = this.el.getAttribute('data-tooltip-id');\n const positionOption = this.el.getAttribute('data-position');\n if (tooltipTextOption) {\n attributeOptions.text = tooltipTextOption;\n }\n if (positionOption) {\n attributeOptions.position = positionOption as TooltipPosition;\n }\n if (tooltipId) {\n attributeOptions.tooltipId = tooltipId;\n }\n\n return attributeOptions;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Utils
|
|
3
|
+
} from "./chunk-MISGHDUU.mjs";
|
|
4
|
+
|
|
5
|
+
// src/ts/behaviors/forms.ts
|
|
6
|
+
var Forms = class _Forms {
|
|
7
|
+
/**
|
|
8
|
+
* Checks if the label has validation and apply
|
|
9
|
+
* the correct class and styles
|
|
10
|
+
* @param textfield
|
|
11
|
+
*/
|
|
12
|
+
static validateField(textfield) {
|
|
13
|
+
if (!textfield) {
|
|
14
|
+
console.error("No text field element found");
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const hasLength = textfield.getAttribute("data-length") !== null;
|
|
18
|
+
const lenAttr = parseInt(textfield.getAttribute("data-length"));
|
|
19
|
+
const len = textfield.value.length;
|
|
20
|
+
if (len === 0 && textfield.validity.badInput === false && !textfield.required && textfield.classList.contains("validate")) {
|
|
21
|
+
textfield.classList.remove("invalid");
|
|
22
|
+
} else if (textfield.classList.contains("validate")) {
|
|
23
|
+
if (textfield.validity.valid && hasLength && len <= lenAttr || textfield.validity.valid && !hasLength) {
|
|
24
|
+
textfield.classList.remove("invalid");
|
|
25
|
+
} else {
|
|
26
|
+
textfield.classList.add("invalid");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resizes the given TextArea after updating the
|
|
32
|
+
* value content dynamically.
|
|
33
|
+
* @param e EventTarget
|
|
34
|
+
*/
|
|
35
|
+
static textareaAutoResize(e) {
|
|
36
|
+
const textarea = e;
|
|
37
|
+
if (!textarea) return;
|
|
38
|
+
if (!textarea.hasAttribute("original-height")) {
|
|
39
|
+
textarea.setAttribute("original-height", textarea.getBoundingClientRect().height.toString());
|
|
40
|
+
}
|
|
41
|
+
const originalHeight = parseInt(textarea.getAttribute("original-height"));
|
|
42
|
+
if (isNaN(originalHeight)) return;
|
|
43
|
+
textarea.style.height = "auto";
|
|
44
|
+
const borders = textarea.offsetHeight - textarea.clientHeight;
|
|
45
|
+
const contentHeight = textarea.scrollHeight + borders;
|
|
46
|
+
textarea.style.height = Math.max(originalHeight, contentHeight) + "px";
|
|
47
|
+
}
|
|
48
|
+
static Init() {
|
|
49
|
+
Utils.onDocumentReady(() => {
|
|
50
|
+
document.addEventListener("change", (e) => {
|
|
51
|
+
const target = e.target;
|
|
52
|
+
if (target instanceof HTMLInputElement) {
|
|
53
|
+
_Forms.validateField(target);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
document.addEventListener("keyup", (e) => {
|
|
57
|
+
const target = e.target;
|
|
58
|
+
if (target instanceof HTMLInputElement && ["radio", "checkbox"].includes(target.type)) {
|
|
59
|
+
if (e.key === Utils.keys.TAB) {
|
|
60
|
+
target.classList.add("tabbed");
|
|
61
|
+
target.addEventListener("blur", () => target.classList.remove("tabbed"), {
|
|
62
|
+
once: true
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
document.querySelectorAll(".expressive-textarea").forEach((textArea) => {
|
|
68
|
+
_Forms.InitTextarea(textArea);
|
|
69
|
+
});
|
|
70
|
+
document.querySelectorAll('.file-field input[type="file"]').forEach((fileInput) => {
|
|
71
|
+
_Forms.InitFileInputPath(fileInput);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
static InitTextarea(textarea) {
|
|
76
|
+
textarea.setAttribute("original-height", textarea.getBoundingClientRect().height.toString());
|
|
77
|
+
_Forms.textareaAutoResize(textarea);
|
|
78
|
+
textarea.addEventListener("input", (e) => _Forms.textareaAutoResize(e.target));
|
|
79
|
+
}
|
|
80
|
+
static InitFileInputPath(fileInput) {
|
|
81
|
+
fileInput.addEventListener("change", () => {
|
|
82
|
+
const fileField = fileInput.closest(".file-field");
|
|
83
|
+
const pathInput = fileField.querySelector("input.file-path");
|
|
84
|
+
const files = fileInput.files;
|
|
85
|
+
const filenames = [];
|
|
86
|
+
for (let i = 0; i < files.length; i++) {
|
|
87
|
+
filenames.push(files[i].name);
|
|
88
|
+
}
|
|
89
|
+
pathInput.value = filenames.join(", ");
|
|
90
|
+
pathInput.dispatchEvent(
|
|
91
|
+
new Event("change", { bubbles: true, cancelable: true, composed: true })
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export {
|
|
98
|
+
Forms
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=chunk-JR24UB4X.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/behaviors/forms.ts"],
|
|
4
|
+
"sourcesContent": ["import { Utils } from '../core/utils';\n\nexport class Forms {\n /**\n * Checks if the label has validation and apply\n * the correct class and styles\n * @param textfield\n */\n static validateField(textfield: HTMLInputElement) {\n if (!textfield) {\n console.error('No text field element found');\n return;\n }\n\n const hasLength = textfield.getAttribute('data-length') !== null;\n const lenAttr = parseInt(textfield.getAttribute('data-length'));\n const len = textfield.value.length;\n\n if (\n len === 0 &&\n textfield.validity.badInput === false &&\n !textfield.required &&\n textfield.classList.contains('validate')\n ) {\n textfield.classList.remove('invalid');\n } else if (textfield.classList.contains('validate')) {\n // Check for character counter attributes\n if (\n (textfield.validity.valid && hasLength && len <= lenAttr) ||\n (textfield.validity.valid && !hasLength)\n ) {\n textfield.classList.remove('invalid');\n } else {\n textfield.classList.add('invalid');\n }\n }\n }\n\n /**\n * Resizes the given TextArea after updating the\n * value content dynamically.\n * @param e EventTarget\n */\n static textareaAutoResize(e: EventTarget) {\n const textarea = e as HTMLTextAreaElement;\n if (!textarea) return;\n\n // Measure the textarea against itself: collapse it to its natural height,\n // then read the content height back. `.expressive-textarea` is\n // `overflow-y: hidden`, so scrollHeight is the full content height and\n // offsetHeight - clientHeight is exactly the borders (no scrollbar to\n // account for) - which border-box sizing needs added back.\n //\n // This replaces a mirror div that the value was copied into via\n // `innerHTML = innerHTML.replace(...)` - a full serialize and reparse of\n // the text on every keystroke, plus getComputedStyle and seven style\n // writes, run twice per keystroke because it was bound to keydown and\n // keyup both.\n if (!textarea.hasAttribute('original-height')) {\n textarea.setAttribute('original-height', textarea.getBoundingClientRect().height.toString());\n }\n const originalHeight = parseInt(textarea.getAttribute('original-height'));\n if (isNaN(originalHeight)) return;\n\n textarea.style.height = 'auto';\n // Three reads after a single write: one layout flush for the whole resize.\n const borders = textarea.offsetHeight - textarea.clientHeight;\n const contentHeight = textarea.scrollHeight + borders;\n textarea.style.height = Math.max(originalHeight, contentHeight) + 'px';\n }\n\n static Init() {\n Utils.onDocumentReady(() => {\n document.addEventListener('change', (e: KeyboardEvent) => {\n const target = <HTMLInputElement>e.target;\n if (target instanceof HTMLInputElement) {\n // The sibling-label loop that used to live here compared\n // `tagName == 'label'` (tagName is uppercase) so it never matched,\n // and no rule in the Sass styles `label.active` anyway - the\n // floating label is driven by CSS, not by a class from here.\n Forms.validateField(target);\n }\n });\n\n document.addEventListener('keyup', (e: KeyboardEvent) => {\n const target = <HTMLInputElement>e.target;\n // Radio and Checkbox focus class\n if (target instanceof HTMLInputElement && ['radio', 'checkbox'].includes(target.type)) {\n // TAB, check if tabbing to radio or checkbox.\n if (e.key === Utils.keys.TAB) {\n target.classList.add('tabbed');\n target.addEventListener('blur', () => target.classList.remove('tabbed'), {\n once: true\n });\n }\n }\n });\n\n document.querySelectorAll('.expressive-textarea').forEach((textArea: HTMLTextAreaElement) => {\n Forms.InitTextarea(textArea);\n });\n\n // File Input Path\n document\n .querySelectorAll('.file-field input[type=\"file\"]')\n .forEach((fileInput: HTMLInputElement) => {\n Forms.InitFileInputPath(fileInput);\n });\n });\n }\n\n static InitTextarea(textarea: HTMLTextAreaElement) {\n // Save Data in Element\n textarea.setAttribute('original-height', textarea.getBoundingClientRect().height.toString());\n Forms.textareaAutoResize(textarea);\n // `input` rather than keydown + keyup: it fires once per actual value\n // change and also covers paste, drag-drop and IME composition, which the\n // key events missed.\n textarea.addEventListener('input', (e) => Forms.textareaAutoResize(e.target));\n }\n\n static InitFileInputPath(fileInput: HTMLInputElement) {\n fileInput.addEventListener('change', () => {\n const fileField = fileInput.closest('.file-field');\n const pathInput = <HTMLInputElement>fileField.querySelector('input.file-path');\n const files = fileInput.files;\n const filenames = [];\n for (let i = 0; i < files.length; i++) {\n filenames.push(files[i].name);\n }\n pathInput.value = filenames.join(', ');\n pathInput.dispatchEvent(\n new Event('change', { bubbles: true, cancelable: true, composed: true })\n );\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
installSheetDrag
|
|
3
|
+
} from "./chunk-LZVBJ33S.mjs";
|
|
4
|
+
import {
|
|
5
|
+
Utils
|
|
6
|
+
} from "./chunk-MISGHDUU.mjs";
|
|
7
|
+
|
|
8
|
+
// src/ts/behaviors/bottomSheets.ts
|
|
9
|
+
var SHEET_SELECTOR = "dialog.bottom-sheet, dialog.bottom";
|
|
10
|
+
var _BottomSheets = class _BottomSheets {
|
|
11
|
+
static Init() {
|
|
12
|
+
installSheetDrag({
|
|
13
|
+
selector: SHEET_SELECTOR,
|
|
14
|
+
axis: "y",
|
|
15
|
+
property: "--md-comp-bottom-sheet-shift",
|
|
16
|
+
direction: () => 1,
|
|
17
|
+
inHandle: (event, dialog) => {
|
|
18
|
+
const target = event.target;
|
|
19
|
+
if (target instanceof Element && target.closest(".handle")) return true;
|
|
20
|
+
const rect = dialog.getBoundingClientRect();
|
|
21
|
+
return event.clientY >= rect.top && event.clientY <= rect.top + 48;
|
|
22
|
+
},
|
|
23
|
+
onPress: () => {
|
|
24
|
+
_BottomSheets._dragged = false;
|
|
25
|
+
},
|
|
26
|
+
onRelease: (dragged) => {
|
|
27
|
+
_BottomSheets._dragged = dragged;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Utils.onDocumentReady(() => {
|
|
31
|
+
document.addEventListener("click", _BottomSheets._onClick);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
static _onClick(event) {
|
|
35
|
+
const target = event.target;
|
|
36
|
+
if (!(target instanceof Element)) return;
|
|
37
|
+
const handle = target.closest(".handle, .drag-handle");
|
|
38
|
+
if (!(handle instanceof HTMLButtonElement)) return;
|
|
39
|
+
if (event.detail !== 0 && _BottomSheets._dragged) return;
|
|
40
|
+
const dialog = handle.closest(SHEET_SELECTOR);
|
|
41
|
+
if (dialog instanceof HTMLDialogElement && dialog.open) dialog.close();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Whether the last pointer sequence moved. A drag ends with a `click` on the
|
|
46
|
+
* element it started on, so without this the tail of a drag that snapped back
|
|
47
|
+
* would dismiss the sheet the drag had just declined to dismiss.
|
|
48
|
+
*/
|
|
49
|
+
_BottomSheets._dragged = false;
|
|
50
|
+
var BottomSheets = _BottomSheets;
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
BottomSheets
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=chunk-KR44BSYQ.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/behaviors/bottomSheets.ts"],
|
|
4
|
+
"sourcesContent": ["import { installSheetDrag } from './sheetDrag';\nimport { Utils } from '../core/utils';\n\nconst SHEET_SELECTOR = 'dialog.bottom-sheet, dialog.bottom';\n\n/**\n * Drag-to-dismiss for `dialog.bottom-sheet` / `dialog.bottom`.\n *\n * The handle is the top 48dp of the sheet (or an explicit `.drag-handle`,\n * `.handle` being its pre-1.0 spelling). A downward drag past 96dp, or a\n * flick, closes. Anything else snaps back. Content below the handle scrolls\n * normally. Light-dismiss on the scrim stays with {@link Dialogs}.\n *\n * The drag itself is {@link installSheetDrag}, shared with the side sheet. What\n * is here is what is not shared: a handle written as a `<button>` also closes\n * the sheet when it is *activated*, which is what makes it reachable without a\n * pointer - dragging is a pointer gesture, so a control labelled \"Dismiss\" that\n * only answers a drag promises an action a keyboard user cannot perform. A\n * handle written as any other element is decoration and does nothing here -\n * Escape still closes the sheet either way, natively.\n */\nexport class BottomSheets {\n /**\n * Whether the last pointer sequence moved. A drag ends with a `click` on the\n * element it started on, so without this the tail of a drag that snapped back\n * would dismiss the sheet the drag had just declined to dismiss.\n */\n private static _dragged = false;\n\n static Init() {\n installSheetDrag({\n selector: SHEET_SELECTOR,\n axis: 'y',\n property: '--md-comp-bottom-sheet-shift',\n direction: () => 1,\n inHandle: (event, dialog) => {\n const target = event.target;\n if (target instanceof Element && target.closest('.handle')) return true;\n const rect = dialog.getBoundingClientRect();\n return event.clientY >= rect.top && event.clientY <= rect.top + 48;\n },\n onPress: () => {\n BottomSheets._dragged = false;\n },\n onRelease: (dragged) => {\n BottomSheets._dragged = dragged;\n }\n });\n Utils.onDocumentReady(() => {\n document.addEventListener('click', BottomSheets._onClick);\n });\n }\n\n static _onClick(event: MouseEvent) {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const handle = target.closest('.handle, .drag-handle');\n // Only a <button> is a control. A decorative <span> in the same slot is\n // exactly what it looks like, and clicking it does nothing.\n if (!(handle instanceof HTMLButtonElement)) return;\n // `detail` is 0 when the click came from Enter or Space and >= 1 when a\n // pointer produced it, so the keyboard path is decided without consulting\n // pointer state at all - a stale drag can never swallow a key press.\n if (event.detail !== 0 && BottomSheets._dragged) return;\n const dialog = handle.closest(SHEET_SELECTOR);\n if (dialog instanceof HTMLDialogElement && dialog.open) dialog.close();\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;AAGA,IAAM,iBAAiB;AAkBhB,IAAM,gBAAN,MAAM,cAAa;AAAA,EAQxB,OAAO,OAAO;AACZ,qBAAiB;AAAA,MACf,UAAU;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,WAAW,MAAM;AAAA,MACjB,UAAU,CAAC,OAAO,WAAW;AAC3B,cAAM,SAAS,MAAM;AACrB,YAAI,kBAAkB,WAAW,OAAO,QAAQ,SAAS,EAAG,QAAO;AACnE,cAAM,OAAO,OAAO,sBAAsB;AAC1C,eAAO,MAAM,WAAW,KAAK,OAAO,MAAM,WAAW,KAAK,MAAM;AAAA,MAClE;AAAA,MACA,SAAS,MAAM;AACb,sBAAa,WAAW;AAAA,MAC1B;AAAA,MACA,WAAW,CAAC,YAAY;AACtB,sBAAa,WAAW;AAAA,MAC1B;AAAA,IACF,CAAC;AACD,UAAM,gBAAgB,MAAM;AAC1B,eAAS,iBAAiB,SAAS,cAAa,QAAQ;AAAA,IAC1D,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,SAAS,OAAmB;AACjC,UAAM,SAAS,MAAM;AACrB,QAAI,EAAE,kBAAkB,SAAU;AAClC,UAAM,SAAS,OAAO,QAAQ,uBAAuB;AAGrD,QAAI,EAAE,kBAAkB,mBAAoB;AAI5C,QAAI,MAAM,WAAW,KAAK,cAAa,SAAU;AACjD,UAAM,SAAS,OAAO,QAAQ,cAAc;AAC5C,QAAI,kBAAkB,qBAAqB,OAAO,KAAM,QAAO,MAAM;AAAA,EACvE;AACF;AAAA;AAAA;AAAA;AAAA;AAAA;AA9Ca,cAMI,WAAW;AANrB,IAAM,eAAN;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Utils
|
|
3
|
+
} from "./chunk-MISGHDUU.mjs";
|
|
4
|
+
|
|
5
|
+
// src/ts/behaviors/sheetDrag.ts
|
|
6
|
+
var DISMISS_DISTANCE = 96;
|
|
7
|
+
var DISMISS_VELOCITY = 0.5;
|
|
8
|
+
var DRAG_SLOP = 4;
|
|
9
|
+
function installSheetDrag(config) {
|
|
10
|
+
const coord = (event) => config.axis === "x" ? event.clientX : event.clientY;
|
|
11
|
+
let observer;
|
|
12
|
+
let drag = null;
|
|
13
|
+
const sheetFor = (target) => {
|
|
14
|
+
if (!(target instanceof Element)) return null;
|
|
15
|
+
const dialog = target.closest(config.selector);
|
|
16
|
+
return dialog instanceof HTMLDialogElement ? dialog : null;
|
|
17
|
+
};
|
|
18
|
+
const reset = (dialog) => {
|
|
19
|
+
dialog.style.transition = "";
|
|
20
|
+
dialog.style.setProperty(config.property, "0px");
|
|
21
|
+
};
|
|
22
|
+
const onDown = (event) => {
|
|
23
|
+
if (!event.isPrimary) return;
|
|
24
|
+
if (event.pointerType === "mouse" && event.button !== 0) return;
|
|
25
|
+
onCancel();
|
|
26
|
+
config.onPress?.();
|
|
27
|
+
const dialog = sheetFor(event.target);
|
|
28
|
+
if (!dialog?.open) {
|
|
29
|
+
drag = null;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (!config.inHandle(event, dialog)) {
|
|
33
|
+
drag = null;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
dialog.style.transition = "none";
|
|
37
|
+
drag = {
|
|
38
|
+
dialog,
|
|
39
|
+
pointerId: event.pointerId,
|
|
40
|
+
direction: config.direction(dialog),
|
|
41
|
+
start: coord(event),
|
|
42
|
+
last: coord(event),
|
|
43
|
+
lastT: Date.now(),
|
|
44
|
+
shift: 0
|
|
45
|
+
};
|
|
46
|
+
observer.observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: ["open"], attributeOldValue: true });
|
|
47
|
+
};
|
|
48
|
+
const onMove = (event) => {
|
|
49
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
50
|
+
if (!drag.dialog.open || !drag.dialog.isConnected) {
|
|
51
|
+
onCancel();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const delta = coord(event) - drag.start;
|
|
55
|
+
drag.shift = drag.direction === 1 ? Math.max(0, delta) : Math.min(0, delta);
|
|
56
|
+
drag.last = coord(event);
|
|
57
|
+
drag.lastT = Date.now();
|
|
58
|
+
drag.dialog.style.setProperty(config.property, `${drag.shift}px`);
|
|
59
|
+
};
|
|
60
|
+
const onUp = (event) => {
|
|
61
|
+
const held = drag;
|
|
62
|
+
if (!held || held.pointerId !== event.pointerId) return;
|
|
63
|
+
if (!held.dialog.open || !held.dialog.isConnected) {
|
|
64
|
+
onCancel();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
drag = null;
|
|
68
|
+
observer.disconnect();
|
|
69
|
+
held.dialog.style.transition = "";
|
|
70
|
+
const dt = Math.max(1, Date.now() - held.lastT);
|
|
71
|
+
const velocity = (coord(event) - held.last) / dt;
|
|
72
|
+
config.onRelease?.(Math.abs(held.shift) > DRAG_SLOP);
|
|
73
|
+
const dismiss = held.direction === 1 ? held.shift > DISMISS_DISTANCE || velocity > DISMISS_VELOCITY : held.shift < -DISMISS_DISTANCE || velocity < -DISMISS_VELOCITY;
|
|
74
|
+
if (dismiss && held.dialog.open) held.dialog.close();
|
|
75
|
+
held.dialog.style.setProperty(config.property, "0px");
|
|
76
|
+
};
|
|
77
|
+
const onCancel = (event) => {
|
|
78
|
+
if (event && drag?.pointerId !== event.pointerId) return;
|
|
79
|
+
observer.disconnect();
|
|
80
|
+
config.onRelease?.(false);
|
|
81
|
+
const held = drag;
|
|
82
|
+
drag = null;
|
|
83
|
+
if (held) reset(held.dialog);
|
|
84
|
+
};
|
|
85
|
+
Utils.onDocumentReady(() => {
|
|
86
|
+
observer = new MutationObserver((records) => {
|
|
87
|
+
const dialog = drag?.dialog;
|
|
88
|
+
if (dialog && (!dialog.open || !dialog.isConnected || records.some(
|
|
89
|
+
(record) => record.type === "attributes" && record.target === dialog && record.oldValue === null || [...record.removedNodes].some((node) => node.contains(dialog))
|
|
90
|
+
))) onCancel();
|
|
91
|
+
});
|
|
92
|
+
document.addEventListener("pointerdown", onDown, { passive: true });
|
|
93
|
+
document.addEventListener("pointermove", onMove, { passive: true });
|
|
94
|
+
document.addEventListener("pointerup", onUp, { passive: true });
|
|
95
|
+
document.addEventListener("pointercancel", onCancel, { passive: true });
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export {
|
|
100
|
+
installSheetDrag
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=chunk-LZVBJ33S.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/behaviors/sheetDrag.ts"],
|
|
4
|
+
"sourcesContent": ["import { Utils } from '../core/utils';\n\n/**\n * Drag-to-dismiss, shared by the bottom sheet and the side sheet.\n *\n * The two were the same state machine written twice on different axes - same\n * dismissal distance, same flick velocity, same transition suppression, same\n * pointer bookkeeping - so a fix to one could land without reaching the other.\n * What actually differs between them is stated as configuration below.\n *\n * Light-dismiss on the scrim is not here; it stays with `Dialogs`.\n */\nexport interface SheetDragConfig {\n /** Which dialogs this drag applies to. */\n selector: string;\n /** The axis the sheet travels on. */\n axis: 'x' | 'y';\n /** The custom property carrying the live drag offset. */\n property: string;\n /**\n * `1` when the sheet dismisses toward increasing coordinates (downward, or\n * rightward for an end-docked side sheet), `-1` when it dismisses toward\n * decreasing ones. A function rather than a constant because a side sheet's\n * direction depends on which edge each individual sheet is docked to.\n */\n direction: (dialog: HTMLDialogElement) => 1 | -1;\n /** Whether a press at this point landed on the sheet's drag handle. */\n inHandle: (event: PointerEvent, dialog: HTMLDialogElement) => boolean;\n /**\n * Called on primary `pointerdown`, after clearing the previous drag. The\n * bottom sheet clears its dragged flag here so a sequence abandoned without\n * a `pointerup` cannot leave the flag set and swallow the next tap.\n */\n onPress?: () => void;\n /** Called when a drag ends, with whether the pointer actually moved. */\n onRelease?: (dragged: boolean) => void;\n}\n\n/** Past this the sheet dismisses rather than snapping back, in pixels. */\nconst DISMISS_DISTANCE = 96;\n/** Past this a flick dismisses whatever the distance, in pixels per millisecond. */\nconst DISMISS_VELOCITY = 0.5;\n/** Past this the pointer was dragging, not tapping. Hand jitter, in pixels. */\nconst DRAG_SLOP = 4;\n\n/**\n * Register one sheet kind's drag handlers on the document. Called once per kind\n * at import time; there is nothing to tear down.\n */\nexport function installSheetDrag(config: SheetDragConfig): void {\n const coord = (event: PointerEvent) => (config.axis === 'x' ? event.clientX : event.clientY);\n let observer: MutationObserver;\n\n let drag: {\n dialog: HTMLDialogElement;\n pointerId: number;\n direction: 1 | -1;\n start: number;\n last: number;\n lastT: number;\n shift: number;\n } | null = null;\n\n const sheetFor = (target: EventTarget | null): HTMLDialogElement | null => {\n if (!(target instanceof Element)) return null;\n const dialog = target.closest(config.selector);\n return dialog instanceof HTMLDialogElement ? dialog : null;\n };\n\n const reset = (dialog: HTMLDialogElement) => {\n dialog.style.transition = '';\n dialog.style.setProperty(config.property, '0px');\n };\n\n const onDown = (event: PointerEvent) => {\n // A press that is not the primary pointer is ignored without disturbing a\n // drag already in flight - a second finger must not abort the first one.\n // A press that lands off the sheet or off its handle does clear it.\n if (!event.isPrimary) return;\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n onCancel();\n config.onPress?.();\n const dialog = sheetFor(event.target);\n if (!dialog?.open) {\n drag = null;\n return;\n }\n if (!config.inHandle(event, dialog)) {\n drag = null;\n return;\n }\n dialog.style.transition = 'none';\n drag = {\n dialog,\n pointerId: event.pointerId,\n direction: config.direction(dialog),\n start: coord(event),\n last: coord(event),\n lastT: Date.now(),\n shift: 0\n };\n observer.observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: ['open'], attributeOldValue: true });\n };\n\n const onMove = (event: PointerEvent) => {\n if (!drag || drag.pointerId !== event.pointerId) return;\n if (!drag.dialog.open || !drag.dialog.isConnected) {\n onCancel();\n return;\n }\n const delta = coord(event) - drag.start;\n // Only movement toward dismissal counts; dragging the other way is a no-op\n // rather than a sheet that lifts off its edge.\n drag.shift = drag.direction === 1 ? Math.max(0, delta) : Math.min(0, delta);\n drag.last = coord(event);\n drag.lastT = Date.now();\n drag.dialog.style.setProperty(config.property, `${drag.shift}px`);\n };\n\n const onUp = (event: PointerEvent) => {\n const held = drag;\n if (!held || held.pointerId !== event.pointerId) return;\n if (!held.dialog.open || !held.dialog.isConnected) {\n onCancel();\n return;\n }\n drag = null;\n observer.disconnect();\n // Not `reset()`, though it looks like it: the two halves belong on either\n // side of close(). The transition has to be back before the sheet closes,\n // so the dismissal animates; the shift has to clear after, or a snap-back\n // would jump to zero before the transition could carry it there.\n held.dialog.style.transition = '';\n const dt = Math.max(1, Date.now() - held.lastT);\n const velocity = (coord(event) - held.last) / dt;\n config.onRelease?.(Math.abs(held.shift) > DRAG_SLOP);\n const dismiss =\n held.direction === 1\n ? held.shift > DISMISS_DISTANCE || velocity > DISMISS_VELOCITY\n : held.shift < -DISMISS_DISTANCE || velocity < -DISMISS_VELOCITY;\n if (dismiss && held.dialog.open) held.dialog.close();\n held.dialog.style.setProperty(config.property, '0px');\n };\n\n const onCancel = (event?: PointerEvent) => {\n if (event && drag?.pointerId !== event.pointerId) return;\n observer.disconnect();\n config.onRelease?.(false);\n const held = drag;\n drag = null;\n if (held) reset(held.dialog);\n };\n\n Utils.onDocumentReady(() => {\n observer = new MutationObserver(records => {\n const dialog = drag?.dialog;\n if (dialog && (!dialog.open || !dialog.isConnected || records.some(record =>\n (record.type === 'attributes' && record.target === dialog && record.oldValue === null) ||\n [...record.removedNodes].some(node => node.contains(dialog))\n ))) onCancel();\n });\n document.addEventListener('pointerdown', onDown, { passive: true });\n document.addEventListener('pointermove', onMove, { passive: true });\n document.addEventListener('pointerup', onUp, { passive: true });\n document.addEventListener('pointercancel', onCancel, { passive: true });\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|