@pixelated-tech/components 3.2.13 → 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 (192) hide show
  1. package/README.COMPONENTS.md +435 -78
  2. package/README.md +59 -32
  3. package/dist/components/callout/callout.scss +0 -3
  4. package/dist/components/cms/flickr.js +8 -2
  5. package/dist/components/cms/google.reviews.components.js +1 -1
  6. package/dist/components/general/tab.css +105 -0
  7. package/dist/components/general/tab.js +26 -0
  8. package/dist/components/menu/menu-expando.js +7 -1
  9. package/dist/components/nerdjoke/nerdjoke.js +13 -7
  10. package/dist/components/seo/manifest.js +40 -0
  11. package/dist/components/seo/metadata.components.js +0 -19
  12. package/dist/components/seo/metadata.functions.js +111 -0
  13. package/dist/components/seo/schema-blogposting.functions.js +42 -0
  14. package/dist/components/seo/schema-blogposting.js +0 -46
  15. package/dist/components/seo/schema-localbusiness.js +46 -2
  16. package/dist/components/seo/schema-website.js +31 -2
  17. package/dist/components/seo/sitemap.js +4 -4
  18. package/dist/components/shoppingcart/shoppingcart.components.js +4 -4
  19. package/dist/components/sitebuilder/config/ConfigBuilder.css +266 -0
  20. package/dist/components/sitebuilder/config/ConfigBuilder.js +221 -0
  21. package/dist/components/{pagebuilder → sitebuilder}/form/form.css +55 -30
  22. package/dist/components/sitebuilder/form/formbuilder.js +106 -0
  23. package/dist/components/sitebuilder/form/formcomponents.js +356 -0
  24. package/dist/components/sitebuilder/form/formengine.js +82 -0
  25. package/dist/components/{pagebuilder/form/form.js → sitebuilder/form/formextractor.js} +10 -211
  26. package/dist/components/sitebuilder/form/formutils.js +206 -0
  27. package/dist/components/sitebuilder/form/formvalidator.js +123 -0
  28. package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentPropertiesForm.js +1 -1
  29. package/dist/components/{pagebuilder → sitebuilder/page}/components/PageBuilderUI.js +2 -2
  30. package/dist/components/{pagebuilder → sitebuilder/page}/components/PageEngine.js +1 -1
  31. package/dist/components/sitebuilder/page/documentation/api-examples/save-route-example.js +37 -0
  32. package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentMap.js +3 -3
  33. package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentMetadata.js +2 -2
  34. package/dist/components/{pagebuilder → sitebuilder/page}/lib/pageStorageContentful.js +2 -2
  35. package/dist/components/sitebuilder/page/lib/pageStorageTypes.js +1 -0
  36. package/dist/data/form.json +18 -18
  37. package/dist/data/routes.json +25 -0
  38. package/dist/data/routes2.json +25 -0
  39. package/dist/data/shipping.to.json +9 -9
  40. package/dist/data/siteinfo-form.json +200 -0
  41. package/dist/index.js +31 -23
  42. package/dist/index.server.js +24 -18
  43. package/dist/types/components/cms/flickr.d.ts.map +1 -1
  44. package/dist/types/components/cms/google.reviews.components.d.ts.map +1 -1
  45. package/dist/types/components/config/config.types.d.ts +30 -0
  46. package/dist/types/components/config/config.types.d.ts.map +1 -1
  47. package/dist/types/components/general/semantic.d.ts +3 -3
  48. package/dist/types/components/general/tab.d.ts +18 -0
  49. package/dist/types/components/general/tab.d.ts.map +1 -0
  50. package/dist/types/components/menu/menu-expando.d.ts.map +1 -1
  51. package/dist/types/components/nerdjoke/nerdjoke.d.ts.map +1 -1
  52. package/dist/types/components/seo/manifest.d.ts +19 -0
  53. package/dist/types/components/seo/manifest.d.ts.map +1 -0
  54. package/dist/types/components/seo/metadata.components.d.ts +0 -17
  55. package/dist/types/components/seo/metadata.components.d.ts.map +1 -1
  56. package/dist/types/components/seo/{metadata.d.ts → metadata.functions.d.ts} +15 -1
  57. package/dist/types/components/seo/metadata.functions.d.ts.map +1 -0
  58. package/dist/types/components/seo/schema-blogposting.d.ts +1 -25
  59. package/dist/types/components/seo/schema-blogposting.d.ts.map +1 -1
  60. package/dist/types/components/seo/schema-blogposting.functions.d.ts +26 -0
  61. package/dist/types/components/seo/schema-blogposting.functions.d.ts.map +1 -0
  62. package/dist/types/components/seo/schema-localbusiness.d.ts +22 -23
  63. package/dist/types/components/seo/schema-localbusiness.d.ts.map +1 -1
  64. package/dist/types/components/seo/schema-website.d.ts +17 -18
  65. package/dist/types/components/seo/schema-website.d.ts.map +1 -1
  66. package/dist/types/components/seo/sitemap.d.ts.map +1 -1
  67. package/dist/types/components/shoppingcart/shoppingcart.components.d.ts +1 -1
  68. package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts +86 -0
  69. package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts.map +1 -0
  70. package/dist/types/components/sitebuilder/form/formbuilder.d.ts +11 -0
  71. package/dist/types/components/sitebuilder/form/formbuilder.d.ts.map +1 -0
  72. package/dist/types/components/{pagebuilder → sitebuilder}/form/formcomponents.d.ts +12 -16
  73. package/dist/types/components/sitebuilder/form/formcomponents.d.ts.map +1 -0
  74. package/dist/types/components/{pagebuilder/form/form.submit.d.ts → sitebuilder/form/formemailer.d.ts} +1 -1
  75. package/dist/types/components/sitebuilder/form/formemailer.d.ts.map +1 -0
  76. package/dist/types/components/sitebuilder/form/formengine.d.ts +14 -0
  77. package/dist/types/components/sitebuilder/form/formengine.d.ts.map +1 -0
  78. package/dist/types/components/sitebuilder/form/formextractor.d.ts +25 -0
  79. package/dist/types/components/sitebuilder/form/formextractor.d.ts.map +1 -0
  80. package/dist/types/components/{pagebuilder/form/formvalidations.d.ts → sitebuilder/form/formfieldvalidations.d.ts} +1 -1
  81. package/dist/types/components/sitebuilder/form/formfieldvalidations.d.ts.map +1 -0
  82. package/dist/types/components/sitebuilder/form/formtypes.d.ts +66 -0
  83. package/dist/types/components/sitebuilder/form/formtypes.d.ts.map +1 -0
  84. package/dist/types/components/sitebuilder/form/formutils.d.ts +20 -0
  85. package/dist/types/components/sitebuilder/form/formutils.d.ts.map +1 -0
  86. package/dist/types/components/sitebuilder/form/formvalidator.d.ts +20 -0
  87. package/dist/types/components/sitebuilder/form/formvalidator.d.ts.map +1 -0
  88. package/dist/types/components/sitebuilder/page/components/ComponentPropertiesForm.d.ts.map +1 -0
  89. package/dist/types/components/sitebuilder/page/components/ComponentSelector.d.ts.map +1 -0
  90. package/dist/types/components/sitebuilder/page/components/ComponentTree.d.ts.map +1 -0
  91. package/dist/types/components/{pagebuilder → sitebuilder/page}/components/PageBuilderUI.d.ts +1 -1
  92. package/dist/types/components/sitebuilder/page/components/PageBuilderUI.d.ts.map +1 -0
  93. package/dist/types/components/sitebuilder/page/components/PageEngine.d.ts.map +1 -0
  94. package/dist/types/components/sitebuilder/page/components/SaveLoadSection.d.ts.map +1 -0
  95. package/dist/types/components/sitebuilder/page/documentation/api-examples/save-route-example.d.ts +6 -0
  96. package/dist/types/components/sitebuilder/page/documentation/api-examples/save-route-example.d.ts.map +1 -0
  97. package/dist/types/components/sitebuilder/page/lib/componentGeneration.d.ts.map +1 -0
  98. package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentMap.d.ts +3 -3
  99. package/dist/types/components/sitebuilder/page/lib/componentMap.d.ts.map +1 -0
  100. package/dist/types/components/sitebuilder/page/lib/componentMetadata.d.ts.map +1 -0
  101. package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageContentful.d.ts +1 -1
  102. package/dist/types/components/sitebuilder/page/lib/pageStorageContentful.d.ts.map +1 -0
  103. package/dist/types/components/sitebuilder/page/lib/pageStorageLocal.d.ts.map +1 -0
  104. package/dist/types/components/sitebuilder/page/lib/pageStorageTypes.d.ts.map +1 -0
  105. package/dist/types/components/sitebuilder/page/lib/propTypeIntrospection.d.ts.map +1 -0
  106. package/dist/types/components/sitebuilder/page/lib/types.d.ts.map +1 -0
  107. package/dist/types/components/sitebuilder/page/lib/usePageBuilder.d.ts.map +1 -0
  108. package/dist/types/index.d.ts +30 -21
  109. package/dist/types/index.server.d.ts +23 -17
  110. package/dist/types/stories/general/tab.stories.d.ts +45 -0
  111. package/dist/types/stories/general/tab.stories.d.ts.map +1 -0
  112. package/dist/types/stories/seo/seo.googleanalytics.stories.d.ts.map +1 -1
  113. package/dist/types/stories/seo/seo.metadata.stories.d.ts +1 -1
  114. package/dist/types/stories/seo/seo.metadata.stories.d.ts.map +1 -1
  115. package/dist/types/stories/seo/seo.schema.stories.d.ts +23 -0
  116. package/dist/types/stories/seo/seo.schema.stories.d.ts.map +1 -0
  117. package/dist/types/stories/sitebuilder/configbuilder.stories.d.ts +48 -0
  118. package/dist/types/stories/sitebuilder/configbuilder.stories.d.ts.map +1 -0
  119. package/dist/types/stories/{pagebuilder → sitebuilder}/form-builder.stories.d.ts +1 -1
  120. package/dist/types/stories/sitebuilder/form-builder.stories.d.ts.map +1 -0
  121. package/dist/types/stories/{pagebuilder → sitebuilder}/form-engine.stories.d.ts +1 -1
  122. package/dist/types/stories/sitebuilder/form-engine.stories.d.ts.map +1 -0
  123. package/dist/types/stories/{pagebuilder → sitebuilder}/form-extractor.stories.d.ts +1 -1
  124. package/dist/types/stories/sitebuilder/form-extractor.stories.d.ts.map +1 -0
  125. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.stories.d.ts +1 -1
  126. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.stories.d.ts.map +1 -1
  127. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.usageguide.stories.d.ts +1 -1
  128. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.usageguide.stories.d.ts.map +1 -1
  129. package/dist/types/stories/{pagebuilder → sitebuilder}/pageengine.stories.d.ts +1 -1
  130. package/dist/types/stories/{pagebuilder → sitebuilder}/pageengine.stories.d.ts.map +1 -1
  131. package/dist/types/tests/configbuilder.test.d.ts +2 -0
  132. package/dist/types/tests/configbuilder.test.d.ts.map +1 -0
  133. package/dist/types/tests/manifest.test.d.ts +2 -0
  134. package/dist/types/tests/manifest.test.d.ts.map +1 -0
  135. package/dist/types/tests/tab.test.d.ts +2 -0
  136. package/dist/types/tests/tab.test.d.ts.map +1 -0
  137. package/package.json +6 -5
  138. package/dist/components/pagebuilder/form/formcomponents.js +0 -359
  139. package/dist/components/seo/metadata.js +0 -108
  140. package/dist/components/utilities/api.js +0 -36
  141. package/dist/types/components/pagebuilder/components/ComponentPropertiesForm.d.ts.map +0 -1
  142. package/dist/types/components/pagebuilder/components/ComponentSelector.d.ts.map +0 -1
  143. package/dist/types/components/pagebuilder/components/ComponentTree.d.ts.map +0 -1
  144. package/dist/types/components/pagebuilder/components/PageBuilderUI.d.ts.map +0 -1
  145. package/dist/types/components/pagebuilder/components/PageEngine.d.ts.map +0 -1
  146. package/dist/types/components/pagebuilder/components/SaveLoadSection.d.ts.map +0 -1
  147. package/dist/types/components/pagebuilder/form/form.d.ts +0 -46
  148. package/dist/types/components/pagebuilder/form/form.d.ts.map +0 -1
  149. package/dist/types/components/pagebuilder/form/form.submit.d.ts.map +0 -1
  150. package/dist/types/components/pagebuilder/form/formcomponents.d.ts.map +0 -1
  151. package/dist/types/components/pagebuilder/form/formvalidations.d.ts.map +0 -1
  152. package/dist/types/components/pagebuilder/lib/componentGeneration.d.ts.map +0 -1
  153. package/dist/types/components/pagebuilder/lib/componentMap.d.ts.map +0 -1
  154. package/dist/types/components/pagebuilder/lib/componentMetadata.d.ts.map +0 -1
  155. package/dist/types/components/pagebuilder/lib/pageStorageContentful.d.ts.map +0 -1
  156. package/dist/types/components/pagebuilder/lib/pageStorageLocal.d.ts.map +0 -1
  157. package/dist/types/components/pagebuilder/lib/pageStorageTypes.d.ts.map +0 -1
  158. package/dist/types/components/pagebuilder/lib/propTypeIntrospection.d.ts.map +0 -1
  159. package/dist/types/components/pagebuilder/lib/types.d.ts.map +0 -1
  160. package/dist/types/components/pagebuilder/lib/usePageBuilder.d.ts.map +0 -1
  161. package/dist/types/components/seo/metadata.d.ts.map +0 -1
  162. package/dist/types/components/utilities/api.d.ts +0 -16
  163. package/dist/types/components/utilities/api.d.ts.map +0 -1
  164. package/dist/types/stories/pagebuilder/form-builder.stories.d.ts.map +0 -1
  165. package/dist/types/stories/pagebuilder/form-engine.stories.d.ts.map +0 -1
  166. package/dist/types/stories/pagebuilder/form-extractor.stories.d.ts.map +0 -1
  167. package/dist/types/tests/api.test.d.ts +0 -2
  168. package/dist/types/tests/api.test.d.ts.map +0 -1
  169. /package/dist/components/{pagebuilder/form/form.submit.js → sitebuilder/form/formemailer.js} +0 -0
  170. /package/dist/components/{pagebuilder/form/formvalidations.js → sitebuilder/form/formfieldvalidations.js} +0 -0
  171. /package/dist/components/{pagebuilder/lib/pageStorageTypes.js → sitebuilder/form/formtypes.js} +0 -0
  172. /package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentSelector.js +0 -0
  173. /package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentTree.js +0 -0
  174. /package/dist/components/{pagebuilder → sitebuilder/page}/components/SaveLoadSection.js +0 -0
  175. /package/dist/components/{pagebuilder → sitebuilder/page}/components/pagebuilder.scss +0 -0
  176. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentGeneration.js +0 -0
  177. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/pageStorageLocal.js +0 -0
  178. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/propTypeIntrospection.js +0 -0
  179. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/types.js +0 -0
  180. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/usePageBuilder.js +0 -0
  181. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentPropertiesForm.d.ts +0 -0
  182. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentSelector.d.ts +0 -0
  183. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentTree.d.ts +0 -0
  184. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/PageEngine.d.ts +0 -0
  185. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/SaveLoadSection.d.ts +0 -0
  186. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentGeneration.d.ts +0 -0
  187. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentMetadata.d.ts +0 -0
  188. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageLocal.d.ts +0 -0
  189. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageTypes.d.ts +0 -0
  190. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/propTypeIntrospection.d.ts +0 -0
  191. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/types.d.ts +0 -0
  192. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/usePageBuilder.d.ts +0 -0
