@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
@@ -1,5 +1,50 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- export function LocalBusinessSchema({ name, streetAddress, addressLocality, addressRegion, postalCode, addressCountry = 'United States', telephone, url, logo, image, openingHours, description, email, priceRange, sameAs }) {
2
+ import PropTypes from "prop-types";
3
+ /**
4
+ * LocalBusiness Schema Component
5
+ * Generates JSON-LD structured data for SEO
6
+ * https://schema.org/LocalBusiness
7
+ *
8
+ * This component uses siteInfo passed as props to generate schema data.
9
+ * It does not use client-side hooks and can be rendered on the server.
10
+ */
11
+ LocalBusinessSchema.propTypes = {
12
+ name: PropTypes.string,
13
+ streetAddress: PropTypes.string,
14
+ addressLocality: PropTypes.string,
15
+ addressRegion: PropTypes.string,
16
+ postalCode: PropTypes.string,
17
+ addressCountry: PropTypes.string,
18
+ telephone: PropTypes.string,
19
+ url: PropTypes.string,
20
+ logo: PropTypes.string,
21
+ image: PropTypes.string,
22
+ openingHours: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
23
+ description: PropTypes.string,
24
+ email: PropTypes.string,
25
+ priceRange: PropTypes.string,
26
+ sameAs: PropTypes.arrayOf(PropTypes.string), // Social media profiles
27
+ siteInfo: PropTypes.object // Required siteinfo from parent component
28
+ };
29
+ export function LocalBusinessSchema(props) {
30
+ // const config = usePixelatedConfig();
31
+ const siteInfo = props.siteInfo;
32
+ // Use props if provided, otherwise fall back to siteInfo
33
+ const name = props.name || siteInfo?.name;
34
+ const streetAddress = props.streetAddress || siteInfo?.address?.streetAddress;
35
+ const addressLocality = props.addressLocality || siteInfo?.address?.addressLocality;
36
+ const addressRegion = props.addressRegion || siteInfo?.address?.addressRegion;
37
+ const postalCode = props.postalCode || siteInfo?.address?.postalCode;
38
+ const addressCountry = props.addressCountry || siteInfo?.address?.addressCountry || 'United States';
39
+ const telephone = props.telephone || siteInfo?.telephone;
40
+ const url = props.url || siteInfo?.url;
41
+ const logo = props.logo || siteInfo?.image;
42
+ const image = props.image || siteInfo?.image;
43
+ const openingHours = props.openingHours;
44
+ const description = props.description || siteInfo?.description;
45
+ const email = props.email || siteInfo?.email;
46
+ const priceRange = props.priceRange || siteInfo?.priceRange;
47
+ const sameAs = props.sameAs || siteInfo?.sameAs;
3
48
  const schemaData = {
4
49
  '@context': 'https://schema.org',
5
50
  '@type': 'LocalBusiness',
@@ -24,4 +69,3 @@ export function LocalBusinessSchema({ name, streetAddress, addressLocality, addr
24
69
  };
25
70
  return (_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: JSON.stringify(schemaData) } }));
26
71
  }
27
- export default LocalBusinessSchema;
@@ -1,5 +1,35 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- export function WebsiteSchema({ name, url, description, potentialAction }) {
2
+ import PropTypes from "prop-types";
3
+ /**
4
+ * Website Schema Component
5
+ * Generates JSON-LD structured data for websites
6
+ * https://schema.org/WebSite
7
+ *
8
+ * This component uses siteInfo passed as props to generate schema data.
9
+ * It does not use client-side hooks and can be rendered on the server.
10
+ */
11
+ WebsiteSchema.propTypes = {
12
+ name: PropTypes.string,
13
+ url: PropTypes.string,
14
+ description: PropTypes.string,
15
+ potentialAction: PropTypes.shape({
16
+ '@type': PropTypes.string,
17
+ target: PropTypes.shape({
18
+ '@type': PropTypes.string,
19
+ urlTemplate: PropTypes.string
20
+ }),
21
+ query: PropTypes.string
22
+ }),
23
+ siteInfo: PropTypes.object // Required siteinfo from parent component
24
+ };
25
+ export function WebsiteSchema(props) {
26
+ // const config = usePixelatedConfig();
27
+ const siteInfo = props.siteInfo;
28
+ // Use props if provided, otherwise fall back to siteInfo
29
+ const name = props.name || siteInfo?.name;
30
+ const url = props.url || siteInfo?.url;
31
+ const description = props.description || siteInfo?.description;
32
+ const potentialAction = props.potentialAction;
3
33
  const schemaData = {
4
34
  '@context': 'https://schema.org',
5
35
  '@type': 'WebSite',
@@ -10,4 +40,3 @@ export function WebsiteSchema({ name, url, description, potentialAction }) {
10
40
  };
11
41
  return (_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: JSON.stringify(schemaData) } }));
12
42
  }
