@emeraldemperaur/vector-sigma 1.4.37 → 1.4.39
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/README.md +271 -6
- package/lib/index.cjs +400 -168
- package/lib/index.esm.js +400 -168
- package/lib/types/components/conditional/conditional.d.ts +1 -1
- package/lib/types/hooks/useVectorSigma.d.ts +9 -0
- package/lib/types/tests/pax.test.d.ts +0 -0
- package/lib/types/vectorSigma.d.ts +151 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
### Overview
|
|
9
9
|
<p align="justify">
|
|
10
|
-
Vector Sigma is a dynamic form orchestrator package for rapidly creating and managing the complex lifecycle of interactive extensible input forms that can be easily embedded into a React front-end client interface for use in data capturing & onboarding applications or systems.
|
|
10
|
+
Vector Sigma (VΣ) is a dynamic form orchestrator package for rapidly creating and managing the complex lifecycle of interactive extensible input forms that can be easily embedded into a React front-end client interface for use in data capturing & onboarding applications or systems.
|
|
11
11
|
|
|
12
12
|
Fields, Input Validation and Submission can be defined and parametized in real-time predicated on a JSON (JavaScript Object Notation) xForm definition or builder object pattern.
|
|
13
13
|
</p>
|
|
@@ -38,9 +38,88 @@ npm install @emeraldemperaur/vector-sigma
|
|
|
38
38
|
npm install react@latest react-dom@latest sass@latest
|
|
39
39
|
```
|
|
40
40
|
### Usage
|
|
41
|
+
|
|
42
|
+
#### Stateless Implementation
|
|
43
|
+
```javascript
|
|
44
|
+
import React from 'react';
|
|
45
|
+
import { VectorSigma } from './VectorSigma';
|
|
46
|
+
|
|
47
|
+
const xForm = new VectorSigma(apiJSONSchema);
|
|
48
|
+
// e.g. https://github.com/emeraldemperaur/vector-sigma/blob/prometheus/src/utils/artificer.json
|
|
49
|
+
|
|
50
|
+
return xForm.transform({
|
|
51
|
+
displayMode: 'dual',
|
|
52
|
+
readOnlyMode: false,
|
|
53
|
+
onSubmit: async (values, actions, instance) => {
|
|
54
|
+
// Send validated xForm 'values' payload to destination API endpoint
|
|
55
|
+
await axios.post('/api/submit', values);
|
|
56
|
+
// Reset form after HTTP POST request success and more (i.e. https://formik.org/docs/api/formik)
|
|
57
|
+
actions.resetForm();
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
#### Stateful Implementation
|
|
62
|
+
<p align="justify">
|
|
63
|
+
<code>useVectorSigma</code> hook method utilizes React lazy initialization in tandem with <code>useRef</code> to guarantee VectorSigma class is created exactly once when the VΣ component mounts, and safely persists across DOM re-renders.
|
|
64
|
+
</p>
|
|
65
|
+
|
|
41
66
|
```javascript
|
|
42
|
-
|
|
43
|
-
|
|
67
|
+
import React from 'react';
|
|
68
|
+
import { useVectorSigma } from './hooks/useVectorSigma';
|
|
69
|
+
import { apiXFormData } from './mockData';
|
|
70
|
+
// e.g. https://github.com/emeraldemperaur/vector-sigma/blob/prometheus/src/utils/artificer.json
|
|
71
|
+
|
|
72
|
+
// Optionally define interface for inputAlias's expected in xForm 'values'
|
|
73
|
+
interface VΣRegistrationForm {
|
|
74
|
+
firstName: string;
|
|
75
|
+
lastName: string;
|
|
76
|
+
emailAddress: string;
|
|
77
|
+
isMITUndergraduate: boolean;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const VΣRegistrationForm = () => {
|
|
81
|
+
|
|
82
|
+
// Optionally pass the interface into the hook to apply <T> typing to 'values'
|
|
83
|
+
const xFormBuilder = useVectorSigma<VΣRegistrationForm>(apiXFormData);
|
|
84
|
+
|
|
85
|
+
// Or w/out a specified interface
|
|
86
|
+
const xFormBuilder = useVectorSigma(apiXFormData);
|
|
87
|
+
.setName('VΣ Registration Form')
|
|
88
|
+
.setBrand("brandHexColor", "www.exampleurl.com/logoimage.png", 'right')
|
|
89
|
+
return xFormBuilder.render({
|
|
90
|
+
displayMode: 'accordion',
|
|
91
|
+
readOnlyMode: false,
|
|
92
|
+
// Access 'values', 'actions' and 'instance' objects in global onSubmit callback function
|
|
93
|
+
onSubmit: async (values, actions, instance) => {
|
|
94
|
+
|
|
95
|
+
console.log("Email:", values.emailAddress);
|
|
96
|
+
console.log("MIT Undergraduate:", values.isMITUndergraduate);
|
|
97
|
+
const timeTakenMs = (instance.timeSubmitted || Date.now()) - instance.timeCreated;
|
|
98
|
+
console.log(`VΣ User finished the xForm in ${timeTakenMs / 1000} seconds.`);
|
|
99
|
+
console.log(`xForm Status:`, instance.statusCode);
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
// Initiate HTTP POST request with stateful 'values' and 'instance' payload
|
|
103
|
+
await fetch(`/api/questionnaires/${instance.formObject.uuid}/responses`, {
|
|
104
|
+
method: 'POST',
|
|
105
|
+
headers: { 'Content-Type': 'application/json' },
|
|
106
|
+
body: JSON.stringify({
|
|
107
|
+
formVersion: instance.formObject.uuid,
|
|
108
|
+
responseTime: instance.timeSubmitted - instance.timeCreated,
|
|
109
|
+
xFormObject: instance.formObject,
|
|
110
|
+
answers: values
|
|
111
|
+
})
|
|
112
|
+
});
|
|
113
|
+
// Reset form after HTTP POST request success and more (i.e. https://formik.org/docs/api/formik)
|
|
114
|
+
actions.resetForm();
|
|
115
|
+
alert("Thank you for completing the VΣ questionnaire!");
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error("Failed to save responses to VΣ DB", error);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
};
|
|
44
123
|
```
|
|
45
124
|
|
|
46
125
|
### Screenshots
|
|
@@ -57,23 +136,209 @@ alert(s);
|
|
|
57
136
|
|
|
58
137
|
<li><strong>🔒JSON Schema Validation</strong></br>
|
|
59
138
|
<p align="justify">Adopted <code>Zod</code> as the native engine for JSON schema validation to provide a TypeScript-first validation layer. Schema validation guarantees any schema object provided strictly adheres with the expected API model before rendering to client viewport.</p>
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
import React from 'react';
|
|
142
|
+
import { VectorSigma } from './VectorSigma';
|
|
143
|
+
import { xFormPrototypeData } from './mockData';
|
|
144
|
+
|
|
145
|
+
export const BespokeAPIForm = ({ brandColor, brandLogoUrl }) => {
|
|
146
|
+
|
|
147
|
+
// Initialize VectorSigma xForm with JSON schema
|
|
148
|
+
const xFormBuilder = new VectorSigma(xFormPrototypeData);
|
|
149
|
+
|
|
150
|
+
// Chain VectorSigma builder methods to specify or override the xForm model properties dynamically
|
|
151
|
+
const xFormElement = xFormBuilder
|
|
152
|
+
.setName('Cyberdyne Systems Billing Form')
|
|
153
|
+
// Optionally override brand color and logo from JSON {} with brand props
|
|
154
|
+
// setBrand(color, logoUrl?, logoPosition?)
|
|
155
|
+
.setBrand(tenantBrandColor, tenantLogo, 'left')
|
|
156
|
+
|
|
157
|
+
// Output xForm React component with .transform()
|
|
158
|
+
.transform({
|
|
159
|
+
displayMode: 'dual', // Dual Display UI (i.e. Codice | Accordion)
|
|
160
|
+
readOnlyMode: false,
|
|
161
|
+
// Optionally inject VectorSigma global callback function
|
|
162
|
+
onSubmit: async (values, actions, instance) => {
|
|
163
|
+
console.log("Processing Payment...", values);
|
|
164
|
+
|
|
165
|
+
// Initiate a HTTP POST request to destination API with 'values' payload
|
|
166
|
+
await new Promise(resolve => setTimeout(resolve, 1997));
|
|
167
|
+
|
|
168
|
+
alert("Payment processed successfully!...");
|
|
169
|
+
// Update Formik context to isSubmitting false after successful HTTP post request
|
|
170
|
+
actions.setSubmitting(false);
|
|
171
|
+
},
|
|
172
|
+
// Optionally inject Teletraan1 (codex display) callback function
|
|
173
|
+
onFinish: () => {
|
|
174
|
+
console.log("xForm submission complete.");
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<div className="cyberdyne-store-portal">
|
|
180
|
+
{xFormElement}
|
|
181
|
+
</div>
|
|
182
|
+
);
|
|
183
|
+
};
|
|
184
|
+
```
|
|
60
185
|
</li>
|
|
61
186
|
|
|
62
187
|
<li><strong>🏗️Builder Object Pattern</strong></br>
|
|
63
188
|
<p align="justify">Method chaining offers a modern, fluent alternative to static JSON object configuration that elevates the developer experience (DX) by enabling rapid form creation using intuitive method chains that are human-readable and generate type-safe xForm schema definitions automatically.</p>
|
|
64
189
|
|
|
65
190
|
```javascript
|
|
66
|
-
|
|
67
|
-
|
|
191
|
+
import React from 'react';
|
|
192
|
+
import { VectorSigma } from './VectorSigma';
|
|
193
|
+
|
|
194
|
+
export const VΣCodexForm = () => {
|
|
195
|
+
// Initialize an empty xForm
|
|
196
|
+
const xFormBuilder = new VectorSigma();
|
|
197
|
+
|
|
198
|
+
// Chain object methods to build xForm schema
|
|
199
|
+
// ---------------------------------------------------------
|
|
200
|
+
// METHOD A: addSection(xFormSectionSchema{})
|
|
201
|
+
// METHOD B: createSection() * addQueryToSection()
|
|
202
|
+
// ---------------------------------------------------------
|
|
203
|
+
const xFormElement = xFormBuilder
|
|
204
|
+
.setUUID('ai-agent-007')
|
|
205
|
+
.setName('New User Onboarding')
|
|
206
|
+
// setBrand(color, logoUrl?, logoPosition?)
|
|
207
|
+
.setBrand(
|
|
208
|
+
'#800020', // Brand (i.e. Primary) color
|
|
209
|
+
'https://www.example.com/brandLogo.jpeg', // Brand Logo URL
|
|
210
|
+
'center' // Brand Logo alignment
|
|
211
|
+
)
|
|
212
|
+
.createSection('personal-info', 'Personal Information', 'user')
|
|
213
|
+
.addQueryToSection('personal-info', {
|
|
214
|
+
queryId: 101,
|
|
215
|
+
inputType: 'text-input',
|
|
216
|
+
inputAlias: 'firstName',
|
|
217
|
+
inputLabel: 'First Name',
|
|
218
|
+
inputPlaceholder: 'Enter your first name',
|
|
219
|
+
inputWidth: 6,
|
|
220
|
+
newRow: true,
|
|
221
|
+
isRequired: true,
|
|
222
|
+
errorText: 'First name is required'
|
|
223
|
+
})
|
|
224
|
+
.createSection('address-info', 'Address Info', 'home')
|
|
225
|
+
.addQueryToSection('address-info', {
|
|
226
|
+
queryId: 102,
|
|
227
|
+
inputType: 'password-input',
|
|
228
|
+
inputAlias: 'securityCode',
|
|
229
|
+
inputLabel: 'Secure Passcode',
|
|
230
|
+
inputWidth: 6,
|
|
231
|
+
newRow: true,
|
|
232
|
+
isRequired: true,
|
|
233
|
+
errorText: 'Security code is required'
|
|
234
|
+
})
|
|
235
|
+
.addSection({
|
|
236
|
+
sectionId: "shipping-info",
|
|
237
|
+
title: "Shipping Address",
|
|
238
|
+
icon: "paperplane",
|
|
239
|
+
queries: [
|
|
240
|
+
{
|
|
241
|
+
queryId: 103,
|
|
242
|
+
inputType: "text-input",
|
|
243
|
+
inputAlias: "deliveryAddress",
|
|
244
|
+
inputLabel: "Home Address",
|
|
245
|
+
inputWidth: 9,
|
|
246
|
+
newRow: false,
|
|
247
|
+
isRequired: true,
|
|
248
|
+
errorText: 'Address is required for shipping'
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
})
|
|
252
|
+
.render({
|
|
253
|
+
displayMode: 'codex',
|
|
254
|
+
readOnlyMode: false,
|
|
255
|
+
// Optionally inject Teletraan1 (codex display) callback
|
|
256
|
+
onFinish: () => {
|
|
257
|
+
console.log("xForm submission complete.");
|
|
258
|
+
}
|
|
259
|
+
// Optionally inject VectorSigma global callback
|
|
260
|
+
onSubmit: async (values, actions, instance) => {
|
|
261
|
+
console.log("Submitting to API...", values);
|
|
262
|
+
try {
|
|
263
|
+
await fetch('/api/users/onboard', {
|
|
264
|
+
method: 'POST',
|
|
265
|
+
body: JSON.stringify(values)
|
|
266
|
+
});
|
|
267
|
+
alert("VΣ has come to...");
|
|
268
|
+
actions.submitForm();
|
|
269
|
+
actions.resetForm();
|
|
270
|
+
} catch (error) {
|
|
271
|
+
console.error("xForm submission failed", error);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
return (
|
|
277
|
+
<div className="x-form-container">
|
|
278
|
+
{xFormElement}
|
|
279
|
+
</div>
|
|
280
|
+
);
|
|
281
|
+
};
|
|
68
282
|
```
|
|
69
283
|
</li>
|
|
70
284
|
|
|
71
285
|
<li><strong>🛡️Input Validation</strong></br>
|
|
72
|
-
<p align="justify">Declarative schema (JSON)
|
|
286
|
+
<p align="justify">Declarative schema (JSON) <code>isRequired</code> and <code>errorText</code> attributes facilitate a validation engine that is comprehensive, accessible and easy to maintain. <code>onChange()</code>, <code>onBlur()</code> input event control state updates, errors and <code>values</code> are handled automatically. <code>onSubmit()</code> handler is automatically blocked if the input vs. validation schema is invalid.</p>
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
const xFormElement = xFormBuilder
|
|
290
|
+
.setUUID('kaiju-zaibatsu-101011')
|
|
291
|
+
.setName('Monaco Smart Road User Registration')
|
|
292
|
+
.setBrand(
|
|
293
|
+
'#800020',
|
|
294
|
+
'https://www.example.com/brandLogo.jpeg',
|
|
295
|
+
'right'
|
|
296
|
+
)
|
|
297
|
+
.createSection('vehicle-info', 'Vehicle Information', 'avatar')
|
|
298
|
+
.addQueryToSection('vehicle-info', {
|
|
299
|
+
queryId: 1,
|
|
300
|
+
inputType: 'text-input',
|
|
301
|
+
inputAlias: 'vehicleRegistration',
|
|
302
|
+
inputLabel: 'Vehicle Registration Number',
|
|
303
|
+
inputPlaceholder: 'Enter your vehicle registration number',
|
|
304
|
+
inputWidth: 7,
|
|
305
|
+
newRow: true,
|
|
306
|
+
isRequired: true, // Specifies if input validation required
|
|
307
|
+
errorText: 'A vehicle registration number is required' // Specifies errorText rendered when isRequired and validation fails
|
|
308
|
+
})
|
|
309
|
+
```
|
|
73
310
|
</li>
|
|
74
311
|
|
|
75
312
|
<li><strong>🧠Form State Management</strong></br>
|
|
76
313
|
<p align="justify">Leveraged Formik for robust React state management and Yup for declarative schema validation to adhere strictly to the standard React form lifecycle, ensuring compatibility with Redux DevTools & standard debugging workflows.</p>
|
|
314
|
+
|
|
315
|
+
```javascript
|
|
316
|
+
import React from 'react';
|
|
317
|
+
import { useVectorSigma } from './hooks/useVectorSigma';
|
|
318
|
+
|
|
319
|
+
const xFormBuilder = useVectorSigma(apiXFormData);
|
|
320
|
+
.setName('VΣ Robot Activation')
|
|
321
|
+
.setBrand("brandHexColor", "www.exampleurl.com/logoimage.png", 'center')
|
|
322
|
+
return xFormBuilder.render({
|
|
323
|
+
displayMode: 'codex',
|
|
324
|
+
readOnlyMode: false,
|
|
325
|
+
// Access 'values', 'actions' and 'instance' object(s) in global onSubmit callback function
|
|
326
|
+
// 'instance' :: { errors, statusCode, isSubmitting, timeCreated, timeInProgress, timeSubmitted, formObject }
|
|
327
|
+
onSubmit: async (values, actions, instance) => {
|
|
328
|
+
|
|
329
|
+
console.log("VΣ User Email:", values.emailAddress);
|
|
330
|
+
console.log("VΣ Robot Serial Number:", values.serialNumber);
|
|
331
|
+
const timeTakenMs = (instance.timeSubmitted || Date.now()) - instance.timeCreated;
|
|
332
|
+
console.log(`VΣ User finished the xForm in ${timeTakenMs / 1000} seconds.`);
|
|
333
|
+
console.log(`Extant xForm Status:`, instance.statusCode);
|
|
334
|
+
console.log(`Extant xForm object:`, instance.formObject);
|
|
335
|
+
// Initiate Promise or API HTTP POST
|
|
336
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
337
|
+
alert("VΣ Robot Activated!");
|
|
338
|
+
actions.resetForm();
|
|
339
|
+
}
|
|
340
|
+
})
|
|
341
|
+
```
|
|
77
342
|
</li>
|
|
78
343
|
|
|
79
344
|
<li><strong>🎨Theming Extensibilty</strong></br>
|