@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.
Files changed (160) hide show
  1. package/README.COMPONENTS.md +289 -30
  2. package/README.md +36 -28
  3. package/dist/components/general/tab.css +105 -0
  4. package/dist/components/general/tab.js +26 -0
  5. package/dist/components/seo/metadata.components.js +0 -19
  6. package/dist/components/seo/metadata.functions.js +111 -0
  7. package/dist/components/seo/schema-blogposting.functions.js +42 -0
  8. package/dist/components/seo/schema-blogposting.js +0 -46
  9. package/dist/components/seo/sitemap.js +1 -1
  10. package/dist/components/shoppingcart/shoppingcart.components.js +4 -4
  11. package/dist/components/sitebuilder/config/ConfigBuilder.css +266 -0
  12. package/dist/components/sitebuilder/config/ConfigBuilder.js +221 -0
  13. package/dist/components/{pagebuilder → sitebuilder}/form/form.css +55 -34
  14. package/dist/components/sitebuilder/form/formbuilder.js +106 -0
  15. package/dist/components/sitebuilder/form/formcomponents.js +356 -0
  16. package/dist/components/sitebuilder/form/formengine.js +82 -0
  17. package/dist/components/{pagebuilder/form/form.js → sitebuilder/form/formextractor.js} +10 -211
  18. package/dist/components/sitebuilder/form/formutils.js +206 -0
  19. package/dist/components/sitebuilder/form/formvalidator.js +123 -0
  20. package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentPropertiesForm.js +1 -1
  21. package/dist/components/{pagebuilder → sitebuilder/page}/components/PageBuilderUI.js +2 -2
  22. package/dist/components/{pagebuilder → sitebuilder/page}/components/PageEngine.js +1 -1
  23. package/dist/components/sitebuilder/page/documentation/api-examples/save-route-example.js +37 -0
  24. package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentMap.js +3 -3
  25. package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentMetadata.js +2 -2
  26. package/dist/components/{pagebuilder → sitebuilder/page}/lib/pageStorageContentful.js +2 -2
  27. package/dist/components/sitebuilder/page/lib/pageStorageTypes.js +1 -0
  28. package/dist/data/form.json +18 -18
  29. package/dist/data/shipping.to.json +9 -9
  30. package/dist/data/siteinfo-form.json +200 -0
  31. package/dist/index.js +29 -21
  32. package/dist/index.server.js +24 -17
  33. package/dist/types/components/general/semantic.d.ts +3 -3
  34. package/dist/types/components/general/tab.d.ts +18 -0
  35. package/dist/types/components/general/tab.d.ts.map +1 -0
  36. package/dist/types/components/seo/metadata.components.d.ts +0 -17
  37. package/dist/types/components/seo/metadata.components.d.ts.map +1 -1
  38. package/dist/types/components/seo/{metadata.d.ts → metadata.functions.d.ts} +15 -1
  39. package/dist/types/components/seo/metadata.functions.d.ts.map +1 -0
  40. package/dist/types/components/seo/schema-blogposting.d.ts +1 -25
  41. package/dist/types/components/seo/schema-blogposting.d.ts.map +1 -1
  42. package/dist/types/components/seo/schema-blogposting.functions.d.ts +26 -0
  43. package/dist/types/components/seo/schema-blogposting.functions.d.ts.map +1 -0
  44. package/dist/types/components/seo/sitemap.d.ts.map +1 -1
  45. package/dist/types/components/shoppingcart/shoppingcart.components.d.ts +1 -1
  46. package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts +86 -0
  47. package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts.map +1 -0
  48. package/dist/types/components/sitebuilder/form/formbuilder.d.ts +11 -0
  49. package/dist/types/components/sitebuilder/form/formbuilder.d.ts.map +1 -0
  50. package/dist/types/components/{pagebuilder → sitebuilder}/form/formcomponents.d.ts +12 -16
  51. package/dist/types/components/sitebuilder/form/formcomponents.d.ts.map +1 -0
  52. package/dist/types/components/{pagebuilder/form/form.submit.d.ts → sitebuilder/form/formemailer.d.ts} +1 -1
  53. package/dist/types/components/sitebuilder/form/formemailer.d.ts.map +1 -0
  54. package/dist/types/components/sitebuilder/form/formengine.d.ts +14 -0
  55. package/dist/types/components/sitebuilder/form/formengine.d.ts.map +1 -0
  56. package/dist/types/components/sitebuilder/form/formextractor.d.ts +25 -0
  57. package/dist/types/components/sitebuilder/form/formextractor.d.ts.map +1 -0
  58. package/dist/types/components/{pagebuilder/form/formvalidations.d.ts → sitebuilder/form/formfieldvalidations.d.ts} +1 -1
  59. package/dist/types/components/sitebuilder/form/formfieldvalidations.d.ts.map +1 -0
  60. package/dist/types/components/sitebuilder/form/formtypes.d.ts +66 -0
  61. package/dist/types/components/sitebuilder/form/formtypes.d.ts.map +1 -0
  62. package/dist/types/components/sitebuilder/form/formutils.d.ts +20 -0
  63. package/dist/types/components/sitebuilder/form/formutils.d.ts.map +1 -0
  64. package/dist/types/components/sitebuilder/form/formvalidator.d.ts +20 -0
  65. package/dist/types/components/sitebuilder/form/formvalidator.d.ts.map +1 -0
  66. package/dist/types/components/sitebuilder/page/components/ComponentPropertiesForm.d.ts.map +1 -0
  67. package/dist/types/components/sitebuilder/page/components/ComponentSelector.d.ts.map +1 -0
  68. package/dist/types/components/sitebuilder/page/components/ComponentTree.d.ts.map +1 -0
  69. package/dist/types/components/{pagebuilder → sitebuilder/page}/components/PageBuilderUI.d.ts +1 -1
  70. package/dist/types/components/sitebuilder/page/components/PageBuilderUI.d.ts.map +1 -0
  71. package/dist/types/components/sitebuilder/page/components/PageEngine.d.ts.map +1 -0
  72. package/dist/types/components/sitebuilder/page/components/SaveLoadSection.d.ts.map +1 -0
  73. package/dist/types/components/sitebuilder/page/documentation/api-examples/save-route-example.d.ts +6 -0
  74. package/dist/types/components/sitebuilder/page/documentation/api-examples/save-route-example.d.ts.map +1 -0
  75. package/dist/types/components/sitebuilder/page/lib/componentGeneration.d.ts.map +1 -0
  76. package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentMap.d.ts +3 -3
  77. package/dist/types/components/sitebuilder/page/lib/componentMap.d.ts.map +1 -0
  78. package/dist/types/components/sitebuilder/page/lib/componentMetadata.d.ts.map +1 -0
  79. package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageContentful.d.ts +1 -1
  80. package/dist/types/components/sitebuilder/page/lib/pageStorageContentful.d.ts.map +1 -0
  81. package/dist/types/components/sitebuilder/page/lib/pageStorageLocal.d.ts.map +1 -0
  82. package/dist/types/components/sitebuilder/page/lib/pageStorageTypes.d.ts.map +1 -0
  83. package/dist/types/components/sitebuilder/page/lib/propTypeIntrospection.d.ts.map +1 -0
  84. package/dist/types/components/sitebuilder/page/lib/types.d.ts.map +1 -0
  85. package/dist/types/components/sitebuilder/page/lib/usePageBuilder.d.ts.map +1 -0
  86. package/dist/types/index.d.ts +29 -20
  87. package/dist/types/index.server.d.ts +23 -16
  88. package/dist/types/stories/general/tab.stories.d.ts +45 -0
  89. package/dist/types/stories/general/tab.stories.d.ts.map +1 -0
  90. package/dist/types/stories/seo/seo.metadata.stories.d.ts +1 -1
  91. package/dist/types/stories/seo/seo.metadata.stories.d.ts.map +1 -1
  92. package/dist/types/stories/sitebuilder/configbuilder.stories.d.ts +48 -0
  93. package/dist/types/stories/sitebuilder/configbuilder.stories.d.ts.map +1 -0
  94. package/dist/types/stories/{pagebuilder → sitebuilder}/form-builder.stories.d.ts +1 -1
  95. package/dist/types/stories/sitebuilder/form-builder.stories.d.ts.map +1 -0
  96. package/dist/types/stories/{pagebuilder → sitebuilder}/form-engine.stories.d.ts +1 -1
  97. package/dist/types/stories/sitebuilder/form-engine.stories.d.ts.map +1 -0
  98. package/dist/types/stories/{pagebuilder → sitebuilder}/form-extractor.stories.d.ts +1 -1
  99. package/dist/types/stories/sitebuilder/form-extractor.stories.d.ts.map +1 -0
  100. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.stories.d.ts +1 -1
  101. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.stories.d.ts.map +1 -1
  102. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.usageguide.stories.d.ts +1 -1
  103. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.usageguide.stories.d.ts.map +1 -1
  104. package/dist/types/stories/{pagebuilder → sitebuilder}/pageengine.stories.d.ts +1 -1
  105. package/dist/types/stories/{pagebuilder → sitebuilder}/pageengine.stories.d.ts.map +1 -1
  106. package/dist/types/tests/configbuilder.test.d.ts +2 -0
  107. package/dist/types/tests/configbuilder.test.d.ts.map +1 -0
  108. package/dist/types/tests/tab.test.d.ts +2 -0
  109. package/dist/types/tests/tab.test.d.ts.map +1 -0
  110. package/package.json +5 -4
  111. package/dist/components/pagebuilder/form/formcomponents.js +0 -359
  112. package/dist/components/seo/metadata.js +0 -108
  113. package/dist/types/components/pagebuilder/components/ComponentPropertiesForm.d.ts.map +0 -1
  114. package/dist/types/components/pagebuilder/components/ComponentSelector.d.ts.map +0 -1
  115. package/dist/types/components/pagebuilder/components/ComponentTree.d.ts.map +0 -1
  116. package/dist/types/components/pagebuilder/components/PageBuilderUI.d.ts.map +0 -1
  117. package/dist/types/components/pagebuilder/components/PageEngine.d.ts.map +0 -1
  118. package/dist/types/components/pagebuilder/components/SaveLoadSection.d.ts.map +0 -1
  119. package/dist/types/components/pagebuilder/form/form.d.ts +0 -46
  120. package/dist/types/components/pagebuilder/form/form.d.ts.map +0 -1
  121. package/dist/types/components/pagebuilder/form/form.submit.d.ts.map +0 -1
  122. package/dist/types/components/pagebuilder/form/formcomponents.d.ts.map +0 -1
  123. package/dist/types/components/pagebuilder/form/formvalidations.d.ts.map +0 -1
  124. package/dist/types/components/pagebuilder/lib/componentGeneration.d.ts.map +0 -1
  125. package/dist/types/components/pagebuilder/lib/componentMap.d.ts.map +0 -1
  126. package/dist/types/components/pagebuilder/lib/componentMetadata.d.ts.map +0 -1
  127. package/dist/types/components/pagebuilder/lib/pageStorageContentful.d.ts.map +0 -1
  128. package/dist/types/components/pagebuilder/lib/pageStorageLocal.d.ts.map +0 -1
  129. package/dist/types/components/pagebuilder/lib/pageStorageTypes.d.ts.map +0 -1
  130. package/dist/types/components/pagebuilder/lib/propTypeIntrospection.d.ts.map +0 -1
  131. package/dist/types/components/pagebuilder/lib/types.d.ts.map +0 -1
  132. package/dist/types/components/pagebuilder/lib/usePageBuilder.d.ts.map +0 -1
  133. package/dist/types/components/seo/metadata.d.ts.map +0 -1
  134. package/dist/types/stories/pagebuilder/form-builder.stories.d.ts.map +0 -1
  135. package/dist/types/stories/pagebuilder/form-engine.stories.d.ts.map +0 -1
  136. package/dist/types/stories/pagebuilder/form-extractor.stories.d.ts.map +0 -1
  137. /package/dist/components/{pagebuilder/form/form.submit.js → sitebuilder/form/formemailer.js} +0 -0
  138. /package/dist/components/{pagebuilder/form/formvalidations.js → sitebuilder/form/formfieldvalidations.js} +0 -0
  139. /package/dist/components/{pagebuilder/lib/pageStorageTypes.js → sitebuilder/form/formtypes.js} +0 -0
  140. /package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentSelector.js +0 -0
  141. /package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentTree.js +0 -0
  142. /package/dist/components/{pagebuilder → sitebuilder/page}/components/SaveLoadSection.js +0 -0
  143. /package/dist/components/{pagebuilder → sitebuilder/page}/components/pagebuilder.scss +0 -0
  144. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentGeneration.js +0 -0
  145. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/pageStorageLocal.js +0 -0
  146. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/propTypeIntrospection.js +0 -0
  147. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/types.js +0 -0
  148. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/usePageBuilder.js +0 -0
  149. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentPropertiesForm.d.ts +0 -0
  150. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentSelector.d.ts +0 -0
  151. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentTree.d.ts +0 -0
  152. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/PageEngine.d.ts +0 -0
  153. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/SaveLoadSection.d.ts +0 -0
  154. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentGeneration.d.ts +0 -0
  155. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentMetadata.d.ts +0 -0
  156. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageLocal.d.ts +0 -0
  157. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageTypes.d.ts +0 -0
  158. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/propTypeIntrospection.d.ts +0 -0
  159. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/types.d.ts +0 -0
  160. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/usePageBuilder.d.ts +0 -0
