@pure-ds/core 0.6.10 → 0.6.11

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 (75) hide show
  1. package/custom-elements.json +803 -16
  2. package/dist/types/pds.d.ts +1 -0
  3. package/dist/types/public/assets/js/pds-manager.d.ts +98 -1
  4. package/dist/types/public/assets/js/pds-manager.d.ts.map +1 -1
  5. package/dist/types/public/assets/js/pds.d.ts.map +1 -1
  6. package/dist/types/public/assets/pds/components/pds-live-converter.d.ts +8 -0
  7. package/dist/types/public/assets/pds/components/pds-live-converter.d.ts.map +1 -0
  8. package/dist/types/public/assets/pds/components/pds-live-importer.d.ts +2 -0
  9. package/dist/types/public/assets/pds/components/pds-live-importer.d.ts.map +1 -0
  10. package/dist/types/public/assets/pds/components/pds-live-template-canvas.d.ts +2 -0
  11. package/dist/types/public/assets/pds/components/pds-live-template-canvas.d.ts.map +1 -0
  12. package/dist/types/public/assets/pds/components/pds-omnibox.d.ts.map +1 -1
  13. package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts +20 -0
  14. package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts.map +1 -1
  15. package/dist/types/public/assets/pds/components/pds-toaster.d.ts +1 -1
  16. package/dist/types/public/assets/pds/components/pds-toaster.d.ts.map +1 -1
  17. package/dist/types/public/assets/pds/components/pds-treeview.d.ts +37 -0
  18. package/dist/types/public/assets/pds/components/pds-treeview.d.ts.map +1 -0
  19. package/dist/types/src/js/common/toast.d.ts +8 -0
  20. package/dist/types/src/js/common/toast.d.ts.map +1 -1
  21. package/dist/types/src/js/pds-core/pds-enhancers.d.ts.map +1 -1
  22. package/dist/types/src/js/pds-core/pds-generator.d.ts.map +1 -1
  23. package/dist/types/src/js/pds-core/pds-live.d.ts +2 -1
  24. package/dist/types/src/js/pds-core/pds-live.d.ts.map +1 -1
  25. package/dist/types/src/js/pds-live-manager/conversion-service.d.ts +66 -0
  26. package/dist/types/src/js/pds-live-manager/conversion-service.d.ts.map +1 -0
  27. package/dist/types/src/js/pds-live-manager/import-contract.d.ts +15 -0
  28. package/dist/types/src/js/pds-live-manager/import-contract.d.ts.map +1 -0
  29. package/dist/types/src/js/pds-live-manager/import-history-service.d.ts +32 -0
  30. package/dist/types/src/js/pds-live-manager/import-history-service.d.ts.map +1 -0
  31. package/dist/types/src/js/pds-live-manager/import-service.d.ts +21 -0
  32. package/dist/types/src/js/pds-live-manager/import-service.d.ts.map +1 -0
  33. package/dist/types/src/js/pds-live-manager/template-service.d.ts +17 -0
  34. package/dist/types/src/js/pds-live-manager/template-service.d.ts.map +1 -0
  35. package/dist/types/src/js/pds-manager.d.ts +4 -0
  36. package/dist/types/src/js/pds.d.ts.map +1 -1
  37. package/package.json +6 -2
  38. package/packages/pds-cli/README.md +51 -0
  39. package/packages/pds-cli/bin/pds-import.js +176 -0
  40. package/packages/pds-cli/bin/pds-static.js +15 -0
  41. package/packages/pds-cli/bin/postinstall.mjs +17 -8
  42. package/public/assets/js/app.js +15 -139
  43. package/public/assets/js/pds-manager.js +358 -255
  44. package/public/assets/js/pds.js +7 -7
  45. package/public/assets/pds/components/pds-live-converter.js +47 -0
  46. package/public/assets/pds/components/pds-live-edit.js +760 -43
  47. package/public/assets/pds/components/pds-live-importer.js +772 -0
  48. package/public/assets/pds/components/pds-live-template-canvas.js +171 -0
  49. package/public/assets/pds/components/pds-omnibox.js +136 -2
  50. package/public/assets/pds/components/pds-scrollrow.js +56 -1
  51. package/public/assets/pds/components/pds-toaster.js +50 -5
  52. package/public/assets/pds/components/pds-treeview.js +972 -0
  53. package/public/assets/pds/custom-elements.json +803 -16
  54. package/public/assets/pds/pds-css-complete.json +7 -2
  55. package/public/assets/pds/templates/commerce-scroll-explorer.html +115 -0
  56. package/public/assets/pds/templates/content-brand-showcase.html +110 -0
  57. package/public/assets/pds/templates/feedback-ops-dashboard.html +91 -0
  58. package/public/assets/pds/templates/release-readiness-radar.html +69 -0
  59. package/public/assets/pds/templates/support-command-center.html +92 -0
  60. package/public/assets/pds/templates/templates.json +53 -0
  61. package/public/assets/pds/templates/workspace-settings-lab.html +131 -0
  62. package/public/assets/pds/vscode-custom-data.json +54 -4
  63. package/readme.md +34 -0
  64. package/src/js/pds-core/pds-config.js +9 -9
  65. package/src/js/pds-core/pds-enhancers.js +146 -0
  66. package/src/js/pds-core/pds-generator.js +170 -29
  67. package/src/js/pds-core/pds-live.js +453 -13
  68. package/src/js/pds-live-manager/conversion-service.js +3136 -0
  69. package/src/js/pds-live-manager/import-contract.js +57 -0
  70. package/src/js/pds-live-manager/import-history-service.js +145 -0
  71. package/src/js/pds-live-manager/import-service.js +255 -0
  72. package/src/js/pds-live-manager/tailwind-conversion-rules.json +383 -0
  73. package/src/js/pds-live-manager/template-service.js +170 -0
  74. package/src/js/pds.d.ts +1 -0
  75. package/src/js/pds.js +35 -0
