@pure-ds/core 0.4.25 → 0.4.27

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/.cursorrules CHANGED
@@ -1,6 +1,6 @@
1
- # PDS (Pure Design System) - Copilot Instructions
1
+ # PDS (Pure Design System) - AI Generation Instructions
2
2
 
3
- > **CRITICAL**: This workspace uses **Pure Design System (PDS)**. All code generation MUST follow PDS patterns. Never use generic web patterns, inline styles, or hardcoded values.
3
+ > **CRITICAL**: This workspace uses **Pure Design System (PDS)**. All code generation MUST follow PDS and vanilla Web Platform patterns. Never use 3rd party framework patterns, non-PDS utility classes, inline styles, or hardcoded CSS values.
4
4
 
5
5
  ## Philosophy
6
6
 
@@ -31,7 +31,7 @@ PDS follows the [Pure Web Manifesto](https://pureweb.dev/manifesto): "The browse
31
31
  | **Web Components** | `custom-elements.json` | Complete component APIs, attributes, methods, events, slots |
32
32
  | **HTML Tags** | `public/assets/pds/vscode-custom-data.json` | Component HTML structure, attribute values |
33
33
  | **Primitives & Utilities** | `src/js/pds-core/pds-ontology.js` | `.card`, `.badge`, `.btn-*`, `.flex`, `.gap-*`, `.surface-*` |
34
- | **Enhancements** | `src/js/pds-core/pds-enhancer-metadata.js` | Selectors + `demoHtml` examples for each enhancement |
34
+ | **Enhancements** | `src/js/pds-core/pds-enhancers.js` | Enhancement metadata (`defaultPDSEnhancerMetadata`) + runtime (`defaultPDSEnhancers`) |
35
35
  | **Generator Logic** | `src/js/pds-core/pds-generator.js` | How CSS is generated, token naming conventions |
36
36
  | **Config** | `pds.config.js` | What's enabled in this workspace |
37
37
 
@@ -94,95 +94,147 @@ async function simulateSubmit(data) {
94
94
  }
95
95
  ```
96
96
 
97
- ### 3. Progressive Enhancement - Add `data-required` to form wrapper
97
+ ### 3. Adding `data-required` to pds-form generated form: simply add the attribute to the pds-form tag
98
98
 
99
99
  ```html
100
- <!-- ✅ CORRECT: Wrap pds-form in form[data-required] -->
101
- <form data-required>
102
- <pds-form id="myForm" hide-actions></pds-form>
103
- <div class="form-actions">
104
- <button type="submit" class="btn-primary">Submit</button>
105
- </div>
106
- </form>
100
+ <pds-form data-required id="myForm" hide-actions></pds-form>
101
+ ```
102
+
103
+ ### 4. Placeholders - ALWAYS include examples
104
+
105
+ **Placeholders improve UX significantly. Try to add 'examples' array to schema properties:**
106
+
107
+ **Rule: When generating a form, infer appropriate placeholders based on field name/type if not specified.**
107
108
 
108
- <!-- WRONG: No data-required enhancement -->
109
- <pds-form id="myForm"></pds-form>
109
+ ### 5. Smart Icons - Infer from field semantics
110
+
111
+ **When generating forms, automatically add appropriate icons based on field names and semantics.**
112
+
113
+ **Sources of truth for available icons:**
114
+ - Check `pds.config.js` for project-specific icon configuration
115
+ - Consult icon sprite at `public/assets/img/icons/pds-icons.svg` for available icons
116
+ - See `public/assets/pds/vscode-custom-data.json` for icon attribute values
117
+
118
+ **Use semantic reasoning to match field names to appropriate icons:**
119
+
120
+ ```javascript
121
+ // ✅ CORRECT: Infer icons based on field semantics
122
+ const uiSchema = {
123
+ "/email": { 'ui:icon': 'envelope', 'ui:autocomplete': 'email' },
124
+ "/phone": { 'ui:icon': 'phone', 'ui:autocomplete': 'tel' },
125
+ "/name": { 'ui:icon': 'user', 'ui:autocomplete': 'name' },
126
+ "/password": { 'ui:icon': 'lock', 'ui:widget': 'password' },
127
+ "/website": { 'ui:icon': 'link' },
128
+ "/address": { 'ui:icon': 'map-pin' },
129
+ "/date": { 'ui:icon': 'calendar' },
130
+ "/message": { 'ui:widget': 'textarea', 'ui:icon': 'message' }
131
+ };
110
132
  ```
111
133
 
112
- ### 4. JSON Schema - Use `examples` for placeholders
134
+ **Rule: When generating forms, analyze field names/types and select semantically appropriate icons from the available icon set.**
135
+
136
+ ### 6. Submit Handler Pattern - ALWAYS provide working async handler
137
+
138
+ **When generating a pds-form, ALWAYS include a complete, iteration-ready submit handler with:**
139
+ - `pw:submit` event (NOT native submit)
140
+ - `btn-working` class for loading state
141
+ - `PDS.toast()` for user feedback
142
+ - Error handling
143
+ - Realistic async simulation
113
144
 
114
145
  ```javascript
115
- // ✅ CORRECT: Use examples array for placeholders
116
- const schema = {
117
- type: "object",
118
- properties: {
119
- name: {
120
- type: "string",
121
- title: "Full Name",
122
- examples: ["John Doe"] // First example becomes placeholder
123
- },
124
- email: {
125
- type: "string",
126
- format: "email",
127
- title: "Email",
128
- examples: ["user@example.com"]
129
- },
130
- age: {
131
- type: "integer",
132
- title: "Age",
133
- examples: [25] // Works for numbers too
134
- }
146
+ // ✅ CORRECT: Complete submit handler pattern
147
+ form.addEventListener('pw:submit', async (e) => {
148
+ const submitBtn = form.querySelector('button[type="submit"]');
149
+ submitBtn?.classList.add('btn-working');
150
+
151
+ try {
152
+ // Simulate async operation (replace with real API call)
153
+ await new Promise(resolve => setTimeout(resolve, 2000));
154
+
155
+ // Log the data for debugging
156
+ console.log('Submitted data:', e.detail.json);
157
+
158
+ // Show success toast
159
+ await PDS.toast('Form submitted successfully!', { type: 'success' });
160
+
161
+ // Optionally reset form
162
+ form.reset();
163
+ } catch (error) {
164
+ // Show error toast
165
+ await PDS.toast('Submission failed: ' + error.message, { type: 'error' });
166
+ } finally {
167
+ // Always remove loading state
168
+ submitBtn?.classList.remove('btn-working');
135
169
  }
136
- };
170
+ });
137
171
 
138
- // ❌ WRONG: No placeholders or using wrong property
172
+ // ❌ WRONG: Native submit event
173
+ form.addEventListener('submit', (e) => { /* Won't work */ });
174
+
175
+ // ❌ WRONG: No loading state
176
+ form.addEventListener('pw:submit', async (e) => {
177
+ await fetch('/api'); // No visual feedback!
178
+ });
179
+
180
+ // ❌ WRONG: Browser dialogs
181
+ form.addEventListener('pw:submit', async (e) => {
182
+ alert('Submitted!'); // Use PDS.toast() instead
183
+ });
139
184
  ```
140
185
 
141
- ### 5. UI Schema - Infer smart icons automatically
186
+ **PDS.toast() is available globally via window.PDS:**
187
+
188
+ ```javascript
189
+ // All toast types
190
+ await PDS.toast('Success message', { type: 'success' });
191
+ await PDS.toast('Error occurred', { type: 'error' });
192
+ await PDS.toast('Warning message', { type: 'warning' });
193
+ await PDS.toast('Info message', { type: 'information' });
142
194
 
143
- **Common field icon mappings (use these by default):**
195
+ // Custom duration (auto-calculated by default based on message length)
196
+ await PDS.toast('Quick message', { type: 'info', duration: 3000 });
197
+
198
+ // Persistent (requires manual close)
199
+ await PDS.toast('Important notice', { type: 'warning', persistent: true });
200
+ ```
201
+
202
+ ### 7. Conditional "Other" Fields - Auto-generate ui:visibleWhen
203
+
204
+ **When a schema has an "Other" enum option, ALWAYS auto-generate a conditional text field:**
144
205
 
145
206
  ```javascript
146
- const smartIcons = {
147
- email: 'envelope',
148
- phone: 'phone',
149
- name: 'user',
150
- password: 'lock',
151
- search: 'search',
152
- message: 'message',
153
- comment: 'comment',
154
- address: 'map-marker',
155
- website: 'link',
156
- date: 'calendar',
157
- time: 'clock',
158
- subject: 'tag',
159
- priority: 'flag',
160
- category: 'folder',
161
- file: 'file',
162
- image: 'image'
207
+ const schema = {
208
+ type: "object",
209
+ properties: {
210
+ reason: {
211
+ type: "string",
212
+ title: "How did you hear about us?",
213
+ oneOf: [
214
+ { const: "search", title: "Search Engine" },
215
+ { const: "social", title: "Social Media" },
216
+ { const: "friend", title: "Friend Referral" },
217
+ { const: "other", title: "Other... (please specify)" }, // ← "Other" option
218
+ ],
219
+ },
220
+ otherReason: { // ← Conditional field for "Other"
221
+ type: "string",
222
+ title: "Please specify",
223
+ examples: ["Tell us more..."],
224
+ },
225
+ },
163
226
  };
164
227
 
165
228
  const uiSchema = {
166
- email: {
167
- 'ui:widget': 'email',
168
- 'ui:placeholder': 'user@example.com',
169
- 'ui:icon': 'envelope', // Auto-infer
170
- 'ui:autocomplete': 'email'
171
- },
172
- phone: {
173
- 'ui:widget': 'tel',
174
- 'ui:icon': 'phone',
175
- 'ui:autocomplete': 'tel'
229
+ // ✅ ALWAYS add these when "other" enum exists
230
+ "/otherReason": {
231
+ "ui:visibleWhen": { "/reason": "other" },
232
+ "ui:requiredWhen": { "/reason": "other" },
176
233
  },
177
- message: {
178
- 'ui:widget': 'textarea',
179
- 'ui:rows': 4,
180
- 'ui:icon': 'message'
181
- }
182
234
  };
183
235
  ```
184
236
 
185
- ### 6. Complete Working Example
237
+ ### 8. Complete Working Example
186
238
 
187
239
  ```javascript
188
240
  // Schema with examples for placeholders
@@ -213,9 +265,9 @@ const contactSchema = {
213
265
 
214
266
  // UI schema with smart icons
215
267
  const uiSchema = {
216
- name: { 'ui:icon': 'user' },
217
- email: { 'ui:icon': 'envelope' },
218
- message: {
268
+ "/name": { 'ui:icon': 'user' },
269
+ "/email": { 'ui:icon': 'envelope' },
270
+ "/message": {
219
271
  'ui:widget': 'textarea',
220
272
  'ui:rows': 4,
221
273
  'ui:icon': 'message'
@@ -296,6 +348,45 @@ const schema = {
296
348
 
297
349
  ---
298
350
 
351
+ ## ⚡ Lit Components & Import Maps
352
+
353
+ **Components that require Lit:** `pds-form`
354
+
355
+ This component uses `import { ... } from "#pds/lit"` and **requires** an import map:
356
+
357
+ ```html
358
+ <!-- REQUIRED in HTML <head> for Lit components -->
359
+ <script type="importmap">
360
+ {
361
+ "imports": {
362
+ "#pds/lit": "/assets/js/lit.js"
363
+ }
364
+ }
365
+ </script>
366
+ ```
367
+
368
+ **When generating code with lazy-loaded components, ALWAYS wait for definition:**
369
+
370
+ ```javascript
371
+ // ✅ CORRECT: Wait for component to load
372
+ await customElements.whenDefined('pds-form');
373
+ const form = document.querySelector('pds-form');
374
+ form.getFormData(); // Safe
375
+
376
+ // ✅ CORRECT: Alternative pattern
377
+ const FormClass = await customElements.get('pds-form');
378
+ if (FormClass) {
379
+ const form = document.createElement('pds-form');
380
+ // ...
381
+ }
382
+
383
+ // ❌ WRONG: Direct access without waiting
384
+ const form = document.querySelector('pds-form');
385
+ form.getFormData(); // May throw error
386
+ ```
387
+
388
+ ---
389
+
299
390
  ## ✅ Quick Reference Patterns
300
391
 
301
392
  ```html
@@ -324,7 +415,7 @@ const schema = {
324
415
  <pds-icon icon="heart" size="sm"></pds-icon>
325
416
  <pds-icon icon="check" size="lg" color="var(--color-success-500)"></pds-icon>
326
417
 
327
- <!-- Enhancements: data attributes (see pds-enhancer-metadata.js) -->
418
+ <!-- Enhancements: data attributes (see pds-enhancers.js → defaultPDSEnhancerMetadata) -->
328
419
  <nav data-dropdown>
329
420
  <button>Menu</button>
330
421
  <menu><li><a href="#">Item</a></li></menu>
@@ -341,10 +432,12 @@ const schema = {
341
432
 
342
433
  <!-- Tabs: web component -->
343
434
  <pds-tabstrip>
344
- <button slot="tab">Tab 1</button>
345
- <div slot="panel">Content 1</div>
346
- <button slot="tab">Tab 2</button>
347
- <div slot="panel">Content 2</div>
435
+ <pds-tabpanel label="Tab 1">
436
+ <p>Content for Tab 1</p>
437
+ </pds-tabpanel>
438
+ <pds-tabpanel label="Tab 2">
439
+ <p>Content for Tab 2</p>
440
+ </pds-tabpanel>
348
441
  </pds-tabstrip>
349
442
  ```
350
443
 
@@ -369,14 +462,15 @@ const results = await PDS.query("border gradient classes");
369
462
  ## 📚 Additional Resources
370
463
 
371
464
  **For comprehensive pds-form documentation:**
372
- - Read [pds-form-docs.md](pds-form-docs.md) for complete API reference
373
- - See [packages/pds-storybook/stories/components/PdsForm.stories.js](packages/pds-storybook/stories/components/PdsForm.stories.js) for real examples
374
- - Check [custom-elements.json](custom-elements.json) for component API details
465
+ - Read [pds-form-docs.md](../pds-form-docs.md) for complete API reference
466
+ - See [packages/pds-storybook/stories/components/PdsForm.stories.js](../packages/pds-storybook/stories/components/PdsForm.stories.js) for real examples
467
+ - Check [custom-elements.json](../custom-elements.json) for component API details
375
468
 
376
469
  **For toast notifications:**
377
- - Use `PDS.toast()` method (see [src/js/common/toast.js](src/js/common/toast.js) for implementation)
470
+ - Use `PDS.toast()` method (see [src/js/common/toast.js](../src/js/common/toast.js) for implementation)
378
471
  - Automatically ensures pds-toaster exists and is loaded before displaying
379
- - See pds-toaster component API in [custom-elements.json](custom-elements.json)
472
+ - See pds-toaster component API in [custom-elements.json](../custom-elements.json)
473
+
380
474
  ---
381
475
 
382
476
  ## How to Look Things Up
@@ -387,7 +481,7 @@ const results = await PDS.query("border gradient classes");
387
481
  | "What components are available?" | Read `custom-elements.json` |
388
482
  | "What utility classes exist?" | Read `pds-ontology.js` → `layoutPatterns`, `utilities` |
389
483
  | "What primitives exist?" | Read `pds-ontology.js` → `primitives` |
390
- | "How do I enhance HTML?" | Read `pds-enhancer-metadata.js` → `demoHtml` |
484
+ | "How do I enhance HTML?" | Read `pds-enhancers.js` → `defaultPDSEnhancerMetadata` → `demoHtml` |
391
485
  | "How are tokens named?" | Read `pds-generator.js` or `pds.css-data.json` |
392
486
 
393
487
  ---
@@ -401,7 +495,7 @@ Before generating code:
401
495
  3. ✅ **No hardcoded values** — Colors, spacing, radii all have tokens
402
496
  4. ✅ **No alert/confirm/prompt** — Use `PDS.ask()` and `PDS.toast()`
403
497
  5. ✅ **Use semantic HTML** — `<button>`, `<nav>`, `<article>`, `<label>`, `<details>`
404
- 6. ✅ **Apply enhancements via data-* attributes** — See `pds-enhancer-metadata.js`
498
+ 6. ✅ **Apply enhancements via data-* attributes** — See `pds-enhancers.js` → `defaultPDSEnhancerMetadata`
405
499
  7. ✅ **Components as last resort** — Only when native HTML can't achieve it
406
500
  8. ✅ **Prefer primitives** — `.card`, `.badge`, `.alert` over custom components
407
501
  9. ✅ **Wait for lazy components** — Use `await customElements.whenDefined()` before accessing APIs
@@ -1,4 +1,4 @@
1
- # PDS (Pure Design System) - Copilot Instructions
1
+ # PDS (Pure Design System) - AI Generation Instructions
2
2
 
3
3
  > **CRITICAL**: This workspace uses **Pure Design System (PDS)**. All code generation MUST follow PDS and vanilla Web Platform patterns. Never use 3rd party framework patterns, non-PDS utility classes, inline styles, or hardcoded CSS values.
4
4
 
@@ -31,7 +31,7 @@ PDS follows the [Pure Web Manifesto](https://pureweb.dev/manifesto): "The browse
31
31
  | **Web Components** | `custom-elements.json` | Complete component APIs, attributes, methods, events, slots |
32
32
  | **HTML Tags** | `public/assets/pds/vscode-custom-data.json` | Component HTML structure, attribute values |
33
33
  | **Primitives & Utilities** | `src/js/pds-core/pds-ontology.js` | `.card`, `.badge`, `.btn-*`, `.flex`, `.gap-*`, `.surface-*` |
34
- | **Enhancements** | `src/js/pds-core/pds-enhancer-metadata.js` | Selectors + `demoHtml` examples for each enhancement |
34
+ | **Enhancements** | `src/js/pds-core/pds-enhancers.js` | Enhancement metadata (`defaultPDSEnhancerMetadata`) + runtime (`defaultPDSEnhancers`) |
35
35
  | **Generator Logic** | `src/js/pds-core/pds-generator.js` | How CSS is generated, token naming conventions |
36
36
  | **Config** | `pds.config.js` | What's enabled in this workspace |
37
37
 
@@ -94,95 +94,147 @@ async function simulateSubmit(data) {
94
94
  }
95
95
  ```
96
96
 
97
- ### 3. Progressive Enhancement - Add `data-required` to form wrapper
97
+ ### 3. Adding `data-required` to pds-form generated form: simply add the attribute to the pds-form tag
98
98
 
99
99
  ```html
100
- <!-- ✅ CORRECT: Wrap pds-form in form[data-required] -->
101
- <form data-required>
102
- <pds-form id="myForm" hide-actions></pds-form>
103
- <div class="form-actions">
104
- <button type="submit" class="btn-primary">Submit</button>
105
- </div>
106
- </form>
100
+ <pds-form data-required id="myForm" hide-actions></pds-form>
101
+ ```
102
+
103
+ ### 4. Placeholders - ALWAYS include examples
104
+
105
+ **Placeholders improve UX significantly. Try to add 'examples' array to schema properties:**
106
+
107
+ **Rule: When generating a form, infer appropriate placeholders based on field name/type if not specified.**
108
+
109
+ ### 5. Smart Icons - Infer from field semantics
110
+
111
+ **When generating forms, automatically add appropriate icons based on field names and semantics.**
112
+
113
+ **Sources of truth for available icons:**
114
+ - Check `pds.config.js` for project-specific icon configuration
115
+ - Consult icon sprite at `public/assets/img/icons/pds-icons.svg` for available icons
116
+ - See `public/assets/pds/vscode-custom-data.json` for icon attribute values
107
117
 
108
- <!-- WRONG: No data-required enhancement -->
109
- <pds-form id="myForm"></pds-form>
118
+ **Use semantic reasoning to match field names to appropriate icons:**
119
+
120
+ ```javascript
121
+ // ✅ CORRECT: Infer icons based on field semantics
122
+ const uiSchema = {
123
+ "/email": { 'ui:icon': 'envelope', 'ui:autocomplete': 'email' },
124
+ "/phone": { 'ui:icon': 'phone', 'ui:autocomplete': 'tel' },
125
+ "/name": { 'ui:icon': 'user', 'ui:autocomplete': 'name' },
126
+ "/password": { 'ui:icon': 'lock', 'ui:widget': 'password' },
127
+ "/website": { 'ui:icon': 'link' },
128
+ "/address": { 'ui:icon': 'map-pin' },
129
+ "/date": { 'ui:icon': 'calendar' },
130
+ "/message": { 'ui:widget': 'textarea', 'ui:icon': 'message' }
131
+ };
110
132
  ```
111
133
 
112
- ### 4. JSON Schema - Use `examples` for placeholders
134
+ **Rule: When generating forms, analyze field names/types and select semantically appropriate icons from the available icon set.**
135
+
136
+ ### 6. Submit Handler Pattern - ALWAYS provide working async handler
137
+
138
+ **When generating a pds-form, ALWAYS include a complete, iteration-ready submit handler with:**
139
+ - `pw:submit` event (NOT native submit)
140
+ - `btn-working` class for loading state
141
+ - `PDS.toast()` for user feedback
142
+ - Error handling
143
+ - Realistic async simulation
113
144
 
114
145
  ```javascript
115
- // ✅ CORRECT: Use examples array for placeholders
116
- const schema = {
117
- type: "object",
118
- properties: {
119
- name: {
120
- type: "string",
121
- title: "Full Name",
122
- examples: ["John Doe"] // First example becomes placeholder
123
- },
124
- email: {
125
- type: "string",
126
- format: "email",
127
- title: "Email",
128
- examples: ["user@example.com"]
129
- },
130
- age: {
131
- type: "integer",
132
- title: "Age",
133
- examples: [25] // Works for numbers too
134
- }
146
+ // ✅ CORRECT: Complete submit handler pattern
147
+ form.addEventListener('pw:submit', async (e) => {
148
+ const submitBtn = form.querySelector('button[type="submit"]');
149
+ submitBtn?.classList.add('btn-working');
150
+
151
+ try {
152
+ // Simulate async operation (replace with real API call)
153
+ await new Promise(resolve => setTimeout(resolve, 2000));
154
+
155
+ // Log the data for debugging
156
+ console.log('Submitted data:', e.detail.json);
157
+
158
+ // Show success toast
159
+ await PDS.toast('Form submitted successfully!', { type: 'success' });
160
+
161
+ // Optionally reset form
162
+ form.reset();
163
+ } catch (error) {
164
+ // Show error toast
165
+ await PDS.toast('Submission failed: ' + error.message, { type: 'error' });
166
+ } finally {
167
+ // Always remove loading state
168
+ submitBtn?.classList.remove('btn-working');
135
169
  }
136
- };
170
+ });
171
+
172
+ // ❌ WRONG: Native submit event
173
+ form.addEventListener('submit', (e) => { /* Won't work */ });
137
174
 
138
- // ❌ WRONG: No placeholders or using wrong property
175
+ // ❌ WRONG: No loading state
176
+ form.addEventListener('pw:submit', async (e) => {
177
+ await fetch('/api'); // No visual feedback!
178
+ });
179
+
180
+ // ❌ WRONG: Browser dialogs
181
+ form.addEventListener('pw:submit', async (e) => {
182
+ alert('Submitted!'); // Use PDS.toast() instead
183
+ });
139
184
  ```
140
185
 
141
- ### 5. UI Schema - Infer smart icons automatically
186
+ **PDS.toast() is available globally via window.PDS:**
187
+
188
+ ```javascript
189
+ // All toast types
190
+ await PDS.toast('Success message', { type: 'success' });
191
+ await PDS.toast('Error occurred', { type: 'error' });
192
+ await PDS.toast('Warning message', { type: 'warning' });
193
+ await PDS.toast('Info message', { type: 'information' });
142
194
 
143
- **Common field icon mappings (use these by default):**
195
+ // Custom duration (auto-calculated by default based on message length)
196
+ await PDS.toast('Quick message', { type: 'info', duration: 3000 });
197
+
198
+ // Persistent (requires manual close)
199
+ await PDS.toast('Important notice', { type: 'warning', persistent: true });
200
+ ```
201
+
202
+ ### 7. Conditional "Other" Fields - Auto-generate ui:visibleWhen
203
+
204
+ **When a schema has an "Other" enum option, ALWAYS auto-generate a conditional text field:**
144
205
 
145
206
  ```javascript
146
- const smartIcons = {
147
- email: 'envelope',
148
- phone: 'phone',
149
- name: 'user',
150
- password: 'lock',
151
- search: 'search',
152
- message: 'message',
153
- comment: 'comment',
154
- address: 'map-marker',
155
- website: 'link',
156
- date: 'calendar',
157
- time: 'clock',
158
- subject: 'tag',
159
- priority: 'flag',
160
- category: 'folder',
161
- file: 'file',
162
- image: 'image'
207
+ const schema = {
208
+ type: "object",
209
+ properties: {
210
+ reason: {
211
+ type: "string",
212
+ title: "How did you hear about us?",
213
+ oneOf: [
214
+ { const: "search", title: "Search Engine" },
215
+ { const: "social", title: "Social Media" },
216
+ { const: "friend", title: "Friend Referral" },
217
+ { const: "other", title: "Other... (please specify)" }, // ← "Other" option
218
+ ],
219
+ },
220
+ otherReason: { // ← Conditional field for "Other"
221
+ type: "string",
222
+ title: "Please specify",
223
+ examples: ["Tell us more..."],
224
+ },
225
+ },
163
226
  };
164
227
 
165
228
  const uiSchema = {
166
- email: {
167
- 'ui:widget': 'email',
168
- 'ui:placeholder': 'user@example.com',
169
- 'ui:icon': 'envelope', // Auto-infer
170
- 'ui:autocomplete': 'email'
171
- },
172
- phone: {
173
- 'ui:widget': 'tel',
174
- 'ui:icon': 'phone',
175
- 'ui:autocomplete': 'tel'
229
+ // ✅ ALWAYS add these when "other" enum exists
230
+ "/otherReason": {
231
+ "ui:visibleWhen": { "/reason": "other" },
232
+ "ui:requiredWhen": { "/reason": "other" },
176
233
  },
177
- message: {
178
- 'ui:widget': 'textarea',
179
- 'ui:rows': 4,
180
- 'ui:icon': 'message'
181
- }
182
234
  };
183
235
  ```
184
236
 
185
- ### 6. Complete Working Example
237
+ ### 8. Complete Working Example
186
238
 
187
239
  ```javascript
188
240
  // Schema with examples for placeholders
@@ -213,9 +265,9 @@ const contactSchema = {
213
265
 
214
266
  // UI schema with smart icons
215
267
  const uiSchema = {
216
- name: { 'ui:icon': 'user' },
217
- email: { 'ui:icon': 'envelope' },
218
- message: {
268
+ "/name": { 'ui:icon': 'user' },
269
+ "/email": { 'ui:icon': 'envelope' },
270
+ "/message": {
219
271
  'ui:widget': 'textarea',
220
272
  'ui:rows': 4,
221
273
  'ui:icon': 'message'
@@ -363,7 +415,7 @@ form.getFormData(); // May throw error
363
415
  <pds-icon icon="heart" size="sm"></pds-icon>
364
416
  <pds-icon icon="check" size="lg" color="var(--color-success-500)"></pds-icon>
365
417
 
366
- <!-- Enhancements: data attributes (see pds-enhancer-metadata.js) -->
418
+ <!-- Enhancements: data attributes (see pds-enhancers.js → defaultPDSEnhancerMetadata) -->
367
419
  <nav data-dropdown>
368
420
  <button>Menu</button>
369
421
  <menu><li><a href="#">Item</a></li></menu>
@@ -380,10 +432,12 @@ form.getFormData(); // May throw error
380
432
 
381
433
  <!-- Tabs: web component -->
382
434
  <pds-tabstrip>
383
- <button slot="tab">Tab 1</button>
384
- <div slot="panel">Content 1</div>
385
- <button slot="tab">Tab 2</button>
386
- <div slot="panel">Content 2</div>
435
+ <pds-tabpanel label="Tab 1">
436
+ <p>Content for Tab 1</p>
437
+ </pds-tabpanel>
438
+ <pds-tabpanel label="Tab 2">
439
+ <p>Content for Tab 2</p>
440
+ </pds-tabpanel>
387
441
  </pds-tabstrip>
388
442
  ```
389
443
 
@@ -427,7 +481,7 @@ const results = await PDS.query("border gradient classes");
427
481
  | "What components are available?" | Read `custom-elements.json` |
428
482
  | "What utility classes exist?" | Read `pds-ontology.js` → `layoutPatterns`, `utilities` |
429
483
  | "What primitives exist?" | Read `pds-ontology.js` → `primitives` |
430
- | "How do I enhance HTML?" | Read `pds-enhancer-metadata.js` → `demoHtml` |
484
+ | "How do I enhance HTML?" | Read `pds-enhancers.js` → `defaultPDSEnhancerMetadata` → `demoHtml` |
431
485
  | "How are tokens named?" | Read `pds-generator.js` or `pds.css-data.json` |
432
486
 
433
487
  ---
@@ -441,7 +495,7 @@ Before generating code:
441
495
  3. ✅ **No hardcoded values** — Colors, spacing, radii all have tokens
442
496
  4. ✅ **No alert/confirm/prompt** — Use `PDS.ask()` and `PDS.toast()`
443
497
  5. ✅ **Use semantic HTML** — `<button>`, `<nav>`, `<article>`, `<label>`, `<details>`
444
- 6. ✅ **Apply enhancements via data-* attributes** — See `pds-enhancer-metadata.js`
498
+ 6. ✅ **Apply enhancements via data-* attributes** — See `pds-enhancers.js` → `defaultPDSEnhancerMetadata`
445
499
  7. ✅ **Components as last resort** — Only when native HTML can't achieve it
446
500
  8. ✅ **Prefer primitives** — `.card`, `.badge`, `.alert` over custom components
447
501
  9. ✅ **Wait for lazy components** — Use `await customElements.whenDefined()` before accessing APIs