@pure-ds/core 0.4.25 → 0.4.26
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/.github/copilot-instructions.md +188 -42
- package/package.json +1 -1
|
@@ -109,10 +109,12 @@ async function simulateSubmit(data) {
|
|
|
109
109
|
<pds-form id="myForm"></pds-form>
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
### 4.
|
|
112
|
+
### 4. Placeholders - ALWAYS include examples
|
|
113
|
+
|
|
114
|
+
**Placeholders improve UX significantly. ALWAYS add examples to schema properties:**
|
|
113
115
|
|
|
114
116
|
```javascript
|
|
115
|
-
// ✅ CORRECT:
|
|
117
|
+
// ✅ CORRECT: Every field has an example (becomes placeholder)
|
|
116
118
|
const schema = {
|
|
117
119
|
type: "object",
|
|
118
120
|
properties: {
|
|
@@ -124,65 +126,209 @@ const schema = {
|
|
|
124
126
|
email: {
|
|
125
127
|
type: "string",
|
|
126
128
|
format: "email",
|
|
127
|
-
title: "Email",
|
|
128
|
-
examples: ["
|
|
129
|
+
title: "Email Address",
|
|
130
|
+
examples: ["john@example.com"] // Shows expected format
|
|
131
|
+
},
|
|
132
|
+
phone: {
|
|
133
|
+
type: "string",
|
|
134
|
+
title: "Phone Number",
|
|
135
|
+
examples: ["+1 (555) 123-4567"] // Pattern example
|
|
129
136
|
},
|
|
130
137
|
age: {
|
|
131
138
|
type: "integer",
|
|
132
139
|
title: "Age",
|
|
133
140
|
examples: [25] // Works for numbers too
|
|
141
|
+
},
|
|
142
|
+
bio: {
|
|
143
|
+
type: "string",
|
|
144
|
+
title: "About You",
|
|
145
|
+
examples: ["Tell us about yourself..."] // Long text hint
|
|
134
146
|
}
|
|
135
147
|
}
|
|
136
148
|
};
|
|
137
149
|
|
|
138
|
-
// ❌ WRONG:
|
|
150
|
+
// ❌ WRONG: Missing examples - fields will have no placeholders
|
|
151
|
+
const badSchema = {
|
|
152
|
+
type: "object",
|
|
153
|
+
properties: {
|
|
154
|
+
email: { type: "string", format: "email" } // No placeholder!
|
|
155
|
+
}
|
|
156
|
+
};
|
|
139
157
|
```
|
|
140
158
|
|
|
141
|
-
|
|
159
|
+
**Rule: When generating a form, infer appropriate placeholders based on field name/type if not specified.**
|
|
160
|
+
|
|
161
|
+
### 5. Smart Icons - Auto-infer from field names
|
|
142
162
|
|
|
143
|
-
**
|
|
163
|
+
**When generating forms, automatically add icons for common field types. Match field names (or semantic meaning) to these icons:**
|
|
144
164
|
|
|
145
165
|
```javascript
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
166
|
+
// Icon inference map - use these patterns by default
|
|
167
|
+
const iconInference = {
|
|
168
|
+
// Contact & Identity
|
|
169
|
+
'email': 'envelope',
|
|
170
|
+
'phone': 'phone',
|
|
171
|
+
'mobile': 'phone',
|
|
172
|
+
'name': 'user',
|
|
173
|
+
'username': 'user',
|
|
174
|
+
'firstname': 'user',
|
|
175
|
+
'lastname': 'user',
|
|
176
|
+
'password': 'lock',
|
|
177
|
+
|
|
178
|
+
// Location
|
|
179
|
+
'address': 'map-pin',
|
|
180
|
+
'street': 'map-pin',
|
|
181
|
+
'city': 'building',
|
|
182
|
+
'location': 'map-marker',
|
|
183
|
+
'country': 'globe',
|
|
184
|
+
|
|
185
|
+
// Communication
|
|
186
|
+
'message': 'message',
|
|
187
|
+
'comment': 'comment',
|
|
188
|
+
'feedback': 'comment',
|
|
189
|
+
|
|
190
|
+
// Web & Links
|
|
191
|
+
'website': 'link',
|
|
192
|
+
'url': 'link',
|
|
193
|
+
'link': 'link',
|
|
194
|
+
|
|
195
|
+
// Time & Dates
|
|
196
|
+
'date': 'calendar',
|
|
197
|
+
'birthday': 'calendar',
|
|
198
|
+
'time': 'clock',
|
|
199
|
+
|
|
200
|
+
// Categorization
|
|
201
|
+
'subject': 'tag',
|
|
202
|
+
'tag': 'tag',
|
|
203
|
+
'category': 'folder',
|
|
204
|
+
'priority': 'flag',
|
|
205
|
+
|
|
206
|
+
// Files
|
|
207
|
+
'file': 'file',
|
|
208
|
+
'upload': 'upload',
|
|
209
|
+
'image': 'image',
|
|
210
|
+
'photo': 'image',
|
|
211
|
+
|
|
212
|
+
// Search
|
|
213
|
+
'search': 'search',
|
|
214
|
+
'query': 'search'
|
|
163
215
|
};
|
|
164
216
|
|
|
217
|
+
// ✅ CORRECT: Auto-generate uiSchema with icons
|
|
165
218
|
const uiSchema = {
|
|
166
|
-
email: {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
219
|
+
"/email": { 'ui:icon': 'envelope', 'ui:autocomplete': 'email' },
|
|
220
|
+
"/phone": { 'ui:icon': 'phone', 'ui:autocomplete': 'tel' },
|
|
221
|
+
"/name": { 'ui:icon': 'user', 'ui:autocomplete': 'name' },
|
|
222
|
+
"/password": { 'ui:icon': 'lock', 'ui:widget': 'password' },
|
|
223
|
+
"/website": { 'ui:icon': 'link' },
|
|
224
|
+
"/message": { 'ui:widget': 'textarea', 'ui:icon': 'message' }
|
|
225
|
+
};
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Rule: When generating a contact/signup/profile form, infer and add appropriate icons automatically.**
|
|
229
|
+
|
|
230
|
+
### 6. Submit Handler Pattern - ALWAYS provide working async handler
|
|
231
|
+
|
|
232
|
+
**When generating a pds-form, ALWAYS include a complete, iteration-ready submit handler with:**
|
|
233
|
+
- `pw:submit` event (NOT native submit)
|
|
234
|
+
- `btn-working` class for loading state
|
|
235
|
+
- `PDS.toast()` for user feedback
|
|
236
|
+
- Error handling
|
|
237
|
+
- Realistic async simulation
|
|
238
|
+
|
|
239
|
+
```javascript
|
|
240
|
+
// ✅ CORRECT: Complete submit handler pattern
|
|
241
|
+
form.addEventListener('pw:submit', async (e) => {
|
|
242
|
+
const submitBtn = form.querySelector('button[type="submit"]');
|
|
243
|
+
submitBtn?.classList.add('btn-working');
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
// Simulate async operation (replace with real API call)
|
|
247
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
248
|
+
|
|
249
|
+
// Log the data for debugging
|
|
250
|
+
console.log('Submitted data:', e.detail.json);
|
|
251
|
+
|
|
252
|
+
// Show success toast
|
|
253
|
+
await PDS.toast('Form submitted successfully!', { type: 'success' });
|
|
254
|
+
|
|
255
|
+
// Optionally reset form
|
|
256
|
+
form.reset();
|
|
257
|
+
} catch (error) {
|
|
258
|
+
// Show error toast
|
|
259
|
+
await PDS.toast('Submission failed: ' + error.message, { type: 'error' });
|
|
260
|
+
} finally {
|
|
261
|
+
// Always remove loading state
|
|
262
|
+
submitBtn?.classList.remove('btn-working');
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// ❌ WRONG: Native submit event
|
|
267
|
+
form.addEventListener('submit', (e) => { /* Won't work */ });
|
|
268
|
+
|
|
269
|
+
// ❌ WRONG: No loading state
|
|
270
|
+
form.addEventListener('pw:submit', async (e) => {
|
|
271
|
+
await fetch('/api'); // No visual feedback!
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// ❌ WRONG: Browser dialogs
|
|
275
|
+
form.addEventListener('pw:submit', async (e) => {
|
|
276
|
+
alert('Submitted!'); // Use PDS.toast() instead
|
|
277
|
+
});
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**PDS.toast() is available globally via window.PDS:**
|
|
281
|
+
|
|
282
|
+
```javascript
|
|
283
|
+
// All toast types
|
|
284
|
+
await PDS.toast('Success message', { type: 'success' });
|
|
285
|
+
await PDS.toast('Error occurred', { type: 'error' });
|
|
286
|
+
await PDS.toast('Warning message', { type: 'warning' });
|
|
287
|
+
await PDS.toast('Info message', { type: 'information' });
|
|
288
|
+
|
|
289
|
+
// Custom duration (auto-calculated by default based on message length)
|
|
290
|
+
await PDS.toast('Quick message', { type: 'info', duration: 3000 });
|
|
291
|
+
|
|
292
|
+
// Persistent (requires manual close)
|
|
293
|
+
await PDS.toast('Important notice', { type: 'warning', persistent: true });
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### 7. Conditional "Other" Fields - Auto-generate ui:visibleWhen
|
|
297
|
+
|
|
298
|
+
**When a schema has an "Other" enum option, ALWAYS auto-generate a conditional text field:**
|
|
299
|
+
|
|
300
|
+
```javascript
|
|
301
|
+
const schema = {
|
|
302
|
+
type: "object",
|
|
303
|
+
properties: {
|
|
304
|
+
reason: {
|
|
305
|
+
type: "string",
|
|
306
|
+
title: "How did you hear about us?",
|
|
307
|
+
oneOf: [
|
|
308
|
+
{ const: "search", title: "Search Engine" },
|
|
309
|
+
{ const: "social", title: "Social Media" },
|
|
310
|
+
{ const: "friend", title: "Friend Referral" },
|
|
311
|
+
{ const: "other", title: "Other... (please specify)" }, // ← "Other" option
|
|
312
|
+
],
|
|
313
|
+
},
|
|
314
|
+
otherReason: { // ← Conditional field for "Other"
|
|
315
|
+
type: "string",
|
|
316
|
+
title: "Please specify",
|
|
317
|
+
examples: ["Tell us more..."],
|
|
318
|
+
},
|
|
171
319
|
},
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const uiSchema = {
|
|
323
|
+
// ✅ ALWAYS add these when "other" enum exists
|
|
324
|
+
"/otherReason": {
|
|
325
|
+
"ui:visibleWhen": { "/reason": "other" },
|
|
326
|
+
"ui:requiredWhen": { "/reason": "other" },
|
|
176
327
|
},
|
|
177
|
-
message: {
|
|
178
|
-
'ui:widget': 'textarea',
|
|
179
|
-
'ui:rows': 4,
|
|
180
|
-
'ui:icon': 'message'
|
|
181
|
-
}
|
|
182
328
|
};
|
|
183
329
|
```
|
|
184
330
|
|
|
185
|
-
###
|
|
331
|
+
### 8. Complete Working Example
|
|
186
332
|
|
|
187
333
|
```javascript
|
|
188
334
|
// Schema with examples for placeholders
|
|
@@ -213,9 +359,9 @@ const contactSchema = {
|
|
|
213
359
|
|
|
214
360
|
// UI schema with smart icons
|
|
215
361
|
const uiSchema = {
|
|
216
|
-
name: { 'ui:icon': 'user' },
|
|
217
|
-
email: { 'ui:icon': 'envelope' },
|
|
218
|
-
message: {
|
|
362
|
+
"/name": { 'ui:icon': 'user' },
|
|
363
|
+
"/email": { 'ui:icon': 'envelope' },
|
|
364
|
+
"/message": {
|
|
219
365
|
'ui:widget': 'textarea',
|
|
220
366
|
'ui:rows': 4,
|
|
221
367
|
'ui:icon': 'message'
|