@@ -0,0 +1,131 @@
1
+ <section class="stack-lg" aria-label="Workspace Settings Lab">
2
+ <header class="card surface-elevated stack-sm">
3
+ <h2>Workspace Settings Lab</h2>
4
+ <p class="text-muted">Stress-test form controls, toggles, grouped settings, and responsive surfaces in one place.</p>
5
+ </header>
6
+
7
+ <section class="grid grid-auto-md gap-md">
8
+ <article class="card surface-base stack-sm border-gradient">
9
+ <h3>Profile form</h3>
10
+ <form data-required class="stack-sm">
11
+ <label>
12
+ <span data-label>Name</span>
13
+ <div class="input-icon">
14
+ <pds-icon icon="user"></pds-icon>
15
+ <input type="text" required placeholder="Alex Morgan" />
16
+ </div>
17
+ </label>
18
+ <label>
19
+ <span data-label>Email</span>
20
+ <div class="input-icon">
21
+ <pds-icon icon="envelope"></pds-icon>
22
+ <input type="email" required placeholder="alex@team.dev" />
23
+ </div>
24
+ </label>
25
+ <label>
26
+ <span data-label>Role</span>
27
+ <select>
28
+ <option>Designer</option>
29
+ <option>Developer</option>
30
+ <option>Product Manager</option>
31
+ </select>
32
+ </label>
33
+ <label>
34
+ <span data-label>Notes</span>
35
+ <textarea rows="3" placeholder="Context about this user profile..."></textarea>
36
+ </label>
37
+ <div class="flex gap-sm">
38
+ <button class="btn-primary" type="submit">Save</button>
39
+ <button class="btn-secondary" type="button">Cancel</button>
40
+ </div>
41
+ </form>
42
+ </article>
43
+
44
+ <article class="card surface-subtle stack-sm border-glow">
45
+ <h3>Notification panel (Dropdown)</h3>
46
+ <nav data-dropdown data-mode="auto">
47
+ <button class="btn-outline">Notification settings</button>
48
+ <div class="card surface-overlay grid grid-auto gap-sm">
49
+ <label data-toggle>
50
+ <input type="checkbox" checked />
51
+ <span data-label>Email alerts</span>
52
+ </label>
53
+ <label data-toggle>
54
+ <input type="checkbox" />
55
+ <span data-label>Slack alerts</span>
56
+ </label>
57
+ <label data-toggle>
58
+ <input type="checkbox" checked />
59
+ <span data-label>Weekly digest</span>
60
+ </label>
61
+ <div class="flex gap-sm">
62
+ <button class="btn-primary btn-sm">Apply</button>
63
+ <button class="btn-secondary btn-sm">Reset</button>
64
+ </div>
65
+ </div>
66
+ </nav>
67
+ <blockquote>
68
+ “Dropdown panels and toggle labels should remain readable under all palette combinations.”
69
+ </blockquote>
70
+ </article>
71
+ </section>
72
+
73
+ <section class="card surface-base stack-sm">
74
+ <h3>Settings sections (Accordion)</h3>
75
+ <section class="accordion" aria-label="Workspace settings groups">
76
+ <details open>
77
+ <summary id="settings-privacy">Privacy</summary>
78
+ <div role="region" aria-labelledby="settings-privacy" class="card stack-sm">
79
+ <label data-toggle>
80
+ <input type="checkbox" checked />
81
+ <span data-label>Require 2FA</span>
82
+ </label>
83
+ <label data-toggle>
84
+ <input type="checkbox" />
85
+ <span data-label>Mask sensitive fields</span>
86
+ </label>
87
+ </div>
88
+ </details>
89
+ <details>
90
+ <summary id="settings-appearance">Appearance</summary>
91
+ <div role="region" aria-labelledby="settings-appearance" class="card grid grid-cols-3 gap-sm">
92
+ <button class="btn-primary btn-sm">Primary</button>
93
+ <button class="btn-secondary btn-sm">Secondary</button>
94
+ <button class="btn-outline btn-sm">Outline</button>
95
+ </div>
96
+ </details>
97
+ <details>
98
+ <summary id="settings-audit">Audit & Activity</summary>
99
+ <div role="region" aria-labelledby="settings-audit" class="card stack-sm">
100
+ <article class="card surface-elevated stack-xs">
101
+ <strong>10:42</strong>
102
+ <small class="text-muted">Preset switched for review session.</small>
103
+ </article>
104
+ <article class="card surface-sunken stack-xs">
105
+ <strong>11:07</strong>
106
+ <small class="text-muted">Button radius and input spacing adjusted.</small>
107
+ </article>
108
+ </div>
109
+ </details>
110
+ </section>
111
+ </section>
112
+
113
+ <section class="grid grid-auto-sm gap-md">
114
+ <article class="card surface-elevated stack-sm">
115
+ <h4>State chip panel</h4>
116
+ <div class="flex gap-sm flex-wrap">
117
+ <span class="badge badge-primary">Primary</span>
118
+ <span class="badge badge-success">Success</span>
119
+ <span class="badge badge-warning">Warning</span>
120
+ <span class="badge badge-danger">Danger</span>
121
+ </div>
122
+ </article>
123
+ <article class="card surface-overlay stack-sm border-gradient">
124
+ <h4>Action states</h4>
125
+ <div class="flex gap-sm">
126
+ <button class="btn-primary btn-working" type="button">Saving</button>
127
+ <button class="btn-outline" type="button" disabled>Disabled</button>
128
+ </div>
129
+ </article>
130
+ </section>
131
+ </section>
@@ -689,10 +689,22 @@
689
689
  }
