@pure-ds/core 0.3.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 (129) hide show
  1. package/CSS-INTELLISENSE-LIMITATION.md +98 -0
  2. package/CSS-INTELLISENSE-QUICK-REF.md +238 -0
  3. package/INTELLISENSE.md +384 -0
  4. package/LICENSE +15 -0
  5. package/custom-elements-manifest.config.js +30 -0
  6. package/custom-elements.json +2003 -0
  7. package/dist/types/index.d.ts +2 -0
  8. package/dist/types/packages/pds-configurator/src/figma-export.d.ts +13 -0
  9. package/dist/types/packages/pds-configurator/src/figma-export.d.ts.map +1 -0
  10. package/dist/types/packages/pds-configurator/src/pds-config-form.d.ts +2 -0
  11. package/dist/types/packages/pds-configurator/src/pds-config-form.d.ts.map +1 -0
  12. package/dist/types/packages/pds-configurator/src/pds-configurator.d.ts +2 -0
  13. package/dist/types/packages/pds-configurator/src/pds-configurator.d.ts.map +1 -0
  14. package/dist/types/packages/pds-configurator/src/pds-demo.d.ts +2 -0
  15. package/dist/types/packages/pds-configurator/src/pds-demo.d.ts.map +1 -0
  16. package/dist/types/pds.config.d.ts +13 -0
  17. package/dist/types/pds.config.d.ts.map +1 -0
  18. package/dist/types/pds.d.ts +408 -0
  19. package/dist/types/public/assets/js/app.d.ts +2 -0
  20. package/dist/types/public/assets/js/app.d.ts.map +1 -0
  21. package/dist/types/public/assets/js/pds.d.ts +23 -0
  22. package/dist/types/public/assets/js/pds.d.ts.map +1 -0
  23. package/dist/types/public/assets/pds/components/pds-calendar.d.ts +23 -0
  24. package/dist/types/public/assets/pds/components/pds-calendar.d.ts.map +1 -0
  25. package/dist/types/public/assets/pds/components/pds-drawer.d.ts +2 -0
  26. package/dist/types/public/assets/pds/components/pds-drawer.d.ts.map +1 -0
  27. package/dist/types/public/assets/pds/components/pds-icon.d.ts +53 -0
  28. package/dist/types/public/assets/pds/components/pds-icon.d.ts.map +1 -0
  29. package/dist/types/public/assets/pds/components/pds-jsonform.d.ts +104 -0
  30. package/dist/types/public/assets/pds/components/pds-jsonform.d.ts.map +1 -0
  31. package/dist/types/public/assets/pds/components/pds-richtext.d.ts +121 -0
  32. package/dist/types/public/assets/pds/components/pds-richtext.d.ts.map +1 -0
  33. package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts +61 -0
  34. package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts.map +1 -0
  35. package/dist/types/public/assets/pds/components/pds-splitpanel.d.ts +1 -0
  36. package/dist/types/public/assets/pds/components/pds-splitpanel.d.ts.map +1 -0
  37. package/dist/types/public/assets/pds/components/pds-tabstrip.d.ts +39 -0
  38. package/dist/types/public/assets/pds/components/pds-tabstrip.d.ts.map +1 -0
  39. package/dist/types/public/assets/pds/components/pds-toaster.d.ts +111 -0
  40. package/dist/types/public/assets/pds/components/pds-toaster.d.ts.map +1 -0
  41. package/dist/types/public/assets/pds/components/pds-upload.d.ts +83 -0
  42. package/dist/types/public/assets/pds/components/pds-upload.d.ts.map +1 -0
  43. package/dist/types/src/js/app.d.ts +2 -0
  44. package/dist/types/src/js/app.d.ts.map +1 -0
  45. package/dist/types/src/js/common/ask.d.ts +22 -0
  46. package/dist/types/src/js/common/ask.d.ts.map +1 -0
  47. package/dist/types/src/js/common/common.d.ts +3 -0
  48. package/dist/types/src/js/common/common.d.ts.map +1 -0
  49. package/dist/types/src/js/common/font-loader.d.ts +24 -0
  50. package/dist/types/src/js/common/font-loader.d.ts.map +1 -0
  51. package/dist/types/src/js/common/msg.d.ts +3 -0
  52. package/dist/types/src/js/common/msg.d.ts.map +1 -0
  53. package/dist/types/src/js/lit.d.ts +25 -0
  54. package/dist/types/src/js/lit.d.ts.map +1 -0
  55. package/dist/types/src/js/pds-configurator/figma-export.d.ts +13 -0
  56. package/dist/types/src/js/pds-configurator/figma-export.d.ts.map +1 -0
  57. package/dist/types/src/js/pds-configurator/pds-config-form.d.ts +2 -0
  58. package/dist/types/src/js/pds-configurator/pds-config-form.d.ts.map +1 -0
  59. package/dist/types/src/js/pds-configurator/pds-configurator.d.ts +2 -0
  60. package/dist/types/src/js/pds-configurator/pds-configurator.d.ts.map +1 -0
  61. package/dist/types/src/js/pds-configurator/pds-demo.d.ts +2 -0
  62. package/dist/types/src/js/pds-configurator/pds-demo.d.ts.map +1 -0
  63. package/dist/types/src/js/pds-core/pds-config.d.ts +758 -0
  64. package/dist/types/src/js/pds-core/pds-config.d.ts.map +1 -0
  65. package/dist/types/src/js/pds-core/pds-enhancer-metadata.d.ts +6 -0
  66. package/dist/types/src/js/pds-core/pds-enhancer-metadata.d.ts.map +1 -0
  67. package/dist/types/src/js/pds-core/pds-enhancers.d.ts +14 -0
  68. package/dist/types/src/js/pds-core/pds-enhancers.d.ts.map +1 -0
  69. package/dist/types/src/js/pds-core/pds-enums.d.ts +87 -0
  70. package/dist/types/src/js/pds-core/pds-enums.d.ts.map +1 -0
  71. package/dist/types/src/js/pds-core/pds-generator.d.ts +741 -0
  72. package/dist/types/src/js/pds-core/pds-generator.d.ts.map +1 -0
  73. package/dist/types/src/js/pds-core/pds-ontology.d.ts +48 -0
  74. package/dist/types/src/js/pds-core/pds-ontology.d.ts.map +1 -0
  75. package/dist/types/src/js/pds-core/pds-paths.d.ts +37 -0
  76. package/dist/types/src/js/pds-core/pds-paths.d.ts.map +1 -0
  77. package/dist/types/src/js/pds-core/pds-query.d.ts +102 -0
  78. package/dist/types/src/js/pds-core/pds-query.d.ts.map +1 -0
  79. package/dist/types/src/js/pds-core/pds-registry.d.ts +40 -0
  80. package/dist/types/src/js/pds-core/pds-registry.d.ts.map +1 -0
  81. package/dist/types/src/js/pds.d.ts +109 -0
  82. package/dist/types/src/js/pds.d.ts.map +1 -0
  83. package/dist/types/src/pds-core/pds-api.d.ts +31 -0
  84. package/dist/types/src/pds-core/pds-api.d.ts.map +1 -0
  85. package/package.json +104 -0
  86. package/packages/pds-cli/README.md +15 -0
  87. package/packages/pds-cli/bin/generate-css-data.js +565 -0
  88. package/packages/pds-cli/bin/generate-manifest.js +352 -0
  89. package/packages/pds-cli/bin/pds-build-icons.js +152 -0
  90. package/packages/pds-cli/bin/pds-dx.js +114 -0
  91. package/packages/pds-cli/bin/pds-static.js +556 -0
  92. package/packages/pds-cli/bin/pds.js +127 -0
  93. package/packages/pds-cli/bin/postinstall.js +380 -0
  94. package/packages/pds-cli/bin/sync-assets.js +252 -0
  95. package/packages/pds-cli/lib/asset-roots.js +47 -0
  96. package/packages/pds-cli/lib/fs-writer.js +75 -0
  97. package/pds.css-data.json +5 -0
  98. package/pds.html-data.json +5 -0
  99. package/public/assets/js/app.js +5719 -0
  100. package/public/assets/js/lit.js +131 -0
  101. package/public/assets/js/pds.js +3423 -0
  102. package/public/assets/pds/components/pds-calendar.js +837 -0
  103. package/public/assets/pds/components/pds-drawer.js +857 -0
  104. package/public/assets/pds/components/pds-icon.js +338 -0
  105. package/public/assets/pds/components/pds-jsonform.js +1775 -0
  106. package/public/assets/pds/components/pds-richtext.js +1035 -0
  107. package/public/assets/pds/components/pds-scrollrow.js +331 -0
  108. package/public/assets/pds/components/pds-splitpanel.js +401 -0
  109. package/public/assets/pds/components/pds-tabstrip.js +251 -0
  110. package/public/assets/pds/components/pds-toaster.js +446 -0
  111. package/public/assets/pds/components/pds-upload.js +657 -0
  112. package/public/assets/pds/custom-elements.json +2003 -0
  113. package/public/assets/pds/icons/pds-icons.svg +498 -0
  114. package/public/assets/pds/pds-css-complete.json +1861 -0
  115. package/public/assets/pds/pds.css-data.json +2152 -0
  116. package/public/assets/pds/vscode-custom-data.json +824 -0
  117. package/readme.md +1870 -0
  118. package/src/js/pds-core/pds-config.js +1162 -0
  119. package/src/js/pds-core/pds-enhancer-metadata.js +75 -0
  120. package/src/js/pds-core/pds-enhancers.js +357 -0
  121. package/src/js/pds-core/pds-enums.js +86 -0
  122. package/src/js/pds-core/pds-generator.js +5317 -0
  123. package/src/js/pds-core/pds-ontology.js +256 -0
  124. package/src/js/pds-core/pds-paths.js +109 -0
  125. package/src/js/pds-core/pds-query.js +571 -0
  126. package/src/js/pds-core/pds-registry.js +129 -0
  127. package/src/js/pds-core/pds.d.ts +129 -0
  128. package/src/js/pds.d.ts +408 -0
  129. package/src/js/pds.js +1579 -0
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Horizontal scrolling row with optional heading and snap alignment controls.
3
+ *
4
+ * @element pds-scrollrow
5
+ * @slot default - Scrollable tile content
6
+ * @slot heading - Optional heading content rendered in the component header
7
+ * @csspart viewport - The scrollable container element
8
+ *
9
+ * @attr {string} label - Accessible label for the scroll region; also used as fallback heading copy
10
+ * @attr {"start"|"center"} snap - Snap alignment for tiles when scrolling (default: start)
11
+ */
12
+ class PdsScrollrow extends HTMLElement {
13
+ #viewport;
14
+ #ro;
15
+ #rendered = false;
16
+ #adopted = false;
17
+
18
+ static get observedAttributes() {
19
+ return ["label", "snap"];
20
+ }
21
+
22
+ constructor() {
23
+ super();
24
+ this.attachShadow({ mode: "open" });
25
+ }
26
+
27
+ static #COMPONENT_CSS = /*css*/`
28
+ :host {
29
+ display: block;
30
+ position: relative;
31
+ --row-gap-def: 10px;
32
+ --tile-min-def: 60px;
33
+ --tile-max-def: 120px;
34
+ --edge-fade-def: 16px;
35
+ }
36
+ section { position: relative; }
37
+ header { display:flex; align-items:baseline; gap:.5rem; margin-bottom:.5rem; }
38
+ header h2 { margin:0; }
39
+ .viewport-wrap { position: relative; }
40
+ .viewport {
41
+ padding-top:10px; padding-bottom:10px; position:relative; overflow-x:auto; overflow-y:hidden;
42
+ scroll-behavior:smooth; scroll-snap-type:x mandatory; -webkit-overflow-scrolling:touch; padding-inline:0.5rem;
43
+ --mask-left:transparent; --mask-right:transparent;
44
+ -webkit-mask-image:linear-gradient(to right, var(--mask-left) 0, #000 var(--edge-fade), #000 calc(100% - var(--edge-fade)), var(--mask-right) 100%);
45
+ mask-image:linear-gradient(to right, var(--mask-left) 0, #000 var(--edge-fade), #000 calc(100% - var(--edge-fade)), var(--mask-right) 100%);
46
+ scrollbar-width:none;
47
+ }
48
+ .viewport::-webkit-scrollbar { display:none; }
49
+ :host(.can-scroll-left) .viewport { --mask-left: rgba(0,0,0,0); }
50
+ :host(.can-scroll-right) .viewport { --mask-right: rgba(0,0,0,0); }
51
+ ul.track { display:flex; gap:var(--row-gap, var(--row-gap-def)); list-style:none; padding:0; margin:0; }
52
+ ::slotted(*) {
53
+ scroll-snap-align: var(--snap-align, start);
54
+ flex:0 0 auto;
55
+ min-inline-size: var(--tile-min, var(--tile-min-def));
56
+ max-inline-size: var(--tile-max, var(--tile-max-def));
57
+ inline-size: clamp(var(--tile-min, var(--tile-min-def)), 40vw, var(--tile-max, var(--tile-max-def)));
58
+ --tile-radius:14px; --tile-bg: var(--color-mostly-trans); --tile-shadow: 0 1px 0 rgba(0,0,0,.06), 0 6px 14px rgba(0,0,0,.12);
59
+ border-radius:var(--tile-radius); overflow:clip; background:var(--tile-bg); box-shadow:var(--tile-shadow); isolation:isolate; overflow:hidden;
60
+ }
61
+ ::slotted(* :focus) { outline-offset:2px; }
62
+ .control { position:absolute; top:50%; transform:translateY(-50%); display:none; place-items:center; inline-size:auto; pointer-events:none; z-index:2; }
63
+ @media (hover:hover) and (pointer:fine) {
64
+ .control { display:grid; opacity:0; transition:opacity .18s ease; }
65
+ .control.left { left: var(--spacing-3, 12px); }
66
+ .control.right { right: var(--spacing-3, 12px); }
67
+ :host(.can-scroll-left) .control.left,
68
+ :host(.can-scroll-right) .control.right { opacity:1; pointer-events:auto; }
69
+ }
70
+ .control button { pointer-events:auto; }
71
+ .control button[disabled]{ opacity:.35; cursor:default; }
72
+ @media (prefers-reduced-motion:reduce){ .viewport { scroll-behavior:auto; } }
73
+ `;
74
+
75
+ async #adopt() {
76
+ if (this.#adopted || !this.shadowRoot) return;
77
+ try {
78
+ if (window.PDS && typeof PDS.createStylesheet === 'function' && typeof PDS.adoptLayers === 'function') {
79
+ const componentSheet = PDS.createStylesheet(PdsScrollrow.#COMPONENT_CSS);
80
+ await PDS.adoptLayers(this.shadowRoot, ['primitives','components', 'utilities'], [componentSheet]);
81
+ this.#adopted = true;
82
+ return;
83
+ }
84
+ } catch (e) {
85
+ console.warn('[pds-scrollrow] adoptLayers failed, falling back', e);
86
+ }
87
+ // Fallback: inline <style>
88
+ const style = document.createElement('style');
89
+ style.textContent = PdsScrollrow.#COMPONENT_CSS;
90
+ this.shadowRoot.prepend(style);
91
+ this.#adopted = true;
92
+ }
93
+
94
+ // Property <-> attribute reflection for ergonomic usage
95
+
96
+ /**
97
+ * Accessible label applied to the scroll region.
98
+ * @returns {string|null}
99
+ */
100
+ get label() {
101
+ // Return null when not set so caller can decide whether to render header
102
+ return this.getAttribute("label");
103
+ }
104
+ /**
105
+ * Update the accessible label and optional fallback heading text.
106
+ * @param {string|null} val
107
+ */
108
+ set label(val) {
109
+ if (val == null) this.removeAttribute("label");
110
+ else this.setAttribute("label", String(val));
111
+ }
112
+ /**
113
+ * Current scroll snap alignment strategy.
114
+ * @returns {"start"|"center"}
115
+ */
116
+ get snap() {
117
+ return this.getAttribute("snap") ?? "start";
118
+ }
119
+ /**
120
+ * Adjust the scroll snap alignment.
121
+ * @param {string|null} val
122
+ */
123
+ set snap(val) {
124
+ if (val == null) this.removeAttribute("snap");
125
+ else this.setAttribute("snap", String(val));
126
+ }
127
+
128
+ /**
129
+ * Lifecycle hook called when the element is inserted into the document.
130
+ */
131
+ connectedCallback() {
132
+ if (!this.#rendered) {
133
+ this.render();
134
+ this.#postRender();
135
+ this.#rendered = true;
136
+ }
137
+ // In case content/size changed while disconnected
138
+ this.#updateControls();
139
+ }
140
+
141
+ /**
142
+ * Lifecycle hook called when the element is removed from the document.
143
+ */
144
+ disconnectedCallback() {
145
+ this.#ro?.disconnect();
146
+ }
147
+
148
+ /**
149
+ * Respond to attribute mutations for `label` and `snap`.
150
+ * @param {string} name
151
+ * @param {string|null} oldValue
152
+ * @param {string|null} newValue
153
+ */
154
+ attributeChangedCallback(name, oldValue, newValue) {
155
+ if (oldValue === newValue) return;
156
+ if (!this.shadowRoot) return;
157
+ switch (name) {
158
+ case "label": {
159
+ const section = this.shadowRoot.querySelector("section");
160
+ // If label was removed, remove the header and aria-label
161
+ if (newValue == null) {
162
+ if (section) section.removeAttribute("aria-label");
163
+ const header = this.shadowRoot.querySelector("header");
164
+ if (header) header.remove();
165
+ } else {
166
+ // Add/update aria-label and header fallback text
167
+ if (section) section.setAttribute("aria-label", newValue);
168
+ const fallbackHeading = this.shadowRoot.querySelector(
169
+ "header h2 span[data-fallback]"
170
+ );
171
+ if (fallbackHeading) {
172
+ fallbackHeading.textContent = newValue;
173
+ } else {
174
+ // Header missing -> create and insert before viewport-wrap
175
+ const viewportWrap = this.shadowRoot.querySelector('.viewport-wrap');
176
+ if (viewportWrap) {
177
+ const header = document.createElement('header');
178
+ header.innerHTML = `<h2><slot name="heading"><span data-fallback>${newValue}</span></slot></h2>`;
179
+ viewportWrap.parentNode.insertBefore(header, viewportWrap);
180
+ }
181
+ }
182
+ }
183
+ break;
184
+ }
185
+ case "snap": {
186
+ this.#applySnap();
187
+ break;
188
+ }
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Render or rerender the component shadow DOM.
194
+ */
195
+ render() {
196
+ const label = this.label;
197
+ const headerHtml = label
198
+ ? `<header>
199
+ <h2>
200
+ <slot name="heading">
201
+ <span data-fallback>${label}</span>
202
+ </slot>
203
+ </h2>
204
+ </header>`
205
+ : "";
206
+
207
+ const sectionOpen = label ? `<section role="region" aria-label="${label}">` : `<section role="region">`;
208
+
209
+ this.shadowRoot.innerHTML = /*html*/`
210
+ ${sectionOpen}
211
+ ${headerHtml}
212
+ <div class="viewport-wrap">
213
+ <div class="viewport" part="viewport" tabindex="0">
214
+ <ul class="track" role="list"><slot></slot></ul>
215
+ </div>
216
+ <div class="control left" aria-hidden="true">
217
+ <button class="btn btn-sm icon-only" part="prev" aria-label="Scroll left">
218
+ <pds-icon icon="arrow-left" size="sm"></pds-icon>
219
+ </button>
220
+ </div>
221
+ <div class="control right" aria-hidden="true">
222
+ <button class="btn btn-sm icon-only" part="next" aria-label="Scroll right">
223
+ <pds-icon icon="arrow-right" size="sm"></pds-icon>
224
+ </button>
225
+ </div>
226
+ </div>
227
+ </section>`;
228
+ // Kick off style adoption after markup so elements exist
229
+ this.#adopt();
230
+ }
231
+
232
+ #postRender() {
233
+ const root = this.shadowRoot;
234
+ this.#viewport = root.querySelector(".viewport");
235
+
236
+ // Events
237
+ this.#viewport.addEventListener("scroll", () => this.#onScroll());
238
+ this.#viewport.addEventListener("keydown", (e) => this.#onKeyDown(e));
239
+ // Update when images inside slotted content finish loading (capture because load doesn't bubble)
240
+ this.#viewport.addEventListener(
241
+ "load",
242
+ () => this.#updateControls(),
243
+ true
244
+ );
245
+
246
+ const [prevBtn, nextBtn] = root.querySelectorAll(".control button");
247
+ if (prevBtn) prevBtn.addEventListener("click", (e) => this.doPage(e));
248
+ if (nextBtn) nextBtn.addEventListener("click", (e) => this.doPage(e));
249
+
250
+ // Slot content changes may affect scrollWidth
251
+ const defaultSlot = root.querySelector("slot:not([name])");
252
+ defaultSlot?.addEventListener("slotchange", () => this.#updateControls());
253
+
254
+ // Apply initial snap alignment
255
+ this.#applySnap();
256
+
257
+ // Observe size changes to refresh controls
258
+ this.#ro = new ResizeObserver(() => this.#updateControls());
259
+ if (this.#viewport) this.#ro.observe(this.#viewport);
260
+
261
+ // Initial state (layout can be delayed; schedule a couple of passes)
262
+ this.#updateControls();
263
+ queueMicrotask(() => this.#updateControls());
264
+ requestAnimationFrame(() => this.#updateControls());
265
+ }
266
+
267
+ #applySnap() {
268
+ const snapAlign = this.snap === "center" ? "center" : "start";
269
+ if (this.#viewport) {
270
+ this.#viewport.style.setProperty("--snap-align", snapAlign);
271
+ }
272
+ }
273
+
274
+ /**
275
+ * Scroll the viewport by roughly one page in the indicated direction.
276
+ * @param {Event} e
277
+ */
278
+ doPage(e) {
279
+ const target = e.currentTarget || e.target;
280
+ const direction = target.getAttribute("part") === "prev" ? -1 : 1;
281
+ this.#page(direction);
282
+ }
283
+
284
+ #onScroll() {
285
+ this.#updateControls();
286
+ }
287
+
288
+ #updateControls() {
289
+ const el = this.#viewport;
290
+ if (!el) return;
291
+ const atStart = el.scrollLeft <= 2;
292
+ const atEnd = Math.ceil(el.scrollLeft + el.clientWidth) >= el.scrollWidth - 2;
293
+ this.classList.toggle("can-scroll-left", !atStart);
294
+ this.classList.toggle("can-scroll-right", !atEnd);
295
+ const buttons = this.shadowRoot.querySelectorAll(".control button");
296
+ const prevBtn = buttons[0];
297
+ const nextBtn = buttons[1];
298
+ if (prevBtn && nextBtn) {
299
+ prevBtn.disabled = atStart;
300
+ nextBtn.disabled = atEnd;
301
+ }
302
+ }
303
+
304
+ #page(direction = 1) {
305
+ const el = this.#viewport;
306
+ if (!el) return;
307
+ const amount = Math.max(1, Math.floor(el.clientWidth * 0.9)) * direction;
308
+ el.scrollBy({ left: amount, behavior: "smooth" });
309
+ }
310
+
311
+ #onKeyDown(e) {
312
+ if (e.key === "ArrowRight") {
313
+ e.preventDefault();
314
+ this.#page(1);
315
+ } else if (e.key === "ArrowLeft") {
316
+ e.preventDefault();
317
+ this.#page(-1);
318
+ } else if (e.key === "Home") {
319
+ e.preventDefault();
320
+ this.#viewport?.scrollTo({ left: 0, behavior: "smooth" });
321
+ } else if (e.key === "End") {
322
+ e.preventDefault();
323
+ this.#viewport?.scrollTo({ left: this.#viewport.scrollWidth, behavior: "smooth" });
324
+ }
325
+ }
326
+ }
327
+
328
+ // Auto-register the component
329
+ if (!customElements.get("pds-scrollrow")) {
330
+ customElements.define("pds-scrollrow", PdsScrollrow);
331
+ }