@@ -59,43 +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;
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;
75
84
  }
76
85
 
77
- .tooltipIcon img {
78
- width: 20px;
79
- margin: 5px 0 0 -10px;
80
- background-color: #DDD;
81
- border-radius: 5px;
86
+ .tooltip-icon-validate {
87
+ color: #d00;
82
88
  }
83
89
 
84
- .tooltipText {
85
- display: none;
90
+ .tooltip-text {
86
91
  position: absolute;
87
- top: -25px;
88
- left: 25px;
89
- width: 200px;
90
- padding: 3px 8px;
91
- color: #fff;
92
- text-align: center;
93
- background-color: #666;
94
- border: 1px solid white;
95
- border-radius: 4px;
96
- 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;
97
104
  }
98
- .tooltip a {
99
- /* pointer-events: none; */
100
- 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;
101
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
+ }
@@ -0,0 +1,356 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useState } from "react";
3
+ import PropTypes from "prop-types";
4
+ import { validateField } from "./formvalidator";
5
+ import { useFormValidation } from "./formvalidator";
6
+ import * as FVF from "./formfieldvalidations";
7
+ import "./form.css";
8
+ /*
9
+ InferProps to generate Types
10
+ https://amanhimself.dev/blog/prop-types-in-react-and-typescript/#inferring-proptypes-in-typescript
11
+ */
12
+ // Shared helper to setup input props for form components
13
+ const setupInputProps = (props, display) => {
14
+ // Clone props efficiently using destructuring instead of JSON.parse/stringify
15
+ let inputProps = { ...props };
16
+ // Remove props that shouldn't go to DOM
17
+ inputProps = Object.fromEntries(Object.entries(inputProps).filter(([key]) => !['display', 'label', 'listItems', 'validate', 'options', 'parent', 'text', 'checked'].includes(key)));
18
+ // Set className based on display mode
19
+ inputProps["className"] = (display == "vertical") ? "displayVertical" : "";
20
+ // Handle controlled vs uncontrolled inputs properly
21
+ // If value is provided, use it for controlled behavior
22
+ // Otherwise, use defaultValue for uncontrolled behavior
23
+ if (props.value !== undefined) {
24
+ inputProps["value"] = props.value;
25
+ // Remove defaultValue if value is present to avoid conflicts
26
+ delete inputProps["defaultValue"];
27
+ }
28
+ else if (props.defaultValue !== undefined) {
29
+ inputProps["defaultValue"] = props.defaultValue;
30
+ }
31
+ // For radio buttons, prioritize defaultChecked over checked to let browser handle state
32
+ // This prevents React's "both checked and defaultChecked" error
33
+ if (props.type === 'radio' || (props.parent && props.parent.type === 'radio')) {
34
+ if (props.checked !== undefined) {
35
+ delete inputProps["checked"];
36
+ }
37
+ }
38
+ return inputProps;
39
+ };
40
+ // Custom hook for common form component logic
41
+ const useFormComponent = (props) => {
42
+ const [validationState, setValidationState] = useState({ isValid: true, errors: [] });
43
+ const { validateField: validateFormField } = useFormValidation();
44
+ // Handle onChange for immediate feedback
45
+ const handleChange = (event) => {
46
+ // Determine the value (checkbox vs other)
47
+ const value = event.target.type === 'checkbox' ? (event.target.checked ? event.target.value : '') : event.target.value;
48
+ // Call custom onChange handler synchronously so controlled inputs update immediately
49
+ const customOnChange = props.onChange || (props.parent && props.parent.onChange);
50
+ if (customOnChange) {
51
+ try {
52
+ customOnChange(value);
53
+ }
54
+ catch {
55
+ // swallow handler errors to avoid breaking validation flow
56
+ }
57
+ }
58
+ };
59
+ // Handle onBlur for full validation
60
+ const handleBlur = (event) => {
61
+ validateField(props, event).then(result => {
62
+ setValidationState(result);
63
+ if (props.id) {
64
+ validateFormField(props.id, result.isValid, result.errors);
65
+ }
66
+ });
67
+ };
68
+ const formValidate = _jsx(FormTooltip, { id: `${props.id}-validate`, mode: "validate", text: validationState.errors });
69
+ const inputProps = setupInputProps(props, props.display);
70
+ // Add validation event handlers
71
+ inputProps["onChange"] = handleChange;
72
+ inputProps["onBlur"] = handleBlur;
73
+ inputProps["onInput"] = handleChange; // Also handle onInput for tests
74
+ return { validationState, formValidate, inputProps, handleChange, handleBlur };
75
+ };
76
+ // Helper function for generating options (used by FormSelect, FormRadio, FormCheckbox)
77
+ const generateOptions = (options, parentProps, prefix, optionComponent) => {
78
+ let result = [];
79
+ for (let option in options) {
80
+ let key = option;
81
+ let thisOption = options[key];
82
+ // Create parent object without options to avoid circular references
83
+ const parentWithoutOptions = Object.fromEntries(Object.entries(parentProps).filter(([key]) => key !== 'options'));
84
+ thisOption.parent = { ...parentWithoutOptions };
85
+ let thisKey = prefix + "-" + parentProps.id + "-" + thisOption.value;
86
+ let newOption = React.createElement(optionComponent, { key: thisKey, ...thisOption });
87
+ result.push(newOption);
88
+ }
89
+ return result;
90
+ };
91
+ FormLabel.propTypes = {
92
+ id: PropTypes.string.isRequired,
93
+ label: PropTypes.string,
94
+ tooltip: PropTypes.string,
95
+ className: PropTypes.string,
96
+ };
97
+ FormLabel.defaultProps = {
98
+ id: "",
99
+ label: "",
100
+ tooltip: "",
101
+ };
102
+ function FormLabel(props) {
103
+ return (_jsxs(_Fragment, { children: [props.label && props.id
104
+ ? _jsx("label", { className: props.className || '', id: `lbl-${props.id}`, htmlFor: props.id, children: props.label })
105
+ : "", props.tooltip
106
+ ? _jsx(FormTooltip, { id: props.id, text: [props.tooltip] })
107
+ : ""] }));
108
+ }
109
+ FormTooltip.propTypes = {
110
+ id: PropTypes.string,
111
+ text: PropTypes.arrayOf(PropTypes.string).isRequired,
112
+ className: PropTypes.string,
113
+ mode: PropTypes.oneOf(['tooltip', 'validate']),
114
+ };
115
+ FormTooltip.defaultProps = {
116
+ id: "",
117
+ mode: 'tooltip',
118
+ };
119
+ function FormTooltip(props) {
120
+ const mode = props.mode || 'tooltip';
121
+ if (mode === 'validate' && props.text.length <= 0) {
122
+ return null;
123
+ }
124
+ const [showTooltip, setShowTooltip] = useState(false);
125
+ const content = props.text.map((item, index) => (_jsx("div", { className: "tooltip-text-item", children: item }, index)));
126
+ const toggleTooltip = () => setShowTooltip(!showTooltip);
127
+ const handleKeyDown = (event) => {
128
+ if (event.key === 'Enter' || event.key === ' ') {
129
+ event.preventDefault();
130
+ toggleTooltip();
131
+ }
132
+ };
133
+ const modeIcons = {
134
+ tooltip: 'ⓘ', // U+24D8
135
+ validate: '❌' // U+274C
136
+ };
137
+ let icon = modeIcons[mode];
138
+ let mouseEvents = {
139
+ onMouseEnter: () => setShowTooltip(true),
140
+ onMouseLeave: () => setShowTooltip(false),
141
+ };
142
+ let clickHandler = toggleTooltip;
143
+ return (_jsx(_Fragment, { children: _jsxs("div", { id: mode + "-" + props.id, className: `tooltip-container ${props.className || ''}`, children: [_jsx("span", { className: "tooltip-icon tooltip-icon-" + mode, ...mouseEvents, onClick: clickHandler, onKeyDown: handleKeyDown, "aria-label": "Show more info", "aria-expanded": showTooltip, "aria-describedby": showTooltip ? `${props.id}-tooltip` : undefined, tabIndex: 0, role: "button", children: icon }), showTooltip && _jsx("div", { className: "tooltip-text", role: "tooltip", id: `${props.id}-tooltip`, children: content })] }) }));
144
+ }
145
+ FormInput.propTypes = {
146
+ type: PropTypes.string,
147
+ id: PropTypes.string.isRequired,
148
+ name: PropTypes.string,
149
+ defaultValue: PropTypes.string,
150
+ value: PropTypes.string,
151
+ list: PropTypes.string,
152
+ listItems: PropTypes.string, /* this one is mine */
153
+ size: PropTypes.string,
154
+ maxLength: PropTypes.string,
155
+ placeholder: PropTypes.string,
156
+ autoComplete: PropTypes.string,
157
+ "aria-label": PropTypes.string,
158
+ min: PropTypes.string,
159
+ max: PropTypes.string,
160
+ step: PropTypes.string,
161
+ // flag attributes
162
+ autoFocus: PropTypes.string,
163
+ disabled: PropTypes.string,
164
+ readOnly: PropTypes.string,
165
+ required: PropTypes.string,
166
+ // className,
167
+ // data-mapping, data-component-endpoint, data-testid
168
+ // aria-invalid, aria-describedby,
169
+ // ----- for calculations
170
+ display: PropTypes.string,
171
+ label: PropTypes.string,
172
+ tooltip: PropTypes.string,
173
+ className: PropTypes.string,
174
+ validate: PropTypes.string,
175
+ onChange: PropTypes.func,
176
+ };
177
+ export function FormInput(props) {
178
+ const { formValidate, inputProps } = useFormComponent(props);
179
+ let formDataList = props.list && props.list in FVF
180
+ ? FVF[props.list]
181
+ : props.list && props.listItems
182
+ ? props.listItems.split(',')
183
+ : undefined;
184
+ return (_jsxs("div", { children: [props.type == "checkbox" ? _jsx("input", { ...inputProps }) : "", _jsx(FormLabel, { id: props.id, label: props.label }, "label-" + props.id), props.tooltip ? _jsx(FormTooltip, { id: props.id, text: [props.tooltip] }) : "", props.display == "vertical" ? formValidate : "", props.type != "checkbox" ? _jsx("input", { ...inputProps }) : "", formDataList && Array.isArray(formDataList) ? _jsx(FormDataList, { id: props.list ?? '', items: formDataList }) : "", props.display != "vertical" ? formValidate : ""] }));
185
+ }
186
+ FormSelect.propTypes = {
187
+ id: PropTypes.string.isRequired,
188
+ name: PropTypes.string,
189
+ size: PropTypes.string,
190
+ autoComplete: PropTypes.string,
191
+ defaultValue: PropTypes.oneOfType([
192
+ PropTypes.string,
193
+ PropTypes.array
194
+ ]),
195
+ // flag attributes
196
+ autoFocus: PropTypes.string,
197
+ disabled: PropTypes.string,
198
+ multiple: PropTypes.string,
199
+ readOnly: PropTypes.string,
200
+ required: PropTypes.string,
201
+ // selected: PropTypes.string, // not used
202
+ // ----- for calculations
203
+ options: PropTypes.array,
204
+ display: PropTypes.string,
205
+ label: PropTypes.string,
206
+ tooltip: PropTypes.string,
207
+ className: PropTypes.string,
208
+ validate: PropTypes.string,
209
+ onChange: PropTypes.func,
210
+ };
211
+ export function FormSelect(props) {
212
+ const { formValidate, inputProps } = useFormComponent(props);
213
+ const options = generateOptions(props.options || [], props, "select", FormSelectOption);
214
+ return (_jsxs("div", { children: [_jsx(FormLabel, { id: props.id, label: props.label }, "label-" + props.id), props.tooltip ? _jsx(FormTooltip, { id: props.id, text: [props.tooltip] }) : "", props.display == "vertical" ? formValidate : "", _jsx("select", { ...inputProps, suppressHydrationWarning: true, children: options }), props.display != "vertical" ? formValidate : ""] }));
215
+ }
216
+ FormSelectOption.propTypes = {
217
+ text: PropTypes.string,
218
+ value: PropTypes.string,
219
+ // flag attributes
220
+ disabled: PropTypes.bool,
221
+ // selected : PropTypes.string
222
+ };
223
+ function FormSelectOption(props) {
224
+ const { text, disabled, value, ...otherProps } = props;
225
+ const inputProps = {
226
+ ...otherProps,
227
+ ...(disabled !== null && disabled !== undefined ? { disabled } : {}),
228
+ ...(value !== null && value !== undefined ? { value } : {})
229
+ };
230
+ return (_jsx("option", { ...inputProps, children: text }));
231
+ }
232
+ FormTextarea.propTypes = {
233
+ id: PropTypes.string.isRequired,
234
+ name: PropTypes.string,
235
+ rows: PropTypes.string,
236
+ cols: PropTypes.string,
237
+ defaultValue: PropTypes.string,
238
+ maxLength: PropTypes.number,
239
+ placeholder: PropTypes.string,
240
+ autoComplete: PropTypes.string,
241
+ // flag attributes
242
+ autoFocus: PropTypes.string,
243
+ disabled: PropTypes.string,
244
+ readOnly: PropTypes.string,
245
+ required: PropTypes.string,
246
+ // ----- for calculations
247
+ display: PropTypes.string,
248
+ label: PropTypes.string,
249
+ tooltip: PropTypes.string,
250
+ className: PropTypes.string,
251
+ validate: PropTypes.string,
252
+ onChange: PropTypes.func,
253
+ };
254
+ export function FormTextarea(props) {
255
+ const { formValidate, inputProps } = useFormComponent(props);
256
+ return (_jsxs("div", { children: [_jsx(FormLabel, { id: props.id, label: props.label }, "label-" + props.id), props.tooltip ? _jsx(FormTooltip, { id: props.id, text: [props.tooltip] }) : "", props.display == "vertical" ? formValidate : "", _jsx("textarea", { ...inputProps }), props.display != "vertical" ? formValidate : ""] }));
257
+ }
258
+ FormRadio.propTypes = {
259
+ id: PropTypes.string.isRequired, // not using?
260
+ name: PropTypes.string.isRequired,
261
+ options: PropTypes.array,
262
+ // flag attributes
263
+ autoFocus: PropTypes.string,
264
+ disabled: PropTypes.string,
265
+ readOnly: PropTypes.string,
266
+ required: PropTypes.string,
267
+ // ? selected: PropTypes.string,
268
+ // ----- for calculations
269
+ display: PropTypes.string,
270
+ label: PropTypes.string,
271
+ tooltip: PropTypes.string,
272
+ validate: PropTypes.string,
273
+ onChange: PropTypes.func,
274
+ };
275
+ export function FormRadio(props) {
276
+ const { formValidate } = useFormComponent(props);
277
+ const options = generateOptions(props.options || [], props, "radio", FormRadioOption);
278
+ return (_jsxs("div", { children: [_jsx(FormLabel, { id: props.name, label: props.label }, "label-" + props.id), props.tooltip ? _jsx(FormTooltip, { id: props.id, text: [props.tooltip] }) : "", props.display == "vertical" ? formValidate : "", options, props.display != "vertical" ? formValidate : ""] }));
279
+ }
280
+ FormRadioOption.propTypes = {
281
+ name: PropTypes.string,
282
+ text: PropTypes.string,
283
+ value: PropTypes.string.isRequired,
284
+ // flag attributes
285
+ checked: PropTypes.string,
286
+ // ----- for calculations
287
+ parent: PropTypes.any,
288
+ };
289
+ function FormRadioOption(props) {
290
+ const inputProps = setupInputProps(props);
291
+ return (_jsxs("span", { className: props.parent.display == "vertical" ? "displayVertical" : "", children: [_jsx("input", { type: "radio", id: `${props.parent.name}-${props.value}`, name: props.parent.name, value: props.value,
292
+ // defaultChecked={!!props.checked}
293
+ defaultChecked: props.checked, required: !!props.parent.required, ...inputProps }), _jsx("label", { htmlFor: `${props.parent.name}-${props.value}`, children: props.text })] }));
294
+ }
295
+ FormCheckbox.propTypes = {
296
+ id: PropTypes.string.isRequired,
297
+ name: PropTypes.string.isRequired,
298
+ options: PropTypes.array,
299
+ // flag attributes
300
+ autoFocus: PropTypes.string,
301
+ disabled: PropTypes.string,
302
+ readOnly: PropTypes.string,
303
+ // ----- for calculations
304
+ display: PropTypes.string,
305
+ label: PropTypes.string,
306
+ tooltip: PropTypes.string,
307
+ className: PropTypes.string,
308
+ validate: PropTypes.string,
309
+ onChange: PropTypes.func,
310
+ };
311
+ export function FormCheckbox(props) {
312
+ const { formValidate } = useFormComponent(props);
313
+ const options = generateOptions(props.options || [], props, "checkbox", FormCheckboxOption);
314
+ return (_jsxs("div", { children: [_jsx(FormLabel, { id: props.name, label: props.label }, "label-" + props.id), props.tooltip ? _jsx(FormTooltip, { id: props.id, text: [props.tooltip] }) : "", props.display == "vertical" ? formValidate : "", options, props.display != "vertical" ? formValidate : ""] }));
315
+ }
316
+ FormCheckboxOption.propTypes = {
317
+ text: PropTypes.string.isRequired,
318
+ value: PropTypes.string.isRequired,
319
+ // flag attributes
320
+ selected: PropTypes.string,
321
+ // ----- for calculations
322
+ parent: PropTypes.any,
323
+ };
324
+ function FormCheckboxOption(props) {
325
+ const inputProps = setupInputProps(props);
326
+ return (_jsxs("span", { className: props.parent.display == "vertical" ? "displayVertical" : "", children: [_jsx("input", { type: "checkbox", id: props.parent.name + "_" + props.text, name: props.text, value: props.value, ...inputProps }), _jsx("label", { htmlFor: props.text, children: props.text })] }));
327
+ }
328
+ FormButton.propTypes = {
329
+ type: PropTypes.string,
330
+ id: PropTypes.string.isRequired,
331
+ text: PropTypes.string,
332
+ // ----- for calculations
333
+ className: PropTypes.string,
334
+ onClick: PropTypes.func.isRequired
335
+ };
336
+ export function FormButton(props) {
337
+ return (_jsx("div", { children: _jsx("button", { type: props.type, id: props.id, className: props.className || "", onClick: props.onClick, children: props.text }) }));
338
+ }
339
+ FormDataList.propTypes = {
340
+ id: PropTypes.string.isRequired,
341
+ items: PropTypes.array,
342
+ };
343
+ export function FormDataList(props) {
344
+ const options = [];
345
+ for (const item in props.items) {
346
+ let key = item;
347
+ const thisItem = props.items[key];
348
+ const newOption = _jsx("option", { value: thisItem }, props.id + '-' + thisItem);
349
+ options.push(newOption);
350
+ }
351
+ return (_jsx("datalist", { id: props.id, children: options }));
352
+ }
353
+ FormFieldset.propTypes = {};
354
+ export function FormFieldset() {
355
+ return (_jsx(_Fragment, {}));
356
+ }
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import * as FC from './formcomponents';
5
+ import { generateKey } from './formutils';
6
+ import { FormValidationProvider, useFormValidation } from './formvalidator';
7
+ const debug = false;
8
+ /* ===== FORM ENGINE =====
9
+ Generate all the elements to display a form */
10
+ FormEngine.propTypes = {
11
+ name: PropTypes.string,
12
+ id: PropTypes.string,
13
+ method: PropTypes.string,
14
+ onSubmitHandler: PropTypes.func,
15
+ formData: PropTypes.object.isRequired
16
+ };
17
+ function FormEngineInner(props) {
18
+ const { validateAllFields } = useFormValidation();
19
+ function generateFormProps(props) {
20
+ // GENERATE PROPS TO RENDER THE FORM CONTAINER, INTERNAL FUNCTION
21
+ if (debug)
22
+ console.log("Generating Form Props");
23
+ const formProps = JSON.parse(JSON.stringify(props));
24
+ ['formData', 'onSubmitHandler'].forEach(e => delete formProps[e]);
25
+ return formProps;
26
+ }
27
+ generateNewFields.propTypes = {
28
+ formData: PropTypes.any.isRequired,
29
+ };
30
+ function generateNewFields(props) {
31
+ // CORE OF THE FORM ENGINE - CONVERT JSON TO COMPONENTS - INTERNAL
32
+ if (debug)
33
+ console.log("Generating Form Fields");
34
+ const newFields = [];
35
+ const formFields = props.formData.fields;
36
+ if (props.formData && formFields) {
37
+ // const thisFields = formFields;
38
+ for (let field = 0; field < formFields.length; field++) {
39
+ const thisField = formFields[field];
40
+ // Shallow clone props to preserve function handlers (JSON stringify drops functions)
41
+ const newProps = { ...thisField.props };
42
+ newProps.key = thisField.props.id || generateKey();
43
+ // Convert string numeric props to numbers where needed
44
+ const numericProps = ['maxLength', 'minLength', 'rows', 'cols', 'size', 'step'];
45
+ numericProps.forEach(prop => {
46
+ if (newProps[prop] !== undefined &&
47
+ newProps[prop] !== null &&
48
+ newProps[prop] !== '') {
49
+ // Only convert if the value is not already a number
50
+ if (typeof newProps[prop] === 'string') {
51
+ const num = Number(newProps[prop]);
52
+ if (!isNaN(num)) {
53
+ newProps[prop] = num;
54
+ }
55
+ }
56
+ }
57
+ });
58
+ const componentName = thisField.component;
59
+ const newElementType = FC[componentName];
60
+ const newElement = React.createElement(newElementType, newProps);
61
+ newFields.push(newElement);
62
+ }
63
+ }
64
+ return newFields;
65
+ }
66
+ function handleSubmit(event) {
67
+ // HANDLES THE FORM ACTION / FORM SUBMIT - EXPOSED EXTERNAL
68
+ event.preventDefault();
69
+ // Check if form is valid before submission
70
+ if (!validateAllFields()) {
71
+ // Form has validation errors, don't submit
72
+ return false;
73
+ }
74
+ if (props.onSubmitHandler)
75
+ props.onSubmitHandler(event);
76
+ return true;
77
+ }
78
+ return (_jsx("form", { ...generateFormProps(props), onSubmit: (event) => { handleSubmit(event); }, suppressHydrationWarning: true, children: generateNewFields(props) }));
79
+ }
80
+ export function FormEngine(props) {
81
+ return (_jsx(FormValidationProvider, { children: _jsx(FormEngineInner, { ...props }) }));
82
+ }