690
690
  ]
691
691
  },
692
+ {
693
+ "name": "COMPONENT_TAG",
694
+ "description": "PdsLiveConverter component"
695
+ },
692
696
  {
693
697
  "name": "EDITOR_TAG",
694
698
  "description": "PdsLiveEdit component"
695
699
  },
700
+ {
701
+ "name": "COMPONENT_TAG",
702
+ "description": "PdsLiveImporter component"
703
+ },
704
+ {
705
+ "name": "COMPONENT_TAG",
706
+ "description": "PdsLiveTemplateCanvas component"
707
+ },
696
708
  {
697
709
  "name": "pds-omnibox",
698
710
  "description": "PdsOmnibox component",
@@ -724,10 +736,6 @@
724
736
  {
725
737
  "name": "icon",
726
738
  "description": ""
727
- },
728
- {
729
- "name": "item-grid",
730
- "description": ""
731
739
  }
732
740
  ]
733
741
  },
@@ -792,6 +800,14 @@
792
800
  "name": "center"
793
801
  }
794
802
  ]
803
+ },
804
+ {
805
+ "name": "tile-min",
806
+ "description": "Minimum tile width (CSS length, e.g. \"250px\")"
807
+ },
808
+ {
809
+ "name": "tile-max",
810
+ "description": "Maximum tile width (CSS length, e.g. \"360px\")"
795
811
  }
