@pure-ds/storybook 0.1.0
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/.storybook/addons/description/preview.js +15 -0
- package/.storybook/addons/description/register.js +60 -0
- package/.storybook/addons/html-preview/Panel.jsx +327 -0
- package/.storybook/addons/html-preview/constants.js +6 -0
- package/.storybook/addons/html-preview/preview.js +178 -0
- package/.storybook/addons/html-preview/register.js +16 -0
- package/.storybook/addons/pds-configurator/SearchTool.js +44 -0
- package/.storybook/addons/pds-configurator/Tool.js +30 -0
- package/.storybook/addons/pds-configurator/constants.js +9 -0
- package/.storybook/addons/pds-configurator/preview.js +159 -0
- package/.storybook/addons/pds-configurator/register.js +24 -0
- package/.storybook/docs.css +35 -0
- package/.storybook/htmlPreview.css +103 -0
- package/.storybook/htmlPreview.js +271 -0
- package/.storybook/main.js +160 -0
- package/.storybook/preview-body.html +48 -0
- package/.storybook/preview-head.html +11 -0
- package/.storybook/preview.js +1563 -0
- package/README.md +266 -0
- package/bin/index.js +40 -0
- package/dist/pds-reference.json +2101 -0
- package/package.json +45 -0
- package/pds.config.js +6 -0
- package/public/assets/css/app.css +1216 -0
- package/public/assets/data/auto-design-advanced.json +704 -0
- package/public/assets/data/auto-design-simple.json +123 -0
- package/public/assets/img/icon-512x512.png +0 -0
- package/public/assets/img/logo-trans.png +0 -0
- package/public/assets/img/logo.png +0 -0
- package/public/assets/js/app.js +15088 -0
- package/public/assets/js/app.js.map +7 -0
- package/public/assets/js/lit.js +1176 -0
- package/public/assets/js/lit.js.map +7 -0
- package/public/assets/js/pds.js +9801 -0
- package/public/assets/js/pds.js.map +7 -0
- package/public/assets/pds/components/pds-calendar.js +837 -0
- package/public/assets/pds/components/pds-drawer.js +857 -0
- package/public/assets/pds/components/pds-icon.js +338 -0
- package/public/assets/pds/components/pds-jsonform.js +1775 -0
- package/public/assets/pds/components/pds-richtext.js +1035 -0
- package/public/assets/pds/components/pds-scrollrow.js +331 -0
- package/public/assets/pds/components/pds-splitpanel.js +401 -0
- package/public/assets/pds/components/pds-tabstrip.js +251 -0
- package/public/assets/pds/components/pds-toaster.js +446 -0
- package/public/assets/pds/components/pds-upload.js +657 -0
- package/public/assets/pds/custom-elements.json +2003 -0
- package/public/assets/pds/icons/pds-icons.svg +498 -0
- package/public/assets/pds/pds-css-complete.json +1861 -0
- package/public/assets/pds/pds-runtime-config.json +11 -0
- package/public/assets/pds/pds.css-data.json +2152 -0
- package/public/assets/pds/styles/pds-components.css +1944 -0
- package/public/assets/pds/styles/pds-components.css.js +3895 -0
- package/public/assets/pds/styles/pds-primitives.css +352 -0
- package/public/assets/pds/styles/pds-primitives.css.js +711 -0
- package/public/assets/pds/styles/pds-styles.css +3761 -0
- package/public/assets/pds/styles/pds-styles.css.js +7529 -0
- package/public/assets/pds/styles/pds-tokens.css +699 -0
- package/public/assets/pds/styles/pds-tokens.css.js +1405 -0
- package/public/assets/pds/styles/pds-utilities.css +763 -0
- package/public/assets/pds/styles/pds-utilities.css.js +1533 -0
- package/public/assets/pds/vscode-custom-data.json +824 -0
- package/scripts/build-pds-reference.mjs +807 -0
- package/scripts/generate-stories.js +542 -0
- package/scripts/package-build.js +86 -0
- package/src/js/app.js +17 -0
- package/src/js/common/ask.js +208 -0
- package/src/js/common/common.js +20 -0
- package/src/js/common/font-loader.js +200 -0
- package/src/js/common/msg.js +90 -0
- package/src/js/lit.js +40 -0
- package/src/js/pds-core/pds-config.js +1162 -0
- package/src/js/pds-core/pds-enhancer-metadata.js +75 -0
- package/src/js/pds-core/pds-enhancers.js +357 -0
- package/src/js/pds-core/pds-enums.js +86 -0
- package/src/js/pds-core/pds-generator.js +5317 -0
- package/src/js/pds-core/pds-ontology.js +256 -0
- package/src/js/pds-core/pds-paths.js +109 -0
- package/src/js/pds-core/pds-query.js +571 -0
- package/src/js/pds-core/pds-registry.js +129 -0
- package/src/js/pds-core/pds.d.ts +129 -0
- package/src/js/pds.d.ts +408 -0
- package/src/js/pds.js +1579 -0
- package/src/pds-core/pds-api.js +105 -0
- package/stories/GettingStarted.md +96 -0
- package/stories/GettingStarted.stories.js +144 -0
- package/stories/WhatIsPDS.md +194 -0
- package/stories/WhatIsPDS.stories.js +144 -0
- package/stories/components/PdsCalendar.stories.js +263 -0
- package/stories/components/PdsDrawer.stories.js +623 -0
- package/stories/components/PdsIcon.stories.js +78 -0
- package/stories/components/PdsJsonform.stories.js +1444 -0
- package/stories/components/PdsRichtext.stories.js +367 -0
- package/stories/components/PdsScrollrow.stories.js +140 -0
- package/stories/components/PdsSplitpanel.stories.js +502 -0
- package/stories/components/PdsTabstrip.stories.js +442 -0
- package/stories/components/PdsToaster.stories.js +186 -0
- package/stories/components/PdsUpload.stories.js +66 -0
- package/stories/enhancements/Dropdowns.stories.js +185 -0
- package/stories/enhancements/InteractiveStates.stories.js +625 -0
- package/stories/enhancements/MeshGradients.stories.js +320 -0
- package/stories/enhancements/OpenGroups.stories.js +227 -0
- package/stories/enhancements/RangeSliders.stories.js +232 -0
- package/stories/enhancements/RequiredFields.stories.js +189 -0
- package/stories/enhancements/Toggles.stories.js +167 -0
- package/stories/foundations/Colors.stories.js +283 -0
- package/stories/foundations/Icons.stories.js +305 -0
- package/stories/foundations/SmartSurfaces.stories.js +367 -0
- package/stories/foundations/Spacing.stories.js +175 -0
- package/stories/foundations/Typography.stories.js +960 -0
- package/stories/foundations/ZIndex.stories.js +325 -0
- package/stories/patterns/BorderEffects.stories.js +72 -0
- package/stories/patterns/Layout.stories.js +99 -0
- package/stories/patterns/Utilities.stories.js +107 -0
- package/stories/primitives/Accordion.stories.js +359 -0
- package/stories/primitives/Alerts.stories.js +64 -0
- package/stories/primitives/Badges.stories.js +183 -0
- package/stories/primitives/Buttons.stories.js +229 -0
- package/stories/primitives/Cards.stories.js +353 -0
- package/stories/primitives/FormGroups.stories.js +569 -0
- package/stories/primitives/Forms.stories.js +131 -0
- package/stories/primitives/Media.stories.js +203 -0
- package/stories/primitives/Tables.stories.js +232 -0
- package/stories/reference/ReferenceCatalog.stories.js +28 -0
- package/stories/reference/reference-catalog.js +413 -0
- package/stories/reference/reference-docs.js +302 -0
- package/stories/reference/reference-helpers.js +310 -0
- package/stories/utilities/GridSystem.stories.js +208 -0
- package/stories/utils/PdsAsk.stories.js +420 -0
- package/stories/utils/toast-utils.js +148 -0
|
@@ -0,0 +1,1444 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
|
|
3
|
+
const docsParameters = {
|
|
4
|
+
description: {
|
|
5
|
+
component: `**⭐ Recommended for modern applications** - Automatically generate complete forms from JSON Schema definitions.
|
|
6
|
+
|
|
7
|
+
### Key Features
|
|
8
|
+
- 🎯 **Zero boilerplate** - Define form structure in JSON, get a working form with validation
|
|
9
|
+
- ✅ **Built-in validation** - Automatic validation based on schema rules (required, min/max, patterns, etc.)
|
|
10
|
+
- 🔄 **Data binding** - Two-way data binding with form state management
|
|
11
|
+
- 🎨 **PDS styled** - Uses all PDS design tokens automatically
|
|
12
|
+
- 📱 **Responsive** - Mobile-friendly layouts out of the box
|
|
13
|
+
- 🧩 **Conditional logic** - Show/hide fields based on other field values
|
|
14
|
+
- 🌐 **Nested objects** - Support for complex nested data structures
|
|
15
|
+
- 🔧 **Extensible** - Custom field types and validators
|
|
16
|
+
|
|
17
|
+
### Why JSON Schema Forms?
|
|
18
|
+
Instead of manually writing HTML for every form field, validation rule, and error message, you define your data schema once and get:
|
|
19
|
+
- Form UI generation
|
|
20
|
+
- Client-side validation
|
|
21
|
+
- Server-side validation (same schema)
|
|
22
|
+
- API documentation
|
|
23
|
+
- Type definitions
|
|
24
|
+
- Database schemas
|
|
25
|
+
|
|
26
|
+
See the examples below to get started, or check the [primitive forms](/story/primitives-forms--default) for manual form building.`
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
if (typeof window !== 'undefined') {
|
|
31
|
+
import('../reference/reference-docs.js')
|
|
32
|
+
.then(({ createComponentDocsPage }) => {
|
|
33
|
+
docsParameters.page = createComponentDocsPage('pds-jsonform');
|
|
34
|
+
})
|
|
35
|
+
.catch((error) => {
|
|
36
|
+
console.warn('storybook: docs page failed to load for pds-jsonform', error);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default {
|
|
41
|
+
title: 'Components/Pds Jsonform',
|
|
42
|
+
tags: ['autodocs', 'buttons', 'forms', 'interaction'],
|
|
43
|
+
parameters: {
|
|
44
|
+
pds: {
|
|
45
|
+
tags: ['buttons', 'forms', 'interaction']
|
|
46
|
+
},
|
|
47
|
+
docs: docsParameters
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const simpleSchema = {
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
name: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
title: 'Full Name',
|
|
57
|
+
examples: ['John Doe']
|
|
58
|
+
},
|
|
59
|
+
email: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
format: 'email',
|
|
62
|
+
title: 'Email Address',
|
|
63
|
+
examples: ['john.doe@example.com']
|
|
64
|
+
},
|
|
65
|
+
age: {
|
|
66
|
+
type: 'number',
|
|
67
|
+
title: 'Age',
|
|
68
|
+
minimum: 18,
|
|
69
|
+
examples: [25]
|
|
70
|
+
},
|
|
71
|
+
newsletter: {
|
|
72
|
+
type: 'boolean',
|
|
73
|
+
title: 'Subscribe to newsletter'
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
required: ['name', 'email']
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const complexSchema = {
|
|
80
|
+
type: 'object',
|
|
81
|
+
properties: {
|
|
82
|
+
personalInfo: {
|
|
83
|
+
type: 'object',
|
|
84
|
+
title: 'Personal Information',
|
|
85
|
+
properties: {
|
|
86
|
+
firstName: { type: 'string', title: 'First Name', examples: ['John'] },
|
|
87
|
+
lastName: { type: 'string', title: 'Last Name', examples: ['Doe'] },
|
|
88
|
+
dateOfBirth: { type: 'string', format: 'date', title: 'Date of Birth' }
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
address: {
|
|
92
|
+
type: 'object',
|
|
93
|
+
title: 'Address',
|
|
94
|
+
properties: {
|
|
95
|
+
street: { type: 'string', title: 'Street', examples: ['123 Main Street'] },
|
|
96
|
+
city: { type: 'string', title: 'City', examples: ['New York'] },
|
|
97
|
+
country: {
|
|
98
|
+
type: 'string',
|
|
99
|
+
title: 'Country',
|
|
100
|
+
enum: ['USA', 'UK', 'Canada', 'Australia']
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
preferences: {
|
|
105
|
+
type: 'array',
|
|
106
|
+
title: 'Interests',
|
|
107
|
+
items: {
|
|
108
|
+
type: 'string',
|
|
109
|
+
enum: ['Technology', 'Sports', 'Music', 'Travel', 'Reading']
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const SimpleForm = {
|
|
116
|
+
render: () => {
|
|
117
|
+
return html`
|
|
118
|
+
<pds-jsonform
|
|
119
|
+
.jsonSchema=${simpleSchema}
|
|
120
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
121
|
+
></pds-jsonform>
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const ComplexForm = {
|
|
127
|
+
render: () => {
|
|
128
|
+
return html`
|
|
129
|
+
<pds-jsonform
|
|
130
|
+
.jsonSchema=${complexSchema}
|
|
131
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
132
|
+
></pds-jsonform>
|
|
133
|
+
`;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export const WithInitialData = {
|
|
138
|
+
render: () => {
|
|
139
|
+
const initialValues = {
|
|
140
|
+
name: 'John Doe',
|
|
141
|
+
email: 'john@example.com',
|
|
142
|
+
age: 25,
|
|
143
|
+
newsletter: true
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return html`
|
|
147
|
+
<pds-jsonform
|
|
148
|
+
.jsonSchema=${simpleSchema}
|
|
149
|
+
.values=${initialValues}
|
|
150
|
+
@pw:value-change=${(e) => console.log('🔄 Value changed:', e.detail)}
|
|
151
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
152
|
+
></pds-jsonform>
|
|
153
|
+
`;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export const WithTogglesSwitches = {
|
|
158
|
+
name: 'Toggles & Switches',
|
|
159
|
+
render: () => {
|
|
160
|
+
const schema = {
|
|
161
|
+
type: 'object',
|
|
162
|
+
properties: {
|
|
163
|
+
toggles: {
|
|
164
|
+
type: 'object',
|
|
165
|
+
title: 'Preferences',
|
|
166
|
+
properties: {
|
|
167
|
+
emailNotifications: {
|
|
168
|
+
type: 'boolean',
|
|
169
|
+
title: 'Email Notifications',
|
|
170
|
+
description: 'Receive notifications via email'
|
|
171
|
+
},
|
|
172
|
+
pushNotifications: {
|
|
173
|
+
type: 'boolean',
|
|
174
|
+
title: 'Push Notifications',
|
|
175
|
+
description: 'Receive push notifications on your device'
|
|
176
|
+
},
|
|
177
|
+
darkMode: {
|
|
178
|
+
type: 'boolean',
|
|
179
|
+
title: 'Dark Mode',
|
|
180
|
+
description: 'Enable dark theme'
|
|
181
|
+
},
|
|
182
|
+
autoSave: {
|
|
183
|
+
type: 'boolean',
|
|
184
|
+
title: 'Auto-save',
|
|
185
|
+
description: 'Automatically save changes'
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const uiSchema = {
|
|
193
|
+
toggles: {
|
|
194
|
+
'ui:layout': 'flex',
|
|
195
|
+
'ui:layoutOptions': {
|
|
196
|
+
direction: 'column',
|
|
197
|
+
gap: 'md'
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const options = {
|
|
203
|
+
widgets: {
|
|
204
|
+
booleans: 'toggle' // Use toggle switches instead of checkboxes
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
return html`
|
|
209
|
+
<pds-jsonform
|
|
210
|
+
.jsonSchema=${schema}
|
|
211
|
+
.uiSchema=${uiSchema}
|
|
212
|
+
.options=${options}
|
|
213
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
214
|
+
></pds-jsonform>
|
|
215
|
+
`;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
export const WithRangeSliders = {
|
|
220
|
+
name: 'Range Sliders with Output',
|
|
221
|
+
render: () => {
|
|
222
|
+
const schema = {
|
|
223
|
+
type: 'object',
|
|
224
|
+
properties: {
|
|
225
|
+
volume: {
|
|
226
|
+
type: 'number',
|
|
227
|
+
title: 'Volume',
|
|
228
|
+
minimum: 0,
|
|
229
|
+
maximum: 100,
|
|
230
|
+
default: 50
|
|
231
|
+
},
|
|
232
|
+
brightness: {
|
|
233
|
+
type: 'number',
|
|
234
|
+
title: 'Brightness',
|
|
235
|
+
minimum: 0,
|
|
236
|
+
maximum: 100,
|
|
237
|
+
default: 75
|
|
238
|
+
},
|
|
239
|
+
fontSize: {
|
|
240
|
+
type: 'number',
|
|
241
|
+
title: 'Font Size',
|
|
242
|
+
minimum: 10,
|
|
243
|
+
maximum: 24,
|
|
244
|
+
default: 16
|
|
245
|
+
},
|
|
246
|
+
quality: {
|
|
247
|
+
type: 'integer',
|
|
248
|
+
title: 'Quality',
|
|
249
|
+
minimum: 1,
|
|
250
|
+
maximum: 10,
|
|
251
|
+
default: 7
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const uiSchema = {
|
|
257
|
+
volume: { 'ui:widget': 'input-range' },
|
|
258
|
+
brightness: { 'ui:widget': 'input-range' },
|
|
259
|
+
fontSize: { 'ui:widget': 'input-range' },
|
|
260
|
+
quality: { 'ui:widget': 'input-range' }
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const options = {
|
|
264
|
+
enhancements: {
|
|
265
|
+
rangeOutput: true // Add live value display
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
return html`
|
|
270
|
+
<pds-jsonform
|
|
271
|
+
.jsonSchema=${schema}
|
|
272
|
+
.uiSchema=${uiSchema}
|
|
273
|
+
.options=${options}
|
|
274
|
+
@pw:value-change=${(e) => console.log('🎚️ Value changed:', e.detail)}
|
|
275
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
276
|
+
></pds-jsonform>
|
|
277
|
+
`;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export const WithIcons = {
|
|
282
|
+
name: 'Icon-Enhanced Inputs',
|
|
283
|
+
render: () => {
|
|
284
|
+
const schema = {
|
|
285
|
+
type: 'object',
|
|
286
|
+
properties: {
|
|
287
|
+
username: {
|
|
288
|
+
type: 'string',
|
|
289
|
+
title: 'Username',
|
|
290
|
+
examples: ['Enter your username']
|
|
291
|
+
},
|
|
292
|
+
email: {
|
|
293
|
+
type: 'string',
|
|
294
|
+
format: 'email',
|
|
295
|
+
title: 'Email',
|
|
296
|
+
examples: ['your.email@example.com']
|
|
297
|
+
},
|
|
298
|
+
password: {
|
|
299
|
+
type: 'string',
|
|
300
|
+
title: 'Password',
|
|
301
|
+
examples: ['••••••••']
|
|
302
|
+
},
|
|
303
|
+
website: {
|
|
304
|
+
type: 'string',
|
|
305
|
+
format: 'uri',
|
|
306
|
+
title: 'Website',
|
|
307
|
+
examples: ['https://yourwebsite.com']
|
|
308
|
+
},
|
|
309
|
+
phone: {
|
|
310
|
+
type: 'string',
|
|
311
|
+
title: 'Phone',
|
|
312
|
+
examples: ['+1 (555) 123-4567']
|
|
313
|
+
},
|
|
314
|
+
location: {
|
|
315
|
+
type: 'string',
|
|
316
|
+
title: 'Location',
|
|
317
|
+
examples: ['City, Country']
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
required: ['username', 'email', 'password']
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const uiSchema = {
|
|
324
|
+
username: {
|
|
325
|
+
'ui:icon': 'user',
|
|
326
|
+
'ui:iconPosition': 'start'
|
|
327
|
+
},
|
|
328
|
+
email: {
|
|
329
|
+
'ui:icon': 'envelope',
|
|
330
|
+
'ui:iconPosition': 'start'
|
|
331
|
+
},
|
|
332
|
+
password: {
|
|
333
|
+
'ui:icon': 'lock',
|
|
334
|
+
'ui:iconPosition': 'start',
|
|
335
|
+
'ui:widget': 'password'
|
|
336
|
+
},
|
|
337
|
+
website: {
|
|
338
|
+
'ui:icon': 'globe',
|
|
339
|
+
'ui:iconPosition': 'start'
|
|
340
|
+
},
|
|
341
|
+
phone: {
|
|
342
|
+
'ui:icon': 'phone',
|
|
343
|
+
'ui:iconPosition': 'start'
|
|
344
|
+
},
|
|
345
|
+
location: {
|
|
346
|
+
'ui:icon': 'map-pin',
|
|
347
|
+
'ui:iconPosition': 'start'
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
return html`
|
|
352
|
+
<pds-jsonform
|
|
353
|
+
.jsonSchema=${schema}
|
|
354
|
+
.uiSchema=${uiSchema}
|
|
355
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
356
|
+
></pds-jsonform>
|
|
357
|
+
`;
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
export const WithPdsUpload = {
|
|
362
|
+
name: 'File Upload (pds-upload)',
|
|
363
|
+
render: () => {
|
|
364
|
+
const schema = {
|
|
365
|
+
type: 'object',
|
|
366
|
+
properties: {
|
|
367
|
+
profilePicture: {
|
|
368
|
+
type: 'string',
|
|
369
|
+
title: 'Profile Picture',
|
|
370
|
+
description: 'Upload your profile photo (JPG, PNG)',
|
|
371
|
+
contentMediaType: 'image/*',
|
|
372
|
+
contentEncoding: 'base64'
|
|
373
|
+
},
|
|
374
|
+
resume: {
|
|
375
|
+
type: 'string',
|
|
376
|
+
title: 'Resume',
|
|
377
|
+
description: 'Upload your resume (PDF)',
|
|
378
|
+
contentMediaType: 'application/pdf',
|
|
379
|
+
contentEncoding: 'base64'
|
|
380
|
+
},
|
|
381
|
+
portfolio: {
|
|
382
|
+
type: 'string',
|
|
383
|
+
title: 'Portfolio Files',
|
|
384
|
+
description: 'Upload multiple portfolio items',
|
|
385
|
+
contentMediaType: 'image/*,application/pdf',
|
|
386
|
+
contentEncoding: 'base64'
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
const uiSchema = {
|
|
392
|
+
profilePicture: {
|
|
393
|
+
'ui:options': {
|
|
394
|
+
accept: 'image/jpeg,image/png',
|
|
395
|
+
maxSize: 5242880, // 5MB
|
|
396
|
+
label: 'Choose photo'
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
resume: {
|
|
400
|
+
'ui:options': {
|
|
401
|
+
accept: 'application/pdf',
|
|
402
|
+
maxSize: 10485760, // 10MB
|
|
403
|
+
label: 'Choose PDF'
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
portfolio: {
|
|
407
|
+
'ui:options': {
|
|
408
|
+
multiple: true,
|
|
409
|
+
accept: 'image/*,application/pdf',
|
|
410
|
+
label: 'Choose files'
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
return html`
|
|
416
|
+
<pds-jsonform
|
|
417
|
+
.jsonSchema=${schema}
|
|
418
|
+
.uiSchema=${uiSchema}
|
|
419
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
420
|
+
></pds-jsonform>
|
|
421
|
+
`;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
export const WithPdsRichtext = {
|
|
426
|
+
name: 'Rich Text Editor (pds-richtext)',
|
|
427
|
+
render: () => {
|
|
428
|
+
const schema = {
|
|
429
|
+
type: 'object',
|
|
430
|
+
properties: {
|
|
431
|
+
bio: {
|
|
432
|
+
type: 'string',
|
|
433
|
+
title: 'Biography',
|
|
434
|
+
description: 'Tell us about yourself',
|
|
435
|
+
examples: ['Write your biography...']
|
|
436
|
+
},
|
|
437
|
+
coverLetter: {
|
|
438
|
+
type: 'string',
|
|
439
|
+
title: 'Cover Letter',
|
|
440
|
+
description: 'Write your cover letter',
|
|
441
|
+
examples: ['Write your cover letter...']
|
|
442
|
+
},
|
|
443
|
+
jobDescription: {
|
|
444
|
+
type: 'string',
|
|
445
|
+
title: 'Job Description',
|
|
446
|
+
examples: ['Describe the position...']
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
const uiSchema = {
|
|
452
|
+
bio: {
|
|
453
|
+
'ui:widget': 'richtext',
|
|
454
|
+
'ui:options': {
|
|
455
|
+
toolbar: 'minimal'
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
coverLetter: {
|
|
459
|
+
'ui:widget': 'richtext',
|
|
460
|
+
'ui:options': {
|
|
461
|
+
toolbar: 'standard'
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
jobDescription: {
|
|
465
|
+
'ui:widget': 'richtext',
|
|
466
|
+
'ui:options': {
|
|
467
|
+
toolbar: 'full'
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
return html`
|
|
473
|
+
<pds-jsonform
|
|
474
|
+
.jsonSchema=${schema}
|
|
475
|
+
.uiSchema=${uiSchema}
|
|
476
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
477
|
+
></pds-jsonform>
|
|
478
|
+
`;
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
export const WithFlexLayout = {
|
|
483
|
+
name: 'Flex Layout',
|
|
484
|
+
render: () => {
|
|
485
|
+
const schema = {
|
|
486
|
+
type: 'object',
|
|
487
|
+
properties: {
|
|
488
|
+
contactInfo: {
|
|
489
|
+
type: 'object',
|
|
490
|
+
title: 'Contact Information',
|
|
491
|
+
properties: {
|
|
492
|
+
firstName: { type: 'string', title: 'First Name', examples: ['Jane'] },
|
|
493
|
+
lastName: { type: 'string', title: 'Last Name', examples: ['Smith'] },
|
|
494
|
+
email: { type: 'string', format: 'email', title: 'Email', examples: ['jane.smith@example.com'] },
|
|
495
|
+
phone: { type: 'string', title: 'Phone', examples: ['+1 (555) 987-6543'] }
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
const uiSchema = {
|
|
502
|
+
contactInfo: {
|
|
503
|
+
'ui:layout': 'flex',
|
|
504
|
+
'ui:layoutOptions': {
|
|
505
|
+
gap: 'md',
|
|
506
|
+
wrap: true,
|
|
507
|
+
direction: 'row'
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
return html`
|
|
513
|
+
<pds-jsonform
|
|
514
|
+
.jsonSchema=${schema}
|
|
515
|
+
.uiSchema=${uiSchema}
|
|
516
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
517
|
+
></pds-jsonform>
|
|
518
|
+
`;
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
export const WithGridLayout = {
|
|
523
|
+
name: 'Grid Layout',
|
|
524
|
+
render: () => {
|
|
525
|
+
const schema = {
|
|
526
|
+
type: 'object',
|
|
527
|
+
properties: {
|
|
528
|
+
productInfo: {
|
|
529
|
+
type: 'object',
|
|
530
|
+
title: 'Product Information',
|
|
531
|
+
properties: {
|
|
532
|
+
name: { type: 'string', title: 'Product Name', examples: ['Wireless Headphones'] },
|
|
533
|
+
sku: { type: 'string', title: 'SKU', examples: ['WH-1000XM4'] },
|
|
534
|
+
price: { type: 'number', title: 'Price', examples: [299.99] },
|
|
535
|
+
quantity: { type: 'integer', title: 'Quantity', examples: [50] },
|
|
536
|
+
category: { type: 'string', title: 'Category', enum: ['Electronics', 'Clothing', 'Books', 'Home', 'Sports', 'Garden'] },
|
|
537
|
+
brand: { type: 'string', title: 'Brand', examples: ['Sony'] },
|
|
538
|
+
weight: { type: 'number', title: 'Weight (kg)', examples: [0.25] },
|
|
539
|
+
dimensions: { type: 'string', title: 'Dimensions', examples: ['20 x 18 x 8 cm'] }
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
const uiSchema = {
|
|
546
|
+
productInfo: {
|
|
547
|
+
'ui:layout': 'grid',
|
|
548
|
+
'ui:layoutOptions': {
|
|
549
|
+
columns: 3,
|
|
550
|
+
gap: 'md'
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
return html`
|
|
556
|
+
<pds-jsonform
|
|
557
|
+
.jsonSchema=${schema}
|
|
558
|
+
.uiSchema=${uiSchema}
|
|
559
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
560
|
+
></pds-jsonform>
|
|
561
|
+
`;
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
export const WithAccordionLayout = {
|
|
566
|
+
name: 'Accordion Layout',
|
|
567
|
+
render: () => {
|
|
568
|
+
const schema = {
|
|
569
|
+
type: 'object',
|
|
570
|
+
properties: {
|
|
571
|
+
name: {
|
|
572
|
+
type: 'string',
|
|
573
|
+
title: 'Full Name',
|
|
574
|
+
examples: ['Alex Rodriguez']
|
|
575
|
+
},
|
|
576
|
+
email: {
|
|
577
|
+
type: 'string',
|
|
578
|
+
format: 'email',
|
|
579
|
+
title: 'Email',
|
|
580
|
+
examples: ['alex.rodriguez@example.com']
|
|
581
|
+
},
|
|
582
|
+
settings: {
|
|
583
|
+
type: 'object',
|
|
584
|
+
title: 'Settings',
|
|
585
|
+
properties: {
|
|
586
|
+
displaySettings: {
|
|
587
|
+
type: 'object',
|
|
588
|
+
title: 'Display Settings',
|
|
589
|
+
properties: {
|
|
590
|
+
theme: { type: 'string', title: 'Theme', enum: ['Light', 'Dark', 'Auto'], default: 'Auto' },
|
|
591
|
+
fontSize: { type: 'number', title: 'Font Size (px)', minimum: 12, maximum: 24, default: 16 },
|
|
592
|
+
density: { type: 'string', title: 'Density', enum: ['Compact', 'Comfortable', 'Spacious'], default: 'Comfortable' },
|
|
593
|
+
animations: { type: 'boolean', title: 'Enable Animations', default: true }
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
notificationSettings: {
|
|
597
|
+
type: 'object',
|
|
598
|
+
title: 'Notification Settings',
|
|
599
|
+
properties: {
|
|
600
|
+
email: { type: 'boolean', title: 'Email Notifications', default: true },
|
|
601
|
+
push: { type: 'boolean', title: 'Push Notifications', default: false },
|
|
602
|
+
sms: { type: 'boolean', title: 'SMS Notifications', default: false },
|
|
603
|
+
frequency: { type: 'string', title: 'Frequency', enum: ['Real-time', 'Daily', 'Weekly'], default: 'Daily' }
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
privacySettings: {
|
|
607
|
+
type: 'object',
|
|
608
|
+
title: 'Privacy Settings',
|
|
609
|
+
properties: {
|
|
610
|
+
profileVisibility: { type: 'string', title: 'Profile Visibility', enum: ['Public', 'Friends', 'Private'], default: 'Friends' },
|
|
611
|
+
showEmail: { type: 'boolean', title: 'Show Email', default: false },
|
|
612
|
+
showActivity: { type: 'boolean', title: 'Show Activity', default: true },
|
|
613
|
+
allowMessages: { type: 'boolean', title: 'Allow Messages', default: true }
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
},
|
|
619
|
+
required: ['name', 'email']
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
const uiSchema = {
|
|
623
|
+
settings: { 'ui:layout': 'accordion' }
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
return html`
|
|
627
|
+
<pds-jsonform
|
|
628
|
+
.jsonSchema=${schema}
|
|
629
|
+
.uiSchema=${uiSchema}
|
|
630
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
631
|
+
></pds-jsonform>
|
|
632
|
+
`;
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
export const WithTabsLayout = {
|
|
637
|
+
name: 'Tabs Layout (pds-tabstrip)',
|
|
638
|
+
render: () => {
|
|
639
|
+
const schema = {
|
|
640
|
+
type: 'object',
|
|
641
|
+
properties: {
|
|
642
|
+
userSettings: {
|
|
643
|
+
type: 'object',
|
|
644
|
+
title: 'User Settings',
|
|
645
|
+
properties: {
|
|
646
|
+
account: {
|
|
647
|
+
type: 'object',
|
|
648
|
+
title: 'Account',
|
|
649
|
+
properties: {
|
|
650
|
+
username: { type: 'string', title: 'Username', examples: ['coolguy123'] },
|
|
651
|
+
email: { type: 'string', format: 'email', title: 'Email', examples: ['user@example.com'] },
|
|
652
|
+
password: { type: 'string', title: 'New Password', examples: ['••••••••'] }
|
|
653
|
+
}
|
|
654
|
+
},
|
|
655
|
+
profile: {
|
|
656
|
+
type: 'object',
|
|
657
|
+
title: 'Profile',
|
|
658
|
+
properties: {
|
|
659
|
+
displayName: { type: 'string', title: 'Display Name', examples: ['Cool Guy'] },
|
|
660
|
+
bio: { type: 'string', title: 'Bio', examples: ['Tell us about yourself...'] },
|
|
661
|
+
location: { type: 'string', title: 'Location', examples: ['San Francisco, CA'] },
|
|
662
|
+
website: { type: 'string', format: 'uri', title: 'Website', examples: ['https://mywebsite.com'] }
|
|
663
|
+
}
|
|
664
|
+
},
|
|
665
|
+
privacy: {
|
|
666
|
+
type: 'object',
|
|
667
|
+
title: 'Privacy',
|
|
668
|
+
properties: {
|
|
669
|
+
publicProfile: { type: 'boolean', title: 'Public Profile' },
|
|
670
|
+
showEmail: { type: 'boolean', title: 'Show Email' },
|
|
671
|
+
allowMessages: { type: 'boolean', title: 'Allow Messages' },
|
|
672
|
+
searchable: { type: 'boolean', title: 'Searchable' }
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
const uiSchema = {
|
|
681
|
+
userSettings: { 'ui:layout': 'tabs' }
|
|
682
|
+
};
|
|
683
|
+
|
|
684
|
+
return html`
|
|
685
|
+
<pds-jsonform
|
|
686
|
+
.jsonSchema=${schema}
|
|
687
|
+
.uiSchema=${uiSchema}
|
|
688
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
689
|
+
></pds-jsonform>
|
|
690
|
+
`;
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
|
|
694
|
+
export const WithSurfaces = {
|
|
695
|
+
name: 'Surface Wrapping (Cards)',
|
|
696
|
+
render: () => {
|
|
697
|
+
const schema = {
|
|
698
|
+
type: 'object',
|
|
699
|
+
properties: {
|
|
700
|
+
cardGroups: {
|
|
701
|
+
type: 'object',
|
|
702
|
+
title: 'Product Catalog',
|
|
703
|
+
properties: {
|
|
704
|
+
product1: {
|
|
705
|
+
type: 'object',
|
|
706
|
+
title: 'Premium Membership',
|
|
707
|
+
properties: {
|
|
708
|
+
name: { type: 'string', title: 'Product Name', default: 'Premium Plan', examples: ['Premium Plan'] },
|
|
709
|
+
price: { type: 'number', title: 'Price (USD)', default: 29.99, minimum: 0, examples: [29.99] },
|
|
710
|
+
billing: { type: 'string', title: 'Billing Cycle', enum: ['Monthly', 'Quarterly', 'Yearly'], default: 'Monthly' },
|
|
711
|
+
autoRenew: { type: 'boolean', title: 'Auto-Renew', default: true }
|
|
712
|
+
}
|
|
713
|
+
},
|
|
714
|
+
product2: {
|
|
715
|
+
type: 'object',
|
|
716
|
+
title: 'Enterprise Solution',
|
|
717
|
+
properties: {
|
|
718
|
+
name: { type: 'string', title: 'Product Name', default: 'Enterprise', examples: ['Enterprise'] },
|
|
719
|
+
seats: { type: 'integer', title: 'Number of Seats', default: 10, minimum: 1, examples: [10] },
|
|
720
|
+
support: { type: 'string', title: 'Support Level', enum: ['Standard', 'Priority', '24/7'], default: 'Priority' },
|
|
721
|
+
sla: { type: 'boolean', title: 'SLA Agreement', default: true }
|
|
722
|
+
}
|
|
723
|
+
},
|
|
724
|
+
product3: {
|
|
725
|
+
type: 'object',
|
|
726
|
+
title: 'Developer Tools',
|
|
727
|
+
properties: {
|
|
728
|
+
name: { type: 'string', title: 'Product Name', default: 'Dev Tools Pro', examples: ['Dev Tools Pro'] },
|
|
729
|
+
apiCalls: { type: 'integer', title: 'API Calls/Month', default: 100000, minimum: 1000, examples: [100000] },
|
|
730
|
+
environments: { type: 'integer', title: 'Environments', default: 3, minimum: 1, maximum: 10, examples: [3] },
|
|
731
|
+
monitoring: { type: 'boolean', title: 'Performance Monitoring', default: true }
|
|
732
|
+
}
|
|
733
|
+
},
|
|
734
|
+
product4: {
|
|
735
|
+
type: 'object',
|
|
736
|
+
title: 'Storage Package',
|
|
737
|
+
properties: {
|
|
738
|
+
name: { type: 'string', title: 'Product Name', default: 'Cloud Storage+', examples: ['Cloud Storage+'] },
|
|
739
|
+
storage: { type: 'number', title: 'Storage (TB)', default: 5, minimum: 1, maximum: 100, examples: [5] },
|
|
740
|
+
bandwidth: { type: 'number', title: 'Bandwidth (TB)', default: 10, minimum: 1, examples: [10] },
|
|
741
|
+
backup: { type: 'boolean', title: 'Automated Backup', default: true }
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
const uiSchema = {
|
|
750
|
+
cardGroups: {
|
|
751
|
+
'ui:layout': 'grid',
|
|
752
|
+
'ui:layoutOptions': {
|
|
753
|
+
columns: 'auto',
|
|
754
|
+
autoSize: 'md',
|
|
755
|
+
gap: 'md'
|
|
756
|
+
}
|
|
757
|
+
},
|
|
758
|
+
'cardGroups/product1': {
|
|
759
|
+
'ui:surface': 'surface-sunken'
|
|
760
|
+
},
|
|
761
|
+
'cardGroups/product2': {
|
|
762
|
+
'ui:surface': 'surface-inverse'
|
|
763
|
+
},
|
|
764
|
+
'cardGroups/product3': {
|
|
765
|
+
'ui:surface': 'card'
|
|
766
|
+
},
|
|
767
|
+
'cardGroups/product4': {
|
|
768
|
+
'ui:surface': 'elevated'
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
|
|
772
|
+
return html`
|
|
773
|
+
<pds-jsonform
|
|
774
|
+
.jsonSchema=${schema}
|
|
775
|
+
.uiSchema=${uiSchema}
|
|
776
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
777
|
+
></pds-jsonform>
|
|
778
|
+
`;
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
export const WithDialogForms = {
|
|
783
|
+
name: 'Dialog-Based Nested Forms',
|
|
784
|
+
parameters: {
|
|
785
|
+
docs: {
|
|
786
|
+
description: {
|
|
787
|
+
story: 'Dialog-based forms use `ui:dialog` to edit nested objects in modal dialogs. State is transferred via FormData when using `PDS.ask()` with `useForm: true`. Click "Edit" buttons to modify nested data, then submit the main form to see all changes preserved.'
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
},
|
|
791
|
+
render: () => {
|
|
792
|
+
const schema = {
|
|
793
|
+
type: 'object',
|
|
794
|
+
properties: {
|
|
795
|
+
projectName: {
|
|
796
|
+
type: 'string',
|
|
797
|
+
title: 'Project Name',
|
|
798
|
+
examples: ['Digital Transformation Initiative']
|
|
799
|
+
},
|
|
800
|
+
teamLead: {
|
|
801
|
+
type: 'object',
|
|
802
|
+
title: 'Team Lead',
|
|
803
|
+
properties: {
|
|
804
|
+
name: { type: 'string', title: 'Full Name', examples: ['Sarah Johnson'] },
|
|
805
|
+
email: { type: 'string', format: 'email', title: 'Email Address', examples: ['sarah.johnson@company.com'] },
|
|
806
|
+
phone: { type: 'string', title: 'Phone Number', examples: ['+1-555-0123'] },
|
|
807
|
+
department: { type: 'string', title: 'Department', examples: ['Engineering'] },
|
|
808
|
+
location: { type: 'string', title: 'Office Location', examples: ['New York Office'] }
|
|
809
|
+
}
|
|
810
|
+
},
|
|
811
|
+
budget: {
|
|
812
|
+
type: 'object',
|
|
813
|
+
title: 'Budget Details',
|
|
814
|
+
properties: {
|
|
815
|
+
amount: { type: 'number', title: 'Budget Amount', examples: [250000] },
|
|
816
|
+
currency: { type: 'string', title: 'Currency', enum: ['USD', 'EUR', 'GBP', 'JPY', 'AUD'] },
|
|
817
|
+
fiscalYear: { type: 'string', title: 'Fiscal Year', examples: ['2025'] },
|
|
818
|
+
department: { type: 'string', title: 'Cost Center', examples: ['IT-001'] },
|
|
819
|
+
approved: { type: 'boolean', title: 'Budget Approved' }
|
|
820
|
+
}
|
|
821
|
+
},
|
|
822
|
+
timeline: {
|
|
823
|
+
type: 'object',
|
|
824
|
+
title: 'Project Timeline',
|
|
825
|
+
properties: {
|
|
826
|
+
startDate: { type: 'string', format: 'date', title: 'Start Date' },
|
|
827
|
+
endDate: { type: 'string', format: 'date', title: 'End Date' },
|
|
828
|
+
milestones: { type: 'integer', title: 'Number of Milestones', minimum: 1, maximum: 20, examples: [8] },
|
|
829
|
+
status: { type: 'string', title: 'Status', enum: ['Planning', 'In Progress', 'On Hold', 'Completed'], default: 'Planning' }
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
// Initial values to test state persistence
|
|
836
|
+
const initialValues = {
|
|
837
|
+
projectName: 'Digital Transformation Initiative',
|
|
838
|
+
teamLead: {
|
|
839
|
+
name: 'Sarah Johnson',
|
|
840
|
+
email: 'sarah.johnson@company.com',
|
|
841
|
+
phone: '+1-555-0123',
|
|
842
|
+
department: 'Engineering',
|
|
843
|
+
location: 'New York Office'
|
|
844
|
+
},
|
|
845
|
+
budget: {
|
|
846
|
+
amount: 250000,
|
|
847
|
+
currency: 'USD',
|
|
848
|
+
fiscalYear: '2025',
|
|
849
|
+
department: 'IT-001',
|
|
850
|
+
approved: true
|
|
851
|
+
},
|
|
852
|
+
timeline: {
|
|
853
|
+
startDate: '2025-01-15',
|
|
854
|
+
endDate: '2025-12-31',
|
|
855
|
+
milestones: 8,
|
|
856
|
+
status: 'In Progress'
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
|
|
860
|
+
const uiSchema = {
|
|
861
|
+
projectName: {
|
|
862
|
+
'ui:icon': 'folder',
|
|
863
|
+
'ui:iconPosition': 'start'
|
|
864
|
+
},
|
|
865
|
+
teamLead: {
|
|
866
|
+
'ui:dialog': true,
|
|
867
|
+
'ui:dialogOptions': {
|
|
868
|
+
buttonLabel: 'Edit Team Lead',
|
|
869
|
+
dialogTitle: 'Team Lead Information',
|
|
870
|
+
icon: 'user-gear'
|
|
871
|
+
},
|
|
872
|
+
name: { 'ui:icon': 'user', 'ui:iconPosition': 'start' },
|
|
873
|
+
email: { 'ui:icon': 'envelope', 'ui:iconPosition': 'start' },
|
|
874
|
+
phone: { 'ui:icon': 'phone', 'ui:iconPosition': 'start' },
|
|
875
|
+
department: { 'ui:icon': 'building', 'ui:iconPosition': 'start' },
|
|
876
|
+
location: { 'ui:icon': 'map-pin', 'ui:iconPosition': 'start' }
|
|
877
|
+
},
|
|
878
|
+
budget: {
|
|
879
|
+
'ui:dialog': true,
|
|
880
|
+
'ui:dialogOptions': {
|
|
881
|
+
buttonLabel: 'Edit Budget',
|
|
882
|
+
dialogTitle: 'Budget Details',
|
|
883
|
+
icon: 'currency-dollar'
|
|
884
|
+
},
|
|
885
|
+
amount: { 'ui:icon': 'dollar-sign', 'ui:iconPosition': 'start' },
|
|
886
|
+
currency: { 'ui:icon': 'coins', 'ui:iconPosition': 'start' },
|
|
887
|
+
fiscalYear: { 'ui:icon': 'calendar', 'ui:iconPosition': 'start' },
|
|
888
|
+
department: { 'ui:icon': 'building', 'ui:iconPosition': 'start' }
|
|
889
|
+
},
|
|
890
|
+
timeline: {
|
|
891
|
+
'ui:dialog': true,
|
|
892
|
+
'ui:dialogOptions': {
|
|
893
|
+
buttonLabel: 'Edit Timeline',
|
|
894
|
+
dialogTitle: 'Project Timeline',
|
|
895
|
+
icon: 'calendar'
|
|
896
|
+
},
|
|
897
|
+
startDate: { 'ui:icon': 'calendar-check', 'ui:iconPosition': 'start' },
|
|
898
|
+
endDate: { 'ui:icon': 'calendar-xmark', 'ui:iconPosition': 'start' },
|
|
899
|
+
milestones: { 'ui:icon': 'flag', 'ui:iconPosition': 'start' },
|
|
900
|
+
status: { 'ui:icon': 'list-check', 'ui:iconPosition': 'start' }
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
|
|
904
|
+
return html`
|
|
905
|
+
<pds-jsonform
|
|
906
|
+
.jsonSchema=${schema}
|
|
907
|
+
.uiSchema=${uiSchema}
|
|
908
|
+
.values=${initialValues}
|
|
909
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
910
|
+
@pw:dialog-submit=${(e) => console.log('📝 Dialog saved:', e.detail)}
|
|
911
|
+
></pds-jsonform>
|
|
912
|
+
`;
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
export const WithRadioGroupOpen = {
|
|
917
|
+
name: 'Radio Group Open (Single Selection)',
|
|
918
|
+
parameters: {
|
|
919
|
+
docs: {
|
|
920
|
+
description: {
|
|
921
|
+
story: `When an array has \`maxItems: 1\`, it renders as a Radio Group Open, allowing single selection with the ability to add custom options.
|
|
922
|
+
|
|
923
|
+
This is perfect for scenarios where users can choose one option from predefined choices or add their own custom value. The \`data-open\` enhancement automatically provides an input field to add new options dynamically.
|
|
924
|
+
|
|
925
|
+
### Key Features:
|
|
926
|
+
- **Single selection** - Only one option can be selected at a time (radio buttons)
|
|
927
|
+
- **Add custom options** - Users can type new options in the input field
|
|
928
|
+
- **Remove options** - Click the × button to remove options
|
|
929
|
+
- **Pre-populated** - Start with default options from the schema
|
|
930
|
+
|
|
931
|
+
This pattern is ideal for fields like "Priority", "Status", "Category", or any single-choice field where users might need custom values.`
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
},
|
|
935
|
+
render: () => {
|
|
936
|
+
const schema = {
|
|
937
|
+
type: 'object',
|
|
938
|
+
properties: {
|
|
939
|
+
priority: {
|
|
940
|
+
type: 'array',
|
|
941
|
+
title: 'Project Priority',
|
|
942
|
+
description: 'Select one priority level or add your own',
|
|
943
|
+
items: {
|
|
944
|
+
type: 'string',
|
|
945
|
+
examples: ['High', 'Medium', 'Low']
|
|
946
|
+
},
|
|
947
|
+
default: ['High', 'Medium', 'Low'],
|
|
948
|
+
uniqueItems: true,
|
|
949
|
+
maxItems: 1
|
|
950
|
+
},
|
|
951
|
+
status: {
|
|
952
|
+
type: 'array',
|
|
953
|
+
title: 'Current Status',
|
|
954
|
+
description: 'Choose the current project status',
|
|
955
|
+
items: {
|
|
956
|
+
type: 'string',
|
|
957
|
+
examples: ['Planning', 'In Progress', 'Review', 'Completed']
|
|
958
|
+
},
|
|
959
|
+
default: ['Planning', 'In Progress', 'Review', 'Completed'],
|
|
960
|
+
uniqueItems: true,
|
|
961
|
+
maxItems: 1
|
|
962
|
+
},
|
|
963
|
+
department: {
|
|
964
|
+
type: 'array',
|
|
965
|
+
title: 'Department',
|
|
966
|
+
description: 'Select your department',
|
|
967
|
+
items: {
|
|
968
|
+
type: 'string',
|
|
969
|
+
examples: ['Engineering', 'Design', 'Marketing', 'Sales']
|
|
970
|
+
},
|
|
971
|
+
default: ['Engineering', 'Design', 'Marketing', 'Sales'],
|
|
972
|
+
uniqueItems: true,
|
|
973
|
+
maxItems: 1
|
|
974
|
+
}
|
|
975
|
+
},
|
|
976
|
+
required: ['priority', 'status']
|
|
977
|
+
};
|
|
978
|
+
|
|
979
|
+
const initialValues = {
|
|
980
|
+
priority: ['High', 'Medium', 'Low'],
|
|
981
|
+
status: ['Planning', 'In Progress', 'Review', 'Completed'],
|
|
982
|
+
department: ['Engineering', 'Design', 'Marketing', 'Sales']
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
return html`
|
|
986
|
+
<pds-jsonform
|
|
987
|
+
.jsonSchema=${schema}
|
|
988
|
+
.values=${initialValues}
|
|
989
|
+
@pw:value-change=${(e) => console.log('🔄 Value changed:', e.detail)}
|
|
990
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
991
|
+
></pds-jsonform>
|
|
992
|
+
`;
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
export const WithDatalistAutocomplete = {
|
|
997
|
+
name: 'Datalist Autocomplete',
|
|
998
|
+
render: () => {
|
|
999
|
+
const schema = {
|
|
1000
|
+
type: 'object',
|
|
1001
|
+
properties: {
|
|
1002
|
+
country: {
|
|
1003
|
+
type: 'string',
|
|
1004
|
+
title: 'Country',
|
|
1005
|
+
examples: ['United States']
|
|
1006
|
+
},
|
|
1007
|
+
city: {
|
|
1008
|
+
type: 'string',
|
|
1009
|
+
title: 'City',
|
|
1010
|
+
examples: ['New York']
|
|
1011
|
+
},
|
|
1012
|
+
skillset: {
|
|
1013
|
+
type: 'string',
|
|
1014
|
+
title: 'Primary Skill',
|
|
1015
|
+
examples: ['JavaScript']
|
|
1016
|
+
},
|
|
1017
|
+
company: {
|
|
1018
|
+
type: 'string',
|
|
1019
|
+
title: 'Company',
|
|
1020
|
+
examples: ['Microsoft']
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
};
|
|
1024
|
+
|
|
1025
|
+
const uiSchema = {
|
|
1026
|
+
country: {
|
|
1027
|
+
'ui:datalist': ['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany', 'France', 'Spain', 'Italy', 'Japan', 'China', 'India', 'Brazil']
|
|
1028
|
+
},
|
|
1029
|
+
city: {
|
|
1030
|
+
'ui:datalist': ['New York', 'London', 'Tokyo', 'Paris', 'Berlin', 'Sydney', 'Toronto', 'Amsterdam', 'Singapore', 'Dubai']
|
|
1031
|
+
},
|
|
1032
|
+
skillset: {
|
|
1033
|
+
'ui:datalist': ['JavaScript', 'Python', 'Java', 'C++', 'Go', 'Rust', 'TypeScript', 'Ruby', 'PHP', 'Swift', 'Kotlin']
|
|
1034
|
+
},
|
|
1035
|
+
company: {
|
|
1036
|
+
'ui:datalist': ['Microsoft', 'Google', 'Apple', 'Amazon', 'Meta', 'Tesla', 'Netflix', 'Adobe', 'Salesforce', 'Oracle']
|
|
1037
|
+
}
|
|
1038
|
+
};
|
|
1039
|
+
|
|
1040
|
+
return html`
|
|
1041
|
+
<pds-jsonform
|
|
1042
|
+
.jsonSchema=${schema}
|
|
1043
|
+
.uiSchema=${uiSchema}
|
|
1044
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
1045
|
+
></pds-jsonform>
|
|
1046
|
+
`;
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
|
|
1050
|
+
export const WithArrayFields = {
|
|
1051
|
+
name: 'Dynamic Arrays (Add/Remove)',
|
|
1052
|
+
parameters: {
|
|
1053
|
+
docs: {
|
|
1054
|
+
description: {
|
|
1055
|
+
story: `Arrays in JSON Schema forms allow users to dynamically add and remove items. This is perfect for managing lists like team members, tasks, or any collection that can grow or shrink.
|
|
1056
|
+
|
|
1057
|
+
### Features:
|
|
1058
|
+
- **Add items** - Click "Add" button to create new entries
|
|
1059
|
+
- **Remove items** - Delete individual items with the "Remove" button
|
|
1060
|
+
- **Reorder items** - Use up/down arrows to change order
|
|
1061
|
+
- **Nested objects** - Each array item can contain complex nested data
|
|
1062
|
+
- **Initial values** - Pre-populate with default items
|
|
1063
|
+
- **Radio Group Open** - Arrays with \`maxItems: 1\` render as radio buttons for single selection`
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
},
|
|
1067
|
+
render: () => {
|
|
1068
|
+
const schema = {
|
|
1069
|
+
type: 'object',
|
|
1070
|
+
properties: {
|
|
1071
|
+
projectName: {
|
|
1072
|
+
type: 'string',
|
|
1073
|
+
title: 'Project Name',
|
|
1074
|
+
examples: ['Website Redesign Project']
|
|
1075
|
+
},
|
|
1076
|
+
priority: {
|
|
1077
|
+
type: 'array',
|
|
1078
|
+
title: 'Project Priority',
|
|
1079
|
+
items: {
|
|
1080
|
+
type: 'string',
|
|
1081
|
+
examples: ['High', 'Medium', 'Low']
|
|
1082
|
+
},
|
|
1083
|
+
default: ['High', 'Medium', 'Low'],
|
|
1084
|
+
uniqueItems: true,
|
|
1085
|
+
maxItems: 1
|
|
1086
|
+
},
|
|
1087
|
+
tags: {
|
|
1088
|
+
type: 'array',
|
|
1089
|
+
title: 'Project Tags',
|
|
1090
|
+
items: {
|
|
1091
|
+
type: 'string'
|
|
1092
|
+
},
|
|
1093
|
+
default: ['web', 'design', 'frontend']
|
|
1094
|
+
},
|
|
1095
|
+
teamMembers: {
|
|
1096
|
+
type: 'array',
|
|
1097
|
+
title: 'Team Members',
|
|
1098
|
+
items: {
|
|
1099
|
+
type: 'object',
|
|
1100
|
+
properties: {
|
|
1101
|
+
name: {
|
|
1102
|
+
type: 'string',
|
|
1103
|
+
title: 'Full Name',
|
|
1104
|
+
examples: ['Alice Johnson']
|
|
1105
|
+
},
|
|
1106
|
+
role: {
|
|
1107
|
+
type: 'string',
|
|
1108
|
+
title: 'Role',
|
|
1109
|
+
enum: ['Developer', 'Designer', 'Project Manager', 'QA Engineer', 'DevOps'],
|
|
1110
|
+
default: 'Developer'
|
|
1111
|
+
},
|
|
1112
|
+
email: {
|
|
1113
|
+
type: 'string',
|
|
1114
|
+
format: 'email',
|
|
1115
|
+
title: 'Email',
|
|
1116
|
+
examples: ['alice.johnson@company.com']
|
|
1117
|
+
},
|
|
1118
|
+
hours: {
|
|
1119
|
+
type: 'number',
|
|
1120
|
+
title: 'Hours/Week',
|
|
1121
|
+
minimum: 1,
|
|
1122
|
+
maximum: 40,
|
|
1123
|
+
default: 40
|
|
1124
|
+
}
|
|
1125
|
+
},
|
|
1126
|
+
required: ['name', 'role', 'email']
|
|
1127
|
+
},
|
|
1128
|
+
minItems: 1
|
|
1129
|
+
},
|
|
1130
|
+
milestones: {
|
|
1131
|
+
type: 'array',
|
|
1132
|
+
title: 'Project Milestones',
|
|
1133
|
+
items: {
|
|
1134
|
+
type: 'object',
|
|
1135
|
+
properties: {
|
|
1136
|
+
title: {
|
|
1137
|
+
type: 'string',
|
|
1138
|
+
title: 'Milestone Title',
|
|
1139
|
+
examples: ['MVP Launch']
|
|
1140
|
+
},
|
|
1141
|
+
dueDate: {
|
|
1142
|
+
type: 'string',
|
|
1143
|
+
format: 'date',
|
|
1144
|
+
title: 'Due Date'
|
|
1145
|
+
},
|
|
1146
|
+
completed: {
|
|
1147
|
+
type: 'boolean',
|
|
1148
|
+
title: 'Completed',
|
|
1149
|
+
default: false
|
|
1150
|
+
}
|
|
1151
|
+
},
|
|
1152
|
+
required: ['title', 'dueDate']
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
},
|
|
1157
|
+
required: ['projectName', 'teamMembers']
|
|
1158
|
+
};
|
|
1159
|
+
|
|
1160
|
+
// Initial values to demonstrate pre-populated arrays
|
|
1161
|
+
const initialValues = {
|
|
1162
|
+
projectName: 'Website Redesign Project',
|
|
1163
|
+
priority: ['High', 'Medium', 'Low'],
|
|
1164
|
+
teamMembers: [
|
|
1165
|
+
{
|
|
1166
|
+
name: 'Alice Johnson',
|
|
1167
|
+
role: 'Project Manager',
|
|
1168
|
+
email: 'alice.johnson@company.com',
|
|
1169
|
+
hours: 40
|
|
1170
|
+
},
|
|
1171
|
+
{
|
|
1172
|
+
name: 'Bob Smith',
|
|
1173
|
+
role: 'Developer',
|
|
1174
|
+
email: 'bob.smith@company.com',
|
|
1175
|
+
hours: 35
|
|
1176
|
+
}
|
|
1177
|
+
],
|
|
1178
|
+
milestones: [
|
|
1179
|
+
{
|
|
1180
|
+
title: 'Design Phase Complete',
|
|
1181
|
+
dueDate: '2025-02-01',
|
|
1182
|
+
completed: true
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
title: 'MVP Launch',
|
|
1186
|
+
dueDate: '2025-04-15',
|
|
1187
|
+
completed: false
|
|
1188
|
+
}
|
|
1189
|
+
],
|
|
1190
|
+
tags: ['web', 'design', 'frontend', 'responsive']
|
|
1191
|
+
};
|
|
1192
|
+
|
|
1193
|
+
const uiSchema = {
|
|
1194
|
+
teamMembers: {
|
|
1195
|
+
'ui:layout': 'default',
|
|
1196
|
+
role: {
|
|
1197
|
+
'ui:widget': 'select'
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
return html`
|
|
1203
|
+
<pds-jsonform
|
|
1204
|
+
.jsonSchema=${schema}
|
|
1205
|
+
.uiSchema=${uiSchema}
|
|
1206
|
+
.values=${initialValues}
|
|
1207
|
+
@pw:array-add=${(e) => console.log('➕ Item added to:', e.detail.path)}
|
|
1208
|
+
@pw:array-remove=${(e) => console.log('➖ Item removed from:', e.detail.path, 'at index:', e.detail.index)}
|
|
1209
|
+
@pw:array-reorder=${(e) => console.log('🔄 Item moved from', e.detail.from, 'to', e.detail.to, 'in:', e.detail.path)}
|
|
1210
|
+
@pw:value-change=${(e) => console.log('🔄 Value changed:', e.detail)}
|
|
1211
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
1212
|
+
></pds-jsonform>
|
|
1213
|
+
`;
|
|
1214
|
+
}
|
|
1215
|
+
};
|
|
1216
|
+
|
|
1217
|
+
export const ComprehensiveExample = {
|
|
1218
|
+
name: 'All Features Combined',
|
|
1219
|
+
render: () => {
|
|
1220
|
+
const schema = {
|
|
1221
|
+
type: 'object',
|
|
1222
|
+
properties: {
|
|
1223
|
+
userProfile: {
|
|
1224
|
+
type: 'object',
|
|
1225
|
+
title: 'User Profile',
|
|
1226
|
+
properties: {
|
|
1227
|
+
personalInfo: {
|
|
1228
|
+
type: 'object',
|
|
1229
|
+
title: 'Personal Information',
|
|
1230
|
+
properties: {
|
|
1231
|
+
firstName: { type: 'string', title: 'First Name', examples: ['John'] },
|
|
1232
|
+
lastName: { type: 'string', title: 'Last Name', examples: ['Doe'] },
|
|
1233
|
+
email: { type: 'string', format: 'email', title: 'Email', examples: ['john.doe@example.com'] },
|
|
1234
|
+
phone: { type: 'string', title: 'Phone', examples: ['+1 (555) 123-4567'] },
|
|
1235
|
+
dateOfBirth: { type: 'string', format: 'date', title: 'Date of Birth' }
|
|
1236
|
+
},
|
|
1237
|
+
required: ['firstName', 'lastName', 'email']
|
|
1238
|
+
},
|
|
1239
|
+
settings: {
|
|
1240
|
+
type: 'object',
|
|
1241
|
+
title: 'Settings',
|
|
1242
|
+
properties: {
|
|
1243
|
+
accountSettings: {
|
|
1244
|
+
type: 'object',
|
|
1245
|
+
title: 'Account Settings',
|
|
1246
|
+
properties: {
|
|
1247
|
+
notifications: { type: 'boolean', title: 'Email Notifications' },
|
|
1248
|
+
newsletter: { type: 'boolean', title: 'Newsletter Subscription' },
|
|
1249
|
+
twoFactor: { type: 'boolean', title: 'Two-Factor Authentication' }
|
|
1250
|
+
}
|
|
1251
|
+
},
|
|
1252
|
+
preferences: {
|
|
1253
|
+
type: 'object',
|
|
1254
|
+
title: 'Preferences',
|
|
1255
|
+
properties: {
|
|
1256
|
+
theme: { type: 'string', title: 'Theme', enum: ['Light', 'Dark', 'Auto'] },
|
|
1257
|
+
language: { type: 'string', title: 'Language', enum: ['English', 'Spanish', 'French', 'German', 'Chinese', 'Japanese'] },
|
|
1258
|
+
fontSize: { type: 'number', title: 'Font Size', minimum: 12, maximum: 20, default: 14 },
|
|
1259
|
+
lineHeight: { type: 'number', title: 'Line Height', minimum: 1.0, maximum: 2.0, default: 1.5 }
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
},
|
|
1266
|
+
profile: {
|
|
1267
|
+
type: 'object',
|
|
1268
|
+
title: 'Profile',
|
|
1269
|
+
properties: {
|
|
1270
|
+
avatar: {
|
|
1271
|
+
type: 'string',
|
|
1272
|
+
title: 'Profile Picture',
|
|
1273
|
+
contentMediaType: 'image/*',
|
|
1274
|
+
contentEncoding: 'base64'
|
|
1275
|
+
},
|
|
1276
|
+
bio: { type: 'string', title: 'Biography', examples: ['Tell us about yourself...'] },
|
|
1277
|
+
website: { type: 'string', format: 'uri', title: 'Website', examples: ['https://yourwebsite.com'] }
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1282
|
+
|
|
1283
|
+
const uiSchema = {
|
|
1284
|
+
userProfile: {
|
|
1285
|
+
'ui:layout': 'accordion',
|
|
1286
|
+
'ui:layoutOptions': { openFirst: true },
|
|
1287
|
+
'ui:surface': 'elevated',
|
|
1288
|
+
personalInfo: {
|
|
1289
|
+
'ui:layout': 'grid',
|
|
1290
|
+
'ui:layoutOptions': { columns: 2, gap: 'md' },
|
|
1291
|
+
'ui:surface': 'sunken',
|
|
1292
|
+
email: { 'ui:icon': 'envelope', 'ui:iconPosition': 'start' },
|
|
1293
|
+
phone: { 'ui:icon': 'phone', 'ui:iconPosition': 'start' }
|
|
1294
|
+
},
|
|
1295
|
+
settings: {
|
|
1296
|
+
accountSettings: {
|
|
1297
|
+
'ui:surface': 'sunken'
|
|
1298
|
+
},
|
|
1299
|
+
preferences: {
|
|
1300
|
+
'ui:surface': 'sunken',
|
|
1301
|
+
theme: { 'ui:class': 'buttons' },
|
|
1302
|
+
fontSize: { 'ui:widget': 'input-range' },
|
|
1303
|
+
lineHeight: { 'ui:widget': 'input-range' }
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
},
|
|
1307
|
+
profile: {
|
|
1308
|
+
'ui:dialog': true,
|
|
1309
|
+
'ui:dialogOptions': {
|
|
1310
|
+
buttonLabel: 'Edit Profile',
|
|
1311
|
+
dialogTitle: 'Your Profile Information'
|
|
1312
|
+
},
|
|
1313
|
+
avatar: {
|
|
1314
|
+
'ui:options': {
|
|
1315
|
+
accept: 'image/*',
|
|
1316
|
+
maxSize: 5242880,
|
|
1317
|
+
label: 'Upload Avatar'
|
|
1318
|
+
}
|
|
1319
|
+
},
|
|
1320
|
+
bio: {
|
|
1321
|
+
'ui:widget': 'richtext',
|
|
1322
|
+
'ui:options': {
|
|
1323
|
+
toolbar: 'standard'
|
|
1324
|
+
}
|
|
1325
|
+
},
|
|
1326
|
+
website: { 'ui:icon': 'globe', 'ui:iconPosition': 'start' }
|
|
1327
|
+
}
|
|
1328
|
+
};
|
|
1329
|
+
|
|
1330
|
+
const options = {
|
|
1331
|
+
widgets: {
|
|
1332
|
+
booleans: 'toggle'
|
|
1333
|
+
},
|
|
1334
|
+
enhancements: {
|
|
1335
|
+
rangeOutput: true
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
|
|
1339
|
+
return html`
|
|
1340
|
+
<pds-jsonform
|
|
1341
|
+
.jsonSchema=${schema}
|
|
1342
|
+
.uiSchema=${uiSchema}
|
|
1343
|
+
.options=${options}
|
|
1344
|
+
@pw:value-change=${(e) => console.log('🔄 Changed:', e.detail)}
|
|
1345
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
1346
|
+
></pds-jsonform>
|
|
1347
|
+
`;
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
|
|
1351
|
+
export const CustomFormActions = {
|
|
1352
|
+
name: 'Custom Form Actions',
|
|
1353
|
+
parameters: {
|
|
1354
|
+
docs: {
|
|
1355
|
+
description: {
|
|
1356
|
+
story: `Demonstrates using \`hide-actions\` to provide custom form submission buttons and handling.
|
|
1357
|
+
|
|
1358
|
+
When \`hide-actions\` is set, the default Submit and Reset buttons are hidden, allowing you to create custom action buttons in the \`actions\` slot. You can then handle form submission programmatically using the form's \`submit()\` method or by manually triggering the form element.`
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
},
|
|
1362
|
+
render: () => {
|
|
1363
|
+
const schema = {
|
|
1364
|
+
type: 'object',
|
|
1365
|
+
properties: {
|
|
1366
|
+
username: {
|
|
1367
|
+
type: 'string',
|
|
1368
|
+
title: 'Username',
|
|
1369
|
+
minLength: 3,
|
|
1370
|
+
examples: ['johndoe']
|
|
1371
|
+
},
|
|
1372
|
+
email: {
|
|
1373
|
+
type: 'string',
|
|
1374
|
+
format: 'email',
|
|
1375
|
+
title: 'Email',
|
|
1376
|
+
examples: ['john@example.com']
|
|
1377
|
+
},
|
|
1378
|
+
password: {
|
|
1379
|
+
type: 'string',
|
|
1380
|
+
format: 'password',
|
|
1381
|
+
title: 'Password',
|
|
1382
|
+
minLength: 8
|
|
1383
|
+
},
|
|
1384
|
+
terms: {
|
|
1385
|
+
type: 'boolean',
|
|
1386
|
+
title: 'I agree to the terms and conditions'
|
|
1387
|
+
}
|
|
1388
|
+
},
|
|
1389
|
+
required: ['username', 'email', 'password', 'terms']
|
|
1390
|
+
};
|
|
1391
|
+
|
|
1392
|
+
const handleSaveDraft = (e) => {
|
|
1393
|
+
const form = e.target.closest('pds-jsonform');
|
|
1394
|
+
const data = form.serialize();
|
|
1395
|
+
console.log('💾 Saving draft:', data.json);
|
|
1396
|
+
};
|
|
1397
|
+
|
|
1398
|
+
return html`
|
|
1399
|
+
<style>
|
|
1400
|
+
.custom-actions {
|
|
1401
|
+
margin-top: var(--spacing-6, 1.5rem);
|
|
1402
|
+
display: flex;
|
|
1403
|
+
gap: var(--spacing-3, 0.75rem);
|
|
1404
|
+
align-items: center;
|
|
1405
|
+
}
|
|
1406
|
+
.custom-actions .btn-secondary {
|
|
1407
|
+
margin-left: auto;
|
|
1408
|
+
}
|
|
1409
|
+
</style>
|
|
1410
|
+
|
|
1411
|
+
<pds-jsonform
|
|
1412
|
+
.jsonSchema=${schema}
|
|
1413
|
+
hide-actions
|
|
1414
|
+
@pw:value-change=${(e) => console.log('🔄 Field changed:', e.detail)}
|
|
1415
|
+
@pw:submit=${(e) => toastFormData(e.detail)}
|
|
1416
|
+
>
|
|
1417
|
+
<div slot="actions" class="custom-actions">
|
|
1418
|
+
<button
|
|
1419
|
+
type="submit"
|
|
1420
|
+
class="btn btn-primary"
|
|
1421
|
+
>
|
|
1422
|
+
<pds-icon icon="check"></pds-icon>
|
|
1423
|
+
Create Account
|
|
1424
|
+
</button>
|
|
1425
|
+
<button
|
|
1426
|
+
type="button"
|
|
1427
|
+
class="btn"
|
|
1428
|
+
@click=${handleSaveDraft}
|
|
1429
|
+
>
|
|
1430
|
+
<pds-icon icon="file"></pds-icon>
|
|
1431
|
+
Save Draft
|
|
1432
|
+
</button>
|
|
1433
|
+
<button
|
|
1434
|
+
type="button"
|
|
1435
|
+
class="btn btn-secondary btn-outline"
|
|
1436
|
+
@click=${() => console.log('Registration cancelled')}
|
|
1437
|
+
>
|
|
1438
|
+
Cancel
|
|
1439
|
+
</button>
|
|
1440
|
+
</div>
|
|
1441
|
+
</pds-jsonform>
|
|
1442
|
+
`;
|
|
1443
|
+
}
|
|
1444
|
+
};
|