@pine-ds/core 3.15.3-dev.0 → 3.16.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.
Files changed (69) hide show
  1. package/components/pds-dropdown-menu.js +70 -27
  2. package/components/pds-dropdown-menu.js.map +1 -1
  3. package/components/pds-tab.js +1 -1
  4. package/components/pds-tab.js.map +1 -1
  5. package/components/pds-table.js +5 -2
  6. package/components/pds-table.js.map +1 -1
  7. package/dist/cjs/pds-dropdown-menu.cjs.entry.js +70 -27
  8. package/dist/cjs/pds-dropdown-menu.entry.cjs.js.map +1 -1
  9. package/dist/cjs/pds-tab.cjs.entry.js +1 -1
  10. package/dist/cjs/pds-tab.entry.cjs.js.map +1 -1
  11. package/dist/cjs/pds-table.cjs.entry.js +5 -2
  12. package/dist/cjs/pds-table.entry.cjs.js.map +1 -1
  13. package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu.css +32 -0
  14. package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu.js +69 -26
  15. package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu.js.map +1 -1
  16. package/dist/collection/components/pds-table/pds-table.js +5 -2
  17. package/dist/collection/components/pds-table/pds-table.js.map +1 -1
  18. package/dist/collection/components/pds-tabs/pds-tab/pds-tab.css +0 -1
  19. package/dist/docs.json +1 -1
  20. package/dist/esm/pds-dropdown-menu.entry.js +70 -27
  21. package/dist/esm/pds-dropdown-menu.entry.js.map +1 -1
  22. package/dist/esm/pds-tab.entry.js +1 -1
  23. package/dist/esm/pds-tab.entry.js.map +1 -1
  24. package/dist/esm/pds-table.entry.js +5 -2
  25. package/dist/esm/pds-table.entry.js.map +1 -1
  26. package/dist/esm-es5/pds-dropdown-menu.entry.js +1 -1
  27. package/dist/esm-es5/pds-dropdown-menu.entry.js.map +1 -1
  28. package/dist/esm-es5/pds-tab.entry.js +1 -1
  29. package/dist/esm-es5/pds-tab.entry.js.map +1 -1
  30. package/dist/esm-es5/pds-table.entry.js +1 -1
  31. package/dist/esm-es5/pds-table.entry.js.map +1 -1
  32. package/dist/pine-core/p-23aba538.entry.js +2 -0
  33. package/dist/pine-core/p-23aba538.entry.js.map +1 -0
  34. package/dist/pine-core/p-2DR2iuEU.system.js.map +1 -0
  35. package/dist/pine-core/p-3c026ec7.system.entry.js +2 -0
  36. package/dist/pine-core/p-3c026ec7.system.entry.js.map +1 -0
  37. package/dist/pine-core/p-838452e0.entry.js +2 -0
  38. package/dist/pine-core/{p-5ef5f6b3.entry.js.map → p-838452e0.entry.js.map} +1 -1
  39. package/dist/pine-core/p-8b4f76e4.system.entry.js +2 -0
  40. package/dist/pine-core/p-8b4f76e4.system.entry.js.map +1 -0
  41. package/dist/pine-core/p-8b7246ea.system.entry.js +2 -0
  42. package/dist/pine-core/{p-4a42e114.system.entry.js.map → p-8b7246ea.system.entry.js.map} +1 -1
  43. package/dist/pine-core/p-C7XKS9nY.system.js.map +1 -0
  44. package/dist/pine-core/p-DZEhYV6y.system.js.map +1 -0
  45. package/dist/pine-core/p-JAVnELnm.system.js +1 -1
  46. package/dist/pine-core/p-d456c898.entry.js +2 -0
  47. package/dist/pine-core/p-d456c898.entry.js.map +1 -0
  48. package/dist/pine-core/pds-dropdown-menu.entry.esm.js.map +1 -1
  49. package/dist/pine-core/pds-tab.entry.esm.js.map +1 -1
  50. package/dist/pine-core/pds-table.entry.esm.js.map +1 -1
  51. package/dist/pine-core/pine-core.esm.js +1 -1
  52. package/dist/types/components/pds-dropdown-menu/pds-dropdown-menu.d.ts +1 -0
  53. package/dist/vscode.html-data.json +1 -1
  54. package/hydrate/index.js +77 -31
  55. package/hydrate/index.mjs +77 -31
  56. package/package.json +2 -2
  57. package/dist/pine-core/p-4a42e114.system.entry.js +0 -2
  58. package/dist/pine-core/p-5ef5f6b3.entry.js +0 -2
  59. package/dist/pine-core/p-9660a2c2.entry.js +0 -2
  60. package/dist/pine-core/p-9660a2c2.entry.js.map +0 -1
  61. package/dist/pine-core/p-9c0ec80a.entry.js +0 -2
  62. package/dist/pine-core/p-9c0ec80a.entry.js.map +0 -1
  63. package/dist/pine-core/p-CCgKUhC7.system.js.map +0 -1
  64. package/dist/pine-core/p-CE8RZXT8.system.js.map +0 -1
  65. package/dist/pine-core/p-d98310b9.system.entry.js +0 -2
  66. package/dist/pine-core/p-d98310b9.system.entry.js.map +0 -1
  67. package/dist/pine-core/p-f00f70bf.system.entry.js +0 -2
  68. package/dist/pine-core/p-f00f70bf.system.entry.js.map +0 -1
  69. package/dist/pine-core/p-g2zH2UyI.system.js.map +0 -1
@@ -27,14 +27,22 @@ export class PdsDropdownMenu {
27
27
  this.slotEl = event.target;
28
28
  // Get all elements assigned to this slot
29
29
  const assignedElements = this.slotEl.assignedElements();
30
- // ensure assignedElements only contains pds-dropdown-menu-item or pds-dropdown-menu-separator
31
- // if there are other elements, throw an error
32
- const invalidElements = assignedElements.filter(el => el.tagName.toLowerCase() !== 'pds-dropdown-menu-item' && el.tagName.toLowerCase() !== 'pds-dropdown-menu-separator');
30
+ // Allowed elements: pds-dropdown-menu-item, pds-dropdown-menu-separator, <a>, <button>
31
+ // Raw <a> and <button> elements are allowed for edge cases requiring native browser/framework
32
+ // behavior (e.g., Rails UJS, Turbo) that cannot work through Shadow DOM.
33
+ const allowedTags = ['pds-dropdown-menu-item', 'pds-dropdown-menu-separator', 'a', 'button'];
34
+ const invalidElements = assignedElements.filter(el => !allowedTags.includes(el.tagName.toLowerCase()));
33
35
  if (invalidElements.length > 0) {
34
- throw new Error(`pds-dropdown-menu only accepts pds-dropdown-menu-item and pds-dropdown-menu-separator elements`);
36
+ const invalidTags = invalidElements.map(el => el.tagName.toLowerCase()).join(', ');
37
+ console.warn(`pds-dropdown-menu: Unexpected element(s) found: ${invalidTags}. ` +
38
+ `Expected: ${allowedTags.join(', ')}`);
35
39
  }
36
- // Store all menu items for keyboard navigation
37
- this.menuItems = assignedElements.filter(el => el.tagName.toLowerCase() === 'pds-dropdown-menu-item');
40
+ // Store all focusable items for keyboard navigation
41
+ // This includes pds-dropdown-menu-item components and raw <a>/<button> elements
42
+ this.menuItems = assignedElements.filter(el => {
43
+ const tag = el.tagName.toLowerCase();
44
+ return tag === 'pds-dropdown-menu-item' || tag === 'a' || tag === 'button';
45
+ });
38
46
  };
39
47
  // Toggle dropdown open/closed
40
48
  this.toggleDropdown = () => {
@@ -103,31 +111,66 @@ export class PdsDropdownMenu {
103
111
  this.cleanupAutoUpdate = null;
104
112
  }
105
113
  }
114
+ // Check if a menu item is disabled (handles both component and raw elements)
115
+ isItemDisabled(item) {
116
+ const tagName = item.tagName.toLowerCase();
117
+ if (tagName === 'pds-dropdown-menu-item') {
118
+ return item.disabled;
119
+ }
120
+ else if (tagName === 'button') {
121
+ return item.disabled;
122
+ }
123
+ else if (tagName === 'a') {
124
+ return item.getAttribute('aria-disabled') === 'true';
125
+ }
126
+ return false;
127
+ }
106
128
  // Get the index of the currently focused menu item
107
129
  getFocusedItemIndex() {
108
130
  const activeElement = document.activeElement;
109
131
  if (!activeElement)
110
132
  return -1;
111
- return this.menuItems.findIndex(item => item === activeElement);
133
+ // For raw elements, check direct match
134
+ // For pds-dropdown-menu-item, also check if the active element is inside the shadow root
135
+ return this.menuItems.findIndex(item => {
136
+ if (item === activeElement)
137
+ return true;
138
+ // Check if activeElement is inside the item's shadow root (for pds-dropdown-menu-item)
139
+ if (item.tagName.toLowerCase() === 'pds-dropdown-menu-item') {
140
+ const shadowRoot = item.shadowRoot;
141
+ if (shadowRoot === null || shadowRoot === void 0 ? void 0 : shadowRoot.contains(activeElement))
142
+ return true;
143
+ }
144
+ return false;
145
+ });
112
146
  }
113
147
  // Focus a specific menu item by index
