@pixelated-tech/components 3.2.14 → 3.3.1

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 (202) hide show
  1. package/README.COMPONENTS.md +520 -31
  2. package/README.md +163 -49
  3. package/dist/components/cms/cloudinary.image.js +1 -0
  4. package/dist/components/cms/wordpress.components.js +1 -0
  5. package/dist/components/general/sidepanel.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-accordion.css +10 -0
  9. package/dist/components/menu/menu-accordion.js +2 -1
  10. package/dist/components/menu/menu-simple.css +0 -7
  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/sitemap.js +1 -1
  16. package/dist/components/shoppingcart/shoppingcart.components.js +4 -4
  17. package/dist/components/sitebuilder/config/CompoundFontSelector.css +25 -0
  18. package/dist/components/sitebuilder/config/CompoundFontSelector.js +41 -0
  19. package/dist/components/sitebuilder/config/ConfigBuilder.css +277 -0
  20. package/dist/components/sitebuilder/config/ConfigBuilder.js +380 -0
  21. package/dist/components/sitebuilder/config/ConfigEngine.js +82 -0
  22. package/dist/components/sitebuilder/config/FontSelector.css +82 -0
  23. package/dist/components/sitebuilder/config/FontSelector.js +115 -0
  24. package/dist/components/sitebuilder/config/google-fonts.js +112 -0
  25. package/dist/components/{pagebuilder → sitebuilder}/form/form.css +55 -34
  26. package/dist/components/sitebuilder/form/formbuilder.js +107 -0
  27. package/dist/components/sitebuilder/form/formcomponents.js +380 -0
  28. package/dist/components/sitebuilder/form/formengine.js +82 -0
  29. package/dist/components/{pagebuilder/form/form.js → sitebuilder/form/formextractor.js} +10 -211
  30. package/dist/components/sitebuilder/form/formutils.js +206 -0
  31. package/dist/components/sitebuilder/form/formvalidator.js +123 -0
  32. package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentPropertiesForm.js +1 -1
  33. package/dist/components/{pagebuilder → sitebuilder/page}/components/PageBuilderUI.js +2 -2
  34. package/dist/components/{pagebuilder → sitebuilder/page}/components/PageEngine.js +1 -1
  35. package/dist/components/sitebuilder/page/documentation/api-examples/save-route-example.js +37 -0
  36. package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentMap.js +3 -3
  37. package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentMetadata.js +2 -2
  38. package/dist/components/{pagebuilder → sitebuilder/page}/lib/pageStorageContentful.js +2 -2
  39. package/dist/components/sitebuilder/page/lib/pageStorageTypes.js +1 -0
  40. package/dist/components/structured/markdown.js +1 -0
  41. package/dist/components/structured/recipe.js +1 -0
  42. package/dist/components/structured/timeline.js +1 -0
  43. package/dist/css/pixelated.global.css +0 -35
  44. package/dist/css/pixelated.grid.scss +4 -0
  45. package/dist/css/pixelated.visualdesign.scss +88 -0
  46. package/dist/data/form.json +18 -18
  47. package/dist/data/routes.json +32 -1
  48. package/dist/data/shipping.to.json +9 -9
  49. package/dist/data/siteinfo-form.json +200 -0
  50. package/dist/data/visualdesignform.json +244 -0
  51. package/dist/index.js +33 -21
  52. package/dist/index.server.js +24 -17
  53. package/dist/types/components/cms/cloudinary.image.d.ts.map +1 -1
  54. package/dist/types/components/cms/wordpress.components.d.ts.map +1 -1
  55. package/dist/types/components/general/semantic.d.ts +3 -3
  56. package/dist/types/components/general/tab.d.ts +18 -0
  57. package/dist/types/components/general/tab.d.ts.map +1 -0
  58. package/dist/types/components/menu/menu-accordion.d.ts.map +1 -1
  59. package/dist/types/components/seo/metadata.components.d.ts +0 -17
  60. package/dist/types/components/seo/metadata.components.d.ts.map +1 -1
  61. package/dist/types/components/seo/{metadata.d.ts → metadata.functions.d.ts} +15 -1
  62. package/dist/types/components/seo/metadata.functions.d.ts.map +1 -0
  63. package/dist/types/components/seo/schema-blogposting.d.ts +1 -25
  64. package/dist/types/components/seo/schema-blogposting.d.ts.map +1 -1
  65. package/dist/types/components/seo/schema-blogposting.functions.d.ts +26 -0
  66. package/dist/types/components/seo/schema-blogposting.functions.d.ts.map +1 -0
  67. package/dist/types/components/seo/sitemap.d.ts.map +1 -1
  68. package/dist/types/components/shoppingcart/shoppingcart.components.d.ts +1 -1
  69. package/dist/types/components/sitebuilder/config/CompoundFontSelector.d.ts +23 -0
  70. package/dist/types/components/sitebuilder/config/CompoundFontSelector.d.ts.map +1 -0
  71. package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts +354 -0
  72. package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts.map +1 -0
  73. package/dist/types/components/sitebuilder/config/ConfigEngine.d.ts +10 -0
  74. package/dist/types/components/sitebuilder/config/ConfigEngine.d.ts.map +1 -0
  75. package/dist/types/components/sitebuilder/config/FontSelector.d.ts +27 -0
  76. package/dist/types/components/sitebuilder/config/FontSelector.d.ts.map +1 -0
  77. package/dist/types/components/sitebuilder/config/google-fonts.d.ts +41 -0
  78. package/dist/types/components/sitebuilder/config/google-fonts.d.ts.map +1 -0
  79. package/dist/types/components/sitebuilder/form/formbuilder.d.ts +11 -0
  80. package/dist/types/components/sitebuilder/form/formbuilder.d.ts.map +1 -0
  81. package/dist/types/components/{pagebuilder → sitebuilder}/form/formcomponents.d.ts +15 -17
  82. package/dist/types/components/sitebuilder/form/formcomponents.d.ts.map +1 -0
  83. package/dist/types/components/{pagebuilder/form/form.submit.d.ts → sitebuilder/form/formemailer.d.ts} +1 -1
  84. package/dist/types/components/sitebuilder/form/formemailer.d.ts.map +1 -0
  85. package/dist/types/components/sitebuilder/form/formengine.d.ts +14 -0
  86. package/dist/types/components/sitebuilder/form/formengine.d.ts.map +1 -0
  87. package/dist/types/components/sitebuilder/form/formextractor.d.ts +25 -0
  88. package/dist/types/components/sitebuilder/form/formextractor.d.ts.map +1 -0
  89. package/dist/types/components/{pagebuilder/form/formvalidations.d.ts → sitebuilder/form/formfieldvalidations.d.ts} +1 -1
  90. package/dist/types/components/sitebuilder/form/formfieldvalidations.d.ts.map +1 -0
  91. package/dist/types/components/sitebuilder/form/formtypes.d.ts +66 -0
  92. package/dist/types/components/sitebuilder/form/formtypes.d.ts.map +1 -0
  93. package/dist/types/components/sitebuilder/form/formutils.d.ts +20 -0
  94. package/dist/types/components/sitebuilder/form/formutils.d.ts.map +1 -0
  95. package/dist/types/components/sitebuilder/form/formvalidator.d.ts +20 -0
  96. package/dist/types/components/sitebuilder/form/formvalidator.d.ts.map +1 -0
  97. package/dist/types/components/sitebuilder/page/components/ComponentPropertiesForm.d.ts.map +1 -0
  98. package/dist/types/components/sitebuilder/page/components/ComponentSelector.d.ts.map +1 -0
  99. package/dist/types/components/sitebuilder/page/components/ComponentTree.d.ts.map +1 -0
  100. package/dist/types/components/{pagebuilder → sitebuilder/page}/components/PageBuilderUI.d.ts +1 -1
  101. package/dist/types/components/sitebuilder/page/components/PageBuilderUI.d.ts.map +1 -0
  102. package/dist/types/components/sitebuilder/page/components/PageEngine.d.ts.map +1 -0
  103. package/dist/types/components/sitebuilder/page/components/SaveLoadSection.d.ts.map +1 -0
  104. package/dist/types/components/sitebuilder/page/documentation/api-examples/save-route-example.d.ts +6 -0
  105. package/dist/types/components/sitebuilder/page/documentation/api-examples/save-route-example.d.ts.map +1 -0
  106. package/dist/types/components/sitebuilder/page/lib/componentGeneration.d.ts.map +1 -0
  107. package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentMap.d.ts +3 -3
  108. package/dist/types/components/sitebuilder/page/lib/componentMap.d.ts.map +1 -0
  109. package/dist/types/components/sitebuilder/page/lib/componentMetadata.d.ts.map +1 -0
  110. package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageContentful.d.ts +1 -1
  111. package/dist/types/components/sitebuilder/page/lib/pageStorageContentful.d.ts.map +1 -0
  112. package/dist/types/components/sitebuilder/page/lib/pageStorageLocal.d.ts.map +1 -0
  113. package/dist/types/components/sitebuilder/page/lib/pageStorageTypes.d.ts.map +1 -0
  114. package/dist/types/components/sitebuilder/page/lib/propTypeIntrospection.d.ts.map +1 -0
  115. package/dist/types/components/sitebuilder/page/lib/types.d.ts.map +1 -0
  116. package/dist/types/components/sitebuilder/page/lib/usePageBuilder.d.ts.map +1 -0
  117. package/dist/types/components/structured/markdown.d.ts.map +1 -1
  118. package/dist/types/components/structured/recipe.d.ts.map +1 -1
  119. package/dist/types/components/structured/timeline.d.ts.map +1 -1
  120. package/dist/types/index.d.ts +33 -20
  121. package/dist/types/index.server.d.ts +23 -16
  122. package/dist/types/stories/general/tab.stories.d.ts +45 -0
  123. package/dist/types/stories/general/tab.stories.d.ts.map +1 -0
  124. package/dist/types/stories/seo/seo.metadata.stories.d.ts +1 -1
  125. package/dist/types/stories/seo/seo.metadata.stories.d.ts.map +1 -1
  126. package/dist/types/stories/sitebuilder/compoundfontselector.stories.d.ts +51 -0
  127. package/dist/types/stories/sitebuilder/compoundfontselector.stories.d.ts.map +1 -0
  128. package/dist/types/stories/sitebuilder/configbuilder.stories.d.ts +103 -0
  129. package/dist/types/stories/sitebuilder/configbuilder.stories.d.ts.map +1 -0
  130. package/dist/types/stories/{pagebuilder → sitebuilder}/form-builder.stories.d.ts +1 -1
  131. package/dist/types/stories/sitebuilder/form-builder.stories.d.ts.map +1 -0
  132. package/dist/types/stories/{pagebuilder → sitebuilder}/form-engine.stories.d.ts +1 -1
  133. package/dist/types/stories/sitebuilder/form-engine.stories.d.ts.map +1 -0
  134. package/dist/types/stories/{pagebuilder → sitebuilder}/form-extractor.stories.d.ts +1 -1
  135. package/dist/types/stories/sitebuilder/form-extractor.stories.d.ts.map +1 -0
  136. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.stories.d.ts +1 -1
  137. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.stories.d.ts.map +1 -1
  138. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.usageguide.stories.d.ts +1 -1
  139. package/dist/types/stories/{pagebuilder → sitebuilder}/pagebuilder.usageguide.stories.d.ts.map +1 -1
  140. package/dist/types/stories/{pagebuilder → sitebuilder}/pageengine.stories.d.ts +1 -1
  141. package/dist/types/stories/{pagebuilder → sitebuilder}/pageengine.stories.d.ts.map +1 -1
  142. package/dist/types/tests/compoundfontselector.test.d.ts +2 -0
  143. package/dist/types/tests/compoundfontselector.test.d.ts.map +1 -0
  144. package/dist/types/tests/configbuilder.test.d.ts +2 -0
  145. package/dist/types/tests/configbuilder.test.d.ts.map +1 -0
  146. package/dist/types/tests/configengine.test.d.ts +2 -0
  147. package/dist/types/tests/configengine.test.d.ts.map +1 -0
  148. package/dist/types/tests/fontselector.test.d.ts +2 -0
  149. package/dist/types/tests/fontselector.test.d.ts.map +1 -0
  150. package/dist/types/tests/tab.test.d.ts +2 -0
  151. package/dist/types/tests/tab.test.d.ts.map +1 -0
  152. package/package.json +15 -12
  153. package/dist/components/pagebuilder/form/formcomponents.js +0 -359
  154. package/dist/components/seo/metadata.js +0 -108
  155. package/dist/types/components/pagebuilder/components/ComponentPropertiesForm.d.ts.map +0 -1
  156. package/dist/types/components/pagebuilder/components/ComponentSelector.d.ts.map +0 -1
  157. package/dist/types/components/pagebuilder/components/ComponentTree.d.ts.map +0 -1
  158. package/dist/types/components/pagebuilder/components/PageBuilderUI.d.ts.map +0 -1
  159. package/dist/types/components/pagebuilder/components/PageEngine.d.ts.map +0 -1
  160. package/dist/types/components/pagebuilder/components/SaveLoadSection.d.ts.map +0 -1
  161. package/dist/types/components/pagebuilder/form/form.d.ts +0 -46
  162. package/dist/types/components/pagebuilder/form/form.d.ts.map +0 -1
  163. package/dist/types/components/pagebuilder/form/form.submit.d.ts.map +0 -1
  164. package/dist/types/components/pagebuilder/form/formcomponents.d.ts.map +0 -1
  165. package/dist/types/components/pagebuilder/form/formvalidations.d.ts.map +0 -1
  166. package/dist/types/components/pagebuilder/lib/componentGeneration.d.ts.map +0 -1
  167. package/dist/types/components/pagebuilder/lib/componentMap.d.ts.map +0 -1
  168. package/dist/types/components/pagebuilder/lib/componentMetadata.d.ts.map +0 -1
  169. package/dist/types/components/pagebuilder/lib/pageStorageContentful.d.ts.map +0 -1
  170. package/dist/types/components/pagebuilder/lib/pageStorageLocal.d.ts.map +0 -1
  171. package/dist/types/components/pagebuilder/lib/pageStorageTypes.d.ts.map +0 -1
  172. package/dist/types/components/pagebuilder/lib/propTypeIntrospection.d.ts.map +0 -1
  173. package/dist/types/components/pagebuilder/lib/types.d.ts.map +0 -1
  174. package/dist/types/components/pagebuilder/lib/usePageBuilder.d.ts.map +0 -1
  175. package/dist/types/components/seo/metadata.d.ts.map +0 -1
  176. package/dist/types/stories/pagebuilder/form-builder.stories.d.ts.map +0 -1
  177. package/dist/types/stories/pagebuilder/form-engine.stories.d.ts.map +0 -1
  178. package/dist/types/stories/pagebuilder/form-extractor.stories.d.ts.map +0 -1
  179. /package/dist/components/{pagebuilder/form/form.submit.js → sitebuilder/form/formemailer.js} +0 -0
  180. /package/dist/components/{pagebuilder/form/formvalidations.js → sitebuilder/form/formfieldvalidations.js} +0 -0
  181. /package/dist/components/{pagebuilder/lib/pageStorageTypes.js → sitebuilder/form/formtypes.js} +0 -0
  182. /package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentSelector.js +0 -0
  183. /package/dist/components/{pagebuilder → sitebuilder/page}/components/ComponentTree.js +0 -0
  184. /package/dist/components/{pagebuilder → sitebuilder/page}/components/SaveLoadSection.js +0 -0
  185. /package/dist/components/{pagebuilder → sitebuilder/page}/components/pagebuilder.scss +0 -0
  186. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/componentGeneration.js +0 -0
  187. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/pageStorageLocal.js +0 -0
  188. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/propTypeIntrospection.js +0 -0
  189. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/types.js +0 -0
  190. /package/dist/components/{pagebuilder → sitebuilder/page}/lib/usePageBuilder.js +0 -0
  191. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentPropertiesForm.d.ts +0 -0
  192. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentSelector.d.ts +0 -0
  193. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/ComponentTree.d.ts +0 -0
  194. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/PageEngine.d.ts +0 -0
  195. /package/dist/types/components/{pagebuilder → sitebuilder/page}/components/SaveLoadSection.d.ts +0 -0
  196. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentGeneration.d.ts +0 -0
  197. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/componentMetadata.d.ts +0 -0
  198. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageLocal.d.ts +0 -0
  199. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/pageStorageTypes.d.ts +0 -0
  200. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/propTypeIntrospection.d.ts +0 -0
  201. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/types.d.ts +0 -0
  202. /package/dist/types/components/{pagebuilder → sitebuilder/page}/lib/usePageBuilder.d.ts +0 -0
