@pixelated-tech/components 3.2.14 → 3.3.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/README.COMPONENTS.md +289 -30
- package/README.md +36 -28
- package/dist/components/general/tab.css +105 -0
- package/dist/components/general/tab.js +26 -0
- package/dist/components/seo/metadata.components.js +0 -19
- package/dist/components/seo/metadata.functions.js +111 -0
- package/dist/components/seo/schema-blogposting.functions.js +42 -0
- package/dist/components/seo/schema-blogposting.js +0 -46
- package/dist/components/seo/sitemap.js +1 -1
- package/dist/components/shoppingcart/shoppingcart.components.js +4 -4
- package/dist/components/sitebuilder/config/ConfigBuilder.css +266 -0
- package/dist/components/sitebuilder/config/ConfigBuilder.js +221 -0
- package/dist/components/{pagebuilder → sitebuilder}/form/form.css +55 -34
- package/dist/components/sitebuilder/form/formbuilder.js +106 -0
- package/dist/components/sitebuilder/form/formcomponents.js +356 -0
- package/dist/components/sitebuilder/form/formengine.js +82 -0
- package/dist/components/{pagebuilder/form/form.js → sitebuilder/form/formextractor.js} +10 -211
- package/dist/components/sitebuilder/form/formutils.js +206 -0
- package/dist/components/sitebuilder/form/formvalidator.js +123 -0
- package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentPropertiesForm.js +1 -1
- package/dist/components/{pagebuilder → sitebuilder/page}/components/PageBuilderUI.js +2 -2
- package/dist/components/{pagebuilder → sitebuilder/page}/components/PageEngine.js +1 -1
- package/dist/components/sitebuilder/page/documentation/api-examples/save-route-example.js +37 -0
- package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentMap.js +3 -3
- package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentMetadata.js +2 -2
- package/dist/components/{pagebuilder → sitebuilder/page}/lib/pageStorageContentful.js +2 -2
- package/dist/components/sitebuilder/page/lib/pageStorageTypes.js +1 -0
- package/dist/data/form.json +18 -18
- package/dist/data/shipping.to.json +9 -9
- package/dist/data/siteinfo-form.json +200 -0
- package/dist/index.js +29 -21
- package/dist/index.server.js +24 -17
- package/dist/types/components/general/semantic.d.ts +3 -3
- package/dist/types/components/general/tab.d.ts +18 -0
- package/dist/types/components/general/tab.d.ts.map +1 -0
- package/dist/types/components/seo/metadata.components.d.ts +0 -17
- package/dist/types/components/seo/metadata.components.d.ts.map +1 -1
- package/dist/types/components/seo/{metadata.d.ts → metadata.functions.d.ts} +15 -1
- package/dist/types/components/seo/metadata.functions.d.ts.map +1 -0
- package/dist/types/components/seo/schema-blogposting.d.ts +1 -25
- package/dist/types/components/seo/schema-blogposting.d.ts.map +1 -1
- package/dist/types/components/seo/schema-blogposting.functions.d.ts +26 -0
- package/dist/types/components/seo/schema-blogposting.functions.d.ts.map +1 -0
- package/dist/types/components/seo/sitemap.d.ts.map +1 -1
- package/dist/types/components/shoppingcart/shoppingcart.components.d.ts +1 -1
- package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts +86 -0
- package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/form/formbuilder.d.ts +11 -0
- package/dist/types/components/sitebuilder/form/formbuilder.d.ts.map +1 -0
- package/dist/types/components/{pagebuilder → sitebuilder}/form/formcomponents.d.ts +12 -16
- package/dist/types/components/sitebuilder/form/formcomponents.d.ts.map +1 -0
- package/dist/types/components/{pagebuilder/form/form.submit.d.ts → sitebuilder/form/formemailer.d.ts} +1 -1
- package/dist/types/components/sitebuilder/form/formemailer.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/form/formengine.d.ts +14 -0
- package/dist/types/components/sitebuilder/form/formengine.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/form/formextractor.d.ts +25 -0
- package/dist/types/components/sitebuilder/form/formextractor.d.ts.map +1 -0
- package/dist/types/components/{pagebuilder/form/formvalidations.d.ts → sitebuilder/form/formfieldvalidations.d.ts} +1 -1
- package/dist/types/components/sitebuilder/form/formfieldvalidations.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/form/formtypes.d.ts +66 -0
- package/dist/types/components/sitebuilder/form/formtypes.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/form/formutils.d.ts +20 -0
- package/dist/types/components/sitebuilder/form/formutils.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/form/formvalidator.d.ts +20 -0
- package/dist/types/components/sitebuilder/form/formvalidator.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/components/ComponentPropertiesForm.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/components/ComponentSelector.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/components/ComponentTree.d.ts.map +1 -0
- package/dist/types/components/{pagebuilder → sitebuilder/page}/components/PageBuilderUI.d.ts +1 -1
- package/dist/types/components/sitebuilder/page/components/PageBuilderUI.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/components/PageEngine.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/components/SaveLoadSection.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/documentation/api-examples/save-route-example.d.ts +6 -0
- package/dist/types/components/sitebuilder/page/documentation/api-examples/save-route-example.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/lib/componentGeneration.d.ts.map +1 -0
- package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentMap.d.ts +3 -3
- package/dist/types/components/sitebuilder/page/lib/componentMap.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/lib/componentMetadata.d.ts.map +1 -0
- package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageContentful.d.ts +1 -1
- package/dist/types/components/sitebuilder/page/lib/pageStorageContentful.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/lib/pageStorageLocal.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/lib/pageStorageTypes.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/lib/propTypeIntrospection.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/lib/types.d.ts.map +1 -0
- package/dist/types/components/sitebuilder/page/lib/usePageBuilder.d.ts.map +1 -0
- package/dist/types/index.d.ts +29 -20
- package/dist/types/index.server.d.ts +23 -16
- package/dist/types/stories/general/tab.stories.d.ts +45 -0
- package/dist/types/stories/general/tab.stories.d.ts.map +1 -0
- package/dist/types/stories/seo/seo.metadata.stories.d.ts +1 -1
- package/dist/types/stories/seo/seo.metadata.stories.d.ts.map +1 -1
- package/dist/types/stories/sitebuilder/configbuilder.stories.d.ts +48 -0
- package/dist/types/stories/sitebuilder/configbuilder.stories.d.ts.map +1 -0
- package/dist/types/stories/{pagebuilder → sitebuilder}/form-builder.stories.d.ts +1 -1
- package/dist/types/stories/sitebuilder/form-builder.stories.d.ts.map +1 -0
- package/dist/types/stories/{pagebuilder → sitebuilder}/form-engine.stories.d.ts +1 -1
- package/dist/types/stories/sitebuilder/form-engine.stories.d.ts.map +1 -0
- package/dist/types/stories/{pagebuilder → sitebuilder}/form-extractor.stories.d.ts +1 -1
- package/dist/types/stories/sitebuilder/form-extractor.stories.d.ts.map +1 -0
- package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.stories.d.ts +1 -1
- package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.stories.d.ts.map +1 -1
- package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.usageguide.stories.d.ts +1 -1
- package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.usageguide.stories.d.ts.map +1 -1
- package/dist/types/stories/{pagebuilder → sitebuilder}/pageengine.stories.d.ts +1 -1
- package/dist/types/stories/{pagebuilder → sitebuilder}/pageengine.stories.d.ts.map +1 -1
- package/dist/types/tests/configbuilder.test.d.ts +2 -0
- package/dist/types/tests/configbuilder.test.d.ts.map +1 -0
- package/dist/types/tests/tab.test.d.ts +2 -0
- package/dist/types/tests/tab.test.d.ts.map +1 -0
- package/package.json +5 -4
- package/dist/components/pagebuilder/form/formcomponents.js +0 -359
- package/dist/components/seo/metadata.js +0 -108
- package/dist/types/components/pagebuilder/components/ComponentPropertiesForm.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/components/ComponentSelector.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/components/ComponentTree.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/components/PageBuilderUI.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/components/PageEngine.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/components/SaveLoadSection.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/form/form.d.ts +0 -46
- package/dist/types/components/pagebuilder/form/form.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/form/form.submit.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/form/formcomponents.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/form/formvalidations.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/lib/componentGeneration.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/lib/componentMap.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/lib/componentMetadata.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/lib/pageStorageContentful.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/lib/pageStorageLocal.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/lib/pageStorageTypes.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/lib/propTypeIntrospection.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/lib/types.d.ts.map +0 -1
- package/dist/types/components/pagebuilder/lib/usePageBuilder.d.ts.map +0 -1
- package/dist/types/components/seo/metadata.d.ts.map +0 -1
- package/dist/types/stories/pagebuilder/form-builder.stories.d.ts.map +0 -1
- package/dist/types/stories/pagebuilder/form-engine.stories.d.ts.map +0 -1
- package/dist/types/stories/pagebuilder/form-extractor.stories.d.ts.map +0 -1
- /package/dist/components/{pagebuilder/form/form.submit.js → sitebuilder/form/formemailer.js} +0 -0
- /package/dist/components/{pagebuilder/form/formvalidations.js → sitebuilder/form/formfieldvalidations.js} +0 -0
- /package/dist/components/{pagebuilder/lib/pageStorageTypes.js → sitebuilder/form/formtypes.js} +0 -0
- /package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentSelector.js +0 -0
- /package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentTree.js +0 -0
- /package/dist/components/{pagebuilder → sitebuilder/page}/components/SaveLoadSection.js +0 -0
- /package/dist/components/{pagebuilder → sitebuilder/page}/components/pagebuilder.scss +0 -0
- /package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentGeneration.js +0 -0
- /package/dist/components/{pagebuilder → sitebuilder/page}/lib/pageStorageLocal.js +0 -0
- /package/dist/components/{pagebuilder → sitebuilder/page}/lib/propTypeIntrospection.js +0 -0
- /package/dist/components/{pagebuilder → sitebuilder/page}/lib/types.js +0 -0
- /package/dist/components/{pagebuilder → sitebuilder/page}/lib/usePageBuilder.js +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentPropertiesForm.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentSelector.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentTree.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/PageEngine.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/SaveLoadSection.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentGeneration.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentMetadata.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageLocal.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageTypes.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/propTypeIntrospection.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/types.d.ts +0 -0
- /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/usePageBuilder.d.ts +0 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// Shared utility functions for form components
|
|
2
|
+
import { generateKey, capitalize, attributeMap } from '../../utilities/functions';
|
|
3
|
+
export const debug = false;
|
|
4
|
+
/**
|
|
5
|
+
* Maps input type to form component name
|
|
6
|
+
*/
|
|
7
|
+
export function mapTypeToComponent(myType) {
|
|
8
|
+
if (debug)
|
|
9
|
+
console.log("Mapping Type Field to Component");
|
|
10
|
+
let myComponent = (["button"].includes(myType)) ? 'FormButton' :
|
|
11
|
+
(["checkbox"].includes(myType)) ? 'FormCheckbox' :
|
|
12
|
+
(["datalist"].includes(myType)) ? 'FormDataList' :
|
|
13
|
+
(["radio"].includes(myType)) ? 'FormRadio' :
|
|
14
|
+
(["select"].includes(myType)) ? 'FormSelect' :
|
|
15
|
+
(["textarea"].includes(myType)) ? 'FormTextarea' :
|
|
16
|
+
"FormInput";
|
|
17
|
+
return myComponent;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generates field JSON for form building
|
|
21
|
+
*/
|
|
22
|
+
export function generateFieldJSON(component, type) {
|
|
23
|
+
const form = {};
|
|
24
|
+
form.fields = [];
|
|
25
|
+
// Common fields for all components
|
|
26
|
+
const commonFields = [
|
|
27
|
+
{
|
|
28
|
+
component: 'FormInput',
|
|
29
|
+
props: {
|
|
30
|
+
label: 'ID : ',
|
|
31
|
+
name: 'id',
|
|
32
|
+
id: 'id',
|
|
33
|
+
type: 'text',
|
|
34
|
+
required: true
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
component: 'FormInput',
|
|
39
|
+
props: {
|
|
40
|
+
label: 'Label : ',
|
|
41
|
+
name: 'label',
|
|
42
|
+
id: 'label',
|
|
43
|
+
type: 'text'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
// Type-specific fields
|
|
48
|
+
let typeSpecificFields = [];
|
|
49
|
+
if (component === 'FormSelect') {
|
|
50
|
+
typeSpecificFields = [
|
|
51
|
+
{
|
|
52
|
+
component: 'FormTextarea',
|
|
53
|
+
props: {
|
|
54
|
+
label: 'Options (JSON) : ',
|
|
55
|
+
name: 'options',
|
|
56
|
+
id: 'options',
|
|
57
|
+
rows: 5,
|
|
58
|
+
placeholder: '[{"value": "option1", "text": "Option 1"}, {"value": "option2", "text": "Option 2"}]'
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
else if (component === 'FormRadio' || component === 'FormCheckbox') {
|
|
64
|
+
typeSpecificFields = [
|
|
65
|
+
{
|
|
66
|
+
component: 'FormInput',
|
|
67
|
+
props: {
|
|
68
|
+
label: 'Value : ',
|
|
69
|
+
name: 'value',
|
|
70
|
+
id: 'value',
|
|
71
|
+
type: 'text'
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
component: 'FormTextarea',
|
|
76
|
+
props: {
|
|
77
|
+
label: 'Options (JSON) : ',
|
|
78
|
+
name: 'options',
|
|
79
|
+
id: 'options',
|
|
80
|
+
rows: 5,
|
|
81
|
+
placeholder: '[{"value": "option1", "text": "Option 1"}, {"value": "option2", "text": "Option 2"}]'
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
typeSpecificFields = [
|
|
88
|
+
{
|
|
89
|
+
component: 'FormInput',
|
|
90
|
+
props: {
|
|
91
|
+
label: 'Type : ',
|
|
92
|
+
name: 'type',
|
|
93
|
+
id: 'type',
|
|
94
|
+
type: 'text',
|
|
95
|
+
value: type,
|
|
96
|
+
list: 'inputTypes'
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
component: 'FormInput',
|
|
101
|
+
props: {
|
|
102
|
+
label: 'Placeholder : ',
|
|
103
|
+
name: 'placeholder',
|
|
104
|
+
id: 'placeholder',
|
|
105
|
+
type: 'text'
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
component: 'FormInput',
|
|
110
|
+
props: {
|
|
111
|
+
label: 'Value : ',
|
|
112
|
+
name: 'value',
|
|
113
|
+
id: 'value',
|
|
114
|
+
type: 'text'
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
// Add required field
|
|
120
|
+
const requiredField = {
|
|
121
|
+
component: 'FormCheckbox',
|
|
122
|
+
props: {
|
|
123
|
+
label: 'Required : ',
|
|
124
|
+
name: 'required',
|
|
125
|
+
id: 'required',
|
|
126
|
+
value: 'required'
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
// Add validation field
|
|
130
|
+
const validationField = {
|
|
131
|
+
component: 'FormInput',
|
|
132
|
+
props: {
|
|
133
|
+
label: 'Validate : ',
|
|
134
|
+
name: 'validate',
|
|
135
|
+
id: 'validate',
|
|
136
|
+
type: 'text',
|
|
137
|
+
list: 'validationTypes',
|
|
138
|
+
placeholder: 'isValidEmailAddress, isValidUrl, etc.'
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
// Combine all fields
|
|
142
|
+
let i = 0;
|
|
143
|
+
[...commonFields, ...typeSpecificFields, requiredField, validationField].forEach(field => {
|
|
144
|
+
form.fields[i] = field;
|
|
145
|
+
i++;
|
|
146
|
+
});
|
|
147
|
+
// Add submit button
|
|
148
|
+
const addButton = {
|
|
149
|
+
component: 'FormButton',
|
|
150
|
+
props: {
|
|
151
|
+
label: 'Add ' + component,
|
|
152
|
+
type: 'submit',
|
|
153
|
+
id: 'Add ' + component,
|
|
154
|
+
text: 'Add ' + component
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
form.fields[i] = addButton;
|
|
158
|
+
return form;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Generates type selection field for form builder
|
|
162
|
+
*/
|
|
163
|
+
export function generateTypeField() {
|
|
164
|
+
const form = {};
|
|
165
|
+
const typeField = {
|
|
166
|
+
component: 'FormInput',
|
|
167
|
+
props: {
|
|
168
|
+
label: 'Type : ',
|
|
169
|
+
name: 'type',
|
|
170
|
+
id: 'type',
|
|
171
|
+
type: 'text',
|
|
172
|
+
list: 'inputTypes'
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
const addButton = {
|
|
176
|
+
component: 'FormButton',
|
|
177
|
+
props: {
|
|
178
|
+
label: 'Build',
|
|
179
|
+
type: 'submit',
|
|
180
|
+
id: 'build',
|
|
181
|
+
text: '=== Build ==='
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
form.fields = [typeField, addButton];
|
|
185
|
+
return form;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Converts numeric string props to numbers
|
|
189
|
+
*/
|
|
190
|
+
export function convertNumericProps(props) {
|
|
191
|
+
const numericProps = ['maxLength', 'minLength', 'rows', 'cols', 'size', 'step'];
|
|
192
|
+
numericProps.forEach(prop => {
|
|
193
|
+
if (props[prop] !== undefined &&
|
|
194
|
+
props[prop] !== null &&
|
|
195
|
+
props[prop] !== '') {
|
|
196
|
+
if (typeof props[prop] === 'string') {
|
|
197
|
+
const num = Number(props[prop]);
|
|
198
|
+
if (!isNaN(num)) {
|
|
199
|
+
props[prop] = num;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
// Re-export utilities from main utilities file for convenience
|
|
206
|
+
export { generateKey, capitalize, attributeMap };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useState, useCallback } from 'react';
|
|
3
|
+
import * as FVF from './formfieldvalidations';
|
|
4
|
+
/**
|
|
5
|
+
* Centralized field validation service
|
|
6
|
+
*/
|
|
7
|
+
export async function validateField(fieldProps, event) {
|
|
8
|
+
const errors = [];
|
|
9
|
+
let isValid = true;
|
|
10
|
+
// 1. Field-specific validation (e.g., isValidEmailAddress, isValidUrl, etc.)
|
|
11
|
+
if (fieldProps.validate && typeof fieldProps.validate === "string" && fieldProps.validate in FVF) {
|
|
12
|
+
const fieldValid = FVF[fieldProps.validate](event.target);
|
|
13
|
+
if (!fieldValid) {
|
|
14
|
+
isValid = false;
|
|
15
|
+
errors.push(`${fieldProps.validate} validation failed`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// 2. Parent validation (for grouped/nested fields)
|
|
19
|
+
if (fieldProps.parent?.validate && typeof fieldProps.parent.validate === "string" && fieldProps.parent.validate in FVF) {
|
|
20
|
+
const parentValid = FVF[fieldProps.parent.validate](event.target);
|
|
21
|
+
if (!parentValid) {
|
|
22
|
+
isValid = false;
|
|
23
|
+
errors.push(`Parent ${fieldProps.parent.validate} validation failed`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// 3. HTML5 required validation
|
|
27
|
+
if (fieldProps.required) {
|
|
28
|
+
const requiredValid = event.target.checkValidity();
|
|
29
|
+
if (!requiredValid) {
|
|
30
|
+
isValid = false;
|
|
31
|
+
errors.push('Required field validation failed');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// 4. Required not empty check
|
|
35
|
+
if (fieldProps.required && !event.target.value) {
|
|
36
|
+
isValid = false;
|
|
37
|
+
errors.push('Field cannot be empty');
|
|
38
|
+
}
|
|
39
|
+
// 5. Custom validation rules can be added here
|
|
40
|
+
// Example: minimum length, maximum length, pattern matching, etc.
|
|
41
|
+
return { isValid, errors };
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Form validation context for managing form-wide validation state
|
|
45
|
+
*/
|
|
46
|
+
const FormValidationContext = createContext(null);
|
|
47
|
+
export function useFormValidation() {
|
|
48
|
+
const context = useContext(FormValidationContext);
|
|
49
|
+
if (!context) {
|
|
50
|
+
throw new Error('useFormValidation must be used within FormValidationProvider');
|
|
51
|
+
}
|
|
52
|
+
return context;
|
|
53
|
+
}
|
|
54
|
+
export function FormValidationProvider({ children }) {
|
|
55
|
+
const [fieldValidity, setFieldValidity] = useState({});
|
|
56
|
+
const [fieldErrors, setFieldErrors] = useState({});
|
|
57
|
+
const validateField = useCallback((fieldId, isValid, errors) => {
|
|
58
|
+
setFieldValidity(prev => ({ ...prev, [fieldId]: isValid }));
|
|
59
|
+
setFieldErrors(prev => ({ ...prev, [fieldId]: errors }));
|
|
60
|
+
}, []);
|
|
61
|
+
const validateAllFields = useCallback(() => {
|
|
62
|
+
return Object.values(fieldValidity).every(valid => valid === true);
|
|
63
|
+
}, [fieldValidity]);
|
|
64
|
+
const resetValidation = useCallback(() => {
|
|
65
|
+
setFieldValidity({});
|
|
66
|
+
setFieldErrors({});
|
|
67
|
+
}, []);
|
|
68
|
+
const isFormValid = Object.values(fieldValidity).every(valid => valid === true);
|
|
69
|
+
const value = {
|
|
70
|
+
fieldValidity,
|
|
71
|
+
fieldErrors,
|
|
72
|
+
isFormValid,
|
|
73
|
+
validateField,
|
|
74
|
+
validateAllFields,
|
|
75
|
+
resetValidation
|
|
76
|
+
};
|
|
77
|
+
return (_jsx(FormValidationContext.Provider, { value: value, children: children }));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Cross-field validation functions
|
|
81
|
+
*/
|
|
82
|
+
export function validatePasswordMatch(formData) {
|
|
83
|
+
const password = formData.password?.value;
|
|
84
|
+
const confirm = formData.passwordConfirm?.value;
|
|
85
|
+
if (!password || !confirm) {
|
|
86
|
+
return { isValid: true, errors: [] }; // Not required fields
|
|
87
|
+
}
|
|
88
|
+
const isValid = password === confirm;
|
|
89
|
+
return {
|
|
90
|
+
isValid,
|
|
91
|
+
errors: isValid ? [] : ['Passwords do not match']
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export function validateAgeRestriction(formData) {
|
|
95
|
+
const age = parseInt(formData.age?.value);
|
|
96
|
+
const hasParentalConsent = formData.parentalConsent?.value === 'yes';
|
|
97
|
+
if (isNaN(age) || age >= 13) {
|
|
98
|
+
return { isValid: true, errors: [] };
|
|
99
|
+
}
|
|
100
|
+
const isValid = hasParentalConsent;
|
|
101
|
+
return {
|
|
102
|
+
isValid,
|
|
103
|
+
errors: isValid ? [] : ['Parental consent required for users under 13']
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Form-level validation orchestrator
|
|
108
|
+
*/
|
|
109
|
+
export function validateFormLevel(formData, customValidators = []) {
|
|
110
|
+
const allErrors = [];
|
|
111
|
+
let isValid = true;
|
|
112
|
+
// Run custom cross-field validations
|
|
113
|
+
const defaultValidators = [validatePasswordMatch, validateAgeRestriction];
|
|
114
|
+
const allValidators = [...defaultValidators, ...customValidators];
|
|
115
|
+
for (const validator of allValidators) {
|
|
116
|
+
const result = validator(formData);
|
|
117
|
+
if (!result.isValid) {
|
|
118
|
+
isValid = false;
|
|
119
|
+
allErrors.push(...result.errors);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { isValid, errors: allErrors };
|
|
123
|
+
}
|
package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentPropertiesForm.js
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
// import { PageSectionHeader } from '../../general/pixelated.headers';
|
|
4
|
-
import { FormEngine } from '
|
|
4
|
+
import { FormEngine } from '../../form/formengine';
|
|
5
5
|
/**
|
|
6
6
|
* ComponentPropertiesForm - Displays the component properties form
|
|
7
7
|
* Shows FormEngine when component is selected, placeholder otherwise
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import { PageSectionHeader } from '
|
|
4
|
+
import { PageSectionHeader } from '../../../general/semantic';
|
|
5
5
|
import { usePageBuilder } from '../lib/usePageBuilder';
|
|
6
6
|
import { ComponentSelector } from '../components/ComponentSelector';
|
|
7
7
|
import { ComponentPropertiesForm } from '../components/ComponentPropertiesForm';
|
|
8
8
|
import { PageEngine } from '../components/PageEngine';
|
|
9
9
|
import { SaveLoadSection } from '../components/SaveLoadSection';
|
|
10
|
-
import "
|
|
10
|
+
import "../../../../css/pixelated.global.css";
|
|
11
11
|
import './pagebuilder.scss';
|
|
12
12
|
/**
|
|
13
13
|
* PageBuilderUI - Main orchestrator component
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
|
-
import { generateKey } from '
|
|
4
|
+
import { generateKey } from '../../../utilities/functions';
|
|
5
5
|
import { componentMap, layoutComponents } from '../lib/componentMap';
|
|
6
6
|
import './pagebuilder.scss';
|
|
7
7
|
/**
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
// Choose ONE of these imports:
|
|
3
|
+
// Option 1: File-based storage
|
|
4
|
+
import { savePage } from '../../lib/pageStorageLocal';
|
|
5
|
+
// Option 2: Contentful storage
|
|
6
|
+
// import { savePage } from '@pixelated-tech/components/server';
|
|
7
|
+
// import type { ContentfulConfig } from '@pixelated-tech/components/server';
|
|
8
|
+
export async function POST(request) {
|
|
9
|
+
try {
|
|
10
|
+
const body = await request.json();
|
|
11
|
+
const { name, data } = body;
|
|
12
|
+
if (!name || !data) {
|
|
13
|
+
return NextResponse.json({
|
|
14
|
+
success: false,
|
|
15
|
+
message: 'Name and data are required'
|
|
16
|
+
}, { status: 400 });
|
|
17
|
+
}
|
|
18
|
+
// ===== OPTION 1: File-based storage =====
|
|
19
|
+
const result = await savePage(name, data);
|
|
20
|
+
// ===== OPTION 2: Contentful storage =====
|
|
21
|
+
// ===== OPTION 2: Contentful storage (recommended when using the unified PIXELATED config blob) =====
|
|
22
|
+
// The app reads the unified config on the server via `getFullPixelatedConfig()` which
|
|
23
|
+
// sources values from `PIXELATED_CONFIG_JSON` or `PIXELATED_CONFIG_B64`.
|
|
24
|
+
// Example (server-side):
|
|
25
|
+
// import { getFullPixelatedConfig } from '@pixelated-tech/components/server';
|
|
26
|
+
// const cfg = getFullPixelatedConfig();
|
|
27
|
+
// const contentfulConfig = cfg.contentful;
|
|
28
|
+
// const result = await savePage(name, data, contentfulConfig);
|
|
29
|
+
return NextResponse.json(result);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return NextResponse.json({
|
|
33
|
+
success: false,
|
|
34
|
+
message: `Invalid request: ${error}`
|
|
35
|
+
}, { status: 400 });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { PageTitleHeader, PageSectionHeader } from "
|
|
2
|
-
import { Callout } from "
|
|
3
|
-
import { PageSection, PageGridItem, PageFlexItem } from "
|
|
1
|
+
import { PageTitleHeader, PageSectionHeader } from "../../../general/semantic";
|
|
2
|
+
import { Callout } from "../../../callout/callout";
|
|
3
|
+
import { PageSection, PageGridItem, PageFlexItem } from "../../../general/semantic";
|
|
4
4
|
/**
|
|
5
5
|
* Component registry and constants
|
|
6
6
|
*/
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* used in PropTypes, generate TypeScript types via InferProps, and provide
|
|
7
7
|
* runtime values for form generation.
|
|
8
8
|
*/
|
|
9
|
-
import { variants, shapes, layouts, directions } from "
|
|
10
|
-
import { layoutTypes, autoFlowValues, flexDirections, flexWraps, justifyContentValues, alignItemsValues } from "
|
|
9
|
+
import { variants, shapes, layouts, directions } from "../../../callout/callout";
|
|
10
|
+
import { layoutTypes, autoFlowValues, flexDirections, flexWraps, justifyContentValues, alignItemsValues } from "../../../general/semantic";
|
|
11
11
|
export const componentMetadata = {
|
|
12
12
|
'Callout': {
|
|
13
13
|
variant: {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Uses generic Contentful management functions with PageBuilder-specific logic
|
|
5
5
|
*/
|
|
6
|
-
import { createEntry, updateEntry, deleteEntry, searchEntriesByField } from '
|
|
7
|
-
import { getContentfulEntriesByType } from '
|
|
6
|
+
import { createEntry, updateEntry, deleteEntry, searchEntriesByField } from '../../../cms/contentful.management';
|
|
7
|
+
import { getContentfulEntriesByType } from '../../../cms/contentful.delivery';
|
|
8
8
|
const CONTENT_TYPE = 'page';
|
|
9
9
|
/**
|
|
10
10
|
* Validate page name format
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/data/form.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"defaultValue": "",
|
|
9
9
|
"autoComplete": "honorific-prefix",
|
|
10
10
|
"multiple": null,
|
|
11
|
-
"required":
|
|
11
|
+
"required": true,
|
|
12
12
|
"display": "horizontal",
|
|
13
13
|
"label": "Title : ",
|
|
14
14
|
"options": [
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"autoComplete": "given-name",
|
|
32
32
|
"size": "40",
|
|
33
33
|
"display": "horizontal",
|
|
34
|
-
"required":
|
|
34
|
+
"required": true,
|
|
35
35
|
"label": "First Name : ",
|
|
36
36
|
"tooltip": "Please type in your First Name"
|
|
37
37
|
}
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"autoComplete": "family-name",
|
|
47
47
|
"size": "40",
|
|
48
48
|
"display": "horizontal",
|
|
49
|
-
"required":
|
|
49
|
+
"required": true,
|
|
50
50
|
"label": "Last Name : "
|
|
51
51
|
}
|
|
52
52
|
},
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"autoComplete": "street-address",
|
|
61
61
|
"size": "40",
|
|
62
62
|
"display": "horizontal",
|
|
63
|
-
"required":
|
|
63
|
+
"required": true,
|
|
64
64
|
"label": "Street Address : "
|
|
65
65
|
}
|
|
66
66
|
},
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"autoComplete": "address-level2",
|
|
75
75
|
"size": "40",
|
|
76
76
|
"display": "horizontal",
|
|
77
|
-
"required":
|
|
77
|
+
"required": true,
|
|
78
78
|
"label": "City : "
|
|
79
79
|
}
|
|
80
80
|
},
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"defaultValue": ["NJ", "SC"],
|
|
88
88
|
"autoComplete": "address-level1",
|
|
89
89
|
"multiple": "multiple",
|
|
90
|
-
"required":
|
|
90
|
+
"required": true,
|
|
91
91
|
"display": "horizontal",
|
|
92
92
|
"label": "State : ",
|
|
93
93
|
"tooltip": "Please select your State",
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
"autoComplete": "postal-code",
|
|
157
157
|
"size": "40",
|
|
158
158
|
"display": "horizontal",
|
|
159
|
-
"required":
|
|
159
|
+
"required": true,
|
|
160
160
|
"label": "Zip Code : ",
|
|
161
161
|
"validate": "isValidUSZipCode"
|
|
162
162
|
}
|
|
@@ -171,7 +171,7 @@
|
|
|
171
171
|
"autoComplete": "tel",
|
|
172
172
|
"size": "40",
|
|
173
173
|
"display": "horizontal",
|
|
174
|
-
"required":
|
|
174
|
+
"required": true,
|
|
175
175
|
"label": "Phone Number : ",
|
|
176
176
|
"validate": "isValidUSPhoneNumber"
|
|
177
177
|
}
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
"autoComplete": "bday",
|
|
187
187
|
"size": "40",
|
|
188
188
|
"display": "horizontal",
|
|
189
|
-
"required":
|
|
189
|
+
"required": true,
|
|
190
190
|
"label": "Birthday : ",
|
|
191
191
|
"validate": "isValidDate"
|
|
192
192
|
}
|
|
@@ -198,7 +198,7 @@
|
|
|
198
198
|
"name": "age",
|
|
199
199
|
"defaultValue": "",
|
|
200
200
|
"multiple": null,
|
|
201
|
-
"required":
|
|
201
|
+
"required": true,
|
|
202
202
|
"display": "horizontal",
|
|
203
203
|
"label": "Age : ",
|
|
204
204
|
"options": [
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
"name": "generation",
|
|
224
224
|
"defaultValue": null,
|
|
225
225
|
"multiple": null,
|
|
226
|
-
"required":
|
|
226
|
+
"required": true,
|
|
227
227
|
"display": "horizontal",
|
|
228
228
|
"label": "Generation : ",
|
|
229
229
|
"options": [
|
|
@@ -248,7 +248,7 @@
|
|
|
248
248
|
"autoComplete": "email",
|
|
249
249
|
"size": "40",
|
|
250
250
|
"display": "horizontal",
|
|
251
|
-
"required":
|
|
251
|
+
"required": true,
|
|
252
252
|
"label": "Email Address : ",
|
|
253
253
|
"validate": "isValidEmailAddress"
|
|
254
254
|
}
|
|
@@ -261,7 +261,7 @@
|
|
|
261
261
|
"autoComplete": "sex",
|
|
262
262
|
"label": "Gender : ",
|
|
263
263
|
"display": "horizontal",
|
|
264
|
-
"required":
|
|
264
|
+
"required": true,
|
|
265
265
|
"validate": "isOneRadioSelected",
|
|
266
266
|
"tooltip": "Please select your gender",
|
|
267
267
|
"options": [
|
|
@@ -296,7 +296,7 @@
|
|
|
296
296
|
"autoComplete": "organization-title",
|
|
297
297
|
"size": "40",
|
|
298
298
|
"display": "horizontal",
|
|
299
|
-
"required":
|
|
299
|
+
"required": true,
|
|
300
300
|
"label": "Job Title : "
|
|
301
301
|
}
|
|
302
302
|
},
|
|
@@ -310,7 +310,7 @@
|
|
|
310
310
|
"autoComplete": "organization",
|
|
311
311
|
"size": "40",
|
|
312
312
|
"display": "horizontal",
|
|
313
|
-
"required":
|
|
313
|
+
"required": true,
|
|
314
314
|
"label": "Company : "
|
|
315
315
|
}
|
|
316
316
|
},
|
|
@@ -326,7 +326,7 @@
|
|
|
326
326
|
"min": "10000",
|
|
327
327
|
"max": "1000000",
|
|
328
328
|
"step": "1000",
|
|
329
|
-
"required":
|
|
329
|
+
"required": true,
|
|
330
330
|
"label": "Salary : "
|
|
331
331
|
}
|
|
332
332
|
},
|
|
@@ -339,7 +339,7 @@
|
|
|
339
339
|
"defaultValue": null,
|
|
340
340
|
"size": "40",
|
|
341
341
|
"display": "horizontal",
|
|
342
|
-
"required":
|
|
342
|
+
"required": true,
|
|
343
343
|
"label": "LinkedIn URL : ",
|
|
344
344
|
"validate": "isValidUrl"
|
|
345
345
|
}
|
|
@@ -353,7 +353,7 @@
|
|
|
353
353
|
"cols": "40",
|
|
354
354
|
"defaultValue": null,
|
|
355
355
|
"display": "horizontal",
|
|
356
|
-
"required":
|
|
356
|
+
"required": true,
|
|
357
357
|
"label": "Comments : ",
|
|
358
358
|
"tooltip": "Please enter your comments"
|
|
359
359
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"autoComplete": "name",
|
|
12
12
|
"size": "40",
|
|
13
13
|
"display": "horizontal",
|
|
14
|
-
"required":
|
|
14
|
+
"required": true,
|
|
15
15
|
"label": "Name : ",
|
|
16
16
|
"tooltip": "Please enter your First and Last Name"
|
|
17
17
|
}
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"autoComplete": "street-address",
|
|
27
27
|
"size": "40",
|
|
28
28
|
"display": "horizontal",
|
|
29
|
-
"required":
|
|
29
|
+
"required": true,
|
|
30
30
|
"label": "Street Address : ",
|
|
31
31
|
"tooltip": "Please enter your Street Address"
|
|
32
32
|
}
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"autoComplete": "address-level2",
|
|
42
42
|
"size": "40",
|
|
43
43
|
"display": "horizontal",
|
|
44
|
-
"required":
|
|
44
|
+
"required": true,
|
|
45
45
|
"label": "City : ",
|
|
46
46
|
"tooltip": "Please enter your City"
|
|
47
47
|
}
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"placeholder": "State",
|
|
56
56
|
"autoComplete": "address-level1",
|
|
57
57
|
"multiple": null,
|
|
58
|
-
"required":
|
|
58
|
+
"required": true,
|
|
59
59
|
"display": "horizontal",
|
|
60
60
|
"label": "State : ",
|
|
61
61
|
"tooltip": "Please select your State",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"autoComplete": "postal-code",
|
|
125
125
|
"size": "40",
|
|
126
126
|
"display": "horizontal",
|
|
127
|
-
"required":
|
|
127
|
+
"required": true,
|
|
128
128
|
"label": "Zip Code : ",
|
|
129
129
|
"tooltip": "Please enter your Zip Code",
|
|
130
130
|
"validate": "isValidUSZipCode"
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
"placeholder": "Country",
|
|
140
140
|
"autoComplete": "country",
|
|
141
141
|
"multiple": null,
|
|
142
|
-
"required":
|
|
142
|
+
"required": true,
|
|
143
143
|
"display": "horizontal",
|
|
144
144
|
"label": "Country : ",
|
|
145
145
|
"tooltip": "Please select your Country",
|
|
@@ -353,7 +353,7 @@
|
|
|
353
353
|
"autoComplete": "tel",
|
|
354
354
|
"size": "40",
|
|
355
355
|
"display": "horizontal",
|
|
356
|
-
"required":
|
|
356
|
+
"required": true,
|
|
357
357
|
"label": "Phone Number : ",
|
|
358
358
|
"tooltip": "Please enter your Phone Number",
|
|
359
359
|
"validate": "isValidUSPhoneNumber"
|
|
@@ -369,7 +369,7 @@
|
|
|
369
369
|
"autoComplete": "email",
|
|
370
370
|
"size": "40",
|
|
371
371
|
"display": "horizontal",
|
|
372
|
-
"required":
|
|
372
|
+
"required": true,
|
|
373
373
|
"label": "Email Address : ",
|
|
374
374
|
"tooltip": "Please enter your Email Address",
|
|
375
375
|
"validate": "isValidEmailAddress"
|
|
@@ -397,7 +397,7 @@
|
|
|
397
397
|
"name": "shippingMethod",
|
|
398
398
|
"label": "Shipping Method : ",
|
|
399
399
|
"display": "vertical",
|
|
400
|
-
"required":
|
|
400
|
+
"required": true,
|
|
401
401
|
"validate": "isOneRadioSelected",
|
|
402
402
|
"tooltip": "Please select your Shipping Method",
|
|
403
403
|
"options": [
|