@aurodesignsystem-dev/auro-formkit 0.0.0-pr1488.2 → 0.0.0-pr1489.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/components/bibtemplate/dist/auro-bibtemplate.d.ts +7 -0
- package/components/bibtemplate/dist/index.js +9 -1
- package/components/bibtemplate/dist/registered.js +9 -1
- package/components/checkbox/demo/customize.min.js +1 -1
- package/components/checkbox/demo/getting-started.min.js +1 -1
- package/components/checkbox/demo/index.min.js +1 -1
- package/components/checkbox/demo/pages.json +1 -1
- package/components/checkbox/demo/why-checkbox.html +57 -0
- package/components/checkbox/demo/why-checkbox.md +86 -0
- package/components/checkbox/dist/index.js +1 -1
- package/components/checkbox/dist/registered.js +1 -1
- package/components/combobox/demo/customize.min.js +234 -16
- package/components/combobox/demo/getting-started.min.js +234 -16
- package/components/combobox/demo/index.min.js +234 -16
- package/components/combobox/demo/pages.json +1 -1
- package/components/combobox/demo/why-combobox.html +57 -0
- package/components/combobox/demo/why-combobox.md +113 -0
- package/components/combobox/dist/index.js +234 -16
- package/components/combobox/dist/registered.js +234 -16
- package/components/counter/demo/customize.min.js +233 -15
- package/components/counter/demo/index.min.js +233 -15
- package/components/counter/demo/keyboard-behavior.md +1 -0
- package/components/counter/demo/pages.json +1 -1
- package/components/counter/demo/why-counter.html +57 -0
- package/components/counter/demo/why-counter.md +108 -0
- package/components/counter/dist/index.js +10 -2
- package/components/counter/dist/registered.js +10 -2
- package/components/datepicker/demo/accessibility.md +51 -3
- package/components/datepicker/demo/api.md +11 -2
- package/components/datepicker/demo/customize.html +2 -0
- package/components/datepicker/demo/customize.js +19 -0
- package/components/datepicker/demo/customize.md +72 -8
- package/components/datepicker/demo/customize.min.js +26029 -0
- package/components/datepicker/demo/design.md +3 -1
- package/components/datepicker/demo/index.js +5 -1
- package/components/datepicker/demo/index.md +83 -2
- package/components/datepicker/demo/index.min.js +1564 -96
- package/components/datepicker/demo/keyboard-behavior.md +201 -2
- package/components/datepicker/demo/pages.json +1 -1
- package/components/datepicker/demo/voiceover.md +19 -12
- package/components/datepicker/demo/why-datepicker.html +57 -0
- package/components/datepicker/demo/why-datepicker.md +133 -0
- package/components/datepicker/dist/index.js +1489 -97
- package/components/datepicker/dist/registered.js +1489 -97
- package/components/datepicker/dist/src/auro-calendar-cell.d.ts +66 -1
- package/components/datepicker/dist/src/auro-calendar-month.d.ts +28 -0
- package/components/datepicker/dist/src/auro-calendar.d.ts +100 -0
- package/components/datepicker/dist/src/auro-datepicker.d.ts +88 -0
- package/components/datepicker/dist/src/datepickerKeyboardStrategy.d.ts +5 -3
- package/components/dropdown/demo/accessibility.md +11 -0
- package/components/dropdown/demo/api.md +1 -0
- package/components/dropdown/demo/customize.md +3 -0
- package/components/dropdown/demo/customize.min.js +223 -13
- package/components/dropdown/demo/getting-started.min.js +223 -13
- package/components/dropdown/demo/index.min.js +223 -13
- package/components/dropdown/demo/keyboard-behavior.md +1 -0
- package/components/dropdown/demo/pages.json +1 -1
- package/components/dropdown/demo/why-dropdown.html +57 -0
- package/components/dropdown/demo/why-dropdown.md +97 -0
- package/components/dropdown/dist/auro-dropdown.d.ts +33 -1
- package/components/dropdown/dist/index.js +223 -13
- package/components/dropdown/dist/registered.js +223 -13
- package/components/form/demo/customize.min.js +2191 -145
- package/components/form/demo/getting-started.min.js +2191 -145
- package/components/form/demo/index.min.js +2191 -145
- package/components/form/demo/pages.json +1 -1
- package/components/form/demo/registerDemoDeps.min.js +2191 -145
- package/components/form/demo/why-form.html +57 -0
- package/components/form/demo/why-form.md +101 -0
- package/components/input/demo/customize.min.js +1 -1
- package/components/input/demo/getting-started.min.js +1 -1
- package/components/input/demo/index.min.js +1 -1
- package/components/input/demo/pages.json +1 -1
- package/components/input/demo/why-input.html +57 -0
- package/components/input/demo/why-input.md +121 -0
- package/components/input/dist/index.js +1 -1
- package/components/input/dist/registered.js +1 -1
- package/components/menu/demo/pages.json +1 -1
- package/components/menu/demo/why-menu.html +57 -0
- package/components/menu/demo/why-menu.md +104 -0
- package/components/radio/demo/customize.min.js +2186 -0
- package/components/radio/demo/demo-support.min.js +55807 -0
- package/components/radio/demo/getting-started.js +1 -1
- package/components/radio/demo/getting-started.md +1 -1
- package/components/radio/demo/getting-started.min.js +2205 -0
- package/components/radio/demo/index.min.js +1 -1
- package/components/radio/demo/pages.json +1 -1
- package/components/radio/demo/why-radio.html +57 -0
- package/components/radio/demo/why-radio.md +92 -0
- package/components/radio/dist/index.js +1 -1
- package/components/radio/dist/registered.js +1 -1
- package/components/select/demo/customize.min.js +233 -15
- package/components/select/demo/getting-started.min.js +233 -15
- package/components/select/demo/index.min.js +233 -15
- package/components/select/demo/keyboard-behavior.md +1 -0
- package/components/select/demo/pages.json +1 -1
- package/components/select/demo/why-select.html +57 -0
- package/components/select/demo/why-select.md +128 -0
- package/components/select/dist/index.js +233 -15
- package/components/select/dist/registered.js +233 -15
- package/custom-elements.json +745 -28
- package/package.json +2 -2
|
@@ -3311,7 +3311,7 @@ function applyKeyboardStrategy(component, strategy, options = {}) {
|
|
|
3311
3311
|
});
|
|
3312
3312
|
}
|
|
3313
3313
|
|
|
3314
|
-
var styleCss$2 = i$2`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
|
|
3314
|
+
var styleCss$2 = i$2`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host([desktopmodal]:popover-open)::backdrop{background:transparent}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
|
|
3315
3315
|
|
|
3316
3316
|
var colorCss$2 = i$2`.container{background-color:var(--ds-auro-dropdownbib-container-color);box-shadow:var(--ds-auro-dropdownbib-boxshadow-color);color:var(--ds-auro-dropdownbib-text-color)}`;
|
|
3317
3317
|
|
|
@@ -3942,7 +3942,7 @@ class AuroHelpText extends i {
|
|
|
3942
3942
|
}
|
|
3943
3943
|
}
|
|
3944
3944
|
|
|
3945
|
-
var formkitVersion = '
|
|
3945
|
+
var formkitVersion = '202606011856';
|
|
3946
3946
|
|
|
3947
3947
|
class AuroElement extends i {
|
|
3948
3948
|
static get properties() {
|
|
@@ -4122,6 +4122,7 @@ class AuroDropdown extends AuroElement {
|
|
|
4122
4122
|
_intializeDefaults() {
|
|
4123
4123
|
this.appearance = 'default';
|
|
4124
4124
|
this.chevron = false;
|
|
4125
|
+
this.desktopModal = false;
|
|
4125
4126
|
this.disabled = false;
|
|
4126
4127
|
this.disableKeyboardHandling = false;
|
|
4127
4128
|
this.error = false;
|
|
@@ -4302,6 +4303,14 @@ class AuroDropdown extends AuroElement {
|
|
|
4302
4303
|
reflect: true
|
|
4303
4304
|
},
|
|
4304
4305
|
|
|
4306
|
+
/**
|
|
4307
|
+
* If declared, the dropdown will behave as a modal dialog when in a desktop viewport size.
|
|
4308
|
+
*/
|
|
4309
|
+
desktopModal: {
|
|
4310
|
+
type: Boolean,
|
|
4311
|
+
reflect: true
|
|
4312
|
+
},
|
|
4313
|
+
|
|
4305
4314
|
/**
|
|
4306
4315
|
* If declared, the dropdown will only show by calling the API .show() public method.
|
|
4307
4316
|
*/
|
|
@@ -4589,6 +4598,15 @@ class AuroDropdown extends AuroElement {
|
|
|
4589
4598
|
|
|
4590
4599
|
disconnectedCallback() {
|
|
4591
4600
|
super.disconnectedCallback();
|
|
4601
|
+
this._clearPageInert();
|
|
4602
|
+
if (this._bibTabHandler) {
|
|
4603
|
+
this.removeEventListener('keydown', this._bibTabHandler);
|
|
4604
|
+
this._bibTabHandler = undefined;
|
|
4605
|
+
}
|
|
4606
|
+
if (this.focusTrap) {
|
|
4607
|
+
this.focusTrap.disconnect();
|
|
4608
|
+
this.focusTrap = undefined;
|
|
4609
|
+
}
|
|
4592
4610
|
if (this.floater) {
|
|
4593
4611
|
this.floater.hideBib('disconnect');
|
|
4594
4612
|
this.floater.disconnect();
|
|
@@ -4616,19 +4634,45 @@ class AuroDropdown extends AuroElement {
|
|
|
4616
4634
|
if (this.isPopoverVisible) {
|
|
4617
4635
|
// Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
|
|
4618
4636
|
// Desktop: use show() for Floating UI positioning + FocusTrap for focus management
|
|
4619
|
-
|
|
4620
|
-
this.
|
|
4637
|
+
this.bibElement.value.open(this.isBibFullscreen);
|
|
4638
|
+
this.updateFocusTrap();
|
|
4639
|
+
|
|
4640
|
+
// Desktop modal: make siblings inert so content outside is not interactive
|
|
4641
|
+
if (this.desktopModal && !this.isBibFullscreen) {
|
|
4642
|
+
this._setPageInert();
|
|
4643
|
+
}
|
|
4621
4644
|
} else {
|
|
4622
4645
|
this.bibElement.value.close();
|
|
4646
|
+
this._clearPageInert();
|
|
4623
4647
|
}
|
|
4624
4648
|
}
|
|
4625
4649
|
|
|
4626
4650
|
// When fullscreen strategy changes while open, re-open dialog with correct mode
|
|
4627
4651
|
// (e.g. resizing from desktop → mobile while dropdown is open)
|
|
4628
4652
|
if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
|
|
4629
|
-
const useModal = this.isBibFullscreen;
|
|
4630
4653
|
this.bibElement.value.close();
|
|
4631
|
-
this.bibElement.value.open(
|
|
4654
|
+
this.bibElement.value.open(this.isBibFullscreen);
|
|
4655
|
+
|
|
4656
|
+
// Re-initialize focus management for the new strategy
|
|
4657
|
+
this.updateFocusTrap();
|
|
4658
|
+
|
|
4659
|
+
// Toggle inert: desktop modal needs it, fullscreen showModal() handles it natively
|
|
4660
|
+
if (this.desktopModal && !this.isBibFullscreen) {
|
|
4661
|
+
this._setPageInert();
|
|
4662
|
+
} else {
|
|
4663
|
+
this._clearPageInert();
|
|
4664
|
+
}
|
|
4665
|
+
}
|
|
4666
|
+
|
|
4667
|
+
// Handle desktopModal toggled while the dropdown is already open.
|
|
4668
|
+
// Re-initialize focus trapping and page inert state to match the new mode.
|
|
4669
|
+
if (changedProperties.has('desktopModal') && this.isPopoverVisible && !this.isBibFullscreen) {
|
|
4670
|
+
this.updateFocusTrap();
|
|
4671
|
+
if (this.desktopModal) {
|
|
4672
|
+
this._setPageInert();
|
|
4673
|
+
} else {
|
|
4674
|
+
this._clearPageInert();
|
|
4675
|
+
}
|
|
4632
4676
|
}
|
|
4633
4677
|
}
|
|
4634
4678
|
|
|
@@ -4638,8 +4682,14 @@ class AuroDropdown extends AuroElement {
|
|
|
4638
4682
|
* @param {CustomEvent} event - The custom event that contains the dropdown toggle information.
|
|
4639
4683
|
*/
|
|
4640
4684
|
handleDropdownToggle(event) {
|
|
4641
|
-
this.updateFocusTrap();
|
|
4642
4685
|
this.isPopoverVisible = event.detail.expanded;
|
|
4686
|
+
|
|
4687
|
+
// Tear down FocusTrap when closing. Creation happens in updated()
|
|
4688
|
+
// after the dialog is open so getFocusableElements can find content.
|
|
4689
|
+
if (!this.isPopoverVisible) {
|
|
4690
|
+
this.updateFocusTrap();
|
|
4691
|
+
}
|
|
4692
|
+
|
|
4643
4693
|
const eventType = event.detail.eventType || "unknown";
|
|
4644
4694
|
if (!this.isPopoverVisible && this.hasFocus && eventType === "keydown") {
|
|
4645
4695
|
this.trigger.focus();
|
|
@@ -4738,19 +4788,178 @@ class AuroDropdown extends AuroElement {
|
|
|
4738
4788
|
* @private
|
|
4739
4789
|
*/
|
|
4740
4790
|
updateFocusTrap() {
|
|
4791
|
+
// Always clean up existing handlers/traps before setting up new ones
|
|
4792
|
+
// to prevent duplicate listeners on repeated calls.
|
|
4793
|
+
if (this._bibTabHandler) {
|
|
4794
|
+
this.removeEventListener('keydown', this._bibTabHandler);
|
|
4795
|
+
this._bibTabHandler = undefined;
|
|
4796
|
+
}
|
|
4797
|
+
|
|
4798
|
+
if (this.focusTrap) {
|
|
4799
|
+
this.focusTrap.disconnect();
|
|
4800
|
+
this.focusTrap = undefined;
|
|
4801
|
+
}
|
|
4802
|
+
|
|
4741
4803
|
if (this.isPopoverVisible) {
|
|
4742
4804
|
if (!this.isBibFullscreen) {
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4805
|
+
if (this.desktopModal) {
|
|
4806
|
+
// Desktop modal: trap focus only within the bib content.
|
|
4807
|
+
// Can't use FocusTrap on the bib element because keydown events
|
|
4808
|
+
// from slotted content bubble through the dropdown host (light DOM),
|
|
4809
|
+
// not through the bib (shadow projection target). Using FocusTrap
|
|
4810
|
+
// on the dropdown would include the trigger in the tab cycle.
|
|
4811
|
+
// Instead, listen for Tab on the dropdown and manually wrap focus
|
|
4812
|
+
// within the bib's focusable elements.
|
|
4813
|
+
this._bibTabHandler = (event) => {
|
|
4814
|
+
if (event.key !== 'Tab') {
|
|
4815
|
+
return;
|
|
4816
|
+
}
|
|
4817
|
+
|
|
4818
|
+
// Collect focusable elements from the bib content.
|
|
4819
|
+
const focusables = getFocusableElements(this.bibContent);
|
|
4820
|
+
|
|
4821
|
+
// Fallback: try from slotted content directly
|
|
4822
|
+
if (!focusables.length) {
|
|
4823
|
+
const slot = this.shadowRoot.querySelector('.slotContent slot');
|
|
4824
|
+
const assignedNodes = slot ? slot.assignedNodes({ flatten: true }) : [];
|
|
4825
|
+
|
|
4826
|
+
for (const node of assignedNodes) {
|
|
4827
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
4828
|
+
focusables.push(...getFocusableElements(node));
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4831
|
+
}
|
|
4832
|
+
|
|
4833
|
+
if (!focusables.length) {
|
|
4834
|
+
return;
|
|
4835
|
+
}
|
|
4836
|
+
|
|
4837
|
+
event.preventDefault();
|
|
4838
|
+
|
|
4839
|
+
const direction = event.shiftKey ? -1 : 1; // eslint-disable-line no-magic-numbers
|
|
4840
|
+
|
|
4841
|
+
// Walk the active element chain through shadow roots
|
|
4842
|
+
const actives = this._getActiveElements();
|
|
4843
|
+
|
|
4844
|
+
let idx = focusables.findIndex((el) => actives.includes(el));
|
|
4845
|
+
|
|
4846
|
+
if (idx === -1) { // eslint-disable-line no-magic-numbers
|
|
4847
|
+
// Focus is not on a known element — move to first/last
|
|
4848
|
+
idx = direction === 1 ? -1 : focusables.length; // eslint-disable-line no-magic-numbers
|
|
4849
|
+
}
|
|
4850
|
+
|
|
4851
|
+
// Try each element in order, skipping any that can't receive focus
|
|
4852
|
+
// (e.g. hidden elements, elements in collapsed sections)
|
|
4853
|
+
for (let index = 0; index < focusables.length; index++) { // eslint-disable-line no-plusplus
|
|
4854
|
+
let nextIdx = idx + direction;
|
|
4855
|
+
|
|
4856
|
+
// Wrap around
|
|
4857
|
+
if (nextIdx < 0) {
|
|
4858
|
+
nextIdx = focusables.length - 1;
|
|
4859
|
+
} else if (nextIdx >= focusables.length) {
|
|
4860
|
+
nextIdx = 0;
|
|
4861
|
+
}
|
|
4862
|
+
|
|
4863
|
+
focusables[nextIdx].focus();
|
|
4864
|
+
|
|
4865
|
+
// Verify focus actually moved to the target
|
|
4866
|
+
const newActives = this._getActiveElements();
|
|
4867
|
+
|
|
4868
|
+
if (newActives.includes(focusables[nextIdx])) {
|
|
4869
|
+
return;
|
|
4870
|
+
}
|
|
4871
|
+
|
|
4872
|
+
// Focus didn't stick — skip this element and try the next
|
|
4873
|
+
idx = nextIdx;
|
|
4874
|
+
}
|
|
4875
|
+
};
|
|
4876
|
+
this.addEventListener('keydown', this._bibTabHandler);
|
|
4877
|
+
|
|
4878
|
+
// Move initial focus into the bib content, matching FocusTrap behavior
|
|
4879
|
+
requestAnimationFrame(() => {
|
|
4880
|
+
const focusables = getFocusableElements(this.bibContent);
|
|
4881
|
+
if (focusables.length) {
|
|
4882
|
+
focusables[0].focus();
|
|
4883
|
+
}
|
|
4884
|
+
});
|
|
4885
|
+
} else {
|
|
4886
|
+
// Normal desktop: use FocusTrap on the bib element
|
|
4887
|
+
this.focusTrap = new FocusTrap(this.bibContent);
|
|
4888
|
+
this.focusTrap.focusFirstElement();
|
|
4889
|
+
}
|
|
4746
4890
|
}
|
|
4747
4891
|
// Fullscreen: showModal() provides native focus trapping
|
|
4892
|
+
}
|
|
4893
|
+
}
|
|
4894
|
+
|
|
4895
|
+
/**
|
|
4896
|
+
* Returns the chain of active (focused) elements through shadow roots.
|
|
4897
|
+
* @private
|
|
4898
|
+
* @returns {Array<HTMLElement>}
|
|
4899
|
+
*/
|
|
4900
|
+
_getActiveElements() {
|
|
4901
|
+
let { activeElement } = document;
|
|
4902
|
+
const actives = [activeElement];
|
|
4903
|
+
|
|
4904
|
+
while (activeElement?.shadowRoot?.activeElement) {
|
|
4905
|
+
activeElement = activeElement.shadowRoot.activeElement;
|
|
4906
|
+
actives.push(activeElement);
|
|
4907
|
+
}
|
|
4908
|
+
|
|
4909
|
+
return actives;
|
|
4910
|
+
}
|
|
4911
|
+
|
|
4912
|
+
/**
|
|
4913
|
+
* Sets `inert` on sibling elements of the dropdown's top-level host
|
|
4914
|
+
* so that content outside the dropdown is not interactive while the modal is open.
|
|
4915
|
+
* Walks up through shadow DOM boundaries to find the outermost host element
|
|
4916
|
+
* in the light DOM, then sets `inert` on siblings at each ancestor level
|
|
4917
|
+
* to ensure all page content outside the host subtree is inert.
|
|
4918
|
+
* @private
|
|
4919
|
+
*/
|
|
4920
|
+
_setPageInert() {
|
|
4921
|
+
if (this._inertSiblings) {
|
|
4748
4922
|
return;
|
|
4749
4923
|
}
|
|
4750
4924
|
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4925
|
+
this._inertSiblings = [];
|
|
4926
|
+
|
|
4927
|
+
// Walk up through shadow DOM boundaries to find the topmost host
|
|
4928
|
+
// element in the light DOM. For example, if this dropdown is inside
|
|
4929
|
+
// auro-datepicker's shadow DOM, we walk up to the datepicker element
|
|
4930
|
+
// so we set inert on its siblings — not on the datepicker itself.
|
|
4931
|
+
let host = this;
|
|
4932
|
+
while (host.getRootNode() instanceof ShadowRoot) {
|
|
4933
|
+
host = host.getRootNode().host;
|
|
4934
|
+
}
|
|
4935
|
+
|
|
4936
|
+
// Walk up the ancestor chain, inerting siblings at each level
|
|
4937
|
+
// to ensure the entire page outside the host subtree is inert.
|
|
4938
|
+
let current = host;
|
|
4939
|
+
while (current.parentElement) {
|
|
4940
|
+
const parent = current.parentElement;
|
|
4941
|
+
for (const sibling of parent.children) {
|
|
4942
|
+
if (sibling !== current) {
|
|
4943
|
+
this._inertSiblings.push({ element: sibling, wasInert: sibling.inert });
|
|
4944
|
+
sibling.inert = true;
|
|
4945
|
+
}
|
|
4946
|
+
}
|
|
4947
|
+
current = parent;
|
|
4948
|
+
}
|
|
4949
|
+
}
|
|
4950
|
+
|
|
4951
|
+
/**
|
|
4952
|
+
* Restores `inert` state on siblings that were tracked by `_setPageInert`.
|
|
4953
|
+
* Preserves the previous inert state so externally-inerted elements are
|
|
4954
|
+
* not inadvertently re-enabled.
|
|
4955
|
+
* @private
|
|
4956
|
+
*/
|
|
4957
|
+
_clearPageInert() {
|
|
4958
|
+
if (this._inertSiblings) {
|
|
4959
|
+
for (const entry of this._inertSiblings) {
|
|
4960
|
+
entry.element.inert = entry.wasInert;
|
|
4961
|
+
}
|
|
4962
|
+
this._inertSiblings = undefined;
|
|
4754
4963
|
}
|
|
4755
4964
|
}
|
|
4756
4965
|
|
|
@@ -4989,6 +5198,7 @@ class AuroDropdown extends AuroElement {
|
|
|
4989
5198
|
shape="${this.shape}"
|
|
4990
5199
|
?data-show="${this.isPopoverVisible}"
|
|
4991
5200
|
?isfullscreen="${this.isBibFullscreen}"
|
|
5201
|
+
?desktopmodal="${this.desktopModal}"
|
|
4992
5202
|
.dialogLabel="${this.bibDialogLabel}"
|
|
4993
5203
|
${n$2(this.bibElement)}
|
|
4994
5204
|
>
|
|
@@ -3311,7 +3311,7 @@ function applyKeyboardStrategy(component, strategy, options = {}) {
|
|
|
3311
3311
|
});
|
|
3312
3312
|
}
|
|
3313
3313
|
|
|
3314
|
-
var styleCss$2 = i$2`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
|
|
3314
|
+
var styleCss$2 = i$2`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host([desktopmodal]:popover-open)::backdrop{background:transparent}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
|
|
3315
3315
|
|
|
3316
3316
|
var colorCss$2 = i$2`.container{background-color:var(--ds-auro-dropdownbib-container-color);box-shadow:var(--ds-auro-dropdownbib-boxshadow-color);color:var(--ds-auro-dropdownbib-text-color)}`;
|
|
3317
3317
|
|
|
@@ -3942,7 +3942,7 @@ class AuroHelpText extends i {
|
|
|
3942
3942
|
}
|
|
3943
3943
|
}
|
|
3944
3944
|
|
|
3945
|
-
var formkitVersion = '
|
|
3945
|
+
var formkitVersion = '202606011856';
|
|
3946
3946
|
|
|
3947
3947
|
class AuroElement extends i {
|
|
3948
3948
|
static get properties() {
|
|
@@ -4122,6 +4122,7 @@ class AuroDropdown extends AuroElement {
|
|
|
4122
4122
|
_intializeDefaults() {
|
|
4123
4123
|
this.appearance = 'default';
|
|
4124
4124
|
this.chevron = false;
|
|
4125
|
+
this.desktopModal = false;
|
|
4125
4126
|
this.disabled = false;
|
|
4126
4127
|
this.disableKeyboardHandling = false;
|
|
4127
4128
|
this.error = false;
|
|
@@ -4302,6 +4303,14 @@ class AuroDropdown extends AuroElement {
|
|
|
4302
4303
|
reflect: true
|
|
4303
4304
|
},
|
|
4304
4305
|
|
|
4306
|
+
/**
|
|
4307
|
+
* If declared, the dropdown will behave as a modal dialog when in a desktop viewport size.
|
|
4308
|
+
*/
|
|
4309
|
+
desktopModal: {
|
|
4310
|
+
type: Boolean,
|
|
4311
|
+
reflect: true
|
|
4312
|
+
},
|
|
4313
|
+
|
|
4305
4314
|
/**
|
|
4306
4315
|
* If declared, the dropdown will only show by calling the API .show() public method.
|
|
4307
4316
|
*/
|
|
@@ -4589,6 +4598,15 @@ class AuroDropdown extends AuroElement {
|
|
|
4589
4598
|
|
|
4590
4599
|
disconnectedCallback() {
|
|
4591
4600
|
super.disconnectedCallback();
|
|
4601
|
+
this._clearPageInert();
|
|
4602
|
+
if (this._bibTabHandler) {
|
|
4603
|
+
this.removeEventListener('keydown', this._bibTabHandler);
|
|
4604
|
+
this._bibTabHandler = undefined;
|
|
4605
|
+
}
|
|
4606
|
+
if (this.focusTrap) {
|
|
4607
|
+
this.focusTrap.disconnect();
|
|
4608
|
+
this.focusTrap = undefined;
|
|
4609
|
+
}
|
|
4592
4610
|
if (this.floater) {
|
|
4593
4611
|
this.floater.hideBib('disconnect');
|
|
4594
4612
|
this.floater.disconnect();
|
|
@@ -4616,19 +4634,45 @@ class AuroDropdown extends AuroElement {
|
|
|
4616
4634
|
if (this.isPopoverVisible) {
|
|
4617
4635
|
// Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
|
|
4618
4636
|
// Desktop: use show() for Floating UI positioning + FocusTrap for focus management
|
|
4619
|
-
|
|
4620
|
-
this.
|
|
4637
|
+
this.bibElement.value.open(this.isBibFullscreen);
|
|
4638
|
+
this.updateFocusTrap();
|
|
4639
|
+
|
|
4640
|
+
// Desktop modal: make siblings inert so content outside is not interactive
|
|
4641
|
+
if (this.desktopModal && !this.isBibFullscreen) {
|
|
4642
|
+
this._setPageInert();
|
|
4643
|
+
}
|
|
4621
4644
|
} else {
|
|
4622
4645
|
this.bibElement.value.close();
|
|
4646
|
+
this._clearPageInert();
|
|
4623
4647
|
}
|
|
4624
4648
|
}
|
|
4625
4649
|
|
|
4626
4650
|
// When fullscreen strategy changes while open, re-open dialog with correct mode
|
|
4627
4651
|
// (e.g. resizing from desktop → mobile while dropdown is open)
|
|
4628
4652
|
if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
|
|
4629
|
-
const useModal = this.isBibFullscreen;
|
|
4630
4653
|
this.bibElement.value.close();
|
|
4631
|
-
this.bibElement.value.open(
|
|
4654
|
+
this.bibElement.value.open(this.isBibFullscreen);
|
|
4655
|
+
|
|
4656
|
+
// Re-initialize focus management for the new strategy
|
|
4657
|
+
this.updateFocusTrap();
|
|
4658
|
+
|
|
4659
|
+
// Toggle inert: desktop modal needs it, fullscreen showModal() handles it natively
|
|
4660
|
+
if (this.desktopModal && !this.isBibFullscreen) {
|
|
4661
|
+
this._setPageInert();
|
|
4662
|
+
} else {
|
|
4663
|
+
this._clearPageInert();
|
|
4664
|
+
}
|
|
4665
|
+
}
|
|
4666
|
+
|
|
4667
|
+
// Handle desktopModal toggled while the dropdown is already open.
|
|
4668
|
+
// Re-initialize focus trapping and page inert state to match the new mode.
|
|
4669
|
+
if (changedProperties.has('desktopModal') && this.isPopoverVisible && !this.isBibFullscreen) {
|
|
4670
|
+
this.updateFocusTrap();
|
|
4671
|
+
if (this.desktopModal) {
|
|
4672
|
+
this._setPageInert();
|
|
4673
|
+
} else {
|
|
4674
|
+
this._clearPageInert();
|
|
4675
|
+
}
|
|
4632
4676
|
}
|
|
4633
4677
|
}
|
|
4634
4678
|
|
|
@@ -4638,8 +4682,14 @@ class AuroDropdown extends AuroElement {
|
|
|
4638
4682
|
* @param {CustomEvent} event - The custom event that contains the dropdown toggle information.
|
|
4639
4683
|
*/
|
|
4640
4684
|
handleDropdownToggle(event) {
|
|
4641
|
-
this.updateFocusTrap();
|
|
4642
4685
|
this.isPopoverVisible = event.detail.expanded;
|
|
4686
|
+
|
|
4687
|
+
// Tear down FocusTrap when closing. Creation happens in updated()
|
|
4688
|
+
// after the dialog is open so getFocusableElements can find content.
|
|
4689
|
+
if (!this.isPopoverVisible) {
|
|
4690
|
+
this.updateFocusTrap();
|
|
4691
|
+
}
|
|
4692
|
+
|
|
4643
4693
|
const eventType = event.detail.eventType || "unknown";
|
|
4644
4694
|
if (!this.isPopoverVisible && this.hasFocus && eventType === "keydown") {
|
|
4645
4695
|
this.trigger.focus();
|
|
@@ -4738,19 +4788,178 @@ class AuroDropdown extends AuroElement {
|
|
|
4738
4788
|
* @private
|
|
4739
4789
|
*/
|
|
4740
4790
|
updateFocusTrap() {
|
|
4791
|
+
// Always clean up existing handlers/traps before setting up new ones
|
|
4792
|
+
// to prevent duplicate listeners on repeated calls.
|
|
4793
|
+
if (this._bibTabHandler) {
|
|
4794
|
+
this.removeEventListener('keydown', this._bibTabHandler);
|
|
4795
|
+
this._bibTabHandler = undefined;
|
|
4796
|
+
}
|
|
4797
|
+
|
|
4798
|
+
if (this.focusTrap) {
|
|
4799
|
+
this.focusTrap.disconnect();
|
|
4800
|
+
this.focusTrap = undefined;
|
|
4801
|
+
}
|
|
4802
|
+
|
|
4741
4803
|
if (this.isPopoverVisible) {
|
|
4742
4804
|
if (!this.isBibFullscreen) {
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4805
|
+
if (this.desktopModal) {
|
|
4806
|
+
// Desktop modal: trap focus only within the bib content.
|
|
4807
|
+
// Can't use FocusTrap on the bib element because keydown events
|
|
4808
|
+
// from slotted content bubble through the dropdown host (light DOM),
|
|
4809
|
+
// not through the bib (shadow projection target). Using FocusTrap
|
|
4810
|
+
// on the dropdown would include the trigger in the tab cycle.
|
|
4811
|
+
// Instead, listen for Tab on the dropdown and manually wrap focus
|
|
4812
|
+
// within the bib's focusable elements.
|
|
4813
|
+
this._bibTabHandler = (event) => {
|
|
4814
|
+
if (event.key !== 'Tab') {
|
|
4815
|
+
return;
|
|
4816
|
+
}
|
|
4817
|
+
|
|
4818
|
+
// Collect focusable elements from the bib content.
|
|
4819
|
+
const focusables = getFocusableElements(this.bibContent);
|
|
4820
|
+
|
|
4821
|
+
// Fallback: try from slotted content directly
|
|
4822
|
+
if (!focusables.length) {
|
|
4823
|
+
const slot = this.shadowRoot.querySelector('.slotContent slot');
|
|
4824
|
+
const assignedNodes = slot ? slot.assignedNodes({ flatten: true }) : [];
|
|
4825
|
+
|
|
4826
|
+
for (const node of assignedNodes) {
|
|
4827
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
4828
|
+
focusables.push(...getFocusableElements(node));
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4831
|
+
}
|
|
4832
|
+
|
|
4833
|
+
if (!focusables.length) {
|
|
4834
|
+
return;
|
|
4835
|
+
}
|
|
4836
|
+
|
|
4837
|
+
event.preventDefault();
|
|
4838
|
+
|
|
4839
|
+
const direction = event.shiftKey ? -1 : 1; // eslint-disable-line no-magic-numbers
|
|
4840
|
+
|
|
4841
|
+
// Walk the active element chain through shadow roots
|
|
4842
|
+
const actives = this._getActiveElements();
|
|
4843
|
+
|
|
4844
|
+
let idx = focusables.findIndex((el) => actives.includes(el));
|
|
4845
|
+
|
|
4846
|
+
if (idx === -1) { // eslint-disable-line no-magic-numbers
|
|
4847
|
+
// Focus is not on a known element — move to first/last
|
|
4848
|
+
idx = direction === 1 ? -1 : focusables.length; // eslint-disable-line no-magic-numbers
|
|
4849
|
+
}
|
|
4850
|
+
|
|
4851
|
+
// Try each element in order, skipping any that can't receive focus
|
|
4852
|
+
// (e.g. hidden elements, elements in collapsed sections)
|
|
4853
|
+
for (let index = 0; index < focusables.length; index++) { // eslint-disable-line no-plusplus
|
|
4854
|
+
let nextIdx = idx + direction;
|
|
4855
|
+
|
|
4856
|
+
// Wrap around
|
|
4857
|
+
if (nextIdx < 0) {
|
|
4858
|
+
nextIdx = focusables.length - 1;
|
|
4859
|
+
} else if (nextIdx >= focusables.length) {
|
|
4860
|
+
nextIdx = 0;
|
|
4861
|
+
}
|
|
4862
|
+
|
|
4863
|
+
focusables[nextIdx].focus();
|
|
4864
|
+
|
|
4865
|
+
// Verify focus actually moved to the target
|
|
4866
|
+
const newActives = this._getActiveElements();
|
|
4867
|
+
|
|
4868
|
+
if (newActives.includes(focusables[nextIdx])) {
|
|
4869
|
+
return;
|
|
4870
|
+
}
|
|
4871
|
+
|
|
4872
|
+
// Focus didn't stick — skip this element and try the next
|
|
4873
|
+
idx = nextIdx;
|
|
4874
|
+
}
|
|
4875
|
+
};
|
|
4876
|
+
this.addEventListener('keydown', this._bibTabHandler);
|
|
4877
|
+
|
|
4878
|
+
// Move initial focus into the bib content, matching FocusTrap behavior
|
|
4879
|
+
requestAnimationFrame(() => {
|
|
4880
|
+
const focusables = getFocusableElements(this.bibContent);
|
|
4881
|
+
if (focusables.length) {
|
|
4882
|
+
focusables[0].focus();
|
|
4883
|
+
}
|
|
4884
|
+
});
|
|
4885
|
+
} else {
|
|
4886
|
+
// Normal desktop: use FocusTrap on the bib element
|
|
4887
|
+
this.focusTrap = new FocusTrap(this.bibContent);
|
|
4888
|
+
this.focusTrap.focusFirstElement();
|
|
4889
|
+
}
|
|
4746
4890
|
}
|
|
4747
4891
|
// Fullscreen: showModal() provides native focus trapping
|
|
4892
|
+
}
|
|
4893
|
+
}
|
|
4894
|
+
|
|
4895
|
+
/**
|
|
4896
|
+
* Returns the chain of active (focused) elements through shadow roots.
|
|
4897
|
+
* @private
|
|
4898
|
+
* @returns {Array<HTMLElement>}
|
|
4899
|
+
*/
|
|
4900
|
+
_getActiveElements() {
|
|
4901
|
+
let { activeElement } = document;
|
|
4902
|
+
const actives = [activeElement];
|
|
4903
|
+
|
|
4904
|
+
while (activeElement?.shadowRoot?.activeElement) {
|
|
4905
|
+
activeElement = activeElement.shadowRoot.activeElement;
|
|
4906
|
+
actives.push(activeElement);
|
|
4907
|
+
}
|
|
4908
|
+
|
|
4909
|
+
return actives;
|
|
4910
|
+
}
|
|
4911
|
+
|
|
4912
|
+
/**
|
|
4913
|
+
* Sets `inert` on sibling elements of the dropdown's top-level host
|
|
4914
|
+
* so that content outside the dropdown is not interactive while the modal is open.
|
|
4915
|
+
* Walks up through shadow DOM boundaries to find the outermost host element
|
|
4916
|
+
* in the light DOM, then sets `inert` on siblings at each ancestor level
|
|
4917
|
+
* to ensure all page content outside the host subtree is inert.
|
|
4918
|
+
* @private
|
|
4919
|
+
*/
|
|
4920
|
+
_setPageInert() {
|
|
4921
|
+
if (this._inertSiblings) {
|
|
4748
4922
|
return;
|
|
4749
4923
|
}
|
|
4750
4924
|
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4925
|
+
this._inertSiblings = [];
|
|
4926
|
+
|
|
4927
|
+
// Walk up through shadow DOM boundaries to find the topmost host
|
|
4928
|
+
// element in the light DOM. For example, if this dropdown is inside
|
|
4929
|
+
// auro-datepicker's shadow DOM, we walk up to the datepicker element
|
|
4930
|
+
// so we set inert on its siblings — not on the datepicker itself.
|
|
4931
|
+
let host = this;
|
|
4932
|
+
while (host.getRootNode() instanceof ShadowRoot) {
|
|
4933
|
+
host = host.getRootNode().host;
|
|
4934
|
+
}
|
|
4935
|
+
|
|
4936
|
+
// Walk up the ancestor chain, inerting siblings at each level
|
|
4937
|
+
// to ensure the entire page outside the host subtree is inert.
|
|
4938
|
+
let current = host;
|
|
4939
|
+
while (current.parentElement) {
|
|
4940
|
+
const parent = current.parentElement;
|
|
4941
|
+
for (const sibling of parent.children) {
|
|
4942
|
+
if (sibling !== current) {
|
|
4943
|
+
this._inertSiblings.push({ element: sibling, wasInert: sibling.inert });
|
|
4944
|
+
sibling.inert = true;
|
|
4945
|
+
}
|
|
4946
|
+
}
|
|
4947
|
+
current = parent;
|
|
4948
|
+
}
|
|
4949
|
+
}
|
|
4950
|
+
|
|
4951
|
+
/**
|
|
4952
|
+
* Restores `inert` state on siblings that were tracked by `_setPageInert`.
|
|
4953
|
+
* Preserves the previous inert state so externally-inerted elements are
|
|
4954
|
+
* not inadvertently re-enabled.
|
|
4955
|
+
* @private
|
|
4956
|
+
*/
|
|
4957
|
+
_clearPageInert() {
|
|
4958
|
+
if (this._inertSiblings) {
|
|
4959
|
+
for (const entry of this._inertSiblings) {
|
|
4960
|
+
entry.element.inert = entry.wasInert;
|
|
4961
|
+
}
|
|
4962
|
+
this._inertSiblings = undefined;
|
|
4754
4963
|
}
|
|
4755
4964
|
}
|
|
4756
4965
|
|
|
@@ -4989,6 +5198,7 @@ class AuroDropdown extends AuroElement {
|
|
|
4989
5198
|
shape="${this.shape}"
|
|
4990
5199
|
?data-show="${this.isPopoverVisible}"
|
|
4991
5200
|
?isfullscreen="${this.isBibFullscreen}"
|
|
5201
|
+
?desktopmodal="${this.desktopModal}"
|
|
4992
5202
|
.dialogLabel="${this.bibDialogLabel}"
|
|
4993
5203
|
${n$2(this.bibElement)}
|
|
4994
5204
|
>
|