@pure-ds/storybook 0.4.17 → 0.4.19

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.
Files changed (35) hide show
  1. package/.storybook/addons/html-preview/Panel.jsx +21 -21
  2. package/.storybook/addons/html-preview/preview.js +4 -5
  3. package/.storybook/manager.js +337 -49
  4. package/.storybook/preview-head.html +2 -2
  5. package/.storybook/preview.js +2 -2
  6. package/README.md +2 -2
  7. package/dist/pds-reference.json +1915 -261
  8. package/package.json +2 -2
  9. package/public/assets/css/app.css +2 -2
  10. package/public/assets/js/app.js +41 -22
  11. package/public/assets/js/pds.js +60 -41
  12. package/public/assets/pds/components/{pds-jsonform.js → pds-form.js} +536 -45
  13. package/public/assets/pds/custom-elements.json +8 -8
  14. package/public/assets/pds/vscode-custom-data.json +63 -63
  15. package/scripts/build-pds-reference.mjs +112 -38
  16. package/scripts/generate-stories.js +2 -2
  17. package/src/js/common/ask.js +48 -21
  18. package/src/js/pds-configurator/pds-config-form.js +9 -9
  19. package/src/js/pds-configurator/pds-demo.js +2 -2
  20. package/src/js/pds-core/pds-config.js +14 -14
  21. package/src/js/pds-core/pds-generator.js +25 -12
  22. package/src/js/pds-core/pds-ontology.js +5 -5
  23. package/src/js/pds.d.ts +2 -2
  24. package/stories/GettingStarted.stories.js +3 -0
  25. package/stories/WhatIsPDS.stories.js +3 -0
  26. package/stories/components/PdsForm.stories.js +4356 -0
  27. package/stories/components/{PdsJsonformUiSchema.md → PdsFormUiSchema.md} +2 -2
  28. package/stories/foundations/Spacing.stories.js +5 -5
  29. package/stories/layout/LayoutOverview.stories.js +13 -11
  30. package/stories/primitives/{Forms.stories.js → FormElements.stories.js} +3 -3
  31. package/stories/primitives/HtmlFormElements.stories.js +128 -0
  32. package/stories/primitives/{FormGroups.stories.js → HtmlFormGroups.stories.js} +70 -21
  33. package/stories/utils/PdsAsk.stories.js +14 -13
  34. package/stories/components/PdsJsonform.stories.js +0 -2007
  35. /package/src/{pds-core → node-api}/pds-api.js +0 -0
@@ -1,6 +1,6 @@
1
- # pds-jsonform uiSchema Reference
1
+ # pds-form uiSchema Reference
2
2
 
3
- The **uiSchema** is the configuration object that controls how `pds-jsonform` renders and behaves. While JSON Schema defines *what* data to collect, uiSchema defines *how* to collect it.
3
+ The **uiSchema** is the configuration object that controls how `pds-form` renders and behaves. While JSON Schema defines *what* data to collect, uiSchema defines *how* to collect it.
4
4
 
5
5
  ## Path Notation
6
6
 
