@pure-ds/core 0.4.5 β†’ 0.4.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.
@@ -21,7 +21,7 @@
21
21
  *
22
22
  * 5. Completely custom actions (hides default buttons):
23
23
  * <pds-jsonform .jsonSchema=${schema} hide-actions>
24
- * <div slot="actions" style="display: flex; gap: 1rem;">
24
+ * <div slot="actions" class="flex gap-md">
25
25
  * <button type="submit" class="btn btn-primary">Custom Submit</button>
26
26
  * <button type="button" class="btn">Custom Action</button>
27
27
  * </div>
@@ -1 +1 @@
1
- {"version":3,"file":"pds-jsonform.d.ts","sourceRoot":"","sources":["../../../../../../public/assets/pds/components/pds-jsonform.js"],"names":[],"mappings":"AAgCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;IACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAcE;IAGF,yBAEC;IAaC,gBAA2B;IAC3B,cAAyB;IACzB,aAAwB;IACxB,YAAuB;IACvB,eAAoB;IACpB,qBAAwB;IACxB,oBAA2B;IAC3B,mBAAyB;IACzB,mBAAsB;IACtB,oBAAuB;IAiBzB,8CAEC;IACD,4BAEC;IAGD,oBAEC;IAkBD;;;MAIC;IAED,uBAEC;IAED,0BAMC;IAGD,+BAyBC;IA+ND,cA2CC;;CA+4CF"}
1
+ {"version":3,"file":"pds-jsonform.d.ts","sourceRoot":"","sources":["../../../../../../public/assets/pds/components/pds-jsonform.js"],"names":[],"mappings":"AAgCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;IACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAcE;IAGF,yBAEC;IAaC,gBAA2B;IAC3B,cAAyB;IACzB,aAAwB;IACxB,YAAuB;IACvB,eAAoB;IACpB,qBAAwB;IACxB,oBAA2B;IAC3B,mBAAyB;IACzB,mBAAsB;IACtB,oBAAuB;IAiBzB,8CAEC;IACD,4BAEC;IAGD,oBAEC;IAkBD;;;MAIC;IAED,uBAEC;IAED,0BAMC;IAGD,+BAyBC;IA+ND,cAyCC;;CA63CF"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pure-ds/core",
3
3
  "shortname": "pds",
4
- "version": "0.4.5",
4
+ "version": "0.4.6",
5
5
  "description": "Pure Design System - Why develop a Design System when you can generate one?",
6
6
  "repository": {
7
7
  "type": "git",
@@ -3684,7 +3684,7 @@ export const pdsConfig = ${JSON.stringify(this.config,null,2)};
3684
3684
  `,setTimeout(()=>{p.innerHTML=`
3685
3685
  <pds-icon icon="clipboard" size="sm"></pds-icon>
3686
3686
  Copy HTML
3687
- `},2e3)})})},100)}async loadShiki(){if(this.#a)return this.#a;if(this.#e){for(;this.#e;)await new Promise(r=>setTimeout(r,100));return this.#a}this.#e=!0;try{let r=await import("https://esm.sh/shiki@1.0.0");return this.#a=await r.getHighlighter({themes:["dark-plus"],langs:["html"]}),this.#a}catch(r){return console.error("Failed to load Shiki:",r),null}finally{this.#e=!1}}async highlightWithShiki(r){let e=await this.loadShiki();if(!e)return this.escapeHTML(r);try{let a=e.codeToHtml(r,{lang:"html",theme:"dark-plus"}).match(/<code[^>]*>([\s\S]*)<\/code>/);return a?a[1]:this.escapeHTML(r)}catch(t){return console.error("Shiki highlighting failed:",t),this.escapeHTML(r)}}escapeHTML(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}async getShowdownConverter(){if(this._showdown)return this._showdown;let r=await this.loadShowdownFromCDN();return!r||!r.Converter?null:(this._showdown=new r.Converter({ghCompatibleHeaderId:!0,tables:!0,strikethrough:!0,tasklists:!0}),this._showdown)}async loadShowdownFromCDN(){if(typeof window<"u"&&window.showdown)return window.showdown;if(this._showdownLoading){for(;this._showdownLoading;)await new Promise(e=>setTimeout(e,50));return window.showdown||null}this._showdownLoading=!0;let r=["https://cdn.jsdelivr.net/npm/showdown@2.1.0/dist/showdown.min.js","https://unpkg.com/showdown@2.1.0/dist/showdown.min.js"];for(let e of r)try{if(await this._injectScript(e,"showdown"),window.showdown)return this._showdownLoading=!1,window.showdown}catch{}return this._showdownLoading=!1,null}_injectScript(r,e){return new Promise((t,a)=>{if(document.querySelector(`script[data-lib="${e}"][src="${r}"]`)){setTimeout(t,0);return}let o=document.createElement("script");o.src=r,o.async=!0,o.defer=!0,o.dataset.lib=e||"lib",o.onload=()=>t(),o.onerror=()=>{o.remove(),a(new Error(`Failed to load script: ${r}`))},document.head.appendChild(o)})}scrollToRelevantSection(r){console.log("\u{1F3AF} Scrolling to section for field:",r);let e=r.startsWith("/")?r.slice(1):r;console.log(" Normalized path:",e);let t={"colors/primary":"color-system","colors/secondary":"color-system","colors/accent":"color-system","colors/background":"color-system","colors/success":"color-system","colors/warning":"color-system","colors/danger":"color-system","colors/info":"color-system","typography/":"typography","spatialRhythm/":"spacing","layers/":"surfaces-shadows","shape/":"buttons","behavior/transitionSpeed":"interactive-states","behavior/":"interactive-states","components/forms":"forms","components/alerts":"alerts","components/badges":"badges","components/tables":"tables","components/toasts":"toasts","components/modals":"modals","components/tabStrip":"tabs","icons/":"icons"},a=null;for(let[o,i]of Object.entries(t))if(e.startsWith(o)){a=i,console.log(` \u2713 Matched pattern "${o}" \u2192 section "${i}"`);break}if(a){let o=this.querySelector(`[data-section="${a}"]`);console.log(` Searching for section: [data-section="${a}"]`,o?"\u2713 Found":"\u2717 Not found"),o?(o.scrollIntoView({behavior:"smooth",block:"start"}),o.style.transition="background-color 0.3s ease",o.style.backgroundColor="var(--color-primary-50)",setTimeout(()=>{o.style.backgroundColor=""},1500),console.log(" \u2713 Scrolled and highlighted section")):console.warn(` \u2717 Section [data-section="${a}"] not found in DOM`)}else console.warn(` \u2717 No section mapping found for field: ${r}`)}renderDisabledSection(r,e){return S`
3687
+ `},2e3)})})},100)}async loadShiki(){if(this.#a)return this.#a;if(this.#e){for(;this.#e;)await new Promise(r=>setTimeout(r,50));return this.#a}this.#e=!0;try{let r=await import("https://esm.sh/shiki@1.0.0");return this.#a=await r.getHighlighter({themes:["github-dark","github-light"],langs:["html","css","javascript","json"]}),this.#a}catch(r){return console.error("Failed to load Shiki:",r),null}finally{this.#e=!1}}async highlightWithShiki(r,e="html"){let t=await this.loadShiki();if(!t)return this.escapeHTML(r);try{let o=document.documentElement.getAttribute("data-theme")==="dark"?"github-dark":"github-light",s=t.codeToHtml(r,{lang:e,theme:o}).match(/<code[^>]*>([\s\S]*)<\/code>/);return s?s[1]:this.escapeHTML(r)}catch(a){return console.error("Shiki highlighting failed:",a),this.escapeHTML(r)}}escapeHTML(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}async getShowdownConverter(){if(this._showdown)return this._showdown;let r=await this.loadShowdownFromCDN();return!r||!r.Converter?null:(this._showdown=new r.Converter({ghCompatibleHeaderId:!0,tables:!0,strikethrough:!0,tasklists:!0}),this._showdown)}async loadShowdownFromCDN(){if(typeof window<"u"&&window.showdown)return window.showdown;if(this._showdownLoading){for(;this._showdownLoading;)await new Promise(e=>setTimeout(e,50));return window.showdown||null}this._showdownLoading=!0;let r=["https://cdn.jsdelivr.net/npm/showdown@2.1.0/dist/showdown.min.js","https://unpkg.com/showdown@2.1.0/dist/showdown.min.js"];for(let e of r)try{if(await this._injectScript(e,"showdown"),window.showdown)return this._showdownLoading=!1,window.showdown}catch{}return this._showdownLoading=!1,null}_injectScript(r,e){return new Promise((t,a)=>{if(document.querySelector(`script[data-lib="${e}"][src="${r}"]`)){setTimeout(t,0);return}let o=document.createElement("script");o.src=r,o.async=!0,o.defer=!0,o.dataset.lib=e||"lib",o.onload=()=>t(),o.onerror=()=>{o.remove(),a(new Error(`Failed to load script: ${r}`))},document.head.appendChild(o)})}scrollToRelevantSection(r){console.log("\u{1F3AF} Scrolling to section for field:",r);let e=r.startsWith("/")?r.slice(1):r;console.log(" Normalized path:",e);let t={"colors/primary":"color-system","colors/secondary":"color-system","colors/accent":"color-system","colors/background":"color-system","colors/success":"color-system","colors/warning":"color-system","colors/danger":"color-system","colors/info":"color-system","typography/":"typography","spatialRhythm/":"spacing","layers/":"surfaces-shadows","shape/":"buttons","behavior/transitionSpeed":"interactive-states","behavior/":"interactive-states","components/forms":"forms","components/alerts":"alerts","components/badges":"badges","components/tables":"tables","components/toasts":"toasts","components/modals":"modals","components/tabStrip":"tabs","icons/":"icons"},a=null;for(let[o,i]of Object.entries(t))if(e.startsWith(o)){a=i,console.log(` \u2713 Matched pattern "${o}" \u2192 section "${i}"`);break}if(a){let o=this.querySelector(`[data-section="${a}"]`);console.log(` Searching for section: [data-section="${a}"]`,o?"\u2713 Found":"\u2717 Not found"),o?(o.scrollIntoView({behavior:"smooth",block:"start"}),o.style.transition="background-color 0.3s ease",o.style.backgroundColor="var(--color-primary-50)",setTimeout(()=>{o.style.backgroundColor=""},1500),console.log(" \u2713 Scrolled and highlighted section")):console.warn(` \u2717 Section [data-section="${a}"] not found in DOM`)}else console.warn(` \u2717 No section mapping found for field: ${r}`)}renderDisabledSection(r,e){return S`
3688
3688
  <section class="showcase-section disabled">
3689
3689
  <h2>${r}</h2>
3690
3690
  <p class="disabled-message">${e}</p>
@@ -53,7 +53,7 @@ const DEFAULT_OPTIONS = {
53
53
  *
54
54
  * 5. Completely custom actions (hides default buttons):
55
55
  * <pds-jsonform .jsonSchema=${schema} hide-actions>
56
- * <div slot="actions" style="display: flex; gap: 1rem;">
56
+ * <div slot="actions" class="flex gap-md">
57
57
  * <button type="submit" class="btn btn-primary">Custom Submit</button>
58
58
  * <button type="button" class="btn">Custom Action</button>
59
59
  * </div>
@@ -416,10 +416,7 @@ export class SchemaForm extends LitElement {
416
416
  render() {
417
417
  const tree = this.#compiled;
418
418
  if (!tree)
419
- return html`<div
420
- class="pds-jsonform-error"
421
- style="color: red; padding: 1rem; border: 1px solid red; background: #fee;"
422
- >
419
+ return html`<div class="alert alert-error">
423
420
  <p>Failed to generate form schema.</p>
424
421
  <pre>${JSON.stringify(this.#data, null, 2)}</pre>
425
422
  </div>`;
@@ -431,6 +428,7 @@ export class SchemaForm extends LitElement {
431
428
  : "post";
432
429
  return html`
433
430
  <form
431
+ ?data-required=${this.hasAttribute("data-required")}
434
432
  method=${m}
435
433
  action=${this.action ?? nothing}
436
434
  @submit=${this.#onSubmit}
@@ -501,9 +499,8 @@ export class SchemaForm extends LitElement {
501
499
  // Check for surface wrapping
502
500
  const surface = ui?.["ui:surface"] || pathOptions.surface;
503
501
 
504
- // Build layout classes and inline styles
502
+ // Build layout classes using PDS utilities
505
503
  const layoutClasses = [];
506
- let layoutStyle = "";
507
504
  const layoutOptions = ui?.["ui:layoutOptions"] || {};
508
505
 
509
506
  if (layout === "flex") {
@@ -511,16 +508,8 @@ export class SchemaForm extends LitElement {
511
508
  if (layoutOptions.wrap) layoutClasses.push("flex-wrap");
512
509
  if (layoutOptions.direction === "column") layoutClasses.push("flex-col");
513
510
  if (layoutOptions.gap) {
514
- // Check if gap is a CSS class name (e.g., 'md', 'lg') or a CSS value
515
- if (
516
- layoutOptions.gap.startsWith("var(") ||
517
- layoutOptions.gap.includes("px") ||
518
- layoutOptions.gap.includes("rem")
519
- ) {
520
- layoutStyle += `gap: ${layoutOptions.gap};`;
521
- } else {
522
- layoutClasses.push(`gap-${layoutOptions.gap}`);
523
- }
511
+ // Use PDS gap utility classes (xs, sm, md, lg, xl, 0)
512
+ layoutClasses.push(`gap-${layoutOptions.gap}`);
524
513
  }
525
514
  } else if (layout === "grid") {
526
515
  layoutClasses.push("grid");
@@ -532,16 +521,8 @@ export class SchemaForm extends LitElement {
532
521
  layoutClasses.push(`grid-cols-${cols}`);
533
522
  }
534
523
  if (layoutOptions.gap) {
535
- // Check if gap is a CSS class name (e.g., 'md', 'lg') or a CSS value
536
- if (
537
- layoutOptions.gap.startsWith("var(") ||
538
- layoutOptions.gap.includes("px") ||
539
- layoutOptions.gap.includes("rem")
540
- ) {
541
- layoutStyle += `gap: ${layoutOptions.gap};`;
542
- } else {
543
- layoutClasses.push(`gap-${layoutOptions.gap}`);
544
- }
524
+ // Use PDS gap utility classes (xs, sm, md, lg, xl, 0)
525
+ layoutClasses.push(`gap-${layoutOptions.gap}`);
545
526
  }
546
527
  }
547
528
 
@@ -553,7 +534,6 @@ export class SchemaForm extends LitElement {
553
534
  <fieldset
554
535
  data-path=${node.path}
555
536
  class=${ifDefined(fieldsetClass)}
556
- style=${ifDefined(layoutStyle || undefined)}
557
537
  >
558
538
  ${!this.hideLegend && !context.hideLegend
559
539
  ? html`<legend>${legend}</legend>`
@@ -1612,7 +1592,7 @@ export class SchemaForm extends LitElement {
1612
1592
  richtextOpts.placeholder || attrs.placeholder
1613
1593
  )}
1614
1594
  .value=${value ?? ""}
1615
- toolbar=${ifDefined(richtextOpts.toolbar)}
1595
+ ?toolbar=${richtextOpts.toolbar}
1616
1596
  ?required=${!!attrs.required}
1617
1597
  ?submit-on-enter=${richtextOpts.submitOnEnter ?? false}
1618
1598
  spellcheck=${richtextOpts.spellcheck ?? true ? "true" : "false"}
package/readme.md CHANGED
@@ -6,18 +6,25 @@
6
6
  [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](#license)
7
7
  [![npm version](https://img.shields.io/npm/v/@pure-ds/core.svg)](https://www.npmjs.com/package/@pure-ds/core)
8
8
 
9
- **Why build a design system when you can generate one?**
10
-
11
9
  ![Pure Design System logo](public/assets/img/logo.png)
12
10
 
13
- > A radically lightweight, fully standards-based design system for the modern web
14
- > Everything optional. Nothing hidden. The force is within the platform.
11
+ ## With Great Standards Comes Great Power
12
+
13
+ **The browser is the framework. Semantic HTML is the component model. Web Standards are enough.**
14
+
15
+ PDS is a **configuration-first, standards-only design system generator**. Not a framework. Not a CSS library. Not tied to any toolchain.
15
16
 
16
- Pure Design System generates complete, production-ready design systems from JavaScript configuration. Write your design intent onceβ€”colors, typography, spacingβ€”and get tokens, primitives, components, and utilities automatically.
17
+ You write a small JavaScript config. PDS generates:
18
+ - **Deterministic CSS** (global and Constructable Stylesheets for Web Components)
19
+ - **A complete token hierarchy** (inspect via `PDS.compiled` in DevTools)
20
+ - **Zero-specificity primitives** (`:where()` selectorsβ€”your CSS always wins)
17
21
 
18
- ### pds.config.js
22
+ Everything is optional. Use only tokens, or CSS, or add enhancements, or include components. Nothing forces itself into your project.
23
+
24
+ ### The Config
19
25
 
20
26
  ```javascript
27
+ // pds.config.js
21
28
  export const config = {
22
29
  design: {
23
30
  colors: { primary: '#007acc', secondary: '#5c2d91' },
@@ -27,43 +34,87 @@ export const config = {
27
34
  }
28
35
  ```
29
36
 
30
- ### app.js
37
+ ### The Result
31
38
 
32
39
  ```javascript
40
+ // app.js
33
41
  import { PDS } from '@pure-ds/core';
34
42
  import { config } from './pds.config.js';
35
43
 
36
44
  await PDS.start(config);
45
+ // That's it. Start writing semantic HTML.
46
+ ```
47
+
48
+ ---
49
+
50
+ ## The PDS Philosophy
51
+
52
+ ### Semantic Classes First
53
+ PDS generates **high-level primitives** that style semantic HTML:
37
54
 
38
- // Start using components immediately
39
- // <pds-icon icon="star"></pds-icon>
55
+ ```html
56
+ <article class="card">...</article>
57
+ <button class="btn-primary">Save</button>
58
+ <div class="alert alert-success">Done!</div>
59
+ ```
60
+
61
+ ### Layout Utilitiesβ€”Sparingly
62
+ A **small set** of layout utilities for composition:
63
+
64
+ ```html
65
+ <div class="flex gap-md items-center">...</div>
66
+ <section class="stack-lg">...</section>
40
67
  ```
41
68
 
42
- **Key Features:**
69
+ No `.text-blue-500`. No `.p-4`. No `.rounded-lg`. **Spacing, colors, radii are tokensβ€”not classes.**
43
70
 
44
- - 🎨 **Configuration-Driven** - Single source of truth generates everything
45
- - πŸš€ **Live or Static** - Runtime generation or pre-built bundles
46
- - 🎯 **Framework Agnostic** - Vanilla, Lit, React, Vue, Svelte, Next.js
47
- - 🌐 **Web Standards** - EventTarget API, Constructable Stylesheets, Shadow DOM
48
- - 🧩 **Progressive Enhancement** - Semantic HTML first, enhance where needed
49
- - πŸ” **Smart Query System** - Ask questions: "what is the focus border color?"
50
- - β™Ώ **Accessibility Built-in** - WCAG AA validation, contrast checking
51
- - πŸŽ›οΈ **Interactive Configurator** - Visual design tool with live preview
52
- - πŸ”€ **Automatic Font Loading** - Google Fonts loaded on demand
53
- - πŸ“¦ **Zero Build Required** - Works directly in browsers
54
- - πŸ“‹ **Custom Elements Manifest** - Full IDE integration with autocomplete and type checking
71
+ ### Inline Styles? Only for Tokens
72
+ The **only** valid `style=""` in PDS sets CSS custom properties:
73
+
74
+ ```html
75
+ <!-- βœ“ Token override -->
76
+ <section style="--surface-bg: var(--color-primary-50);">
77
+
78
+ <!-- βœ— Never do this -->
79
+ <div style="display: flex; gap: 16px;">
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Why PDS Exists
85
+
86
+ | The Old Way | The PDS Way |
87
+ |-------------|-------------|
88
+ | `class="flex items-center gap-4 p-6 bg-white rounded-lg shadow-md"` | `class="card"` |
89
+ | `style="color: #007acc;"` | Uses `--color-primary-500` token |
90
+ | Import a Button component | `<button class="btn-primary">` |
91
+ | 47 utility classes per element | Semantic class + maybe one layout utility |
92
+
93
+ **The result:** Readable HTML. Inspectable CSS. Sites that work without JS. Code that lasts decades.
94
+
95
+ PDS follows the [Pure Web Manifesto](https://pureweb.dev/manifesto)β€”sustainable architecture for long-lived applications.
96
+
97
+ ---
98
+
99
+ ## Key Features
100
+
101
+ - 🎨 **Configuration-Driven** β€” Single source of truth generates everything
102
+ - πŸš€ **Live or Static** β€” Runtime generation or pre-built bundles
103
+ - 🎯 **Framework Agnostic** β€” Vanilla, Lit, React, Vue, Svelte, Next.js
104
+ - 🌐 **Web Standards** β€” EventTarget API, Constructable Stylesheets, Shadow DOM
105
+ - 🧩 **Progressive Enhancement** β€” Semantic HTML first, enhance where needed
106
+ - β™Ώ **Accessibility Built-in** β€” WCAG AA validation, contrast checking
107
+ - πŸ“¦ **Zero Build Required** β€” Works directly in browsers
108
+ - πŸ“‹ **IDE IntelliSense** β€” Full autocomplete via Custom Elements Manifest
55
109
 
56
110
  ---
57
111
 
58
112
  ## Table of Contents
59
113
 
60
- - [What is This?](#what-is-this)
114
+ - [The Three Layers](#the-three-layers)
61
115
  - [Who is it For?](#who-is-it-for)
62
116
  - [Getting Started](#getting-started)
63
117
  - [Core Architecture](#core-architecture)
64
- - [1. Style Generation & Injection](#1-style-generation--injection)
65
- - [2. Progressive Enhancements](#2-progressive-enhancements)
66
- - [3. Web Components](#3-web-components)
67
118
  - [Styling Layers](#styling-layers)
68
119
  - [Shadow DOM Adoption](#shadow-dom-adoption)
69
120
  - [Icon System](#icon-system)
@@ -81,40 +132,47 @@ await PDS.start(config);
81
132
 
82
133
  ---
83
134
 
84
- ## What is This?
85
-
86
- Pure Design System is based on the [Pure Web Manifesto](https://pureweb.dev/manifesto).
87
-
88
- It transforms configuration into complete design systems using three integrated pillars:
89
-
90
- ### 1. **Generated Styles** (Tokens β†’ CSS)
91
- Your config defines design intent. PDS generates (in a deterministic way):
92
- - **Color scales** (50-900 shades from base colors)
93
- - **Surface semantics** (bg, text, border, shadow, interactive states)
94
- - **Spacing tokens** (mathematical progression)
95
- - **Typography scales** (modular scale from base size)
96
- - **Component primitives** (buttons, forms, cards, badges)
97
- - **Utility classes** (layout, borders, effects)
98
-
99
- ### 2. **Progressive Enhancements** (Lightweight DOM behaviors)
100
- Semantic HTML gets enhanced with JavaScript:
101
- - **Dropdowns** - `<nav data-dropdown>` auto-enhanced
102
- - **Toggles** - `<label data-toggle>` becomes switches
103
- - **Range sliders** - Value bubbles and visual feedback
104
- - **Required fields** - Automatic asterisks and validation hints
105
- - **Custom enhancements** - Extensible system for your patterns
106
-
107
- ### 3. **Web Components** (Rich UI, lazy-loaded using [AutoDefiner](https://www.npmjs.com/package/pure-web#user-content-autodefiner))
108
- Optional components loaded on demand:
109
- - `<pds-icon>` - SVG sprite icons
110
- - `<pds-drawer>` - Slide-out panels (top, bottom, lef, right)
111
- - `<pds-tabstrip>` - Accessible tabs
112
- - `<pds-upload>` - File upload with drag & drop and preview
113
- - `<pds-toaster>` - Smart Toast notifications
114
- - `<pds-richtext>` - Rich text editor (prefers `#showdown` import map; `format="markdown"` keeps Markdown values)
115
- - `<pds-jsonform>` - Dynamic forms generated from JSON Schema
116
- - `<pds-splitpanel>` - Resizable panes
117
- - `<pds-scrollrow>` - Horizontal scrolling containers
135
+ ## The Three Layers
136
+
137
+ PDS is built on **three fully optional layers**, each powered by your config:
138
+
139
+ ### 1. Styles β€” Deterministic Global CSS
140
+
141
+ Your config generates:
142
+ - **Color scales** (50–900 from base colors)
143
+ - **Surface semantics** (bg, text, border, shadow, states)
144
+ - **Spacing system** (mathematical progression)
145
+ - **Typography scale** (modular scale from base)
146
+ - **Primitives** (`.btn-primary`, `.card`, `.badge`)
147
+ - **Utilities** (`.flex`, `.gap-md`, `.stack-lg`)
148
+
149
+ All exported as CSS Custom Properties. Zero specificity via `:where()`.
150
+ Same values available in JS via `PDS.compiled.tokens`.
151
+
152
+ ### 2. Enhancements β€” Semantic HTML Made Powerful
153
+
154
+ Optional selector-based upgrades that run in Light DOM and Shadow DOM:
155
+ - Required fields show markers and help text automatically
156
+ - `<label data-toggle>` becomes a switch
157
+ - `<nav data-dropdown>` gets dropdown behavior
158
+ - `<dialog>` gets better focus management
159
+ - Form elements gain consistent theming
160
+
161
+ **Think: HTML β†’ UX upgrades, zero integration work.**
162
+
163
+ ### 3. Components β€” Auto-defined, Lazy-loaded Web Components
164
+
165
+ A growing set of PDS components:
166
+ - `<pds-icon>` β€” SVG sprite icons
167
+ - `<pds-drawer>` β€” Slide-out panels
168
+ - `<pds-tabstrip>` β€” Accessible tabs
169
+ - `<pds-jsonform>` β€” Forms from JSON Schema
170
+ - `<pds-upload>` β€” Drag & drop file upload
171
+ - `<pds-richtext>` β€” Rich text / Markdown editor
172
+ - `<pds-splitpanel>` β€” Resizable panes
173
+ - `<pds-toaster>` β€” Toast notifications
174
+
175
+ Auto-defined when used. Lazy-loaded via dynamic imports. Styled by your tokens. Zero dependencies.
118
176
 
119
177
  ### How It Works
120
178
 
@@ -146,7 +204,7 @@ Optional components loaded on demand:
146
204
  β”‚ Tokens: --color-primary-500, --spacing-4 β”‚
147
205
  β”‚ Primitives: .btn-primary, .card, .badge β”‚
148
206
  β”‚ Components: <pds-drawer>, <pds-icon> β”‚
149
- β”‚ Utilities: .flex, .gap-4, .border-gradient β”‚
207
+ β”‚ Utilities: .flex, .gap-md, .border-gradient β”‚
150
208
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
151
209
  ```
152
210