@@ -0,0 +1,380 @@
1
+ 'use client';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import React, { useState } from "react";
4
+ import PropTypes from "prop-types";
5
+ import { validateField } from "./formvalidator";
6
+ import { useFormValidation } from "./formvalidator";
7
+ import * as FVF from "./formfieldvalidations";
8
+ import { FontSelector } from "../config/FontSelector";
9
+ import { CompoundFontSelector } from "../config/CompoundFontSelector";
10
+ import "./form.css";
11
+ /*
12
+ InferProps to generate Types
13
+ https://amanhimself.dev/blog/prop-types-in-react-and-typescript/#inferring-proptypes-in-typescript
14
+ */
15
+ // Shared helper to setup input props for form components
16
+ const setupInputProps = (props, display) => {
17
+ // Clone props efficiently using destructuring instead of JSON.parse/stringify
18
+ let inputProps = { ...props };
19
+ // Remove props that shouldn't go to DOM
20
+ inputProps = Object.fromEntries(Object.entries(inputProps).filter(([key]) => !['display', 'label', 'listItems', 'validate', 'options', 'parent', 'text', 'checked'].includes(key)));
21
+ // Set className based on display mode
22
+ inputProps["className"] = (display == "vertical") ? "displayVertical" : "";
23
+ // Handle controlled vs uncontrolled inputs properly
24
+ // If value is provided, use it for controlled behavior
25
+ // Otherwise, use defaultValue for uncontrolled behavior
26
+ if (props.value !== undefined) {
27
+ inputProps["value"] = props.value;
28
+ // Remove defaultValue if value is present to avoid conflicts
29
+ delete inputProps["defaultValue"];
30
+ }
31
+ else if (props.defaultValue !== undefined) {
32
+ inputProps["defaultValue"] = props.defaultValue;
33
+ }
34
+ // For radio buttons, prioritize defaultChecked over checked to let browser handle state
35
+ // This prevents React's "both checked and defaultChecked" error
36
+ if (props.type === 'radio' || (props.parent && props.parent.type === 'radio')) {
37
+ if (props.checked !== undefined) {
38
+ delete inputProps["checked"];
39
+ }
40
+ }
41
+ return inputProps;
42
+ };
43
+ // Custom hook for common form component logic
44
+ const useFormComponent = (props) => {
45
+ const [validationState, setValidationState] = useState({ isValid: true, errors: [] });
46
+ const { validateField: validateFormField } = useFormValidation();
47
+ // Handle onChange for immediate feedback
48
+ const handleChange = (event) => {
49
+ // Determine the value (checkbox vs other)
50
+ const value = event.target.type === 'checkbox' ? (event.target.checked ? event.target.value : '') : event.target.value;
51
+ // Call custom onChange handler synchronously so controlled inputs update immediately
52
+ const customOnChange = props.onChange || (props.parent && props.parent.onChange);
53
+ if (customOnChange) {
54
+ try {
55
+ customOnChange(value);
56
+ }
57
+ catch {
58
+ // swallow handler errors to avoid breaking validation flow
59
+ }
60
+ }
61
+ };
62
+ // Handle onBlur for full validation
63
+ const handleBlur = (event) => {
64
+ validateField(props, event).then(result => {
65
+ setValidationState(result);
66
+ if (props.id) {
67
+ validateFormField(props.id, result.isValid, result.errors);
68
+ }
69
+ });
70
+ };
71
+ const formValidate = _jsx(FormTooltip, { id: `${props.id}-validate`, mode: "validate", text: validationState.errors });
72
+ const inputProps = setupInputProps(props, props.display);
73
+ // Add validation event handlers
74
+ inputProps["onChange"] = handleChange;
75
+ inputProps["onBlur"] = handleBlur;
76
+ inputProps["onInput"] = handleChange; // Also handle onInput for tests
77
+ return { validationState, formValidate, inputProps, handleChange, handleBlur };
78
+ };
79
+ // Helper function for generating options (used by FormSelect, FormRadio, FormCheckbox)
80
+ const generateOptions = (options, parentProps, prefix, optionComponent) => {
81
+ let result = [];
82
+ for (let option in options) {
83
+ let key = option;
84
+ let thisOption = options[key];
85
+ // Create parent object without options to avoid circular references
86
+ const parentWithoutOptions = Object.fromEntries(Object.entries(parentProps).filter(([key]) => key !== 'options'));
87
+ thisOption.parent = { ...parentWithoutOptions };
88
+ let thisKey = prefix + "-" + parentProps.id + "-" + thisOption.value;
89
+ let newOption = React.createElement(optionComponent, { key: thisKey, ...thisOption });
90
+ result.push(newOption);
91
+ }
92
+ return result;
93
+ };
94
+ FormLabel.propTypes = {
95
+ id: PropTypes.string.isRequired,
96
+ label: PropTypes.string,
97
+ tooltip: PropTypes.string,
98
+ className: PropTypes.string,
99
+ };
100
+ FormLabel.defaultProps = {
101
+ id: "",
102
+ label: "",
103
+ tooltip: "",
104
+ };
105
+ function FormLabel(props) {
106
+ return (_jsxs(_Fragment, { children: [props.label && props.id
107
+ ? _jsx("label", { className: props.className || '', id: `lbl-${props.id}`, htmlFor: props.id, children: props.label })
108
+ : "", props.tooltip
109
+ ? _jsx(FormTooltip, { id: props.id, text: [props.tooltip] })
110
+ : ""] }));
111
+ }
112
+ FormTooltip.propTypes = {
113
+ id: PropTypes.string,
114
+ text: PropTypes.arrayOf(PropTypes.string).isRequired,
115
+ className: PropTypes.string,
116
+ mode: PropTypes.oneOf(['tooltip', 'validate']),
117
+ };
118
+ FormTooltip.defaultProps = {
119
+ id: "",
120
+ mode: 'tooltip',
121
+ };
122
+ function FormTooltip(props) {
123
+ const mode = props.mode || 'tooltip';
124
+ if (mode === 'validate' && props.text.length <= 0) {
125
+ return null;
126
+ }
127
+ const [showTooltip, setShowTooltip] = useState(false);
128
+ const content = props.text.map((item, index) => (_jsx("div", { className: "tooltip-text-item", children: item }, index)));
129
+ const toggleTooltip = () => setShowTooltip(!showTooltip);
130
+ const handleKeyDown = (event) => {
131
+ if (event.key === 'Enter' || event.key === ' ') {
132
+ event.preventDefault();
133
+ toggleTooltip();
134
+ }
135
+ };
136
+ const modeIcons = {
137
+ tooltip: 'ⓘ', // U+24D8
138
+ validate: '❌' // U+274C
139
+ };
140
+ let icon = modeIcons[mode];
141
+ let mouseEvents = {
142
+ onMouseEnter: () => setShowTooltip(true),
143
+ onMouseLeave: () => setShowTooltip(false),
144
+ };
145
+ let clickHandler = toggleTooltip;
146
+ 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 })] }) }));
147
+ }
148
+ FormInput.propTypes = {
149
+ type: PropTypes.string,
150
+ id: PropTypes.string.isRequired,
151
+ name: PropTypes.string,
152
+ defaultValue: PropTypes.string,
153
+ value: PropTypes.string,
154
+ list: PropTypes.string,
155
+ listItems: PropTypes.string, /* this one is mine */
156
+ size: PropTypes.string,
157
+ maxLength: PropTypes.string,
158
+ placeholder: PropTypes.string,
159
+ autoComplete: PropTypes.string,
160
+ "aria-label": PropTypes.string,
161
+ min: PropTypes.string,
162
+ max: PropTypes.string,
163
+ step: PropTypes.string,
164
+ // flag attributes
165
+ autoFocus: PropTypes.string,
166
+ disabled: PropTypes.string,
167
+ readOnly: PropTypes.string,
168
+ required: PropTypes.string,
169
+ // className,
170
+ // data-mapping, data-component-endpoint, data-testid
171
+ // aria-invalid, aria-describedby,
172
+ // ----- for calculations
173
+ display: PropTypes.string,
174
+ label: PropTypes.string,
175
+ tooltip: PropTypes.string,
176
+ className: PropTypes.string,
177
+ validate: PropTypes.string,
178
+ onChange: PropTypes.func,
179
+ };
180
+ export function FormInput(props) {
181
+ const { formValidate, inputProps } = useFormComponent(props);
182
+ let formDataList = props.list && props.list in FVF
183
+ ? FVF[props.list]
184
+ : props.list && props.listItems
185
+ ? props.listItems.split(',')
186
+ : undefined;
187
+ 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 : ""] }));
188
+ }
189
+ FormSelect.propTypes = {
190
+ id: PropTypes.string.isRequired,
191
+ name: PropTypes.string,
192
+ size: PropTypes.string,
193
+ autoComplete: PropTypes.string,
194
+ defaultValue: PropTypes.oneOfType([
195
+ PropTypes.string,
196
+ PropTypes.array
197
+ ]),
198
+ // flag attributes
199
+ autoFocus: PropTypes.string,
200
+ disabled: PropTypes.string,
201
+ multiple: PropTypes.string,
202
+ readOnly: PropTypes.string,
203
+ required: PropTypes.string,
204
+ // selected: PropTypes.string, // not used
205
+ // ----- for calculations
206
+ options: PropTypes.array,
207
+ display: PropTypes.string,
208
+ label: PropTypes.string,
209
+ tooltip: PropTypes.string,
210
+ className: PropTypes.string,
211
+ validate: PropTypes.string,
212
+ onChange: PropTypes.func,
213
+ };
214
+ export function FormSelect(props) {
215
+ const { formValidate, inputProps } = useFormComponent(props);
216
+ const options = generateOptions(props.options || [], props, "select", FormSelectOption);
217
+ 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 : ""] }));
218
+ }
219
+ FormSelectOption.propTypes = {
220
+ text: PropTypes.string,
221
+ value: PropTypes.string,
222
+ // flag attributes
223
+ disabled: PropTypes.bool,
224
+ // selected : PropTypes.string
225
+ };
226
+ function FormSelectOption(props) {
227
+ const { text, disabled, value, ...otherProps } = props;
228
+ const inputProps = {
229
+ ...otherProps,
230
+ ...(disabled !== null && disabled !== undefined ? { disabled } : {}),
231
+ ...(value !== null && value !== undefined ? { value } : {})
232
+ };
233
+ return (_jsx("option", { ...inputProps, children: text }));
234
+ }
235
+ FormTextarea.propTypes = {
236
+ id: PropTypes.string.isRequired,
237
+ name: PropTypes.string,
238
+ rows: PropTypes.string,
239
+ cols: PropTypes.string,
240
+ defaultValue: PropTypes.string,
241
+ maxLength: PropTypes.number,
242
+ placeholder: PropTypes.string,
243
+ autoComplete: PropTypes.string,
244
+ // flag attributes
245
+ autoFocus: PropTypes.string,
246
+ disabled: PropTypes.string,
247
+ readOnly: PropTypes.string,
248
+ required: PropTypes.string,
249
+ // ----- for calculations
250
+ display: PropTypes.string,
251
+ label: PropTypes.string,
252
+ tooltip: PropTypes.string,
253
+ className: PropTypes.string,
254
+ validate: PropTypes.string,
255
+ onChange: PropTypes.func,
256
+ };
257
+ export function FormTextarea(props) {
258
+ const { formValidate, inputProps } = useFormComponent(props);
259
+ 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 : ""] }));
260
+ }
261
+ FormRadio.propTypes = {
262
+ id: PropTypes.string.isRequired, // not using?
263
+ name: PropTypes.string.isRequired,
264
+ options: PropTypes.array,
265
+ // flag attributes
266
+ autoFocus: PropTypes.string,
267
+ disabled: PropTypes.string,
268
+ readOnly: PropTypes.string,
269
+ required: PropTypes.string,
270
+ // ? selected: PropTypes.string,
271
+ // ----- for calculations
272
+ display: PropTypes.string,
273
+ label: PropTypes.string,
274
+ tooltip: PropTypes.string,
275
+ validate: PropTypes.string,
276
+ onChange: PropTypes.func,
277
+ };
278
+ export function FormRadio(props) {
279
+ const { formValidate } = useFormComponent(props);
280
+ const options = generateOptions(props.options || [], props, "radio", FormRadioOption);
281
+ 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 : ""] }));
282
+ }
283
+ FormRadioOption.propTypes = {
284
+ name: PropTypes.string,
285
+ text: PropTypes.string,
286
+ value: PropTypes.string.isRequired,
287
+ // flag attributes
288
+ checked: PropTypes.string,
289
+ // ----- for calculations
290
+ parent: PropTypes.any,
291
+ };
292
+ function FormRadioOption(props) {
293
+ const inputProps = setupInputProps(props);
294
+ const isChecked = props.parent.checked === props.value;
295
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
296
+ const handleChange = (e) => {
297
+ if (props.parent.onChange) {
298
+ props.parent.onChange(props.value);
299
+ }
300
+ };
301
+ 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, checked: isChecked, onChange: handleChange, required: !!props.parent.required, ...inputProps }), _jsx("label", { htmlFor: `${props.parent.name}-${props.value}`, children: props.text })] }));
302
+ }
303
+ FormCheckbox.propTypes = {
304
+ id: PropTypes.string.isRequired,
305
+ name: PropTypes.string.isRequired,
306
+ options: PropTypes.array,
307
+ // flag attributes
308
+ autoFocus: PropTypes.string,
309
+ disabled: PropTypes.string,
310
+ readOnly: PropTypes.string,
311
+ // ----- for calculations
312
+ display: PropTypes.string,
313
+ label: PropTypes.string,
314
+ tooltip: PropTypes.string,
315
+ className: PropTypes.string,
316
+ validate: PropTypes.string,
317
+ onChange: PropTypes.func,
318
+ };
319
+ export function FormCheckbox(props) {
320
+ const { formValidate } = useFormComponent(props);
321
+ const options = generateOptions(props.options || [], props, "checkbox", FormCheckboxOption);
322
+ 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 : ""] }));
323
+ }
324
+ FormCheckboxOption.propTypes = {
325
+ text: PropTypes.string.isRequired,
326
+ value: PropTypes.string.isRequired,
327
+ // flag attributes
328
+ selected: PropTypes.string,
329
+ // ----- for calculations
330
+ parent: PropTypes.any,
331
+ };
332
+ function FormCheckboxOption(props) {
333
+ const inputProps = setupInputProps(props);
334
+ const isChecked = props.parent.checked ? props.parent.checked.includes(props.value) : false;
335
+ const handleChange = (e) => {
336
+ if (props.parent.onChange) {
337
+ const currentChecked = props.parent.checked || [];
338
+ let newChecked;
339
+ if (e.target.checked) {
340
+ newChecked = [...currentChecked, props.value];
341
+ }
342
+ else {
343
+ newChecked = currentChecked.filter((val) => val !== props.value);
344
+ }
345
+ props.parent.onChange(newChecked);
346
+ }
347
+ };
348
+ 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, checked: isChecked, onChange: handleChange, ...inputProps }), _jsx("label", { htmlFor: props.parent.name + "_" + props.text, children: props.text })] }));
349
+ }
350
+ FormButton.propTypes = {
351
+ type: PropTypes.string,
352
+ id: PropTypes.string.isRequired,
353
+ text: PropTypes.string,
354
+ // ----- for calculations
355
+ className: PropTypes.string,
356
+ onClick: PropTypes.func.isRequired
357
+ };
358
+ export function FormButton(props) {
359
+ return (_jsx("div", { children: _jsx("button", { type: props.type, id: props.id, className: props.className || "", onClick: props.onClick, children: props.text }) }));
360
+ }
361
+ FormDataList.propTypes = {
362
+ id: PropTypes.string.isRequired,
363
+ items: PropTypes.array,
364
+ };
365
+ export function FormDataList(props) {
366
+ const options = [];
367
+ for (const item in props.items) {
368
+ let key = item;
369
+ const thisItem = props.items[key];
370
+ const newOption = _jsx("option", { value: thisItem }, props.id + '-' + thisItem);
371
+ options.push(newOption);
372
+ }
373
+ return (_jsx("datalist", { id: props.id, children: options }));
374
+ }
375
+ FormFieldset.propTypes = {};
376
+ export function FormFieldset() {
377
+ return (_jsx(_Fragment, {}));
378
+ }
379
+ // Re-export FontSelector for use in forms
380
+ export { FontSelector, CompoundFontSelector };
@@ -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
+ }