@pure-ds/core 0.5.4 → 0.5.6

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.
@@ -4,110 +4,21 @@
4
4
  * This file defines all progressive enhancements for the Pure Design System.
5
5
  * Each enhancer has:
6
6
  * - selector: CSS selector to target elements
7
- * - description: Human-readable explanation
8
- * - demoHtml: Example usage markup
9
7
  * - run: Enhancement function (added at the end)
10
8
  */
11
9
 
12
10
  // ============================================================================
13
- // ENHANCEMENT METADATA DEFINITIONS
11
+ // ENHANCEMENT RUNTIME DEFINITIONS
14
12
  // ============================================================================
15
13
 
16
14
  const enhancerDefinitions = [
17
- {
18
- selector: ".accordion",
19
- description:
20
- "Ensures only one <details> element can be open at a time within the accordion.",
21
- demoHtml: `
22
- <div class="accordion">
23
- <details>
24
- <summary>Section 1</summary>
25
- <p>Content for section 1</p>
26
- </details>
27
- <details>
28
- <summary>Section 2</summary>
29
- <p>Content for section 2</p>
30
- </details>
31
- <details>
32
- <summary>Section 3</summary>
33
- <p>Content for section 3</p>
34
- </details>
35
- </div>
36
- `.trim(),
37
- },
38
- {
39
- selector: "nav[data-dropdown]",
40
- description:
41
- "Enhances a nav element with data-dropdown to function as a dropdown menu.",
42
- demoHtml: `
43
- <nav data-dropdown>
44
- <button class="btn-primary">Menu</button>
45
- <menu>
46
- <li><a href="#">Item 1</a></li>
47
- <li><a href="#">Item 2</a></li>
48
- </menu>
49
- </nav>
50
- `.trim(),
51
- },
52
- {
53
- selector: "label[data-toggle]",
54
- description: "Creates a toggle switch element from a checkbox.",
55
- demoHtml: `
56
- <label data-toggle>
57
- <input type="checkbox">
58
- <span data-label>Enable notifications</span>
59
- </label>
60
- `.trim(),
61
- },
62
- {
63
- selector: 'input[type="range"]',
64
- description: "Enhances range inputs with an attached <output>.",
65
- demoHtml: `
66
- <label class="range-output">
67
- <span data-label>Volume</span>
68
- <input type="range" min="0" max="100" value="40">
69
- </label>
70
- `.trim(),
71
- },
72
- {
73
- selector: "form[data-required]",
74
- description:
75
- "Enhances required form fields using an asterisk in the label.",
76
- demoHtml: `
77
- <form data-required action="#" method="post">
78
- <label>
79
- <span>Field Label</span>
80
- <input type="text" required>
81
- </label>
82
- <nav class="form-actions">
83
- <button type="submit" class="btn-primary">Submit</button>
84
- </nav>
85
- </form>
86
- `.trim(),
87
- },
88
- {
89
- selector: "fieldset[role=group][data-open]",
90
- description:
91
- "Enhances a checkbox/radio group to be open (have a way to add and remove items).",
92
- demoHtml: `
93
- <fieldset role="group" data-open>
94
- <label>
95
- <span data-label>Test</span>
96
- <input value="lala" name="test1" type="radio" />
97
- </label>
98
- </fieldset>
99
- `.trim(),
100
- },
101
- {
102
- selector: "button, a[class*='btn-']",
103
- description:
104
- "Automatically manages spinner icon for buttons with .btn-working class",
105
- demoHtml: `
106
- <button class="btn-primary btn-working">
107
- <span>Saving</span>
108
- </button>
109
- `.trim(),
110
- },
15
+ { selector: ".accordion" },
16
+ { selector: "nav[data-dropdown]" },
17
+ { selector: "label[data-toggle]" },
18
+ { selector: 'input[type="range"]' },
19
+ { selector: "form[data-required]" },
20
+ { selector: "fieldset[role=group][data-open]" },
21
+ { selector: "button, a[class*='btn-']" },
111
22
  ];
112
23
 
113
24
  // ============================================================================
@@ -507,12 +418,4 @@ export const defaultPDSEnhancers = enhancerDefinitions.map((meta) => ({
507
418
  run: enhancerRunners.get(meta.selector) || (() => {}),
508
419
  }));
509
420
 
510
- /**
511
- * Metadata-only export for build tools and documentation.
512
- * This is semantically identical to enhancerDefinitions but exported
513
- * for tooling that wants to explicitly access metadata without run functions.
514
- *
515
- * Build tools can safely import defaultPDSEnhancers too - Node.js won't
516
- * execute browser-only DOM code in the run functions.
517
- */
518
- export const defaultPDSEnhancerMetadata = enhancerDefinitions;
421
+ // Metadata lives in pds-enhancers-meta.js (live-mode only).
@@ -6,6 +6,7 @@ import { Generator } from "./pds-generator.js";
6
6
  import { applyStyles, adoptLayers, adoptPrimitives } from "./pds-runtime.js";
7
7
  import { presets, defaultLog } from "./pds-config.js";
8
8
  import { defaultPDSEnhancers } from "./pds-enhancers.js";
9
+ import { defaultPDSEnhancerMetadata } from "./pds-enhancers-meta.js";
9
10
  import { resolvePublicAssetURL } from "./pds-paths.js";
10
11
  import { loadTypographyFonts } from "../common/font-loader.js";
