@pure-ds/core 0.4.36 → 0.5.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.
- package/dist/types/pds.d.ts +32 -11
- package/dist/types/public/assets/auto-definer-XWHRBQPU.d.ts +9 -0
- package/dist/types/public/assets/auto-definer-XWHRBQPU.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-746HIXIK.d.ts +52 -0
- package/dist/types/public/assets/chunk-746HIXIK.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-APJV5T3J.d.ts +106 -0
- package/dist/types/public/assets/chunk-APJV5T3J.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-BEPKFFM7.d.ts +398 -0
- package/dist/types/public/assets/chunk-BEPKFFM7.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-ISS7UH5H.d.ts +2424 -0
- package/dist/types/public/assets/chunk-ISS7UH5H.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-RUPLQUDG.d.ts +582 -0
- package/dist/types/public/assets/chunk-RUPLQUDG.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-USML4NYF.d.ts +18 -0
- package/dist/types/public/assets/chunk-USML4NYF.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-Z47A3HLT.d.ts +3 -0
- package/dist/types/public/assets/chunk-Z47A3HLT.d.ts.map +1 -0
- package/dist/types/public/assets/js/auto-definer-HZLD2XF4.d.ts +9 -0
- package/dist/types/public/assets/js/auto-definer-HZLD2XF4.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-6A6DFAIG.d.ts +88 -0
- package/dist/types/public/assets/js/chunk-6A6DFAIG.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-746HIXIK.d.ts +52 -0
- package/dist/types/public/assets/js/chunk-746HIXIK.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-A3TZGIYX.d.ts +4 -0
- package/dist/types/public/assets/js/chunk-A3TZGIYX.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-BEPKFFM7.d.ts +398 -0
- package/dist/types/public/assets/js/chunk-BEPKFFM7.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-OTTRJ5MB.d.ts +1695 -0
- package/dist/types/public/assets/js/chunk-OTTRJ5MB.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-RBPKHG76.d.ts +747 -0
- package/dist/types/public/assets/js/chunk-RBPKHG76.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-RUPLQUDG.d.ts +582 -0
- package/dist/types/public/assets/js/chunk-RUPLQUDG.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-SMD2R3CX.d.ts +68 -0
- package/dist/types/public/assets/js/chunk-SMD2R3CX.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-Y73DA2D5.d.ts +15 -0
- package/dist/types/public/assets/js/chunk-Y73DA2D5.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/auto-definer-X7MSXKTU.d.ts +9 -0
- package/dist/types/public/assets/js/chunks/auto-definer-X7MSXKTU.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/chunk-7BDQH5CT.d.ts +485 -0
- package/dist/types/public/assets/js/chunks/chunk-7BDQH5CT.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/chunk-MWB3S7NG.d.ts +3 -0
- package/dist/types/public/assets/js/chunks/chunk-MWB3S7NG.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/chunk-WIMLORAU.d.ts +5 -0
- package/dist/types/public/assets/js/chunks/chunk-WIMLORAU.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/chunk-WN4Y2ELN.d.ts +833 -0
- package/dist/types/public/assets/js/chunks/chunk-WN4Y2ELN.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/chunk-XQOUIBLO.d.ts +1687 -0
- package/dist/types/public/assets/js/chunks/chunk-XQOUIBLO.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/font-loader-VN5SRNOD.d.ts +5 -0
- package/dist/types/public/assets/js/chunks/font-loader-VN5SRNOD.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/pds-live-validation-BQPWN5JG.d.ts +38 -0
- package/dist/types/public/assets/js/chunks/pds-live-validation-BQPWN5JG.d.ts.map +1 -0
- package/dist/types/public/assets/js/common-WIAC4WAJ.d.ts +4 -0
- package/dist/types/public/assets/js/common-WIAC4WAJ.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-config-WEBAXXSM.d.ts +4 -0
- package/dist/types/public/assets/js/pds-config-WEBAXXSM.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-core/pds-generator.d.ts +700 -0
- package/dist/types/public/assets/js/pds-core/pds-generator.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-core/pds-utilities.d.ts +27 -0
- package/dist/types/public/assets/js/pds-core/pds-utilities.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-enums-DCBZHS64.d.ts +3 -0
- package/dist/types/public/assets/js/pds-enums-DCBZHS64.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-gen.d.ts +106 -0
- package/dist/types/public/assets/js/pds-gen.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-live.d.ts +11 -0
- package/dist/types/public/assets/js/pds-live.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-manager.d.ts +1328 -0
- package/dist/types/public/assets/js/pds-manager.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-ontology-2DICJXHO.d.ts +9 -0
- package/dist/types/public/assets/js/pds-ontology-2DICJXHO.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-query-B54LBKKR.d.ts +70 -0
- package/dist/types/public/assets/js/pds-query-B54LBKKR.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds.d.ts +2 -18
- package/dist/types/public/assets/js/pds.d.ts.map +1 -1
- package/dist/types/public/assets/pds-ontology-ZO6TJHO3.d.ts +9 -0
- package/dist/types/public/assets/pds-ontology-ZO6TJHO3.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-config.d.ts +757 -0
- package/dist/types/src/js/common/pds-core/pds-config.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-enhancers.d.ts +28 -0
- package/dist/types/src/js/common/pds-core/pds-enhancers.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-enums.d.ts +87 -0
- package/dist/types/src/js/common/pds-core/pds-enums.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-generator.d.ts +700 -0
- package/dist/types/src/js/common/pds-core/pds-generator.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-ontology.d.ts +380 -0
- package/dist/types/src/js/common/pds-core/pds-ontology.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-paths.d.ts +37 -0
- package/dist/types/src/js/common/pds-core/pds-paths.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-query.d.ts +102 -0
- package/dist/types/src/js/common/pds-core/pds-query.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-registry.d.ts +35 -0
- package/dist/types/src/js/common/pds-core/pds-registry.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-utilities.d.ts +27 -0
- package/dist/types/src/js/common/pds-core/pds-utilities.d.ts.map +1 -0
- package/dist/types/src/js/pds-core/pds-generator.d.ts +38 -46
- package/dist/types/src/js/pds-core/pds-generator.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-live.d.ts +39 -0
- package/dist/types/src/js/pds-core/pds-live.d.ts.map +1 -0
- package/dist/types/src/js/pds-core/pds-runtime.d.ts +39 -0
- package/dist/types/src/js/pds-core/pds-runtime.d.ts.map +1 -0
- package/dist/types/src/js/pds-core/pds-start-helpers.d.ts +60 -0
- package/dist/types/src/js/pds-core/pds-start-helpers.d.ts.map +1 -0
- package/dist/types/src/js/pds-core/pds-utilities.d.ts +27 -0
- package/dist/types/src/js/pds-core/pds-utilities.d.ts.map +1 -0
- package/dist/types/src/js/pds-gen.d.ts +48 -0
- package/dist/types/src/js/pds-gen.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-runtime.d.ts +7 -0
- package/dist/types/src/js/pds-live-runtime.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-validation.d.ts +44 -0
- package/dist/types/src/js/pds-live-validation.d.ts.map +1 -0
- package/dist/types/src/js/pds-live.d.ts +11 -0
- package/dist/types/src/js/pds-live.d.ts.map +1 -0
- package/dist/types/src/js/pds-manager.d.ts +2 -0
- package/dist/types/src/js/pds-manager.d.ts.map +1 -0
- package/dist/types/src/js/pds.d.ts +6 -33
- package/dist/types/src/js/pds.d.ts.map +1 -1
- package/package.json +11 -12
- package/packages/pds-cli/bin/{generate-css-data.mjs → generate-css-data.js} +563 -563
- package/packages/pds-cli/bin/{generate-manifest.mjs → generate-manifest.js} +352 -352
- package/packages/pds-cli/bin/{pds-build-icons.mjs → pds-build-icons.js} +152 -152
- package/packages/pds-cli/bin/{pds-dx.mjs → pds-dx.js} +114 -114
- package/packages/pds-cli/bin/{pds-init-config.mjs → pds-init-config.js} +34 -34
- package/packages/pds-cli/bin/{pds-setup-copilot.mjs → pds-setup-copilot.js} +106 -106
- package/packages/pds-cli/bin/{pds-static.mjs → pds-static.js} +581 -581
- package/packages/pds-cli/bin/{pds.mjs → pds.js} +127 -127
- package/packages/pds-cli/bin/postinstall.mjs +522 -563
- package/packages/pds-cli/bin/{sync-assets.mjs → sync-assets.js} +251 -251
- package/packages/pds-cli/lib/{asset-roots.mjs → asset-roots.js} +47 -47
- package/packages/pds-cli/lib/{fs-writer.mjs → fs-writer.js} +75 -75
- package/public/assets/js/app.js +95 -118
- package/public/assets/js/pds-manager.js +3251 -0
- package/public/assets/js/pds.js +10 -3201
- package/readme.md +2014 -2008
- package/src/js/pds-core/pds-enhancers.js +518 -518
- package/src/js/pds-core/pds-enums.js +86 -86
- package/src/js/pds-core/pds-generator.js +255 -185
- package/src/js/pds-core/pds-live.js +434 -0
- package/src/js/pds-core/pds-paths.js +109 -109
- package/src/js/pds-core/pds-registry.js +79 -79
- package/src/js/pds-core/pds-runtime.js +184 -0
- package/src/js/pds-core/pds-start-helpers.js +404 -0
- package/src/js/pds.d.ts +32 -11
- package/src/js/pds.js +37 -1182
- package/getting-started.md +0 -599
- package/src/js/pds-core/pds.d.ts +0 -129
package/readme.md
CHANGED
|
@@ -1,2008 +1,2014 @@
|
|
|
1
|
-
# Pure Design System (PDS)
|
|
2
|
-
|
|
3
|
-
> ⚠️ **Beta Software** - APIs are stabilizing but may still change. Pin versions in production: `"@pure-ds/core": "~0.
|
|
4
|
-
|
|
5
|
-
[](https://github.com/mvneerven/pure-ds/actions/workflows/ci.yml)
|
|
6
|
-
[](#license)
|
|
7
|
-
[](https://www.npmjs.com/package/@pure-ds/core)
|
|
8
|
-
|
|
9
|
-

|
|
10
|
-
|
|
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.
|
|
16
|
-
|
|
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)
|
|
21
|
-
|
|
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
|
|
25
|
-
|
|
26
|
-
```javascript
|
|
27
|
-
// pds.config.js
|
|
28
|
-
export const config = {
|
|
29
|
-
design: {
|
|
30
|
-
colors: { primary: '#007acc', secondary: '#5c2d91' },
|
|
31
|
-
typography: { baseFontSize: 16, fontScale: 1.25 },
|
|
32
|
-
spatialRhythm: { baseUnit: 8, scaleRatio: 1.5 }
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### The Result
|
|
38
|
-
|
|
39
|
-
```javascript
|
|
40
|
-
// app.js
|
|
41
|
-
import { PDS } from '@pure-ds/core';
|
|
42
|
-
import { config } from './pds.config.js';
|
|
43
|
-
|
|
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:
|
|
54
|
-
|
|
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>
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
No `.text-blue-500`. No `.p-4`. No `.rounded-lg`. **Spacing, colors, radii are tokens—not classes.**
|
|
70
|
-
|
|
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
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
## Table of Contents
|
|
113
|
-
|
|
114
|
-
- [The Three Layers](#the-three-layers)
|
|
115
|
-
- [Who is it For?](#who-is-it-for)
|
|
116
|
-
- [Getting Started](#getting-started)
|
|
117
|
-
- [Core Architecture](#core-architecture)
|
|
118
|
-
- [Styling Layers](#styling-layers)
|
|
119
|
-
- [Shadow DOM Adoption](#shadow-dom-adoption)
|
|
120
|
-
- [Icon System](#icon-system)
|
|
121
|
-
- [Smart Query System](#smart-query-system)
|
|
122
|
-
- [Design Validation](#design-validation)
|
|
123
|
-
- [Advanced Features](#advanced-features)
|
|
124
|
-
- [API Reference](#api-reference)
|
|
125
|
-
- [Extending PDS](#extending-pds)
|
|
126
|
-
- [Using from CDN](#using-from-cdn)
|
|
127
|
-
- [CLI & Export](#cli--export)
|
|
128
|
-
- [Custom Elements Manifest](#custom-elements-manifest)
|
|
129
|
-
- [Framework Integration](#framework-integration)
|
|
130
|
-
- [Troubleshooting](#troubleshooting)
|
|
131
|
-
- [License](#license)
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
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-form>` — 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.
|
|
176
|
-
|
|
177
|
-
### How It Works
|
|
178
|
-
|
|
179
|
-
```
|
|
180
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
181
|
-
│ Configuration │
|
|
182
|
-
│ ───────────── │
|
|
183
|
-
│ colors: { primary: '#007acc' } │
|
|
184
|
-
│ typography: { baseFontSize: 16, fontScale: 1.25 } │
|
|
185
|
-
│ spatialRhythm: { baseUnit: 8 } │
|
|
186
|
-
└─────────────────────┬────────────────────────────────────────┘
|
|
187
|
-
│
|
|
188
|
-
▼
|
|
189
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
190
|
-
│ Generator (Live or Static) │
|
|
191
|
-
│ ────────────────────────── │
|
|
192
|
-
│ • Generates color scales (primary-50 → primary-900) │
|
|
193
|
-
│ • Creates surface tokens (bg, text, border, shadow) │
|
|
194
|
-
│ • Computes spacing progression (0-12) │
|
|
195
|
-
│ • Builds typography scale (6 levels) │
|
|
196
|
-
│ • Generates CSS layers (tokens → primitives → utilities) │
|
|
197
|
-
│ • Validates contrast ratios (WCAG AA) │
|
|
198
|
-
└─────────────────────┬────────────────────────────────────────┘
|
|
199
|
-
│
|
|
200
|
-
▼
|
|
201
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
202
|
-
│ Output │
|
|
203
|
-
│ ────── │
|
|
204
|
-
│ Tokens: --color-primary-500, --spacing-4 │
|
|
205
|
-
│ Primitives: .btn-primary, .card, .badge │
|
|
206
|
-
│ Components: <pds-drawer>, <pds-icon> │
|
|
207
|
-
│ Utilities: .flex, .gap-md, .border-gradient │
|
|
208
|
-
└──────────────────────────────────────────────────────────────┘
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
## Who is it For?
|
|
214
|
-
|
|
215
|
-
### 🎨 Design System Teams
|
|
216
|
-
- Generate multiple brand variants from a single codebase
|
|
217
|
-
- A/B test design directions by swapping configs
|
|
218
|
-
- Maintain consistency with centralized tokens
|
|
219
|
-
- Validate accessibility automatically
|
|
220
|
-
|
|
221
|
-
### 🚀 Product Teams
|
|
222
|
-
- Ship faster with auto-generated primitives
|
|
223
|
-
- Customize with JS config instead of SASS/CSS
|
|
224
|
-
- Work with any framework or no framework
|
|
225
|
-
- Reduce bundle size with lazy-loaded components
|
|
226
|
-
|
|
227
|
-
### 🛠️ Design Tool Builders
|
|
228
|
-
- Build live configurators with instant preview
|
|
229
|
-
- Export static bundles for production
|
|
230
|
-
- Query the system programmatically
|
|
231
|
-
- Access complete object model for introspection
|
|
232
|
-
|
|
233
|
-
### 👩💻 Developers
|
|
234
|
-
- Learn by exploring the interactive showcase
|
|
235
|
-
- Adopt incrementally (tokens only → full system)
|
|
236
|
-
- Extend with custom enhancers and components
|
|
237
|
-
- Debug with structured CSS layers
|
|
238
|
-
|
|
239
|
-
---
|
|
240
|
-
|
|
241
|
-
## Getting Started
|
|
242
|
-
|
|
243
|
-
### Installation
|
|
244
|
-
|
|
245
|
-
```bash
|
|
246
|
-
npm install @pure-ds/core
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
**Post-install automation:**
|
|
250
|
-
|
|
251
|
-
During installation, PDS automatically:
|
|
252
|
-
- Creates a default `pds.config.js` (if one doesn't exist)
|
|
253
|
-
- Copies Copilot/AI instructions to `.github/copilot-instructions.md`
|
|
254
|
-
- Adds `pds:export` and `pds:build-icons` scripts to your `package.json`
|
|
255
|
-
- Runs `pds:export` to generate static assets
|
|
256
|
-
|
|
257
|
-
To manually re-sync assets:
|
|
258
|
-
|
|
259
|
-
```bash
|
|
260
|
-
npm run pds:export
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### Lit Import Convention
|
|
264
|
-
|
|
265
|
-
PDS uses a virtual import for Lit so you control the resolution:
|
|
266
|
-
|
|
267
|
-
```javascript
|
|
268
|
-
import { html, css, LitElement } from '#pds/lit';
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
**In browsers (no bundler)** - Use import maps:
|
|
272
|
-
|
|
273
|
-
```html
|
|
274
|
-
<script type="importmap">
|
|
275
|
-
{
|
|
276
|
-
"imports": {
|
|
277
|
-
"#pds/lit": "/assets/js/lit.js"
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
</script>
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
**In bundlers** - Alias to the real `lit` package:
|
|
284
|
-
|
|
285
|
-
```javascript
|
|
286
|
-
// vite.config.js
|
|
287
|
-
export default {
|
|
288
|
-
resolve: {
|
|
289
|
-
alias: { '#pds/lit': 'lit' }
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
### Quick Start: Live Mode
|
|
295
|
-
|
|
296
|
-
Generate styles at runtime with instant updates:
|
|
297
|
-
|
|
298
|
-
```javascript
|
|
299
|
-
import { PDS } from '@pure-ds/core';
|
|
300
|
-
|
|
301
|
-
await PDS.start({
|
|
302
|
-
mode: 'live',
|
|
303
|
-
preset: 'default', // or: ocean-breeze, midnight-steel, etc.
|
|
304
|
-
|
|
305
|
-
// Override preset values
|
|
306
|
-
design: {
|
|
307
|
-
colors: {
|
|
308
|
-
primary: '#007acc',
|
|
309
|
-
secondary: '#5c2d91'
|
|
310
|
-
},
|
|
311
|
-
typography: {
|
|
312
|
-
fontFamilyHeadings: 'Inter, sans-serif',
|
|
313
|
-
fontFamilyBody: 'Inter, sans-serif'
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
|
|
317
|
-
// Component auto-loading
|
|
318
|
-
autoDefine: {
|
|
319
|
-
predefine: ['pds-icon'] // Eagerly load these
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
// Use components - they'll lazy-load automatically
|
|
324
|
-
// <pds-drawer id="menu"></pds-drawer>
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
### Quick Start: Static Mode
|
|
328
|
-
|
|
329
|
-
Pre-generate assets for production:
|
|
330
|
-
|
|
331
|
-
**1. Export static files:**
|
|
332
|
-
|
|
333
|
-
```bash
|
|
334
|
-
npm run pds:export
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
This creates:
|
|
338
|
-
- `pds/styles/pds-*.css` and `pds-*.css.js` (Constructable Stylesheets)
|
|
339
|
-
- `pds/components/*.js` (Web Components)
|
|
340
|
-
- `pds/icons/pds-icons.svg` (Icon sprite)
|
|
341
|
-
- `pds/custom-elements.json` (Custom Elements Manifest for IDE integration)
|
|
342
|
-
|
|
343
|
-
**2. Initialize in static mode:**
|
|
344
|
-
|
|
345
|
-
```javascript
|
|
346
|
-
import { PDS } from '@pure-ds/core';
|
|
347
|
-
|
|
348
|
-
await PDS.start({
|
|
349
|
-
mode: 'static',
|
|
350
|
-
preset: 'default',
|
|
351
|
-
|
|
352
|
-
staticPaths: {
|
|
353
|
-
tokens: '/pds/styles/pds-tokens.css.js',
|
|
354
|
-
primitives: '/pds/styles/pds-primitives.css.js',
|
|
355
|
-
components: '/pds/styles/pds-components.css.js',
|
|
356
|
-
utilities: '/pds/styles/pds-utilities.css.js',
|
|
357
|
-
styles: '/pds/styles/pds-styles.css.js'
|
|
358
|
-
},
|
|
359
|
-
});
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
### Minimal Example
|
|
363
|
-
|
|
364
|
-
```html
|
|
365
|
-
<!DOCTYPE html>
|
|
366
|
-
<html lang="en">
|
|
367
|
-
<head>
|
|
368
|
-
<meta charset="UTF-8">
|
|
369
|
-
<title>PDS App</title>
|
|
370
|
-
<script type="importmap">
|
|
371
|
-
{
|
|
372
|
-
"imports": {
|
|
373
|
-
"#pds/lit": "/assets/js/lit.js"
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
</script>
|
|
377
|
-
</head>
|
|
378
|
-
<body>
|
|
379
|
-
<button class="btn-primary">
|
|
380
|
-
<pds-icon icon="heart"></pds-icon>
|
|
381
|
-
Click me
|
|
382
|
-
</button>
|
|
383
|
-
|
|
384
|
-
<script type="module">
|
|
385
|
-
import { PDS } from '/assets/js/pds.js';
|
|
386
|
-
|
|
387
|
-
await PDS.start({
|
|
388
|
-
design: {
|
|
389
|
-
colors: { primary: '#007acc' }
|
|
390
|
-
}
|
|
391
|
-
});
|
|
392
|
-
</script>
|
|
393
|
-
</body>
|
|
394
|
-
</html>
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
---
|
|
398
|
-
|
|
399
|
-
## Core Architecture
|
|
400
|
-
|
|
401
|
-
PDS has three integrated systems that work together to create complete design systems.
|
|
402
|
-
|
|
403
|
-
### 1. Style Generation & Injection
|
|
404
|
-
|
|
405
|
-
The heart of PDS is the **Generator** - it transforms your configuration into structured CSS.
|
|
406
|
-
|
|
407
|
-
#### Token Generation
|
|
408
|
-
|
|
409
|
-
```javascript
|
|
410
|
-
// Your config
|
|
411
|
-
{
|
|
412
|
-
colors: { primary: '#007acc' },
|
|
413
|
-
typography: { baseFontSize: 16, fontScale: 1.25 },
|
|
414
|
-
spatialRhythm: { baseUnit: 8, scaleRatio: 1.5 }
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// PDS generates tokens
|
|
418
|
-
--color-primary-50 → #e6f7ff
|
|
419
|
-
--color-primary-100 → #b3e5ff
|
|
420
|
-
--color-primary-200 → #80d4ff
|
|
421
|
-
...
|
|
422
|
-
--color-primary-900 → #003d66
|
|
423
|
-
|
|
424
|
-
--spacing-0 → 0
|
|
425
|
-
--spacing-1 → 8px
|
|
426
|
-
--spacing-2 → 12px (8 × 1.5)
|
|
427
|
-
--spacing-3 → 18px (12 × 1.5)
|
|
428
|
-
...
|
|
429
|
-
|
|
430
|
-
--font-size-xs → 0.64rem
|
|
431
|
-
--font-size-sm → 0.8rem
|
|
432
|
-
--font-size-base → 1rem
|
|
433
|
-
--font-size-lg → 1.25rem
|
|
434
|
-
--font-size-xl → 1.5625rem
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
#### Surface Semantics
|
|
438
|
-
|
|
439
|
-
PDS generates smart surface tokens that adapt to context:
|
|
440
|
-
|
|
441
|
-
```css
|
|
442
|
-
/* Light theme */
|
|
443
|
-
--surface-bg: var(--color-gray-50);
|
|
444
|
-
--surface-text: var(--color-gray-900);
|
|
445
|
-
--surface-text-secondary: var(--color-gray-700);
|
|
446
|
-
--surface-border: var(--color-gray-300);
|
|
447
|
-
--surface-shadow: rgba(0, 0, 0, 0.1);
|
|
448
|
-
|
|
449
|
-
/* Dark theme (auto-generated) */
|
|
450
|
-
[data-theme="dark"] {
|
|
451
|
-
--surface-bg: var(--color-gray-900);
|
|
452
|
-
--surface-text: var(--color-gray-50);
|
|
453
|
-
--surface-text-secondary: var(--color-gray-300);
|
|
454
|
-
--surface-border: var(--color-gray-700);
|
|
455
|
-
--surface-shadow: rgba(0, 0, 0, 0.5);
|
|
456
|
-
}
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
#### Interactive States
|
|
460
|
-
|
|
461
|
-
Button and interactive element states are computed automatically:
|
|
462
|
-
|
|
463
|
-
```css
|
|
464
|
-
/* Primary button */
|
|
465
|
-
--primary-fill: var(--color-primary-600);
|
|
466
|
-
--primary-fill-hover: var(--color-primary-700);
|
|
467
|
-
--primary-fill-active: var(--color-primary-800);
|
|
468
|
-
|
|
469
|
-
/* Text/outline buttons */
|
|
470
|
-
--primary-text: var(--color-primary-600);
|
|
471
|
-
--primary-text-hover: var(--color-primary-700);
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
#### Live vs Static Mode
|
|
475
|
-
|
|
476
|
-
**Live Mode:**
|
|
477
|
-
- CSS generated in-browser at runtime
|
|
478
|
-
- Instant updates when config changes
|
|
479
|
-
- Perfect for design tools and configurators
|
|
480
|
-
- Access via `PDS.compiled` object model
|
|
481
|
-
- Automatic font loading from Google Fonts
|
|
482
|
-
|
|
483
|
-
**Static Mode:**
|
|
484
|
-
- CSS pre-generated at build time
|
|
485
|
-
- Optimized for production performance
|
|
486
|
-
- Host anywhere (CDN, static server)
|
|
487
|
-
- Constructable Stylesheets for instant adoption
|
|
488
|
-
- No runtime overhead
|
|
489
|
-
|
|
490
|
-
### 2. Progressive Enhancements
|
|
491
|
-
|
|
492
|
-
Lightweight JavaScript behaviors applied to semantic HTML. These are **not Web Components** - just DOM enhancements that make standard HTML more interactive.
|
|
493
|
-
|
|
494
|
-
#### Built-in Enhancers
|
|
495
|
-
|
|
496
|
-
**Dropdown Menus** - `<nav data-dropdown>`
|
|
497
|
-
|
|
498
|
-
```html
|
|
499
|
-
<nav data-dropdown>
|
|
500
|
-
<button>Menu</button>
|
|
501
|
-
<menu>
|
|
502
|
-
<li><a href="#home">Home</a></li>
|
|
503
|
-
<li><a href="#about">About</a></li>
|
|
504
|
-
<li><a href="#contact">Contact</a></li>
|
|
505
|
-
</menu>
|
|
506
|
-
</nav>
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
Features:
|
|
510
|
-
- Click to toggle visibility
|
|
511
|
-
- Auto-positioning (up/down based on space)
|
|
512
|
-
- Horizontal alignment (`.align-right` class)
|
|
513
|
-
- Keyboard support (Escape to close)
|
|
514
|
-
- Click-outside to close
|
|
515
|
-
- Scrollable when content exceeds viewport
|
|
516
|
-
|
|
517
|
-
**Toggle Switches** - `<label data-toggle>`
|
|
518
|
-
|
|
519
|
-
```html
|
|
520
|
-
<label data-toggle>
|
|
521
|
-
<span data-label>Enable notifications</span>
|
|
522
|
-
<input type="checkbox">
|
|
523
|
-
</label>
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
Creates styled toggle switches from standard checkboxes.
|
|
527
|
-
|
|
528
|
-
**Range Sliders** - `<input type="range">`
|
|
529
|
-
|
|
530
|
-
```html
|
|
531
|
-
<!-- Standard mode: floating bubble on interaction -->
|
|
532
|
-
<label>
|
|
533
|
-
<span>Volume</span>
|
|
534
|
-
<input type="range" min="0" max="100" value="50">
|
|
535
|
-
</label>
|
|
536
|
-
|
|
537
|
-
<!-- Inline output mode: persistent value display -->
|
|
538
|
-
<label class="range-output">
|
|
539
|
-
<span>Volume</span>
|
|
540
|
-
<input type="range" min="0" max="100" value="50">
|
|
541
|
-
</label>
|
|
542
|
-
```
|
|
543
|
-
|
|
544
|
-
Enhances range inputs with automatic value display. Use `range-output` class for inline output with semantic `<output>` element.
|
|
545
|
-
|
|
546
|
-
**Required Field Indicators** - `form [required]`
|
|
547
|
-
|
|
548
|
-
```html
|
|
549
|
-
<label>
|
|
550
|
-
<span>Email</span>
|
|
551
|
-
<input type="email" required>
|
|
552
|
-
</label>
|
|
553
|
-
```
|
|
554
|
-
|
|
555
|
-
Automatically adds asterisk to label.
|
|
556
|
-
|
|
557
|
-
#### Custom Enhancers
|
|
558
|
-
|
|
559
|
-
Add your own progressive enhancements:
|
|
560
|
-
|
|
561
|
-
```javascript
|
|
562
|
-
await PDS.start({
|
|
563
|
-
enhancers: [
|
|
564
|
-
{
|
|
565
|
-
selector: '[data-tooltip]',
|
|
566
|
-
description: 'Adds tooltip on hover',
|
|
567
|
-
run: (element) => {
|
|
568
|
-
const text = element.dataset.tooltip;
|
|
569
|
-
element.addEventListener('mouseenter', () => {
|
|
570
|
-
// Show tooltip
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
},
|
|
574
|
-
{
|
|
575
|
-
selector: '[data-copy]',
|
|
576
|
-
description: 'Copy text to clipboard on click',
|
|
577
|
-
run: (element) => {
|
|
578
|
-
element.addEventListener('click', () => {
|
|
579
|
-
navigator.clipboard.writeText(element.dataset.copy);
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
]
|
|
584
|
-
});
|
|
585
|
-
```
|
|
586
|
-
|
|
587
|
-
### 3. Web Components
|
|
588
|
-
|
|
589
|
-
Rich, reusable UI components built with Lit. Lazy-loaded automatically via the **Auto-Define** system.
|
|
590
|
-
|
|
591
|
-
#### Available Components
|
|
592
|
-
|
|
593
|
-
**`<pds-icon>`** - SVG sprite icons
|
|
594
|
-
```html
|
|
595
|
-
<pds-icon icon="heart"></pds-icon>
|
|
596
|
-
<pds-icon icon="star" size="lg"></pds-icon>
|
|
597
|
-
<pds-icon icon="list" size="32" color="red"></pds-icon>
|
|
598
|
-
<pds-icon icon="info" label="Information"></pds-icon>
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
Attributes:
|
|
602
|
-
- `icon` - Symbol ID (required)
|
|
603
|
-
- `size` - Named size (xs/sm/md/lg/xl/2xl) or pixel value
|
|
604
|
-
- `color` - CSS color (defaults to currentColor)
|
|
605
|
-
- `label` - Accessible name (makes icon `role="img"`)
|
|
606
|
-
|
|
607
|
-
**`<pds-drawer>`** - Slide-out panels
|
|
608
|
-
```html
|
|
609
|
-
<pds-drawer id="menu" position="left">
|
|
610
|
-
<h2 slot="header">Menu</h2>
|
|
611
|
-
<nav>...</nav>
|
|
612
|
-
</pds-drawer>
|
|
613
|
-
|
|
614
|
-
<button onclick="document.getElementById('menu').open()">
|
|
615
|
-
Open Menu
|
|
616
|
-
</button>
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
Attributes:
|
|
620
|
-
- `position` - left/right/top/bottom
|
|
621
|
-
- `open` - Boolean, controls visibility
|
|
622
|
-
|
|
623
|
-
Methods:
|
|
624
|
-
- `open()` - Show drawer
|
|
625
|
-
- `close()` - Hide drawer
|
|
626
|
-
- `toggle()` - Toggle visibility
|
|
627
|
-
|
|
628
|
-
**`<pds-tabstrip>`** - Accessible tab interface
|
|
629
|
-
```html
|
|
630
|
-
<pds-tabstrip>
|
|
631
|
-
<button slot="tab">Overview</button>
|
|
632
|
-
<div slot="panel">Overview content</div>
|
|
633
|
-
|
|
634
|
-
<button slot="tab">Details</button>
|
|
635
|
-
<div slot="panel">Details content</div>
|
|
636
|
-
</pds-tabstrip>
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
Features:
|
|
640
|
-
- Keyboard navigation (Arrow keys, Home, End)
|
|
641
|
-
- ARIA attributes automatic
|
|
642
|
-
- Focus management
|
|
643
|
-
- URL hash sync (optional)
|
|
644
|
-
|
|
645
|
-
**`<pds-upload>`** - File upload with preview
|
|
646
|
-
```html
|
|
647
|
-
<pds-upload
|
|
648
|
-
accept="image/*"
|
|
649
|
-
multiple
|
|
650
|
-
max-size="5000000">
|
|
651
|
-
</pds-upload>
|
|
652
|
-
```
|
|
653
|
-
|
|
654
|
-
Attributes:
|
|
655
|
-
- `accept` - File types (MIME or extensions)
|
|
656
|
-
- `multiple` - Allow multiple files
|
|
657
|
-
- `max-size` - Max file size in bytes
|
|
658
|
-
- `max-files` - Max number of files
|
|
659
|
-
|
|
660
|
-
Events:
|
|
661
|
-
- `files-changed` - Fired when selection changes
|
|
662
|
-
- `file-error` - Fired on validation errors
|
|
663
|
-
|
|
664
|
-
**`<pds-toaster>`** - Toast notifications
|
|
665
|
-
```html
|
|
666
|
-
<pds-toaster id="toaster"></pds-toaster>
|
|
667
|
-
|
|
668
|
-
<script>
|
|
669
|
-
const toaster = document.getElementById('toaster');
|
|
670
|
-
toaster.show({
|
|
671
|
-
message: 'Saved successfully!',
|
|
672
|
-
type: 'success',
|
|
673
|
-
duration: 3000
|
|
674
|
-
});
|
|
675
|
-
</script>
|
|
676
|
-
```
|
|
677
|
-
|
|
678
|
-
Or use via events:
|
|
679
|
-
```javascript
|
|
680
|
-
PDS.dispatchEvent(new CustomEvent('pds:toast', {
|
|
681
|
-
detail: {
|
|
682
|
-
message: 'Error occurred',
|
|
683
|
-
type: 'danger',
|
|
684
|
-
duration: 5000
|
|
685
|
-
}
|
|
686
|
-
}));
|
|
687
|
-
```
|
|
688
|
-
|
|
689
|
-
**`<pds-richtext>`** - Rich text editor
|
|
690
|
-
```html
|
|
691
|
-
<script type="importmap">
|
|
692
|
-
{
|
|
693
|
-
"imports": {
|
|
694
|
-
"#showdown": "https://cdn.jsdelivr.net/npm/showdown@2.1.0/dist/showdown.mjs"
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
</script>
|
|
698
|
-
|
|
699
|
-
<pds-richtext
|
|
700
|
-
value="<p>Initial content</p>"
|
|
701
|
-
format="html">
|
|
702
|
-
</pds-richtext>
|
|
703
|
-
```
|
|
704
|
-
|
|
705
|
-
Set `format="markdown"` when you want the submitted form value to stay in Markdown:
|
|
706
|
-
```html
|
|
707
|
-
<pds-richtext name="release-notes" format="markdown"></pds-richtext>
|
|
708
|
-
```
|
|
709
|
-
The element will use the `#showdown` import-map specifier first, and will only fall back to loading the script from CDNs if that specifier is missing.
|
|
710
|
-
|
|
711
|
-
Features:
|
|
712
|
-
- Bold, italic, underline, strikethrough
|
|
713
|
-
- Headings, lists, links
|
|
714
|
-
- Code blocks
|
|
715
|
-
- Undo/redo
|
|
716
|
-
- Markdown shortcuts
|
|
717
|
-
|
|
718
|
-
**`<pds-form>`** - Dynamic forms from JSON Schema
|
|
719
|
-
```html
|
|
720
|
-
<pds-form schema='{"type":"object","properties":{...}}'></pds-form>
|
|
721
|
-
```
|
|
722
|
-
|
|
723
|
-
Generates complete forms with validation from JSON Schema.
|
|
724
|
-
|
|
725
|
-
**`<pds-splitpanel>`** - Resizable panes
|
|
726
|
-
```html
|
|
727
|
-
<pds-splitpanel orientation="horizontal">
|
|
728
|
-
<div slot="start">Left pane</div>
|
|
729
|
-
<div slot="end">Right pane</div>
|
|
730
|
-
</pds-splitpanel>
|
|
731
|
-
```
|
|
732
|
-
|
|
733
|
-
**`<pds-scrollrow>`** - Horizontal scrolling container
|
|
734
|
-
```html
|
|
735
|
-
<pds-scrollrow>
|
|
736
|
-
<div class="card">Card 1</div>
|
|
737
|
-
<div class="card">Card 2</div>
|
|
738
|
-
<div class="card">Card 3</div>
|
|
739
|
-
</pds-scrollrow>
|
|
740
|
-
```
|
|
741
|
-
|
|
742
|
-
Shows scroll buttons when content overflows.
|
|
743
|
-
|
|
744
|
-
#### Auto-Define System
|
|
745
|
-
|
|
746
|
-
Components are registered automatically when their tags appear in the DOM:
|
|
747
|
-
|
|
748
|
-
```javascript
|
|
749
|
-
await PDS.start({
|
|
750
|
-
autoDefine: {
|
|
751
|
-
baseURL: '/auto-define/',
|
|
752
|
-
|
|
753
|
-
// Eagerly load these components
|
|
754
|
-
predefine: ['pds-icon', 'pds-drawer'],
|
|
755
|
-
|
|
756
|
-
// Custom file mapping
|
|
757
|
-
mapper: (tag) => {
|
|
758
|
-
if (tag.startsWith('my-')) {
|
|
759
|
-
return `/components/${tag}.js`;
|
|
760
|
-
}
|
|
761
|
-
// Return nothing to use PDS default mapping
|
|
762
|
-
},
|
|
763
|
-
|
|
764
|
-
// Advanced options
|
|
765
|
-
scanExisting: true, // Scan for tags on init
|
|
766
|
-
observeShadows: true, // Watch Shadow DOM
|
|
767
|
-
patchAttachShadow: true, // Monitor dynamic shadows
|
|
768
|
-
debounceMs: 16 // Debounce observation
|
|
769
|
-
}
|
|
770
|
-
});
|
|
771
|
-
```
|
|
772
|
-
|
|
773
|
-
The system:
|
|
774
|
-
1. Observes DOM for new custom elements
|
|
775
|
-
2. Checks if tag is defined
|
|
776
|
-
3. Loads corresponding module
|
|
777
|
-
4. Registers custom element
|
|
778
|
-
5. Upgrades existing instances
|
|
779
|
-
|
|
780
|
-
> ⚠️ **Important: Programmatic Access to Auto-Defined Components**
|
|
781
|
-
>
|
|
782
|
-
> Components loaded via `autoDefine` are registered asynchronously. If you need to access component methods or properties programmatically (e.g., `toaster.toast()`), ensure the component is defined first:
|
|
783
|
-
>
|
|
784
|
-
> ```javascript
|
|
785
|
-
> // Wait for component to be defined
|
|
786
|
-
> await customElements.whenDefined('pds-toaster');
|
|
787
|
-
> const toaster = document.querySelector('pds-toaster');
|
|
788
|
-
> toaster.toast('Hello!');
|
|
789
|
-
> ```
|
|
790
|
-
>
|
|
791
|
-
> **Alternative:** Use `predefine` to eagerly load components at `PDS.start()` time:
|
|
792
|
-
>
|
|
793
|
-
> ```javascript
|
|
794
|
-
> await PDS.start({
|
|
795
|
-
> autoDefine: {
|
|
796
|
-
> predefine: ['pds-toaster', 'pds-icon'] // Loaded immediately
|
|
797
|
-
> }
|
|
798
|
-
> });
|
|
799
|
-
> // Components are now available synchronously
|
|
800
|
-
> ```
|
|
801
|
-
|
|
802
|
-
---
|
|
803
|
-
|
|
804
|
-
## Styling Layers
|
|
805
|
-
|
|
806
|
-
PDS generates CSS in structured layers for predictable specificity and modularity.
|
|
807
|
-
|
|
808
|
-
### Layer Structure
|
|
809
|
-
|
|
810
|
-
```
|
|
811
|
-
┌──────────────────────────────────────────────────────────┐
|
|
812
|
-
│ tokens CSS Custom Properties │
|
|
813
|
-
│ --color-*, --spacing-*, --font-* │
|
|
814
|
-
├──────────────────────────────────────────────────────────┤
|
|
815
|
-
│ primitives Base elements │
|
|
816
|
-
│ button, input, .card, .badge │
|
|
817
|
-
├──────────────────────────────────────────────────────────┤
|
|
818
|
-
│ components Rich UI │
|
|
819
|
-
│ .drawer, .tabstrip, .upload │
|
|
820
|
-
├──────────────────────────────────────────────────────────┤
|
|
821
|
-
│ utilities Composable helpers │
|
|
822
|
-
│ .flex, .gap-4, .border-gradient │
|
|
823
|
-
└──────────────────────────────────────────────────────────┘
|
|
824
|
-
```
|
|
825
|
-
|
|
826
|
-
### Layer Details
|
|
827
|
-
|
|
828
|
-
**Tokens** - Design foundation
|
|
829
|
-
- Colors (scales + semantics)
|
|
830
|
-
- Spacing (0-12 progression)
|
|
831
|
-
- Typography (families, sizes, weights)
|
|
832
|
-
- Borders (widths, radius)
|
|
833
|
-
- Shadows (depths)
|
|
834
|
-
- Transitions (speeds)
|
|
835
|
-
- Z-index (layers)
|
|
836
|
-
- Layout (breakpoints, max-width)
|
|
837
|
-
|
|
838
|
-
**Primitives** - Native elements enhanced
|
|
839
|
-
- Buttons (`.btn-primary`, `.btn-secondary`, `.btn-outline`)
|
|
840
|
-
- Forms (`input`, `select`, `textarea`, `fieldset`)
|
|
841
|
-
- Surfaces (`.card`, `.surface`)
|
|
842
|
-
- Badges (`.badge`, `.badge-success`)
|
|
843
|
-
- Alerts (`.alert`, `.alert-warning`)
|
|
844
|
-
- Typography (headings, paragraphs, lists)
|
|
845
|
-
- Tables (responsive, striped)
|
|
846
|
-
|
|
847
|
-
**Components** - Web Component styles
|
|
848
|
-
- Styles for `<pds-*>` elements
|
|
849
|
-
- Internal component structure
|
|
850
|
-
- State management (`:state()` selectors)
|
|
851
|
-
|
|
852
|
-
**Utilities** - Layout and effects
|
|
853
|
-
- Flex (`.flex`, `.flex-col`, `.items-center`)
|
|
854
|
-
- Grid (`.grid`, `.grid-cols-3`)
|
|
855
|
-
- Spacing (`.gap-4`, `.p-4`, `.m-2`)
|
|
856
|
-
- Borders (`.border`, `.border-gradient`, `.border-glow`)
|
|
857
|
-
- Effects (`.shadow-lg`, `.rounded-lg`)
|
|
858
|
-
|
|
859
|
-
### Accessing Layers
|
|
860
|
-
|
|
861
|
-
**In live mode:**
|
|
862
|
-
```javascript
|
|
863
|
-
const compiled = PDS.compiled;
|
|
864
|
-
|
|
865
|
-
// Get layer CSS
|
|
866
|
-
const tokensCSS = compiled.layers.tokens.css;
|
|
867
|
-
const primitivesCSS = compiled.layers.primitives.css;
|
|
868
|
-
|
|
869
|
-
// Get as stylesheet
|
|
870
|
-
const sheet = await PDS.registry.getStylesheet('primitives');
|
|
871
|
-
```
|
|
872
|
-
|
|
873
|
-
**In static mode:**
|
|
874
|
-
```javascript
|
|
875
|
-
// Import constructable stylesheets
|
|
876
|
-
import tokensSheet from '/pds/styles/pds-tokens.css.js';
|
|
877
|
-
import primitivesSheet from '/pds/styles/pds-primitives.css.js';
|
|
878
|
-
```
|
|
879
|
-
|
|
880
|
-
---
|
|
881
|
-
|
|
882
|
-
## Shadow DOM Adoption
|
|
883
|
-
|
|
884
|
-
PDS provides helpers for adopting styles into Shadow DOM.
|
|
885
|
-
|
|
886
|
-
### Basic Adoption
|
|
887
|
-
|
|
888
|
-
```javascript
|
|
889
|
-
class MyComponent extends HTMLElement {
|
|
890
|
-
constructor() {
|
|
891
|
-
super();
|
|
892
|
-
this.attachShadow({ mode: 'open' });
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
async connectedCallback() {
|
|
896
|
-
// Adopt just primitives (most common)
|
|
897
|
-
await PDS.adoptPrimitives(this.shadowRoot);
|
|
898
|
-
|
|
899
|
-
this.shadowRoot.innerHTML = `
|
|
900
|
-
<button class="btn-primary">Click me</button>
|
|
901
|
-
`;
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
```
|
|
905
|
-
|
|
906
|
-
### Multiple Layers
|
|
907
|
-
|
|
908
|
-
```javascript
|
|
909
|
-
// Adopt specific layers
|
|
910
|
-
await PDS.adoptLayers(this.shadowRoot, ['primitives', 'components']);
|
|
911
|
-
|
|
912
|
-
// Adopt with custom styles
|
|
913
|
-
const myStyles = PDS.createStylesheet(`
|
|
914
|
-
:host {
|
|
915
|
-
display: block;
|
|
916
|
-
padding: var(--spacing-4);
|
|
917
|
-
}
|
|
918
|
-
`);
|
|
919
|
-
|
|
920
|
-
await PDS.adoptLayers(this.shadowRoot, ['primitives'], [myStyles]);
|
|
921
|
-
```
|
|
922
|
-
|
|
923
|
-
### Lit Component Example
|
|
924
|
-
|
|
925
|
-
```javascript
|
|
926
|
-
import { html, css, LitElement } from '#pds/lit';
|
|
927
|
-
|
|
928
|
-
class MyCard extends LitElement {
|
|
929
|
-
static styles = css`
|
|
930
|
-
:host {
|
|
931
|
-
display: block;
|
|
932
|
-
}
|
|
933
|
-
`;
|
|
934
|
-
|
|
935
|
-
async connectedCallback() {
|
|
936
|
-
super.connectedCallback();
|
|
937
|
-
await PDS.adoptPrimitives(this.shadowRoot);
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
render() {
|
|
941
|
-
return html`
|
|
942
|
-
<article class="card">
|
|
943
|
-
<h3>Card Title</h3>
|
|
944
|
-
<p>Card content</p>
|
|
945
|
-
<button class="btn-primary">Action</button>
|
|
946
|
-
</article>
|
|
947
|
-
`;
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
```
|
|
951
|
-
|
|
952
|
-
---
|
|
953
|
-
|
|
954
|
-
## Icon System
|
|
955
|
-
|
|
956
|
-
PDS uses SVG sprites for efficient icon rendering.
|
|
957
|
-
|
|
958
|
-
### Icon Component
|
|
959
|
-
|
|
960
|
-
```html
|
|
961
|
-
<!-- Basic usage -->
|
|
962
|
-
<pds-icon icon="heart"></pds-icon>
|
|
963
|
-
|
|
964
|
-
<!-- Sized icons -->
|
|
965
|
-
<pds-icon icon="star" size="sm"></pds-icon>
|
|
966
|
-
<pds-icon icon="star" size="lg"></pds-icon>
|
|
967
|
-
<pds-icon icon="star" size="32"></pds-icon>
|
|
968
|
-
|
|
969
|
-
<!-- Colored icons -->
|
|
970
|
-
<pds-icon icon="warning" color="red"></pds-icon>
|
|
971
|
-
<pds-icon icon="info" color="var(--color-primary-500)"></pds-icon>
|
|
972
|
-
|
|
973
|
-
<!-- Accessible icons -->
|
|
974
|
-
<pds-icon icon="list" label="Open navigation menu"></pds-icon>
|
|
975
|
-
```
|
|
976
|
-
|
|
977
|
-
### Configuration
|
|
978
|
-
|
|
979
|
-
```javascript
|
|
980
|
-
await PDS.start({
|
|
981
|
-
design: {
|
|
982
|
-
icons: {
|
|
983
|
-
set: 'phosphor', // Icon family
|
|
984
|
-
weight: 'regular', // Icon weight
|
|
985
|
-
defaultSize: 24, // Default size in pixels
|
|
986
|
-
sizes: { // Named sizes
|
|
987
|
-
xs: 16,
|
|
988
|
-
sm: 20,
|
|
989
|
-
md: 24,
|
|
990
|
-
lg: 32,
|
|
991
|
-
xl: 48,
|
|
992
|
-
'2xl': 64
|
|
993
|
-
},
|
|
994
|
-
spritePath: '/assets/pds/icons/pds-icons.svg'
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
});
|
|
998
|
-
```
|
|
999
|
-
|
|
1000
|
-
### Custom Icons
|
|
1001
|
-
|
|
1002
|
-
Add custom icons to the sprite:
|
|
1003
|
-
|
|
1004
|
-
**1. Configure custom icons:**
|
|
1005
|
-
```javascript
|
|
1006
|
-
// pds.config.js
|
|
1007
|
-
export default {
|
|
1008
|
-
design: {
|
|
1009
|
-
icons: {
|
|
1010
|
-
set: 'phosphor',
|
|
1011
|
-
include: [
|
|
1012
|
-
'house', 'gear', 'heart', 'star',
|
|
1013
|
-
'user', 'bell', 'search', 'menu'
|
|
1014
|
-
]
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
};
|
|
1018
|
-
```
|
|
1019
|
-
|
|
1020
|
-
**2. Rebuild sprite:**
|
|
1021
|
-
```bash
|
|
1022
|
-
npm run pds:build-icons
|
|
1023
|
-
```
|
|
1024
|
-
|
|
1025
|
-
**3. Use in your app:**
|
|
1026
|
-
```html
|
|
1027
|
-
<pds-icon icon="house"></pds-icon>
|
|
1028
|
-
```
|
|
1029
|
-
|
|
1030
|
-
### Icon Tokens
|
|
1031
|
-
|
|
1032
|
-
Icons are available as CSS custom properties:
|
|
1033
|
-
|
|
1034
|
-
```css
|
|
1035
|
-
--icon-set: phosphor;
|
|
1036
|
-
--icon-weight: regular;
|
|
1037
|
-
--icon-size-xs: 16px;
|
|
1038
|
-
--icon-size-sm: 20px;
|
|
1039
|
-
--icon-size-md: 24px;
|
|
1040
|
-
--icon-size-lg: 32px;
|
|
1041
|
-
```
|
|
1042
|
-
|
|
1043
|
-
---
|
|
1044
|
-
|
|
1045
|
-
## Smart Query System
|
|
1046
|
-
|
|
1047
|
-
Ask questions about your design system using natural language.
|
|
1048
|
-
|
|
1049
|
-
### Usage
|
|
1050
|
-
|
|
1051
|
-
```javascript
|
|
1052
|
-
// Programmatic API
|
|
1053
|
-
const results = await PDS.query("what is the focus border color on inputs?");
|
|
1054
|
-
|
|
1055
|
-
results.forEach(result => {
|
|
1056
|
-
console.log(result.text); // "Focus border color: var(--color-primary-500)"
|
|
1057
|
-
console.log(result.category); // "Color Token"
|
|
1058
|
-
console.log(result.cssVar); // "var(--color-primary-500)"
|
|
1059
|
-
console.log(result.code); // Example code
|
|
1060
|
-
});
|
|
1061
|
-
```
|
|
1062
|
-
|
|
1063
|
-
### Example Queries
|
|
1064
|
-
|
|
1065
|
-
**Color Questions:**
|
|
1066
|
-
```javascript
|
|
1067
|
-
await PDS.query("what is the focus border color on inputs?")
|
|
1068
|
-
await PDS.query("what foreground color should I use on this surface?")
|
|
1069
|
-
await PDS.query("button hover color")
|
|
1070
|
-
await PDS.query("primary color scale")
|
|
1071
|
-
```
|
|
1072
|
-
|
|
1073
|
-
**Utility Questions:**
|
|
1074
|
-
```javascript
|
|
1075
|
-
await PDS.query("what are the utility classes for borders?")
|
|
1076
|
-
await PDS.query("border gradient effect")
|
|
1077
|
-
await PDS.query("flex layout utilities")
|
|
1078
|
-
await PDS.query("gap between elements")
|
|
1079
|
-
```
|
|
1080
|
-
|
|
1081
|
-
**Component Questions:**
|
|
1082
|
-
```javascript
|
|
1083
|
-
await PDS.query("how do I create an icon-only button?")
|
|
1084
|
-
await PDS.query("drawer component")
|
|
1085
|
-
await PDS.query("tab strip usage")
|
|
1086
|
-
```
|
|
1087
|
-
|
|
1088
|
-
**Layout Questions:**
|
|
1089
|
-
```javascript
|
|
1090
|
-
await PDS.query("how can I group stuff in containers?")
|
|
1091
|
-
await PDS.query("grid container")
|
|
1092
|
-
await PDS.query("card component")
|
|
1093
|
-
```
|
|
1094
|
-
|
|
1095
|
-
### AutoComplete Integration
|
|
1096
|
-
|
|
1097
|
-
The query system integrates with `#pds-search` in the configurator. Type queries directly in the search box for instant answers.
|
|
1098
|
-
|
|
1099
|
-
### How It Works
|
|
1100
|
-
|
|
1101
|
-
1. **Intent Detection** - Recognizes what you're asking about (color, spacing, component, utility)
|
|
1102
|
-
2. **Entity Recognition** - Identifies design elements (button, input, surface)
|
|
1103
|
-
3. **Context Analysis** - Detects states (hover, focus, active)
|
|
1104
|
-
4. **Data Querying** - Searches `PDS.compiled`, `PDS.ontology`, `PDS.currentConfig`
|
|
1105
|
-
5. **Scoring & Ranking** - Returns top 10 most relevant results
|
|
1106
|
-
|
|
1107
|
-
See [PDS-QUERY-SYSTEM.md](./PDS-QUERY-SYSTEM.md) for detailed documentation.
|
|
1108
|
-
|
|
1109
|
-
---
|
|
1110
|
-
|
|
1111
|
-
## Design Validation
|
|
1112
|
-
|
|
1113
|
-
PDS automatically validates designs for accessibility issues.
|
|
1114
|
-
|
|
1115
|
-
### Automatic Validation
|
|
1116
|
-
|
|
1117
|
-
In live mode with presets enabled:
|
|
1118
|
-
|
|
1119
|
-
```bash
|
|
1120
|
-
npm run build
|
|
1121
|
-
```
|
|
1122
|
-
|
|
1123
|
-
Validates all presets during build and reports issues:
|
|
1124
|
-
|
|
1125
|
-
```
|
|
1126
|
-
❌ Preset validation failed:
|
|
1127
|
-
|
|
1128
|
-
— Travel Market
|
|
1129
|
-
• Primary text on surface is too low (3.95 < 4.5)
|
|
1130
|
-
[light/outline] (/colors/primary)
|
|
1131
|
-
|
|
1132
|
-
— Mobility App
|
|
1133
|
-
• Primary button contrast too low in dark theme (2.85 < 4.5)
|
|
1134
|
-
[dark/btn-primary] (/colors/darkMode/primary)
|
|
1135
|
-
```
|
|
1136
|
-
|
|
1137
|
-
### Manual Validation
|
|
1138
|
-
|
|
1139
|
-
```javascript
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
//
|
|
1154
|
-
//
|
|
1155
|
-
//
|
|
1156
|
-
//
|
|
1157
|
-
//
|
|
1158
|
-
//
|
|
1159
|
-
//
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
})
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
- **
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
PDS
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
- `pds:
|
|
1262
|
-
- `pds:
|
|
1263
|
-
- `pds:
|
|
1264
|
-
- `pds:
|
|
1265
|
-
- `pds:
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
PDS.theme
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
compiled.
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
compiled.
|
|
1298
|
-
compiled.
|
|
1299
|
-
|
|
1300
|
-
//
|
|
1301
|
-
compiled.
|
|
1302
|
-
compiled.
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
compiled.
|
|
1307
|
-
compiled.
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
//
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
- `
|
|
1340
|
-
- `
|
|
1341
|
-
- `
|
|
1342
|
-
- `
|
|
1343
|
-
- `
|
|
1344
|
-
- `
|
|
1345
|
-
- `
|
|
1346
|
-
- `
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
```
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
PDS
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
PDS.
|
|
1458
|
-
PDS.
|
|
1459
|
-
PDS.
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
});
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
```
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
|
1570
|
-
|
|
1571
|
-
| `
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
```
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
│ ├── pds-
|
|
1610
|
-
│ ├── pds-
|
|
1611
|
-
│
|
|
1612
|
-
├──
|
|
1613
|
-
│
|
|
1614
|
-
├──
|
|
1615
|
-
│
|
|
1616
|
-
├──
|
|
1617
|
-
|
|
1618
|
-
├──
|
|
1619
|
-
└── pds
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
```
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
```
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
```
|
|
1654
|
-
|
|
1655
|
-
###
|
|
1656
|
-
|
|
1657
|
-
```bash
|
|
1658
|
-
npm run
|
|
1659
|
-
```
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
####
|
|
1695
|
-
- ✅
|
|
1696
|
-
- ✅
|
|
1697
|
-
- ✅
|
|
1698
|
-
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
IntelliSense
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
#
|
|
1714
|
-
npm run pds:
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
<pds-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
```
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
-
|
|
1777
|
-
-
|
|
1778
|
-
-
|
|
1779
|
-
-
|
|
1780
|
-
|
|
1781
|
-
**
|
|
1782
|
-
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
}
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
};
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
**
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
form.
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
```
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
---
|
|
1994
|
-
|
|
1995
|
-
##
|
|
1996
|
-
|
|
1997
|
-
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
1
|
+
# Pure Design System (PDS)
|
|
2
|
+
|
|
3
|
+
> ⚠️ **Beta Software** - APIs are stabilizing but may still change. Pin versions in production: `"@pure-ds/core": "~0.3.0"`
|
|
4
|
+
|
|
5
|
+
[](https://github.com/mvneerven/pure-ds/actions/workflows/ci.yml)
|
|
6
|
+
[](#license)
|
|
7
|
+
[](https://www.npmjs.com/package/@pure-ds/core)
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
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.
|
|
16
|
+
|
|
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)
|
|
21
|
+
|
|
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
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
// pds.config.js
|
|
28
|
+
export const config = {
|
|
29
|
+
design: {
|
|
30
|
+
colors: { primary: '#007acc', secondary: '#5c2d91' },
|
|
31
|
+
typography: { baseFontSize: 16, fontScale: 1.25 },
|
|
32
|
+
spatialRhythm: { baseUnit: 8, scaleRatio: 1.5 }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### The Result
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
// app.js
|
|
41
|
+
import { PDS } from '@pure-ds/core';
|
|
42
|
+
import { config } from './pds.config.js';
|
|
43
|
+
|
|
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:
|
|
54
|
+
|
|
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>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
No `.text-blue-500`. No `.p-4`. No `.rounded-lg`. **Spacing, colors, radii are tokens—not classes.**
|
|
70
|
+
|
|
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
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Table of Contents
|
|
113
|
+
|
|
114
|
+
- [The Three Layers](#the-three-layers)
|
|
115
|
+
- [Who is it For?](#who-is-it-for)
|
|
116
|
+
- [Getting Started](#getting-started)
|
|
117
|
+
- [Core Architecture](#core-architecture)
|
|
118
|
+
- [Styling Layers](#styling-layers)
|
|
119
|
+
- [Shadow DOM Adoption](#shadow-dom-adoption)
|
|
120
|
+
- [Icon System](#icon-system)
|
|
121
|
+
- [Smart Query System](#smart-query-system)
|
|
122
|
+
- [Design Validation](#design-validation)
|
|
123
|
+
- [Advanced Features](#advanced-features)
|
|
124
|
+
- [API Reference](#api-reference)
|
|
125
|
+
- [Extending PDS](#extending-pds)
|
|
126
|
+
- [Using from CDN](#using-from-cdn)
|
|
127
|
+
- [CLI & Export](#cli--export)
|
|
128
|
+
- [Custom Elements Manifest](#custom-elements-manifest)
|
|
129
|
+
- [Framework Integration](#framework-integration)
|
|
130
|
+
- [Troubleshooting](#troubleshooting)
|
|
131
|
+
- [License](#license)
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
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-form>` — 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.
|
|
176
|
+
|
|
177
|
+
### How It Works
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
181
|
+
│ Configuration │
|
|
182
|
+
│ ───────────── │
|
|
183
|
+
│ colors: { primary: '#007acc' } │
|
|
184
|
+
│ typography: { baseFontSize: 16, fontScale: 1.25 } │
|
|
185
|
+
│ spatialRhythm: { baseUnit: 8 } │
|
|
186
|
+
└─────────────────────┬────────────────────────────────────────┘
|
|
187
|
+
│
|
|
188
|
+
▼
|
|
189
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
190
|
+
│ Generator (Live or Static) │
|
|
191
|
+
│ ────────────────────────── │
|
|
192
|
+
│ • Generates color scales (primary-50 → primary-900) │
|
|
193
|
+
│ • Creates surface tokens (bg, text, border, shadow) │
|
|
194
|
+
│ • Computes spacing progression (0-12) │
|
|
195
|
+
│ • Builds typography scale (6 levels) │
|
|
196
|
+
│ • Generates CSS layers (tokens → primitives → utilities) │
|
|
197
|
+
│ • Validates contrast ratios (WCAG AA) │
|
|
198
|
+
└─────────────────────┬────────────────────────────────────────┘
|
|
199
|
+
│
|
|
200
|
+
▼
|
|
201
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
202
|
+
│ Output │
|
|
203
|
+
│ ────── │
|
|
204
|
+
│ Tokens: --color-primary-500, --spacing-4 │
|
|
205
|
+
│ Primitives: .btn-primary, .card, .badge │
|
|
206
|
+
│ Components: <pds-drawer>, <pds-icon> │
|
|
207
|
+
│ Utilities: .flex, .gap-md, .border-gradient │
|
|
208
|
+
└──────────────────────────────────────────────────────────────┘
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Who is it For?
|
|
214
|
+
|
|
215
|
+
### 🎨 Design System Teams
|
|
216
|
+
- Generate multiple brand variants from a single codebase
|
|
217
|
+
- A/B test design directions by swapping configs
|
|
218
|
+
- Maintain consistency with centralized tokens
|
|
219
|
+
- Validate accessibility automatically
|
|
220
|
+
|
|
221
|
+
### 🚀 Product Teams
|
|
222
|
+
- Ship faster with auto-generated primitives
|
|
223
|
+
- Customize with JS config instead of SASS/CSS
|
|
224
|
+
- Work with any framework or no framework
|
|
225
|
+
- Reduce bundle size with lazy-loaded components
|
|
226
|
+
|
|
227
|
+
### 🛠️ Design Tool Builders
|
|
228
|
+
- Build live configurators with instant preview
|
|
229
|
+
- Export static bundles for production
|
|
230
|
+
- Query the system programmatically
|
|
231
|
+
- Access complete object model for introspection
|
|
232
|
+
|
|
233
|
+
### 👩💻 Developers
|
|
234
|
+
- Learn by exploring the interactive showcase
|
|
235
|
+
- Adopt incrementally (tokens only → full system)
|
|
236
|
+
- Extend with custom enhancers and components
|
|
237
|
+
- Debug with structured CSS layers
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Getting Started
|
|
242
|
+
|
|
243
|
+
### Installation
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
npm install @pure-ds/core
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Post-install automation:**
|
|
250
|
+
|
|
251
|
+
During installation, PDS automatically:
|
|
252
|
+
- Creates a default `pds.config.js` (if one doesn't exist)
|
|
253
|
+
- Copies Copilot/AI instructions to `.github/copilot-instructions.md`
|
|
254
|
+
- Adds `pds:export` and `pds:build-icons` scripts to your `package.json`
|
|
255
|
+
- Runs `pds:export` to generate static assets
|
|
256
|
+
|
|
257
|
+
To manually re-sync assets:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
npm run pds:export
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Lit Import Convention
|
|
264
|
+
|
|
265
|
+
PDS uses a virtual import for Lit so you control the resolution:
|
|
266
|
+
|
|
267
|
+
```javascript
|
|
268
|
+
import { html, css, LitElement } from '#pds/lit';
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**In browsers (no bundler)** - Use import maps:
|
|
272
|
+
|
|
273
|
+
```html
|
|
274
|
+
<script type="importmap">
|
|
275
|
+
{
|
|
276
|
+
"imports": {
|
|
277
|
+
"#pds/lit": "/assets/js/lit.js"
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
</script>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**In bundlers** - Alias to the real `lit` package:
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
// vite.config.js
|
|
287
|
+
export default {
|
|
288
|
+
resolve: {
|
|
289
|
+
alias: { '#pds/lit': 'lit' }
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Quick Start: Live Mode
|
|
295
|
+
|
|
296
|
+
Generate styles at runtime with instant updates:
|
|
297
|
+
|
|
298
|
+
```javascript
|
|
299
|
+
import { PDS } from '@pure-ds/core';
|
|
300
|
+
|
|
301
|
+
await PDS.start({
|
|
302
|
+
mode: 'live',
|
|
303
|
+
preset: 'default', // or: ocean-breeze, midnight-steel, etc.
|
|
304
|
+
|
|
305
|
+
// Override preset values
|
|
306
|
+
design: {
|
|
307
|
+
colors: {
|
|
308
|
+
primary: '#007acc',
|
|
309
|
+
secondary: '#5c2d91'
|
|
310
|
+
},
|
|
311
|
+
typography: {
|
|
312
|
+
fontFamilyHeadings: 'Inter, sans-serif',
|
|
313
|
+
fontFamilyBody: 'Inter, sans-serif'
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
// Component auto-loading
|
|
318
|
+
autoDefine: {
|
|
319
|
+
predefine: ['pds-icon'] // Eagerly load these
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// Use components - they'll lazy-load automatically
|
|
324
|
+
// <pds-drawer id="menu"></pds-drawer>
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Quick Start: Static Mode
|
|
328
|
+
|
|
329
|
+
Pre-generate assets for production:
|
|
330
|
+
|
|
331
|
+
**1. Export static files:**
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
npm run pds:export
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
This creates:
|
|
338
|
+
- `pds/styles/pds-*.css` and `pds-*.css.js` (Constructable Stylesheets)
|
|
339
|
+
- `pds/components/*.js` (Web Components)
|
|
340
|
+
- `pds/icons/pds-icons.svg` (Icon sprite)
|
|
341
|
+
- `pds/custom-elements.json` (Custom Elements Manifest for IDE integration)
|
|
342
|
+
|
|
343
|
+
**2. Initialize in static mode:**
|
|
344
|
+
|
|
345
|
+
```javascript
|
|
346
|
+
import { PDS } from '@pure-ds/core';
|
|
347
|
+
|
|
348
|
+
await PDS.start({
|
|
349
|
+
mode: 'static',
|
|
350
|
+
preset: 'default',
|
|
351
|
+
|
|
352
|
+
staticPaths: {
|
|
353
|
+
tokens: '/pds/styles/pds-tokens.css.js',
|
|
354
|
+
primitives: '/pds/styles/pds-primitives.css.js',
|
|
355
|
+
components: '/pds/styles/pds-components.css.js',
|
|
356
|
+
utilities: '/pds/styles/pds-utilities.css.js',
|
|
357
|
+
styles: '/pds/styles/pds-styles.css.js'
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Minimal Example
|
|
363
|
+
|
|
364
|
+
```html
|
|
365
|
+
<!DOCTYPE html>
|
|
366
|
+
<html lang="en">
|
|
367
|
+
<head>
|
|
368
|
+
<meta charset="UTF-8">
|
|
369
|
+
<title>PDS App</title>
|
|
370
|
+
<script type="importmap">
|
|
371
|
+
{
|
|
372
|
+
"imports": {
|
|
373
|
+
"#pds/lit": "/assets/js/lit.js"
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
</script>
|
|
377
|
+
</head>
|
|
378
|
+
<body>
|
|
379
|
+
<button class="btn-primary">
|
|
380
|
+
<pds-icon icon="heart"></pds-icon>
|
|
381
|
+
Click me
|
|
382
|
+
</button>
|
|
383
|
+
|
|
384
|
+
<script type="module">
|
|
385
|
+
import { PDS } from '/assets/js/pds.js';
|
|
386
|
+
|
|
387
|
+
await PDS.start({
|
|
388
|
+
design: {
|
|
389
|
+
colors: { primary: '#007acc' }
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
</script>
|
|
393
|
+
</body>
|
|
394
|
+
</html>
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Core Architecture
|
|
400
|
+
|
|
401
|
+
PDS has three integrated systems that work together to create complete design systems.
|
|
402
|
+
|
|
403
|
+
### 1. Style Generation & Injection
|
|
404
|
+
|
|
405
|
+
The heart of PDS is the **Generator** - it transforms your configuration into structured CSS.
|
|
406
|
+
|
|
407
|
+
#### Token Generation
|
|
408
|
+
|
|
409
|
+
```javascript
|
|
410
|
+
// Your config
|
|
411
|
+
{
|
|
412
|
+
colors: { primary: '#007acc' },
|
|
413
|
+
typography: { baseFontSize: 16, fontScale: 1.25 },
|
|
414
|
+
spatialRhythm: { baseUnit: 8, scaleRatio: 1.5 }
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// PDS generates tokens
|
|
418
|
+
--color-primary-50 → #e6f7ff
|
|
419
|
+
--color-primary-100 → #b3e5ff
|
|
420
|
+
--color-primary-200 → #80d4ff
|
|
421
|
+
...
|
|
422
|
+
--color-primary-900 → #003d66
|
|
423
|
+
|
|
424
|
+
--spacing-0 → 0
|
|
425
|
+
--spacing-1 → 8px
|
|
426
|
+
--spacing-2 → 12px (8 × 1.5)
|
|
427
|
+
--spacing-3 → 18px (12 × 1.5)
|
|
428
|
+
...
|
|
429
|
+
|
|
430
|
+
--font-size-xs → 0.64rem
|
|
431
|
+
--font-size-sm → 0.8rem
|
|
432
|
+
--font-size-base → 1rem
|
|
433
|
+
--font-size-lg → 1.25rem
|
|
434
|
+
--font-size-xl → 1.5625rem
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
#### Surface Semantics
|
|
438
|
+
|
|
439
|
+
PDS generates smart surface tokens that adapt to context:
|
|
440
|
+
|
|
441
|
+
```css
|
|
442
|
+
/* Light theme */
|
|
443
|
+
--surface-bg: var(--color-gray-50);
|
|
444
|
+
--surface-text: var(--color-gray-900);
|
|
445
|
+
--surface-text-secondary: var(--color-gray-700);
|
|
446
|
+
--surface-border: var(--color-gray-300);
|
|
447
|
+
--surface-shadow: rgba(0, 0, 0, 0.1);
|
|
448
|
+
|
|
449
|
+
/* Dark theme (auto-generated) */
|
|
450
|
+
[data-theme="dark"] {
|
|
451
|
+
--surface-bg: var(--color-gray-900);
|
|
452
|
+
--surface-text: var(--color-gray-50);
|
|
453
|
+
--surface-text-secondary: var(--color-gray-300);
|
|
454
|
+
--surface-border: var(--color-gray-700);
|
|
455
|
+
--surface-shadow: rgba(0, 0, 0, 0.5);
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
#### Interactive States
|
|
460
|
+
|
|
461
|
+
Button and interactive element states are computed automatically:
|
|
462
|
+
|
|
463
|
+
```css
|
|
464
|
+
/* Primary button */
|
|
465
|
+
--primary-fill: var(--color-primary-600);
|
|
466
|
+
--primary-fill-hover: var(--color-primary-700);
|
|
467
|
+
--primary-fill-active: var(--color-primary-800);
|
|
468
|
+
|
|
469
|
+
/* Text/outline buttons */
|
|
470
|
+
--primary-text: var(--color-primary-600);
|
|
471
|
+
--primary-text-hover: var(--color-primary-700);
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
#### Live vs Static Mode
|
|
475
|
+
|
|
476
|
+
**Live Mode:**
|
|
477
|
+
- CSS generated in-browser at runtime
|
|
478
|
+
- Instant updates when config changes
|
|
479
|
+
- Perfect for design tools and configurators
|
|
480
|
+
- Access via `PDS.compiled` object model
|
|
481
|
+
- Automatic font loading from Google Fonts
|
|
482
|
+
|
|
483
|
+
**Static Mode:**
|
|
484
|
+
- CSS pre-generated at build time
|
|
485
|
+
- Optimized for production performance
|
|
486
|
+
- Host anywhere (CDN, static server)
|
|
487
|
+
- Constructable Stylesheets for instant adoption
|
|
488
|
+
- No runtime overhead
|
|
489
|
+
|
|
490
|
+
### 2. Progressive Enhancements
|
|
491
|
+
|
|
492
|
+
Lightweight JavaScript behaviors applied to semantic HTML. These are **not Web Components** - just DOM enhancements that make standard HTML more interactive.
|
|
493
|
+
|
|
494
|
+
#### Built-in Enhancers
|
|
495
|
+
|
|
496
|
+
**Dropdown Menus** - `<nav data-dropdown>`
|
|
497
|
+
|
|
498
|
+
```html
|
|
499
|
+
<nav data-dropdown>
|
|
500
|
+
<button>Menu</button>
|
|
501
|
+
<menu>
|
|
502
|
+
<li><a href="#home">Home</a></li>
|
|
503
|
+
<li><a href="#about">About</a></li>
|
|
504
|
+
<li><a href="#contact">Contact</a></li>
|
|
505
|
+
</menu>
|
|
506
|
+
</nav>
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
Features:
|
|
510
|
+
- Click to toggle visibility
|
|
511
|
+
- Auto-positioning (up/down based on space)
|
|
512
|
+
- Horizontal alignment (`.align-right` class)
|
|
513
|
+
- Keyboard support (Escape to close)
|
|
514
|
+
- Click-outside to close
|
|
515
|
+
- Scrollable when content exceeds viewport
|
|
516
|
+
|
|
517
|
+
**Toggle Switches** - `<label data-toggle>`
|
|
518
|
+
|
|
519
|
+
```html
|
|
520
|
+
<label data-toggle>
|
|
521
|
+
<span data-label>Enable notifications</span>
|
|
522
|
+
<input type="checkbox">
|
|
523
|
+
</label>
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
Creates styled toggle switches from standard checkboxes.
|
|
527
|
+
|
|
528
|
+
**Range Sliders** - `<input type="range">`
|
|
529
|
+
|
|
530
|
+
```html
|
|
531
|
+
<!-- Standard mode: floating bubble on interaction -->
|
|
532
|
+
<label>
|
|
533
|
+
<span>Volume</span>
|
|
534
|
+
<input type="range" min="0" max="100" value="50">
|
|
535
|
+
</label>
|
|
536
|
+
|
|
537
|
+
<!-- Inline output mode: persistent value display -->
|
|
538
|
+
<label class="range-output">
|
|
539
|
+
<span>Volume</span>
|
|
540
|
+
<input type="range" min="0" max="100" value="50">
|
|
541
|
+
</label>
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
Enhances range inputs with automatic value display. Use `range-output` class for inline output with semantic `<output>` element.
|
|
545
|
+
|
|
546
|
+
**Required Field Indicators** - `form [required]`
|
|
547
|
+
|
|
548
|
+
```html
|
|
549
|
+
<label>
|
|
550
|
+
<span>Email</span>
|
|
551
|
+
<input type="email" required>
|
|
552
|
+
</label>
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Automatically adds asterisk to label.
|
|
556
|
+
|
|
557
|
+
#### Custom Enhancers
|
|
558
|
+
|
|
559
|
+
Add your own progressive enhancements:
|
|
560
|
+
|
|
561
|
+
```javascript
|
|
562
|
+
await PDS.start({
|
|
563
|
+
enhancers: [
|
|
564
|
+
{
|
|
565
|
+
selector: '[data-tooltip]',
|
|
566
|
+
description: 'Adds tooltip on hover',
|
|
567
|
+
run: (element) => {
|
|
568
|
+
const text = element.dataset.tooltip;
|
|
569
|
+
element.addEventListener('mouseenter', () => {
|
|
570
|
+
// Show tooltip
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
selector: '[data-copy]',
|
|
576
|
+
description: 'Copy text to clipboard on click',
|
|
577
|
+
run: (element) => {
|
|
578
|
+
element.addEventListener('click', () => {
|
|
579
|
+
navigator.clipboard.writeText(element.dataset.copy);
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
]
|
|
584
|
+
});
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### 3. Web Components
|
|
588
|
+
|
|
589
|
+
Rich, reusable UI components built with Lit. Lazy-loaded automatically via the **Auto-Define** system.
|
|
590
|
+
|
|
591
|
+
#### Available Components
|
|
592
|
+
|
|
593
|
+
**`<pds-icon>`** - SVG sprite icons
|
|
594
|
+
```html
|
|
595
|
+
<pds-icon icon="heart"></pds-icon>
|
|
596
|
+
<pds-icon icon="star" size="lg"></pds-icon>
|
|
597
|
+
<pds-icon icon="list" size="32" color="red"></pds-icon>
|
|
598
|
+
<pds-icon icon="info" label="Information"></pds-icon>
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
Attributes:
|
|
602
|
+
- `icon` - Symbol ID (required)
|
|
603
|
+
- `size` - Named size (xs/sm/md/lg/xl/2xl) or pixel value
|
|
604
|
+
- `color` - CSS color (defaults to currentColor)
|
|
605
|
+
- `label` - Accessible name (makes icon `role="img"`)
|
|
606
|
+
|
|
607
|
+
**`<pds-drawer>`** - Slide-out panels
|
|
608
|
+
```html
|
|
609
|
+
<pds-drawer id="menu" position="left">
|
|
610
|
+
<h2 slot="header">Menu</h2>
|
|
611
|
+
<nav>...</nav>
|
|
612
|
+
</pds-drawer>
|
|
613
|
+
|
|
614
|
+
<button onclick="document.getElementById('menu').open()">
|
|
615
|
+
Open Menu
|
|
616
|
+
</button>
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
Attributes:
|
|
620
|
+
- `position` - left/right/top/bottom
|
|
621
|
+
- `open` - Boolean, controls visibility
|
|
622
|
+
|
|
623
|
+
Methods:
|
|
624
|
+
- `open()` - Show drawer
|
|
625
|
+
- `close()` - Hide drawer
|
|
626
|
+
- `toggle()` - Toggle visibility
|
|
627
|
+
|
|
628
|
+
**`<pds-tabstrip>`** - Accessible tab interface
|
|
629
|
+
```html
|
|
630
|
+
<pds-tabstrip>
|
|
631
|
+
<button slot="tab">Overview</button>
|
|
632
|
+
<div slot="panel">Overview content</div>
|
|
633
|
+
|
|
634
|
+
<button slot="tab">Details</button>
|
|
635
|
+
<div slot="panel">Details content</div>
|
|
636
|
+
</pds-tabstrip>
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
Features:
|
|
640
|
+
- Keyboard navigation (Arrow keys, Home, End)
|
|
641
|
+
- ARIA attributes automatic
|
|
642
|
+
- Focus management
|
|
643
|
+
- URL hash sync (optional)
|
|
644
|
+
|
|
645
|
+
**`<pds-upload>`** - File upload with preview
|
|
646
|
+
```html
|
|
647
|
+
<pds-upload
|
|
648
|
+
accept="image/*"
|
|
649
|
+
multiple
|
|
650
|
+
max-size="5000000">
|
|
651
|
+
</pds-upload>
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
Attributes:
|
|
655
|
+
- `accept` - File types (MIME or extensions)
|
|
656
|
+
- `multiple` - Allow multiple files
|
|
657
|
+
- `max-size` - Max file size in bytes
|
|
658
|
+
- `max-files` - Max number of files
|
|
659
|
+
|
|
660
|
+
Events:
|
|
661
|
+
- `files-changed` - Fired when selection changes
|
|
662
|
+
- `file-error` - Fired on validation errors
|
|
663
|
+
|
|
664
|
+
**`<pds-toaster>`** - Toast notifications
|
|
665
|
+
```html
|
|
666
|
+
<pds-toaster id="toaster"></pds-toaster>
|
|
667
|
+
|
|
668
|
+
<script>
|
|
669
|
+
const toaster = document.getElementById('toaster');
|
|
670
|
+
toaster.show({
|
|
671
|
+
message: 'Saved successfully!',
|
|
672
|
+
type: 'success',
|
|
673
|
+
duration: 3000
|
|
674
|
+
});
|
|
675
|
+
</script>
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
Or use via events:
|
|
679
|
+
```javascript
|
|
680
|
+
PDS.dispatchEvent(new CustomEvent('pds:toast', {
|
|
681
|
+
detail: {
|
|
682
|
+
message: 'Error occurred',
|
|
683
|
+
type: 'danger',
|
|
684
|
+
duration: 5000
|
|
685
|
+
}
|
|
686
|
+
}));
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
**`<pds-richtext>`** - Rich text editor
|
|
690
|
+
```html
|
|
691
|
+
<script type="importmap">
|
|
692
|
+
{
|
|
693
|
+
"imports": {
|
|
694
|
+
"#showdown": "https://cdn.jsdelivr.net/npm/showdown@2.1.0/dist/showdown.mjs"
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
</script>
|
|
698
|
+
|
|
699
|
+
<pds-richtext
|
|
700
|
+
value="<p>Initial content</p>"
|
|
701
|
+
format="html">
|
|
702
|
+
</pds-richtext>
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
Set `format="markdown"` when you want the submitted form value to stay in Markdown:
|
|
706
|
+
```html
|
|
707
|
+
<pds-richtext name="release-notes" format="markdown"></pds-richtext>
|
|
708
|
+
```
|
|
709
|
+
The element will use the `#showdown` import-map specifier first, and will only fall back to loading the script from CDNs if that specifier is missing.
|
|
710
|
+
|
|
711
|
+
Features:
|
|
712
|
+
- Bold, italic, underline, strikethrough
|
|
713
|
+
- Headings, lists, links
|
|
714
|
+
- Code blocks
|
|
715
|
+
- Undo/redo
|
|
716
|
+
- Markdown shortcuts
|
|
717
|
+
|
|
718
|
+
**`<pds-form>`** - Dynamic forms from JSON Schema
|
|
719
|
+
```html
|
|
720
|
+
<pds-form schema='{"type":"object","properties":{...}}'></pds-form>
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
Generates complete forms with validation from JSON Schema.
|
|
724
|
+
|
|
725
|
+
**`<pds-splitpanel>`** - Resizable panes
|
|
726
|
+
```html
|
|
727
|
+
<pds-splitpanel orientation="horizontal">
|
|
728
|
+
<div slot="start">Left pane</div>
|
|
729
|
+
<div slot="end">Right pane</div>
|
|
730
|
+
</pds-splitpanel>
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
**`<pds-scrollrow>`** - Horizontal scrolling container
|
|
734
|
+
```html
|
|
735
|
+
<pds-scrollrow>
|
|
736
|
+
<div class="card">Card 1</div>
|
|
737
|
+
<div class="card">Card 2</div>
|
|
738
|
+
<div class="card">Card 3</div>
|
|
739
|
+
</pds-scrollrow>
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
Shows scroll buttons when content overflows.
|
|
743
|
+
|
|
744
|
+
#### Auto-Define System
|
|
745
|
+
|
|
746
|
+
Components are registered automatically when their tags appear in the DOM:
|
|
747
|
+
|
|
748
|
+
```javascript
|
|
749
|
+
await PDS.start({
|
|
750
|
+
autoDefine: {
|
|
751
|
+
baseURL: '/auto-define/',
|
|
752
|
+
|
|
753
|
+
// Eagerly load these components
|
|
754
|
+
predefine: ['pds-icon', 'pds-drawer'],
|
|
755
|
+
|
|
756
|
+
// Custom file mapping
|
|
757
|
+
mapper: (tag) => {
|
|
758
|
+
if (tag.startsWith('my-')) {
|
|
759
|
+
return `/components/${tag}.js`;
|
|
760
|
+
}
|
|
761
|
+
// Return nothing to use PDS default mapping
|
|
762
|
+
},
|
|
763
|
+
|
|
764
|
+
// Advanced options
|
|
765
|
+
scanExisting: true, // Scan for tags on init
|
|
766
|
+
observeShadows: true, // Watch Shadow DOM
|
|
767
|
+
patchAttachShadow: true, // Monitor dynamic shadows
|
|
768
|
+
debounceMs: 16 // Debounce observation
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
The system:
|
|
774
|
+
1. Observes DOM for new custom elements
|
|
775
|
+
2. Checks if tag is defined
|
|
776
|
+
3. Loads corresponding module
|
|
777
|
+
4. Registers custom element
|
|
778
|
+
5. Upgrades existing instances
|
|
779
|
+
|
|
780
|
+
> ⚠️ **Important: Programmatic Access to Auto-Defined Components**
|
|
781
|
+
>
|
|
782
|
+
> Components loaded via `autoDefine` are registered asynchronously. If you need to access component methods or properties programmatically (e.g., `toaster.toast()`), ensure the component is defined first:
|
|
783
|
+
>
|
|
784
|
+
> ```javascript
|
|
785
|
+
> // Wait for component to be defined
|
|
786
|
+
> await customElements.whenDefined('pds-toaster');
|
|
787
|
+
> const toaster = document.querySelector('pds-toaster');
|
|
788
|
+
> toaster.toast('Hello!');
|
|
789
|
+
> ```
|
|
790
|
+
>
|
|
791
|
+
> **Alternative:** Use `predefine` to eagerly load components at `PDS.start()` time:
|
|
792
|
+
>
|
|
793
|
+
> ```javascript
|
|
794
|
+
> await PDS.start({
|
|
795
|
+
> autoDefine: {
|
|
796
|
+
> predefine: ['pds-toaster', 'pds-icon'] // Loaded immediately
|
|
797
|
+
> }
|
|
798
|
+
> });
|
|
799
|
+
> // Components are now available synchronously
|
|
800
|
+
> ```
|
|
801
|
+
|
|
802
|
+
---
|
|
803
|
+
|
|
804
|
+
## Styling Layers
|
|
805
|
+
|
|
806
|
+
PDS generates CSS in structured layers for predictable specificity and modularity.
|
|
807
|
+
|
|
808
|
+
### Layer Structure
|
|
809
|
+
|
|
810
|
+
```
|
|
811
|
+
┌──────────────────────────────────────────────────────────┐
|
|
812
|
+
│ tokens CSS Custom Properties │
|
|
813
|
+
│ --color-*, --spacing-*, --font-* │
|
|
814
|
+
├──────────────────────────────────────────────────────────┤
|
|
815
|
+
│ primitives Base elements │
|
|
816
|
+
│ button, input, .card, .badge │
|
|
817
|
+
├──────────────────────────────────────────────────────────┤
|
|
818
|
+
│ components Rich UI │
|
|
819
|
+
│ .drawer, .tabstrip, .upload │
|
|
820
|
+
├──────────────────────────────────────────────────────────┤
|
|
821
|
+
│ utilities Composable helpers │
|
|
822
|
+
│ .flex, .gap-4, .border-gradient │
|
|
823
|
+
└──────────────────────────────────────────────────────────┘
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
### Layer Details
|
|
827
|
+
|
|
828
|
+
**Tokens** - Design foundation
|
|
829
|
+
- Colors (scales + semantics)
|
|
830
|
+
- Spacing (0-12 progression)
|
|
831
|
+
- Typography (families, sizes, weights)
|
|
832
|
+
- Borders (widths, radius)
|
|
833
|
+
- Shadows (depths)
|
|
834
|
+
- Transitions (speeds)
|
|
835
|
+
- Z-index (layers)
|
|
836
|
+
- Layout (breakpoints, max-width)
|
|
837
|
+
|
|
838
|
+
**Primitives** - Native elements enhanced
|
|
839
|
+
- Buttons (`.btn-primary`, `.btn-secondary`, `.btn-outline`)
|
|
840
|
+
- Forms (`input`, `select`, `textarea`, `fieldset`)
|
|
841
|
+
- Surfaces (`.card`, `.surface`)
|
|
842
|
+
- Badges (`.badge`, `.badge-success`)
|
|
843
|
+
- Alerts (`.alert`, `.alert-warning`)
|
|
844
|
+
- Typography (headings, paragraphs, lists)
|
|
845
|
+
- Tables (responsive, striped)
|
|
846
|
+
|
|
847
|
+
**Components** - Web Component styles
|
|
848
|
+
- Styles for `<pds-*>` elements
|
|
849
|
+
- Internal component structure
|
|
850
|
+
- State management (`:state()` selectors)
|
|
851
|
+
|
|
852
|
+
**Utilities** - Layout and effects
|
|
853
|
+
- Flex (`.flex`, `.flex-col`, `.items-center`)
|
|
854
|
+
- Grid (`.grid`, `.grid-cols-3`)
|
|
855
|
+
- Spacing (`.gap-4`, `.p-4`, `.m-2`)
|
|
856
|
+
- Borders (`.border`, `.border-gradient`, `.border-glow`)
|
|
857
|
+
- Effects (`.shadow-lg`, `.rounded-lg`)
|
|
858
|
+
|
|
859
|
+
### Accessing Layers
|
|
860
|
+
|
|
861
|
+
**In live mode:**
|
|
862
|
+
```javascript
|
|
863
|
+
const compiled = PDS.compiled;
|
|
864
|
+
|
|
865
|
+
// Get layer CSS
|
|
866
|
+
const tokensCSS = compiled.layers.tokens.css;
|
|
867
|
+
const primitivesCSS = compiled.layers.primitives.css;
|
|
868
|
+
|
|
869
|
+
// Get as stylesheet
|
|
870
|
+
const sheet = await PDS.registry.getStylesheet('primitives');
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
**In static mode:**
|
|
874
|
+
```javascript
|
|
875
|
+
// Import constructable stylesheets
|
|
876
|
+
import tokensSheet from '/pds/styles/pds-tokens.css.js';
|
|
877
|
+
import primitivesSheet from '/pds/styles/pds-primitives.css.js';
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
---
|
|
881
|
+
|
|
882
|
+
## Shadow DOM Adoption
|
|
883
|
+
|
|
884
|
+
PDS provides helpers for adopting styles into Shadow DOM.
|
|
885
|
+
|
|
886
|
+
### Basic Adoption
|
|
887
|
+
|
|
888
|
+
```javascript
|
|
889
|
+
class MyComponent extends HTMLElement {
|
|
890
|
+
constructor() {
|
|
891
|
+
super();
|
|
892
|
+
this.attachShadow({ mode: 'open' });
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
async connectedCallback() {
|
|
896
|
+
// Adopt just primitives (most common)
|
|
897
|
+
await PDS.adoptPrimitives(this.shadowRoot);
|
|
898
|
+
|
|
899
|
+
this.shadowRoot.innerHTML = `
|
|
900
|
+
<button class="btn-primary">Click me</button>
|
|
901
|
+
`;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
### Multiple Layers
|
|
907
|
+
|
|
908
|
+
```javascript
|
|
909
|
+
// Adopt specific layers
|
|
910
|
+
await PDS.adoptLayers(this.shadowRoot, ['primitives', 'components']);
|
|
911
|
+
|
|
912
|
+
// Adopt with custom styles
|
|
913
|
+
const myStyles = PDS.createStylesheet(`
|
|
914
|
+
:host {
|
|
915
|
+
display: block;
|
|
916
|
+
padding: var(--spacing-4);
|
|
917
|
+
}
|
|
918
|
+
`);
|
|
919
|
+
|
|
920
|
+
await PDS.adoptLayers(this.shadowRoot, ['primitives'], [myStyles]);
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
### Lit Component Example
|
|
924
|
+
|
|
925
|
+
```javascript
|
|
926
|
+
import { html, css, LitElement } from '#pds/lit';
|
|
927
|
+
|
|
928
|
+
class MyCard extends LitElement {
|
|
929
|
+
static styles = css`
|
|
930
|
+
:host {
|
|
931
|
+
display: block;
|
|
932
|
+
}
|
|
933
|
+
`;
|
|
934
|
+
|
|
935
|
+
async connectedCallback() {
|
|
936
|
+
super.connectedCallback();
|
|
937
|
+
await PDS.adoptPrimitives(this.shadowRoot);
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
render() {
|
|
941
|
+
return html`
|
|
942
|
+
<article class="card">
|
|
943
|
+
<h3>Card Title</h3>
|
|
944
|
+
<p>Card content</p>
|
|
945
|
+
<button class="btn-primary">Action</button>
|
|
946
|
+
</article>
|
|
947
|
+
`;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
---
|
|
953
|
+
|
|
954
|
+
## Icon System
|
|
955
|
+
|
|
956
|
+
PDS uses SVG sprites for efficient icon rendering.
|
|
957
|
+
|
|
958
|
+
### Icon Component
|
|
959
|
+
|
|
960
|
+
```html
|
|
961
|
+
<!-- Basic usage -->
|
|
962
|
+
<pds-icon icon="heart"></pds-icon>
|
|
963
|
+
|
|
964
|
+
<!-- Sized icons -->
|
|
965
|
+
<pds-icon icon="star" size="sm"></pds-icon>
|
|
966
|
+
<pds-icon icon="star" size="lg"></pds-icon>
|
|
967
|
+
<pds-icon icon="star" size="32"></pds-icon>
|
|
968
|
+
|
|
969
|
+
<!-- Colored icons -->
|
|
970
|
+
<pds-icon icon="warning" color="red"></pds-icon>
|
|
971
|
+
<pds-icon icon="info" color="var(--color-primary-500)"></pds-icon>
|
|
972
|
+
|
|
973
|
+
<!-- Accessible icons -->
|
|
974
|
+
<pds-icon icon="list" label="Open navigation menu"></pds-icon>
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
### Configuration
|
|
978
|
+
|
|
979
|
+
```javascript
|
|
980
|
+
await PDS.start({
|
|
981
|
+
design: {
|
|
982
|
+
icons: {
|
|
983
|
+
set: 'phosphor', // Icon family
|
|
984
|
+
weight: 'regular', // Icon weight
|
|
985
|
+
defaultSize: 24, // Default size in pixels
|
|
986
|
+
sizes: { // Named sizes
|
|
987
|
+
xs: 16,
|
|
988
|
+
sm: 20,
|
|
989
|
+
md: 24,
|
|
990
|
+
lg: 32,
|
|
991
|
+
xl: 48,
|
|
992
|
+
'2xl': 64
|
|
993
|
+
},
|
|
994
|
+
spritePath: '/assets/pds/icons/pds-icons.svg'
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
### Custom Icons
|
|
1001
|
+
|
|
1002
|
+
Add custom icons to the sprite:
|
|
1003
|
+
|
|
1004
|
+
**1. Configure custom icons:**
|
|
1005
|
+
```javascript
|
|
1006
|
+
// pds.config.js
|
|
1007
|
+
export default {
|
|
1008
|
+
design: {
|
|
1009
|
+
icons: {
|
|
1010
|
+
set: 'phosphor',
|
|
1011
|
+
include: [
|
|
1012
|
+
'house', 'gear', 'heart', 'star',
|
|
1013
|
+
'user', 'bell', 'search', 'menu'
|
|
1014
|
+
]
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
**2. Rebuild sprite:**
|
|
1021
|
+
```bash
|
|
1022
|
+
npm run pds:build-icons
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
**3. Use in your app:**
|
|
1026
|
+
```html
|
|
1027
|
+
<pds-icon icon="house"></pds-icon>
|
|
1028
|
+
```
|
|
1029
|
+
|
|
1030
|
+
### Icon Tokens
|
|
1031
|
+
|
|
1032
|
+
Icons are available as CSS custom properties:
|
|
1033
|
+
|
|
1034
|
+
```css
|
|
1035
|
+
--icon-set: phosphor;
|
|
1036
|
+
--icon-weight: regular;
|
|
1037
|
+
--icon-size-xs: 16px;
|
|
1038
|
+
--icon-size-sm: 20px;
|
|
1039
|
+
--icon-size-md: 24px;
|
|
1040
|
+
--icon-size-lg: 32px;
|
|
1041
|
+
```
|
|
1042
|
+
|
|
1043
|
+
---
|
|
1044
|
+
|
|
1045
|
+
## Smart Query System
|
|
1046
|
+
|
|
1047
|
+
Ask questions about your design system using natural language.
|
|
1048
|
+
|
|
1049
|
+
### Usage
|
|
1050
|
+
|
|
1051
|
+
```javascript
|
|
1052
|
+
// Programmatic API
|
|
1053
|
+
const results = await PDS.query("what is the focus border color on inputs?");
|
|
1054
|
+
|
|
1055
|
+
results.forEach(result => {
|
|
1056
|
+
console.log(result.text); // "Focus border color: var(--color-primary-500)"
|
|
1057
|
+
console.log(result.category); // "Color Token"
|
|
1058
|
+
console.log(result.cssVar); // "var(--color-primary-500)"
|
|
1059
|
+
console.log(result.code); // Example code
|
|
1060
|
+
});
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
### Example Queries
|
|
1064
|
+
|
|
1065
|
+
**Color Questions:**
|
|
1066
|
+
```javascript
|
|
1067
|
+
await PDS.query("what is the focus border color on inputs?")
|
|
1068
|
+
await PDS.query("what foreground color should I use on this surface?")
|
|
1069
|
+
await PDS.query("button hover color")
|
|
1070
|
+
await PDS.query("primary color scale")
|
|
1071
|
+
```
|
|
1072
|
+
|
|
1073
|
+
**Utility Questions:**
|
|
1074
|
+
```javascript
|
|
1075
|
+
await PDS.query("what are the utility classes for borders?")
|
|
1076
|
+
await PDS.query("border gradient effect")
|
|
1077
|
+
await PDS.query("flex layout utilities")
|
|
1078
|
+
await PDS.query("gap between elements")
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
**Component Questions:**
|
|
1082
|
+
```javascript
|
|
1083
|
+
await PDS.query("how do I create an icon-only button?")
|
|
1084
|
+
await PDS.query("drawer component")
|
|
1085
|
+
await PDS.query("tab strip usage")
|
|
1086
|
+
```
|
|
1087
|
+
|
|
1088
|
+
**Layout Questions:**
|
|
1089
|
+
```javascript
|
|
1090
|
+
await PDS.query("how can I group stuff in containers?")
|
|
1091
|
+
await PDS.query("grid container")
|
|
1092
|
+
await PDS.query("card component")
|
|
1093
|
+
```
|
|
1094
|
+
|
|
1095
|
+
### AutoComplete Integration
|
|
1096
|
+
|
|
1097
|
+
The query system integrates with `#pds-search` in the configurator. Type queries directly in the search box for instant answers.
|
|
1098
|
+
|
|
1099
|
+
### How It Works
|
|
1100
|
+
|
|
1101
|
+
1. **Intent Detection** - Recognizes what you're asking about (color, spacing, component, utility)
|
|
1102
|
+
2. **Entity Recognition** - Identifies design elements (button, input, surface)
|
|
1103
|
+
3. **Context Analysis** - Detects states (hover, focus, active)
|
|
1104
|
+
4. **Data Querying** - Searches `PDS.compiled`, `PDS.ontology`, `PDS.currentConfig`
|
|
1105
|
+
5. **Scoring & Ranking** - Returns top 10 most relevant results
|
|
1106
|
+
|
|
1107
|
+
See [PDS-QUERY-SYSTEM.md](./PDS-QUERY-SYSTEM.md) for detailed documentation.
|
|
1108
|
+
|
|
1109
|
+
---
|
|
1110
|
+
|
|
1111
|
+
## Design Validation
|
|
1112
|
+
|
|
1113
|
+
PDS automatically validates designs for accessibility issues.
|
|
1114
|
+
|
|
1115
|
+
### Automatic Validation
|
|
1116
|
+
|
|
1117
|
+
In live mode with presets enabled:
|
|
1118
|
+
|
|
1119
|
+
```bash
|
|
1120
|
+
npm run build
|
|
1121
|
+
```
|
|
1122
|
+
|
|
1123
|
+
Validates all presets during build and reports issues:
|
|
1124
|
+
|
|
1125
|
+
```
|
|
1126
|
+
❌ Preset validation failed:
|
|
1127
|
+
|
|
1128
|
+
— Travel Market
|
|
1129
|
+
• Primary text on surface is too low (3.95 < 4.5)
|
|
1130
|
+
[light/outline] (/colors/primary)
|
|
1131
|
+
|
|
1132
|
+
— Mobility App
|
|
1133
|
+
• Primary button contrast too low in dark theme (2.85 < 4.5)
|
|
1134
|
+
[dark/btn-primary] (/colors/darkMode/primary)
|
|
1135
|
+
```
|
|
1136
|
+
|
|
1137
|
+
### Manual Validation
|
|
1138
|
+
|
|
1139
|
+
```javascript
|
|
1140
|
+
import { validateDesign } from '@pure-ds/core/pds-core/pds-generator.js';
|
|
1141
|
+
|
|
1142
|
+
const result = validateDesign({
|
|
1143
|
+
colors: {
|
|
1144
|
+
primary: '#007acc',
|
|
1145
|
+
background: '#ffffff'
|
|
1146
|
+
}
|
|
1147
|
+
}, {
|
|
1148
|
+
minContrast: 4.5 // WCAG AA standard
|
|
1149
|
+
});
|
|
1150
|
+
|
|
1151
|
+
if (!result.ok) {
|
|
1152
|
+
console.table(result.issues);
|
|
1153
|
+
// [
|
|
1154
|
+
// {
|
|
1155
|
+
// path: '/colors/primary',
|
|
1156
|
+
// message: 'Primary button contrast too low...',
|
|
1157
|
+
// ratio: 3.2,
|
|
1158
|
+
// min: 4.5,
|
|
1159
|
+
// context: 'light/btn-primary'
|
|
1160
|
+
// }
|
|
1161
|
+
// ]
|
|
1162
|
+
}
|
|
1163
|
+
```
|
|
1164
|
+
|
|
1165
|
+
### Batch Validation
|
|
1166
|
+
|
|
1167
|
+
```javascript
|
|
1168
|
+
import { validateDesigns } from '@pure-ds/core/pds-core/pds-generator.js';
|
|
1169
|
+
|
|
1170
|
+
const results = validateDesigns([
|
|
1171
|
+
{ name: 'Light', config: {...} },
|
|
1172
|
+
{ name: 'Dark', config: {...} }
|
|
1173
|
+
], {
|
|
1174
|
+
minContrast: 4.5
|
|
1175
|
+
});
|
|
1176
|
+
|
|
1177
|
+
results.forEach(({ name, ok, issues }) => {
|
|
1178
|
+
if (!ok) {
|
|
1179
|
+
console.log(`${name} has ${issues.length} issues`);
|
|
1180
|
+
}
|
|
1181
|
+
});
|
|
1182
|
+
```
|
|
1183
|
+
|
|
1184
|
+
### Validation Checks
|
|
1185
|
+
|
|
1186
|
+
- **Primary Button (Light)** - Button fill vs white text
|
|
1187
|
+
- **Primary Button (Dark)** - Button fill vs white text in dark mode
|
|
1188
|
+
- **Surface Text (Light)** - Text color vs surface background
|
|
1189
|
+
- **Primary Links/Outline (Light)** - Primary text vs surface
|
|
1190
|
+
- **Surface Text (Dark)** - Text color vs dark surface
|
|
1191
|
+
|
|
1192
|
+
All checks verify WCAG AA minimum contrast ratio (4.5:1 default).
|
|
1193
|
+
|
|
1194
|
+
---
|
|
1195
|
+
|
|
1196
|
+
## Advanced Features
|
|
1197
|
+
|
|
1198
|
+
### Automatic Font Loading
|
|
1199
|
+
|
|
1200
|
+
In live mode, PDS automatically loads fonts from Google Fonts when they're not available locally.
|
|
1201
|
+
|
|
1202
|
+
```javascript
|
|
1203
|
+
await PDS.start({
|
|
1204
|
+
mode: 'live',
|
|
1205
|
+
design: {
|
|
1206
|
+
typography: {
|
|
1207
|
+
fontFamilyHeadings: 'Inter, sans-serif',
|
|
1208
|
+
fontFamilyBody: 'Inter, sans-serif',
|
|
1209
|
+
fontFamilyMono: 'Fira Code, monospace'
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
});
|
|
1213
|
+
|
|
1214
|
+
// Fonts are automatically loaded from Google Fonts if needed
|
|
1215
|
+
```
|
|
1216
|
+
|
|
1217
|
+
**Features:**
|
|
1218
|
+
- Smart detection (skips system fonts)
|
|
1219
|
+
- Parallel loading for performance
|
|
1220
|
+
- Font weights: 400, 500, 600, 700
|
|
1221
|
+
- `font-display: swap` for better UX
|
|
1222
|
+
- 5-second timeout prevents hanging
|
|
1223
|
+
|
|
1224
|
+
**Manual loading:**
|
|
1225
|
+
```javascript
|
|
1226
|
+
import { loadGoogleFont } from '@pure-ds/core/common/font-loader';
|
|
1227
|
+
|
|
1228
|
+
await loadGoogleFont('Roboto', {
|
|
1229
|
+
weights: [400, 500, 700],
|
|
1230
|
+
italic: true
|
|
1231
|
+
});
|
|
1232
|
+
```
|
|
1233
|
+
|
|
1234
|
+
### Event Bus
|
|
1235
|
+
|
|
1236
|
+
PDS is an EventTarget - listen for system events:
|
|
1237
|
+
|
|
1238
|
+
```javascript
|
|
1239
|
+
// System ready
|
|
1240
|
+
PDS.addEventListener('pds:ready', (e) => {
|
|
1241
|
+
console.log('PDS ready:', e.detail.mode);
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
// Theme changed
|
|
1245
|
+
PDS.addEventListener('pds:theme:changed', (e) => {
|
|
1246
|
+
console.log('Theme:', e.detail.theme);
|
|
1247
|
+
});
|
|
1248
|
+
|
|
1249
|
+
// Design updated (configurator)
|
|
1250
|
+
PDS.addEventListener('pds:design:updated', (e) => {
|
|
1251
|
+
console.log('New config:', e.detail.config);
|
|
1252
|
+
});
|
|
1253
|
+
|
|
1254
|
+
// Error handling
|
|
1255
|
+
PDS.addEventListener('pds:error', (e) => {
|
|
1256
|
+
console.error('PDS error:', e.detail.error);
|
|
1257
|
+
});
|
|
1258
|
+
```
|
|
1259
|
+
|
|
1260
|
+
**Available events:**
|
|
1261
|
+
- `pds:ready` - System initialized
|
|
1262
|
+
- `pds:error` - Error occurred
|
|
1263
|
+
- `pds:theme:changed` - Theme switched
|
|
1264
|
+
- `pds:design:updated` - Config changed
|
|
1265
|
+
- `pds:design:field:changed` - Single field updated
|
|
1266
|
+
- `pds:inspector:mode:changed` - Inspector toggled
|
|
1267
|
+
- `pds:inspector:deactivate` - Inspector close requested
|
|
1268
|
+
- `pds:docs:view` - Documentation view requested
|
|
1269
|
+
- `pds:toast` - Toast notification triggered
|
|
1270
|
+
|
|
1271
|
+
### Theme Management
|
|
1272
|
+
|
|
1273
|
+
```javascript
|
|
1274
|
+
// Get current theme
|
|
1275
|
+
const theme = PDS.theme; // 'light' | 'dark' | 'system' | null
|
|
1276
|
+
|
|
1277
|
+
// Set theme
|
|
1278
|
+
PDS.theme = 'dark';
|
|
1279
|
+
PDS.theme = 'system'; // Follows OS preference
|
|
1280
|
+
PDS.theme = null; // Remove preference
|
|
1281
|
+
|
|
1282
|
+
// Or use method
|
|
1283
|
+
await PDS.setTheme('dark');
|
|
1284
|
+
```
|
|
1285
|
+
|
|
1286
|
+
Theme is stored in localStorage and updates `html[data-theme]` automatically.
|
|
1287
|
+
|
|
1288
|
+
### Compiled Object Model
|
|
1289
|
+
|
|
1290
|
+
In live mode, access the complete generated system:
|
|
1291
|
+
|
|
1292
|
+
```javascript
|
|
1293
|
+
const compiled = PDS.compiled;
|
|
1294
|
+
|
|
1295
|
+
// Tokens
|
|
1296
|
+
compiled.tokens.colors.primary[500];
|
|
1297
|
+
compiled.tokens.spacing[4];
|
|
1298
|
+
compiled.tokens.typography.fontFamily.body;
|
|
1299
|
+
|
|
1300
|
+
// Layers
|
|
1301
|
+
compiled.layers.tokens.css;
|
|
1302
|
+
compiled.layers.primitives.css;
|
|
1303
|
+
|
|
1304
|
+
// Metadata
|
|
1305
|
+
compiled.meta.generatedAt;
|
|
1306
|
+
compiled.meta.totalSize;
|
|
1307
|
+
compiled.meta.tokenGroups;
|
|
1308
|
+
|
|
1309
|
+
// Helpers
|
|
1310
|
+
compiled.helpers.getColorScales();
|
|
1311
|
+
compiled.helpers.getColorScale('primary');
|
|
1312
|
+
compiled.helpers.getSpacingValues();
|
|
1313
|
+
```
|
|
1314
|
+
|
|
1315
|
+
### Presets
|
|
1316
|
+
|
|
1317
|
+
Choose from built-in presets:
|
|
1318
|
+
|
|
1319
|
+
```javascript
|
|
1320
|
+
// View available presets
|
|
1321
|
+
Object.keys(PDS.presets);
|
|
1322
|
+
// ['default', 'ocean-breeze', 'midnight-steel', ...]
|
|
1323
|
+
|
|
1324
|
+
// Use a preset
|
|
1325
|
+
await PDS.start({
|
|
1326
|
+
preset: 'ocean-breeze',
|
|
1327
|
+
design: {
|
|
1328
|
+
// Override specific values
|
|
1329
|
+
colors: { primary: '#custom' }
|
|
1330
|
+
}
|
|
1331
|
+
});
|
|
1332
|
+
|
|
1333
|
+
// Access preset config
|
|
1334
|
+
const preset = PDS.presets['ocean-breeze'];
|
|
1335
|
+
console.log(preset.colors.primary);
|
|
1336
|
+
```
|
|
1337
|
+
|
|
1338
|
+
**Available presets:**
|
|
1339
|
+
- `default` - Clean, modern baseline
|
|
1340
|
+
- `ocean-breeze` - Cool blues and teals
|
|
1341
|
+
- `midnight-steel` - Dark, professional
|
|
1342
|
+
- `sunset-vibes` - Warm oranges and purples
|
|
1343
|
+
- `forest-calm` - Natural greens
|
|
1344
|
+
- `lavender-dream` - Soft purples
|
|
1345
|
+
- `coral-energy` - Vibrant pinks and oranges
|
|
1346
|
+
- `arctic-frost` - Cool grays and blues
|
|
1347
|
+
- `golden-hour` - Warm yellows and golds
|
|
1348
|
+
- `neon-city` - Bright, high-contrast
|
|
1349
|
+
- `travel-market` - Earthy, adventurous
|
|
1350
|
+
- `mobility-app` - Tech-forward transportation
|
|
1351
|
+
|
|
1352
|
+
---
|
|
1353
|
+
|
|
1354
|
+
## API Reference
|
|
1355
|
+
|
|
1356
|
+
### PDS.start(config)
|
|
1357
|
+
|
|
1358
|
+
Main initialization method.
|
|
1359
|
+
|
|
1360
|
+
```typescript
|
|
1361
|
+
await PDS.start({
|
|
1362
|
+
// Mode
|
|
1363
|
+
mode?: 'live' | 'static' = 'live',
|
|
1364
|
+
|
|
1365
|
+
// Design configuration
|
|
1366
|
+
preset?: string,
|
|
1367
|
+
design?: {
|
|
1368
|
+
colors?: {...},
|
|
1369
|
+
typography?: {...},
|
|
1370
|
+
spatialRhythm?: {...},
|
|
1371
|
+
shape?: {...},
|
|
1372
|
+
behavior?: {...},
|
|
1373
|
+
layout?: {...},
|
|
1374
|
+
layers?: {...},
|
|
1375
|
+
icons?: {...}
|
|
1376
|
+
},
|
|
1377
|
+
|
|
1378
|
+
// Static mode paths
|
|
1379
|
+
staticPaths?: {
|
|
1380
|
+
tokens?: string,
|
|
1381
|
+
primitives?: string,
|
|
1382
|
+
components?: string,
|
|
1383
|
+
utilities?: string,
|
|
1384
|
+
styles?: string
|
|
1385
|
+
},
|
|
1386
|
+
|
|
1387
|
+
// Component loading
|
|
1388
|
+
autoDefine?: {
|
|
1389
|
+
baseURL?: string,
|
|
1390
|
+
predefine?: string[],
|
|
1391
|
+
mapper?: (tag: string) => string | void,
|
|
1392
|
+
scanExisting?: boolean,
|
|
1393
|
+
observeShadows?: boolean,
|
|
1394
|
+
patchAttachShadow?: boolean,
|
|
1395
|
+
debounceMs?: number
|
|
1396
|
+
},
|
|
1397
|
+
|
|
1398
|
+
// Progressive enhancements
|
|
1399
|
+
enhancers?: Array<{
|
|
1400
|
+
selector: string,
|
|
1401
|
+
description?: string,
|
|
1402
|
+
run: (element: Element) => void
|
|
1403
|
+
}>,
|
|
1404
|
+
|
|
1405
|
+
// Runtime options
|
|
1406
|
+
applyGlobalStyles?: boolean = false,
|
|
1407
|
+
manageTheme?: boolean = false,
|
|
1408
|
+
themeStorageKey?: string = 'pure-ds-theme',
|
|
1409
|
+
preloadStyles?: boolean = false,
|
|
1410
|
+
criticalLayers?: string[] = ['tokens', 'primitives']
|
|
1411
|
+
});
|
|
1412
|
+
```
|
|
1413
|
+
|
|
1414
|
+
### PDS.query(question)
|
|
1415
|
+
|
|
1416
|
+
Smart query interface.
|
|
1417
|
+
|
|
1418
|
+
```typescript
|
|
1419
|
+
const results = await PDS.query(question: string);
|
|
1420
|
+
// Returns array of results with text, value, icon, category, etc.
|
|
1421
|
+
```
|
|
1422
|
+
|
|
1423
|
+
### validateDesign(config, options)
|
|
1424
|
+
|
|
1425
|
+
Validate design for accessibility.
|
|
1426
|
+
|
|
1427
|
+
```typescript
|
|
1428
|
+
import { validateDesign } from '@pure-ds/core/pds-core/pds-generator.js';
|
|
1429
|
+
|
|
1430
|
+
const result = validateDesign(config, { minContrast: 4.5 });
|
|
1431
|
+
// Returns: { ok: boolean, issues: Array }
|
|
1432
|
+
```
|
|
1433
|
+
|
|
1434
|
+
### PDS.adoptLayers(shadowRoot, layers, additionalSheets)
|
|
1435
|
+
|
|
1436
|
+
Adopt stylesheets into Shadow DOM.
|
|
1437
|
+
|
|
1438
|
+
```typescript
|
|
1439
|
+
await PDS.adoptLayers(shadowRoot, ['primitives'], [customSheet]);
|
|
1440
|
+
```
|
|
1441
|
+
|
|
1442
|
+
### PDS.adoptPrimitives(shadowRoot, additionalSheets)
|
|
1443
|
+
|
|
1444
|
+
Adopt primitives layer (convenience method).
|
|
1445
|
+
|
|
1446
|
+
### PDS.createStylesheet(css)
|
|
1447
|
+
|
|
1448
|
+
Create constructable stylesheet from CSS string.
|
|
1449
|
+
|
|
1450
|
+
### PDS.setTheme(theme)
|
|
1451
|
+
|
|
1452
|
+
Change theme programmatically.
|
|
1453
|
+
|
|
1454
|
+
### PDS Properties
|
|
1455
|
+
|
|
1456
|
+
```typescript
|
|
1457
|
+
PDS.registry // Runtime registry
|
|
1458
|
+
PDS.getGenerator() // Live-only Generator accessor
|
|
1459
|
+
PDS.ontology // Design system metadata (live-only)
|
|
1460
|
+
PDS.presets // Built-in presets (live-only)
|
|
1461
|
+
PDS.enums // Enumeration values (live-only)
|
|
1462
|
+
PDS.currentConfig // Current configuration (read-only)
|
|
1463
|
+
PDS.compiled // Compiled state (live mode only)
|
|
1464
|
+
PDS.theme // Current theme (getter/setter)
|
|
1465
|
+
PDS.defaultEnhancers // Built-in enhancements
|
|
1466
|
+
```
|
|
1467
|
+
|
|
1468
|
+
---
|
|
1469
|
+
|
|
1470
|
+
## Extending PDS
|
|
1471
|
+
|
|
1472
|
+
### Custom Enhancers
|
|
1473
|
+
|
|
1474
|
+
```javascript
|
|
1475
|
+
await PDS.start({
|
|
1476
|
+
enhancers: [
|
|
1477
|
+
{
|
|
1478
|
+
selector: '[data-animate-in]',
|
|
1479
|
+
description: 'Animate elements as they enter viewport',
|
|
1480
|
+
run: (element) => {
|
|
1481
|
+
const observer = new IntersectionObserver((entries) => {
|
|
1482
|
+
entries.forEach(entry => {
|
|
1483
|
+
if (entry.isIntersecting) {
|
|
1484
|
+
element.classList.add('animated');
|
|
1485
|
+
observer.unobserve(element);
|
|
1486
|
+
}
|
|
1487
|
+
});
|
|
1488
|
+
});
|
|
1489
|
+
observer.observe(element);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
]
|
|
1493
|
+
});
|
|
1494
|
+
```
|
|
1495
|
+
|
|
1496
|
+
### Custom Components
|
|
1497
|
+
|
|
1498
|
+
```javascript
|
|
1499
|
+
await PDS.start({
|
|
1500
|
+
autoDefine: {
|
|
1501
|
+
mapper: (tag) => {
|
|
1502
|
+
if (tag.startsWith('my-')) {
|
|
1503
|
+
return `/components/${tag}.js`;
|
|
1504
|
+
}
|
|
1505
|
+
// Let PDS handle pds-* components
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
});
|
|
1509
|
+
```
|
|
1510
|
+
|
|
1511
|
+
### Custom Presets
|
|
1512
|
+
|
|
1513
|
+
```javascript
|
|
1514
|
+
export const myPreset = {
|
|
1515
|
+
id: 'my-brand',
|
|
1516
|
+
name: 'My Brand Theme',
|
|
1517
|
+
colors: { primary: '#007acc', secondary: '#5c2d91' },
|
|
1518
|
+
typography: { fontFamilyHeadings: 'Montserrat' }
|
|
1519
|
+
};
|
|
1520
|
+
|
|
1521
|
+
await PDS.start({ design: myPreset });
|
|
1522
|
+
```
|
|
1523
|
+
|
|
1524
|
+
---
|
|
1525
|
+
|
|
1526
|
+
## Using from CDN
|
|
1527
|
+
|
|
1528
|
+
```html
|
|
1529
|
+
<!DOCTYPE html>
|
|
1530
|
+
<html lang="en">
|
|
1531
|
+
<head>
|
|
1532
|
+
<script type="importmap">
|
|
1533
|
+
{
|
|
1534
|
+
"imports": {
|
|
1535
|
+
"#pds/lit": "https://cdn.jsdelivr.net/npm/lit@3/index.js"
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
</script>
|
|
1539
|
+
</head>
|
|
1540
|
+
<body>
|
|
1541
|
+
<button class="btn-primary">Click me</button>
|
|
1542
|
+
|
|
1543
|
+
<script type="module">
|
|
1544
|
+
import { PDS } from 'https://cdn.jsdelivr.net/npm/@pure-ds/core@latest/public/assets/js/pds.js';
|
|
1545
|
+
|
|
1546
|
+
await PDS.start({
|
|
1547
|
+
mode: 'static',
|
|
1548
|
+
staticPaths: {
|
|
1549
|
+
tokens: 'https://cdn.jsdelivr.net/npm/@pure-ds/core@latest/public/assets/pds/styles/pds-tokens.css.js',
|
|
1550
|
+
primitives: 'https://cdn.jsdelivr.net/npm/@pure-ds/core@latest/public/assets/pds/styles/pds-primitives.css.js',
|
|
1551
|
+
utilities: 'https://cdn.jsdelivr.net/npm/@pure-ds/core@latest/public/assets/pds/styles/pds-utilities.css.js'
|
|
1552
|
+
},
|
|
1553
|
+
autoDefine: {
|
|
1554
|
+
baseURL: 'https://cdn.jsdelivr.net/npm/@pure-ds/core@latest/public/assets/pds/components/'
|
|
1555
|
+
},
|
|
1556
|
+
applyGlobalStyles: true
|
|
1557
|
+
});
|
|
1558
|
+
</script>
|
|
1559
|
+
</body>
|
|
1560
|
+
</html>
|
|
1561
|
+
```
|
|
1562
|
+
|
|
1563
|
+
---
|
|
1564
|
+
|
|
1565
|
+
## CLI & Export
|
|
1566
|
+
|
|
1567
|
+
### Available Scripts
|
|
1568
|
+
|
|
1569
|
+
| Script | Description |
|
|
1570
|
+
|--------|-------------|
|
|
1571
|
+
| `npm run pds:export` | Full export: styles, components, icons, and IntelliSense data |
|
|
1572
|
+
| `npm run pds:dx` | Generate all IntelliSense data (HTML + CSS) |
|
|
1573
|
+
| `npm run pds:manifest` | Generate HTML IntelliSense (Custom Elements Manifest) |
|
|
1574
|
+
| `npm run pds:css-data` | Generate CSS IntelliSense (tokens, classes, attributes) |
|
|
1575
|
+
| `npm run pds:build-icons` | Build custom icon sprite |
|
|
1576
|
+
| `npm run sync-assets` | Sync assets between locations |
|
|
1577
|
+
| `npx pds-init-config` | Create default `pds.config.js` with helpful examples |
|
|
1578
|
+
|
|
1579
|
+
### Initialize Configuration
|
|
1580
|
+
|
|
1581
|
+
Create a starter `pds.config.js` file with commented examples:
|
|
1582
|
+
|
|
1583
|
+
```bash
|
|
1584
|
+
# Create config in current directory
|
|
1585
|
+
npx pds-init-config
|
|
1586
|
+
|
|
1587
|
+
# Force overwrite existing config
|
|
1588
|
+
npx pds-init-config --force
|
|
1589
|
+
```
|
|
1590
|
+
|
|
1591
|
+
This generates a `pds.config.js` with:
|
|
1592
|
+
- Basic `mode` and `preset` settings
|
|
1593
|
+
- Commented examples for design token overrides
|
|
1594
|
+
- Template for custom progressive enhancers
|
|
1595
|
+
- Template for lazy-loaded component configuration
|
|
1596
|
+
|
|
1597
|
+
**Note:** During `npm install`, PDS automatically creates this file if it doesn't exist.
|
|
1598
|
+
|
|
1599
|
+
### Export Static Assets
|
|
1600
|
+
|
|
1601
|
+
```bash
|
|
1602
|
+
npm run pds:export
|
|
1603
|
+
```
|
|
1604
|
+
|
|
1605
|
+
**Output:**
|
|
1606
|
+
```
|
|
1607
|
+
pds/
|
|
1608
|
+
├── styles/
|
|
1609
|
+
│ ├── pds-tokens.css
|
|
1610
|
+
│ ├── pds-tokens.css.js
|
|
1611
|
+
│ ├── pds-primitives.css
|
|
1612
|
+
│ ├── pds-primitives.css.js
|
|
1613
|
+
│ ├── pds-components.css
|
|
1614
|
+
│ ├── pds-components.css.js
|
|
1615
|
+
│ ├── pds-utilities.css
|
|
1616
|
+
│ ├── pds-utilities.css.js
|
|
1617
|
+
│ └── pds-styles.css.js
|
|
1618
|
+
├── components/
|
|
1619
|
+
│ └── pds-*.js (all components)
|
|
1620
|
+
├── icons/
|
|
1621
|
+
│ └── pds-icons.svg
|
|
1622
|
+
├── custom-elements.json # HTML IntelliSense
|
|
1623
|
+
├── vscode-custom-data.json # HTML IntelliSense (VS Code)
|
|
1624
|
+
├── pds.css-data.json # CSS IntelliSense (VS Code)
|
|
1625
|
+
└── pds-css-complete.json # CSS IntelliSense (all editors)
|
|
1626
|
+
```
|
|
1627
|
+
|
|
1628
|
+
### Generate IntelliSense Data
|
|
1629
|
+
|
|
1630
|
+
For complete IDE support with autocomplete:
|
|
1631
|
+
|
|
1632
|
+
```bash
|
|
1633
|
+
# Generate both HTML and CSS IntelliSense (recommended)
|
|
1634
|
+
npm run pds:dx
|
|
1635
|
+
|
|
1636
|
+
# Or generate individually
|
|
1637
|
+
npm run pds:manifest # HTML component autocomplete
|
|
1638
|
+
npm run pds:css-data # CSS token & class autocomplete
|
|
1639
|
+
```
|
|
1640
|
+
|
|
1641
|
+
See [INTELLISENSE.md](./INTELLISENSE.md) for setup instructions.
|
|
1642
|
+
|
|
1643
|
+
### Configuration
|
|
1644
|
+
|
|
1645
|
+
```javascript
|
|
1646
|
+
// pds.config.js
|
|
1647
|
+
export default {
|
|
1648
|
+
staticBase: 'pds',
|
|
1649
|
+
static: { root: 'public/assets/pds/' },
|
|
1650
|
+
preset: 'default',
|
|
1651
|
+
design: { colors: { primary: '#007acc' } }
|
|
1652
|
+
};
|
|
1653
|
+
```
|
|
1654
|
+
|
|
1655
|
+
### Build Icons
|
|
1656
|
+
|
|
1657
|
+
```bash
|
|
1658
|
+
npm run pds:build-icons
|
|
1659
|
+
```
|
|
1660
|
+
|
|
1661
|
+
### Sync Assets
|
|
1662
|
+
|
|
1663
|
+
```bash
|
|
1664
|
+
npm run sync-assets
|
|
1665
|
+
```
|
|
1666
|
+
|
|
1667
|
+
---
|
|
1668
|
+
|
|
1669
|
+
## IntelliSense & IDE Support
|
|
1670
|
+
|
|
1671
|
+
PDS provides comprehensive IntelliSense support for both HTML and CSS, dramatically improving developer experience with autocomplete, documentation, and type hints.
|
|
1672
|
+
|
|
1673
|
+
> 📖 **[Full IntelliSense Guide](./INTELLISENSE.md)** - Detailed setup for all editors
|
|
1674
|
+
|
|
1675
|
+
### Quick Setup (VS Code)
|
|
1676
|
+
|
|
1677
|
+
Add to `.vscode/settings.json`:
|
|
1678
|
+
|
|
1679
|
+
```json
|
|
1680
|
+
{
|
|
1681
|
+
"html.customData": [
|
|
1682
|
+
"node_modules/@pure-ds/core/public/assets/pds/vscode-custom-data.json"
|
|
1683
|
+
],
|
|
1684
|
+
"css.customData": [
|
|
1685
|
+
"node_modules/@pure-ds/core/public/assets/pds/pds.css-data.json"
|
|
1686
|
+
]
|
|
1687
|
+
}
|
|
1688
|
+
```
|
|
1689
|
+
|
|
1690
|
+
Reload VS Code: **Ctrl+Shift+P** → **Developer: Reload Window**
|
|
1691
|
+
|
|
1692
|
+
### What You Get
|
|
1693
|
+
|
|
1694
|
+
#### HTML IntelliSense
|
|
1695
|
+
- ✅ Web component autocomplete (`<pds-drawer>`, `<pds-icon>`)
|
|
1696
|
+
- ✅ Attribute suggestions with descriptions
|
|
1697
|
+
- ✅ Enum value autocomplete (`position="left|right|top|bottom"`)
|
|
1698
|
+
- ✅ Icon name suggestions (all available icons)
|
|
1699
|
+
|
|
1700
|
+
#### CSS IntelliSense
|
|
1701
|
+
- ✅ CSS token autocomplete in `.css` files and `<style>` tags
|
|
1702
|
+
- ✅ Token value previews on hover (`--color-primary-500`, `--spacing-4`)
|
|
1703
|
+
- ✅ 165 CSS custom properties with descriptions
|
|
1704
|
+
- ⚠️ **Note**: Inline `style` attributes don't support IntelliSense (VS Code limitation - use CSS files or `<style>` tags)
|
|
1705
|
+
|
|
1706
|
+
> 📖 **[CSS IntelliSense Limitations](./CSS-INTELLISENSE-LIMITATION.md)** - Important info about where IntelliSense works
|
|
1707
|
+
|
|
1708
|
+
### Generation
|
|
1709
|
+
|
|
1710
|
+
IntelliSense data is automatically generated with export:
|
|
1711
|
+
|
|
1712
|
+
```bash
|
|
1713
|
+
# Generate all IntelliSense data (HTML + CSS)
|
|
1714
|
+
npm run pds:dx
|
|
1715
|
+
|
|
1716
|
+
# Or as part of full export
|
|
1717
|
+
npm run pds:export
|
|
1718
|
+
|
|
1719
|
+
# Or generate individually
|
|
1720
|
+
npm run pds:manifest # HTML IntelliSense only
|
|
1721
|
+
npm run pds:css-data # CSS IntelliSense only
|
|
1722
|
+
```
|
|
1723
|
+
|
|
1724
|
+
### Generated Files
|
|
1725
|
+
|
|
1726
|
+
```
|
|
1727
|
+
public/assets/pds/
|
|
1728
|
+
├── custom-elements.json # Standard Custom Elements Manifest
|
|
1729
|
+
├── vscode-custom-data.json # VS Code HTML custom data
|
|
1730
|
+
├── pds.css-data.json # VS Code CSS custom data
|
|
1731
|
+
└── pds-css-complete.json # Standard CSS data (all editors)
|
|
1732
|
+
|
|
1733
|
+
# Root reference files
|
|
1734
|
+
pds.html-data.json # Points to HTML custom data
|
|
1735
|
+
pds.css-data.json # Points to CSS custom data
|
|
1736
|
+
```
|
|
1737
|
+
|
|
1738
|
+
### Usage Examples
|
|
1739
|
+
|
|
1740
|
+
**HTML Autocomplete:**
|
|
1741
|
+
```html
|
|
1742
|
+
<!-- Type <pds- to see all components -->
|
|
1743
|
+
<pds-drawer position="right" open>
|
|
1744
|
+
<div slot="drawer-header">Settings</div>
|
|
1745
|
+
</pds-drawer>
|
|
1746
|
+
|
|
1747
|
+
<!-- Icon autocomplete suggests all available icons -->
|
|
1748
|
+
<pds-icon icon="star"></pds-icon>
|
|
1749
|
+
```
|
|
1750
|
+
|
|
1751
|
+
**CSS Token Autocomplete:**
|
|
1752
|
+
```css
|
|
1753
|
+
.my-component {
|
|
1754
|
+
/* Type --color and see all color tokens */
|
|
1755
|
+
background: var(--color-primary-500);
|
|
1756
|
+
padding: var(--spacing-4);
|
|
1757
|
+
border-radius: var(--radius-md);
|
|
1758
|
+
box-shadow: var(--shadow-lg);
|
|
1759
|
+
}
|
|
1760
|
+
```
|
|
1761
|
+
|
|
1762
|
+
**Utility Class Autocomplete:**
|
|
1763
|
+
```html
|
|
1764
|
+
<div class="flex gap-4 items-center">
|
|
1765
|
+
<div class="card surface-elevated">
|
|
1766
|
+
<!-- Primitives and utilities autocomplete -->
|
|
1767
|
+
</div>
|
|
1768
|
+
</div>
|
|
1769
|
+
```
|
|
1770
|
+
|
|
1771
|
+
### What's Included
|
|
1772
|
+
|
|
1773
|
+
**150+ CSS Custom Properties:**
|
|
1774
|
+
- Colors: `--color-{name}-{50-900}`
|
|
1775
|
+
- Spacing: `--spacing-{xs|sm|md|lg|xl|...}`
|
|
1776
|
+
- Typography: `--font-family-*`, `--font-size-*`, `--font-weight-*`
|
|
1777
|
+
- Borders: `--radius-*`, `--border-width-*`
|
|
1778
|
+
- Shadows: `--shadow-{sm|md|lg|xl|2xl}`
|
|
1779
|
+
- Surfaces: `--surface-bg`, `--surface-text`, `--surface-border`
|
|
1780
|
+
|
|
1781
|
+
**50+ CSS Classes:**
|
|
1782
|
+
- Primitives: `.badge`, `.card`, `.surface`, `.alert`
|
|
1783
|
+
- Layout: `.flex`, `.grid`, `.grid-cols-{1-6}`, `.container`
|
|
1784
|
+
- Utilities: `.gap-{0-12}`, `.items-*`, `.justify-*`
|
|
1785
|
+
- Effects: `.border-gradient`, `.border-glow`
|
|
1786
|
+
|
|
1787
|
+
**5+ Data Enhancements:**
|
|
1788
|
+
- `data-dropdown`, `data-toggle`, `data-tabs`, `data-modal`, `data-tooltip`
|
|
1789
|
+
|
|
1790
|
+
### Cross-Editor Support
|
|
1791
|
+
|
|
1792
|
+
PDS IntelliSense works with:
|
|
1793
|
+
- ✅ **VS Code** - Full support (HTML + CSS)
|
|
1794
|
+
- ✅ **WebStorm/IntelliJ** - Automatic recognition
|
|
1795
|
+
- ✅ **Sublime Text** - Via LSP package
|
|
1796
|
+
- ✅ **Vim/Neovim** - Via coc-css/coc-html
|
|
1797
|
+
- ✅ **Any LSP-compliant editor**
|
|
1798
|
+
|
|
1799
|
+
See [INTELLISENSE.md](./INTELLISENSE.md) for detailed setup instructions for each editor.
|
|
1800
|
+
|
|
1801
|
+
---
|
|
1802
|
+
|
|
1803
|
+
## Custom Elements Manifest
|
|
1804
|
+
|
|
1805
|
+
PDS automatically generates a [Custom Elements Manifest](https://github.com/webcomponents/custom-elements-manifest) for web component documentation. This is part of the IntelliSense system but can be used standalone.
|
|
1806
|
+
|
|
1807
|
+
### What's Documented
|
|
1808
|
+
- Properties, attributes, methods, events
|
|
1809
|
+
- Slots and CSS custom properties
|
|
1810
|
+
- CSS parts for Shadow DOM styling
|
|
1811
|
+
|
|
1812
|
+
See the [IntelliSense Guide](./INTELLISENSE.md) for complete documentation.
|
|
1813
|
+
- 📖 **Hover documentation** - View descriptions without leaving your code
|
|
1814
|
+
|
|
1815
|
+
For detailed information, see [CUSTOM-ELEMENTS-MANIFEST.md](./CUSTOM-ELEMENTS-MANIFEST.md).
|
|
1816
|
+
|
|
1817
|
+
---
|
|
1818
|
+
|
|
1819
|
+
## Framework Integration
|
|
1820
|
+
|
|
1821
|
+
### Vite
|
|
1822
|
+
|
|
1823
|
+
```javascript
|
|
1824
|
+
// vite.config.js
|
|
1825
|
+
export default {
|
|
1826
|
+
resolve: {
|
|
1827
|
+
alias: { '#pds/lit': 'lit' }
|
|
1828
|
+
}
|
|
1829
|
+
};
|
|
1830
|
+
|
|
1831
|
+
// main.js
|
|
1832
|
+
import { PDS } from '@pure-ds/core';
|
|
1833
|
+
await PDS.start({ design: { colors: { primary: '#007acc' } } });
|
|
1834
|
+
```
|
|
1835
|
+
|
|
1836
|
+
### Next.js
|
|
1837
|
+
|
|
1838
|
+
```javascript
|
|
1839
|
+
// app/layout.tsx
|
|
1840
|
+
'use client';
|
|
1841
|
+
|
|
1842
|
+
import { useEffect } from 'react';
|
|
1843
|
+
import { PDS } from '@pure-ds/core';
|
|
1844
|
+
|
|
1845
|
+
export default function RootLayout({ children }) {
|
|
1846
|
+
useEffect(() => {
|
|
1847
|
+
PDS.start({ mode: 'static', applyGlobalStyles: true });
|
|
1848
|
+
}, []);
|
|
1849
|
+
|
|
1850
|
+
return <html><body>{children}</body></html>;
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
// next.config.js
|
|
1854
|
+
module.exports = {
|
|
1855
|
+
webpack: (config) => {
|
|
1856
|
+
config.resolve.alias['#pds/lit'] = 'lit';
|
|
1857
|
+
return config;
|
|
1858
|
+
}
|
|
1859
|
+
};
|
|
1860
|
+
```
|
|
1861
|
+
|
|
1862
|
+
### React
|
|
1863
|
+
|
|
1864
|
+
```javascript
|
|
1865
|
+
import { useEffect } from 'react';
|
|
1866
|
+
import { PDS } from 'pure-ds';
|
|
1867
|
+
|
|
1868
|
+
function App() {
|
|
1869
|
+
useEffect(() => {
|
|
1870
|
+
PDS.start({ design: { colors: { primary: '#007acc' } } });
|
|
1871
|
+
}, []);
|
|
1872
|
+
|
|
1873
|
+
return <button className="btn-primary">Click me</button>;
|
|
1874
|
+
}
|
|
1875
|
+
```
|
|
1876
|
+
|
|
1877
|
+
### Vue
|
|
1878
|
+
|
|
1879
|
+
```javascript
|
|
1880
|
+
// main.js
|
|
1881
|
+
import { PDS } from 'pure-ds';
|
|
1882
|
+
await PDS.start({ design: { colors: { primary: '#007acc' } } });
|
|
1883
|
+
|
|
1884
|
+
// vite.config.js
|
|
1885
|
+
export default {
|
|
1886
|
+
resolve: { alias: { '#pds/lit': 'lit' } }
|
|
1887
|
+
};
|
|
1888
|
+
```
|
|
1889
|
+
|
|
1890
|
+
---
|
|
1891
|
+
|
|
1892
|
+
## Troubleshooting
|
|
1893
|
+
|
|
1894
|
+
### Components Not Loading
|
|
1895
|
+
|
|
1896
|
+
1. Verify components directory exists
|
|
1897
|
+
2. Check import map for `#pds/lit` (required for Lit components - see below)
|
|
1898
|
+
3. Manually sync: `node node_modules/pure-ds/packages/pds-cli/bin/postinstall.js`
|
|
1899
|
+
4. Check browser console for errors
|
|
1900
|
+
|
|
1901
|
+
### Lit Components Not Working
|
|
1902
|
+
|
|
1903
|
+
**Symptoms:** `<pds-form>` or other Lit-based components fail to load with module resolution errors.
|
|
1904
|
+
|
|
1905
|
+
**Components requiring Lit:**
|
|
1906
|
+
- `<pds-form>` - JSON Schema forms
|
|
1907
|
+
- `<pds-drawer>` - Drawer/sidebar panels
|
|
1908
|
+
|
|
1909
|
+
**Solution:** Add import map to your HTML `<head>`:
|
|
1910
|
+
|
|
1911
|
+
```html
|
|
1912
|
+
<script type="importmap">
|
|
1913
|
+
{
|
|
1914
|
+
"imports": {
|
|
1915
|
+
"#pds/lit": "/assets/js/lit.js"
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
</script>
|
|
1919
|
+
```
|
|
1920
|
+
|
|
1921
|
+
Or in bundlers (Vite, Webpack, etc.):
|
|
1922
|
+
|
|
1923
|
+
```javascript
|
|
1924
|
+
// vite.config.js
|
|
1925
|
+
export default {
|
|
1926
|
+
resolve: {
|
|
1927
|
+
alias: { '#pds/lit': 'lit' }
|
|
1928
|
+
}
|
|
1929
|
+
};
|
|
1930
|
+
|
|
1931
|
+
// webpack.config.js
|
|
1932
|
+
module.exports = {
|
|
1933
|
+
resolve: {
|
|
1934
|
+
alias: { '#pds/lit': 'lit' }
|
|
1935
|
+
}
|
|
1936
|
+
};
|
|
1937
|
+
```
|
|
1938
|
+
|
|
1939
|
+
**Note:** Wait for components to load before accessing their APIs:
|
|
1940
|
+
|
|
1941
|
+
```javascript
|
|
1942
|
+
// ❌ Don't do this
|
|
1943
|
+
const form = document.querySelector('pds-form');
|
|
1944
|
+
form.getFormData(); // May fail if component not loaded yet
|
|
1945
|
+
|
|
1946
|
+
// ✅ Do this instead
|
|
1947
|
+
await customElements.whenDefined('pds-form');
|
|
1948
|
+
const form = document.querySelector('pds-form');
|
|
1949
|
+
form.getFormData(); // Safe
|
|
1950
|
+
```
|
|
1951
|
+
|
|
1952
|
+
### Flash of Unstyled Content
|
|
1953
|
+
|
|
1954
|
+
```javascript
|
|
1955
|
+
await PDS.start({
|
|
1956
|
+
preloadStyles: true,
|
|
1957
|
+
criticalLayers: ['tokens', 'primitives']
|
|
1958
|
+
});
|
|
1959
|
+
```
|
|
1960
|
+
|
|
1961
|
+
### Theme Not Changing
|
|
1962
|
+
|
|
1963
|
+
Enable theme management:
|
|
1964
|
+
```javascript
|
|
1965
|
+
await PDS.start({ manageTheme: true });
|
|
1966
|
+
await PDS.setTheme('dark');
|
|
1967
|
+
```
|
|
1968
|
+
|
|
1969
|
+
### Fonts Not Loading
|
|
1970
|
+
|
|
1971
|
+
Check font names are correct:
|
|
1972
|
+
```javascript
|
|
1973
|
+
design: {
|
|
1974
|
+
typography: {
|
|
1975
|
+
fontFamilyHeadings: 'Inter, sans-serif' // Exact name
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
```
|
|
1979
|
+
|
|
1980
|
+
---
|
|
1981
|
+
|
|
1982
|
+
## Contributing
|
|
1983
|
+
|
|
1984
|
+
Contributions welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
1985
|
+
|
|
1986
|
+
```bash
|
|
1987
|
+
git clone https://github.com/mvneerven/pure-ds.git
|
|
1988
|
+
cd pure-ds
|
|
1989
|
+
npm install
|
|
1990
|
+
npm run dev
|
|
1991
|
+
```
|
|
1992
|
+
|
|
1993
|
+
---
|
|
1994
|
+
|
|
1995
|
+
## License
|
|
1996
|
+
|
|
1997
|
+
**ISC License** - See [LICENSE](./LICENSE)
|
|
1998
|
+
|
|
1999
|
+
---
|
|
2000
|
+
|
|
2001
|
+
## Links
|
|
2002
|
+
|
|
2003
|
+
- 🌐 **Homepage:** https://puredesignsystem.z6.web.core.windows.net/
|
|
2004
|
+
- 📦 **NPM:** https://www.npmjs.com/package/pure-ds
|
|
2005
|
+
- 🐙 **GitHub:** https://github.com/mvneerven/pure-ds
|
|
2006
|
+
- 📖 **Docs:** [GETTING-STARTED.md](./GETTING-STARTED.md) | [PDS-QUERY-SYSTEM.md](./PDS-QUERY-SYSTEM.md)
|
|
2007
|
+
- 💬 **Discussions:** https://github.com/mvneerven/pure-ds/discussions
|
|
2008
|
+
- 🐛 **Issues:** https://github.com/mvneerven/pure-ds/issues
|
|
2009
|
+
|
|
2010
|
+
---
|
|
2011
|
+
|
|
2012
|
+
**Made with ❤️ for the open web**
|
|
2013
|
+
|
|
2014
|
+
|