796
812
  ]
797
813
  },
@@ -853,6 +869,40 @@
853
869
  "name": "pds-toaster",
854
870
  "description": "AppToaster component"
855
871
  },
872
+ {
873
+ "name": "pds-treeview",
874
+ "description": "PdsTreeview component",
875
+ "attributes": [
876
+ {
877
+ "name": "name",
878
+ "description": ""
879
+ },
880
+ {
881
+ "name": "value",
882
+ "description": ""
883
+ },
884
+ {
885
+ "name": "disabled",
886
+ "description": ""
887
+ },
888
+ {
889
+ "name": "required",
890
+ "description": ""
891
+ },
892
+ {
893
+ "name": "display-only",
894
+ "description": ""
895
+ },
896
+ {
897
+ "name": "expanded-all",
898
+ "description": ""
899
+ },
900
+ {
901
+ "name": "src",
902
+ "description": ""
903
+ }
904
+ ]
905
+ },
856
906
  {
857
907
  "name": "pds-upload",
858
908
  "description": "Drag-and-drop file uploader that participates in native forms.",
package/readme.md CHANGED
@@ -1513,6 +1513,40 @@ npm run pds:css-data # CSS token & class autocomplete
1513
1513
 
1514
1514
  See [INTELLISENSE.md](./INTELLISENSE.md) for setup instructions.
1515
1515
 
1516
+ ### Import External HTML / Styles (`pds-import`)
1517
+
1518
+ Use `pds-import` to run the same import pipeline used by live edit from CLI.
1519
+
1520
+ ```bash
1521
+ # 1) Convert HTML only (no style adoption)
1522
+ node packages/pds-cli/bin/pds-import.js \
1523
+ --type tailwind-html \
1524
+ --mode convert-only \
1525
+ --source ./input.html \
1526
+ --out ./out/import-result.json \
1527
+ --html-out ./out/import-result.html
1528
+
1529
+ # 2) Convert HTML + adopt inferred styles
1530
+ node packages/pds-cli/bin/pds-import.js \
1531
+ --type tailwind-html \
1532
+ --mode adopt-design-and-convert \
1533
+ --source ./input.html \
1534
+ --out ./out/adopt-result.json \
1535
+ --html-out ./out/adopt-result.html \
1536
+ --design-out ./out/adopt-design.json
1537
+ ```
1538
+
1539
+ **Modes**
1540
+ - `convert-only`: outputs converted template HTML only (no design patch application intent)
1541
+ - `adopt-design-and-convert`: outputs converted HTML plus inferred `designPatch`
1542
+
1543
+ **Where output goes**
1544
+ - `--out`: full import result JSON (required)
1545
+ - `--html-out`: writes `result.template.html` when present
1546
+ - `--design-out`: writes `result.designPatch` JSON
1547
+
1548
+ All paths are resolved from your current working directory, and directories are created automatically.
1549
+
1516
1550
  ### Configuration
1517
1551
 
1518
1552
  ```javascript
@@ -1515,7 +1515,7 @@ export const presets = {
1515
1515
  },
1516
1516
  typography: {
1517
1517
  baseFontSize: 17,
1518
- fontScale: 1.5, // More dramatic scale for breathing room
1518
+ fontScale: 1.35, // More dramatic scale for breathing room
1519
1519
  fontFamilyHeadings:
1520
1520
  'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif',
1521
1521
  fontFamilyBody:
@@ -1580,7 +1580,7 @@ export const presets = {
1580
1580
  },
1581
1581
  typography: {
1582
1582
  baseFontSize: 16,
1583
- fontScale: 1.618, // Golden ratio for futuristic feel
1583
+ fontScale: 1.318, // Golden ratio for futuristic feel
1584
1584
  fontFamilyHeadings: "'Space Grotesk', system-ui, sans-serif",
1585
1585
  fontFamilyBody: "'Space Grotesk', system-ui, sans-serif",
1586
1586
  },
@@ -1652,7 +1652,7 @@ export const presets = {
1652
1652
  },
1653
1653
  typography: {
1654
1654
  baseFontSize: 16,
1655
- fontScale: 1.5,
1655
+ fontScale: 1.3,
1656
1656
  fontFamilyHeadings: "'Quicksand', 'Comfortaa', sans-serif",
1657
1657
  fontFamilyBody: "'Quicksand', 'Comfortaa', sans-serif",
1658
1658
  },
@@ -1747,7 +1747,7 @@ export const presets = {
1747
1747
  },
1748
1748
  typography: {
1749
1749
  baseFontSize: 17,
1750
- fontScale: 1.5,
1750
+ fontScale: 1.3,
1751
1751
  fontFamilyHeadings: "'Playfair Display', 'Georgia', serif",
1752
1752
  fontFamilyBody: "'Crimson Text', 'Garamond', serif",
1753
1753
  fontWeightNormal: 400,
@@ -1755,7 +1755,7 @@ export const presets = {
1755
1755
  },
1756
1756
  spatialRhythm: {
1757
1757
  baseUnit: 4,
1758
- scaleRatio: 1.333,
1758
+ scaleRatio: 1.3,
1759
1759
  },
1760
1760
  shape: {
1761
1761
  radiusSize: enums.RadiusSizes.small, // Subtle elegance
@@ -1931,7 +1931,7 @@ export const presets = {
1931
1931
  },
1932
1932
  typography: {
1933
1933
  baseFontSize: 17,
1934
- fontScale: 1.414,
1934
+ fontScale: 1.35,
1935
1935
  fontFamilyHeadings: "'Merriweather', Georgia, serif",
1936
1936
  fontFamilyBody: "'Noto Sans', system-ui, -apple-system, sans-serif",
1937
1937
  },
@@ -2292,8 +2292,8 @@ presets.default = {
2292
2292
  tags: ["app", "featured"],
2293
2293
  description: "Fresh and modern design system with balanced aesthetics and usability",
2294
2294
  options: {
2295
- liquidGlassEffects: true,
2296
- backgroundMesh: 4,
2295
+ liquidGlassEffects: false,
2296
+ backgroundMesh: 0,
2297
2297
  },
2298
2298
 
2299
2299
  form: {
@@ -2433,7 +2433,7 @@ presets.default = {
2433
2433
  densityCompact: 0.8,
2434
2434
  densityNormal: 1.0,
2435
2435
  densityComfortable: 1.2,
2436
- buttonMinHeight: enums.TouchTargetSizes.standard,
2436
+ buttonMinHeight: 30,
2437
2437
  inputMinHeight: 40,
2438
2438
 
2439
2439
  // Layout utility system
@@ -68,6 +68,7 @@ function enhanceDropdown(elem) {
68
68
  }
69
69
 
70
70
  const isMenu = menu.tagName?.toLowerCase() === "menu";
71
+ const VIEWPORT_PADDING = 8;
71
72
  if (isMenu && !menu.hasAttribute("role")) {
72
73
  menu.setAttribute("role", "menu");
73
74
  }
@@ -152,6 +153,145 @@ function enhanceDropdown(elem) {
152
153
  return spaceForRightAligned > spaceForLeftAligned ? "right" : "left";
153
154
  };
154
155
 
156
+ const readLengthToken = (tokenName, fallback = 8) => {
157
+ const raw = getComputedStyle(elem).getPropertyValue(tokenName).trim();
158
+ if (!raw) return fallback;
159
+ const probe = document.createElement("span");
160
+ probe.style.position = "fixed";
161
+ probe.style.visibility = "hidden";
162
+ probe.style.pointerEvents = "none";
163
+ probe.style.height = raw;
164
+ document.body.appendChild(probe);
165
+ const parsed = Number.parseFloat(getComputedStyle(probe).height);
166
+ probe.remove();
167
+ return Number.isFinite(parsed) ? parsed : fallback;
168
+ };
169
+
170
+ const clearFloatingMenuPosition = () => {
171
+ menu.style.removeProperty("position");
172
+ menu.style.removeProperty("left");
173
+ menu.style.removeProperty("top");
174
+ menu.style.removeProperty("right");
175
+ menu.style.removeProperty("bottom");
176
+ menu.style.removeProperty("margin-top");
177
+ menu.style.removeProperty("margin-bottom");
178
+ menu.style.removeProperty("max-width");
179
+ menu.style.removeProperty("max-inline-size");
180
+ menu.style.removeProperty("max-height");
181
+ menu.style.removeProperty("overflow");
182
+ };
183
+
184
+ const reattachFloatingMenu = () => {
185
+ if (menu.getAttribute("aria-hidden") !== "false") return;
186
+ clearFloatingMenuPosition();
187
+ requestAnimationFrame(() => {
188
+ requestAnimationFrame(() => {
189
+ positionFloatingMenu();
190
+ });
191
+ });
192
+ };
193
+
194
+ const positionFloatingMenu = () => {
195
+ if (menu.getAttribute("aria-hidden") !== "false") return;
196
+ const anchorRect = (trigger || elem).getBoundingClientRect();
197
+ const viewport = window.visualViewport;
198
+ const viewportWidth =
199
+ viewport?.width || document.documentElement?.clientWidth || window.innerWidth;
200
+ const viewportHeight =
201
+ viewport?.height || document.documentElement?.clientHeight || window.innerHeight;
202
+ const viewportOffsetLeft = viewport?.offsetLeft || 0;
203
+ const viewportOffsetTop = viewport?.offsetTop || 0;
204
+ const maxMenuWidth = Math.max(1, viewportWidth - VIEWPORT_PADDING * 2);
205
+ const maxMenuHeight = Math.max(1, viewportHeight - VIEWPORT_PADDING * 2);
206
+
207
+ menu.style.maxWidth = `${Math.round(maxMenuWidth)}px`;
208
+ menu.style.maxInlineSize = `${Math.round(maxMenuWidth)}px`;
209
+ menu.style.maxHeight = `${Math.round(maxMenuHeight)}px`;
210
+ menu.style.overflow = "auto";
211
+
212
+ const { width: menuWidth, height: menuHeight } = measureMenuSize();
213
+ const spacing = readLengthToken("--spacing-2", 8);
214
+ const direction = resolveDirection();
215
+ const align = resolveAlign();
216
+
217
+ elem.dataset.dropdownDirection = direction;
218
+ elem.dataset.dropdownAlign = align;
219
+
220
+ let left = align === "right" ? anchorRect.right - menuWidth : anchorRect.left;
221
+ if (menuWidth >= maxMenuWidth - 1) {
222
+ left = viewportOffsetLeft + VIEWPORT_PADDING;
223
+ } else {
224
+ left = Math.max(
225
+ viewportOffsetLeft + VIEWPORT_PADDING,
226
+ Math.min(
227
+ left,
228
+ viewportOffsetLeft + viewportWidth - menuWidth - VIEWPORT_PADDING,
229
+ ),
230
+ );
231
+ }
232
+
233
+ let top =
234
+ direction === "up"
235
+ ? anchorRect.top - spacing - menuHeight
236
+ : anchorRect.bottom + spacing;
237
+ top = Math.max(
238
+ viewportOffsetTop + VIEWPORT_PADDING,
239
+ Math.min(
240
+ top,
241
+ viewportOffsetTop + viewportHeight - menuHeight - VIEWPORT_PADDING,
242
+ ),
243
+ );
244
+
245
+ menu.style.position = "fixed";
246
+ menu.style.left = `${Math.round(left)}px`;
247
+ menu.style.top = `${Math.round(top)}px`;
248
+ menu.style.right = "auto";
249
+ menu.style.bottom = "auto";
250
+ menu.style.marginTop = "0";
251
+ menu.style.marginBottom = "0";
252
+ };
253
+
254
+ let repositionHandler = null;
255
+ const bindReposition = () => {
256
+ if (repositionHandler) return;
257
+ repositionHandler = () => positionFloatingMenu();
258
+ window.addEventListener("resize", repositionHandler);
259
+ window.addEventListener("scroll", repositionHandler, true);
260
+ };
261
+
262
+ const unbindReposition = () => {
263
+ if (!repositionHandler) return;
264
+ window.removeEventListener("resize", repositionHandler);
265
+ window.removeEventListener("scroll", repositionHandler, true);
266
+ repositionHandler = null;
267
+ };
268
+
269
+ let configChangedHandler = null;
270
+ const bindConfigChanged = () => {
271
+ if (configChangedHandler || typeof document === "undefined") return;
272
+ configChangedHandler = () => {
273
+ if (menu.getAttribute("aria-hidden") !== "false") return;
274
+ elem.dataset.dropdownDirection = resolveDirection();
275
+ elem.dataset.dropdownAlign = resolveAlign();
276
+ reattachFloatingMenu();
277
+ setTimeout(() => {
278
+ if (menu.getAttribute("aria-hidden") !== "false") return;
279
+ reattachFloatingMenu();
280
+ }, 50);
281
+ setTimeout(() => {
282
+ if (menu.getAttribute("aria-hidden") !== "false") return;
283
+ reattachFloatingMenu();
284
+ }, 150);
285
+ };
286
+ document.addEventListener("pds:config-changed", configChangedHandler);
287
+ };
288
+
289
+ const unbindConfigChanged = () => {
290
+ if (!configChangedHandler || typeof document === "undefined") return;
291
+ document.removeEventListener("pds:config-changed", configChangedHandler);
292
+ configChangedHandler = null;
293
+ };
294
+
155
295
  // Store click handler reference for cleanup
156
296
  let clickHandler = null;
157
297
 
@@ -160,6 +300,9 @@ function enhanceDropdown(elem) {
160
300
  elem.dataset.dropdownAlign = resolveAlign();
161
301
  menu.setAttribute("aria-hidden", "false");
162
302
  trigger?.setAttribute("aria-expanded", "true");
303
+ bindReposition();
304
+ bindConfigChanged();
305
+ reattachFloatingMenu();
163
306
 
164
307
  // Add click-outside handler when opening
165
308
  if (!clickHandler) {
@@ -182,6 +325,9 @@ function enhanceDropdown(elem) {
182
325
  const closeMenu = () => {
183
326
  menu.setAttribute("aria-hidden", "true");
184
327
  trigger?.setAttribute("aria-expanded", "false");
328
+ unbindReposition();
329
+ unbindConfigChanged();
330
+ clearFloatingMenuPosition();
185
331
 
186
332
  // Remove click-outside handler when closing
187
333
  if (clickHandler) {