@unabridged/midwest 0.22.1 → 0.23.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/README.md +1 -1
- package/app/assets/javascript/midwest/index.ts +8 -0
- package/app/assets/javascript/midwest/keyboard_navigation.ts +68 -0
- package/app/assets/javascript/midwest/markdown.ts +79 -0
- package/app/assets/javascript/midwest.js +795 -39
- package/app/assets/javascript/midwest.js.map +1 -1
- package/app/assets/stylesheets/midwest/utilities.css +4 -0
- package/app/assets/stylesheets/midwest.css +1 -1
- package/app/assets/stylesheets/midwest.tailwind.css +13 -1
- package/dist/css/midwest.css +1 -1
- package/dist/javascript/collection/app/assets/javascript/midwest/index.js +8 -0
- package/dist/javascript/collection/app/assets/javascript/midwest/index.js.map +1 -1
- package/dist/javascript/collection/app/assets/javascript/midwest/keyboard_navigation.js +42 -0
- package/dist/javascript/collection/app/assets/javascript/midwest/keyboard_navigation.js.map +1 -0
- package/dist/javascript/collection/app/assets/javascript/midwest/markdown.js +52 -0
- package/dist/javascript/collection/app/assets/javascript/midwest/markdown.js.map +1 -0
- package/dist/javascript/collection/app/components/midwest/command_palette_component/command_palette_component_controller.js +270 -2
- package/dist/javascript/collection/app/components/midwest/command_palette_component/command_palette_component_controller.js.map +1 -1
- package/dist/javascript/collection/app/components/midwest/dropdown_component/dropdown_component_controller.js +8 -37
- package/dist/javascript/collection/app/components/midwest/dropdown_component/dropdown_component_controller.js.map +1 -1
- package/dist/javascript/collection/app/components/midwest/focus_trap_component/focus_trap_component_controller.js +83 -0
- package/dist/javascript/collection/app/components/midwest/focus_trap_component/focus_trap_component_controller.js.map +1 -0
- package/dist/javascript/collection/app/components/midwest/form/switch_component/theme_switch_controller.js +42 -0
- package/dist/javascript/collection/app/components/midwest/form/switch_component/theme_switch_controller.js.map +1 -0
- package/dist/javascript/collection/app/components/midwest/intersection_observer_component/intersection_observer_component_controller.js +43 -0
- package/dist/javascript/collection/app/components/midwest/intersection_observer_component/intersection_observer_component_controller.js.map +1 -0
- package/dist/javascript/collection/app/components/midwest/onboarding_component/onboarding_component_controller.js +273 -0
- package/dist/javascript/collection/app/components/midwest/onboarding_component/onboarding_component_controller.js.map +1 -0
- package/dist/javascript/midwest.js +795 -39
- package/dist/javascript/midwest.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
|
2
|
+
|
|
3
|
+
const FOCUSABLE = [
|
|
4
|
+
"a[href]",
|
|
5
|
+
"button:not([disabled])",
|
|
6
|
+
"textarea:not([disabled])",
|
|
7
|
+
"input:not([disabled])",
|
|
8
|
+
"select:not([disabled])",
|
|
9
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
10
|
+
].join(", ");
|
|
11
|
+
const GAP = 12;
|
|
12
|
+
class Onboarding extends Controller {
|
|
13
|
+
static targets = ["step", "overlay", "card", "title", "body", "back", "next", "done", "arrow"];
|
|
14
|
+
static values = {
|
|
15
|
+
autoOpen: { type: Boolean, default: false },
|
|
16
|
+
confirm: { type: String, default: "" }
|
|
17
|
+
};
|
|
18
|
+
steps = [];
|
|
19
|
+
index = 0;
|
|
20
|
+
active = false;
|
|
21
|
+
previousFocus = null;
|
|
22
|
+
highlighted = null;
|
|
23
|
+
connect() {
|
|
24
|
+
this.steps = this.stepTargets.map((el) => ({
|
|
25
|
+
el,
|
|
26
|
+
name: el.dataset.name ?? "",
|
|
27
|
+
selector: el.dataset.selector ?? "",
|
|
28
|
+
position: el.dataset.position ?? "auto",
|
|
29
|
+
title: el.dataset.title ?? "",
|
|
30
|
+
nextText: el.dataset.nextText ?? "Next",
|
|
31
|
+
backText: el.dataset.backText ?? "Back",
|
|
32
|
+
completeText: el.dataset.completeText ?? "Done",
|
|
33
|
+
canClickTarget: el.dataset.canClickTarget === "true"
|
|
34
|
+
}));
|
|
35
|
+
window.addEventListener("midwest-onboarding:open", this.handleOpen);
|
|
36
|
+
if (this.autoOpenValue)
|
|
37
|
+
this.start();
|
|
38
|
+
}
|
|
39
|
+
disconnect() {
|
|
40
|
+
window.removeEventListener("midwest-onboarding:open", this.handleOpen);
|
|
41
|
+
this.teardown();
|
|
42
|
+
}
|
|
43
|
+
start() {
|
|
44
|
+
if (this.active || this.steps.length === 0)
|
|
45
|
+
return;
|
|
46
|
+
this.active = true;
|
|
47
|
+
this.previousFocus = document.activeElement;
|
|
48
|
+
this.overlayTarget.hidden = false;
|
|
49
|
+
this.cardTarget.hidden = false;
|
|
50
|
+
document.addEventListener("keydown", this.handleKeydown, true);
|
|
51
|
+
window.addEventListener("resize", this.reposition);
|
|
52
|
+
window.addEventListener("scroll", this.reposition, true);
|
|
53
|
+
this.dispatch("start", { bubbles: true });
|
|
54
|
+
this.render(0);
|
|
55
|
+
}
|
|
56
|
+
next() {
|
|
57
|
+
if (this.index < this.steps.length - 1)
|
|
58
|
+
this.render(this.index + 1);
|
|
59
|
+
else
|
|
60
|
+
this.complete();
|
|
61
|
+
}
|
|
62
|
+
back() {
|
|
63
|
+
if (this.index > 0)
|
|
64
|
+
this.render(this.index - 1);
|
|
65
|
+
}
|
|
66
|
+
// Jump to a step by its `name`.
|
|
67
|
+
show(name) {
|
|
68
|
+
const target = this.steps.findIndex((step) => step.name === name);
|
|
69
|
+
if (target >= 0) {
|
|
70
|
+
if (!this.active)
|
|
71
|
+
this.start();
|
|
72
|
+
this.render(target);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
complete() {
|
|
76
|
+
if (!this.active)
|
|
77
|
+
return;
|
|
78
|
+
this.teardown();
|
|
79
|
+
this.dispatch("complete", { bubbles: true });
|
|
80
|
+
}
|
|
81
|
+
cancel() {
|
|
82
|
+
if (!this.active)
|
|
83
|
+
return;
|
|
84
|
+
if (this.confirmValue && !window.confirm(this.confirmValue))
|
|
85
|
+
return;
|
|
86
|
+
this.teardown();
|
|
87
|
+
this.dispatch("cancel", { bubbles: true });
|
|
88
|
+
}
|
|
89
|
+
render(index) {
|
|
90
|
+
this.index = index;
|
|
91
|
+
const step = this.steps[index];
|
|
92
|
+
this.clearHighlight();
|
|
93
|
+
this.titleTarget.textContent = step.title;
|
|
94
|
+
this.renderBody(step);
|
|
95
|
+
this.renderButtons(step, index);
|
|
96
|
+
const target = step.selector ? document.querySelector(step.selector) : null;
|
|
97
|
+
if (target) {
|
|
98
|
+
this.highlight(target, step.canClickTarget);
|
|
99
|
+
this.position(target, step.position);
|
|
100
|
+
} else {
|
|
101
|
+
this.center();
|
|
102
|
+
}
|
|
103
|
+
this.dispatch("show", { detail: { index, name: step.name }, bubbles: true });
|
|
104
|
+
this.focusCard();
|
|
105
|
+
}
|
|
106
|
+
renderBody(step) {
|
|
107
|
+
this.bodyTarget.replaceChildren();
|
|
108
|
+
const template = step.el.querySelector("template");
|
|
109
|
+
if (template)
|
|
110
|
+
this.bodyTarget.appendChild(template.content.cloneNode(true));
|
|
111
|
+
}
|
|
112
|
+
renderButtons(step, index) {
|
|
113
|
+
const isFirst = index === 0;
|
|
114
|
+
const isLast = index === this.steps.length - 1;
|
|
115
|
+
this.backTarget.textContent = step.backText;
|
|
116
|
+
this.backTarget.style.visibility = isFirst ? "hidden" : "";
|
|
117
|
+
this.nextTarget.textContent = step.nextText;
|
|
118
|
+
this.nextTarget.style.display = isLast ? "none" : "";
|
|
119
|
+
this.doneTarget.textContent = step.completeText;
|
|
120
|
+
this.doneTarget.style.display = isLast ? "" : "none";
|
|
121
|
+
}
|
|
122
|
+
highlight(target, canClickTarget) {
|
|
123
|
+
target.classList.add("midwest-onboarding-highlight");
|
|
124
|
+
target.classList.toggle("is-locked", !canClickTarget);
|
|
125
|
+
this.highlighted = target;
|
|
126
|
+
target.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
127
|
+
}
|
|
128
|
+
clearHighlight() {
|
|
129
|
+
this.highlighted?.classList.remove("midwest-onboarding-highlight", "is-locked");
|
|
130
|
+
this.highlighted = null;
|
|
131
|
+
}
|
|
132
|
+
// Places the card against the target, choosing a side when `position` is auto.
|
|
133
|
+
position(target, position) {
|
|
134
|
+
const rect = target.getBoundingClientRect();
|
|
135
|
+
const card = this.cardTarget.getBoundingClientRect();
|
|
136
|
+
const vw = window.innerWidth;
|
|
137
|
+
const vh = window.innerHeight;
|
|
138
|
+
let placement = position;
|
|
139
|
+
if (placement === "auto") {
|
|
140
|
+
if (rect.bottom + card.height + GAP <= vh)
|
|
141
|
+
placement = "bottom";
|
|
142
|
+
else if (rect.top - card.height - GAP >= 0)
|
|
143
|
+
placement = "top";
|
|
144
|
+
else if (rect.right + card.width + GAP <= vw)
|
|
145
|
+
placement = "right";
|
|
146
|
+
else
|
|
147
|
+
placement = "left";
|
|
148
|
+
}
|
|
149
|
+
let top;
|
|
150
|
+
let left;
|
|
151
|
+
switch (placement) {
|
|
152
|
+
case "top":
|
|
153
|
+
top = rect.top - card.height - GAP;
|
|
154
|
+
left = rect.left + rect.width / 2 - card.width / 2;
|
|
155
|
+
break;
|
|
156
|
+
case "left":
|
|
157
|
+
top = rect.top + rect.height / 2 - card.height / 2;
|
|
158
|
+
left = rect.left - card.width - GAP;
|
|
159
|
+
break;
|
|
160
|
+
case "right":
|
|
161
|
+
top = rect.top + rect.height / 2 - card.height / 2;
|
|
162
|
+
left = rect.right + GAP;
|
|
163
|
+
break;
|
|
164
|
+
default:
|
|
165
|
+
top = rect.bottom + GAP;
|
|
166
|
+
left = rect.left + rect.width / 2 - card.width / 2;
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
left = Math.max(8, Math.min(left, vw - card.width - 8));
|
|
170
|
+
top = Math.max(8, Math.min(top, vh - card.height - 8));
|
|
171
|
+
this.cardTarget.style.top = `${top}px`;
|
|
172
|
+
this.cardTarget.style.left = `${left}px`;
|
|
173
|
+
this.cardTarget.dataset.placement = placement;
|
|
174
|
+
this.positionArrow(placement, rect, top, left);
|
|
175
|
+
}
|
|
176
|
+
// Nudges the arrow so it points at the target's center, not the card's.
|
|
177
|
+
positionArrow(placement, rect, top, left) {
|
|
178
|
+
const card = this.cardTarget.getBoundingClientRect();
|
|
179
|
+
const arrow = this.arrowTarget.style;
|
|
180
|
+
if (placement === "top" || placement === "bottom") {
|
|
181
|
+
const targetCenter = rect.left + rect.width / 2;
|
|
182
|
+
const offset = Math.max(12, Math.min(targetCenter - left, card.width - 12));
|
|
183
|
+
arrow.left = `${offset}px`;
|
|
184
|
+
arrow.top = "";
|
|
185
|
+
} else {
|
|
186
|
+
const targetCenter = rect.top + rect.height / 2;
|
|
187
|
+
const offset = Math.max(12, Math.min(targetCenter - top, card.height - 12));
|
|
188
|
+
arrow.top = `${offset}px`;
|
|
189
|
+
arrow.left = "";
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
center() {
|
|
193
|
+
const card = this.cardTarget.getBoundingClientRect();
|
|
194
|
+
this.cardTarget.style.top = `${Math.max(8, window.innerHeight / 2 - card.height / 2)}px`;
|
|
195
|
+
this.cardTarget.style.left = `${Math.max(8, window.innerWidth / 2 - card.width / 2)}px`;
|
|
196
|
+
this.cardTarget.dataset.placement = "center";
|
|
197
|
+
}
|
|
198
|
+
focusCard() {
|
|
199
|
+
requestAnimationFrame(() => {
|
|
200
|
+
if (this.active)
|
|
201
|
+
this.cardTarget.focus();
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
teardown() {
|
|
205
|
+
this.active = false;
|
|
206
|
+
this.clearHighlight();
|
|
207
|
+
this.overlayTarget.hidden = true;
|
|
208
|
+
this.cardTarget.hidden = true;
|
|
209
|
+
document.removeEventListener("keydown", this.handleKeydown, true);
|
|
210
|
+
window.removeEventListener("resize", this.reposition);
|
|
211
|
+
window.removeEventListener("scroll", this.reposition, true);
|
|
212
|
+
this.previousFocus?.focus();
|
|
213
|
+
this.previousFocus = null;
|
|
214
|
+
}
|
|
215
|
+
handleOpen = (event) => {
|
|
216
|
+
const detail = event.detail ?? {};
|
|
217
|
+
const id = String(detail.id ?? "").replace("#", "");
|
|
218
|
+
if (id === this.element.id)
|
|
219
|
+
this.start();
|
|
220
|
+
};
|
|
221
|
+
reposition = () => {
|
|
222
|
+
if (!this.active)
|
|
223
|
+
return;
|
|
224
|
+
const step = this.steps[this.index];
|
|
225
|
+
const target = step.selector ? document.querySelector(step.selector) : null;
|
|
226
|
+
if (target)
|
|
227
|
+
this.position(target, step.position);
|
|
228
|
+
else
|
|
229
|
+
this.center();
|
|
230
|
+
};
|
|
231
|
+
handleKeydown = (event) => {
|
|
232
|
+
if (!this.active)
|
|
233
|
+
return;
|
|
234
|
+
switch (event.key) {
|
|
235
|
+
case "Escape":
|
|
236
|
+
event.preventDefault();
|
|
237
|
+
this.cancel();
|
|
238
|
+
break;
|
|
239
|
+
case "ArrowRight":
|
|
240
|
+
event.preventDefault();
|
|
241
|
+
this.next();
|
|
242
|
+
break;
|
|
243
|
+
case "ArrowLeft":
|
|
244
|
+
event.preventDefault();
|
|
245
|
+
this.back();
|
|
246
|
+
break;
|
|
247
|
+
case "Tab":
|
|
248
|
+
this.trapTab(event);
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
// Keep Tab focus within the card while the tour is active.
|
|
253
|
+
trapTab(event) {
|
|
254
|
+
const focusable = Array.from(this.cardTarget.querySelectorAll(FOCUSABLE)).filter((el) => !el.hidden && el.offsetParent !== null && getComputedStyle(el).visibility !== "hidden");
|
|
255
|
+
if (focusable.length === 0)
|
|
256
|
+
return;
|
|
257
|
+
const first = focusable[0];
|
|
258
|
+
const last = focusable[focusable.length - 1];
|
|
259
|
+
const active = document.activeElement;
|
|
260
|
+
if (event.shiftKey) {
|
|
261
|
+
if (active === first || active === this.cardTarget || !this.cardTarget.contains(active)) {
|
|
262
|
+
event.preventDefault();
|
|
263
|
+
last.focus();
|
|
264
|
+
}
|
|
265
|
+
} else if (active === last || !this.cardTarget.contains(active)) {
|
|
266
|
+
event.preventDefault();
|
|
267
|
+
first.focus();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export { Onboarding as default };
|
|
273
|
+
//# sourceMappingURL=onboarding_component_controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding_component_controller.js","sources":["../../../../../../../app/components/midwest/onboarding_component/onboarding_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\nconst FOCUSABLE = [\n 'a[href]',\n 'button:not([disabled])',\n 'textarea:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])'\n].join(', ')\n\nconst GAP = 12 // px between the target and the card\n\ninterface StepConfig {\n el: HTMLElement\n name: string\n selector: string\n position: string\n title: string\n nextText: string\n backText: string\n completeText: string\n canClickTarget: boolean\n}\n\n// Native, dependency-free guided-tour engine. Reads the nested step config\n// carriers, then walks the user through them with a dimmed overlay, a card\n// positioned against each step's target element, and Back/Next/Done buttons.\nexport default class Onboarding extends Controller<HTMLElement> {\n static targets = ['step', 'overlay', 'card', 'title', 'body', 'back', 'next', 'done', 'arrow']\n\n static values = {\n autoOpen: { type: Boolean, default: false },\n confirm: { type: String, default: '' }\n }\n\n declare readonly stepTargets: HTMLElement[]\n declare readonly overlayTarget: HTMLElement\n declare readonly cardTarget: HTMLElement\n declare readonly titleTarget: HTMLElement\n declare readonly bodyTarget: HTMLElement\n declare readonly backTarget: HTMLButtonElement\n declare readonly nextTarget: HTMLButtonElement\n declare readonly doneTarget: HTMLButtonElement\n declare readonly arrowTarget: HTMLElement\n declare autoOpenValue: boolean\n declare confirmValue: string\n\n private steps: StepConfig[] = []\n private index = 0\n private active = false\n private previousFocus: HTMLElement | null = null\n private highlighted: HTMLElement | null = null\n\n connect () {\n this.steps = this.stepTargets.map((el) => ({\n el,\n name: el.dataset.name ?? '',\n selector: el.dataset.selector ?? '',\n position: el.dataset.position ?? 'auto',\n title: el.dataset.title ?? '',\n nextText: el.dataset.nextText ?? 'Next',\n backText: el.dataset.backText ?? 'Back',\n completeText: el.dataset.completeText ?? 'Done',\n canClickTarget: el.dataset.canClickTarget === 'true'\n }))\n\n window.addEventListener('midwest-onboarding:open', this.handleOpen)\n\n if (this.autoOpenValue) this.start()\n }\n\n disconnect () {\n window.removeEventListener('midwest-onboarding:open', this.handleOpen)\n this.teardown()\n }\n\n start () {\n if (this.active || this.steps.length === 0) return\n this.active = true\n this.previousFocus = document.activeElement as HTMLElement | null\n this.overlayTarget.hidden = false\n this.cardTarget.hidden = false\n document.addEventListener('keydown', this.handleKeydown, true)\n window.addEventListener('resize', this.reposition)\n window.addEventListener('scroll', this.reposition, true)\n this.dispatch('start', { bubbles: true })\n this.render(0)\n }\n\n next () {\n if (this.index < this.steps.length - 1) this.render(this.index + 1)\n else this.complete()\n }\n\n back () {\n if (this.index > 0) this.render(this.index - 1)\n }\n\n // Jump to a step by its `name`.\n show (name: string) {\n const target = this.steps.findIndex((step) => step.name === name)\n if (target >= 0) {\n if (!this.active) this.start()\n this.render(target)\n }\n }\n\n complete () {\n if (!this.active) return\n this.teardown()\n this.dispatch('complete', { bubbles: true })\n }\n\n cancel () {\n if (!this.active) return\n if (this.confirmValue && !window.confirm(this.confirmValue)) return\n this.teardown()\n this.dispatch('cancel', { bubbles: true })\n }\n\n private render (index: number) {\n this.index = index\n const step = this.steps[index]\n\n this.clearHighlight()\n\n this.titleTarget.textContent = step.title\n this.renderBody(step)\n this.renderButtons(step, index)\n\n const target = step.selector\n ? document.querySelector<HTMLElement>(step.selector)\n : null\n\n if (target) {\n this.highlight(target, step.canClickTarget)\n this.position(target, step.position)\n } else {\n this.center()\n }\n\n this.dispatch('show', { detail: { index, name: step.name }, bubbles: true })\n this.focusCard()\n }\n\n private renderBody (step: StepConfig) {\n this.bodyTarget.replaceChildren()\n const template = step.el.querySelector('template')\n if (template) this.bodyTarget.appendChild(template.content.cloneNode(true))\n }\n\n private renderButtons (step: StepConfig, index: number) {\n const isFirst = index === 0\n const isLast = index === this.steps.length - 1\n\n // Back keeps its layout box (visibility) so the forward button never shifts;\n // Next and Done are mutually exclusive, so exactly one fills the right slot.\n this.backTarget.textContent = step.backText\n this.backTarget.style.visibility = isFirst ? 'hidden' : ''\n\n // Inline display beats the button's own `display: inline-flex` rule.\n this.nextTarget.textContent = step.nextText\n this.nextTarget.style.display = isLast ? 'none' : ''\n\n this.doneTarget.textContent = step.completeText\n this.doneTarget.style.display = isLast ? '' : 'none'\n }\n\n private highlight (target: HTMLElement, canClickTarget: boolean) {\n target.classList.add('midwest-onboarding-highlight')\n target.classList.toggle('is-locked', !canClickTarget)\n this.highlighted = target\n target.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n\n private clearHighlight () {\n this.highlighted?.classList.remove('midwest-onboarding-highlight', 'is-locked')\n this.highlighted = null\n }\n\n // Places the card against the target, choosing a side when `position` is auto.\n private position (target: HTMLElement, position: string) {\n const rect = target.getBoundingClientRect()\n const card = this.cardTarget.getBoundingClientRect()\n const vw = window.innerWidth\n const vh = window.innerHeight\n\n let placement = position\n if (placement === 'auto') {\n if (rect.bottom + card.height + GAP <= vh) placement = 'bottom'\n else if (rect.top - card.height - GAP >= 0) placement = 'top'\n else if (rect.right + card.width + GAP <= vw) placement = 'right'\n else placement = 'left'\n }\n\n let top: number\n let left: number\n\n switch (placement) {\n case 'top':\n top = rect.top - card.height - GAP\n left = rect.left + rect.width / 2 - card.width / 2\n break\n case 'left':\n top = rect.top + rect.height / 2 - card.height / 2\n left = rect.left - card.width - GAP\n break\n case 'right':\n top = rect.top + rect.height / 2 - card.height / 2\n left = rect.right + GAP\n break\n default: // bottom\n top = rect.bottom + GAP\n left = rect.left + rect.width / 2 - card.width / 2\n break\n }\n\n // Keep the card fully on screen.\n left = Math.max(8, Math.min(left, vw - card.width - 8))\n top = Math.max(8, Math.min(top, vh - card.height - 8))\n\n this.cardTarget.style.top = `${top}px`\n this.cardTarget.style.left = `${left}px`\n this.cardTarget.dataset.placement = placement\n\n this.positionArrow(placement, rect, top, left)\n }\n\n // Nudges the arrow so it points at the target's center, not the card's.\n private positionArrow (placement: string, rect: DOMRect, top: number, left: number) {\n const card = this.cardTarget.getBoundingClientRect()\n const arrow = this.arrowTarget.style\n\n if (placement === 'top' || placement === 'bottom') {\n const targetCenter = rect.left + rect.width / 2\n const offset = Math.max(12, Math.min(targetCenter - left, card.width - 12))\n arrow.left = `${offset}px`\n arrow.top = ''\n } else {\n const targetCenter = rect.top + rect.height / 2\n const offset = Math.max(12, Math.min(targetCenter - top, card.height - 12))\n arrow.top = `${offset}px`\n arrow.left = ''\n }\n }\n\n private center () {\n const card = this.cardTarget.getBoundingClientRect()\n this.cardTarget.style.top = `${Math.max(8, window.innerHeight / 2 - card.height / 2)}px`\n this.cardTarget.style.left = `${Math.max(8, window.innerWidth / 2 - card.width / 2)}px`\n this.cardTarget.dataset.placement = 'center'\n }\n\n private focusCard () {\n requestAnimationFrame(() => {\n if (this.active) this.cardTarget.focus()\n })\n }\n\n private teardown () {\n this.active = false\n this.clearHighlight()\n this.overlayTarget.hidden = true\n this.cardTarget.hidden = true\n document.removeEventListener('keydown', this.handleKeydown, true)\n window.removeEventListener('resize', this.reposition)\n window.removeEventListener('scroll', this.reposition, true)\n this.previousFocus?.focus()\n this.previousFocus = null\n }\n\n private handleOpen = (event: Event) => {\n const detail = (event as CustomEvent).detail ?? {}\n const id = String(detail.id ?? '').replace('#', '')\n if (id === this.element.id) this.start()\n }\n\n private reposition = () => {\n if (!this.active) return\n const step = this.steps[this.index]\n const target = step.selector ? document.querySelector<HTMLElement>(step.selector) : null\n if (target) this.position(target, step.position)\n else this.center()\n }\n\n private handleKeydown = (event: KeyboardEvent) => {\n if (!this.active) return\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault()\n this.cancel()\n break\n case 'ArrowRight':\n event.preventDefault()\n this.next()\n break\n case 'ArrowLeft':\n event.preventDefault()\n this.back()\n break\n case 'Tab':\n this.trapTab(event)\n break\n }\n }\n\n // Keep Tab focus within the card while the tour is active.\n private trapTab (event: KeyboardEvent) {\n const focusable = Array.from(this.cardTarget.querySelectorAll<HTMLElement>(FOCUSABLE))\n .filter((el) => !el.hidden && el.offsetParent !== null && getComputedStyle(el).visibility !== 'hidden')\n if (focusable.length === 0) return\n\n const first = focusable[0]\n const last = focusable[focusable.length - 1]\n const active = document.activeElement\n\n if (event.shiftKey) {\n if (active === first || active === this.cardTarget || !this.cardTarget.contains(active)) {\n event.preventDefault()\n last.focus()\n }\n } else if (active === last || !this.cardTarget.contains(active)) {\n event.preventDefault()\n first.focus()\n }\n }\n}\n"],"names":[],"mappings":"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"}
|