fokus-styles 2.3.0 → 2.5.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/CHANGELOG.md +36 -0
- package/dist/css/components.css +583 -83
- package/dist/css/components.css.map +1 -1
- package/dist/css/components.min.css +1 -1
- package/dist/css/components.min.css.map +1 -1
- package/dist/css/fokus-components.css +583 -83
- package/dist/css/fokus-components.css.map +1 -1
- package/dist/css/fokus-components.min.css +1 -1
- package/dist/css/fokus-components.min.css.map +1 -1
- package/dist/css/fokus-core.css +22 -0
- package/dist/css/fokus-core.css.map +1 -1
- package/dist/css/fokus-core.min.css +1 -1
- package/dist/css/fokus-core.min.css.map +1 -1
- package/dist/css/fokus-dark.css +10 -0
- package/dist/css/fokus-dark.css.map +1 -1
- package/dist/css/fokus-dark.min.css +1 -1
- package/dist/css/fokus-dark.min.css.map +1 -1
- package/dist/css/fokus-rtl.css +9166 -0
- package/dist/css/fokus-rtl.css.map +1 -0
- package/dist/css/fokus-rtl.min.css +2 -0
- package/dist/css/fokus-rtl.min.css.map +1 -0
- package/dist/css/fokus-utilities.css +158 -0
- package/dist/css/fokus-utilities.css.map +1 -1
- package/dist/css/fokus-utilities.min.css +1 -1
- package/dist/css/fokus-utilities.min.css.map +1 -1
- package/dist/css/fokus.css +1018 -258
- package/dist/css/fokus.css.map +1 -1
- package/dist/css/fokus.min.css +1 -1
- package/dist/css/fokus.min.css.map +1 -1
- package/dist/css/forms.css +322 -176
- package/dist/css/forms.css.map +1 -1
- package/dist/css/forms.min.css +1 -1
- package/dist/css/forms.min.css.map +1 -1
- package/dist/css/helpers.css +158 -0
- package/dist/css/helpers.css.map +1 -1
- package/dist/css/helpers.min.css +1 -1
- package/dist/css/helpers.min.css.map +1 -1
- package/dist/css/layout.css +22 -0
- package/dist/css/layout.css.map +1 -1
- package/dist/css/layout.min.css +1 -1
- package/dist/css/layout.min.css.map +1 -1
- package/dist/js/fokus.js +270 -25
- package/dist/js/fokus.js.map +2 -2
- package/dist/js/fokus.min.js +18 -18
- package/dist/js/fokus.min.js.map +3 -3
- package/docs/components/alert.md +69 -24
- package/docs/components/badge.md +23 -4
- package/docs/components/checkbox.md +16 -3
- package/docs/components/popover.md +20 -7
- package/docs/components/radio.md +11 -1
- package/docs/components/responsive.md +19 -0
- package/docs/components/switch.md +30 -8
- package/docs/components/tag.md +19 -4
- package/docs/components/toast.md +72 -59
- package/docs/components/tooltip.md +38 -2
- package/docs/guides/accessibility.md +7 -0
- package/docs/guides/rtl-and-system-preferences.md +28 -0
- package/docs/prompts/prompt-plan.md +4 -4
- package/docs/reference/accessibility-matrix.md +7 -7
- package/docs/reference/contrast-report.md +4 -0
- package/docs/reference/definitions.md +5 -1
- package/docs/reference/design-tokens.md +14 -0
- package/docs/reference/size-baseline.json +13 -13
- package/mockup/assets/example-theme.css +11 -0
- package/mockup/assets/showcase-contracts.js +6 -6
- package/mockup/examples/alerts.html +105 -31
- package/mockup/examples/badges-alerts.html +91 -59
- package/mockup/examples/check-radio-switch.html +575 -99
- package/mockup/examples/popover.html +81 -0
- package/mockup/examples/tag.html +97 -87
- package/mockup/examples/toast.html +113 -0
- package/mockup/examples/tooltip.html +68 -0
- package/mockup/forms.html +1 -1
- package/mockup/overlays-commands.html +2 -2
- package/package.json +2 -1
- package/packages/fokus-components/scss/components/_alerts.scss +128 -6
- package/packages/fokus-components/scss/components/_badges.scss +26 -10
- package/packages/fokus-components/scss/components/_index.scss +1 -0
- package/packages/fokus-components/scss/components/_popover.scss +131 -21
- package/packages/fokus-components/scss/components/_responsive.scss +23 -0
- package/packages/fokus-components/scss/components/_tag.scss +37 -14
- package/packages/fokus-components/scss/components/_toasts.scss +156 -11
- package/packages/fokus-components/scss/components/_tooltips.scss +70 -18
- package/packages/fokus-components/scss/forms/_check-radio-switch.scss +313 -215
- package/packages/fokus-components/scss/forms/_forms.scss +16 -0
- package/packages/fokus-core/scss/base/_accessibility.scss +14 -0
- package/packages/fokus-core/scss/tokens/_root.scss +11 -0
- package/packages/fokus-js/js/carousel.d.ts +4 -0
- package/packages/fokus-js/js/carousel.js +8 -0
- package/packages/fokus-js/js/core/positioning.js +18 -9
- package/packages/fokus-js/js/dropdown.d.ts +4 -0
- package/packages/fokus-js/js/dropdown.js +7 -0
- package/packages/fokus-js/js/popover.js +26 -1
- package/packages/fokus-js/js/tabs.d.ts +3 -0
- package/packages/fokus-js/js/tabs.js +5 -0
- package/packages/fokus-js/js/tag.js +17 -0
- package/packages/fokus-js/js/toast.js +77 -3
- package/packages/fokus-js/js/tooltip.d.ts +8 -1
- package/packages/fokus-js/js/tooltip.js +106 -13
- package/packages/fokus-utilities/scss/utilities/_api.scss +48 -0
- package/scss/entries/rtl-entry.scss +11 -0
package/dist/js/fokus.js
CHANGED
|
@@ -110,15 +110,15 @@ var FokusStyles = (() => {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
function computePosition(referenceEl, floatingEl, options = {}) {
|
|
113
|
-
|
|
113
|
+
var _a;
|
|
114
|
+
const { placement = "bottom", align = "center", offset = 8, padding = 8, fallbackPlacements } = options;
|
|
114
115
|
const referenceRect = referenceEl.getBoundingClientRect();
|
|
115
116
|
const floatingRect = floatingEl.getBoundingClientRect();
|
|
116
117
|
const viewportWidth = document.documentElement.clientWidth;
|
|
117
118
|
const viewportHeight = document.documentElement.clientHeight;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
119
|
+
const candidates = [...new Set(fallbackPlacements != null ? fallbackPlacements : [placement, OPPOSITE_PLACEMENT[placement], "bottom", "top", "right", "left"])].filter(Boolean);
|
|
120
|
+
const primaryCandidates = candidates.slice(0, 2);
|
|
121
|
+
const finalPlacement = (_a = primaryCandidates.find((candidate) => fitsPlacement(candidate, referenceRect, floatingRect, offset, viewportWidth, viewportHeight))) != null ? _a : placement;
|
|
122
122
|
let top;
|
|
123
123
|
let left;
|
|
124
124
|
if (finalPlacement === "top" || finalPlacement === "bottom") {
|
|
@@ -132,10 +132,15 @@ var FokusStyles = (() => {
|
|
|
132
132
|
const maxTop = Math.max(padding, viewportHeight - floatingRect.height - padding);
|
|
133
133
|
left = Math.min(Math.max(left, padding), maxLeft);
|
|
134
134
|
top = Math.min(Math.max(top, padding), maxTop);
|
|
135
|
+
const crossSize = finalPlacement === "top" || finalPlacement === "bottom" ? floatingRect.width : floatingRect.height;
|
|
136
|
+
const crossStart = finalPlacement === "top" || finalPlacement === "bottom" ? left : top;
|
|
137
|
+
const referenceCenter = finalPlacement === "top" || finalPlacement === "bottom" ? referenceRect.left + referenceRect.width / 2 : referenceRect.top + referenceRect.height / 2;
|
|
138
|
+
const crossOffset = Math.min(Math.max(referenceCenter - crossStart, 8), Math.max(8, crossSize - 8));
|
|
135
139
|
return {
|
|
136
140
|
top: top + window.scrollY,
|
|
137
141
|
left: left + window.scrollX,
|
|
138
|
-
placement: finalPlacement
|
|
142
|
+
placement: finalPlacement,
|
|
143
|
+
arrowOffset: `${crossOffset}px`
|
|
139
144
|
};
|
|
140
145
|
}
|
|
141
146
|
function watchPosition(referenceEl, floatingEl, options = {}) {
|
|
@@ -164,6 +169,10 @@ var FokusStyles = (() => {
|
|
|
164
169
|
floatingEl.style.position = "absolute";
|
|
165
170
|
floatingEl.style.top = `${position.top}px`;
|
|
166
171
|
floatingEl.style.left = `${position.left}px`;
|
|
172
|
+
if (position.arrowOffset) {
|
|
173
|
+
floatingEl.style.setProperty("--fs-popover-arrow-offset", position.arrowOffset);
|
|
174
|
+
floatingEl.style.setProperty("--fs-tooltip-arrow-offset", position.arrowOffset);
|
|
175
|
+
}
|
|
167
176
|
}
|
|
168
177
|
|
|
169
178
|
// packages/fokus-js/js/core/overlay.js
|
|
@@ -385,7 +394,7 @@ var FokusStyles = (() => {
|
|
|
385
394
|
|
|
386
395
|
// packages/fokus-js/js/dropdown.js
|
|
387
396
|
var instances = createInstanceRegistry();
|
|
388
|
-
var Dropdown = class {
|
|
397
|
+
var Dropdown = class _Dropdown {
|
|
389
398
|
constructor(toggleEl, options = {}) {
|
|
390
399
|
var _a, _b, _c, _d;
|
|
391
400
|
const targetSelector = toggleEl.getAttribute("data-fs-target");
|
|
@@ -428,6 +437,20 @@ var FokusStyles = (() => {
|
|
|
428
437
|
static getInstance(el) {
|
|
429
438
|
return instances.get(el);
|
|
430
439
|
}
|
|
440
|
+
static getOrCreateInstance(el, options = {}) {
|
|
441
|
+
var _a;
|
|
442
|
+
return (_a = this.getInstance(el)) != null ? _a : new _Dropdown(el, options);
|
|
443
|
+
}
|
|
444
|
+
static show(el, options = {}) {
|
|
445
|
+
return this.getOrCreateInstance(el, options).show();
|
|
446
|
+
}
|
|
447
|
+
static hide(el) {
|
|
448
|
+
var _a;
|
|
449
|
+
return (_a = this.getInstance(el)) == null ? void 0 : _a.hide();
|
|
450
|
+
}
|
|
451
|
+
static toggle(el, options = {}) {
|
|
452
|
+
return this.getOrCreateInstance(el, options).toggle();
|
|
453
|
+
}
|
|
431
454
|
_handleToggleClick(event) {
|
|
432
455
|
event.preventDefault();
|
|
433
456
|
this.toggle();
|
|
@@ -489,6 +512,7 @@ var FokusStyles = (() => {
|
|
|
489
512
|
if (this.toggleEl.contains(event.target)) return;
|
|
490
513
|
this.hide();
|
|
491
514
|
});
|
|
515
|
+
this.toggleEl.dispatchEvent(new CustomEvent("fs:shown", { bubbles: true }));
|
|
492
516
|
this.toggleEl.dispatchEvent(new CustomEvent("fs:dropdown:shown", { bubbles: true }));
|
|
493
517
|
}
|
|
494
518
|
hide() {
|
|
@@ -504,6 +528,7 @@ var FokusStyles = (() => {
|
|
|
504
528
|
this._outsideClickCleanup = null;
|
|
505
529
|
(_b = this._positionCleanup) == null ? void 0 : _b.call(this);
|
|
506
530
|
this._positionCleanup = null;
|
|
531
|
+
this.toggleEl.dispatchEvent(new CustomEvent("fs:hidden", { bubbles: true }));
|
|
507
532
|
this.toggleEl.dispatchEvent(new CustomEvent("fs:dropdown:hidden", { bubbles: true }));
|
|
508
533
|
}
|
|
509
534
|
toggle() {
|
|
@@ -530,9 +555,20 @@ var FokusStyles = (() => {
|
|
|
530
555
|
// packages/fokus-js/js/tooltip.js
|
|
531
556
|
var instances2 = createInstanceRegistry();
|
|
532
557
|
var idCounter = 0;
|
|
558
|
+
var openInstance = null;
|
|
559
|
+
var DEFAULT_TOOLTIP_OFFSET = 8;
|
|
560
|
+
function toDelay(value, fallback = 0) {
|
|
561
|
+
if (value === null || value === void 0 || value === "") return fallback;
|
|
562
|
+
const parsed = Number(value);
|
|
563
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
|
564
|
+
}
|
|
565
|
+
function parsePlacement(value = "top") {
|
|
566
|
+
const [placement, align = "center"] = value.split("-");
|
|
567
|
+
return { placement, align: ["start", "center", "end"].includes(align) ? align : "center" };
|
|
568
|
+
}
|
|
533
569
|
var Tooltip = class {
|
|
534
570
|
constructor(referenceEl, options = {}) {
|
|
535
|
-
var _a, _b, _c, _d;
|
|
571
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
536
572
|
const title = (_b = (_a = referenceEl.getAttribute("title")) != null ? _a : referenceEl.getAttribute("data-title")) != null ? _b : options.title;
|
|
537
573
|
if (!title) {
|
|
538
574
|
throw new Error("FokusStyles.Tooltip: elemento sem texto (atributo title/data-title).");
|
|
@@ -541,10 +577,18 @@ var FokusStyles = (() => {
|
|
|
541
577
|
idCounter += 1;
|
|
542
578
|
this.referenceEl = referenceEl;
|
|
543
579
|
this.title = title;
|
|
544
|
-
|
|
580
|
+
const parsedPlacement = parsePlacement((_d = (_c = options.placement) != null ? _c : referenceEl.getAttribute("data-placement")) != null ? _d : "top");
|
|
581
|
+
this.placement = parsedPlacement.placement;
|
|
582
|
+
this.align = (_f = (_e = options.align) != null ? _e : referenceEl.getAttribute("data-align")) != null ? _f : parsedPlacement.align;
|
|
583
|
+
this.offset = toDelay((_g = options.offset) != null ? _g : referenceEl.getAttribute("data-offset"), DEFAULT_TOOLTIP_OFFSET);
|
|
584
|
+
this.showDelay = toDelay((_h = options.showDelay) != null ? _h : referenceEl.getAttribute("data-show-delay"), 0);
|
|
585
|
+
this.hideDelay = toDelay((_i = options.hideDelay) != null ? _i : referenceEl.getAttribute("data-hide-delay"));
|
|
545
586
|
this.isOpen = false;
|
|
546
587
|
this.id = `fokus-tooltip-${idCounter}`;
|
|
547
588
|
this._positionCleanup = null;
|
|
589
|
+
this._showTimer = null;
|
|
590
|
+
this._hideTimer = null;
|
|
591
|
+
this._touchOpened = false;
|
|
548
592
|
this._originalDescribedBy = referenceEl.getAttribute("aria-describedby");
|
|
549
593
|
this.tooltipEl = document.createElement("div");
|
|
550
594
|
this.tooltipEl.className = "fs-tooltip";
|
|
@@ -553,13 +597,32 @@ var FokusStyles = (() => {
|
|
|
553
597
|
this.tooltipEl.innerHTML = '<div class="fs-tooltip-arrow"></div><div class="fs-tooltip-inner"></div>';
|
|
554
598
|
this.tooltipEl.querySelector(".fs-tooltip-inner").textContent = this.title;
|
|
555
599
|
document.body.appendChild(this.tooltipEl);
|
|
556
|
-
|
|
557
|
-
this._handleShow = this.
|
|
558
|
-
this._handleHide = this.
|
|
559
|
-
|
|
560
|
-
|
|
600
|
+
this._addDescribedBy();
|
|
601
|
+
this._handleShow = () => this._scheduleShow(true);
|
|
602
|
+
this._handleHide = () => this._scheduleHide();
|
|
603
|
+
this._handlePointerEnter = () => this._scheduleShow();
|
|
604
|
+
this._handlePointerLeave = () => this._scheduleHide();
|
|
605
|
+
this._handlePointerDown = (event) => {
|
|
606
|
+
if (event.pointerType === "touch") {
|
|
607
|
+
if (this._touchOpened && this.isOpen) {
|
|
608
|
+
this.hideImmediate();
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
this._touchOpened = true;
|
|
612
|
+
this._scheduleShow(true);
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
referenceEl.addEventListener("pointerenter", this._handlePointerEnter);
|
|
616
|
+
referenceEl.addEventListener("pointerleave", this._handlePointerLeave);
|
|
617
|
+
referenceEl.addEventListener("pointerdown", this._handlePointerDown);
|
|
618
|
+
referenceEl.addEventListener("mouseenter", this._handlePointerEnter);
|
|
619
|
+
referenceEl.addEventListener("mouseleave", this._handlePointerLeave);
|
|
561
620
|
referenceEl.addEventListener("focus", this._handleShow);
|
|
562
621
|
referenceEl.addEventListener("blur", this._handleHide);
|
|
622
|
+
this._handleDocumentPointerDown = (event) => {
|
|
623
|
+
if (this._touchOpened && !this.referenceEl.contains(event.target) && !this.tooltipEl.contains(event.target)) this.hide();
|
|
624
|
+
};
|
|
625
|
+
document.addEventListener("pointerdown", this._handleDocumentPointerDown, true);
|
|
563
626
|
this._removeEscapeListener = onEscapeKey(() => {
|
|
564
627
|
if (this.isOpen) this.hide();
|
|
565
628
|
});
|
|
@@ -568,9 +631,44 @@ var FokusStyles = (() => {
|
|
|
568
631
|
static getInstance(el) {
|
|
569
632
|
return instances2.get(el);
|
|
570
633
|
}
|
|
634
|
+
_clearTimers() {
|
|
635
|
+
clearTimeout(this._showTimer);
|
|
636
|
+
clearTimeout(this._hideTimer);
|
|
637
|
+
this._showTimer = null;
|
|
638
|
+
this._hideTimer = null;
|
|
639
|
+
}
|
|
640
|
+
_addDescribedBy() {
|
|
641
|
+
var _a;
|
|
642
|
+
const ids = new Set(((_a = this.referenceEl.getAttribute("aria-describedby")) != null ? _a : "").split(/\s+/).filter(Boolean));
|
|
643
|
+
ids.add(this.id);
|
|
644
|
+
this.referenceEl.setAttribute("aria-describedby", [...ids].join(" "));
|
|
645
|
+
}
|
|
646
|
+
_scheduleShow(immediate = false) {
|
|
647
|
+
this._clearTimers();
|
|
648
|
+
if (this.isOpen) return;
|
|
649
|
+
const delay = immediate ? 0 : this.showDelay;
|
|
650
|
+
if (delay === 0) {
|
|
651
|
+
this.show();
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
this._showTimer = setTimeout(() => this.show(), delay);
|
|
655
|
+
}
|
|
656
|
+
_scheduleHide(immediate = false) {
|
|
657
|
+
this._clearTimers();
|
|
658
|
+
if (!this.isOpen) return;
|
|
659
|
+
const delay = immediate ? 0 : this.hideDelay;
|
|
660
|
+
if (delay === 0) {
|
|
661
|
+
this.hide();
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
this._hideTimer = setTimeout(() => this.hide(), delay);
|
|
665
|
+
}
|
|
571
666
|
show() {
|
|
572
667
|
var _a;
|
|
668
|
+
this._clearTimers();
|
|
573
669
|
if (this.isOpen) return;
|
|
670
|
+
if (openInstance && openInstance !== this) openInstance.hide(true);
|
|
671
|
+
openInstance = this;
|
|
574
672
|
this.isOpen = true;
|
|
575
673
|
const theme = (_a = this.referenceEl.closest("[data-theme]")) == null ? void 0 : _a.getAttribute("data-theme");
|
|
576
674
|
if (theme) {
|
|
@@ -579,23 +677,31 @@ var FokusStyles = (() => {
|
|
|
579
677
|
this.tooltipEl.removeAttribute("data-theme");
|
|
580
678
|
}
|
|
581
679
|
this.tooltipEl.classList.add("is-open");
|
|
582
|
-
const position = computePosition(this.referenceEl, this.tooltipEl, { placement: this.placement, offset:
|
|
680
|
+
const position = computePosition(this.referenceEl, this.tooltipEl, { placement: this.placement, align: this.align, offset: this.offset });
|
|
583
681
|
applyPosition(this.tooltipEl, position);
|
|
584
682
|
this._positionCleanup = watchPosition(this.referenceEl, this.tooltipEl, {
|
|
585
683
|
placement: this.placement,
|
|
586
|
-
|
|
684
|
+
align: this.align,
|
|
685
|
+
offset: this.offset
|
|
587
686
|
});
|
|
588
687
|
this.tooltipEl.setAttribute("data-placement", position.placement);
|
|
688
|
+
this.tooltipEl.setAttribute("data-align", this.align);
|
|
589
689
|
this.referenceEl.dispatchEvent(new CustomEvent("fs:tooltip:shown", { bubbles: true }));
|
|
590
690
|
}
|
|
591
691
|
hide() {
|
|
692
|
+
this.hideImmediate();
|
|
693
|
+
}
|
|
694
|
+
hideImmediate() {
|
|
592
695
|
var _a;
|
|
696
|
+
this._clearTimers();
|
|
593
697
|
if (!this.isOpen) return;
|
|
594
698
|
this.isOpen = false;
|
|
699
|
+
this._touchOpened = false;
|
|
595
700
|
this.tooltipEl.classList.remove("is-open");
|
|
596
701
|
(_a = this._positionCleanup) == null ? void 0 : _a.call(this);
|
|
597
702
|
this._positionCleanup = null;
|
|
598
703
|
this.referenceEl.dispatchEvent(new CustomEvent("fs:tooltip:hidden", { bubbles: true }));
|
|
704
|
+
if (openInstance === this) openInstance = null;
|
|
599
705
|
}
|
|
600
706
|
toggle() {
|
|
601
707
|
if (this.isOpen) {
|
|
@@ -605,11 +711,16 @@ var FokusStyles = (() => {
|
|
|
605
711
|
}
|
|
606
712
|
}
|
|
607
713
|
dispose() {
|
|
608
|
-
this.
|
|
609
|
-
this.
|
|
610
|
-
this.referenceEl.removeEventListener("
|
|
714
|
+
this.hideImmediate();
|
|
715
|
+
this._clearTimers();
|
|
716
|
+
this.referenceEl.removeEventListener("pointerenter", this._handlePointerEnter);
|
|
717
|
+
this.referenceEl.removeEventListener("pointerleave", this._handlePointerLeave);
|
|
718
|
+
this.referenceEl.removeEventListener("pointerdown", this._handlePointerDown);
|
|
719
|
+
this.referenceEl.removeEventListener("mouseenter", this._handlePointerEnter);
|
|
720
|
+
this.referenceEl.removeEventListener("mouseleave", this._handlePointerLeave);
|
|
611
721
|
this.referenceEl.removeEventListener("focus", this._handleShow);
|
|
612
722
|
this.referenceEl.removeEventListener("blur", this._handleHide);
|
|
723
|
+
document.removeEventListener("pointerdown", this._handleDocumentPointerDown, true);
|
|
613
724
|
this._removeEscapeListener();
|
|
614
725
|
if (this._originalDescribedBy === null) this.referenceEl.removeAttribute("aria-describedby");
|
|
615
726
|
else this.referenceEl.setAttribute("aria-describedby", this._originalDescribedBy);
|
|
@@ -623,6 +734,7 @@ var FokusStyles = (() => {
|
|
|
623
734
|
var instances3 = createInstanceRegistry();
|
|
624
735
|
var idCounter2 = 0;
|
|
625
736
|
var HOVER_HIDE_DELAY = 100;
|
|
737
|
+
var openPopovers = /* @__PURE__ */ new Set();
|
|
626
738
|
var Popover = class {
|
|
627
739
|
constructor(triggerEl, options = {}) {
|
|
628
740
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -640,6 +752,7 @@ var FokusStyles = (() => {
|
|
|
640
752
|
this._outsideClickCleanup = null;
|
|
641
753
|
this._removeEscapeListener = null;
|
|
642
754
|
this._hideTimer = null;
|
|
755
|
+
this._suppressNextFocus = false;
|
|
643
756
|
this._positionCleanup = null;
|
|
644
757
|
this._originalParent = popoverEl.parentNode;
|
|
645
758
|
this._originalNextSibling = popoverEl.nextSibling;
|
|
@@ -653,6 +766,11 @@ var FokusStyles = (() => {
|
|
|
653
766
|
if (!headerEl.id) headerEl.id = `fokus-popover-header-${idCounter2}`;
|
|
654
767
|
popoverEl.setAttribute("aria-labelledby", headerEl.id);
|
|
655
768
|
}
|
|
769
|
+
const descriptionEl = popoverEl.querySelector(".fs-popover-text");
|
|
770
|
+
if (descriptionEl) {
|
|
771
|
+
if (!descriptionEl.id) descriptionEl.id = `fokus-popover-text-${idCounter2}`;
|
|
772
|
+
popoverEl.setAttribute("aria-describedby", descriptionEl.id);
|
|
773
|
+
}
|
|
656
774
|
triggerEl.setAttribute("aria-controls", popoverEl.id);
|
|
657
775
|
triggerEl.setAttribute("aria-expanded", "false");
|
|
658
776
|
this._handleDismissClick = this._handleDismissClick.bind(this);
|
|
@@ -684,7 +802,13 @@ var FokusStyles = (() => {
|
|
|
684
802
|
this.popoverEl.addEventListener("mouseenter", this._handleMouseEnter);
|
|
685
803
|
this.popoverEl.addEventListener("mouseleave", this._handleMouseLeave);
|
|
686
804
|
} else if (this.trigger === "focus") {
|
|
687
|
-
this._handleTriggerFocus = () =>
|
|
805
|
+
this._handleTriggerFocus = () => {
|
|
806
|
+
if (this._suppressNextFocus) {
|
|
807
|
+
this._suppressNextFocus = false;
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
this.show();
|
|
811
|
+
};
|
|
688
812
|
this._handleTriggerFocusOut = (event) => {
|
|
689
813
|
if (this.popoverEl.contains(event.relatedTarget)) return;
|
|
690
814
|
this.hide();
|
|
@@ -707,7 +831,12 @@ var FokusStyles = (() => {
|
|
|
707
831
|
}
|
|
708
832
|
_handleDismissClick(event) {
|
|
709
833
|
if (event.target.closest('[data-fs-dismiss="popover"]')) {
|
|
834
|
+
const restoreFocus = this.popoverEl.contains(document.activeElement);
|
|
835
|
+
if (restoreFocus && this.trigger === "focus") this._suppressNextFocus = true;
|
|
710
836
|
this.hide();
|
|
837
|
+
if (restoreFocus && typeof this.triggerEl.focus === "function") {
|
|
838
|
+
this.triggerEl.focus();
|
|
839
|
+
}
|
|
711
840
|
}
|
|
712
841
|
}
|
|
713
842
|
show() {
|
|
@@ -721,6 +850,9 @@ var FokusStyles = (() => {
|
|
|
721
850
|
this.popoverEl.removeAttribute("data-theme");
|
|
722
851
|
}
|
|
723
852
|
this.popoverEl.classList.add("is-open");
|
|
853
|
+
openPopovers.forEach((popover) => {
|
|
854
|
+
if (popover !== this) popover.hide();
|
|
855
|
+
});
|
|
724
856
|
const position = computePosition(this.triggerEl, this.popoverEl, {
|
|
725
857
|
placement: this.placement,
|
|
726
858
|
align: this.align,
|
|
@@ -733,6 +865,7 @@ var FokusStyles = (() => {
|
|
|
733
865
|
offset: 10
|
|
734
866
|
});
|
|
735
867
|
this.popoverEl.setAttribute("data-placement", position.placement);
|
|
868
|
+
openPopovers.add(this);
|
|
736
869
|
this.triggerEl.setAttribute("aria-expanded", "true");
|
|
737
870
|
if (this.trigger === "click") {
|
|
738
871
|
this._outsideClickCleanup = onClickOutside(this.popoverEl, (event) => {
|
|
@@ -746,6 +879,7 @@ var FokusStyles = (() => {
|
|
|
746
879
|
var _a, _b;
|
|
747
880
|
if (!this.isOpen) return;
|
|
748
881
|
this.isOpen = false;
|
|
882
|
+
openPopovers.delete(this);
|
|
749
883
|
this.popoverEl.classList.remove("is-open");
|
|
750
884
|
(_a = this._positionCleanup) == null ? void 0 : _a.call(this);
|
|
751
885
|
this._positionCleanup = null;
|
|
@@ -975,12 +1109,25 @@ var FokusStyles = (() => {
|
|
|
975
1109
|
// fs:stepper:beforechange): preventDefault() bloqueia a remoção.
|
|
976
1110
|
dismiss() {
|
|
977
1111
|
if (this._isLoading) return false;
|
|
1112
|
+
const dismissButton = this.tagEl.querySelector('[data-fs-dismiss="tag"]');
|
|
1113
|
+
const shouldRestoreFocus = dismissButton && document.activeElement === dismissButton;
|
|
978
1114
|
const event = new CustomEvent("fs:tag:dismissed", { bubbles: true, cancelable: true });
|
|
979
1115
|
this.tagEl.dispatchEvent(event);
|
|
980
1116
|
if (event.defaultPrevented) return false;
|
|
1117
|
+
const focusTarget = shouldRestoreFocus ? this._getFocusTarget() : null;
|
|
981
1118
|
this.tagEl.remove();
|
|
1119
|
+
focusTarget == null ? void 0 : focusTarget.focus();
|
|
982
1120
|
return true;
|
|
983
1121
|
}
|
|
1122
|
+
_getFocusTarget() {
|
|
1123
|
+
const group = this.tagEl.closest(".fs-tag-group");
|
|
1124
|
+
if (!group) return null;
|
|
1125
|
+
const buttons = [...group.querySelectorAll('[data-fs-dismiss="tag"]')].filter((button) => !button.disabled && !button.hidden && button.getAttribute("aria-hidden") !== "true");
|
|
1126
|
+
const currentButton = this.tagEl.querySelector('[data-fs-dismiss="tag"]');
|
|
1127
|
+
const currentIndex = buttons.indexOf(currentButton);
|
|
1128
|
+
const remaining = buttons.filter((button) => button !== currentButton);
|
|
1129
|
+
return remaining[currentIndex] || remaining[currentIndex - 1] || null;
|
|
1130
|
+
}
|
|
984
1131
|
// Estado útil enquanto uma remoção ou atualização assíncrona está pendente.
|
|
985
1132
|
// Além da aparência, bloqueia o dismiss e comunica o estado a AT.
|
|
986
1133
|
setLoading(loading) {
|
|
@@ -1422,7 +1569,7 @@ var FokusStyles = (() => {
|
|
|
1422
1569
|
// packages/fokus-js/js/tabs.js
|
|
1423
1570
|
var instances11 = createInstanceRegistry();
|
|
1424
1571
|
var idCounter6 = 0;
|
|
1425
|
-
var Tabs = class {
|
|
1572
|
+
var Tabs = class _Tabs {
|
|
1426
1573
|
constructor(tablistEl) {
|
|
1427
1574
|
this.tablistEl = tablistEl;
|
|
1428
1575
|
this.tabs = Array.from(tablistEl.querySelectorAll(".fs-nav-link"));
|
|
@@ -1453,6 +1600,17 @@ var FokusStyles = (() => {
|
|
|
1453
1600
|
static getInstance(el) {
|
|
1454
1601
|
return instances11.get(el);
|
|
1455
1602
|
}
|
|
1603
|
+
static getOrCreateInstance(el) {
|
|
1604
|
+
var _a;
|
|
1605
|
+
return (_a = this.getInstance(el)) != null ? _a : new _Tabs(el);
|
|
1606
|
+
}
|
|
1607
|
+
static show(el, tab) {
|
|
1608
|
+
return this.getOrCreateInstance(el).show(tab);
|
|
1609
|
+
}
|
|
1610
|
+
static dispose(el) {
|
|
1611
|
+
var _a;
|
|
1612
|
+
return (_a = this.getInstance(el)) == null ? void 0 : _a.dispose();
|
|
1613
|
+
}
|
|
1456
1614
|
_handleClick(event) {
|
|
1457
1615
|
const tab = event.target.closest(".fs-nav-link:not(.is-disabled)");
|
|
1458
1616
|
if (!tab || !this.tabs.includes(tab)) return;
|
|
@@ -1485,6 +1643,7 @@ var FokusStyles = (() => {
|
|
|
1485
1643
|
pane == null ? void 0 : pane.classList.toggle("is-active", isActive);
|
|
1486
1644
|
if (pane) pane.hidden = !isActive;
|
|
1487
1645
|
});
|
|
1646
|
+
tab.dispatchEvent(new CustomEvent("fs:shown", { bubbles: true }));
|
|
1488
1647
|
tab.dispatchEvent(
|
|
1489
1648
|
new CustomEvent("fs:tab:changed", { bubbles: true, detail: { target: tab.getAttribute("data-fs-target") } })
|
|
1490
1649
|
);
|
|
@@ -1506,11 +1665,37 @@ var FokusStyles = (() => {
|
|
|
1506
1665
|
this.autohide = toastEl.getAttribute("data-autohide") !== "false";
|
|
1507
1666
|
this.isOpen = false;
|
|
1508
1667
|
this._hideTimer = null;
|
|
1668
|
+
this._paused = false;
|
|
1669
|
+
this._remaining = this.delay;
|
|
1670
|
+
this._startedAt = 0;
|
|
1671
|
+
this._progressTimer = null;
|
|
1509
1672
|
toastEl.setAttribute("role", "status");
|
|
1510
1673
|
toastEl.setAttribute("aria-live", "polite");
|
|
1511
1674
|
toastEl.style.display = "none";
|
|
1512
1675
|
this._handleDismissClick = this._handleDismissClick.bind(this);
|
|
1676
|
+
this._pause = () => {
|
|
1677
|
+
if (!this.isOpen || this._paused) return;
|
|
1678
|
+
this._paused = true;
|
|
1679
|
+
clearTimeout(this._hideTimer);
|
|
1680
|
+
if (this.autohide && this._startedAt) {
|
|
1681
|
+
this._remaining = Math.max(0, this._remaining - (Date.now() - this._startedAt));
|
|
1682
|
+
}
|
|
1683
|
+
this._updateProgress();
|
|
1684
|
+
clearInterval(this._progressTimer);
|
|
1685
|
+
this.toastEl.classList.add("is-paused");
|
|
1686
|
+
};
|
|
1687
|
+
this._resume = () => {
|
|
1688
|
+
if (!this.isOpen || !this._paused) return;
|
|
1689
|
+
this._paused = false;
|
|
1690
|
+
this.toastEl.classList.remove("is-paused");
|
|
1691
|
+
this._startProgress();
|
|
1692
|
+
if (this.autohide) this._scheduleHide();
|
|
1693
|
+
};
|
|
1513
1694
|
toastEl.addEventListener("click", this._handleDismissClick);
|
|
1695
|
+
toastEl.addEventListener("mouseenter", this._pause);
|
|
1696
|
+
toastEl.addEventListener("mouseleave", this._resume);
|
|
1697
|
+
toastEl.addEventListener("focusin", this._pause);
|
|
1698
|
+
toastEl.addEventListener("focusout", this._resume);
|
|
1514
1699
|
instances12.set(toastEl, this);
|
|
1515
1700
|
}
|
|
1516
1701
|
static getInstance(el) {
|
|
@@ -1525,20 +1710,59 @@ var FokusStyles = (() => {
|
|
|
1525
1710
|
if (this.isOpen) return;
|
|
1526
1711
|
this.toastEl.dispatchEvent(new CustomEvent("fs:show", { bubbles: true }));
|
|
1527
1712
|
this.isOpen = true;
|
|
1528
|
-
|
|
1713
|
+
this._remaining = this.delay;
|
|
1714
|
+
this._startedAt = Date.now();
|
|
1715
|
+
this.toastEl.style.setProperty("--fs-toast-duration", `${this.delay}ms`);
|
|
1716
|
+
const expansion = expand(this.toastEl);
|
|
1717
|
+
this.toastEl.classList.remove("is-progressing");
|
|
1718
|
+
void this.toastEl.offsetWidth;
|
|
1719
|
+
if (this.toastEl.getAttribute("data-toast-progress") === "true" && this.autohide) {
|
|
1720
|
+
this.toastEl.classList.add("is-progressing");
|
|
1721
|
+
this._startProgress();
|
|
1722
|
+
}
|
|
1723
|
+
expansion.then(() => {
|
|
1529
1724
|
this.toastEl.dispatchEvent(new CustomEvent("fs:shown", { bubbles: true }));
|
|
1530
1725
|
this.toastEl.dispatchEvent(new CustomEvent("fs:toast:shown", { bubbles: true }));
|
|
1531
1726
|
});
|
|
1532
|
-
|
|
1533
|
-
|
|
1727
|
+
this._scheduleHide();
|
|
1728
|
+
}
|
|
1729
|
+
_scheduleHide() {
|
|
1730
|
+
clearTimeout(this._hideTimer);
|
|
1731
|
+
if (this.autohide && !this._paused) {
|
|
1732
|
+
this._startedAt = Date.now();
|
|
1733
|
+
this._hideTimer = setTimeout(() => this.hide(), this._remaining);
|
|
1534
1734
|
}
|
|
1535
1735
|
}
|
|
1736
|
+
_updateProgress() {
|
|
1737
|
+
if (this.toastEl.getAttribute("data-toast-progress") !== "true" || !this.autohide) return;
|
|
1738
|
+
const percentage = Math.max(0, Math.min(100, this._remaining / this.delay * 100));
|
|
1739
|
+
const progressEl = this.toastEl.querySelector(".fs-toast-progress");
|
|
1740
|
+
if (progressEl) progressEl.style.inlineSize = `${percentage}%`;
|
|
1741
|
+
}
|
|
1742
|
+
_startProgress() {
|
|
1743
|
+
if (this.toastEl.getAttribute("data-toast-progress") !== "true" || !this.autohide) return;
|
|
1744
|
+
clearInterval(this._progressTimer);
|
|
1745
|
+
this._updateProgress();
|
|
1746
|
+
this._progressTimer = setInterval(() => {
|
|
1747
|
+
if (!this.isOpen || this._paused) return;
|
|
1748
|
+
this._remaining = Math.max(0, this.delay - (Date.now() - this._startedAt));
|
|
1749
|
+
this._updateProgress();
|
|
1750
|
+
}, 50);
|
|
1751
|
+
}
|
|
1536
1752
|
hide() {
|
|
1537
1753
|
if (!this.isOpen) return;
|
|
1538
1754
|
this.toastEl.dispatchEvent(new CustomEvent("fs:hide", { bubbles: true }));
|
|
1539
1755
|
this.isOpen = false;
|
|
1540
1756
|
clearTimeout(this._hideTimer);
|
|
1541
1757
|
this._hideTimer = null;
|
|
1758
|
+
clearInterval(this._progressTimer);
|
|
1759
|
+
this._progressTimer = null;
|
|
1760
|
+
this._startedAt = 0;
|
|
1761
|
+
this._remaining = this.delay;
|
|
1762
|
+
this.toastEl.classList.remove("is-paused");
|
|
1763
|
+
this.toastEl.classList.remove("is-progressing");
|
|
1764
|
+
const progressEl = this.toastEl.querySelector(".fs-toast-progress");
|
|
1765
|
+
if (progressEl) progressEl.style.removeProperty("inline-size");
|
|
1542
1766
|
collapse(this.toastEl).then(() => {
|
|
1543
1767
|
this.toastEl.dispatchEvent(new CustomEvent("fs:hidden", { bubbles: true }));
|
|
1544
1768
|
this.toastEl.dispatchEvent(new CustomEvent("fs:toast:hidden", { bubbles: true }));
|
|
@@ -1553,7 +1777,12 @@ var FokusStyles = (() => {
|
|
|
1553
1777
|
}
|
|
1554
1778
|
dispose() {
|
|
1555
1779
|
clearTimeout(this._hideTimer);
|
|
1780
|
+
clearInterval(this._progressTimer);
|
|
1556
1781
|
this.toastEl.removeEventListener("click", this._handleDismissClick);
|
|
1782
|
+
this.toastEl.removeEventListener("mouseenter", this._pause);
|
|
1783
|
+
this.toastEl.removeEventListener("mouseleave", this._resume);
|
|
1784
|
+
this.toastEl.removeEventListener("focusin", this._pause);
|
|
1785
|
+
this.toastEl.removeEventListener("focusout", this._resume);
|
|
1557
1786
|
instances12.delete(this.toastEl);
|
|
1558
1787
|
}
|
|
1559
1788
|
};
|
|
@@ -1562,7 +1791,7 @@ var FokusStyles = (() => {
|
|
|
1562
1791
|
// packages/fokus-js/js/carousel.js
|
|
1563
1792
|
var instances13 = createInstanceRegistry();
|
|
1564
1793
|
var interactiveSelector = "a, button, input, select, textarea, label, [contenteditable='true']";
|
|
1565
|
-
var Carousel = class {
|
|
1794
|
+
var Carousel = class _Carousel {
|
|
1566
1795
|
constructor(carouselEl) {
|
|
1567
1796
|
var _a, _b, _c;
|
|
1568
1797
|
this.carouselEl = carouselEl;
|
|
@@ -1643,6 +1872,19 @@ var FokusStyles = (() => {
|
|
|
1643
1872
|
static getInstance(el) {
|
|
1644
1873
|
return instances13.get(el);
|
|
1645
1874
|
}
|
|
1875
|
+
static getOrCreateInstance(el) {
|
|
1876
|
+
var _a;
|
|
1877
|
+
return (_a = this.getInstance(el)) != null ? _a : new _Carousel(el);
|
|
1878
|
+
}
|
|
1879
|
+
static next(el) {
|
|
1880
|
+
return this.getOrCreateInstance(el).next();
|
|
1881
|
+
}
|
|
1882
|
+
static prev(el) {
|
|
1883
|
+
return this.getOrCreateInstance(el).prev();
|
|
1884
|
+
}
|
|
1885
|
+
static goTo(el, index) {
|
|
1886
|
+
return this.getOrCreateInstance(el).goTo(index);
|
|
1887
|
+
}
|
|
1646
1888
|
_isDocumentVisible() {
|
|
1647
1889
|
return document.visibilityState !== "hidden";
|
|
1648
1890
|
}
|
|
@@ -1707,6 +1949,9 @@ var FokusStyles = (() => {
|
|
|
1707
1949
|
if (to === from) return;
|
|
1708
1950
|
this.index = to;
|
|
1709
1951
|
this._render();
|
|
1952
|
+
this.carouselEl.dispatchEvent(
|
|
1953
|
+
new CustomEvent("fs:shown", { bubbles: true, detail: { from, to } })
|
|
1954
|
+
);
|
|
1710
1955
|
this.carouselEl.dispatchEvent(
|
|
1711
1956
|
new CustomEvent("fs:carousel:slid", { bubbles: true, detail: { from, to } })
|
|
1712
1957
|
);
|