13
- export default WebsiteSchema;
@@ -1,5 +1,5 @@
1
1
  import PropTypes from "prop-types";
2
- import { getAllRoutes } from "./metadata";
2
+ import { getAllRoutes } from "./metadata.functions";
3
3
  import { getWordPressItems, getWordPressItemImages } from "../cms/wordpress.functions";
4
4
  import { getContentfulFieldValues, getContentfulAssetURLs } from "../cms/contentful.delivery";
5
5
  import { getEbayAppToken, getEbayItemsSearch } from "../shoppingcart/ebay.functions";
@@ -173,9 +173,9 @@ export async function createImageURLsFromJSON(origin, jsonPath = 'public/site-im
173
173
  images: newImages,
174
174
  });
175
175
  }
176
- catch (e) {
177
- if (typeof console !== 'undefined')
178
- console.warn('createImageURLsFromJSON failed', e);
176
+ catch /* (e) */ {
177
+ // During build time, fetch will fail - suppress the error to avoid build noise
178
+ // The function returns an empty array, which is acceptable
179
179
  }
180
180
  return sitemap;
181
181
  }
@@ -4,10 +4,10 @@ import { useState, useEffect } from 'react';
4
4
  import PropTypes from 'prop-types';
5
5
  import { PayPal } from "./paypal";
6
6
  import { CalloutHeader } from "../callout/callout";
7
- import { FormEngine } from "../pagebuilder/form/form";
8
- import { FormButton } from '../pagebuilder/form/formcomponents';
9
- import { emailJSON } from "../pagebuilder/form/form.submit";
10
- import '../pagebuilder/form/form.css';
7
+ import { FormEngine } from "../sitebuilder/form/formengine";
8
+ import { FormButton } from '../sitebuilder/form/formcomponents';
9
+ import { emailJSON } from "../sitebuilder/form/formemailer";
10
+ import '../sitebuilder/form/form.css';
11
11
  import { MicroInteractions } from '../general/microinteractions';
12
12
  import { Modal, handleModalOpen } from '../general/modal';
13
13
  import { Table } from "../general/table";