@@ -0,0 +1,221 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import { Tab } from '../../general/tab';
5
+ import { FormEngine } from '../form/formengine';
6
+ import siteInfoForm from '../../../data/siteinfo-form.json';
7
+ import './ConfigBuilder.css';
8
+ const SiteInfoPropTypes = {
9
+ name: PropTypes.string.isRequired,
10
+ author: PropTypes.string.isRequired,
11
+ description: PropTypes.string.isRequired,
12
+ url: PropTypes.string.isRequired,
13
+ email: PropTypes.string.isRequired,
14
+ favicon: PropTypes.string.isRequired,
15
+ favicon_sizes: PropTypes.string.isRequired,
16
+ favicon_type: PropTypes.string.isRequired,
17
+ theme_color: PropTypes.string.isRequired,
18
+ background_color: PropTypes.string.isRequired,
19
+ default_locale: PropTypes.string.isRequired,
20
+ display: PropTypes.string.isRequired,
21
+ image: PropTypes.string,
22
+ image_height: PropTypes.string,
23
+ image_width: PropTypes.string,
24
+ telephone: PropTypes.string,
25
+ address: PropTypes.shape({
26
+ streetAddress: PropTypes.string.isRequired,
27
+ addressLocality: PropTypes.string.isRequired,
28
+ addressRegion: PropTypes.string.isRequired,
29
+ postalCode: PropTypes.string.isRequired,
30
+ addressCountry: PropTypes.string.isRequired,
31
+ }),
32
+ priceRange: PropTypes.string,
33
+ sameAs: PropTypes.arrayOf(PropTypes.string.isRequired),
34
+ keywords: PropTypes.string,
35
+ };
36
+ const RoutePropTypes = {
37
+ path: PropTypes.string.isRequired,
38
+ component: PropTypes.string.isRequired,
39
+ title: PropTypes.string,
40
+ description: PropTypes.string,
41
+ };
42
+ const SiteConfigPropTypes = {
43
+ siteInfo: PropTypes.shape(SiteInfoPropTypes).isRequired,
44
+ routes: PropTypes.arrayOf(PropTypes.shape(RoutePropTypes).isRequired).isRequired,
45
+ };
46
+ const ConfigBuilderPropTypes = {
47
+ initialConfig: PropTypes.shape(SiteConfigPropTypes),
48
+ onSave: PropTypes.func,
49
+ };
50
+ export function ConfigBuilder({ initialConfig, onSave }) {
51
+ const [config, setConfig] = useState(initialConfig || {
52
+ siteInfo: {
53
+ name: '',
54
+ author: '',
55
+ description: '',
56
+ url: '',
57
+ email: '',
58
+ favicon: '/favicon.ico',
59
+ favicon_sizes: '64x64 32x32 24x24 16x16',
60
+ favicon_type: 'image/x-icon',
61
+ theme_color: '#ffffff',
62
+ background_color: '#ffffff',
63
+ default_locale: 'en',
64
+ display: 'standalone',
65
+ address: {
66
+ streetAddress: '',
67
+ addressLocality: '',
68
+ addressRegion: '',
69
+ postalCode: '',
70
+ addressCountry: ''
71
+ }
72
+ },
73
+ routes: []
74
+ });
75
+ const [socialLinks, setSocialLinks] = useState(initialConfig?.siteInfo?.sameAs || ['']);
76
+ const [isFormValid, setIsFormValid] = useState(false);
77
+ // Validate form whenever config changes
78
+ useEffect(() => {
79
+ const siteInfo = config.siteInfo || {};
80
+ const isValid = (siteInfo.name || '').trim() !== '' &&
81
+ (siteInfo.author || '').trim() !== '' &&
82
+ (siteInfo.description || '').trim() !== '' &&
83
+ (siteInfo.url || '').trim() !== '' &&
84
+ (siteInfo.email || '').trim() !== '' &&
85
+ // Basic email validation
86
+ /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(siteInfo.email || '');
87
+ setIsFormValid(isValid);
88
+ }, [config]);
89
+ const handleFileUpload = (event) => {
90
+ const file = event.target.files?.[0];
91
+ if (!file)
92
+ return;
93
+ const reader = new FileReader();
94
+ reader.onload = (e) => {
95
+ try {
96
+ const jsonContent = e.target?.result;
97
+ const parsedConfig = JSON.parse(jsonContent);
98
+ // Validate the structure
99
+ if (parsedConfig.siteInfo && parsedConfig.routes) {
100
+ setConfig(parsedConfig);
101
+ setSocialLinks(parsedConfig.siteInfo.sameAs || ['']);
102
+ }
103
+ else {
104
+ alert('Invalid configuration file. Expected siteInfo and routes properties.');
105
+ }
106
+ }
107
+ catch {
108
+ alert('Error parsing JSON file. Please ensure it contains valid JSON.');
109
+ }
110
+ };
111
+ reader.readAsText(file);
112
+ // Reset the input
113
+ event.target.value = '';
114
+ };
115
+ useEffect(() => {
116
+ if (initialConfig) {
117
+ setConfig(prev => ({
118
+ siteInfo: { ...prev.siteInfo, ...initialConfig.siteInfo },
119
+ routes: initialConfig.routes || []
120
+ }));
121
+ setSocialLinks(initialConfig.siteInfo?.sameAs || ['']);
122
+ }
123
+ }, [initialConfig]);
124
+ // Prepare form data for FormEngine with current values
125
+ const formData = {
126
+ fields: siteInfoForm.fields.map(field => ({
127
+ ...field,
128
+ props: {
129
+ ...field.props,
130
+ value: config.siteInfo[field.props.name] || '',
131
+ defaultValue: config.siteInfo[field.props.name] || field.props.defaultValue || '',
132
+ onChange: (value) => {
133
+ setConfig(prev => ({
134
+ ...prev,
135
+ siteInfo: {
136
+ ...prev.siteInfo,
137
+ [field.props.name]: value
138
+ }
139
+ }));
140
+ }
141
+ }
142
+ }))
143
+ };
144
+ const handleFormSubmit = (event) => {
145
+ event.preventDefault();
146
+ const formData = new FormData(event.target);
147
+ const siteInfoData = {};
148
+ // Extract form data
149
+ for (const [key, value] of formData.entries()) {
150
+ siteInfoData[key] = value;
151
+ }
152
+ // Update config with form data
153
+ setConfig(prev => ({
154
+ ...prev,
155
+ siteInfo: {
156
+ ...prev.siteInfo,
157
+ ...siteInfoData,
158
+ sameAs: socialLinks.filter(link => link.trim() !== '')
159
+ }
160
+ }));
161
+ };
162
+ const updateAddress = (field, value) => {
163
+ setConfig(prev => ({
164
+ ...prev,
165
+ siteInfo: {
166
+ ...prev.siteInfo,
167
+ address: {
168
+ ...(prev.siteInfo.address || {}),
169
+ [field]: value
170
+ }
171
+ }
172
+ }));
173
+ };
174
+ const addSocialLink = () => {
175
+ setSocialLinks(prev => [...prev, '']);
176
+ };
177
+ const updateSocialLink = (index, value) => {
178
+ setSocialLinks(prev => prev.map((link, i) => i === index ? value : link));
179
+ };
180
+ const removeSocialLink = (index) => {
181
+ setSocialLinks(prev => prev.filter((_, i) => i !== index));
182
+ };
183
+ const addRoute = () => {
184
+ setConfig(prev => ({
185
+ ...prev,
186
+ routes: [...prev.routes, { path: '', component: '', title: '', description: '' }]
187
+ }));
188
+ };
189
+ const updateRoute = (index, field, value) => {
190
+ setConfig(prev => ({
191
+ ...prev,
192
+ routes: prev.routes.map((route, i) => i === index ? { ...route, [field]: value } : route)
193
+ }));
194
+ };
195
+ const removeRoute = (index) => {
196
+ setConfig(prev => ({
197
+ ...prev,
198
+ routes: prev.routes.filter((_, i) => i !== index)
199
+ }));
200
+ };
201
+ const handleSave = () => {
202
+ if (!isFormValid) {
203
+ alert('Please fill in all required fields correctly before saving.');
204
+ return;
205
+ }
206
+ onSave?.(config);
207
+ };
208
+ return (_jsxs("div", { className: "config-builder", children: [_jsx("h2", { children: "Config Builder" }), _jsxs("div", { className: "file-upload-section", children: [_jsx("label", { htmlFor: "config-file-upload", className: "file-upload-label", children: "Load Configuration File:" }), _jsx("input", { id: "config-file-upload", type: "file", accept: ".json", onChange: handleFileUpload, className: "file-upload-input" })] }), _jsx(Tab, { tabs: [
209
+ {
210
+ id: 'siteinfo',
211
+ label: 'Site Info',
212
+ content: (_jsxs("div", { className: "site-info-section", children: [_jsx(FormEngine, { formData: formData, onSubmitHandler: handleFormSubmit, name: "siteinfo", id: "siteinfo" }), _jsxs("div", { className: "address-section", children: [_jsx("h4", { children: "Address" }), _jsxs("div", { className: "field-group", children: [_jsx("label", { htmlFor: "street-address", children: "Street Address" }), _jsx("input", { id: "street-address", type: "text", placeholder: "Street Address", value: config.siteInfo.address?.streetAddress || '', onChange: (e) => updateAddress('streetAddress', e.target.value) })] }), _jsxs("div", { className: "field-group", children: [_jsx("label", { htmlFor: "city", children: "City" }), _jsx("input", { id: "city", type: "text", placeholder: "City", value: config.siteInfo.address?.addressLocality || '', onChange: (e) => updateAddress('addressLocality', e.target.value) })] }), _jsxs("div", { className: "field-group", children: [_jsx("label", { htmlFor: "state-region", children: "State/Region" }), _jsx("input", { id: "state-region", type: "text", placeholder: "State/Region", value: config.siteInfo.address?.addressRegion || '', onChange: (e) => updateAddress('addressRegion', e.target.value) })] }), _jsxs("div", { className: "field-group", children: [_jsx("label", { htmlFor: "postal-code", children: "Postal Code" }), _jsx("input", { id: "postal-code", type: "text", placeholder: "Postal Code", value: config.siteInfo.address?.postalCode || '', onChange: (e) => updateAddress('postalCode', e.target.value) })] }), _jsxs("div", { className: "field-group", children: [_jsx("label", { htmlFor: "country", children: "Country" }), _jsx("input", { id: "country", type: "text", placeholder: "Country", value: config.siteInfo.address?.addressCountry || '', onChange: (e) => updateAddress('addressCountry', e.target.value) })] })] }), _jsxs("div", { className: "social-links-section", children: [_jsx("h4", { children: "Social Links" }), socialLinks.map((link, index) => (_jsxs("div", { className: "field-group social-link-item", children: [_jsx("input", { type: "url", placeholder: "https://social-link.com", value: link, onChange: (e) => updateSocialLink(index, e.target.value) }), _jsx("button", { type: "button", onClick: () => removeSocialLink(index), children: "Remove" })] }, index))), _jsx("button", { type: "button", onClick: addSocialLink, children: "Add Social Link" })] })] }))
213
+ },
214
+ {
215
+ id: 'routes',
216
+ label: 'Routes',
217
+ content: (_jsxs("div", { className: "routes-section", children: [_jsx("div", { className: "routes-list", children: config.routes.map((route, index) => (_jsxs("div", { className: "route-item", children: [_jsx("input", { type: "text", placeholder: "Path", value: route.path, onChange: (e) => updateRoute(index, 'path', e.target.value) }), _jsx("input", { type: "text", placeholder: "Component", value: route.component, onChange: (e) => updateRoute(index, 'component', e.target.value) }), _jsx("input", { type: "text", placeholder: "Title", value: route.title || '', onChange: (e) => updateRoute(index, 'title', e.target.value) }), _jsx("input", { type: "text", placeholder: "Description", value: route.description || '', onChange: (e) => updateRoute(index, 'description', e.target.value) }), _jsx("button", { onClick: () => removeRoute(index), children: "Remove" })] }, index))) }), _jsx("button", { onClick: addRoute, children: "Add Route" })] }))
218
+ }
219
+ ], orientation: "top" }), _jsx("button", { onClick: handleSave, disabled: !isFormValid, className: isFormValid ? 'save-button-valid' : 'save-button-invalid', children: "Save Config" }), !isFormValid && (_jsx("div", { className: "validation-message", children: "Please fill in all required fields (marked with *) before saving." })), _jsx("pre", { children: JSON.stringify(config, null, 2) })] }));
220
+ }
221
+ ConfigBuilder.propTypes = ConfigBuilderPropTypes;
@@ -59,47 +59,68 @@ form span {
59
59
  vertical-align: middle;
60
60
  }
