@pure-ds/core 0.7.32 → 0.7.33

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.
@@ -0,0 +1,9 @@
1
+ export {
2
+ msg,
3
+ str,
4
+ joinStringsAndValues,
5
+ configureLocalization,
6
+ loadLocale,
7
+ setLocale,
8
+ getLocalizationState,
9
+ } from "./localization.js";
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Runtime registry singleton that controls live vs static behavior.
3
+ * Consumers can call `registry.setDesigner(designer)` to enable live mode
4
+ * or `registry.setStaticMode(paths)` to point to static asset modules.
5
+ */
6
+ export interface PDSRegistry {
7
+ /** Attach a designer instance and switch the registry to live mode. */
8
+ setDesigner(designer: any, meta?: { presetName?: string }): void;
9
+ /** Switch to static mode and override static paths (keys: tokens, primitives, components, utilities, styles) */
10
+ setStaticMode(paths?: Record<string, string>): void;
11
+ /** Return a constructable stylesheet for the requested layer or null on failure. */
12
+ getStylesheet(layer: string): Promise<CSSStyleSheet | null>;
13
+ /** Return a BLOB URL (live mode only) for layer imports used in CSS */
14
+ getBlobURL(layer: string): string | null;
15
+ /** 'live' or 'static' */
16
+ readonly mode: string;
17
+ /** true when a live designer instance is registered */
18
+ readonly isLive: boolean;
19
+ /** true when a designer instance exists */
20
+ readonly hasDesigner: boolean;
21
+ }
22
+
23
+ /** A small shape describing component metadata used by the PDS ontology. */
24
+ export interface ComponentDef {
25
+ /** canonical name of the component (e.g., 'Button') */
26
+ name: string;
27
+ /** optional HTML tag name for the component ('pds-button') */
28
+ tag?: string;
29
+ /** documented props and their types/metadata */
30
+ props?: Record<string, any>;
31
+ /** human-friendly description used by the designer */
32
+ description?: string;
33
+ }
34
+
35
+ /**
36
+ * Generator - programmatic API to produce tokens, layered CSS and helper modules from a config.
37
+ * Typical usage:
38
+ * const g = new Generator({ example: true });
39
+ * // tokens may be returned synchronously or via a Promise
40
+ * const tokens = await g.generateTokens?.();
41
+ * const css = await g.generateCSS?.();
42
+ */
43
+ export class Generator {
44
+ constructor(options?: any);
45
+ /** runtime options / config passed to the generator */
46
+ options: any;
47
+ /** generated token object */
48
+ tokens: Record<string, any>;
49
+ /** concatenated CSS (layered) */
50
+ css: string;
51
+ /** Generate the token map (may be async in some implementations) */
52
+ generateTokens?(): Record<string, any> | Promise<Record<string, any>>;
53
+ /** Generate the CSS string (may be async) */
54
+ generateCSS?(): string | Promise<string>;
55
+ }
56
+
57
+ /** Public runtime surface exported as `PDS` */
58
+ export interface PDSEventMap {
59
+ 'pds:ready': CustomEvent<{ mode: 'live' | 'static'; generator?: Generator; config: any; theme: string; autoDefiner?: any }>;
60
+ 'pds:error': CustomEvent<{ error: any }>;
61
+ 'pds:theme:changed': CustomEvent<{ theme: string; requested?: string; source: 'system' | 'programmatic' }>;
62
+ 'pds:config-changed': CustomEvent<{ at: number; mode?: 'live' | 'static'; source?: string; preset?: string }>;
63
+ 'pds:design:updated': CustomEvent<{ config: any; designer?: any }>;
64
+ 'pds:design:field:changed': CustomEvent<{ field: string; config: any }>;
65
+ 'pds:inspector:mode:changed': CustomEvent<{ active: boolean }>;
66
+ 'pds:inspector:deactivate': CustomEvent<{}>;
67
+ 'pds:docs:view': CustomEvent<{ file: string }>;
68
+ }
69
+
70
+ export const PDS: {
71
+ /** Registry singleton to query/adopt styles and control live/static behavior. */
72
+ registry: PDSRegistry;
73
+ /** Live-only accessor for the Generator class. */
74
+ getGenerator?: () => Promise<typeof Generator>;
75
+ /** Presets keyed by id (lowercased). Available in live mode. */
76
+ presets?: Record<string, any>;
77
+ /** Ontology metadata about components (live mode). */
78
+ ontology?: any;
79
+ /** Apply generated styles to the document (live mode). */
80
+ applyStyles?: (generator?: Generator) => void;
81
+ /** Adopt multiple named layers into a ShadowRoot. See `LAYER-ARCHITECTURE.md` for layer ordering. */
82
+ adoptLayers: (shadowRoot: ShadowRoot, layers?: string[], additionalSheets?: CSSStyleSheet[]) => Promise<void>;
83
+ /** Convenience to adopt only primitives/styles commonly needed by components. */
84
+ adoptPrimitives: (shadowRoot: ShadowRoot, additionalSheets?: CSSStyleSheet[]) => Promise<void>;
85
+ /** Create a constructable stylesheet from a CSS string. May throw on invalid CSS in some browsers. */
86
+ createStylesheet: (css: string) => CSSStyleSheet;
87
+ /** Utility to inspect whether runtime is running in live mode. */
88
+ isLiveMode: () => boolean;
89
+ /** Find a component definition for a given DOM element, or null if not matched (live mode). */
90
+ findComponentForElement?: (el: Element) => ComponentDef | null;
91
+ /** Primary unified entry point to start PDS in live or static mode. Default mode is 'live'. */
92
+ start: (config: {
93
+ mode?: 'live' | 'static';
94
+ preset?: string;
95
+ design?: any;
96
+ autoDefine?: {
97
+ /** AutoDefiner is bundled with PDS core; external moduleURL overrides are not supported. */
98
+ baseURL?: string;
99
+ predefine?: string[];
100
+ mapper?: (tag: string) => string | undefined | null | false;
101
+ scanExisting?: boolean;
102
+ observeShadows?: boolean;
103
+ patchAttachShadow?: boolean;
104
+ debounceMs?: number;
105
+ onError?: (tag: string, err: any) => void;
106
+ };
107
+ applyGlobalStyles?: boolean;
108
+ manageTheme?: boolean;
109
+ themeStorageKey?: string;
110
+ // live-only
111
+ preloadStyles?: boolean;
112
+ criticalLayers?: string[];
113
+ // static-only
114
+ staticPaths?: Record<string, string>;
115
+ enhancers?: Array<any>;
116
+ }) => Promise<{ generator?: Generator; config: any; theme: string; autoDefiner?: any }>;
117
+ /** Preload minimal CSS to prevent flash of unstyled content. Call before DOM content renders. */
118
+ preloadCritical?: (config: any, options?: {
119
+ theme?: string;
120
+ layers?: string[];
121
+ }) => void;
122
+ /** EventTarget API (strongly typed for common PDS events). */
123
+ addEventListener: <K extends keyof PDSEventMap>(type: K, listener: (ev: PDSEventMap[K]) => any, options?: boolean | AddEventListenerOptions) => void;
124
+ removeEventListener: <K extends keyof PDSEventMap>(type: K, listener: (ev: PDSEventMap[K]) => any, options?: boolean | EventListenerOptions) => void;
125
+ dispatchEvent: (event: PDSEventMap[keyof PDSEventMap] | Event) => boolean;
126
+ };
127
+
128
+ export { PDS as default };
@@ -0,0 +1,144 @@
1
+ const __SUPPORTED_LOG_LEVELS = new Set(["log", "warn", "error", "debug", "info"]);
2
+ const __PDS_SINGLETON_KEY = "__PURE_DS_PDS_SINGLETON__";
3
+
4
+ let __logProvider = null;
5
+ let __contextProvider = null;
6
+
7
+ function __resolveGlobalPDS() {
8
+ try {
9
+ const scope = typeof globalThis !== "undefined" ? globalThis : window;
10
+ const candidate = scope?.[__PDS_SINGLETON_KEY];
11
+ if (candidate && typeof candidate === "object") {
12
+ return candidate;
13
+ }
14
+ } catch (error) {
15
+ return null;
16
+ }
17
+ return null;
18
+ }
19
+
20
+ function __normalizeContext(context) {
21
+ if (!context || typeof context !== "object") {
22
+ return null;
23
+ }
24
+ return {
25
+ mode: context.mode === "live" || context.mode === "static" ? context.mode : null,
26
+ debug: context.debug === true,
27
+ thisArg: context.thisArg,
28
+ };
29
+ }
30
+
31
+ function __normalizeLevel(level) {
32
+ if (typeof level !== "string") return "log";
33
+ const normalized = level.toLowerCase();
34
+ return __SUPPORTED_LOG_LEVELS.has(normalized) ? normalized : "log";
35
+ }
36
+
37
+ function __resolveContext() {
38
+ if (typeof __contextProvider === "function") {
39
+ try {
40
+ const configuredContext = __normalizeContext(__contextProvider());
41
+ if (configuredContext) {
42
+ return configuredContext;
43
+ }
44
+ } catch (error) {}
45
+ }
46
+
47
+ const globalPDS = __resolveGlobalPDS();
48
+ if (globalPDS) {
49
+ const mode =
50
+ globalPDS?.mode ||
51
+ globalPDS?.compiled?.mode ||
52
+ (globalPDS?.registry?.isLive ? "live" : "static");
53
+ const debug =
54
+ (globalPDS?.debug ||
55
+ globalPDS?.currentConfig?.debug ||
56
+ globalPDS?.currentConfig?.design?.debug ||
57
+ globalPDS?.compiled?.debug ||
58
+ globalPDS?.compiled?.design?.debug ||
59
+ false) === true;
60
+ return {
61
+ mode,
62
+ debug,
63
+ thisArg: globalPDS,
64
+ };
65
+ }
66
+
67
+ return { mode: null, debug: false };
68
+ }
69
+
70
+ function __resolveLogger() {
71
+ if (typeof __logProvider === "function") {
72
+ try {
73
+ const logger = __logProvider();
74
+ if (typeof logger === "function") {
75
+ return logger;
76
+ }
77
+ } catch (error) {}
78
+ }
79
+
80
+ const globalPDS = __resolveGlobalPDS();
81
+ if (typeof globalPDS?.logHandler === "function") {
82
+ return globalPDS.logHandler;
83
+ }
84
+
85
+ return null;
86
+ }
87
+
88
+ function __consoleLog(level, message, ...data) {
89
+ if (typeof console === "undefined") return;
90
+ const method =
91
+ typeof console[level] === "function"
92
+ ? console[level].bind(console)
93
+ : typeof console.log === "function"
94
+ ? console.log.bind(console)
95
+ : null;
96
+ if (!method) return;
97
+
98
+ if (data.length > 0) {
99
+ method(message, ...data);
100
+ } else {
101
+ method(message);
102
+ }
103
+ }
104
+
105
+ function __shouldUseConsoleFallback(level, context) {
106
+ const debugEnabled = context?.debug === true;
107
+ const staticMode = context?.mode === "static";
108
+
109
+ if (staticMode && !debugEnabled) {
110
+ return false;
111
+ }
112
+
113
+ if (!debugEnabled && level !== "error" && level !== "warn") {
114
+ return false;
115
+ }
116
+
117
+ return true;
118
+ }
119
+
120
+ export function configurePDSLogger({ getLogger, getContext } = {}) {
121
+ __logProvider = typeof getLogger === "function" ? getLogger : null;
122
+ __contextProvider = typeof getContext === "function" ? getContext : null;
123
+ }
124
+
125
+ export function pdsLog(level = "log", message, ...data) {
126
+ const normalizedLevel = __normalizeLevel(level);
127
+ const context = __resolveContext();
128
+ const customLogger = __resolveLogger();
129
+
130
+ if (customLogger) {
131
+ try {
132
+ customLogger.call(context?.thisArg, normalizedLevel, message, ...data);
133
+ return;
134
+ } catch (error) {
135
+ __consoleLog("error", "Custom log handler failed:", error);
136
+ }
137
+ }
138
+
139
+ if (!__shouldUseConsoleFallback(normalizedLevel, context)) {
140
+ return;
141
+ }
142
+
143
+ __consoleLog(normalizedLevel, message, ...data);
144
+ }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Toast notification utilities for PDS
3
+ * Ensures pds-toaster component is properly initialized before use
4
+ */
5
+
6
+ /**
7
+ * Ensures pds-toaster exists in DOM and is fully loaded
8
+ * @returns {Promise<HTMLElement>} The pds-toaster element
9
+ * @private
10
+ */
11
+ async function ensureToaster() {
12
+ let toaster = document.querySelector('pds-toaster');
13
+ if (!toaster) {
14
+ toaster = document.createElement('pds-toaster');
15
+ document.body.appendChild(toaster);
16
+ await customElements.whenDefined('pds-toaster');
17
+ }
18
+ return toaster;
19
+ }
20
+
21
+ /**
22
+ * Display a toast notification
23
+ *
24
+ * This method automatically ensures the pds-toaster component exists and is loaded
25
+ * before displaying the notification. The toaster element is appended to document.body
26
+ * if not already present.
27
+ *
28
+ * @param {string} message - The message to display
29
+ * @param {Object} [options={}] - Toast configuration
30
+ * @param {"information"|"success"|"warning"|"error"} [options.type="information"] - Toast type/severity
31
+ * @param {number} [options.duration] - Duration in milliseconds (auto-calculated if not provided based on message length)
32
+ * @param {boolean} [options.closable=true] - Whether the toast can be manually closed
33
+ * @param {boolean} [options.persistent=false] - If true, toast won't auto-dismiss (requires manual close)
34
+ * @param {boolean} [options.html=false] - Render `message` as HTML (trusted content only)
35
+ * @param {{label: string, onClick?: Function, dismissOnClick?: boolean}} [options.action] - Optional action button config
36
+ * @returns {Promise<string>} Toast ID (can be used to dismiss programmatically)
37
+ *
38
+ * @example
39
+ * // Simple success toast
40
+ * await PDS.toast('Changes saved successfully!', { type: 'success' });
41
+ *
42
+ * @example
43
+ * // Error with custom duration
44
+ * await PDS.toast('Failed to save changes', {
45
+ * type: 'error',
46
+ * duration: 8000
47
+ * });
48
+ *
49
+ * @example
50
+ * // Persistent warning (must be manually closed)
51
+ * await PDS.toast('This action cannot be undone', {
52
+ * type: 'warning',
53
+ * persistent: true
54
+ * });
55
+ *
56
+ * @example
57
+ * // Get toast ID to dismiss later
58
+ * const toastId = await PDS.toast('Processing...', { persistent: true });
59
+ * // ... later
60
+ * const toaster = document.querySelector('pds-toaster');
61
+ * toaster.dismissToast(toastId);
62
+ */
63
+ export async function toast(message, options = {}) {
64
+ const toaster = await ensureToaster();
65
+ return toaster.toast(message, options);
66
+ }
67
+
68
+ /**
69
+ * Display a success toast (convenience method)
70
+ *
71
+ * @param {string} message - The success message
72
+ * @param {Object} [options={}] - Additional toast options (type is preset to 'success')
73
+ * @returns {Promise<string>} Toast ID
74
+ *
75
+ * @example
76
+ * await PDS.toast.success('Profile updated!');
77
+ */
78
+ toast.success = async function(message, options = {}) {
79
+ return toast(message, { ...options, type: 'success' });
80
+ };
81
+
82
+ /**
83
+ * Display an error toast (convenience method)
84
+ *
85
+ * @param {string} message - The error message
86
+ * @param {Object} [options={}] - Additional toast options (type is preset to 'error')
87
+ * @returns {Promise<string>} Toast ID
88
+ *
89
+ * @example
90
+ * await PDS.toast.error('Failed to connect to server');
91
+ */
92
+ toast.error = async function(message, options = {}) {
93
+ return toast(message, { ...options, type: 'error' });
94
+ };
95
+
96
+ /**
97
+ * Display a warning toast (convenience method)
98
+ *
99
+ * @param {string} message - The warning message
100
+ * @param {Object} [options={}] - Additional toast options (type is preset to 'warning')
101
+ * @returns {Promise<string>} Toast ID
102
+ *
103
+ * @example
104
+ * await PDS.toast.warning('Session will expire in 5 minutes');
105
+ */
106
+ toast.warning = async function(message, options = {}) {
107
+ return toast(message, { ...options, type: 'warning' });
108
+ };
109
+
110
+ /**
111
+ * Display an information toast (convenience method)
112
+ *
113
+ * @param {string} message - The information message
114
+ * @param {Object} [options={}] - Additional toast options (type is preset to 'information')
115
+ * @returns {Promise<string>} Toast ID
116
+ *
117
+ * @example
118
+ * await PDS.toast.info('New features available!');
119
+ */
120
+ toast.info = async function(message, options = {}) {
121
+ return toast(message, { ...options, type: 'information' });
122
+ };
@@ -1,5 +1,4 @@
1
1
  import { enums } from "./pds-enums.js";
