@pure-ds/core 0.6.10 → 0.7.1

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 (132) hide show
  1. package/.github/copilot-instructions.md +6 -1
  2. package/custom-elements.json +803 -16
  3. package/dist/types/pds.d.ts +1 -0
  4. package/dist/types/public/assets/js/pds-ask.d.ts +2 -0
  5. package/dist/types/public/assets/js/pds-ask.d.ts.map +1 -0
  6. package/dist/types/public/assets/js/pds-auto-definer.d.ts +14 -0
  7. package/dist/types/public/assets/js/pds-auto-definer.d.ts.map +1 -0
  8. package/dist/types/public/assets/js/pds-autocomplete.d.ts +79 -0
  9. package/dist/types/public/assets/js/pds-autocomplete.d.ts.map +1 -0
  10. package/dist/types/public/assets/js/pds-enhancers.d.ts +7 -0
  11. package/dist/types/public/assets/js/pds-enhancers.d.ts.map +1 -0
  12. package/dist/types/public/assets/js/pds-manager.d.ts +98 -1
  13. package/dist/types/public/assets/js/pds-manager.d.ts.map +1 -1
  14. package/dist/types/public/assets/js/pds-toast.d.ts +8 -0
  15. package/dist/types/public/assets/js/pds-toast.d.ts.map +1 -0
  16. package/dist/types/public/assets/js/pds.d.ts.map +1 -1
  17. package/dist/types/public/assets/pds/components/pds-drawer.d.ts +1 -143
  18. package/dist/types/public/assets/pds/components/pds-drawer.d.ts.map +1 -1
  19. package/dist/types/public/assets/pds/components/pds-form.d.ts.map +1 -1
  20. package/dist/types/public/assets/pds/components/pds-icon.d.ts.map +1 -1
  21. package/dist/types/public/assets/pds/components/pds-live-converter.d.ts +8 -0
  22. package/dist/types/public/assets/pds/components/pds-live-converter.d.ts.map +1 -0
  23. package/dist/types/public/assets/pds/components/pds-live-importer.d.ts +2 -0
  24. package/dist/types/public/assets/pds/components/pds-live-importer.d.ts.map +1 -0
  25. package/dist/types/public/assets/pds/components/pds-live-template-canvas.d.ts +2 -0
  26. package/dist/types/public/assets/pds/components/pds-live-template-canvas.d.ts.map +1 -0
  27. package/dist/types/public/assets/pds/components/pds-omnibox.d.ts.map +1 -1
  28. package/dist/types/public/assets/pds/components/pds-richtext.d.ts.map +1 -1
  29. package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts +1 -63
  30. package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts.map +1 -1
  31. package/dist/types/public/assets/pds/components/pds-splitpanel.d.ts +1 -89
  32. package/dist/types/public/assets/pds/components/pds-splitpanel.d.ts.map +1 -1
  33. package/dist/types/public/assets/pds/components/pds-theme.d.ts +1 -22
  34. package/dist/types/public/assets/pds/components/pds-theme.d.ts.map +1 -1
  35. package/dist/types/public/assets/pds/components/pds-toaster.d.ts +1 -1
  36. package/dist/types/public/assets/pds/components/pds-toaster.d.ts.map +1 -1
  37. package/dist/types/public/assets/pds/components/pds-treeview.d.ts +37 -0
  38. package/dist/types/public/assets/pds/components/pds-treeview.d.ts.map +1 -0
  39. package/dist/types/public/assets/pds/components/pds-upload.d.ts.map +1 -1
  40. package/dist/types/src/js/common/ask.d.ts.map +1 -1
  41. package/dist/types/src/js/common/toast.d.ts +8 -0
  42. package/dist/types/src/js/common/toast.d.ts.map +1 -1
  43. package/dist/types/src/js/pds-ask.d.ts +2 -0
  44. package/dist/types/src/js/pds-ask.d.ts.map +1 -0
  45. package/dist/types/src/js/pds-auto-definer.d.ts +2 -0
  46. package/dist/types/src/js/pds-auto-definer.d.ts.map +1 -0
  47. package/dist/types/src/js/pds-autocomplete.d.ts +2 -0
  48. package/dist/types/src/js/pds-autocomplete.d.ts.map +1 -0
  49. package/dist/types/src/js/pds-core/pds-enhancers.d.ts.map +1 -1
  50. package/dist/types/src/js/pds-core/pds-generator.d.ts.map +1 -1
  51. package/dist/types/src/js/pds-core/pds-live.d.ts +2 -1
  52. package/dist/types/src/js/pds-core/pds-live.d.ts.map +1 -1
  53. package/dist/types/src/js/pds-core/pds-start-helpers.d.ts.map +1 -1
  54. package/dist/types/src/js/pds-enhancers.d.ts +2 -0
  55. package/dist/types/src/js/pds-enhancers.d.ts.map +1 -0
  56. package/dist/types/src/js/pds-live-manager/conversion-service.d.ts +66 -0
  57. package/dist/types/src/js/pds-live-manager/conversion-service.d.ts.map +1 -0
  58. package/dist/types/src/js/pds-live-manager/import-contract.d.ts +15 -0
  59. package/dist/types/src/js/pds-live-manager/import-contract.d.ts.map +1 -0
  60. package/dist/types/src/js/pds-live-manager/import-history-service.d.ts +32 -0
  61. package/dist/types/src/js/pds-live-manager/import-history-service.d.ts.map +1 -0
  62. package/dist/types/src/js/pds-live-manager/import-service.d.ts +21 -0
  63. package/dist/types/src/js/pds-live-manager/import-service.d.ts.map +1 -0
  64. package/dist/types/src/js/pds-live-manager/template-service.d.ts +17 -0
  65. package/dist/types/src/js/pds-live-manager/template-service.d.ts.map +1 -0
  66. package/dist/types/src/js/pds-manager.d.ts +4 -0
  67. package/dist/types/src/js/pds-toast.d.ts +2 -0
  68. package/dist/types/src/js/pds-toast.d.ts.map +1 -0
  69. package/dist/types/src/js/pds.d.ts.map +1 -1
  70. package/package.json +11 -5
  71. package/packages/pds-cli/README.md +60 -0
  72. package/packages/pds-cli/bin/pds-import.js +176 -0
  73. package/packages/pds-cli/bin/pds-static.js +27 -1
  74. package/packages/pds-cli/bin/postinstall.mjs +17 -8
  75. package/packages/pds-cli/bin/templates/bootstrap/pds.config.js +1 -5
  76. package/packages/pds-cli/bin/templates/bootstrap/public/index.html +2 -1
  77. package/packages/pds-cli/bin/templates/starter-templates.js +1 -3
  78. package/public/assets/js/app.js +9 -163
  79. package/public/assets/js/pds-ask.js +25 -0
  80. package/public/assets/js/pds-auto-definer.js +1 -0
  81. package/public/assets/js/pds-autocomplete.js +7 -0
  82. package/public/assets/js/pds-enhancers.js +1 -0
  83. package/public/assets/js/pds-manager.js +370 -267
  84. package/public/assets/js/pds-toast.js +1 -0
  85. package/public/assets/js/pds.js +2 -32
  86. package/public/assets/pds/components/pds-calendar.js +2 -2
  87. package/public/assets/pds/components/pds-drawer.js +1 -1
  88. package/public/assets/pds/components/pds-form.js +7 -6
  89. package/public/assets/pds/components/pds-icon.js +12 -9
  90. package/public/assets/pds/components/pds-live-converter.js +47 -0
  91. package/public/assets/pds/components/pds-live-edit.js +758 -44
  92. package/public/assets/pds/components/pds-live-importer.js +773 -0
  93. package/public/assets/pds/components/pds-live-template-canvas.js +172 -0
  94. package/public/assets/pds/components/pds-omnibox.js +147 -3
  95. package/public/assets/pds/components/pds-richtext.js +2 -0
  96. package/public/assets/pds/components/pds-scrollrow.js +61 -2
  97. package/public/assets/pds/components/pds-splitpanel.js +3 -1
  98. package/public/assets/pds/components/pds-theme.js +2 -0
  99. package/public/assets/pds/components/pds-toaster.js +52 -5
  100. package/public/assets/pds/components/pds-treeview.js +974 -0
  101. package/public/assets/pds/components/pds-upload.js +2 -0
  102. package/public/assets/pds/core/pds-ask.js +25 -0
  103. package/public/assets/pds/core/pds-auto-definer.js +1 -0
  104. package/public/assets/pds/core/pds-autocomplete.js +7 -0
  105. package/public/assets/pds/core/pds-enhancers.js +1 -0
  106. package/public/assets/pds/core/pds-manager.js +3646 -0
  107. package/public/assets/pds/core/pds-toast.js +1 -0
  108. package/public/assets/pds/core.js +2 -0
  109. package/public/assets/pds/custom-elements.json +803 -16
  110. package/public/assets/pds/pds-css-complete.json +7 -2
  111. package/public/assets/pds/templates/commerce-scroll-explorer.html +115 -0
  112. package/public/assets/pds/templates/content-brand-showcase.html +110 -0
  113. package/public/assets/pds/templates/feedback-ops-dashboard.html +91 -0
  114. package/public/assets/pds/templates/release-readiness-radar.html +69 -0
  115. package/public/assets/pds/templates/support-command-center.html +92 -0
  116. package/public/assets/pds/templates/templates.json +53 -0
  117. package/public/assets/pds/templates/workspace-settings-lab.html +131 -0
  118. package/public/assets/pds/vscode-custom-data.json +54 -4
  119. package/readme.md +38 -1
  120. package/src/js/pds-core/pds-config.js +9 -9
  121. package/src/js/pds-core/pds-enhancers.js +146 -0
  122. package/src/js/pds-core/pds-generator.js +170 -29
  123. package/src/js/pds-core/pds-live.js +456 -13
  124. package/src/js/pds-core/pds-start-helpers.js +5 -1
  125. package/src/js/pds-live-manager/conversion-service.js +3135 -0
  126. package/src/js/pds-live-manager/import-contract.js +57 -0
  127. package/src/js/pds-live-manager/import-history-service.js +145 -0
  128. package/src/js/pds-live-manager/import-service.js +255 -0
  129. package/src/js/pds-live-manager/tailwind-conversion-rules.json +383 -0
  130. package/src/js/pds-live-manager/template-service.js +170 -0
  131. package/src/js/pds.d.ts +1 -0
  132. package/src/js/pds.js +192 -12