61
61
 
62
- .tooltip {
63
- display: inline;
64
- margin-right: 10px;
62
+
63
+ /* ========================================
64
+ ============== TOOLTIP ==============
65
+ ======================================== */
66
+
67
+ .tooltip-container {
68
+ display: inline-block;
65
69
  position: relative;
70
+ margin-left: 5px;
71
+ vertical-align: middle;
66
72
  }
67
73
 
68
- .tooltipIcon {
69
- /* display: inline;
70
- color: white !important;
71
- background-color: #369;
72
- border-radius: 20px;
73
- padding: 0 3px; */
74
- vertical-align: middle;
75
- padding: 5px;
76
- box-shadow: none;
77
- background-color: transparent;
78
- border: none;
74
+ .tooltip-icon {
75
+ display: inline-flex;
76
+ align-items: center;
77
+ justify-content: center;
78
+ font-size: 1.0rem;
79
+ font-weight: bold;
80
+ cursor: pointer;
81
+ padding: 0 3px;
82
+ line-height: 1;
83
+ color: #00F;
79
84
  }
80
85
 
81
- .tooltipIcon img {
82
- width: 20px;
83
- /* margin: 5px 0 0 -10px; */
84
- background-color: #DDD;
85
- border-radius: 5px;
86
+ .tooltip-icon-validate {
87
+ color: #d00;
86
88
  }
87
89
 
88
- .tooltipText {
89
- display: none;
90
+ .tooltip-text {
90
91
  position: absolute;
91
- top: -25px;
92
- left: 25px;
93
- width: 200px;
94
- padding: 3px 8px;
95
- color: #fff;
96
- text-align: center;
97
- background-color: #666;
98
- border: 1px solid white;
99
- border-radius: 4px;
100
- box-shadow: -3px 0 10px #369, 0 3px 10px #369, 3px 0 10px #369, 0 -3px 10px #369;
92
+ top: -15px;
93
+ left: 35px;
94
+ min-width: 200px;
95
+ max-width: 300px;
96
+ padding: 8px 12px;
97
+ background-color: #333;
98
+ color: white;
99
+ border-radius: 4px;
100
+ box-shadow: 0 2px 8px rgba(0,0,0,0.3);
101
+ z-index: 1000;
102
+ font-size: 0.9em;
103
+ white-space: normal;
101
104
  }
102
- .tooltip a {
103
- /* pointer-events: none; */
104
- text-decoration: none;
105
+
106
+ .tooltip-text::before {
107
+ content: '';
108
+ position: absolute;
109
+ top: 50%;
110
+ left: -8px;
111
+ transform: translateY(-50%);
112
+ width: 0;
113
+ height: 0;
114
+ border-top: 8px solid transparent;
115
+ border-bottom: 8px solid transparent;
116
+ border-right: 8px solid #333;
117
+ z-index: 1001;
118
+ }
119
+
120
+ .tooltip-text-item {
121
+ margin-bottom: 4px;
122
+ }
123
+
124
+ .tooltip-text-item:last-child {
125
+ margin-bottom: 0;
105
126
  }
@@ -0,0 +1,106 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import * as FC from './formcomponents';
5
+ import { mapTypeToComponent, generateTypeField, debug } from './formutils';
6
+ import { FormEngine } from './formengine';
7
+ /* ===== FORM BUILDER =====
8
+ Display all the components for a Form Builder -
9
+ Element Buttons, Element Details, and the Form */
10
+ export function FormBuilder() {
11
+ const [formData, setFormData] = useState({ fields: [] });
12
+ const [fieldFormData, setFieldFormData] = useState({ fields: [] });
13
+ function appendFormData(event) {
14
+ // APPEND JSON FOR NEW FIELD TO EXISTING JSON CONFIG OBJECT - EXPOSED EXTERNAL
15
+ if (debug)
16
+ console.log("Appending form Data...");
17
+ const props = {};
18
+ const target = event.target;
19
+ for (const prop in target) {
20
+ const thisProp = target[prop];
21
+ if (thisProp && thisProp.value && (thisProp.value !== Object(thisProp.value))) {
22
+ props[thisProp.name] = thisProp.value;
23
+ }
24
+ }
25
+ const field = {};
26
+ field.props = props;
27
+ field.component = mapTypeToComponent(field.props.type);
28
+ let fields = [];
29
+ if (Object.keys(formData).length > 0) {
30
+ fields = JSON.parse(JSON.stringify(formData.fields));
31
+ }
32
+ fields[fields.length] = field;
33
+ setFormData({ fields: fields });
34
+ setFieldFormData({ fields: [] });
35
+ return (field);
36
+ }
37
+ /* function getCircularReplacer() {
38
+ const seen = new WeakSet();
39
+ return (key, value) => {
40
+ if (typeof value === 'object' && value !== null) {
41
+ if (seen.has(value)) {
42
+ return ; // return undefined ;
43
+ }
44
+ seen.add(value);
45
+ }
46
+ return value;
47
+ };
48
+ } */
49
+ return (_jsxs("div", { className: "section-container", children: [_jsxs("div", { style: { display: 'inline-block', verticalAlign: 'top' }, children: [_jsx(FormBuild, { setFormData: setFieldFormData }), _jsx("div", {}), _jsx(FormEngine, { name: "field_props", id: "field_props", onSubmitHandler: appendFormData, formData: fieldFormData })] }), _jsx("div", { style: { display: 'inline-block', verticalAlign: 'top' }, children: _jsx("pre", { style: { width: '100%' }, children: JSON.stringify(formData, null, 2) }) }), _jsxs("div", { children: [_jsx("br", {}), _jsx("br", {}), _jsx("hr", {}), _jsx("br", {}), _jsx("br", {})] }), _jsx("div", { style: { display: 'block', verticalAlign: 'top' }, children: _jsx(FormEngine, { formData: formData || {} }) })] }));
50
+ }
51
+ /*
52
+ ===== FORM BUILD =====
53
+ Dynamically generate, component by component, and prop by prop,
54
+ the JSON to create a form via FormEngine
55
+ */
56
+ FormBuild.propTypes = {
57
+ setFormData: PropTypes.func.isRequired,
58
+ };
59
+ export function FormBuild(props) {
60
+ function generateFieldJSON(component, type) {
61
+ // GENERATE THE JSON TO DISPLAY A FORM TO ADD A FIELD - INTERNAL
62
+ if (debug)
63
+ console.log("Generating Form JSON for ", component, " Type : ", type);
64
+ const form = { fields: [] };
65
+ let i = 0;
66
+ for (const prop in FC[component].propTypes) {
67
+ const field = {};
68
+ field.component = 'FormInput';
69
+ const props = {};
70
+ props.label = prop;
71
+ props.name = prop;
72
+ props.id = prop;
73
+ props.type = 'text';
74
+ if (prop === 'type') {
75
+ props.disabled = true;
76
+ props.value = type;
77
+ props.list = 'inputTypes';
78
+ }
79
+ field.props = props;
80
+ form.fields[i] = field;
81
+ i++;
82
+ }
83
+ const addButton = {
84
+ component: 'FormButton',
85
+ props: {
86
+ label: 'Add ' + component,
87
+ type: 'submit',
88
+ id: 'Add ' + component,
89
+ text: 'Add ' + component
90
+ }
91
+ };
92
+ form.fields[i] = addButton;
93
+ return (form);
94
+ }
95
+ function handlePhaseOneSubmit(event) {
96
+ // GENERATE THE JSON TO DISPLAY A FORM TO ADD A FIELD - EXTERNAL
97
+ const target = event.target;
98
+ const typeElement = target.elements.namedItem('type');
99
+ const myType = typeElement ? typeElement.value : '';
100
+ const myComponent = mapTypeToComponent(myType);
101
+ const fieldJSON = generateFieldJSON(myComponent, myType);
102
+ props.setFormData(fieldJSON);
103
+ return true;
104
+ }
105
+ return (_jsx(_Fragment, { children: _jsx(FormEngine, { formData: generateTypeField(), onSubmitHandler: event => { handlePhaseOneSubmit(event); }, name: "build", id: "build", method: "post" }) }));
106
+ }