11
12
  import {
@@ -44,6 +45,7 @@ async function __attachLiveAPIs(PDS, { applyResolvedTheme, setupSystemListenerIf
44
45
  PDS.enums = enums;
45
46
  PDS.common = commonModule || {};
46
47
  PDS.presets = presets;
48
+ PDS.enhancerMetadata = defaultPDSEnhancerMetadata;
47
49
  PDS.applyStyles = function(generator) {
48
50
  return applyStyles(generator || Generator.instance);
49
51
  };
package/src/js/pds.d.ts CHANGED
@@ -168,6 +168,8 @@ export class PDS extends EventTarget {
168
168
  static isLiveMode: () => boolean;
169
169
  static findComponentForElement?: (el: Element) => ComponentDef | null;
170
170
  static presets?: Record<string, any>;
171
+ static enhancerMetadata?: Array<{ selector: string; description?: string; demoHtml?: string }>;
172
+ static defaultEnhancers?: Array<any>;
171
173
  static ontology?: any;
172
174
  static enums?: Record<string, any>;
173
175
  static common?: Record<string, any>;
package/src/js/pds.js CHANGED
@@ -64,6 +64,39 @@ import {
64
64
  stripFunctions,
65
65
  } from "./pds-core/pds-start-helpers.js";
66
66
 
67
+ const __slugifyPreset = (str = "") =>
68
+ String(str)
69
+ .toLowerCase()
70
+ .replace(/&/g, " and ")
71
+ .replace(/[^a-z0-9]+/g, "-")
72
+ .replace(/^-+|-+$/g, "");
73
+
74
+ const __defaultLog = function (level = "log", message, ...data) {
75
+ const debug = this?.debug || this?.design?.debug || false;
76
+ if (debug || level === "error" || level === "warn") {
77
+ const method = console[level] || console.log;
78
+ if (data.length > 0) {
79
+ method(message, ...data);
80
+ } else {
81
+ method(message);
82
+ }
83
+ }
84
+ };
85
+
86
+ async function __loadRuntimeConfig(assetRootURL, config = {}) {
87
+ if (config?.runtimeConfig === false) return null;
88
+ if (typeof fetch !== "function") return null;
89
+ const runtimeUrl =
90
+ config?.runtimeConfigURL || `${assetRootURL}pds-runtime-config.json`;
91
+ try {
92
+ const res = await fetch(runtimeUrl, { cache: "no-store" });
93
+ if (!res.ok) return null;
94
+ return await res.json();
95
+ } catch (e) {
96
+ return null;
97
+ }
98
+ }
99
+
67
100
  /** Singleton runtime registry. Use `registry.setLiveMode()` to enable live mode or `registry.setStaticMode()` for static assets */
68
101
  PDS.registry = registry;
69
102
 
@@ -377,8 +410,52 @@ async function staticInit(config) {
377
410
  });
378
411
 
379
412
  // Normalize first-arg to allow { preset, design, enhancers }
380
- const { presets, defaultLog } = await import("./pds-core/pds-config.js");
381
- const normalized = normalizeInitConfig(config, {}, { presets, defaultLog });
413
+ const runtimeConfig = await __loadRuntimeConfig(assetRootURL, config);
414
+ const runtimeDesign =
415
+ runtimeConfig?.config?.design || runtimeConfig?.design || null;
416
+ const runtimePresetLabel =
417
+ runtimeConfig?.config?.preset || runtimeConfig?.preset || "default";
418
+ const runtimePresetId =
419
+ runtimeConfig?.presetId || __slugifyPreset(runtimePresetLabel) || "default";
420
+ const runtimePresets = runtimeDesign
421
+ ? {
422
+ [String(runtimePresetId).toLowerCase()]: runtimeDesign,
423
+ ...(String(runtimePresetId).toLowerCase() !== "default"
424
+ ? { default: runtimeDesign }
425
+ : {}),
426
+ }
427
+ : null;
428
+
429
+ const inlineDesign =
430
+ config?.design && typeof config.design === "object"
431
+ ? stripFunctions(config.design)
432
+ : null;
433
+ const inlinePresetId = __slugifyPreset(config?.preset || "default") || "default";
434
+ const inlinePresets = inlineDesign
435
+ ? {
436
+ [String(inlinePresetId).toLowerCase()]: inlineDesign,
437
+ ...(String(inlinePresetId).toLowerCase() !== "default"
438
+ ? { default: inlineDesign }
439
+ : {}),
440
+ }
441
+ : null;
442
+
443
+ const presets = runtimePresets || config?.presets || inlinePresets || {};
444
+ if (!Object.keys(presets || {}).length) {
445
+ throw new Error(
446
+ "PDS static mode requires preset data. Run pds:export or provide config.presets/config.design."
447
+ );
448
+ }
449
+ const normalizedInput = runtimeConfig?.config
450
+ ? {
451
+ ...runtimeConfig.config,
452
+ ...config,
453
+ preset: config?.preset || runtimePresetId,
454
+ design: inlineDesign || runtimeDesign || runtimeConfig?.config?.design,
455
+ }
456
+ : config;
457
+
458
+ const normalized = normalizeInitConfig(normalizedInput, {}, { presets, defaultLog: __defaultLog });
382
459
  const userEnhancers = normalized.enhancers;
383
460
 
384
461
  // 2) Derive static asset URLs from the normalized public root
@@ -389,7 +466,8 @@ async function staticInit(config) {
389
466
  utilities: `${assetRootURL}styles/pds-utilities.css.js`,
390
467
  styles: `${assetRootURL}styles/pds-styles.css.js`,
391
468
  };
392
- staticPaths = { ...baseStaticPaths, ...staticPaths };
469
+ const runtimePaths = runtimeConfig?.paths || {};
470
+ staticPaths = { ...baseStaticPaths, ...runtimePaths, ...staticPaths };
393
471
 
394
472
  // 3) Static mode registry
395
473
  PDS.registry.setStaticMode(staticPaths);