114
148
  focusItemByIndex(index) {
115
- var _a, _b, _c, _d;
149
+ var _a, _b, _c, _d, _e;
116
150
  if (index >= 0 && index < this.menuItems.length) {
117
151
  this.currentFocusIndex = index;
118
- // Focus the inner button/link instead of the host element
119
- const menuItem = this.menuItems[index];
120
- const innerButton = (_a = menuItem.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('button');
121
- const innerLink = (_d = (_c = (_b = menuItem.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('pds-link')) === null || _c === void 0 ? void 0 : _c.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelector('a');
122
- if (innerButton) {
123
- return innerButton.focus();
124
- }
125
- else if (innerLink) {
126
- return innerLink.focus();
152
+ const item = this.menuItems[index];
153
+ const tagName = item.tagName.toLowerCase();
154
+ if (tagName === 'pds-dropdown-menu-item') {
155
+ // For pds-dropdown-menu-item, focus the inner element
156
+ const menuItem = item;
157
+ const innerButton = (_a = menuItem.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('button');
158
+ const innerLink = ((_d = (_c = (_b = menuItem.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('pds-link')) === null || _c === void 0 ? void 0 : _c.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelector('a'))
159
+ || ((_e = menuItem.shadowRoot) === null || _e === void 0 ? void 0 : _e.querySelector('a'));
160
+ if (innerButton) {
161
+ innerButton.focus();
162
+ }
163
+ else if (innerLink) {
164
+ innerLink.focus();
165
+ }
166
+ else {
167
+ // Fallback to focusing the host
168
+ menuItem.focus();
169
+ }
127
170
  }
128
171
  else {
129
- // Fallback to focusing the host if we can't find the inner element
130
- menuItem.focus();
172
+ // For raw <a> or <button> elements, focus directly
173
+ item.focus();
131
174
  }
132
175
  }
133
176
  }
@@ -137,7 +180,7 @@ export class PdsDropdownMenu {
137
180
  // Skip disabled items
138
181
  let attempts = 0;
139
182
  const maxAttempts = this.menuItems.length;
140
- while (attempts < maxAttempts && this.menuItems[nextIndex].disabled) {
183
+ while (attempts < maxAttempts && this.isItemDisabled(this.menuItems[nextIndex])) {
141
184
  nextIndex = (nextIndex + 1) % this.menuItems.length;
142
185
  attempts++;
143
186
  }
@@ -154,7 +197,7 @@ export class PdsDropdownMenu {
154
197
  // Skip disabled items
155
198
  let attempts = 0;
156
199
  const maxAttempts = this.menuItems.length;
157
- while (attempts < maxAttempts && this.menuItems[prevIndex].disabled) {
200
+ while (attempts < maxAttempts && this.isItemDisabled(this.menuItems[prevIndex])) {
158
201
  prevIndex = prevIndex <= 0 ? this.menuItems.length - 1 : prevIndex - 1;
159
202
  attempts++;
160
203
  }
@@ -185,7 +228,7 @@ export class PdsDropdownMenu {
185
228
  if (this.menuItems.length > 0) {
186
229
  // Find first non-disabled item
187
230
  let firstIndex = 0;
188
- while (firstIndex < this.menuItems.length && this.menuItems[firstIndex].disabled) {
231
+ while (firstIndex < this.menuItems.length && this.isItemDisabled(this.menuItems[firstIndex])) {
189
232
  firstIndex++;
190
233
  }
191
234
  if (firstIndex < this.menuItems.length) {
@@ -198,7 +241,7 @@ export class PdsDropdownMenu {
198
241
  if (this.menuItems.length > 0) {
199
242
  // Find last non-disabled item
200
243
  let lastIndex = this.menuItems.length - 1;
201
- while (lastIndex >= 0 && this.menuItems[lastIndex].disabled) {
244
+ while (lastIndex >= 0 && this.isItemDisabled(this.menuItems[lastIndex])) {
202
245
  lastIndex--;
203
246
  }
204
247
  if (lastIndex >= 0) {
@@ -228,7 +271,7 @@ export class PdsDropdownMenu {
228
271
  event.preventDefault();
229
272
  // Find the first non-disabled item
230
273
  let firstFocusableIndex = 0;
231
- while (firstFocusableIndex < this.menuItems.length && this.menuItems[firstFocusableIndex].disabled) {
274
+ while (firstFocusableIndex < this.menuItems.length && this.isItemDisabled(this.menuItems[firstFocusableIndex])) {
232
275
  firstFocusableIndex++;
233
276
  }
234
277
  if (firstFocusableIndex < this.menuItems.length) {
@@ -240,7 +283,7 @@ export class PdsDropdownMenu {
240
283
  event.preventDefault();
241
284
  // Find the first non-disabled item
242
285
  let firstFocusableIndex = 0;
243
- while (firstFocusableIndex < this.menuItems.length && this.menuItems[firstFocusableIndex].disabled) {
286
+ while (firstFocusableIndex < this.menuItems.length && this.isItemDisabled(this.menuItems[firstFocusableIndex])) {
244
287
  firstFocusableIndex++;
245
288
  }
246
289
  if (firstFocusableIndex < this.menuItems.length) {
@@ -263,7 +306,7 @@ export class PdsDropdownMenu {
263
306
  }
264
307
  }
265
308
  render() {
266
- return (h(Host, { key: 'bedd78a69e84f10abb3c714c02227fa76e255a35', id: this.componentId }, h("slot", { key: 'd2bf56037a85679a677470d04865823966ca19d6', name: "trigger", onSlotchange: this.handleTriggerSlotChange }), h("pds-box", { key: '64f56896103bb6cca6c71020d3d37c375d300c40', "border-radius": "sm", display: "flex", direction: "column", class: "pds-dropdown-menu--panel is-hidden", shadow: "100", role: "menu", "aria-orientation": "vertical", part: "menu-panel" }, h("slot", { key: '0303160562f74fe9d32cc020c4539a7c8fc288a9', onSlotchange: this.handleSlotChange }))));
309
+ return (h(Host, { key: '3144bc264072eccf89cdca45a0b28eb004b5d06e', id: this.componentId }, h("slot", { key: '500288f266dc7ab7e1ac5070e628c31a6ed50861', name: "trigger", onSlotchange: this.handleTriggerSlotChange }), h("pds-box", { key: '4085130e381b8be28e2e36de073c0755a455e30c', "border-radius": "sm", display: "flex", direction: "column", class: "pds-dropdown-menu--panel is-hidden", shadow: "100", role: "menu", "aria-orientation": "vertical", part: "menu-panel" }, h("slot", { key: '2c4d53799576d1c6913df9bb854bfbaf50e5032c', onSlotchange: this.handleSlotChange }))));
267
310
  }
268
311
  static get is() { return "pds-dropdown-menu"; }
269
312
  static get encapsulation() { return "shadow"; }
@@ -1 +1 @@
1
- {"version":3,"file":"pds-dropdown-menu.js","sourceRoot":"","sources":["../../../../src/components/pds-dropdown-menu/pds-dropdown-menu.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Element, Host, h, Prop, Listen, State } from '@stencil/core';\nimport type { BasePdsProps } from '@utils/interfaces';\nimport { PlacementType } from '@utils/types';\nimport { computePosition,\n flip,\n offset,\n shift,\n autoUpdate,\n} from '@floating-ui/dom';\n\n/**\n * @part menu-panel - Exposes the dropdown menu container for styling.\n */\n@Component({\n tag: 'pds-dropdown-menu',\n styleUrl: 'pds-dropdown-menu.scss',\n shadow: true,\n})\nexport class PdsDropdownMenu implements BasePdsProps {\n private slotEl: HTMLSlotElement;\n private triggerEl: HTMLElement;\n private panelEl: HTMLPdsBoxElement;\n private isOpen: boolean = false;\n private menuItems: HTMLPdsDropdownMenuItemElement[] = [];\n private cleanupAutoUpdate: (() => void) | null = null;\n\n @Element() host: HTMLPdsDropdownMenuElement;\n\n @State() currentFocusIndex: number = -1;\n\n /**\n * A unique identifier used for the underlying component `id` attribute.\n */\n @Prop() componentId: string;\n\n /**\n * The placement of the dropdown panel relative to the trigger.\n */\n @Prop() placement: PlacementType = 'bottom-start';\n\n componentDidRender() {\n this.panelEl = this.host.shadowRoot?.querySelector('pds-box') as HTMLPdsBoxElement;\n }\n\n disconnectedCallback() {\n // Clean up auto-update when component is removed from DOM\n if (this.cleanupAutoUpdate) {\n this.cleanupAutoUpdate();\n this.cleanupAutoUpdate = null;\n }\n }\n\n private handleTriggerSlotChange = (event: Event) => {\n this.slotEl = event.target as HTMLSlotElement;\n\n // Get all elements assigned to this slot\n const assignedElements = this.slotEl.assignedElements();\n\n this.triggerEl = assignedElements[0] as HTMLElement;\n this.triggerEl.onclick = this.handleClick;\n\n // Add accessibility attributes to trigger\n this.triggerEl.setAttribute('aria-haspopup', 'menu');\n this.triggerEl.setAttribute('aria-expanded', 'false');\n }\n\n private handleSlotChange = (event: Event) => {\n this.slotEl = event.target as HTMLSlotElement;\n\n // Get all elements assigned to this slot\n const assignedElements = this.slotEl.assignedElements();\n\n // ensure assignedElements only contains pds-dropdown-menu-item or pds-dropdown-menu-separator\n // if there are other elements, throw an error\n const invalidElements = assignedElements.filter(el => el.tagName.toLowerCase() !== 'pds-dropdown-menu-item' && el.tagName.toLowerCase() !== 'pds-dropdown-menu-separator');\n if (invalidElements.length > 0) {\n throw new Error(`pds-dropdown-menu only accepts pds-dropdown-menu-item and pds-dropdown-menu-separator elements`);\n }\n\n // Store all menu items for keyboard navigation\n this.menuItems = assignedElements.filter(\n el => el.tagName.toLowerCase() === 'pds-dropdown-menu-item'\n ) as HTMLPdsDropdownMenuItemElement[];\n }\n\n // Toggle dropdown open/closed\n private toggleDropdown = () => {\n this.isOpen = !this.isOpen;\n\n if (this.isOpen) {\n this.openDropdown();\n } else {\n this.closeDropdown();\n }\n }\n\n // Open the dropdown and position it\n private openDropdown = () => {\n const updatePosition = () => {\n computePosition(this.triggerEl, this.panelEl as HTMLElement, {\n placement: this.placement,\n strategy: 'fixed',\n middleware: [offset(6), flip(), shift({padding: 5})],\n }).then(({ x, y }) => {\n Object.assign(this.panelEl.style, {\n left: `${x}px`,\n top: `${y}px`,\n });\n });\n };\n\n // Initial position\n updatePosition();\n\n // Set up auto-update for window resize and scroll\n this.cleanupAutoUpdate = autoUpdate(\n this.triggerEl,\n this.panelEl as HTMLElement,\n updatePosition\n );\n\n this.host.shadowRoot?.querySelector('pds-box').classList.remove('is-hidden');\n this.isOpen = true;\n\n // Update ARIA attributes\n this.triggerEl.setAttribute('aria-expanded', 'true');\n }\n\n // Close the dropdown\n private closeDropdown = () => {\n this.host.shadowRoot?.querySelector('pds-box').classList.add('is-hidden');\n this.isOpen = false;\n\n // Clean up auto-update\n if (this.cleanupAutoUpdate) {\n this.cleanupAutoUpdate();\n this.cleanupAutoUpdate = null;\n }\n\n // Update ARIA attributes\n this.triggerEl.setAttribute('aria-expanded', 'false');\n\n // Reset focus index\n this.currentFocusIndex = -1;\n\n // Return focus to trigger\n this.triggerEl.focus();\n }\n\n // Handle click on the trigger element\n private handleClick = () => {\n this.toggleDropdown();\n }\n\n // Get the index of the currently focused menu item\n private getFocusedItemIndex(): number {\n const activeElement = document.activeElement as HTMLPdsDropdownMenuItemElement | null;\n if (!activeElement) return -1;\n return this.menuItems.findIndex(item => item === activeElement);\n }\n\n // Focus a specific menu item by index\n private focusItemByIndex(index: number): void {\n if (index >= 0 && index < this.menuItems.length) {\n this.currentFocusIndex = index;\n\n // Focus the inner button/link instead of the host element\n const menuItem = this.menuItems[index];\n const innerButton = menuItem.shadowRoot?.querySelector('button');\n const innerLink = menuItem.shadowRoot?.querySelector('pds-link')?.shadowRoot?.querySelector('a');\n\n if (innerButton) {\n return innerButton.focus();\n } else if (innerLink) {\n return innerLink.focus();\n } else {\n // Fallback to focusing the host if we can't find the inner element\n menuItem.focus();\n }\n }\n }\n\n // Focus the next menu item\n private focusNextItem(): void {\n let nextIndex = (this.currentFocusIndex + 1) % this.menuItems.length;\n\n // Skip disabled items\n let attempts = 0;\n const maxAttempts = this.menuItems.length;\n\n while (attempts < maxAttempts && this.menuItems[nextIndex].disabled) {\n nextIndex = (nextIndex + 1) % this.menuItems.length;\n attempts++;\n }\n\n // Only focus if we found a non-disabled item\n if (attempts < maxAttempts) {\n this.focusItemByIndex(nextIndex);\n }\n }\n\n // Focus the previous menu item\n private focusPreviousItem(): void {\n let prevIndex = this.currentFocusIndex <= 0\n ? this.menuItems.length - 1\n : this.currentFocusIndex - 1;\n\n // Skip disabled items\n let attempts = 0;\n const maxAttempts = this.menuItems.length;\n\n while (attempts < maxAttempts && this.menuItems[prevIndex].disabled) {\n prevIndex = prevIndex <= 0 ? this.menuItems.length - 1 : prevIndex - 1;\n attempts++;\n }\n\n // Only focus if we found a non-disabled item\n if (attempts < maxAttempts) {\n this.focusItemByIndex(prevIndex);\n }\n }\n\n // Handle keyboard events for the dropdown\n @Listen('keydown', { target: 'window' })\n handleKeyDown(event: KeyboardEvent) {\n if (!this.isOpen) return;\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault();\n this.closeDropdown();\n break;\n\n case 'ArrowDown':\n event.preventDefault();\n this.focusNextItem();\n break;\n\n case 'ArrowUp':\n event.preventDefault();\n this.focusPreviousItem();\n break;\n\n case 'Home':\n event.preventDefault();\n if (this.menuItems.length > 0) {\n // Find first non-disabled item\n let firstIndex = 0;\n while (firstIndex < this.menuItems.length && this.menuItems[firstIndex].disabled) {\n firstIndex++;\n }\n if (firstIndex < this.menuItems.length) {\n this.focusItemByIndex(firstIndex);\n }\n }\n break;\n\n case 'End':\n event.preventDefault();\n if (this.menuItems.length > 0) {\n // Find last non-disabled item\n let lastIndex = this.menuItems.length - 1;\n while (lastIndex >= 0 && this.menuItems[lastIndex].disabled) {\n lastIndex--;\n }\n if (lastIndex >= 0) {\n this.focusItemByIndex(lastIndex);\n }\n }\n break;\n\n case 'Tab':\n if (event.shiftKey) {\n // Let Shift+Tab navigate naturally from first item to trigger\n // For all other items, move to previous item\n const currentIndex = this.getFocusedItemIndex();\n\n if (currentIndex > 0) {\n // If not on first item, prevent default and go to previous item\n event.preventDefault();\n this.focusPreviousItem(); // Use our method that skips disabled items\n }\n // If on first item or no item, let natural tab order move back to trigger\n } else {\n // Forward Tab navigation\n const activeElement = document.activeElement;\n const isTriggerFocused = activeElement === this.triggerEl;\n const currentIndex = this.getFocusedItemIndex();\n\n if (isTriggerFocused && this.menuItems.length > 0) {\n // If trigger is focused, move to first non-disabled menu item\n event.preventDefault();\n\n // Find the first non-disabled item\n let firstFocusableIndex = 0;\n while (firstFocusableIndex < this.menuItems.length && this.menuItems[firstFocusableIndex].disabled) {\n firstFocusableIndex++;\n }\n\n if (firstFocusableIndex < this.menuItems.length) {\n this.focusItemByIndex(firstFocusableIndex);\n }\n } else if (currentIndex === -1 && this.menuItems.length > 0) {\n // If no menu item is focused, focus the first non-disabled one\n event.preventDefault();\n\n // Find the first non-disabled item\n let firstFocusableIndex = 0;\n while (firstFocusableIndex < this.menuItems.length && this.menuItems[firstFocusableIndex].disabled) {\n firstFocusableIndex++;\n }\n\n if (firstFocusableIndex < this.menuItems.length) {\n this.focusItemByIndex(firstFocusableIndex);\n }\n } else if (currentIndex !== -1) {\n // Use our method that skips disabled items\n event.preventDefault();\n this.focusNextItem();\n }\n }\n break;\n }\n }\n\n // Handle clicks outside the dropdown to close it\n @Listen('click', { target: 'window' })\n handleWindowClick(event: MouseEvent) {\n if (this.isOpen && !this.host.contains(event.target as Node) && event.target !== this.triggerEl) {\n this.closeDropdown();\n }\n }\n\n\n render() {\n return (\n <Host id={this.componentId}>\n <slot\n name=\"trigger\"\n onSlotchange={this.handleTriggerSlotChange}\n ></slot>\n <pds-box\n border-radius=\"sm\"\n display=\"flex\"\n direction=\"column\"\n class=\"pds-dropdown-menu--panel is-hidden\"\n shadow=\"100\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n part=\"menu-panel\"\n >\n <slot onSlotchange={this.handleSlotChange}></slot>\n </pds-box>\n </Host>\n );\n }\n}\n"]}
1
+ {"version":3,"file":"pds-dropdown-menu.js","sourceRoot":"","sources":["../../../../src/components/pds-dropdown-menu/pds-dropdown-menu.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Element, Host, h, Prop, Listen, State } from '@stencil/core';\nimport type { BasePdsProps } from '@utils/interfaces';\nimport { PlacementType } from '@utils/types';\nimport { computePosition,\n flip,\n offset,\n shift,\n autoUpdate,\n} from '@floating-ui/dom';\n\n/**\n * Union type for focusable menu items (component or raw elements)\n */\ntype MenuItemElement = HTMLPdsDropdownMenuItemElement | HTMLAnchorElement | HTMLButtonElement;\n\n/**\n * @part menu-panel - Exposes the dropdown menu container for styling.\n */\n@Component({\n tag: 'pds-dropdown-menu',\n styleUrl: 'pds-dropdown-menu.scss',\n shadow: true,\n})\nexport class PdsDropdownMenu implements BasePdsProps {\n private slotEl: HTMLSlotElement;\n private triggerEl: HTMLElement;\n private panelEl: HTMLPdsBoxElement;\n private isOpen: boolean = false;\n private menuItems: MenuItemElement[] = [];\n private cleanupAutoUpdate: (() => void) | null = null;\n\n @Element() host: HTMLPdsDropdownMenuElement;\n\n @State() currentFocusIndex: number = -1;\n\n /**\n * A unique identifier used for the underlying component `id` attribute.\n */\n @Prop() componentId: string;\n\n /**\n * The placement of the dropdown panel relative to the trigger.\n */\n @Prop() placement: PlacementType = 'bottom-start';\n\n componentDidRender() {\n this.panelEl = this.host.shadowRoot?.querySelector('pds-box') as HTMLPdsBoxElement;\n }\n\n disconnectedCallback() {\n // Clean up auto-update when component is removed from DOM\n if (this.cleanupAutoUpdate) {\n this.cleanupAutoUpdate();\n this.cleanupAutoUpdate = null;\n }\n }\n\n private handleTriggerSlotChange = (event: Event) => {\n this.slotEl = event.target as HTMLSlotElement;\n\n // Get all elements assigned to this slot\n const assignedElements = this.slotEl.assignedElements();\n\n this.triggerEl = assignedElements[0] as HTMLElement;\n this.triggerEl.onclick = this.handleClick;\n\n // Add accessibility attributes to trigger\n this.triggerEl.setAttribute('aria-haspopup', 'menu');\n this.triggerEl.setAttribute('aria-expanded', 'false');\n }\n\n private handleSlotChange = (event: Event) => {\n this.slotEl = event.target as HTMLSlotElement;\n\n // Get all elements assigned to this slot\n const assignedElements = this.slotEl.assignedElements();\n\n // Allowed elements: pds-dropdown-menu-item, pds-dropdown-menu-separator, <a>, <button>\n // Raw <a> and <button> elements are allowed for edge cases requiring native browser/framework\n // behavior (e.g., Rails UJS, Turbo) that cannot work through Shadow DOM.\n const allowedTags = ['pds-dropdown-menu-item', 'pds-dropdown-menu-separator', 'a', 'button'];\n const invalidElements = assignedElements.filter(\n el => !allowedTags.includes(el.tagName.toLowerCase())\n );\n\n if (invalidElements.length > 0) {\n const invalidTags = invalidElements.map(el => el.tagName.toLowerCase()).join(', ');\n console.warn(\n `pds-dropdown-menu: Unexpected element(s) found: ${invalidTags}. ` +\n `Expected: ${allowedTags.join(', ')}`\n );\n }\n\n // Store all focusable items for keyboard navigation\n // This includes pds-dropdown-menu-item components and raw <a>/<button> elements\n this.menuItems = assignedElements.filter(el => {\n const tag = el.tagName.toLowerCase();\n return tag === 'pds-dropdown-menu-item' || tag === 'a' || tag === 'button';\n }) as MenuItemElement[];\n }\n\n // Toggle dropdown open/closed\n private toggleDropdown = () => {\n this.isOpen = !this.isOpen;\n\n if (this.isOpen) {\n this.openDropdown();\n } else {\n this.closeDropdown();\n }\n }\n\n // Open the dropdown and position it\n private openDropdown = () => {\n const updatePosition = () => {\n computePosition(this.triggerEl, this.panelEl as HTMLElement, {\n placement: this.placement,\n strategy: 'fixed',\n middleware: [offset(6), flip(), shift({padding: 5})],\n }).then(({ x, y }) => {\n Object.assign(this.panelEl.style, {\n left: `${x}px`,\n top: `${y}px`,\n });\n });\n };\n\n // Initial position\n updatePosition();\n\n // Set up auto-update for window resize and scroll\n this.cleanupAutoUpdate = autoUpdate(\n this.triggerEl,\n this.panelEl as HTMLElement,\n updatePosition\n );\n\n this.host.shadowRoot?.querySelector('pds-box').classList.remove('is-hidden');\n this.isOpen = true;\n\n // Update ARIA attributes\n this.triggerEl.setAttribute('aria-expanded', 'true');\n }\n\n // Close the dropdown\n private closeDropdown = () => {\n this.host.shadowRoot?.querySelector('pds-box').classList.add('is-hidden');\n this.isOpen = false;\n\n // Clean up auto-update\n if (this.cleanupAutoUpdate) {\n this.cleanupAutoUpdate();\n this.cleanupAutoUpdate = null;\n }\n\n // Update ARIA attributes\n this.triggerEl.setAttribute('aria-expanded', 'false');\n\n // Reset focus index\n this.currentFocusIndex = -1;\n\n // Return focus to trigger\n this.triggerEl.focus();\n }\n\n // Handle click on the trigger element\n private handleClick = () => {\n this.toggleDropdown();\n }\n\n // Check if a menu item is disabled (handles both component and raw elements)\n private isItemDisabled(item: MenuItemElement): boolean {\n const tagName = item.tagName.toLowerCase();\n\n if (tagName === 'pds-dropdown-menu-item') {\n return (item as HTMLPdsDropdownMenuItemElement).disabled;\n } else if (tagName === 'button') {\n return (item as HTMLButtonElement).disabled;\n } else if (tagName === 'a') {\n return item.getAttribute('aria-disabled') === 'true';\n }\n return false;\n }\n\n // Get the index of the currently focused menu item\n private getFocusedItemIndex(): number {\n const activeElement = document.activeElement as MenuItemElement | null;\n if (!activeElement) return -1;\n\n // For raw elements, check direct match\n // For pds-dropdown-menu-item, also check if the active element is inside the shadow root\n return this.menuItems.findIndex(item => {\n if (item === activeElement) return true;\n\n // Check if activeElement is inside the item's shadow root (for pds-dropdown-menu-item)\n if (item.tagName.toLowerCase() === 'pds-dropdown-menu-item') {\n const shadowRoot = (item as HTMLPdsDropdownMenuItemElement).shadowRoot;\n if (shadowRoot?.contains(activeElement)) return true;\n }\n\n return false;\n });\n }\n\n // Focus a specific menu item by index\n private focusItemByIndex(index: number): void {\n if (index >= 0 && index < this.menuItems.length) {\n this.currentFocusIndex = index;\n const item = this.menuItems[index];\n const tagName = item.tagName.toLowerCase();\n\n if (tagName === 'pds-dropdown-menu-item') {\n // For pds-dropdown-menu-item, focus the inner element\n const menuItem = item as HTMLPdsDropdownMenuItemElement;\n const innerButton = menuItem.shadowRoot?.querySelector('button');\n const innerLink = menuItem.shadowRoot?.querySelector('pds-link')?.shadowRoot?.querySelector('a')\n || menuItem.shadowRoot?.querySelector('a');\n\n if (innerButton) {\n innerButton.focus();\n } else if (innerLink) {\n innerLink.focus();\n } else {\n // Fallback to focusing the host\n menuItem.focus();\n }\n } else {\n // For raw <a> or <button> elements, focus directly\n (item as HTMLElement).focus();\n }\n }\n }\n\n // Focus the next menu item\n private focusNextItem(): void {\n let nextIndex = (this.currentFocusIndex + 1) % this.menuItems.length;\n\n // Skip disabled items\n let attempts = 0;\n const maxAttempts = this.menuItems.length;\n\n while (attempts < maxAttempts && this.isItemDisabled(this.menuItems[nextIndex])) {\n nextIndex = (nextIndex + 1) % this.menuItems.length;\n attempts++;\n }\n\n // Only focus if we found a non-disabled item\n if (attempts < maxAttempts) {\n this.focusItemByIndex(nextIndex);\n }\n }\n\n // Focus the previous menu item\n private focusPreviousItem(): void {\n let prevIndex = this.currentFocusIndex <= 0\n ? this.menuItems.length - 1\n : this.currentFocusIndex - 1;\n\n // Skip disabled items\n let attempts = 0;\n const maxAttempts = this.menuItems.length;\n\n while (attempts < maxAttempts && this.isItemDisabled(this.menuItems[prevIndex])) {\n prevIndex = prevIndex <= 0 ? this.menuItems.length - 1 : prevIndex - 1;\n attempts++;\n }\n\n // Only focus if we found a non-disabled item\n if (attempts < maxAttempts) {\n this.focusItemByIndex(prevIndex);\n }\n }\n\n // Handle keyboard events for the dropdown\n @Listen('keydown', { target: 'window' })\n handleKeyDown(event: KeyboardEvent) {\n if (!this.isOpen) return;\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault();\n this.closeDropdown();\n break;\n\n case 'ArrowDown':\n event.preventDefault();\n this.focusNextItem();\n break;\n\n case 'ArrowUp':\n event.preventDefault();\n this.focusPreviousItem();\n break;\n\n case 'Home':\n event.preventDefault();\n if (this.menuItems.length > 0) {\n // Find first non-disabled item\n let firstIndex = 0;\n while (firstIndex < this.menuItems.length && this.isItemDisabled(this.menuItems[firstIndex])) {\n firstIndex++;\n }\n if (firstIndex < this.menuItems.length) {\n this.focusItemByIndex(firstIndex);\n }\n }\n break;\n\n case 'End':\n event.preventDefault();\n if (this.menuItems.length > 0) {\n // Find last non-disabled item\n let lastIndex = this.menuItems.length - 1;\n while (lastIndex >= 0 && this.isItemDisabled(this.menuItems[lastIndex])) {\n lastIndex--;\n }\n if (lastIndex >= 0) {\n this.focusItemByIndex(lastIndex);\n }\n }\n break;\n\n case 'Tab':\n if (event.shiftKey) {\n // Let Shift+Tab navigate naturally from first item to trigger\n // For all other items, move to previous item\n const currentIndex = this.getFocusedItemIndex();\n\n if (currentIndex > 0) {\n // If not on first item, prevent default and go to previous item\n event.preventDefault();\n this.focusPreviousItem(); // Use our method that skips disabled items\n }\n // If on first item or no item, let natural tab order move back to trigger\n } else {\n // Forward Tab navigation\n const activeElement = document.activeElement;\n const isTriggerFocused = activeElement === this.triggerEl;\n const currentIndex = this.getFocusedItemIndex();\n\n if (isTriggerFocused && this.menuItems.length > 0) {\n // If trigger is focused, move to first non-disabled menu item\n event.preventDefault();\n\n // Find the first non-disabled item\n let firstFocusableIndex = 0;\n while (firstFocusableIndex < this.menuItems.length && this.isItemDisabled(this.menuItems[firstFocusableIndex])) {\n firstFocusableIndex++;\n }\n\n if (firstFocusableIndex < this.menuItems.length) {\n this.focusItemByIndex(firstFocusableIndex);\n }\n } else if (currentIndex === -1 && this.menuItems.length > 0) {\n // If no menu item is focused, focus the first non-disabled one\n event.preventDefault();\n\n // Find the first non-disabled item\n let firstFocusableIndex = 0;\n while (firstFocusableIndex < this.menuItems.length && this.isItemDisabled(this.menuItems[firstFocusableIndex])) {\n firstFocusableIndex++;\n }\n\n if (firstFocusableIndex < this.menuItems.length) {\n this.focusItemByIndex(firstFocusableIndex);\n }\n } else if (currentIndex !== -1) {\n // Use our method that skips disabled items\n event.preventDefault();\n this.focusNextItem();\n }\n }\n break;\n }\n }\n\n // Handle clicks outside the dropdown to close it\n @Listen('click', { target: 'window' })\n handleWindowClick(event: MouseEvent) {\n if (this.isOpen && !this.host.contains(event.target as Node) && event.target !== this.triggerEl) {\n this.closeDropdown();\n }\n }\n\n\n render() {\n return (\n <Host id={this.componentId}>\n <slot\n name=\"trigger\"\n onSlotchange={this.handleTriggerSlotChange}\n ></slot>\n <pds-box\n border-radius=\"sm\"\n display=\"flex\"\n direction=\"column\"\n class=\"pds-dropdown-menu--panel is-hidden\"\n shadow=\"100\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n part=\"menu-panel\"\n >\n <slot onSlotchange={this.handleSlotChange}></slot>\n </pds-box>\n </Host>\n );\n }\n}\n"]}
@@ -33,9 +33,12 @@ export class PdsTable {
33
33
  this.setupResponsiveScrolling();
34
34
  }
35
35
  // Apply default sort if specified
36
+ // Use requestAnimationFrame to defer until child components are fully initialized
36
37
  if (this.defaultSortColumn) {
37
- void this.applyDefaultSort().catch((err) => {
38
- console.warn('Failed to apply default sort.', err);
38
+ requestAnimationFrame(() => {
39
+ void this.applyDefaultSort().catch((err) => {
40
+ console.warn('Failed to apply default sort.', err);
41
+ });
39
42
  });
40
43
  }
41
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pds-table.js","sourceRoot":"","sources":["../../../../src/components/pds-table/pds-table.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAgB,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAOtG,MAAM,OAAO,QAAQ;IALrB;QAOU,oBAAe,GAAuB,IAAI,CAAC;QAC3C,4BAAuB,GAAwB,IAAI,CAAC;QACpD,4BAAuB,GAAwB,IAAI,CAAC;QACpD,8BAAyB,GAA0B,IAAI,CAAC;QACxD,wBAAmB,GAAwB,IAAI,CAAC;QA2BxD;;;WAGG;QACsB,gBAAW,GAAY,KAAK,CAAC;QAQtD;;;;WAIG;QACK,yBAAoB,GAAoB,KAAK,CAAC;QAEtD;;;WAGG;QACM,kBAAa,GAAkB,IAAI,CAAC;QAE7C;;;WAGG;QACM,qBAAgB,GAAmB,KAAK,CAAC;KAkSnD;IArRC,gBAAgB;QACd,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAClC,CAAC;QAED,kCAAkC;QAClC,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,KAAK,IAAI,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACzC,OAAO,CAAC,IAAI,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,gBAAgB;;QAC5B,8DAA8D;QAC9D,MAAM,SAAS,GAAmB,IAAI,CAAC,oBAAoB,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QAExF,yCAAyC;QACzC,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAClC,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,+BAA+B,CAAC,CACzB,CAAC;QAEnC,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,CACzC,CAAC,IAAI,EAAE,EAAE,WAAC,OAAA,CAAC,MAAA,IAAI,CAAC,WAAW,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,iBAAiB,CAAA,EAAA,CACrE,CAAC;QAEF,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,UAAU,GAAG,CAAC,MAAA,YAAY,CAAC,WAAW,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3D,sBAAsB;YACtB,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;YACtC,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC;YAChC,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;YAElC,+CAA+C;YAC/C,MAAM,YAAY,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,wBAAwB,IAAI,CAAC,iBAAiB,cAAc,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,oBAAoB;QAClB,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC3B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAClC,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACK,wBAAwB;;QAC9B,MAAM,SAAS,GAAG,MAAA,IAAI,CAAC,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,iCAAiC,CAAgB,CAAC;QACtG,MAAM,UAAU,GAAG,MAAA,IAAI,CAAC,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,qBAAqB,CAAgB,CAAC;QAC3F,MAAM,WAAW,GAAG,MAAA,IAAI,CAAC,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,sBAAsB,CAAgB,CAAC;QAE7F,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW;YAAE,OAAO;QAEtD,wCAAwC;QACxC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QAEjC;;;;WAIG;QACH,IAAI,CAAC,uBAAuB,GAAG,GAAG,EAAE;YAClC,IAAI,CAAC,IAAI,CAAC,eAAe;gBAAE,OAAO;YAElC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;YACnD,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC;YAE1F,oFAAoF;YACpF,UAAU,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YAE7E,qEAAqE;YACrE,WAAW,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,aAAa,GAAG,CAAC,IAAI,UAAU,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAChG,CAAC,CAAC;QAEF,iDAAiD;QACjD,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,uBAAuB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAEjG,oEAAoE;QACpE,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;YAC3D,IAAI,CAAC;gBACH,IAAI,CAAC,yBAAyB,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE;;oBACvD,MAAA,IAAI,CAAC,uBAAuB,oDAAI,CAAC;gBACnC,CAAC,CAAC,CAAC;gBACH,IAAI,CAAC,yBAAyB,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC/D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,kEAAkE;gBAClE,2CAA2C;YAC7C,CAAC;QACH,CAAC;QAED,uCAAuC;QACvC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,IAAI,CAAC,uBAAuB,GAAG,GAAG,EAAE;;gBAClC,MAAA,IAAI,CAAC,uBAAuB,oDAAI,CAAC;YACnC,CAAC,CAAC;YACF,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAClE,CAAC;QAED,uCAAuC;QACvC,IAAI,CAAC,mBAAmB,GAAG,GAAG,EAAE;YAC9B,IAAI,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;gBACzD,IAAI,CAAC,eAAe,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;gBACjF,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;YAC9B,CAAC;YAED,IAAI,IAAI,CAAC,yBAAyB,EAAE,CAAC;gBACnC,IAAI,CAAC,yBAAyB,CAAC,UAAU,EAAE,CAAC;gBAC5C,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC;YACxC,CAAC;YAED,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;gBAClE,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;gBACnE,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;YACtC,CAAC;YAED,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;QACtC,CAAC,CAAC;QAEF,4BAA4B;QAC5B,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAGO,UAAU;QAChB,MAAM,UAAU,GAAG,CAAC,WAAW,CAAC,CAAC;QAEjC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAEO,SAAS,CAAC,MAAc,EAAE,SAAyB;QACzD,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAE1D,uCAAuC;QACvC,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,iCAAiC;QACjC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC,CAAC;QAE1E,iDAAiD;QACjD,MAAM,iBAAiB,GAAkB,KAAK,CAAC,IAAI,CACjD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,+BAA+B,CAAC,CAC1D,CAAC;QAEF,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,IAAI,CAC7C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,MAAM,CAC3C,CAAC;QAEF,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,WAAW,MAAM,cAAc,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAEhE,6DAA6D;QAC7D,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACtB,MAAM,MAAM,GAAG,CAAC,CAAC,aAAa,CAAC,4BAA4B,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YAClG,MAAM,MAAM,GAAG,CAAC,CAAC,aAAa,CAAC,4BAA4B,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YAElG,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;gBACxB,OAAO,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1E,CAAC;iBAAM,CAAC;gBACN,OAAO,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,0DAA0D;QAC1D,SAAS,CAAC,SAAS,GAAG,EAAE,CAAC;QACzB,SAAS,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACxB,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAGD,eAAe,CAAC,KAAiE;QAC/E,IAAI,KAAK,CAAC,gBAAgB;YAAE,OAAO;QAEnC,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;QACnC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC/C,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;QACzC,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;IACpC,CAAC;IAGD,oBAAoB,CAAC,KAA2C;QAC9D,IAAI,KAAK,CAAC,gBAAgB;YAAE,OAAO;QAEnC,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC,CAAC;QAE7E,SAAS,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACxB,GAAG,CAAC,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC;IAGD,KAAK,CAAC,iBAAiB,CAAC,KAA6D;QACnF,IAAI,KAAK,CAAC,gBAAgB;YAAE,OAAO;QAEnC,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;QAC/D,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAChF,MAAM,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClF,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAC7D,IAAI,CAAC,YAAY;YAAE,OAAO;QAE1B,MAAM,cAAc,GAAG,YAAY,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QAC7E,cAAc,CAAC,OAAO,GAAG,eAAe,CAAC;QACzC,cAAc,CAAC,aAAa,GAAG,CAAC,eAAe,IAAI,CAAC,gBAAgB,CAAC;IACvE,CAAC;IAED,MAAM;QACJ,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO,CACL,EAAC,IAAI,IACH,KAAK,EAAC,mDAAmD,EACzD,EAAE,EAAE,IAAI,CAAC,WAAW,EACpB,IAAI,EAAC,MAAM,EACX,UAAU,EAAE,IAAI,CAAC,UAAU,EAC3B,QAAQ,EAAC,GAAG,EACZ,IAAI,EAAC,wBAAwB;gBAE7B,WAAK,KAAK,EAAC,oBAAoB,EAAC,IAAI,EAAC,oBAAoB,GAAO;gBAChE,WAAK,KAAK,EAAC,qBAAqB,EAAC,IAAI,EAAC,qBAAqB,GAAO;gBAClE,WAAK,KAAK,EAAC,gCAAgC,EAAC,IAAI,EAAC,sBAAsB;oBACrE,WAAK,KAAK,EAAC,8BAA8B,EAAC,IAAI,EAAC,oBAAoB;wBACjE,WAAK,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,IAAI,EAAC,aAAa;4BAC/C,eAAa,CACT,CACF,CACF,CACD,CACR,CAAC;QACJ,CAAC;QAED,OAAO,CACL,EAAC,IAAI,IACH,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,EACxB,EAAE,EAAE,IAAI,CAAC,WAAW,EACpB,IAAI,EAAC,MAAM,EACX,UAAU,EAAE,IAAI,CAAC,UAAU,EAC3B,QAAQ,EAAC,GAAG,EACZ,IAAI,EAAC,OAAO;YAEZ,eAAa,CACR,CACR,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, Element, Event, EventEmitter, Host, h, Prop, State, Listen } from '@stencil/core';\n\n@Component({\n tag: 'pds-table',\n styleUrls: ['pds-table.scss'],\n shadow: true,\n})\nexport class PdsTable {\n @Element() el: HTMLPdsTableElement;\n private scrollContainer: HTMLElement | null = null;\n private _responsiveHandleScroll: (() => void) | null = null;\n private _responsiveHandleResize: (() => void) | null = null;\n private _responsiveResizeObserver: ResizeObserver | null = null;\n private _teardownResponsive: (() => void) | null = null;\n\n /**\n * Determines if the table displays with reduced table cell padding.\n */\n @Prop() compact: boolean;\n\n /**\n * A unique identifier used for the table `id` attribute.\n */\n @Prop() componentId!: string;\n\n /**\n * Enables the table to be responsive by horizontally scrolling on smaller screens.\n */\n @Prop() responsive: boolean;\n\n /**\n * Determines if the should display a fixed first column.\n */\n @Prop() fixedColumn: boolean;\n\n /**\n * Determines if the table displays checkboxes for selectable rows.\n */\n @Prop() selectable: boolean;\n\n /**\n * Adds divider borders between table rows. The last row will not have a bottom border.\n * @defaultValue false\n */\n @Prop({ reflect: true }) rowDividers: boolean = false;\n\n /**\n * The name of the column to sort by on initial load.\n * Must match the text content of a sortable column header.\n */\n @Prop() defaultSortColumn?: string;\n\n /**\n * The direction to sort the default column on initial load.\n * Only applies if `defaultSortColumn` is set.\n * @defaultValue 'asc'\n */\n @Prop() defaultSortDirection?: 'asc' | 'desc' = 'asc';\n\n /**\n * The name of the column being sorted.\n * @defaultValue null\n */\n @State() sortingColumn: string | null = null;\n\n /**\n * The direction of sorting.\n * @defaultValue 'asc'\n */\n @State() sortingDirection: 'asc' | 'desc' = 'asc';\n\n\n /**\n * Event that is emitted when the checkbox is clicked, carrying the rowIndex and selected value.\n */\n @Event() pdsTableSelect: EventEmitter<{ rowIndex: number; isSelected: boolean }>;\n\n /**\n * Event that is emitted when the select all checkbox is clicked, carrying the selected value.\n */\n @Event() pdsTableSelectAll: EventEmitter<{ isSelected: boolean }>;\n\n componentDidLoad() {\n if (this.responsive) {\n this.setupResponsiveScrolling();\n }\n\n // Apply default sort if specified\n if (this.defaultSortColumn) {\n void this.applyDefaultSort().catch((err) => {\n console.warn('Failed to apply default sort.', err);\n });\n }\n }\n\n /**\n * Applies the default sort configuration on initial load.\n * Finds the matching column header and activates its sort state.\n * @private\n */\n private async applyDefaultSort() {\n // Normalize direction to handle invalid HTML attribute values\n const direction: 'asc' | 'desc' = this.defaultSortDirection === 'desc' ? 'desc' : 'asc';\n\n // Find the matching sortable header cell\n const columnHeaderCells = Array.from(\n this.el.querySelectorAll('pds-table-head-cell[sortable]')\n ) as HTMLPdsTableHeadCellElement[];\n\n const matchingCell = columnHeaderCells.find(\n (cell) => (cell.textContent ?? '').trim() === this.defaultSortColumn\n );\n\n if (matchingCell) {\n const columnName = (matchingCell.textContent ?? '').trim();\n // Sort the table data\n this.sortTable(columnName, direction);\n this.sortingColumn = columnName;\n this.sortingDirection = direction;\n\n // Activate the visual state on the header cell\n await matchingCell.setActiveSort(direction);\n } else {\n console.warn(`Default sort column \"${this.defaultSortColumn}\" not found.`);\n }\n }\n\n disconnectedCallback() {\n if (this._teardownResponsive) {\n this._teardownResponsive();\n this._teardownResponsive = null;\n }\n }\n\n /**\n * Sets up responsive scrolling behavior for the table.\n *\n * This method creates a horizontal scrolling system where:\n * - The table content can scroll horizontally when it exceeds the container width\n * - Scroll shadows appear at the left/right edges to indicate scrollable content\n * - Fixed columns remain sticky during horizontal scrolling\n * - Shadows respect border-radius and don't appear when there's nothing to scroll\n *\n * Architecture:\n * - Host element: Contains everything, respects parent constraints\n * - Container element: Handles horizontal scrolling (overflow-x: auto)\n * - Shadow elements: Positioned fixed relative to host, show scroll indicators\n *\n * @private\n */\n private setupResponsiveScrolling() {\n const container = this.el.shadowRoot?.querySelector('.pds-table-responsive-container') as HTMLElement;\n const leftShadow = this.el.shadowRoot?.querySelector('.scroll-shadow-left') as HTMLElement;\n const rightShadow = this.el.shadowRoot?.querySelector('.scroll-shadow-right') as HTMLElement;\n\n if (!container || !leftShadow || !rightShadow) return;\n\n // Store container reference for cleanup\n this.scrollContainer = container;\n\n /**\n * Updates the visibility of scroll shadows based on current scroll position.\n * Left shadow: Shows when scrolled away from start (hidden if fixedColumn is enabled)\n * Right shadow: Shows when there's content to scroll and not at the end\n */\n this._responsiveHandleScroll = () => {\n if (!this.scrollContainer) return;\n\n const scrollLeft = this.scrollContainer.scrollLeft;\n const maxScrollLeft = this.scrollContainer.scrollWidth - this.scrollContainer.clientWidth;\n\n // Show left shadow when scrolled away from start, but not if there's a fixed column\n leftShadow.style.opacity = (scrollLeft > 0 && !this.fixedColumn) ? '1' : '0';\n\n // Show right shadow only if there's content to scroll AND not at end\n rightShadow.style.opacity = (maxScrollLeft > 0 && scrollLeft < maxScrollLeft - 1) ? '1' : '0';\n };\n\n // Add scroll event listener to container element\n this.scrollContainer.addEventListener('scroll', this._responsiveHandleScroll, { passive: true });\n\n // Add resize observer to update shadows when container size changes\n if (typeof window !== 'undefined' && window.ResizeObserver) {\n try {\n this._responsiveResizeObserver = new ResizeObserver(() => {\n this._responsiveHandleScroll?.();\n });\n this._responsiveResizeObserver.observe(this.scrollContainer);\n } catch (error) {\n // ResizeObserver not available in some environments (e.g., tests)\n // Fall back to window resize listener only\n }\n }\n\n // Listen for window resize as fallback\n if (typeof window !== 'undefined') {\n this._responsiveHandleResize = () => {\n this._responsiveHandleScroll?.();\n };\n window.addEventListener('resize', this._responsiveHandleResize);\n }\n\n // Create teardown function for cleanup\n this._teardownResponsive = () => {\n if (this.scrollContainer && this._responsiveHandleScroll) {\n this.scrollContainer.removeEventListener('scroll', this._responsiveHandleScroll);\n this.scrollContainer = null;\n }\n\n if (this._responsiveResizeObserver) {\n this._responsiveResizeObserver.disconnect();\n this._responsiveResizeObserver = null;\n }\n\n if (typeof window !== 'undefined' && this._responsiveHandleResize) {\n window.removeEventListener('resize', this._responsiveHandleResize);\n this._responsiveHandleResize = null;\n }\n\n this._responsiveHandleScroll = null;\n };\n\n // Initial check after setup\n this._responsiveHandleScroll();\n }\n\n\n private classNames() {\n const classNames = ['pds-table'];\n\n if (this.compact) {\n classNames.push('is-compact');\n }\n\n if (this.responsive) {\n classNames.push('is-responsive');\n }\n\n return classNames.join(' ');\n }\n\n private sortTable(column: string, direction: 'asc' | 'desc') {\n const tableBody = this.el.querySelector('pds-table-body');\n\n // Return early if no table body exists\n if (!tableBody) return;\n\n // Get the rows in the table body\n const tableRows = Array.from(tableBody.querySelectorAll('pds-table-row'));\n\n // Find the column index based on the column name\n const columnHeaderCells: HTMLElement[] = Array.from(\n this.el.querySelectorAll('pds-table-head-cell[sortable]')\n );\n\n const columnHeaderCell = columnHeaderCells.find(\n (cell) => cell.innerText.trim() === column\n );\n\n if (!columnHeaderCell) {\n console.warn(`Column \"${column}\" not found.`);\n return;\n }\n\n const columnIndex = columnHeaderCells.indexOf(columnHeaderCell);\n\n // Sort the rows based on the content of the specified column\n tableRows.sort((a, b) => {\n const valueA = a.querySelector(`pds-table-cell:nth-child(${columnIndex + 1})`).textContent.trim();\n const valueB = b.querySelector(`pds-table-cell:nth-child(${columnIndex + 1})`).textContent.trim();\n\n if (direction === 'asc') {\n return valueA.localeCompare(valueB, undefined, { sensitivity: 'base' });\n } else {\n return valueB.localeCompare(valueA, undefined, { sensitivity: 'base' });\n }\n });\n\n // Clear and append the sorted rows back to the table body\n tableBody.innerHTML = '';\n tableRows.forEach((row) => {\n tableBody.appendChild(row);\n });\n }\n\n @Listen('pdsTableSort')\n handleTableSort(event: CustomEvent<{ column: string; direction: 'asc' | 'desc' }>) {\n if (event.defaultPrevented) return;\n\n const { direction } = event.detail;\n this.sortTable(event.detail.column, direction);\n this.sortingColumn = event.detail.column;\n this.sortingDirection = direction;\n }\n\n @Listen('pdsTableSelectAll')\n handleTableSelectAll(event: CustomEvent<{ isSelected: boolean }>) {\n if (event.defaultPrevented) return;\n\n const pdsTableBody = this.el.querySelector('pds-table-body');\n const tableRows = Array.from(pdsTableBody.querySelectorAll('pds-table-row'));\n\n tableRows.forEach((row) => {\n row.isSelected = event.detail.isSelected;\n });\n }\n\n @Listen('pdsTableRowSelected')\n async handleTableSelect(event: CustomEvent<{ rowIndex: number; isSelected: boolean }>) {\n if (event.defaultPrevented) return;\n\n const allTableRows = this.el.querySelectorAll('pds-table-row');\n const allSelectedRows = Array.from(allTableRows).every((row) => row.isSelected);\n const noneSelectedRows = Array.from(allTableRows).every((row) => !row.isSelected);\n const pdsTableHead = this.el.querySelector('pds-table-head');\n if (!pdsTableHead) return;\n\n const headerCheckbox = pdsTableHead.shadowRoot.querySelector('pds-checkbox');\n headerCheckbox.checked = allSelectedRows;\n headerCheckbox.indeterminate = !allSelectedRows && !noneSelectedRows;\n }\n\n render() {\n if (this.responsive) {\n return (\n <Host\n class=\"pds-table is-responsive pds-table-responsive-host\"\n id={this.componentId}\n role=\"grid\"\n selectable={this.selectable}\n tabindex=\"0\"\n part=\"table responsive-table\"\n >\n <div class=\"scroll-shadow-left\" part=\"scroll-shadow-left\"></div>\n <div class=\"scroll-shadow-right\" part=\"scroll-shadow-right\"></div>\n <div class=\"pds-table-responsive-container\" part=\"responsive-container\">\n <div class=\"pds-table-responsive-wrapper\" part=\"responsive-wrapper\">\n <div class={this.classNames()} part=\"table-inner\">\n <slot></slot>\n </div>\n </div>\n </div>\n </Host>\n );\n }\n\n return (\n <Host\n class={this.classNames()}\n id={this.componentId}\n role=\"grid\"\n selectable={this.selectable}\n tabindex=\"0\"\n part=\"table\"\n >\n <slot></slot>\n </Host>\n );\n }\n}\n"]}
1
+ {"version":3,"file":"pds-table.js","sourceRoot":"","sources":["../../../../src/components/pds-table/pds-table.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Element, Event, EventEmitter, Host, h, Prop, State, Listen } from '@stencil/core';\n\n@Component({\n tag: 'pds-table',\n styleUrls: ['pds-table.scss'],\n shadow: true,\n})\nexport class PdsTable {\n @Element() el: HTMLPdsTableElement;\n private scrollContainer: HTMLElement | null = null;\n private _responsiveHandleScroll: (() => void) | null = null;\n private _responsiveHandleResize: (() => void) | null = null;\n private _responsiveResizeObserver: ResizeObserver | null = null;\n private _teardownResponsive: (() => void) | null = null;\n\n /**\n * Determines if the table displays with reduced table cell padding.\n */\n @Prop() compact: boolean;\n\n /**\n * A unique identifier used for the table `id` attribute.\n */\n @Prop() componentId!: string;\n\n /**\n * Enables the table to be responsive by horizontally scrolling on smaller screens.\n */\n @Prop() responsive: boolean;\n\n /**\n * Determines if the should display a fixed first column.\n */\n @Prop() fixedColumn: boolean;\n\n /**\n * Determines if the table displays checkboxes for selectable rows.\n */\n @Prop() selectable: boolean;\n\n /**\n * Adds divider borders between table rows. The last row will not have a bottom border.\n * @defaultValue false\n */\n @Prop({ reflect: true }) rowDividers: boolean = false;\n\n /**\n * The name of the column to sort by on initial load.\n * Must match the text content of a sortable column header.\n */\n @Prop() defaultSortColumn?: string;\n\n /**\n * The direction to sort the default column on initial load.\n * Only applies if `defaultSortColumn` is set.\n * @defaultValue 'asc'\n */\n @Prop() defaultSortDirection?: 'asc' | 'desc' = 'asc';\n\n /**\n * The name of the column being sorted.\n * @defaultValue null\n */\n @State() sortingColumn: string | null = null;\n\n /**\n * The direction of sorting.\n * @defaultValue 'asc'\n */\n @State() sortingDirection: 'asc' | 'desc' = 'asc';\n\n\n /**\n * Event that is emitted when the checkbox is clicked, carrying the rowIndex and selected value.\n */\n @Event() pdsTableSelect: EventEmitter<{ rowIndex: number; isSelected: boolean }>;\n\n /**\n * Event that is emitted when the select all checkbox is clicked, carrying the selected value.\n */\n @Event() pdsTableSelectAll: EventEmitter<{ isSelected: boolean }>;\n\n componentDidLoad() {\n if (this.responsive) {\n this.setupResponsiveScrolling();\n }\n\n // Apply default sort if specified\n // Use requestAnimationFrame to defer until child components are fully initialized\n if (this.defaultSortColumn) {\n requestAnimationFrame(() => {\n void this.applyDefaultSort().catch((err) => {\n console.warn('Failed to apply default sort.', err);\n });\n });\n }\n }\n\n /**\n * Applies the default sort configuration on initial load.\n * Finds the matching column header and activates its sort state.\n * @private\n */\n private async applyDefaultSort() {\n // Normalize direction to handle invalid HTML attribute values\n const direction: 'asc' | 'desc' = this.defaultSortDirection === 'desc' ? 'desc' : 'asc';\n\n // Find the matching sortable header cell\n const columnHeaderCells = Array.from(\n this.el.querySelectorAll('pds-table-head-cell[sortable]')\n ) as HTMLPdsTableHeadCellElement[];\n\n const matchingCell = columnHeaderCells.find(\n (cell) => (cell.textContent ?? '').trim() === this.defaultSortColumn\n );\n\n if (matchingCell) {\n const columnName = (matchingCell.textContent ?? '').trim();\n // Sort the table data\n this.sortTable(columnName, direction);\n this.sortingColumn = columnName;\n this.sortingDirection = direction;\n\n // Activate the visual state on the header cell\n await matchingCell.setActiveSort(direction);\n } else {\n console.warn(`Default sort column \"${this.defaultSortColumn}\" not found.`);\n }\n }\n\n disconnectedCallback() {\n if (this._teardownResponsive) {\n this._teardownResponsive();\n this._teardownResponsive = null;\n }\n }\n\n /**\n * Sets up responsive scrolling behavior for the table.\n *\n * This method creates a horizontal scrolling system where:\n * - The table content can scroll horizontally when it exceeds the container width\n * - Scroll shadows appear at the left/right edges to indicate scrollable content\n * - Fixed columns remain sticky during horizontal scrolling\n * - Shadows respect border-radius and don't appear when there's nothing to scroll\n *\n * Architecture:\n * - Host element: Contains everything, respects parent constraints\n * - Container element: Handles horizontal scrolling (overflow-x: auto)\n * - Shadow elements: Positioned fixed relative to host, show scroll indicators\n *\n * @private\n */\n private setupResponsiveScrolling() {\n const container = this.el.shadowRoot?.querySelector('.pds-table-responsive-container') as HTMLElement;\n const leftShadow = this.el.shadowRoot?.querySelector('.scroll-shadow-left') as HTMLElement;\n const rightShadow = this.el.shadowRoot?.querySelector('.scroll-shadow-right') as HTMLElement;\n\n if (!container || !leftShadow || !rightShadow) return;\n\n // Store container reference for cleanup\n this.scrollContainer = container;\n\n /**\n * Updates the visibility of scroll shadows based on current scroll position.\n * Left shadow: Shows when scrolled away from start (hidden if fixedColumn is enabled)\n * Right shadow: Shows when there's content to scroll and not at the end\n */\n this._responsiveHandleScroll = () => {\n if (!this.scrollContainer) return;\n\n const scrollLeft = this.scrollContainer.scrollLeft;\n const maxScrollLeft = this.scrollContainer.scrollWidth - this.scrollContainer.clientWidth;\n\n // Show left shadow when scrolled away from start, but not if there's a fixed column\n leftShadow.style.opacity = (scrollLeft > 0 && !this.fixedColumn) ? '1' : '0';\n\n // Show right shadow only if there's content to scroll AND not at end\n rightShadow.style.opacity = (maxScrollLeft > 0 && scrollLeft < maxScrollLeft - 1) ? '1' : '0';\n };\n\n // Add scroll event listener to container element\n this.scrollContainer.addEventListener('scroll', this._responsiveHandleScroll, { passive: true });\n\n // Add resize observer to update shadows when container size changes\n if (typeof window !== 'undefined' && window.ResizeObserver) {\n try {\n this._responsiveResizeObserver = new ResizeObserver(() => {\n this._responsiveHandleScroll?.();\n });\n this._responsiveResizeObserver.observe(this.scrollContainer);\n } catch (error) {\n // ResizeObserver not available in some environments (e.g., tests)\n // Fall back to window resize listener only\n }\n }\n\n // Listen for window resize as fallback\n if (typeof window !== 'undefined') {\n this._responsiveHandleResize = () => {\n this._responsiveHandleScroll?.();\n };\n window.addEventListener('resize', this._responsiveHandleResize);\n }\n\n // Create teardown function for cleanup\n this._teardownResponsive = () => {\n if (this.scrollContainer && this._responsiveHandleScroll) {\n this.scrollContainer.removeEventListener('scroll', this._responsiveHandleScroll);\n this.scrollContainer = null;\n }\n\n if (this._responsiveResizeObserver) {\n this._responsiveResizeObserver.disconnect();\n this._responsiveResizeObserver = null;\n }\n\n if (typeof window !== 'undefined' && this._responsiveHandleResize) {\n window.removeEventListener('resize', this._responsiveHandleResize);\n this._responsiveHandleResize = null;\n }\n\n this._responsiveHandleScroll = null;\n };\n\n // Initial check after setup\n this._responsiveHandleScroll();\n }\n\n\n private classNames() {\n const classNames = ['pds-table'];\n\n if (this.compact) {\n classNames.push('is-compact');\n }\n\n if (this.responsive) {\n classNames.push('is-responsive');\n }\n\n return classNames.join(' ');\n }\n\n private sortTable(column: string, direction: 'asc' | 'desc') {\n const tableBody = this.el.querySelector('pds-table-body');\n\n // Return early if no table body exists\n if (!tableBody) return;\n\n // Get the rows in the table body\n const tableRows = Array.from(tableBody.querySelectorAll('pds-table-row'));\n\n // Find the column index based on the column name\n const columnHeaderCells: HTMLElement[] = Array.from(\n this.el.querySelectorAll('pds-table-head-cell[sortable]')\n );\n\n const columnHeaderCell = columnHeaderCells.find(\n (cell) => cell.innerText.trim() === column\n );\n\n if (!columnHeaderCell) {\n console.warn(`Column \"${column}\" not found.`);\n return;\n }\n\n const columnIndex = columnHeaderCells.indexOf(columnHeaderCell);\n\n // Sort the rows based on the content of the specified column\n tableRows.sort((a, b) => {\n const valueA = a.querySelector(`pds-table-cell:nth-child(${columnIndex + 1})`).textContent.trim();\n const valueB = b.querySelector(`pds-table-cell:nth-child(${columnIndex + 1})`).textContent.trim();\n\n if (direction === 'asc') {\n return valueA.localeCompare(valueB, undefined, { sensitivity: 'base' });\n } else {\n return valueB.localeCompare(valueA, undefined, { sensitivity: 'base' });\n }\n });\n\n // Clear and append the sorted rows back to the table body\n tableBody.innerHTML = '';\n tableRows.forEach((row) => {\n tableBody.appendChild(row);\n });\n }\n\n @Listen('pdsTableSort')\n handleTableSort(event: CustomEvent<{ column: string; direction: 'asc' | 'desc' }>) {\n if (event.defaultPrevented) return;\n\n const { direction } = event.detail;\n this.sortTable(event.detail.column, direction);\n this.sortingColumn = event.detail.column;\n this.sortingDirection = direction;\n }\n\n @Listen('pdsTableSelectAll')\n handleTableSelectAll(event: CustomEvent<{ isSelected: boolean }>) {\n if (event.defaultPrevented) return;\n\n const pdsTableBody = this.el.querySelector('pds-table-body');\n const tableRows = Array.from(pdsTableBody.querySelectorAll('pds-table-row'));\n\n tableRows.forEach((row) => {\n row.isSelected = event.detail.isSelected;\n });\n }\n\n @Listen('pdsTableRowSelected')\n async handleTableSelect(event: CustomEvent<{ rowIndex: number; isSelected: boolean }>) {\n if (event.defaultPrevented) return;\n\n const allTableRows = this.el.querySelectorAll('pds-table-row');\n const allSelectedRows = Array.from(allTableRows).every((row) => row.isSelected);\n const noneSelectedRows = Array.from(allTableRows).every((row) => !row.isSelected);\n const pdsTableHead = this.el.querySelector('pds-table-head');\n if (!pdsTableHead) return;\n\n const headerCheckbox = pdsTableHead.shadowRoot.querySelector('pds-checkbox');\n headerCheckbox.checked = allSelectedRows;\n headerCheckbox.indeterminate = !allSelectedRows && !noneSelectedRows;\n }\n\n render() {\n if (this.responsive) {\n return (\n <Host\n class=\"pds-table is-responsive pds-table-responsive-host\"\n id={this.componentId}\n role=\"grid\"\n selectable={this.selectable}\n tabindex=\"0\"\n part=\"table responsive-table\"\n >\n <div class=\"scroll-shadow-left\" part=\"scroll-shadow-left\"></div>\n <div class=\"scroll-shadow-right\" part=\"scroll-shadow-right\"></div>\n <div class=\"pds-table-responsive-container\" part=\"responsive-container\">\n <div class=\"pds-table-responsive-wrapper\" part=\"responsive-wrapper\">\n <div class={this.classNames()} part=\"table-inner\">\n <slot></slot>\n </div>\n </div>\n </div>\n </Host>\n );\n }\n\n return (\n <Host\n class={this.classNames()}\n id={this.componentId}\n role=\"grid\"\n selectable={this.selectable}\n tabindex=\"0\"\n part=\"table\"\n >\n <slot></slot>\n </Host>\n );\n }\n}\n"]}
@@ -42,7 +42,6 @@ pds-tab {
42
42
  .pds-tab:disabled, .pds-tab.is-disabled {
43
43
  color: var(--pine-color-text-disabled);
44
44
  cursor: not-allowed;
45
- pointer-events: none;
46
45
  }
47
46
  .pds-tab .pds-tab__content {
48
47
  font-family: var(--pine-font-family-body);
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-02-03T21:03:37",
2
+ "timestamp": "2026-02-05T18:59:08",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.38.3",
@@ -1,7 +1,7 @@
1
1
  import { r as registerInstance, h, H as Host, a as getElement } from './index-DHPhrb5T.js';
2
2
  import { a as autoUpdate, c as computePosition, o as offset, f as flip, s as shift } from './floating-ui.dom-BO6p966C.js';
3
3
 
4
- const pdsDropdownMenuCss = ":host{display:block}.is-hidden{display:none}.pds-dropdown-menu--panel{background-color:var(--pine-color-background-container);border-radius:var(--pine-dimension-xs);left:var(--pine-dimension-none);min-width:170px;padding:var(--pine-dimension-xs);position:fixed;z-index:var(--pine-z-index-overlay)}:host-context([data-theme=dark]) .pds-dropdown-menu--panel{border:var(--pine-border)}";
4
+ const pdsDropdownMenuCss = ":host{display:block}.is-hidden{display:none}.pds-dropdown-menu--panel{background-color:var(--pine-color-background-container);border-radius:var(--pine-dimension-xs);left:var(--pine-dimension-none);min-width:170px;padding:var(--pine-dimension-xs);position:fixed;z-index:var(--pine-z-index-overlay)}:host-context([data-theme=dark]) .pds-dropdown-menu--panel{border:var(--pine-border)}::slotted(a),::slotted(button){-ms-flex-align:center;align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;border-radius:var(--pine-dimension-xs);-webkit-box-sizing:border-box;box-sizing:border-box;color:var(--pine-color-text) !important;cursor:pointer;display:-ms-flexbox;display:flex;-ms-flex-positive:1;flex-grow:1;font:var(--pine-typography-body-medium);gap:var(--pine-dimension-xs);margin:calc(var(--pine-border-width) + 2px);padding:var(--pine-dimension-xs);text-align:start;text-decoration:none !important;width:calc(100% - (var(--pine-border-width) + 2px) * 2)}::slotted(.destructive){color:var(--pine-color-danger) !important}::slotted([aria-disabled=true]),::slotted([disabled]){cursor:not-allowed;opacity:0.5;pointer-events:none}";
5
5
 
6
6
  const PdsDropdownMenu = class {
7
7
  constructor(hostRef) {
@@ -28,14 +28,22 @@ const PdsDropdownMenu = class {
28
28
  this.slotEl = event.target;
29
29
  // Get all elements assigned to this slot
30
30
  const assignedElements = this.slotEl.assignedElements();
31
- // ensure assignedElements only contains pds-dropdown-menu-item or pds-dropdown-menu-separator
32
- // if there are other elements, throw an error
33
- const invalidElements = assignedElements.filter(el => el.tagName.toLowerCase() !== 'pds-dropdown-menu-item' && el.tagName.toLowerCase() !== 'pds-dropdown-menu-separator');
31
+ // Allowed elements: pds-dropdown-menu-item, pds-dropdown-menu-separator, <a>, <button>
32
+ // Raw <a> and <button> elements are allowed for edge cases requiring native browser/framework
33
+ // behavior (e.g., Rails UJS, Turbo) that cannot work through Shadow DOM.
34
+ const allowedTags = ['pds-dropdown-menu-item', 'pds-dropdown-menu-separator', 'a', 'button'];
35
+ const invalidElements = assignedElements.filter(el => !allowedTags.includes(el.tagName.toLowerCase()));
34
36
  if (invalidElements.length > 0) {
35
- throw new Error(`pds-dropdown-menu only accepts pds-dropdown-menu-item and pds-dropdown-menu-separator elements`);
37
+ const invalidTags = invalidElements.map(el => el.tagName.toLowerCase()).join(', ');
38
+ console.warn(`pds-dropdown-menu: Unexpected element(s) found: ${invalidTags}. ` +
39
+ `Expected: ${allowedTags.join(', ')}`);
36
40
  }
37
- // Store all menu items for keyboard navigation
38
- this.menuItems = assignedElements.filter(el => el.tagName.toLowerCase() === 'pds-dropdown-menu-item');
41
+ // Store all focusable items for keyboard navigation
42
+ // This includes pds-dropdown-menu-item components and raw <a>/<button> elements
43
+ this.menuItems = assignedElements.filter(el => {
44
+ const tag = el.tagName.toLowerCase();
45
+ return tag === 'pds-dropdown-menu-item' || tag === 'a' || tag === 'button';
46
+ });
39
47
  };
40
48
  // Toggle dropdown open/closed
41
49
  this.toggleDropdown = () => {
@@ -104,31 +112,66 @@ const PdsDropdownMenu = class {
104
112
  this.cleanupAutoUpdate = null;
105
113
  }
106
114
  }
115
+ // Check if a menu item is disabled (handles both component and raw elements)
116
+ isItemDisabled(item) {
117
+ const tagName = item.tagName.toLowerCase();
118
+ if (tagName === 'pds-dropdown-menu-item') {
119
+ return item.disabled;
120
+ }
121
+ else if (tagName === 'button') {
122
+ return item.disabled;
123
+ }
124
+ else if (tagName === 'a') {
125
+ return item.getAttribute('aria-disabled') === 'true';
126
+ }
127
+ return false;
128
+ }
107
129
  // Get the index of the currently focused menu item
108
130
  getFocusedItemIndex() {
109
131
  const activeElement = document.activeElement;
110
132
  if (!activeElement)
111
133
  return -1;
112
- return this.menuItems.findIndex(item => item === activeElement);
134
+ // For raw elements, check direct match
135
+ // For pds-dropdown-menu-item, also check if the active element is inside the shadow root
136
+ return this.menuItems.findIndex(item => {
137
+ if (item === activeElement)
138
+ return true;
139
+ // Check if activeElement is inside the item's shadow root (for pds-dropdown-menu-item)
140
+ if (item.tagName.toLowerCase() === 'pds-dropdown-menu-item') {
141
+ const shadowRoot = item.shadowRoot;
142
+ if (shadowRoot === null || shadowRoot === void 0 ? void 0 : shadowRoot.contains(activeElement))
143
+ return true;
144
+ }
145
+ return false;
146
+ });
113
147
  }
114
148
  // Focus a specific menu item by index
115
149
  focusItemByIndex(index) {
116
- var _a, _b, _c, _d;
150
+ var _a, _b, _c, _d, _e;
117
151
  if (index >= 0 && index < this.menuItems.length) {
118
152
  this.currentFocusIndex = index;
119
- // Focus the inner button/link instead of the host element
120
- const menuItem = this.menuItems[index];
121
- const innerButton = (_a = menuItem.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('button');
122
- const innerLink = (_d = (_c = (_b = menuItem.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('pds-link')) === null || _c === void 0 ? void 0 : _c.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelector('a');
123
- if (innerButton) {
124
- return innerButton.focus();
125
- }
126
- else if (innerLink) {
127
- return innerLink.focus();
153
+ const item = this.menuItems[index];
154
+ const tagName = item.tagName.toLowerCase();
155
+ if (tagName === 'pds-dropdown-menu-item') {
156
+ // For pds-dropdown-menu-item, focus the inner element
157
+ const menuItem = item;
158
+ const innerButton = (_a = menuItem.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('button');
159
+ const innerLink = ((_d = (_c = (_b = menuItem.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('pds-link')) === null || _c === void 0 ? void 0 : _c.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelector('a'))
160
+ || ((_e = menuItem.shadowRoot) === null || _e === void 0 ? void 0 : _e.querySelector('a'));
161
+ if (innerButton) {
162
+ innerButton.focus();
163
+ }
164
+ else if (innerLink) {
165
+ innerLink.focus();
166
+ }
167
+ else {
168
+ // Fallback to focusing the host
169
+ menuItem.focus();
170
+ }
128
171
  }
129
172
  else {
130
- // Fallback to focusing the host if we can't find the inner element
131
- menuItem.focus();
173
+ // For raw <a> or <button> elements, focus directly
174
+ item.focus();
132
175
  }
133
176
  }
134
177
  }
@@ -138,7 +181,7 @@ const PdsDropdownMenu = class {
138
181
  // Skip disabled items
139
182
  let attempts = 0;
140
183
  const maxAttempts = this.menuItems.length;
141
- while (attempts < maxAttempts && this.menuItems[nextIndex].disabled) {
184
+ while (attempts < maxAttempts && this.isItemDisabled(this.menuItems[nextIndex])) {
142
185
  nextIndex = (nextIndex + 1) % this.menuItems.length;
143
186
  attempts++;
144
187
  }
@@ -155,7 +198,7 @@ const PdsDropdownMenu = class {
155
198
  // Skip disabled items
156
199
  let attempts = 0;
157
200
  const maxAttempts = this.menuItems.length;
158
- while (attempts < maxAttempts && this.menuItems[prevIndex].disabled) {
201
+ while (attempts < maxAttempts && this.isItemDisabled(this.menuItems[prevIndex])) {
159
202
  prevIndex = prevIndex <= 0 ? this.menuItems.length - 1 : prevIndex - 1;
160
203
  attempts++;
161
204
  }
@@ -186,7 +229,7 @@ const PdsDropdownMenu = class {
186
229
  if (this.menuItems.length > 0) {
187
230
  // Find first non-disabled item
188
231
  let firstIndex = 0;
189
- while (firstIndex < this.menuItems.length && this.menuItems[firstIndex].disabled) {
232
+ while (firstIndex < this.menuItems.length && this.isItemDisabled(this.menuItems[firstIndex])) {
190
233
  firstIndex++;
191
234
  }
192
235
  if (firstIndex < this.menuItems.length) {
@@ -199,7 +242,7 @@ const PdsDropdownMenu = class {
199
242
  if (this.menuItems.length > 0) {
200
243
  // Find last non-disabled item
201
244
  let lastIndex = this.menuItems.length - 1;
202
- while (lastIndex >= 0 && this.menuItems[lastIndex].disabled) {
245
+ while (lastIndex >= 0 && this.isItemDisabled(this.menuItems[lastIndex])) {
203
246
  lastIndex--;
204
247
  }
205
248
  if (lastIndex >= 0) {
@@ -229,7 +272,7 @@ const PdsDropdownMenu = class {
229
272
  event.preventDefault();
230
273
  // Find the first non-disabled item
231
274
  let firstFocusableIndex = 0;
232
- while (firstFocusableIndex < this.menuItems.length && this.menuItems[firstFocusableIndex].disabled) {
275
+ while (firstFocusableIndex < this.menuItems.length && this.isItemDisabled(this.menuItems[firstFocusableIndex])) {
233
276
  firstFocusableIndex++;
234
277
  }
235
278
  if (firstFocusableIndex < this.menuItems.length) {
@@ -241,7 +284,7 @@ const PdsDropdownMenu = class {
241
284
  event.preventDefault();
242
285
  // Find the first non-disabled item
243
286
  let firstFocusableIndex = 0;
244
- while (firstFocusableIndex < this.menuItems.length && this.menuItems[firstFocusableIndex].disabled) {
287
+ while (firstFocusableIndex < this.menuItems.length && this.isItemDisabled(this.menuItems[firstFocusableIndex])) {
245
288
  firstFocusableIndex++;
246
289
  }
247
290
  if (firstFocusableIndex < this.menuItems.length) {
@@ -264,7 +307,7 @@ const PdsDropdownMenu = class {
264
307
  }
265
308
  }
266
309
  render() {
267
- return (h(Host, { key: 'bedd78a69e84f10abb3c714c02227fa76e255a35', id: this.componentId }, h("slot", { key: 'd2bf56037a85679a677470d04865823966ca19d6', name: "trigger", onSlotchange: this.handleTriggerSlotChange }), h("pds-box", { key: '64f56896103bb6cca6c71020d3d37c375d300c40', "border-radius": "sm", display: "flex", direction: "column", class: "pds-dropdown-menu--panel is-hidden", shadow: "100", role: "menu", "aria-orientation": "vertical", part: "menu-panel" }, h("slot", { key: '0303160562f74fe9d32cc020c4539a7c8fc288a9', onSlotchange: this.handleSlotChange }))));
310
+ return (h(Host, { key: '3144bc264072eccf89cdca45a0b28eb004b5d06e', id: this.componentId }, h("slot", { key: '500288f266dc7ab7e1ac5070e628c31a6ed50861', name: "trigger", onSlotchange: this.handleTriggerSlotChange }), h("pds-box", { key: '4085130e381b8be28e2e36de073c0755a455e30c', "border-radius": "sm", display: "flex", direction: "column", class: "pds-dropdown-menu--panel is-hidden", shadow: "100", role: "menu", "aria-orientation": "vertical", part: "menu-panel" }, h("slot", { key: '2c4d53799576d1c6913df9bb854bfbaf50e5032c', onSlotchange: this.handleSlotChange }))));
268
311
  }
269
312
  get host() { return getElement(this); }
270
313
  };