2
- import { PDS } from "../pds-singleton.js";
3
2
 
4
3
  /**
5
4
  * Design config types (SSoT) - mirror generator input and document output impact.
@@ -2674,5 +2673,24 @@ export const PDS_DEFAULT_CONFIG_FORM_SCHEMA = buildDesignConfigFormSchema(
2674
2673
  * @param {...any} data - additional data to log
2675
2674
  */
2676
2675
  export function defaultLog(level = "log", message, ...data) {
2677
- PDS.log(level, message, ...data);
2676
+ const runtimeLogger = globalThis?.PDS?.log;
2677
+ if (typeof runtimeLogger === "function") {
2678
+ runtimeLogger(level, message, ...data);
2679
+ return;
2680
+ }
2681
+
2682
+ if (typeof console === "undefined") return;
2683
+ const method =
2684
+ typeof console[level] === "function"
2685
+ ? console[level].bind(console)
2686
+ : typeof console.log === "function"
2687
+ ? console.log.bind(console)
2688
+ : null;
2689
+ if (!method) return;
2690
+
2691
+ if (data.length > 0) {
2692
+ method(message, ...data);
2693
+ } else {
2694
+ method(message);
2695
+ }
2678
2696
  }
@@ -0,0 +1,49 @@
1
+ export class PDSBase extends EventTarget {
2
+ constructor() {
3
+ super();
4
+ /** @type {'live' | 'static' | null} */
5
+ this.mode = null;
6
+ /** @type {Record<string, any> | null} */
7
+ this.compiled = null;
8
+ /** @type {(level: 'log' | 'warn' | 'error' | 'debug' | 'info', message?: any, ...data: any[]) => void} */
9
+ this.log = () => {};
10
+ /** @type {((level: 'log' | 'warn' | 'error' | 'debug' | 'info', message?: any, ...data: any[]) => void) | null} */
11
+ this.logHandler = null;
12
+ }
13
+ }
14
+
15
+ export const PDS_SINGLETON_KEY = "__PURE_DS_PDS_SINGLETON__";
16
+
17
+ const globalScope = typeof globalThis !== "undefined" ? globalThis : window;
18
+ const existingPDS = globalScope?.[PDS_SINGLETON_KEY];
19
+
20
+ export const PDS =
21
+ existingPDS && typeof existingPDS.addEventListener === "function"
22
+ ? existingPDS
23
+ : new PDSBase();
24
+
25
+ if (globalScope) {
26
+ globalScope[PDS_SINGLETON_KEY] = PDS;
27
+ }
28
+
29
+ if (typeof PDS.log !== "function") {
30
+ PDS.log = (level = "log", message, ...data) => {
31
+ if (typeof console === "undefined") return;
32
+ const method =
33
+ typeof console[level] === "function"
34
+ ? console[level].bind(console)
35
+ : typeof console.log === "function"
36
+ ? console.log.bind(console)
37
+ : null;
38
+ if (!method) return;
39
+ if (data.length > 0) {
40
+ method(message, ...data);
41
+ } else {
42
+ method(message);
43
+ }
44
+ };
45
+ }
46
+
47
+ if (typeof PDS.logHandler !== "function") {
48
+ PDS.logHandler = null;
49
+ }