@@ -0,0 +1,266 @@
1
+ .config-builder {
2
+ max-width: 800px;
3
+ margin: 0 auto;
4
+ padding: 20px;
5
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
6
+ }
7
+
8
+ .config-builder h2 {
9
+ color: #333;
10
+ margin-bottom: 20px;
11
+ }
12
+
13
+ .file-upload-section {
14
+ display: flex;
15
+ align-items: center;
16
+ gap: 15px;
17
+ margin-bottom: 20px;
18
+ padding: 15px;
19
+ background-color: #f8f9fa;
20
+ border-radius: 6px;
21
+ border: 1px solid #e9ecef;
22
+ }
23
+
24
+ .file-upload-label {
25
+ font-weight: 600;
26
+ color: #495057;
27
+ font-size: 14px;
28
+ white-space: nowrap;
29
+ }
30
+
31
+ .file-upload-input {
32
+ flex: 1;
33
+ padding: 8px 12px;
34
+ border: 1px solid #ced4da;
35
+ border-radius: 4px;
36
+ font-size: 14px;
37
+ background-color: #fff;
38
+ }
39
+
40
+ .file-upload-input:focus {
41
+ outline: none;
42
+ border-color: #007acc;
43
+ box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2);
44
+ }
45
+
46
+ .site-info-section {
47
+ padding: 20px 0;
48
+ }
49
+
50
+ .site-info-fields {
51
+ display: grid;
52
+ grid-template-columns: 1fr 1fr;
53
+ gap: 15px;
54
+ }
55
+
56
+ .field-group {
57
+ display: flex;
58
+ flex-direction: column;
59
+ }
60
+
61
+ .field-group label {
62
+ font-weight: 600;
63
+ margin-bottom: 5px;
64
+ color: #555;
65
+ font-size: 14px;
66
+ }
67
+
68
+ .field-group input,
69
+ .field-group select {
70
+ padding: 8px 12px;
71
+ border: 1px solid #ddd;
72
+ border-radius: 4px;
73
+ font-size: 14px;
74
+ transition: border-color 0.2s;
75
+ }
76
+
77
+ .field-group input:focus,
78
+ .field-group select:focus {
79
+ outline: none;
80
+ border-color: #007acc;
81
+ box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2);
82
+ }
83
+
84
+ .field-group input[type="color"] {
85
+ height: 40px;
86
+ cursor: pointer;
87
+ }
88
+
89
+ .address-section {
90
+ grid-column: 1 / -1;
91
+ margin-top: 20px;
92
+ padding: 15px;
93
+ background-color: #f9f9f9;
94
+ border-radius: 6px;
95
+ border: 1px solid #e0e0e0;
96
+ }
97
+
98
+ .social-links-section {
99
+ grid-column: 1 / -1;
100
+ margin-top: 20px;
101
+ padding: 15px;
102
+ background-color: #f9f9f9;
103
+ border-radius: 6px;
104
+ border: 1px solid #e0e0e0;
105
+ }
106
+
107
+ .social-links-section h4 {
108
+ margin: 0 0 15px 0;
109
+ color: #333;
110
+ font-size: 16px;
111
+ }
112
+
113
+ .social-link-item {
114
+ display: flex !important;
115
+ flex-direction: row !important;
116
+ gap: 10px;
117
+ align-items: center;
118
+ margin-bottom: 10px;
119
+ }
120
+
121
+ .social-link-item input {
122
+ flex: 2;
123
+ padding: 8px 12px;
124
+ border: 1px solid #ddd;
125
+ border-radius: 4px;
126
+ font-size: 14px;
127
+ }
128
+
129
+ .social-link-item button {
130
+ flex-shrink: 0;
131
+ padding: 8px 12px;
132
+ background-color: #dc3545;
133
+ color: white;
134
+ border: none;
135
+ border-radius: 4px;
136
+ cursor: pointer;
137
+ font-size: 12px;
138
+ transition: background-color 0.2s;
139
+ }
140
+
141
+ .social-link-item button:hover {
142
+ background-color: #c82333;
143
+ }
144
+
145
+ .routes-section {
146
+ padding: 20px 0;
147
+ }
148
+
149
+ .routes-list {
150
+ margin-bottom: 15px;
151
+ }
152
+
153
+ .route-item {
154
+ display: grid;
155
+ grid-template-columns: 2fr 2fr 2fr 2fr auto;
156
+ gap: 10px;
157
+ align-items: center;
158
+ padding: 10px;
159
+ background-color: #f9f9f9;
160
+ border-radius: 4px;
161
+ margin-bottom: 10px;
162
+ }
163
+
164
+ .route-item input {
165
+ padding: 6px 8px;
166
+ border: 1px solid #ddd;
167
+ border-radius: 3px;
168
+ font-size: 14px;
169
+ }
170
+
171
+ .route-item button {
172
+ padding: 6px 12px;
173
+ background-color: #dc3545;
174
+ color: white;
175
+ border: none;
176
+ border-radius: 3px;
177
+ cursor: pointer;
178
+ font-size: 12px;
179
+ transition: background-color 0.2s;
180
+ }
181
+
182
+ .route-item button:hover {
183
+ background-color: #c82333;
184
+ }
185
+
186
+ .config-builder button[type="button"] {
187
+ padding: 10px 20px;
188
+ background-color: #28a745;
189
+ color: white;
190
+ border: none;
191
+ border-radius: 4px;
192
+ cursor: pointer;
193
+ font-size: 14px;
194
+ font-weight: 600;
195
+ transition: background-color 0.2s;
196
+ margin-top: 20px;
197
+ }
198
+
199
+ .config-builder button[type="button"]:hover {
200
+ background-color: #218838;
201
+ }
202
+
203
+ .config-builder pre {
204
+ background-color: #f8f9fa;
205
+ border: 1px solid #e9ecef;
206
+ border-radius: 4px;
207
+ padding: 15px;
208
+ margin-top: 20px;
209
+ font-size: 12px;
210
+ overflow-x: auto;
211
+ white-space: pre-wrap;
212
+ word-wrap: break-word;
213
+ }
214
+
215
+ @media (max-width: 768px) {
216
+ .site-info-fields {
217
+ grid-template-columns: 1fr;
218
+ }
219
+
220
+ .address-section .site-info-fields {
221
+ grid-template-columns: 1fr;
222
+ }
223
+
224
+ .route-item {
225
+ grid-template-columns: 1fr;
226
+ gap: 8px;
227
+ }
228
+ }
229
+
230
+ /* Save Button Validation Styles */
231
+ .save-button-valid {
232
+ background-color: #28a745;
233
+ color: white;
234
+ border: none;
235
+ padding: 12px 24px;
236
+ border-radius: 6px;
237
+ font-size: 16px;
238
+ font-weight: 600;
239
+ cursor: pointer;
240
+ transition: background-color 0.2s ease;
241
+ margin: 20px 0;
242
+ }
243
+
244
+ .save-button-valid:hover {
245
+ background-color: #218838;
246
+ }
247
+
248
+ .save-button-invalid {
249
+ background-color: #dc3545;
250
+ color: white;
251
+ border: none;
252
+ padding: 12px 24px;
253
+ border-radius: 6px;
254
+ font-size: 16px;
255
+ font-weight: 600;
256
+ cursor: not-allowed;
257
+ opacity: 0.6;
258
+ margin: 20px 0;
259
+ }
260
+
261
+ .validation-message {
262
+ color: #dc3545;
263
+ font-size: 14px;
264
+ margin-top: 8px;
265
+ font-weight: 500;
266
+ }
@@ -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;