@pine-ds/core 4.7.1 → 4.8.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/pds-avatar.js +1 -1
- package/components/pds-button2.js +1 -1
- package/components/pds-checkbox2.js +1 -1
- package/components/pds-chip2.js +1 -1
- package/components/pds-combobox.js +1 -1
- package/components/pds-drawer.js +1 -1
- package/components/pds-dropdown-menu-item.js +1 -1
- package/components/pds-dropdown-menu.js +1 -1
- package/components/pds-modal-content.js +1 -1
- package/components/pds-modal2.js +1 -1
- package/components/pds-multiselect.js +1 -1
- package/components/pds-popover.js +1 -1
- package/components/pds-radio-group.js +1 -1
- package/components/pds-radio.js +1 -1
- package/components/pds-switch.js +1 -1
- package/components/pds-table-head-cell2.js +1 -1
- package/components/pds-textarea.js +1 -1
- package/components/pds-toast.js +1 -1
- package/components/truncation-tooltip.js +1 -1
- package/dist/cjs/{index-5Azb8EQG.js → index-Do70atou.js} +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/pds-accordion.cjs.entry.js +1 -1
- package/dist/cjs/pds-avatar.cjs.entry.js +3 -3
- package/dist/cjs/pds-button.cjs.entry.js +24 -21
- package/dist/cjs/pds-checkbox.cjs.entry.js +2 -2
- package/dist/cjs/pds-chip.cjs.entry.js +4 -4
- package/dist/cjs/pds-combobox.cjs.entry.js +4 -4
- package/dist/cjs/pds-copytext.cjs.entry.js +2 -2
- package/dist/cjs/pds-datepicker.cjs.entry.js +1 -1
- package/dist/cjs/pds-drawer.cjs.entry.js +1 -1
- package/dist/cjs/pds-dropdown-menu-item.cjs.entry.js +31 -2
- package/dist/cjs/pds-dropdown-menu.cjs.entry.js +4 -4
- package/dist/cjs/pds-filter.cjs.entry.js +1 -1
- package/dist/cjs/pds-input.cjs.entry.js +1 -1
- package/dist/cjs/pds-link.cjs.entry.js +1 -1
- package/dist/cjs/pds-modal-content.cjs.entry.js +32 -30
- package/dist/cjs/pds-modal.cjs.entry.js +4 -4
- package/dist/cjs/pds-multiselect.cjs.entry.js +6 -6
- package/dist/cjs/pds-popover.cjs.entry.js +187 -11
- package/dist/cjs/pds-radio-group.cjs.entry.js +2 -2
- package/dist/cjs/pds-radio.cjs.entry.js +3 -3
- package/dist/cjs/pds-select.cjs.entry.js +1 -1
- package/dist/cjs/pds-sortable-item.cjs.entry.js +1 -1
- package/dist/cjs/pds-switch.cjs.entry.js +2 -2
- package/dist/cjs/pds-table-cell.cjs.entry.js +1 -1
- package/dist/cjs/pds-table-head-cell.cjs.entry.js +2 -2
- package/dist/cjs/pds-text.cjs.entry.js +1 -1
- package/dist/cjs/pds-textarea.cjs.entry.js +2 -2
- package/dist/cjs/pds-toast.cjs.entry.js +1 -1
- package/dist/cjs/pine-core.cjs.js +1 -1
- package/dist/cjs/{truncation-tooltip-DO9xli2e.js → truncation-tooltip-BtuiXLV0.js} +31 -6
- package/dist/collection/components/pds-avatar/pds-avatar.js +2 -2
- package/dist/collection/components/pds-button/pds-button.js +24 -22
- package/dist/collection/components/pds-button/stories/pds-button.stories.js +3 -3
- package/dist/collection/components/pds-checkbox/pds-checkbox.js +1 -1
- package/dist/collection/components/pds-chip/pds-chip.js +2 -2
- package/dist/collection/components/pds-combobox/pds-combobox.js +4 -4
- package/dist/collection/components/pds-datepicker/stories/pds-datepicker.stories.js +1 -1
- package/dist/collection/components/pds-drawer/pds-drawer.css +4 -0
- package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu-item/pds-dropdown-menu-item.css +8 -0
- package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu-item/pds-dropdown-menu-item.js +58 -6
- package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu.js +4 -4
- package/dist/collection/components/pds-dropdown-menu/stories/pds-dropdown-menu.stories.js +39 -0
- package/dist/collection/components/pds-modal/pds-modal-content/pds-modal-content.js +32 -30
- package/dist/collection/components/pds-modal/pds-modal.js +4 -4
- package/dist/collection/components/pds-multiselect/pds-multiselect.js +5 -5
- package/dist/collection/components/pds-popover/pds-popover.js +240 -11
- package/dist/collection/components/pds-popover/stories/pds-popover.stories.js +31 -0
- package/dist/collection/components/pds-radio/pds-radio.js +2 -2
- package/dist/collection/components/pds-radio-group/pds-radio-group.js +1 -1
- package/dist/collection/components/pds-switch/pds-switch.js +1 -1
- package/dist/collection/components/pds-table/pds-table-head-cell/pds-table-head-cell.js +1 -1
- package/dist/collection/components/pds-table/stories/pds-table.stories.js +1 -1
- package/dist/collection/components/pds-text/stories/pds-text.stories.js +1 -1
- package/dist/collection/components/pds-textarea/pds-textarea.js +1 -1
- package/dist/collection/components/pds-toast/pds-toast.js +1 -1
- package/dist/collection/utils/truncation-tooltip.js +31 -6
- package/dist/docs.json +124 -7
- package/dist/esm/{index-BJXk71tO.js → index-BWDu62Mo.js} +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/pds-accordion.entry.js +1 -1
- package/dist/esm/pds-avatar.entry.js +3 -3
- package/dist/esm/pds-button.entry.js +24 -21
- package/dist/esm/pds-checkbox.entry.js +2 -2
- package/dist/esm/pds-chip.entry.js +4 -4
- package/dist/esm/pds-combobox.entry.js +4 -4
- package/dist/esm/pds-copytext.entry.js +2 -2
- package/dist/esm/pds-datepicker.entry.js +1 -1
- package/dist/esm/pds-drawer.entry.js +1 -1
- package/dist/esm/pds-dropdown-menu-item.entry.js +31 -2
- package/dist/esm/pds-dropdown-menu.entry.js +4 -4
- package/dist/esm/pds-filter.entry.js +1 -1
- package/dist/esm/pds-input.entry.js +1 -1
- package/dist/esm/pds-link.entry.js +1 -1
- package/dist/esm/pds-modal-content.entry.js +32 -30
- package/dist/esm/pds-modal.entry.js +4 -4
- package/dist/esm/pds-multiselect.entry.js +6 -6
- package/dist/esm/pds-popover.entry.js +187 -11
- package/dist/esm/pds-radio-group.entry.js +2 -2
- package/dist/esm/pds-radio.entry.js +3 -3
- package/dist/esm/pds-select.entry.js +1 -1
- package/dist/esm/pds-sortable-item.entry.js +1 -1
- package/dist/esm/pds-switch.entry.js +2 -2
- package/dist/esm/pds-table-cell.entry.js +1 -1
- package/dist/esm/pds-table-head-cell.entry.js +2 -2
- package/dist/esm/pds-text.entry.js +1 -1
- package/dist/esm/pds-textarea.entry.js +2 -2
- package/dist/esm/pds-toast.entry.js +1 -1
- package/dist/esm/pine-core.js +1 -1
- package/dist/esm/{truncation-tooltip-DRXsdKk1.js → truncation-tooltip-FaW67DiY.js} +31 -6
- package/dist/esm-es5/loader.js +1 -1
- package/dist/esm-es5/pds-accordion.entry.js +1 -1
- package/dist/esm-es5/pds-avatar.entry.js +1 -1
- package/dist/esm-es5/pds-button.entry.js +1 -1
- package/dist/esm-es5/pds-checkbox.entry.js +1 -1
- package/dist/esm-es5/pds-chip.entry.js +1 -1
- package/dist/esm-es5/pds-combobox.entry.js +1 -1
- package/dist/esm-es5/pds-copytext.entry.js +1 -1
- package/dist/esm-es5/pds-datepicker.entry.js +1 -1
- package/dist/esm-es5/pds-drawer.entry.js +1 -1
- package/dist/esm-es5/pds-dropdown-menu-item.entry.js +1 -1
- package/dist/esm-es5/pds-dropdown-menu.entry.js +1 -1
- package/dist/esm-es5/pds-filter.entry.js +1 -1
- package/dist/esm-es5/pds-input.entry.js +1 -1
- package/dist/esm-es5/pds-link.entry.js +1 -1
- package/dist/esm-es5/pds-modal-content.entry.js +1 -1
- package/dist/esm-es5/pds-modal.entry.js +1 -1
- package/dist/esm-es5/pds-multiselect.entry.js +1 -1
- package/dist/esm-es5/pds-popover.entry.js +1 -1
- package/dist/esm-es5/pds-radio-group.entry.js +1 -1
- package/dist/esm-es5/pds-radio.entry.js +1 -1
- package/dist/esm-es5/pds-select.entry.js +1 -1
- package/dist/esm-es5/pds-sortable-item.entry.js +1 -1
- package/dist/esm-es5/pds-switch.entry.js +1 -1
- package/dist/esm-es5/pds-table-cell.entry.js +1 -1
- package/dist/esm-es5/pds-table-head-cell.entry.js +1 -1
- package/dist/esm-es5/pds-text.entry.js +1 -1
- package/dist/esm-es5/pds-textarea.entry.js +1 -1
- package/dist/esm-es5/pds-toast.entry.js +1 -1
- package/dist/esm-es5/pine-core.js +1 -1
- package/dist/esm-es5/truncation-tooltip-FaW67DiY.js +1 -0
- package/dist/pine-core/{p-e836f3ec.system.entry.js → p-00a50de5.system.entry.js} +2 -2
- package/dist/pine-core/{p-1437585e.system.entry.js → p-047433a4.system.entry.js} +1 -1
- package/dist/pine-core/{p-7fa66cad.entry.js → p-089c3e60.entry.js} +1 -1
- package/dist/pine-core/{p-341c38f1.system.entry.js → p-0af0d752.system.entry.js} +1 -1
- package/dist/pine-core/{p-3a959459.system.entry.js → p-121612a7.system.entry.js} +1 -1
- package/dist/pine-core/{p-cde8eb81.entry.js → p-138b278b.entry.js} +1 -1
- package/dist/pine-core/{p-cfd012d4.entry.js → p-158b2f51.entry.js} +1 -1
- package/dist/pine-core/p-17f97f1a.entry.js +1 -0
- package/dist/pine-core/{p-5c90091e.system.entry.js → p-19ba2788.system.entry.js} +1 -1
- package/dist/pine-core/p-1dc5a7e0.system.entry.js +1 -0
- package/dist/pine-core/{p-355e4cf9.entry.js → p-25ea48d1.entry.js} +1 -1
- package/dist/pine-core/{p-c81d8ac8.entry.js → p-295f64ea.entry.js} +1 -1
- package/dist/pine-core/{p-576cf904.system.entry.js → p-29cd4113.system.entry.js} +1 -1
- package/dist/pine-core/{p-1ee86d87.system.entry.js → p-332590c7.system.entry.js} +1 -1
- package/dist/pine-core/p-36cb4bf6.entry.js +1 -0
- package/dist/pine-core/{p-080cb087.system.entry.js → p-3c977d8d.system.entry.js} +1 -1
- package/dist/pine-core/p-3d51891a.entry.js +1 -0
- package/dist/pine-core/{p-72865997.entry.js → p-44f546ae.entry.js} +1 -1
- package/dist/pine-core/{p-b60ac7eb.system.entry.js → p-4bfc8b3e.system.entry.js} +1 -1
- package/dist/pine-core/p-5833a072.system.entry.js +1 -0
- package/dist/pine-core/p-5cfd4d41.system.entry.js +1 -0
- package/dist/pine-core/{p-f2c253d8.entry.js → p-62433f32.entry.js} +1 -1
- package/dist/pine-core/{p-ebd0bff2.entry.js → p-631f5bcc.entry.js} +1 -1
- package/dist/pine-core/p-717323e4.entry.js +1 -0
- package/dist/pine-core/{p-e7a95a49.system.entry.js → p-719542e1.system.entry.js} +1 -1
- package/dist/pine-core/p-73f931a1.entry.js +1 -0
- package/dist/pine-core/{p-f77905aa.system.entry.js → p-884cb31d.system.entry.js} +1 -1
- package/dist/pine-core/{p-4435fff6.system.entry.js → p-8987fd45.system.entry.js} +1 -1
- package/dist/pine-core/{p-02088776.entry.js → p-8c588ca0.entry.js} +1 -1
- package/dist/pine-core/p-8e3ff75d.entry.js +1 -0
- package/dist/pine-core/{p-bd26a5e8.entry.js → p-90d5edc6.entry.js} +1 -1
- package/dist/pine-core/p-91f60173.entry.js +1 -0
- package/dist/pine-core/{p-258770cf.system.entry.js → p-9265497e.system.entry.js} +1 -1
- package/dist/pine-core/p-9713fb36.entry.js +1 -0
- package/dist/pine-core/p-99fdf70f.entry.js +1 -0
- package/dist/pine-core/{p-0a84d220.entry.js → p-9aaedded.entry.js} +1 -1
- package/dist/pine-core/p-9df5e204.entry.js +1 -0
- package/dist/pine-core/p-CuSNnuFu.system.js +1 -1
- package/dist/pine-core/p-D04W0cAO.system.js +1 -0
- package/dist/pine-core/{p-6d603d16.system.entry.js → p-acca5f7b.system.entry.js} +1 -1
- package/dist/pine-core/{p-a19cd59c.entry.js → p-aff411d0.entry.js} +1 -1
- package/dist/pine-core/{p-bb73ad66.entry.js → p-b182f806.entry.js} +1 -1
- package/dist/pine-core/{p-01aa382c.system.entry.js → p-b9d145f8.system.entry.js} +1 -1
- package/dist/pine-core/p-bdac8f2b.entry.js +1 -0
- package/dist/pine-core/{p-aa032a5e.system.entry.js → p-be9b6e63.system.entry.js} +1 -1
- package/dist/pine-core/{p-ff3de72e.entry.js → p-c483997a.entry.js} +1 -1
- package/dist/pine-core/p-c4e12f0a.entry.js +1 -0
- package/dist/pine-core/{p-e8cb76e8.entry.js → p-c97bfac9.entry.js} +1 -1
- package/dist/pine-core/{p-bd67156b.system.entry.js → p-ca4ee736.system.entry.js} +1 -1
- package/dist/pine-core/p-cccfe60f.system.entry.js +1 -0
- package/dist/pine-core/{p-c5c9ed36.system.entry.js → p-d3d69ca4.system.entry.js} +1 -1
- package/dist/pine-core/{p-f0d24298.system.entry.js → p-ea340c55.system.entry.js} +1 -1
- package/dist/pine-core/{p-88ff1604.entry.js → p-ea8f5d29.entry.js} +1 -1
- package/dist/pine-core/{p-d8570b4b.system.entry.js → p-eaf85be6.system.entry.js} +1 -1
- package/dist/pine-core/{p-fc25b956.system.entry.js → p-ecc7a531.system.entry.js} +1 -1
- package/dist/pine-core/{p-cfc52b95.system.entry.js → p-ee0e30bf.system.entry.js} +1 -1
- package/dist/pine-core/{p-e803f629.system.entry.js → p-ef13f665.system.entry.js} +1 -1
- package/dist/pine-core/{p-97d0b89e.system.entry.js → p-f3067d90.system.entry.js} +1 -1
- package/dist/pine-core/{p-JtdHT_W5.js → p-jrkGLEPe.js} +1 -1
- package/dist/pine-core/pine-core.esm.js +1 -1
- package/dist/types/components/pds-button/pds-button.d.ts +3 -4
- package/dist/types/components/pds-dropdown-menu/pds-dropdown-menu-item/pds-dropdown-menu-item.d.ts +13 -3
- package/dist/types/components/pds-modal/pds-modal-content/pds-modal-content.d.ts +2 -0
- package/dist/types/components/pds-popover/pds-popover.d.ts +43 -1
- package/dist/types/components.d.ts +43 -10
- package/dist/types/utils/truncation-tooltip.d.ts +4 -4
- package/dist/types/utils/types.d.ts +1 -0
- package/dist/vscode.html-data.json +50 -7
- package/hydrate/index.js +341 -104
- package/hydrate/index.mjs +341 -104
- package/package.json +2 -2
- package/dist/esm-es5/truncation-tooltip-DRXsdKk1.js +0 -1
- package/dist/pine-core/p-153ba77b.entry.js +0 -1
- package/dist/pine-core/p-645a482b.system.entry.js +0 -1
- package/dist/pine-core/p-74a05bcc.entry.js +0 -1
- package/dist/pine-core/p-7bf6563a.system.entry.js +0 -1
- package/dist/pine-core/p-80a698ae.entry.js +0 -1
- package/dist/pine-core/p-82cf4ec6.entry.js +0 -1
- package/dist/pine-core/p-8d292b48.entry.js +0 -1
- package/dist/pine-core/p-92ae6082.entry.js +0 -1
- package/dist/pine-core/p-993d1043.entry.js +0 -1
- package/dist/pine-core/p-a787b34a.system.entry.js +0 -1
- package/dist/pine-core/p-b69f04b7.entry.js +0 -1
- package/dist/pine-core/p-beb23781.entry.js +0 -1
- package/dist/pine-core/p-bf5887e8.system.entry.js +0 -1
- package/dist/pine-core/p-c36b490e.entry.js +0 -1
- package/dist/pine-core/p-ca0d48e8.entry.js +0 -1
- package/dist/pine-core/p-f474d7de.entry.js +0 -1
- package/dist/pine-core/p-qhdoK1Jp.system.js +0 -1
- /package/dist/esm-es5/{index-BJXk71tO.js → index-BWDu62Mo.js} +0 -0
- /package/dist/pine-core/{p-BJXk71tO.js → p-BWDu62Mo.js} +0 -0
- /package/dist/pine-core/{p-n3_ytl_p.system.js → p-ClDiSG97.system.js} +0 -0
|
@@ -4,8 +4,12 @@ import { restoreReflectedDefault } from "../../utils/reflected-attribute-default
|
|
|
4
4
|
import { setAttributesIfChanged } from "../../utils/attributes";
|
|
5
5
|
import { cssEscape } from "../../utils/css";
|
|
6
6
|
import { limitRestores } from "../../utils/keep-hydrated";
|
|
7
|
-
/** Open
|
|
8
|
-
const
|
|
7
|
+
/** Open popovers that close on Escape, in the order they opened: Escape goes to the last one it applies to. */
|
|
8
|
+
const popoversTakingEscape = [];
|
|
9
|
+
/** Hovering the trigger waits this long before opening, so a pointer passing over it doesn't open it. */
|
|
10
|
+
const HOVER_OPEN_DELAY_MS = 120;
|
|
11
|
+
/** Leaving the trigger and panel waits this long before closing, which covers the gap between them. */
|
|
12
|
+
const HOVER_CLOSE_DELAY_MS = 200;
|
|
9
13
|
/** The focused element, followed down through shadow roots to the control that has focus. */
|
|
10
14
|
function deepActiveElement() {
|
|
11
15
|
var _a;
|
|
@@ -66,11 +70,29 @@ export class PdsPopover {
|
|
|
66
70
|
* Timestamp when popover was opened (for preventing immediate close)
|
|
67
71
|
*/
|
|
68
72
|
this.openTimestamp = 0;
|
|
73
|
+
/**
|
|
74
|
+
* Set while hover holds the popover open, until a click pins it or it closes
|
|
75
|
+
*/
|
|
76
|
+
this.hoverOpened = false;
|
|
77
|
+
/**
|
|
78
|
+
* Set when the pointer left while focus was in the panel, so focus leaving it closes it instead
|
|
79
|
+
*/
|
|
80
|
+
this.closeWhenFocusLeaves = false;
|
|
81
|
+
/**
|
|
82
|
+
* How far the pointer was from the panel at its last move after leaving the trigger
|
|
83
|
+
*/
|
|
84
|
+
this.panelDistance = Infinity;
|
|
69
85
|
/**
|
|
70
86
|
* Determines the action that triggers the popover. For manual popovers, the consumer is responsible for toggling this value.
|
|
71
87
|
* @defaultValue "show"
|
|
72
88
|
*/
|
|
73
89
|
this.popoverTargetAction = 'show';
|
|
90
|
+
/**
|
|
91
|
+
* Determines how the popover opens. With `hover`, it also opens when the pointer rests on the trigger and closes
|
|
92
|
+
* when the pointer leaves, until a click on the trigger keeps it open. Enter or Space on the trigger opens it either way.
|
|
93
|
+
* @defaultValue "click"
|
|
94
|
+
*/
|
|
95
|
+
this.openOn = 'click';
|
|
74
96
|
/**
|
|
75
97
|
* Determines the type of popover. Auto popovers can be "light dismissed" by clicking outside of the popover.
|
|
76
98
|
* Manual popovers require the consumer to handle the visibility of the popover.
|
|
@@ -81,6 +103,11 @@ export class PdsPopover {
|
|
|
81
103
|
* @defaultValue 352
|
|
82
104
|
*/
|
|
83
105
|
this.maxWidth = 352;
|
|
106
|
+
/**
|
|
107
|
+
* Sets the padding of the popover content
|
|
108
|
+
* @defaultValue "md"
|
|
109
|
+
*/
|
|
110
|
+
this.padding = 'md';
|
|
84
111
|
/**
|
|
85
112
|
* Determines the preferred position of the popover
|
|
86
113
|
* @defaultValue "right"
|
|
@@ -95,6 +122,7 @@ export class PdsPopover {
|
|
|
95
122
|
// Clean up previous trigger's event listener if it exists
|
|
96
123
|
if (this.triggerEl != null) {
|
|
97
124
|
this.triggerEl.removeEventListener('click', this.handleTriggerClick);
|
|
125
|
+
this.stopListeningForHover(this.triggerEl);
|
|
98
126
|
}
|
|
99
127
|
if (assignedElements.length > 0) {
|
|
100
128
|
// Use the first assigned element as the trigger
|
|
@@ -102,6 +130,7 @@ export class PdsPopover {
|
|
|
102
130
|
this.linkTriggerToPortal();
|
|
103
131
|
// Attach click listener to handle popover visibility
|
|
104
132
|
this.triggerEl.addEventListener('click', this.handleTriggerClick);
|
|
133
|
+
this.listenForHover(this.triggerEl);
|
|
105
134
|
}
|
|
106
135
|
else {
|
|
107
136
|
this.triggerEl = null;
|
|
@@ -128,6 +157,13 @@ export class PdsPopover {
|
|
|
128
157
|
if (!anchorWithHref) {
|
|
129
158
|
event.preventDefault();
|
|
130
159
|
}
|
|
160
|
+
if (this.openOn === 'hover' && this.popoverTargetAction !== 'hide') {
|
|
161
|
+
const heldByHover = this.hoverOpened;
|
|
162
|
+
this.pin();
|
|
163
|
+
// Pinning, not toggling: the hover before a click has already opened it.
|
|
164
|
+
if (heldByHover)
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
131
167
|
// Execute the appropriate action based on popoverTargetAction prop
|
|
132
168
|
switch (this.popoverTargetAction) {
|
|
133
169
|
case 'show':
|
|
@@ -142,6 +178,60 @@ export class PdsPopover {
|
|
|
142
178
|
break;
|
|
143
179
|
}
|
|
144
180
|
};
|
|
181
|
+
// A tap sends touch pointer events and then a click, so touch takes the click path alone.
|
|
182
|
+
this.handleHoverEnter = (event) => {
|
|
183
|
+
if (event.pointerType === 'touch')
|
|
184
|
+
return;
|
|
185
|
+
this.clearHoverTimers();
|
|
186
|
+
if (this.active)
|
|
187
|
+
return;
|
|
188
|
+
this.hoverOpenTimer = setTimeout(() => {
|
|
189
|
+
this.hoverOpenTimer = undefined;
|
|
190
|
+
if (this.active || this.portalEl == null)
|
|
191
|
+
return;
|
|
192
|
+
this.hoverOpened = true;
|
|
193
|
+
this.show();
|
|
194
|
+
}, HOVER_OPEN_DELAY_MS);
|
|
195
|
+
};
|
|
196
|
+
this.handleHoverLeave = (event) => {
|
|
197
|
+
if (event.pointerType === 'touch')
|
|
198
|
+
return;
|
|
199
|
+
this.clearHoverTimers();
|
|
200
|
+
if (!this.hoverOpened)
|
|
201
|
+
return;
|
|
202
|
+
this.hoverCloseTimer = setTimeout(this.closeFromHover, HOVER_CLOSE_DELAY_MS);
|
|
203
|
+
if (event.currentTarget !== this.triggerEl)
|
|
204
|
+
return;
|
|
205
|
+
this.panelDistance = this.distanceToPanel(event);
|
|
206
|
+
document.addEventListener('pointermove', this.handleMoveTowardPanel);
|
|
207
|
+
};
|
|
208
|
+
// A slow diagonal from the trigger to a panel shorter than it runs beside the panel for longer
|
|
209
|
+
// than the close delay, so each move that brings the pointer closer starts the delay again.
|
|
210
|
+
this.handleMoveTowardPanel = (event) => {
|
|
211
|
+
const distance = this.distanceToPanel(event);
|
|
212
|
+
if (distance < this.panelDistance) {
|
|
213
|
+
clearTimeout(this.hoverCloseTimer);
|
|
214
|
+
this.hoverCloseTimer = setTimeout(this.closeFromHover, HOVER_CLOSE_DELAY_MS);
|
|
215
|
+
}
|
|
216
|
+
this.panelDistance = distance;
|
|
217
|
+
};
|
|
218
|
+
this.handleHoverFocusOut = (event) => {
|
|
219
|
+
if (!this.closeWhenFocusLeaves || containsComposed(this.portalEl, event.relatedTarget))
|
|
220
|
+
return;
|
|
221
|
+
this.closeWhenFocusLeaves = false;
|
|
222
|
+
this.hoverCloseTimer = setTimeout(this.closeFromHover, HOVER_CLOSE_DELAY_MS);
|
|
223
|
+
};
|
|
224
|
+
this.closeFromHover = () => {
|
|
225
|
+
this.clearHoverTimers();
|
|
226
|
+
if (!this.hoverOpened)
|
|
227
|
+
return;
|
|
228
|
+
// Content shown on hover stays while focus is in it (WCAG 1.4.13).
|
|
229
|
+
if (containsComposed(this.portalEl, deepActiveElement())) {
|
|
230
|
+
this.closeWhenFocusLeaves = true;
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
this.hide();
|
|
234
|
+
};
|
|
145
235
|
/** The focus style copied into a shadow root the panel opened in, which `document.head` can't reach. */
|
|
146
236
|
this.shadowFocusStyle = null;
|
|
147
237
|
/** The dialog the panel was opened in, closed along with it. */
|
|
@@ -163,6 +253,32 @@ export class PdsPopover {
|
|
|
163
253
|
}
|
|
164
254
|
};
|
|
165
255
|
}
|
|
256
|
+
openOnChanged() {
|
|
257
|
+
this.pin();
|
|
258
|
+
this.stopListeningForHover(this.triggerEl);
|
|
259
|
+
this.stopListeningForHover(this.portalEl);
|
|
260
|
+
// Out of the page, connectedCallback binds them when it comes back.
|
|
261
|
+
if (!this.isComponentMounted)
|
|
262
|
+
return;
|
|
263
|
+
this.listenForHover(this.triggerEl);
|
|
264
|
+
this.listenForHover(this.portalEl);
|
|
265
|
+
}
|
|
266
|
+
applyPadding() {
|
|
267
|
+
if (this.portalEl != null)
|
|
268
|
+
this.portalEl.style.padding = this.paddingToken();
|
|
269
|
+
}
|
|
270
|
+
paddingToken() {
|
|
271
|
+
switch (this.padding) {
|
|
272
|
+
case 'none':
|
|
273
|
+
return 'var(--pine-dimension-none)';
|
|
274
|
+
case 'xs':
|
|
275
|
+
return 'var(--pine-dimension-xs)';
|
|
276
|
+
case 'sm':
|
|
277
|
+
return 'var(--pine-dimension-sm)';
|
|
278
|
+
default:
|
|
279
|
+
return 'var(--pine-dimension-md)';
|
|
280
|
+
}
|
|
281
|
+
}
|
|
166
282
|
restorePlacementDefault(newValue) {
|
|
167
283
|
this.placement = restoreReflectedDefault(this.el, 'placement', newValue, 'right');
|
|
168
284
|
}
|
|
@@ -213,6 +329,48 @@ export class PdsPopover {
|
|
|
213
329
|
// Skips values already in place, so the trigger observer's own callback doesn't loop.
|
|
214
330
|
return setAttributesIfChanged(this.triggerEl, { 'aria-expanded': String(this.active), 'aria-controls': this.portalEl.id });
|
|
215
331
|
}
|
|
332
|
+
listenForHover(el) {
|
|
333
|
+
if (this.openOn !== 'hover' || el == null)
|
|
334
|
+
return;
|
|
335
|
+
el.addEventListener('pointerenter', this.handleHoverEnter);
|
|
336
|
+
el.addEventListener('pointerleave', this.handleHoverLeave);
|
|
337
|
+
el.addEventListener('focusout', this.handleHoverFocusOut);
|
|
338
|
+
}
|
|
339
|
+
stopListeningForHover(el) {
|
|
340
|
+
if (el == null)
|
|
341
|
+
return;
|
|
342
|
+
el.removeEventListener('pointerenter', this.handleHoverEnter);
|
|
343
|
+
el.removeEventListener('pointerleave', this.handleHoverLeave);
|
|
344
|
+
el.removeEventListener('focusout', this.handleHoverFocusOut);
|
|
345
|
+
}
|
|
346
|
+
distanceToPanel({ clientX, clientY }) {
|
|
347
|
+
const panel = this.portalEl.getBoundingClientRect();
|
|
348
|
+
return Math.hypot(Math.max(panel.left - clientX, 0, clientX - panel.right), Math.max(panel.top - clientY, 0, clientY - panel.bottom));
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Keeps a popover that hover opened open, closing from then on as one opened by a click does. A
|
|
352
|
+
* manual one gives up Escape again, which it took only while hover held it.
|
|
353
|
+
*/
|
|
354
|
+
pin() {
|
|
355
|
+
var _a;
|
|
356
|
+
this.clearHoverTimers();
|
|
357
|
+
if (!this.hoverOpened)
|
|
358
|
+
return;
|
|
359
|
+
this.hoverOpened = false;
|
|
360
|
+
if (this.popoverType === 'auto')
|
|
361
|
+
return;
|
|
362
|
+
this.forgetOpen();
|
|
363
|
+
(_a = this.portalEl) === null || _a === void 0 ? void 0 : _a.removeAttribute('data-pds-popover-open');
|
|
364
|
+
document.removeEventListener('keydown', this.boundEscapeKeyHandler);
|
|
365
|
+
}
|
|
366
|
+
clearHoverTimers() {
|
|
367
|
+
clearTimeout(this.hoverOpenTimer);
|
|
368
|
+
clearTimeout(this.hoverCloseTimer);
|
|
369
|
+
this.hoverOpenTimer = undefined;
|
|
370
|
+
this.hoverCloseTimer = undefined;
|
|
371
|
+
this.closeWhenFocusLeaves = false;
|
|
372
|
+
document.removeEventListener('pointermove', this.handleMoveTowardPanel);
|
|
373
|
+
}
|
|
216
374
|
// componentDidLoad doesn't run again when a popover comes back, so rebuild whatever
|
|
217
375
|
// disconnectedCallback tore down. Each step is a no-op when nothing was.
|
|
218
376
|
connectedCallback() {
|
|
@@ -222,6 +380,7 @@ export class PdsPopover {
|
|
|
222
380
|
this.isComponentMounted = true;
|
|
223
381
|
this.createPortal();
|
|
224
382
|
(_a = this.triggerEl) === null || _a === void 0 ? void 0 : _a.addEventListener('click', this.handleTriggerClick);
|
|
383
|
+
this.listenForHover(this.triggerEl);
|
|
225
384
|
this.observeTrigger();
|
|
226
385
|
this.linkTriggerToPortal();
|
|
227
386
|
// Still open after a move: the trigger moved, so the portal follows it, into the dialog it
|
|
@@ -256,6 +415,7 @@ export class PdsPopover {
|
|
|
256
415
|
if (this.triggerEl != null) {
|
|
257
416
|
this.triggerEl.removeEventListener('click', this.handleTriggerClick);
|
|
258
417
|
}
|
|
418
|
+
this.stopListeningForHover(this.triggerEl);
|
|
259
419
|
(_a = this.triggerObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
260
420
|
this.triggerObserver = null;
|
|
261
421
|
// Clean up all event listeners
|
|
@@ -264,6 +424,8 @@ export class PdsPopover {
|
|
|
264
424
|
document.removeEventListener('submit', this.handleSubmitFromPanel, true);
|
|
265
425
|
// Clear any pending debounce timers
|
|
266
426
|
this.clearDebounceTimers();
|
|
427
|
+
this.clearHoverTimers();
|
|
428
|
+
this.hoverOpened = false;
|
|
267
429
|
// Remove portal from DOM
|
|
268
430
|
this.removePortal();
|
|
269
431
|
}
|
|
@@ -297,7 +459,7 @@ export class PdsPopover {
|
|
|
297
459
|
this.portalEl.style.borderRadius = 'var(--pine-dimension-125)';
|
|
298
460
|
this.portalEl.style.boxShadow = 'var(--pine-box-shadow-200)';
|
|
299
461
|
this.portalEl.style.margin = 'var(--pine-dimension-none)';
|
|
300
|
-
this.portalEl.style.padding =
|
|
462
|
+
this.portalEl.style.padding = this.paddingToken();
|
|
301
463
|
// Generate unique ID
|
|
302
464
|
if (!this.componentId) {
|
|
303
465
|
(_a = this.generatedPortalId) !== null && _a !== void 0 ? _a : (this.generatedPortalId = `pds-popover-portal-${PdsPopover.instanceCounter++}`);
|
|
@@ -311,6 +473,7 @@ export class PdsPopover {
|
|
|
311
473
|
// Add global focus styles to match Pine design system
|
|
312
474
|
// This is done after appending to ensure it's part of the document and can access CSS variables
|
|
313
475
|
this.addPortalFocusStyles();
|
|
476
|
+
this.listenForHover(this.portalEl);
|
|
314
477
|
}
|
|
315
478
|
/**
|
|
316
479
|
* Adds Pine design system focus styles and dark mode border to the portal element
|
|
@@ -438,8 +601,8 @@ export class PdsPopover {
|
|
|
438
601
|
// Update portal content with latest slot content
|
|
439
602
|
this.updatePortalContent();
|
|
440
603
|
// Show portal. The attribute tells a modal around it that this popover takes Escape first; only
|
|
441
|
-
// an auto popover listens for Escape.
|
|
442
|
-
if (this.popoverType === 'auto')
|
|
604
|
+
// an auto popover, or one hover opened, listens for Escape.
|
|
605
|
+
if (this.popoverType === 'auto' || this.hoverOpened)
|
|
443
606
|
this.portalEl.setAttribute('data-pds-popover-open', '');
|
|
444
607
|
this.portalEl.style.display = 'block';
|
|
445
608
|
this.portalEl.style.opacity = '1';
|
|
@@ -453,11 +616,16 @@ export class PdsPopover {
|
|
|
453
616
|
// Add scroll and resize listeners for repositioning (always)
|
|
454
617
|
this.addScrollAndResizeListeners();
|
|
455
618
|
document.addEventListener('submit', this.handleSubmitFromPanel, true);
|
|
456
|
-
// Add document listeners for light dismiss and escape key (auto type only)
|
|
619
|
+
// Add document listeners for light dismiss and escape key (auto type only), or for the escape
|
|
620
|
+
// key alone while hover holds a manual popover open
|
|
457
621
|
if (this.popoverType === 'auto') {
|
|
458
|
-
|
|
622
|
+
popoversTakingEscape.push(this);
|
|
459
623
|
this.addLightDismissListeners();
|
|
460
624
|
}
|
|
625
|
+
else if (this.hoverOpened) {
|
|
626
|
+
popoversTakingEscape.push(this);
|
|
627
|
+
document.addEventListener('keydown', this.boundEscapeKeyHandler);
|
|
628
|
+
}
|
|
461
629
|
// Emit open event
|
|
462
630
|
this.pdsPopoverOpen.emit({
|
|
463
631
|
componentId: this.componentId,
|
|
@@ -468,9 +636,11 @@ export class PdsPopover {
|
|
|
468
636
|
* Closes the popover programmatically
|
|
469
637
|
*/
|
|
470
638
|
async hide() {
|
|
639
|
+
this.clearHoverTimers();
|
|
471
640
|
if (!this.active || !this.portalEl)
|
|
472
641
|
return;
|
|
473
642
|
this.active = false;
|
|
643
|
+
this.hoverOpened = false;
|
|
474
644
|
this.unwatchDialogClose();
|
|
475
645
|
// Restoring the content drops its focus to the body, so check where focus is first. In a
|
|
476
646
|
// shadow root, document.activeElement is only its host.
|
|
@@ -549,9 +719,9 @@ export class PdsPopover {
|
|
|
549
719
|
this.portalEl.style.border = root instanceof ShadowRoot && closest('[data-theme="dark"]', this.el) ? 'var(--pine-border)' : '';
|
|
550
720
|
}
|
|
551
721
|
forgetOpen() {
|
|
552
|
-
const index =
|
|
722
|
+
const index = popoversTakingEscape.indexOf(this);
|
|
553
723
|
if (index >= 0)
|
|
554
|
-
|
|
724
|
+
popoversTakingEscape.splice(index, 1);
|
|
555
725
|
}
|
|
556
726
|
/**
|
|
557
727
|
* Whether an Escape is this popover's. One from a dialog the popover isn't in belongs to that
|
|
@@ -660,7 +830,7 @@ export class PdsPopover {
|
|
|
660
830
|
return;
|
|
661
831
|
// Like the native Popover API, Escape closes only the top popover: the last one opened that
|
|
662
832
|
// it applies to. Every open popover hears it, so each checks whether it's that one.
|
|
663
|
-
const top = [...
|
|
833
|
+
const top = [...popoversTakingEscape].reverse().find(popover => popover.takesEscapeFrom(event));
|
|
664
834
|
if (top !== this)
|
|
665
835
|
return;
|
|
666
836
|
// Take the key, so the dialog or modal around it doesn't close too.
|
|
@@ -785,7 +955,7 @@ export class PdsPopover {
|
|
|
785
955
|
}, 16); // ~1 frame at 60fps
|
|
786
956
|
}
|
|
787
957
|
render() {
|
|
788
|
-
return (h(Host, { key: '
|
|
958
|
+
return (h(Host, { key: 'e48b897acdc9e89f2e6b1449e7a358da7da1060c', id: this.componentId }, h("span", { key: 'b83b2c234b07703c2c850a9991c94939ed2fdaf7', class: "pds-popover__trigger-wrapper" }, h("slot", { key: '0a7f7829ee445fd57cf824ebee1409b3c571f983', name: "trigger", onSlotchange: this.handleTriggerSlotChange })), h("div", { key: '8c1fe2d4d7c4342b4bd5eb4c56e596f17b4e14fa', class: "pds-popover__content-slot-wrapper" }, h("slot", { key: '4ccfce1f335acbc436f7942e497f5d360f849d48', onSlotchange: this.handleContentSlotChange }))));
|
|
789
959
|
}
|
|
790
960
|
static get is() { return "pds-popover"; }
|
|
791
961
|
static get encapsulation() { return "shadow"; }
|
|
@@ -824,6 +994,29 @@ export class PdsPopover {
|
|
|
824
994
|
"attribute": "popover-target-action",
|
|
825
995
|
"defaultValue": "'show'"
|
|
826
996
|
},
|
|
997
|
+
"openOn": {
|
|
998
|
+
"type": "string",
|
|
999
|
+
"mutable": false,
|
|
1000
|
+
"complexType": {
|
|
1001
|
+
"original": "'click' | 'hover'",
|
|
1002
|
+
"resolved": "\"click\" | \"hover\"",
|
|
1003
|
+
"references": {}
|
|
1004
|
+
},
|
|
1005
|
+
"required": false,
|
|
1006
|
+
"optional": true,
|
|
1007
|
+
"docs": {
|
|
1008
|
+
"tags": [{
|
|
1009
|
+
"name": "defaultValue",
|
|
1010
|
+
"text": "\"click\""
|
|
1011
|
+
}],
|
|
1012
|
+
"text": "Determines how the popover opens. With `hover`, it also opens when the pointer rests on the trigger and closes\nwhen the pointer leaves, until a click on the trigger keeps it open. Enter or Space on the trigger opens it either way."
|
|
1013
|
+
},
|
|
1014
|
+
"getter": false,
|
|
1015
|
+
"setter": false,
|
|
1016
|
+
"reflect": false,
|
|
1017
|
+
"attribute": "open-on",
|
|
1018
|
+
"defaultValue": "'click'"
|
|
1019
|
+
},
|
|
827
1020
|
"popoverType": {
|
|
828
1021
|
"type": "string",
|
|
829
1022
|
"mutable": false,
|
|
@@ -886,6 +1079,36 @@ export class PdsPopover {
|
|
|
886
1079
|
"attribute": "max-width",
|
|
887
1080
|
"defaultValue": "352"
|
|
888
1081
|
},
|
|
1082
|
+
"padding": {
|
|
1083
|
+
"type": "string",
|
|
1084
|
+
"mutable": false,
|
|
1085
|
+
"complexType": {
|
|
1086
|
+
"original": "PopoverPaddingType",
|
|
1087
|
+
"resolved": "\"md\" | \"none\" | \"sm\" | \"xs\"",
|
|
1088
|
+
"references": {
|
|
1089
|
+
"PopoverPaddingType": {
|
|
1090
|
+
"location": "import",
|
|
1091
|
+
"path": "@utils/types",
|
|
1092
|
+
"id": "src/utils/types.ts::PopoverPaddingType",
|
|
1093
|
+
"referenceLocation": "PopoverPaddingType"
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
},
|
|
1097
|
+
"required": false,
|
|
1098
|
+
"optional": true,
|
|
1099
|
+
"docs": {
|
|
1100
|
+
"tags": [{
|
|
1101
|
+
"name": "defaultValue",
|
|
1102
|
+
"text": "\"md\""
|
|
1103
|
+
}],
|
|
1104
|
+
"text": "Sets the padding of the popover content"
|
|
1105
|
+
},
|
|
1106
|
+
"getter": false,
|
|
1107
|
+
"setter": false,
|
|
1108
|
+
"reflect": false,
|
|
1109
|
+
"attribute": "padding",
|
|
1110
|
+
"defaultValue": "'md'"
|
|
1111
|
+
},
|
|
889
1112
|
"placement": {
|
|
890
1113
|
"type": "string",
|
|
891
1114
|
"mutable": true,
|
|
@@ -1028,6 +1251,12 @@ export class PdsPopover {
|
|
|
1028
1251
|
static get elementRef() { return "el"; }
|
|
1029
1252
|
static get watchers() {
|
|
1030
1253
|
return [{
|
|
1254
|
+
"propName": "openOn",
|
|
1255
|
+
"methodName": "openOnChanged"
|
|
1256
|
+
}, {
|
|
1257
|
+
"propName": "padding",
|
|
1258
|
+
"methodName": "applyPadding"
|
|
1259
|
+
}, {
|
|
1031
1260
|
"propName": "placement",
|
|
1032
1261
|
"methodName": "restorePlacementDefault"
|
|
1033
1262
|
}];
|
|
@@ -6,9 +6,18 @@ export default {
|
|
|
6
6
|
args: {
|
|
7
7
|
popoverTargetAction: 'toggle',
|
|
8
8
|
popoverType: 'auto',
|
|
9
|
+
openOn: 'click',
|
|
9
10
|
placement: 'bottom-start',
|
|
11
|
+
padding: 'md',
|
|
10
12
|
componentId: 'popover-playground',
|
|
11
13
|
},
|
|
14
|
+
argTypes: {
|
|
15
|
+
padding: {
|
|
16
|
+
control: { type: 'select' },
|
|
17
|
+
options: ['none', 'xs', 'sm', 'md'],
|
|
18
|
+
},
|
|
19
|
+
openOn: { control: 'inline-radio', options: ['click', 'hover'] },
|
|
20
|
+
},
|
|
12
21
|
component: 'pds-popover',
|
|
13
22
|
parameters: {},
|
|
14
23
|
title: 'components/Popover'
|
|
@@ -19,8 +28,10 @@ const BaseTemplate = (args) => html`
|
|
|
19
28
|
component-id=${args.componentId}
|
|
20
29
|
popover-target-action=${args.popoverTargetAction}
|
|
21
30
|
popover-type=${args.popoverType}
|
|
31
|
+
open-on=${args.openOn}
|
|
22
32
|
placement=${args.placement}
|
|
23
33
|
.maxWidth=${args.maxWidth}
|
|
34
|
+
padding=${args.padding}
|
|
24
35
|
>
|
|
25
36
|
<pds-button slot="trigger">Show popover</pds-button>
|
|
26
37
|
<p>This is popover content that can be configured using the controls below.</p>
|
|
@@ -84,3 +95,23 @@ export const WithContent = (args) => html`
|
|
|
84
95
|
WithContent.args = {
|
|
85
96
|
componentId: 'popover-rich'
|
|
86
97
|
};
|
|
98
|
+
|
|
99
|
+
export const OpenOnHover = (args) => html`
|
|
100
|
+
<pds-popover
|
|
101
|
+
component-id=${args.componentId || 'popover-hover'}
|
|
102
|
+
open-on="hover"
|
|
103
|
+
popover-target-action=${args.popoverTargetAction}
|
|
104
|
+
popover-type=${args.popoverType}
|
|
105
|
+
placement=${args.placement}
|
|
106
|
+
.maxWidth=${args.maxWidth}
|
|
107
|
+
>
|
|
108
|
+
<pds-button slot="trigger" variant="secondary">Hover for details</pds-button>
|
|
109
|
+
<pds-box direction="column" gap="xs" fit="true">
|
|
110
|
+
<pds-text tag="h3" size="md" weight="semibold">Project summary</pds-text>
|
|
111
|
+
<pds-text tag="p" size="sm" color="secondary">Rest the pointer on the trigger to preview supporting details. Click the trigger to keep this open while you read.</pds-text>
|
|
112
|
+
</pds-box>
|
|
113
|
+
</pds-popover>
|
|
114
|
+
`;
|
|
115
|
+
OpenOnHover.args = {
|
|
116
|
+
componentId: 'popover-hover'
|
|
117
|
+
};
|
|
@@ -101,11 +101,11 @@ export class PdsRadio {
|
|
|
101
101
|
const renderLabelAndMessages = () => [
|
|
102
102
|
h("label", { htmlFor: this.componentId, key: `${this.componentId}-label` }, h("input", { key: 'ccd618855831bcee309e815f2cd2712fd4e8fe1f', "aria-describedby": assignDescription(this.componentId, this.invalid, this.helperMessage, this.errorMessage), "aria-invalid": this.invalid ? "true" : undefined, type: "radio", id: this.componentId, name: this.name, value: this.value, checked: this.checked, required: this.required, disabled: this.disabled, onChange: this.handleRadioChange, class: this.hasImage() ? 'visually-hidden' : '' }), h("span", { key: '2e372a880c28f48fb804bac2518208082c141fad', class: this.hideLabel ? 'visually-hidden' : '' }, this.label)),
|
|
103
103
|
this.helperMessage && (h("div", { key: `${this.componentId}-helper`, class: 'pds-radio__message', id: messageId(this.componentId, 'helper') }, this.helperMessage)),
|
|
104
|
-
this.errorMessage && (h("div", { key: `${this.componentId}-error`, class: `pds-radio__message pds-radio__message--error`, id: messageId(this.componentId, 'error'), "aria-live": "assertive" }, h("pds-icon", { key: '
|
|
104
|
+
this.errorMessage && (h("div", { key: `${this.componentId}-error`, class: `pds-radio__message pds-radio__message--error`, id: messageId(this.componentId, 'error'), "aria-live": "assertive" }, h("pds-icon", { key: '08e7a2319eddc1d314ee9dddd51a5ce88cd4ae48', "aria-hidden": "true", icon: danger, size: "small" }), this.errorMessage))
|
|
105
105
|
];
|
|
106
106
|
const hostClass = this.classNames();
|
|
107
107
|
this.hostKeeper.record(hostClass);
|
|
108
|
-
return (h(Host, { key: '
|
|
108
|
+
return (h(Host, { key: '351376552abee90f50c3aceb03ecf8a81ae1b82b', class: hostClass }, this.hasImage() && (h("div", { key: 'fd85fd36b2ebd99b12c3bb2a13cf3d3e3c26530f', class: "pds-radio__image-container", part: "image-container" }, h("slot", { key: 'abe75dbe38d29340b805f70861b084c1b3836be9', name: "image", onSlotchange: () => (this._hasImage = this.hasImageSlot()) }))), this.hasImage() ? (h("div", { class: "pds-radio__content-wrapper" }, renderLabelAndMessages())) : (renderLabelAndMessages())));
|
|
109
109
|
}
|
|
110
110
|
static get is() { return "pds-radio"; }
|
|
111
111
|
static get encapsulation() { return "scoped"; }
|
|
@@ -167,7 +167,7 @@ export class PdsRadioGroup {
|
|
|
167
167
|
'pds-radio-group__radios': true,
|
|
168
168
|
'pds-radio-group__radios--row': this.direction === 'row',
|
|
169
169
|
'pds-radio-group__radios--column': this.direction === 'column',
|
|
170
|
-
} }, h("slot", { key: 'd88dde3c631e25c01bc7b6d3ef5d517255fabd1a', onSlotchange: () => this.updateChildRadios() })), this.helperMessage && (h("div", { key: 'a229214ed01663b0fc34f35e27c7148b4eb412ab', class: "pds-radio-group__message", id: messageId(this._groupId, 'helper') }, this.helperMessage)), this.errorMessage && (h("div", { key: 'dc092f2e6dbef0cb369cf00a6eccf9a095a0313d', class: "pds-radio-group__message pds-radio-group__message--error", id: messageId(this._groupId, 'error'), "aria-live": "assertive" }, h("pds-icon", { key: '
|
|
170
|
+
} }, h("slot", { key: 'd88dde3c631e25c01bc7b6d3ef5d517255fabd1a', onSlotchange: () => this.updateChildRadios() })), this.helperMessage && (h("div", { key: 'a229214ed01663b0fc34f35e27c7148b4eb412ab', class: "pds-radio-group__message", id: messageId(this._groupId, 'helper') }, this.helperMessage)), this.errorMessage && (h("div", { key: 'dc092f2e6dbef0cb369cf00a6eccf9a095a0313d', class: "pds-radio-group__message pds-radio-group__message--error", id: messageId(this._groupId, 'error'), "aria-live": "assertive" }, h("pds-icon", { key: '83b0129d3d45b74ef1f53acc923387b2de7f079b', "aria-hidden": "true", icon: danger, size: "small" }), this.errorMessage))));
|
|
171
171
|
}
|
|
172
172
|
static get is() { return "pds-radio-group"; }
|
|
173
173
|
static get encapsulation() { return "scoped"; }
|
|
@@ -115,7 +115,7 @@ export class PdsSwitch {
|
|
|
115
115
|
this.hostKeeper.record(hostClass, {}, { 'aria-disabled': ariaDisabled });
|
|
116
116
|
return (h(Host, { key: 'b8bd2870be101081aa8a65cdee45397bc4c21435', class: hostClass, "aria-disabled": ariaDisabled }, h("label", { key: '1e223f22f7fc6c576098353ad67dc11500def8b4', htmlFor: this.componentId }, h("input", Object.assign({ key: 'edf59869e165a65b97465ea9de06f7ea82fbc9a6', "aria-describedby": assignDescription(this.componentId, this.invalid, this.helperMessage, this.errorMessage), "aria-invalid": this.invalid ? "true" : undefined, checked: this.checked, class: "pds-switch__input", disabled: this.disabled, id: this.componentId, name: this.name ? this.name : this.componentId, onChange: this.onSwitchUpdate, required: this.required, type: "checkbox", value: this.value }, this.inheritedAttributes)), h("span", { key: '1c252b9455471069f8c6ea6c13f2e88c99308b41', class: this.hideLabel ? 'visually-hidden' : '' }, h("slot", { key: 'ce0d471918bd3018f5e55d0d1e6c5c2247790f81', name: "label", onSlotchange: this.updateHasLabelSlot }), !this.hasLabelSlot && this.label)), this.helperMessage &&
|
|
117
117
|
h("div", { key: '64874b15403f1f42344715ac34febdfb8d94042a', class: `pds-switch__message`, id: messageId(this.componentId, 'helper') }, this.helperMessage), this.errorMessage &&
|
|
118
|
-
h("div", { key: '560ea486859124bb0ac2f75ab4bd34b0bca7efbc', class: `pds-switch__message pds-switch__message--error`, id: messageId(this.componentId, 'error'), "aria-live": "assertive" }, h("pds-icon", { key: '
|
|
118
|
+
h("div", { key: '560ea486859124bb0ac2f75ab4bd34b0bca7efbc', class: `pds-switch__message pds-switch__message--error`, id: messageId(this.componentId, 'error'), "aria-live": "assertive" }, h("pds-icon", { key: '2ae8dc876745af26fa2418f2265248aeb8f97a2b', "aria-hidden": "true", icon: danger, size: "small" }), this.errorMessage)));
|
|
119
119
|
}
|
|
120
120
|
static get is() { return "pds-switch"; }
|
|
121
121
|
static get encapsulation() { return "shadow"; }
|
|
@@ -203,7 +203,7 @@ export class PdsTableHeadCell {
|
|
|
203
203
|
this.tableRef.fixedColumn &&
|
|
204
204
|
this.tableRef.selectable
|
|
205
205
|
? { '--fixed-cell-position': '40px' }
|
|
206
|
-
: {} }, h("slot", { key: '96084d87a34d7b601a8e8325f344f1fe6601204e' }), this.sortable && this.isActive && (h("pds-icon", { key: '
|
|
206
|
+
: {} }, h("slot", { key: '96084d87a34d7b601a8e8325f344f1fe6601204e' }), this.sortable && this.isActive && (h("pds-icon", { key: '79606519d810dc9882a91cbc3b6a199457086631', icon: this.sortingDirection === 'asc' ? upSmall : downSmall, part: "sort-icon", "aria-hidden": "true" }))));
|
|
207
207
|
}
|
|
208
208
|
static get is() { return "pds-table-head-cell"; }
|
|
209
209
|
static get encapsulation() { return "shadow"; }
|
|
@@ -488,7 +488,7 @@ const TruncateTemplate = (args) => html`
|
|
|
488
488
|
</pds-table-row>
|
|
489
489
|
</pds-table-body>
|
|
490
490
|
</pds-table>
|
|
491
|
-
<pds-text tag="p" size="xs" color="secondary" gutter="sm">Hover over truncated
|
|
491
|
+
<pds-text tag="p" size="xs" color="secondary" gutter="sm">Hover over or tab to a truncated cell to see the full content in a tooltip.</pds-text>`;
|
|
492
492
|
|
|
493
493
|
export const Truncate = TruncateTemplate.bind();
|
|
494
494
|
Truncate.args = {
|
|
@@ -113,7 +113,7 @@ const TruncateTemplate = (args) => html`
|
|
|
113
113
|
${args.slot}
|
|
114
114
|
</pds-text>
|
|
115
115
|
</div>
|
|
116
|
-
<pds-text tag="p" size="xs" color="secondary" gutter="sm">Hover over the truncated text above to see the full content in a tooltip.</pds-text>`;
|
|
116
|
+
<pds-text tag="p" size="xs" color="secondary" gutter="sm">Hover over or tab to the truncated text above to see the full content in a tooltip.</pds-text>`;
|
|
117
117
|
|
|
118
118
|
export const Truncate = TruncateTemplate.bind();
|
|
119
119
|
Truncate.args = {
|
|
@@ -309,7 +309,7 @@ export class PdsTextarea {
|
|
|
309
309
|
return (h(Host, { key: '5933dab0c3cd25b1cf2f6851ece8e8064bc7f3b9', "aria-disabled": this.disabled ? 'true' : null, "aria-readonly": this.readonly ? 'true' : null, "has-action": this.hasAction && !this.hideLabel ? 'true' : null }, h("div", { key: '4f1752514d8e5b0f0e3439515cb9e5f043607da1', class: "pds-textarea" }, this.label &&
|
|
310
310
|
h("div", { key: 'd4e6df0b381d781b70eeae72ff2f0e9428c0d901', class: "pds-textarea__label-wrapper" }, h("label", { key: '747d82067eb571d02840cfd981865821099f288b', htmlFor: this.componentId }, h("span", { key: 'bfab6e8ede66d0169dd020b7dd97e125aba417b0', class: this.hideLabel ? 'visually-hidden' : '' }, this.label)), !this.hideLabel && this.renderAction()), h("div", { key: 'a18611c03270e7491c1af69f931419c832192c06', class: "pds-textarea__field-wrapper" }, h("textarea", Object.assign({ key: '868382c7b04a4e59c0daa9d98afcdc9048f6224f', ref: (el) => this.nativeTextarea = el, "aria-describedby": assignDescription(this.componentId, this.invalid, this.helperMessage, this.errorMessage), "aria-invalid": this.invalid ? "true" : undefined, autocomplete: this.autocomplete, class: this.textareaClassNames(), disabled: this.disabled, id: this.componentId, maxlength: this.maxLength, name: this.name, placeholder: this.placeholder, readOnly: this.readonly, required: this.required, rows: this.rows, onBlur: this.onBlur, onChange: this.onTextareaChange, onFocus: this.onFocus, onInput: this.onInput, onKeyDown: this.onKeyDown }, this.inheritedAttributes), value), this.renderCharacterCounter()), this.helperMessage &&
|
|
311
311
|
h("p", { key: 'dcb36f21443d2a782c25b7c29c4ce6215f3b212b', class: "pds-textarea__helper-message", id: messageId(this.componentId, 'helper') }, this.helperMessage), this.invalid &&
|
|
312
|
-
h("p", { key: 'be30fb1a38453296e26b775955389c0ec569df67', "aria-live": "assertive", class: "pds-textarea__error-message", id: messageId(this.componentId, 'error') }, h("pds-icon", { key: '
|
|
312
|
+
h("p", { key: 'be30fb1a38453296e26b775955389c0ec569df67', "aria-live": "assertive", class: "pds-textarea__error-message", id: messageId(this.componentId, 'error') }, h("pds-icon", { key: '853f06489ef6ca50205799659d221bd3bea7d8da', "aria-hidden": "true", icon: danger, size: "small" }), this.errorMessage))));
|
|
313
313
|
}
|
|
314
314
|
static get is() { return "pds-textarea"; }
|
|
315
315
|
static get encapsulation() { return "shadow"; }
|
|
@@ -127,7 +127,7 @@ export class PdsToast {
|
|
|
127
127
|
'pds-toast--animating-out': this.isAnimatingOut
|
|
128
128
|
}, role: "alert", "aria-live": "polite" }, this.renderIcon(), h("span", { key: 'eaf615d41c138e2c73088d29bac9349f49a63ba7', class: "pds-toast__message" }, h("slot", { key: '33973447154d80b016f5a7954b0473db03228379' })), this.dismissible && (h("button", { key: 'e189834633e1e648282ee43633fd05e53ce38869', type: "button", part: "dismiss", class: "pds-toast__button", onClick: () => {
|
|
129
129
|
this.dismiss();
|
|
130
|
-
}, "aria-label": this.dismissLabel }, h("pds-icon", { key: '
|
|
130
|
+
}, "aria-label": this.dismissLabel }, h("pds-icon", { key: '913201979e52be743ba933ff173e023b81553362', name: "remove", "aria-hidden": "true" }))))));
|
|
131
131
|
}
|
|
132
132
|
static get is() { return "pds-toast"; }
|
|
133
133
|
static get encapsulation() { return "shadow"; }
|
|
@@ -57,12 +57,24 @@ function injectStyles() {
|
|
|
57
57
|
function isOverflowing(el) {
|
|
58
58
|
return el.scrollWidth > el.clientWidth;
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Engines without `:focus-visible` throw on the selector, so there every
|
|
62
|
+
* focus counts as visible rather than none.
|
|
63
|
+
*/
|
|
64
|
+
function isFocusVisible(el) {
|
|
65
|
+
try {
|
|
66
|
+
return el.matches(':focus-visible');
|
|
67
|
+
}
|
|
68
|
+
catch (_a) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
60
72
|
/**
|
|
61
73
|
* Sets up automatic tooltip behavior for a truncated element.
|
|
62
74
|
*
|
|
63
|
-
* When the element's text overflows, hovering
|
|
64
|
-
* will display a tooltip showing the full text content. The
|
|
65
|
-
* rendered as a portal on document.body and positioned with Floating UI.
|
|
75
|
+
* When the element's text overflows, hovering the host element or giving it
|
|
76
|
+
* keyboard focus will display a tooltip showing the full text content. The
|
|
77
|
+
* tooltip is rendered as a portal on document.body and positioned with Floating UI.
|
|
66
78
|
*
|
|
67
79
|
* Also owns the element's `tabindex` while it is clipped — see syncTabIndex.
|
|
68
80
|
*
|
|
@@ -253,18 +265,30 @@ export function setupTruncationTooltip(options) {
|
|
|
253
265
|
isHoveringPortal = false;
|
|
254
266
|
scheduleHide();
|
|
255
267
|
}
|
|
256
|
-
|
|
268
|
+
// Keyboard focus only: focus from a click would pin the tooltip open after the pointer leaves.
|
|
269
|
+
// Events from inside a shadow root arrive retargeted to its host, so test the innermost target.
|
|
270
|
+
function showForVisibleFocus(event) {
|
|
271
|
+
if (!isFocusVisible(event.composedPath()[0]))
|
|
272
|
+
return;
|
|
257
273
|
isFocused = true;
|
|
258
274
|
showTooltip();
|
|
259
275
|
}
|
|
276
|
+
// A key press after a click makes focus visible in place, with no new focusin. keyup, not
|
|
277
|
+
// keydown, so Tab's focus move lands first; Escape asks to dismiss, never to reveal.
|
|
278
|
+
function handleKeyUp(event) {
|
|
279
|
+
if (isFocused || event.key === 'Escape')
|
|
280
|
+
return;
|
|
281
|
+
showForVisibleFocus(event);
|
|
282
|
+
}
|
|
260
283
|
function handleFocusOut() {
|
|
261
284
|
isFocused = false;
|
|
262
285
|
scheduleHide();
|
|
263
286
|
}
|
|
264
287
|
hostEl.addEventListener('mouseenter', handleMouseEnter);
|
|
265
288
|
hostEl.addEventListener('mouseleave', handleMouseLeave);
|
|
266
|
-
focusEl.addEventListener('focusin',
|
|
289
|
+
focusEl.addEventListener('focusin', showForVisibleFocus);
|
|
267
290
|
focusEl.addEventListener('focusout', handleFocusOut);
|
|
291
|
+
focusEl.addEventListener('keyup', handleKeyUp);
|
|
268
292
|
// Return cleanup function
|
|
269
293
|
return () => {
|
|
270
294
|
disposed = true;
|
|
@@ -284,8 +308,9 @@ export function setupTruncationTooltip(options) {
|
|
|
284
308
|
}
|
|
285
309
|
hostEl.removeEventListener('mouseenter', handleMouseEnter);
|
|
286
310
|
hostEl.removeEventListener('mouseleave', handleMouseLeave);
|
|
287
|
-
focusEl.removeEventListener('focusin',
|
|
311
|
+
focusEl.removeEventListener('focusin', showForVisibleFocus);
|
|
288
312
|
focusEl.removeEventListener('focusout', handleFocusOut);
|
|
313
|
+
focusEl.removeEventListener('keyup', handleKeyUp);
|
|
289
314
|
removePortal();
|
|
290
315
|
};
|
|
291
316
|
}
|