@@ -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
@@ -571,6 +571,7 @@ PDS.dispatchEvent(new CustomEvent('pds:toast', {
571
571
  <script type="importmap">
572
572
  {
573
573
  "imports": {
574
+ "#pds": "/assets/pds/core.js",
574
575
  "#showdown": "https://cdn.jsdelivr.net/npm/showdown@2.1.0/+esm"
575
576
  }
576
577
  }
@@ -1405,6 +1406,7 @@ await PDS.start({ design: myPreset });
1405
1406
  <script type="importmap">
1406
1407
  {
1407
1408
  "imports": {
1409
+ "#pds": "https://cdn.jsdelivr.net/npm/@pure-ds/core@latest/public/assets/pds/core.js",
1408
1410
  "#pds/lit": "https://cdn.jsdelivr.net/npm/@pure-ds/core@latest/public/assets/pds/external/lit.js"
1409
1411
  }
1410
1412
  }
@@ -1414,7 +1416,7 @@ await PDS.start({ design: myPreset });
1414
1416
  <button class="btn-primary">Click me</button>
1415
1417
 
1416
1418
  <script type="module">
1417
- import { PDS } from 'https://cdn.jsdelivr.net/npm/@pure-ds/core@latest/public/assets/js/pds.js';
1419
+ import { PDS } from '#pds';
1418
1420
 
1419
1421
  await PDS.start({
1420
1422
  mode: 'static',
@@ -1513,6 +1515,40 @@ npm run pds:css-data # CSS token & class autocomplete
1513
1515
 
1514
1516
  See [INTELLISENSE.md](./INTELLISENSE.md) for setup instructions.
1515
1517
 
1518
+ ### Import External HTML / Styles (`pds-import`)
1519
+
1520
+ Use `pds-import` to run the same import pipeline used by live edit from CLI.
1521
+
1522
+ ```bash
1523
+ # 1) Convert HTML only (no style adoption)
1524
+ node packages/pds-cli/bin/pds-import.js \
1525
+ --type tailwind-html \
1526
+ --mode convert-only \
1527
+ --source ./input.html \
1528
+ --out ./out/import-result.json \
1529
+ --html-out ./out/import-result.html
1530
+
1531
+ # 2) Convert HTML + adopt inferred styles
1532
+ node packages/pds-cli/bin/pds-import.js \
1533
+ --type tailwind-html \
1534
+ --mode adopt-design-and-convert \
1535
+ --source ./input.html \
1536
+ --out ./out/adopt-result.json \
1537
+ --html-out ./out/adopt-result.html \
1538
+ --design-out ./out/adopt-design.json
1539
+ ```
1540
+
1541
+ **Modes**
1542
+ - `convert-only`: outputs converted template HTML only (no design patch application intent)
1543
+ - `adopt-design-and-convert`: outputs converted HTML plus inferred `designPatch`
1544
+
1545
+ **Where output goes**
1546
+ - `--out`: full import result JSON (required)
1547
+ - `--html-out`: writes `result.template.html` when present
1548
+ - `--design-out`: writes `result.designPatch` JSON
1549
+
1550
+ All paths are resolved from your current working directory, and directories are created automatically.
1551
+
1516
1552
  ### Configuration
1517
1553
 
1518
1554
  ```javascript
@@ -1785,6 +1821,7 @@ export default {
1785
1821
  <script type="importmap">
1786
1822
  {
1787
1823
  "imports": {
1824
+ "#pds": "/assets/pds/core.js",
1788
1825
  "#pds/lit": "/assets/pds/external/lit.js"
1789
1826
  }
1790
1827
  }
@@ -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) {