@@ -154,11 +154,11 @@ export const SpacingScale = {
154
154
  <h3>Vertical Stacks</h3>
155
155
  <article class="card spacing-demo-card">
156
156
  <div class="story-spacing-demo-card__stack">
157
- <div class="story-spacing-demo-card__bar spacing-card-spacing-1"></div>
158
- <div class="story-spacing-demo-card__bar spacing-card-spacing-2"></div>
159
- <div class="story-spacing-demo-card__bar spacing-card-spacing-3"></div>
160
- <div class="story-spacing-demo-card__bar spacing-card-spacing-4"></div>
161
- <div class="story-spacing-demo-card__bar spacing-card-spacing-5"></div>
157
+ <div class="story-spacing-demo-card__bar story-spacing-card-spacing-1"></div>
158
+ <div class="story-spacing-demo-card__bar story-spacing-card-spacing-2"></div>
159
+ <div class="story-spacing-demo-card__bar story-spacing-card-spacing-3"></div>
160
+ <div class="story-spacing-demo-card__bar story-spacing-card-spacing-4"></div>
161
+ <div class="story-spacing-demo-card__bar story-spacing-card-spacing-5"></div>
162
162
  </div>
163
163
  </article>
164
164
  </div>
@@ -15,18 +15,20 @@ const layoutOverviewStyles = html`
15
15
  `;
16
16
 
17
17
  // Code samples for comparison
18
- const tailwindCode = `<div class="p-4 mt-2 rounded-lg shadow-md bg-white
19
- flex flex-col gap-2">
20
- <div class="text-lg font-bold">
21
- A Nice Box With a Title
22
- </div>
23
- <div class="text-sm text-gray-500">
24
- The subtitle of the item
25
- </div>
26
- <div class="text-base">
18
+ const tailwindCode = `<article class="max-w-md rounded-lg bg-white p-4 shadow-md">
19
+ <header class="space-y-1">
20
+ <h3 class="text-lg font-semibold">
21
+ A Nice Box With a Title
22
+ </h3>
23
+ <small class="text-sm text-slate-500">
24
+ The subtitle of the item
25
+ </small>
26
+ </header>
27
+ <p class="mt-3 text-base">
27
28
  The body of the item with some descriptive text.
28
- </div>
29
- </div>`;
29
+ </p>
30
+ </article>
31
+ `;
30
32
 
31
33
  const pdsCode = `<article class="card surface-overlay">
32
34
  <header>
@@ -1,4 +1,4 @@
1
- import { html } from 'lit';
1
+ import { html } from 'lit';
2
2
  import { toastFormData } from '../utils/toast-utils.js';
3
3
 
4
4
  // Story-specific styles (not PDS classes - demo only)
@@ -9,7 +9,7 @@ const formsStoryStyles = html`
9
9
  `;
10
10
 
11
11
  export default {
12
- title: 'Primitives/Forms',
12
+ title: 'Primitives/Form Elements',
13
13
  tags: ['buttons', 'forms'],
14
14
  parameters: {
15
15
  pds: {
@@ -19,7 +19,7 @@ export default {
19
19
  description: {
20
20
  component: `Standard HTML form controls styled by PDS.
21
21
 
22
- **💡 For modern apps, consider using [pds-jsonform](/story/components-pds-jsonform--simple-form)** - a powerful web component that automatically generates forms from JSON Schema with built-in validation, conditional logic, and data binding.
22
+ **💡 For modern apps, consider using [pds-form](/story/components-pds-form--simple-form)** - a powerful web component that automatically generates forms from JSON Schema with built-in validation, conditional logic, and data binding.
23
23
 
24
24
  These primitive form controls provide the foundation for manual form building when you need full control over the markup.`
25
25
  }
@@ -0,0 +1,128 @@
1
+ import { html } from 'lit';
2
+ import { toastFormData } from '../utils/toast-utils.js';
3
+
4
+ // Story-specific styles (not PDS classes - demo only)
5
+ const formsStoryStyles = html`
6
+ <style>
7
+ .story-form-max { max-width: 24rem; }
8
+ </style>
9
+ `;
10
+
11
+ export default {
12
+ title: 'Primitives/HTML Form Elements',
13
+ tags: ['buttons', 'forms'],
14
+ parameters: {
15
+ pds: {
16
+ tags: ['buttons', 'forms']
17
+ },
18
+ docs: {
19
+ description: {
20
+ component: `Standard HTML form controls styled by PDS.
21
+
22
+ **💡 For modern apps, consider using [pds-form](/story/components-pds-form--simple-form)** - a powerful web component that automatically generates forms from JSON Schema with built-in validation, conditional logic, and data binding.
23
+
24
+ These primitive form controls provide the foundation for manual form building when you need full control over the markup.`
25
+ }
26
+ }
27
+ },
28
+ argTypes: {
29
+ preset: {
30
+ control: 'select',
31
+ options: ['default', 'ocean-breeze', 'midnight-steel', 'sunset-vibes', 'forest-calm', 'lavender-dream'],
32
+ description: 'Choose a design preset'
33
+ },
34
+ primaryColor: {
35
+ control: 'color',
36
+ description: 'Override primary color'
37
+ },
38
+ secondaryColor: {
39
+ control: 'color',
40
+ description: 'Override secondary color'
41
+ }
42
+ }
43
+ };
44
+
45
+ export const Default = {
46
+ render: (args) => {
47
+ // Preset changes are handled by toolbar in preview.js
48
+ const handleSubmit = (event) => {
49
+ event.preventDefault();
50
+ toastFormData(new FormData(event.target));
51
+ };
52
+
53
+ return html`
54
+ ${formsStoryStyles}
55
+ <div class="card">
56
+ <form class="story-form-max" @submit=${handleSubmit}>
57
+ <label>
58
+ <span data-label>Text Input</span>
59
+ <input type="text" name="text" placeholder="Enter text...">
60
+ </label>
61
+ <label>
62
+ <span data-label>Email</span>
63
+ <div class="input-icon">
64
+ <pds-icon icon="envelope"></pds-icon>
65
+ <input type="email" name="email" required placeholder="email@example.com">
66
+ </div>
67
+ </label>
68
+ <label>
69
+ <span data-label>Select</span>
70
+ <select name="select">
71
+ <option>Option 1</option>
72
+ <option>Option 2</option>
73
+ <option>Option 3</option>
74
+ </select>
75
+ </label>
76
+ <label>
77
+ <span data-label>Textarea</span>
78
+ <textarea name="textarea" rows="4" placeholder="Enter longer text..."></textarea>
79
+ </label>
80
+ <button type="submit" class="btn-primary">Submit</button>
81
+ </form>
82
+ </div>
83
+ `;
84
+ },
85
+ args: {
86
+ preset: 'default'
87
+ }
88
+ };
89
+
90
+ export const InputsWithIcons = {
91
+ render: (args) => {
92
+ return html`
93
+ ${formsStoryStyles}
94
+ <div class="card stack-md">
95
+ <h3>Inputs with Icons</h3>
96
+ <p>Enhance inputs with icons for better UX. Icons can be positioned at the start or end of the input.</p>
97
+
98
+ <div class="stack-lg story-form-max">
99
+ <label>
100
+ <span data-label>Search (Icon Start)</span>
101
+ <div class="input-icon">
102
+ <pds-icon icon="magnifying-glass"></pds-icon>
103
+ <input type="search" placeholder="Search..." />
104
+ </div>
105
+ </label>
106
+
107
+ <label>
108
+ <span data-label>Username (Icon End)</span>
109
+ <div class="input-icon input-icon-end">
110
+ <input type="text" placeholder="Username" />
111
+ <pds-icon icon="user"></pds-icon>
112
+ </div>
113
+ </label>
114
+ </div>
115
+ </div>
116
+ `;
117
+ },
118
+ args: {
119
+ preset: 'default'
120
+ },
121
+ parameters: {
122
+ docs: {
123
+ description: {
124
+ story: 'Input fields can be enhanced with icons to provide visual context. Use the `input-icon` class wrapper and position icons at the start (default) or end (`input-icon-end`) of the input.'
125
+ }
126
+ }
127
+ }
128
+ };
@@ -1,12 +1,20 @@
1
- import { html } from 'lit';
2
- import { toastFormData } from '../utils/toast-utils.js';
3
-
1
+ import { html } from "lit";
2
+ import { toastFormData } from "../utils/toast-utils.js";
3
+
4
+ const styles = html`
5
+ <style>
6
+ /* Story-specific styles for form group demos */
7
+ .card:has(fieldset) {
8
+ max-width: 28rem;
9
+ }
10
+ </style>
11
+ `;
4
12
  export default {
5
- title: "Primitives/Form Groups",
6
- tags: ['grouping'],
13
+ title: 'Primitives/HTML Form Groups',
14
+ tags: ["grouping"],
7
15
  parameters: {
8
16
  pds: {
9
- tags: ['forms', 'grouping']
17
+ tags: ["forms", "radio", "checkbox", "grouping"],
10
18
  },
11
19
  docs: {
12
20
  description: {
@@ -38,10 +46,13 @@ Add the \`.buttons\` class to either type for outlined button-style controls:
38
46
  };
39
47
 
40
48
  export const RadioGroupDefault = () => html`
49
+ ${styles}
41
50
  <div class="card stack-md">
42
51
  <header>
43
52
  <h3>Radio Group - Default Style</h3>
44
- <small class="text-muted">Default radio group with visible radio buttons, vertical layout</small>
53
+ <small class="text-muted"
54
+ >Default radio group with visible radio buttons, vertical layout</small
55
+ >
45
56
  </header>
46
57
  <fieldset role="radiogroup">
47
58
  <legend>Select your plan</legend>
@@ -64,10 +75,14 @@ export const RadioGroupDefault = () => html`
64
75
  RadioGroupDefault.storyName = "Radio Group - Default";
65
76
 
66
77
  export const RadioGroupButtons = () => html`
78
+ ${styles}
67
79
  <div class="card stack-md">
68
80
  <header>
69
81
  <h3>Radio Group - Button Style</h3>
70
- <small class="text-muted">Add <code>class="buttons"</code> for outlined button-style radio controls</small>
82
+ <small class="text-muted"
83
+ >Add <code>class="buttons"</code> for outlined button-style radio
84
+ controls</small
85
+ >
71
86
  </header>
72
87
  <fieldset role="radiogroup" class="buttons">
73
88
  <legend>Select your plan</legend>
@@ -90,10 +105,13 @@ export const RadioGroupButtons = () => html`
90
105
  RadioGroupButtons.storyName = "Radio Group - Buttons";
91
106
 
92
107
  export const CheckboxGroupDefault = () => html`
108
+ ${styles}
93
109
  <div class="card stack-md">
94
110
  <header>
95
111
  <h3>Checkbox Group - Default Style</h3>
96
- <small class="text-muted">Default checkbox group with visible checkboxes, vertical layout</small>
112
+ <small class="text-muted"
113
+ >Default checkbox group with visible checkboxes, vertical layout</small
114
+ >
97
115
  </header>
98
116
  <fieldset role="group">
99
117
  <legend>Select features</legend>
@@ -125,10 +143,14 @@ export const CheckboxGroupDefault = () => html`
125
143
  CheckboxGroupDefault.storyName = "Checkbox Group - Default";
126
144
 
127
145
  export const CheckboxGroupButtons = () => html`
146
+ ${styles}
128
147
  <div class="card stack-md">
129
148
  <header>
130
149
  <h3>Checkbox Group - Button Style</h3>
131
- <small class="text-muted">Add <code>class="buttons"</code> for outlined button-style checkboxes</small>
150
+ <small class="text-muted"
151
+ >Add <code>class="buttons"</code> for outlined button-style
152
+ checkboxes</small
153
+ >
132
154
  </header>
133
155
  <fieldset role="group" class="buttons">
134
156
  <legend>Select features</legend>
@@ -160,10 +182,15 @@ export const CheckboxGroupButtons = () => html`
160
182
  CheckboxGroupButtons.storyName = "Checkbox Group - Buttons";
161
183
 
162
184
  export const StyleComparison = () => html`
185
+
186
+ ${styles}
163
187
  <div class="card stack-md">
164
188
  <header>
165
189
  <h3>Side-by-Side Comparison</h3>
166
- <small class="text-muted">Compare default vs button styles for both radio and checkbox groups</small>
190
+ <small class="text-muted"
191
+ >Compare default vs button styles for both radio and checkbox
192
+ groups</small
193
+ >
167
194
  </header>
168
195
  <div class="grid grid-cols-2 gap-lg">
169
196
  <div class="stack-md">
@@ -256,10 +283,14 @@ export const StyleComparison = () => html`
256
283
  StyleComparison.storyName = "Style Comparison";
257
284
 
258
285
  export const ToggleSwitches = () => html`
286
+ ${styles}
259
287
  <div class="card stack-md gap-lg">
260
288
  <header>
261
289
  <h3>Toggle Switches</h3>
262
- <small class="text-muted">Uses <code>data-toggle</code> attribute for enhanced toggle switch styling</small>
290
+ <small class="text-muted"
291
+ >Uses <code>data-toggle</code> attribute for enhanced toggle switch
292
+ styling</small
293
+ >
263
294
  </header>
264
295
 
265
296
  <section class="card">
@@ -298,11 +329,14 @@ export const ToggleSwitches = () => html`
298
329
  ToggleSwitches.storyName = "Toggle Switches";
299
330
 
300
331
  export const CustomLayout = () => html`
332
+ ${styles}
301
333
  <div class="card stack-md">
302
334
  <h3>Custom Layout with Flex Utilities</h3>
303
- <div class="alert alert-info">Override default column layout using standard CSS flex properties</div>
335
+ <div class="alert alert-info">
336
+ Override default column layout using standard CSS flex properties
337
+ </div>
304
338
 
305
- <fieldset role="radiogroup" class="flex flex-wrap gap-sm">
339
+ <fieldset role="radiogroup" class="flex-row flex-wrap gap-sm">
306
340
  <legend>Horizontal Radio Group (flex-direction: row)</legend>
307
341
  <label>
308
342
  <input type="radio" name="horizontal-radio" value="1" checked />
@@ -318,7 +352,7 @@ export const CustomLayout = () => html`
318
352
  </label>
319
353
  </fieldset>
320
354
 
321
- <fieldset role="group" class="flex flex-wrap gap-sm">
355
+ <fieldset role="group" class="flex-row flex-wrap gap-sm">
322
356
  <legend>Horizontal Checkbox Group (flex-direction: row)</legend>
323
357
  <label>
324
358
  <input type="checkbox" name="horizontal-check" value="1" checked />
@@ -339,10 +373,13 @@ export const CustomLayout = () => html`
339
373
  CustomLayout.storyName = "Custom Layout";
340
374
 
341
375
  export const ButtonStyleVariants = () => html`
376
+ ${styles}
342
377
  <div class="card stack-md">
343
378
  <header>
344
379
  <h3>Button Style Variants</h3>
345
- <small class="text-muted">Examples of button-style groups in different contexts</small>
380
+ <small class="text-muted"
381
+ >Examples of button-style groups in different contexts</small
382
+ >
346
383
  </header>
347
384
  <div class="stack-md gap-lg max-w-lg">
348
385
  <fieldset role="radiogroup" class="buttons">
@@ -421,7 +458,10 @@ export const AccessibleFormGroups = {
421
458
  <div class="card stack-md">
422
459
  <header>
423
460
  <h2>Accessibility Features</h2>
424
- <small class="text-muted">Form groups include proper ARIA attributes, semantic HTML, and keyboard navigation support.</small>
461
+ <small class="text-muted"
462
+ >Form groups include proper ARIA attributes, semantic HTML, and
463
+ keyboard navigation support.</small
464
+ >
425
465
  </header>
426
466
  <div class="card max-w-md">
427
467
  <form class="stack-md gap-lg" @submit=${handleSubmit}>
@@ -436,7 +476,12 @@ export const AccessibleFormGroups = {
436
476
 
437
477
  <fieldset role="group" class="flex flex-row">
438
478
  <label>
439
- <input type="radio" name="notification" value="email" checked />
479
+ <input
480
+ type="radio"
481
+ name="notification"
482
+ value="email"
483
+ checked
484
+ />
440
485
  <span>Email only</span>
441
486
  </label>
442
487
  <label>
@@ -456,7 +501,9 @@ export const AccessibleFormGroups = {
456
501
 
457
502
  <fieldset role="group" aria-describedby="topics-help">
458
503
  <legend>Topics to Follow</legend>
459
- <small id="topics-help" class="text-muted">Select all topics you're interested in</small>
504
+ <small id="topics-help" class="text-muted"
505
+ >Select all topics you're interested in</small
506
+ >
460
507
  <label data-toggle>
461
508
  <input type="checkbox" name="topics" value="product" checked />
462
509
  <span>Product Updates</span>
@@ -472,14 +519,16 @@ export const AccessibleFormGroups = {
472
519
  </fieldset>
473
520
 
474
521
  <nav class="flex gap-sm">
475
- <button type="submit" class="btn-primary">Save Preferences</button>
522
+ <button type="submit" class="btn-primary">
523
+ Save Preferences
524
+ </button>
476
525
  <button type="reset" class="btn-secondary">Reset</button>
477
526
  </nav>
478
527
  </form>
479
528
  </div>
480
529
  </div>
481
530
  `;
482
- }
531
+ },
483
532
  };
484
533
 
485
534
  AccessibleFormGroups.storyName = "Accessible Form Groups";
@@ -1,4 +1,4 @@
1
- import { html } from 'lit';
1
+ import { html } from 'lit';
2
2
  import { ask as askFallback } from '../../../../src/js/common/ask.js';
3
3
  import { toastFormData } from './toast-utils.js';
4
4
 
@@ -50,13 +50,13 @@ const marketingSchema = {
50
50
 
51
51
  const marketingUiSchema = {
52
52
  description: {
53
- 'ui:widget': 'textarea',
54
- 'ui:options': {
55
- rows: 3
56
- }
53
+ 'ui:widget': 'richtext'
54
+ },
55
+ emphasis: {
56
+ 'ui:class': 'buttons'
57
57
  },
58
58
  audiences: {
59
- 'ui:widget': 'checkboxes'
59
+ 'ui:class': 'buttons'
60
60
  }
61
61
  };
62
62
 
@@ -128,7 +128,7 @@ export const BareConfirm = {
128
128
  }
129
129
  };
130
130
 
131
- export const SimpleForm = {
131
+ export const MiniForm = {
132
132
  name: 'Mini form submission',
133
133
  render: () => {
134
134
  const handleClick = async (event) => {
@@ -263,8 +263,8 @@ export const QuickConfirm = {
263
263
  }
264
264
  };
265
265
 
266
- export const JsonformSubdialog = {
267
- name: 'Embed a pds-jsonform subform',
266
+ export const formSubdialog = {
267
+ name: 'Embed a pds-form subform',
268
268
  render: () => {
269
269
  const handleClick = async (event) => {
270
270
  const ask = ensureAsk();
@@ -278,19 +278,20 @@ export const JsonformSubdialog = {
278
278
  const dialogResult = await ask(
279
279
  html`
280
280
  <form method="dialog" class="stack-md min-w-sm">
281
- <pds-jsonform
281
+ <pds-form
282
282
  id="spotlight-form"
283
283
  .jsonSchema=${marketingSchema}
284
284
  .uiSchema=${marketingUiSchema}
285
285
  .values=${marketingInitialValues}
286
286
  hide-actions
287
- ></pds-jsonform>
287
+ ></pds-form>
288
288
  <input type="hidden" name="spotlight" value="" />
289
289
  </form>
290
290
  `,
291
291
  {
292
292
  title: 'Marketing spotlight',
293
293
  useForm: true,
294
+ maxHeight: '500px',
294
295
  buttons: {
295
296
  ok: { name: 'Save changes', primary: true },
296
297
  cancel: { name: 'Cancel', cancel: true }
@@ -329,7 +330,7 @@ export const JsonformSubdialog = {
329
330
  });
330
331
 
331
332
  if (typeof customElements?.whenDefined === 'function') {
332
- customElements.whenDefined('pds-jsonform').then(() => syncHidden());
333
+ customElements.whenDefined('pds-form').then(() => syncHidden());
333
334
  } else {
334
335
  syncHidden();
335
336
  }
@@ -366,7 +367,7 @@ export const JsonformSubdialog = {
366
367
  >
367
368
  <h3>Deep editing workflows</h3>
368
369
  <p>
369
- Use <code>PDS.ask()</code> with <code>useForm: true</code> to mount an entire <code>&lt;pds-jsonform&gt;</code>
370
+ Use <code>PDS.ask()</code> with <code>useForm: true</code> to mount an entire <code>&lt;pds-form&gt;</code>
370
371
  inside the dialog. The promise resolves with the form data, letting you merge the changes into the parent flow.
371
372
  </p>
372
373
  <button class="btn btn-outline" @click=${handleClick}>Edit spotlight copy</button>