@pixelated-tech/components 3.4.3 → 3.5.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 (241) hide show
  1. package/README.md +12 -191
  2. package/dist/components/admin/componentusage/componentAnalysis.js +12 -4
  3. package/dist/components/admin/componentusage/componentDiscovery.js +20 -6
  4. package/dist/components/admin/site-health/site-health-accessibility.js +5 -1
  5. package/dist/components/admin/site-health/site-health-axe-core.js +4 -0
  6. package/dist/components/admin/site-health/site-health-cloudwatch.integration.js +0 -5
  7. package/dist/components/admin/site-health/site-health-cloudwatch.js +7 -1
  8. package/dist/components/admin/site-health/site-health-core-web-vitals.integration.js +3 -3
  9. package/dist/components/admin/site-health/site-health-dependency-vulnerabilities.js +4 -0
  10. package/dist/components/admin/site-health/site-health-github.js +8 -2
  11. package/dist/components/admin/site-health/site-health-google-analytics.js +6 -0
  12. package/dist/components/admin/site-health/site-health-google-search-console.js +6 -0
  13. package/dist/components/admin/site-health/site-health-on-site-seo.integration.js +128 -55
  14. package/dist/components/admin/site-health/site-health-on-site-seo.js +4 -0
  15. package/dist/components/admin/site-health/site-health-overview.js +11 -4
  16. package/dist/components/admin/site-health/site-health-performance.js +4 -0
  17. package/dist/components/admin/site-health/site-health-security.js +7 -3
  18. package/dist/components/admin/site-health/site-health-seo.js +5 -1
  19. package/dist/components/admin/site-health/site-health-template.js +20 -9
  20. package/dist/components/admin/site-health/site-health-uptime.js +4 -0
  21. package/dist/components/callout/callout.js +0 -10
  22. package/dist/components/carousel/carousel.js +15 -4
  23. package/dist/components/carousel/tiles.js +1 -1
  24. package/dist/components/cms/contentful.items.components.js +3 -4
  25. package/dist/components/cms/flickr.js +1 -1
  26. package/dist/components/cms/google.reviews.components.js +3 -3
  27. package/dist/components/cms/instagram.components.js +15 -5
  28. package/dist/components/cms/smartimage.js +2 -2
  29. package/dist/components/cms/wordpress.components.js +32 -6
  30. package/dist/components/cms/yelp.js +5 -0
  31. package/dist/components/config/config.server.js +7 -1
  32. package/dist/components/general/accordion.js +4 -3
  33. package/dist/components/general/css.js +0 -1
  34. package/dist/components/general/image.js +0 -1
  35. package/dist/components/general/loading.js +2 -1
  36. package/dist/components/general/microinteractions.js +0 -1
  37. package/dist/components/general/modal.css +2 -4
  38. package/dist/components/general/modal.js +72 -30
  39. package/dist/components/general/sidepanel.js +16 -0
  40. package/dist/components/general/tab.js +1 -0
  41. package/dist/components/menu/menu-accordion.css +1 -1
  42. package/dist/components/menu/menu-accordion.js +15 -4
  43. package/dist/components/menu/menu-expando.js +21 -19
  44. package/dist/components/menu/menu-simple.js +14 -14
  45. package/dist/components/nerdjoke/nerdjoke.js +1 -1
  46. package/dist/components/seo/faq-accordion.css +125 -0
  47. package/dist/components/seo/faq-accordion.js +56 -0
  48. package/dist/components/seo/googlesearch.js +0 -1
  49. package/dist/components/seo/schema-blogposting.js +6 -1
  50. package/dist/components/seo/schema-faq.js +6 -0
  51. package/dist/components/seo/schema-recipe.js +34 -1
  52. package/dist/components/seo/schema-services.js +20 -2
  53. package/dist/components/shoppingcart/ebay.components.js +3 -3
  54. package/dist/components/shoppingcart/shoppingcart.components.js +76 -28
  55. package/dist/components/shoppingcart/shoppingcart.functions.js +4 -4
  56. package/dist/components/sitebuilder/config/CompoundFontSelector.js +13 -4
  57. package/dist/components/sitebuilder/config/ConfigBuilder.css +194 -5
  58. package/dist/components/sitebuilder/config/ConfigBuilder.js +183 -17
  59. package/dist/components/sitebuilder/config/FontSelector.js +13 -2
  60. package/dist/components/sitebuilder/config/routes-form.json +67 -0
  61. package/dist/components/sitebuilder/config/siteinfo-form.json +28 -14
  62. package/dist/components/sitebuilder/config/visualdesignform.json +4 -4
  63. package/dist/components/sitebuilder/form/formbuilder.js +1 -0
  64. package/dist/components/sitebuilder/form/formcomponents.js +2 -3
  65. package/dist/components/sitebuilder/form/formengine.js +6 -5
  66. package/dist/components/sitebuilder/form/formvalidator.js +5 -0
  67. package/dist/components/sitebuilder/page/components/PageBuilderUI.js +5 -1
  68. package/dist/components/structured/buzzwordbingo.css +0 -1
  69. package/dist/components/structured/recipe.js +1 -1
  70. package/dist/components/structured/socialcard.js +2 -2
  71. package/dist/components/utilities/functions.js +82 -1
  72. package/dist/components/utilities/gemini-api.client.js +76 -0
  73. package/dist/components/utilities/gemini-api.server.js +185 -0
  74. package/dist/data/routes.json +5 -5
  75. package/dist/index.adminclient.js +30 -0
  76. package/dist/index.adminserver.js +19 -0
  77. package/dist/index.js +11 -18
  78. package/dist/index.server.js +16 -28
  79. package/dist/types/components/admin/componentusage/componentAnalysis.d.ts.map +1 -1
  80. package/dist/types/components/admin/componentusage/componentDiscovery.d.ts +1 -1
  81. package/dist/types/components/admin/componentusage/componentDiscovery.d.ts.map +1 -1
  82. package/dist/types/components/admin/site-health/site-health-accessibility.d.ts +7 -4
  83. package/dist/types/components/admin/site-health/site-health-accessibility.d.ts.map +1 -1
  84. package/dist/types/components/admin/site-health/site-health-axe-core.d.ts +7 -4
  85. package/dist/types/components/admin/site-health/site-health-axe-core.d.ts.map +1 -1
  86. package/dist/types/components/admin/site-health/site-health-cloudwatch.d.ts +9 -6
  87. package/dist/types/components/admin/site-health/site-health-cloudwatch.d.ts.map +1 -1
  88. package/dist/types/components/admin/site-health/site-health-cloudwatch.integration.d.ts.map +1 -1
  89. package/dist/types/components/admin/site-health/site-health-dependency-vulnerabilities.d.ts +7 -4
  90. package/dist/types/components/admin/site-health/site-health-dependency-vulnerabilities.d.ts.map +1 -1
  91. package/dist/types/components/admin/site-health/site-health-github.d.ts +9 -6
  92. package/dist/types/components/admin/site-health/site-health-github.d.ts.map +1 -1
  93. package/dist/types/components/admin/site-health/site-health-google-analytics.d.ts +9 -6
  94. package/dist/types/components/admin/site-health/site-health-google-analytics.d.ts.map +1 -1
  95. package/dist/types/components/admin/site-health/site-health-google-search-console.d.ts +9 -6
  96. package/dist/types/components/admin/site-health/site-health-google-search-console.d.ts.map +1 -1
  97. package/dist/types/components/admin/site-health/site-health-on-site-seo.d.ts +8 -3
  98. package/dist/types/components/admin/site-health/site-health-on-site-seo.d.ts.map +1 -1
  99. package/dist/types/components/admin/site-health/site-health-on-site-seo.integration.d.ts.map +1 -1
  100. package/dist/types/components/admin/site-health/site-health-overview.d.ts +7 -4
  101. package/dist/types/components/admin/site-health/site-health-overview.d.ts.map +1 -1
  102. package/dist/types/components/admin/site-health/site-health-performance.d.ts +7 -4
  103. package/dist/types/components/admin/site-health/site-health-performance.d.ts.map +1 -1
  104. package/dist/types/components/admin/site-health/site-health-security.d.ts +7 -4
  105. package/dist/types/components/admin/site-health/site-health-security.d.ts.map +1 -1
  106. package/dist/types/components/admin/site-health/site-health-seo.d.ts +7 -4
  107. package/dist/types/components/admin/site-health/site-health-seo.d.ts.map +1 -1
  108. package/dist/types/components/admin/site-health/site-health-template.d.ts +13 -10
  109. package/dist/types/components/admin/site-health/site-health-template.d.ts.map +1 -1
  110. package/dist/types/components/admin/site-health/site-health-types.d.ts +0 -21
  111. package/dist/types/components/admin/site-health/site-health-types.d.ts.map +1 -1
  112. package/dist/types/components/admin/site-health/site-health-uptime.d.ts +7 -4
  113. package/dist/types/components/admin/site-health/site-health-uptime.d.ts.map +1 -1
  114. package/dist/types/components/callout/callout.d.ts +3 -3
  115. package/dist/types/components/callout/callout.d.ts.map +1 -1
  116. package/dist/types/components/carousel/carousel.d.ts +16 -7
  117. package/dist/types/components/carousel/carousel.d.ts.map +1 -1
  118. package/dist/types/components/carousel/tiles.d.ts +3 -6
  119. package/dist/types/components/carousel/tiles.d.ts.map +1 -1
  120. package/dist/types/components/cms/flickr.d.ts +3 -6
  121. package/dist/types/components/cms/flickr.d.ts.map +1 -1
  122. package/dist/types/components/cms/google.reviews.components.d.ts +1 -7
  123. package/dist/types/components/cms/google.reviews.components.d.ts.map +1 -1
  124. package/dist/types/components/cms/hubspot.components.d.ts +1 -2
  125. package/dist/types/components/cms/hubspot.components.d.ts.map +1 -1
  126. package/dist/types/components/cms/instagram.components.d.ts +14 -9
  127. package/dist/types/components/cms/instagram.components.d.ts.map +1 -1
  128. package/dist/types/components/cms/smartimage.d.ts +2 -28
  129. package/dist/types/components/cms/smartimage.d.ts.map +1 -1
  130. package/dist/types/components/cms/wordpress.components.d.ts +33 -14
  131. package/dist/types/components/cms/wordpress.components.d.ts.map +1 -1
  132. package/dist/types/components/cms/yelp.d.ts +9 -4
  133. package/dist/types/components/cms/yelp.d.ts.map +1 -1
  134. package/dist/types/components/config/config.server.d.ts +9 -6
  135. package/dist/types/components/config/config.server.d.ts.map +1 -1
  136. package/dist/types/components/general/accordion.d.ts +3 -2
  137. package/dist/types/components/general/accordion.d.ts.map +1 -1
  138. package/dist/types/components/general/loading.d.ts +5 -1
  139. package/dist/types/components/general/loading.d.ts.map +1 -1
  140. package/dist/types/components/general/microinteractions.d.ts +1 -3
  141. package/dist/types/components/general/microinteractions.d.ts.map +1 -1
  142. package/dist/types/components/general/modal.d.ts +11 -5
  143. package/dist/types/components/general/modal.d.ts.map +1 -1
  144. package/dist/types/components/general/semantic.d.ts +3 -3
  145. package/dist/types/components/general/sidepanel.d.ts +20 -13
  146. package/dist/types/components/general/sidepanel.d.ts.map +1 -1
  147. package/dist/types/components/general/tab.d.ts +1 -2
  148. package/dist/types/components/general/tab.d.ts.map +1 -1
  149. package/dist/types/components/menu/menu-accordion.d.ts +22 -9
  150. package/dist/types/components/menu/menu-accordion.d.ts.map +1 -1
  151. package/dist/types/components/menu/menu-expando.d.ts +14 -5
  152. package/dist/types/components/menu/menu-expando.d.ts.map +1 -1
  153. package/dist/types/components/menu/menu-simple.d.ts +4 -5
  154. package/dist/types/components/menu/menu-simple.d.ts.map +1 -1
  155. package/dist/types/components/nerdjoke/nerdjoke.d.ts +1 -1
  156. package/dist/types/components/nerdjoke/nerdjoke.d.ts.map +1 -1
  157. package/dist/types/components/seo/faq-accordion.d.ts +18 -0
  158. package/dist/types/components/seo/faq-accordion.d.ts.map +1 -0
  159. package/dist/types/components/seo/googleanalytics.d.ts.map +1 -1
  160. package/dist/types/components/seo/metadata.components.d.ts +2 -2
  161. package/dist/types/components/seo/metadata.components.d.ts.map +1 -1
  162. package/dist/types/components/seo/schema-blogposting.d.ts +7 -4
  163. package/dist/types/components/seo/schema-blogposting.d.ts.map +1 -1
  164. package/dist/types/components/seo/schema-faq.d.ts +6 -0
  165. package/dist/types/components/seo/schema-faq.d.ts.map +1 -0
  166. package/dist/types/components/seo/schema-recipe.d.ts +29 -30
  167. package/dist/types/components/seo/schema-recipe.d.ts.map +1 -1
  168. package/dist/types/components/seo/schema-services.d.ts +19 -9
  169. package/dist/types/components/seo/schema-services.d.ts.map +1 -1
  170. package/dist/types/components/shoppingcart/paypal.d.ts +1 -1
  171. package/dist/types/components/shoppingcart/paypal.d.ts.map +1 -1
  172. package/dist/types/components/shoppingcart/shoppingcart.components.d.ts +77 -28
  173. package/dist/types/components/shoppingcart/shoppingcart.components.d.ts.map +1 -1
  174. package/dist/types/components/shoppingcart/shoppingcart.functions.d.ts +4 -23
  175. package/dist/types/components/shoppingcart/shoppingcart.functions.d.ts.map +1 -1
  176. package/dist/types/components/sitebuilder/config/CompoundFontSelector.d.ts +10 -11
  177. package/dist/types/components/sitebuilder/config/CompoundFontSelector.d.ts.map +1 -1
  178. package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts +41 -174
  179. package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts.map +1 -1
  180. package/dist/types/components/sitebuilder/config/FontSelector.d.ts +12 -13
  181. package/dist/types/components/sitebuilder/config/FontSelector.d.ts.map +1 -1
  182. package/dist/types/components/sitebuilder/form/formbuilder.d.ts +7 -3
  183. package/dist/types/components/sitebuilder/form/formbuilder.d.ts.map +1 -1
  184. package/dist/types/components/sitebuilder/form/formcomponents.d.ts +1 -1
  185. package/dist/types/components/sitebuilder/form/formcomponents.d.ts.map +1 -1
  186. package/dist/types/components/sitebuilder/form/formengine.d.ts +1 -2
  187. package/dist/types/components/sitebuilder/form/formengine.d.ts.map +1 -1
  188. package/dist/types/components/sitebuilder/form/formextractor.d.ts +5 -4
  189. package/dist/types/components/sitebuilder/form/formextractor.d.ts.map +1 -1
  190. package/dist/types/components/sitebuilder/form/formtypes.d.ts +3 -3
  191. package/dist/types/components/sitebuilder/form/formtypes.d.ts.map +1 -1
  192. package/dist/types/components/sitebuilder/form/formvalidator.d.ts +8 -3
  193. package/dist/types/components/sitebuilder/form/formvalidator.d.ts.map +1 -1
  194. package/dist/types/components/sitebuilder/page/components/ComponentPropertiesForm.d.ts +2 -3
  195. package/dist/types/components/sitebuilder/page/components/ComponentPropertiesForm.d.ts.map +1 -1
  196. package/dist/types/components/sitebuilder/page/components/ComponentSelector.d.ts +2 -3
  197. package/dist/types/components/sitebuilder/page/components/ComponentSelector.d.ts.map +1 -1
  198. package/dist/types/components/sitebuilder/page/components/ComponentTree.d.ts +2 -3
  199. package/dist/types/components/sitebuilder/page/components/ComponentTree.d.ts.map +1 -1
  200. package/dist/types/components/sitebuilder/page/components/PageBuilderUI.d.ts +8 -7
  201. package/dist/types/components/sitebuilder/page/components/PageBuilderUI.d.ts.map +1 -1
  202. package/dist/types/components/sitebuilder/page/components/PageEngine.d.ts.map +1 -1
  203. package/dist/types/components/sitebuilder/page/components/SaveLoadSection.d.ts +2 -3
  204. package/dist/types/components/sitebuilder/page/components/SaveLoadSection.d.ts.map +1 -1
  205. package/dist/types/components/sitebuilder/page/lib/componentMap.d.ts +1 -1
  206. package/dist/types/components/structured/markdown.d.ts +1 -3
  207. package/dist/types/components/structured/markdown.d.ts.map +1 -1
  208. package/dist/types/components/structured/recipe.d.ts +5 -32
  209. package/dist/types/components/structured/recipe.d.ts.map +1 -1
  210. package/dist/types/components/structured/socialcard.d.ts +4 -0
  211. package/dist/types/components/structured/socialcard.d.ts.map +1 -1
  212. package/dist/types/components/structured/timeline.d.ts +1 -3
  213. package/dist/types/components/structured/timeline.d.ts.map +1 -1
  214. package/dist/types/components/utilities/functions.d.ts +20 -0
  215. package/dist/types/components/utilities/functions.d.ts.map +1 -1
  216. package/dist/types/components/utilities/gemini-api.client.d.ts +38 -0
  217. package/dist/types/components/utilities/gemini-api.client.d.ts.map +1 -0
  218. package/dist/types/components/utilities/gemini-api.server.d.ts +17 -0
  219. package/dist/types/components/utilities/gemini-api.server.d.ts.map +1 -0
  220. package/dist/types/index.adminclient.d.ts +27 -0
  221. package/dist/types/index.adminclient.d.ts.map +1 -0
  222. package/dist/types/index.adminserver.d.ts +20 -0
  223. package/dist/types/index.adminserver.d.ts.map +1 -0
  224. package/dist/types/index.d.ts +11 -18
  225. package/dist/types/index.server.d.ts +6 -28
  226. package/dist/types/stories/general/sidepanel.stories.d.ts.map +1 -1
  227. package/dist/types/stories/general/smartimage.stories.d.ts +74 -2
  228. package/dist/types/stories/general/smartimage.stories.d.ts.map +1 -1
  229. package/package.json +19 -9
  230. package/README.COMPONENTS.md +0 -2310
  231. package/dist/components/cms/pixelated.linkedin.js +0 -180
  232. package/dist/components/cms/pixelated.linkedin1.js +0 -84
  233. package/dist/components/cms/pixelated.linkedin2.js +0 -92
  234. package/dist/types/components/cms/pixelated.linkedin.d.ts +0 -2
  235. package/dist/types/components/cms/pixelated.linkedin.d.ts.map +0 -1
  236. package/dist/types/components/cms/pixelated.linkedin1.d.ts +0 -2
  237. package/dist/types/components/cms/pixelated.linkedin1.d.ts.map +0 -1
  238. package/dist/types/components/cms/pixelated.linkedin2.d.ts +0 -2
  239. package/dist/types/components/cms/pixelated.linkedin2.d.ts.map +0 -1
  240. package/dist/types/tests/pixelated.menu-expando.test.d.ts +0 -2
  241. package/dist/types/tests/pixelated.menu-expando.test.d.ts.map +0 -1
@@ -0,0 +1,125 @@
1
+ /* FAQ Accordion Styles */
2
+
3
+ .faq-container {
4
+ width: 100%;
5
+ margin: 0 auto;
6
+ padding: 1.5rem; /* p-6 */
7
+ background-color: white;
8
+ border-radius: 0.5rem; /* rounded-lg */
9
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); /* shadow-sm */
10
+ }
11
+
12
+ .faq-toolbar {
13
+ display: flex;
14
+ justify-content: space-between;
15
+ align-items: center;
16
+ margin-bottom: 1.5rem; /* mb-6 */
17
+ }
18
+
19
+ .search-box {
20
+ flex: 1;
21
+ max-width: 28rem; /* max-w-md */
22
+ }
23
+
24
+ .search-input {
25
+ width: 100%;
26
+ padding: 0.5rem 1rem; /* px-4 py-2 */
27
+ border: 1px solid #d1d5db; /* border-gray-300 */
28
+ border-radius: 0.5rem; /* rounded-lg */
29
+ color: #374151; /* text-gray-700 */
30
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
31
+ }
32
+
33
+ .search-input:focus {
34
+ outline: none;
35
+ border-color: #3b82f6; /* focus:ring-blue-200 */
36
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); /* focus:ring-2 */
37
+ }
38
+
39
+ .expand-buttons {
40
+ display: flex;
41
+ gap: 0.5rem;
42
+ }
43
+
44
+ .expand-button {
45
+ padding: 0.5rem 1rem; /* px-4 py-2 */
46
+ background-color: #dbeafe; /* bg-blue-100 */
47
+ color: #1d4ed8; /* text-blue-700 */
48
+ border-radius: 0.5rem; /* rounded-lg */
49
+ border: none;
50
+ cursor: pointer;
51
+ transition: background-color 0.15s ease-in-out, transform 0.1s ease-in-out;
52
+ font-size: 1.25rem;
53
+ font-weight: bold;
54
+ min-width: 3rem;
55
+ }
56
+
57
+ .expand-button:hover {
58
+ background-color: #bfdbfe; /* hover:bg-blue-200 */
59
+ transform: scale(1.05);
60
+ }
61
+
62
+ .expand-button:focus {
63
+ outline: 2px solid #3b82f6;
64
+ outline-offset: 2px;
65
+ }
66
+
67
+ .faq-list {
68
+ display: flex;
69
+ flex-direction: column;
70
+ gap: 1rem; /* space-y-4 */
71
+ }
72
+
73
+ /* Override general accordion styles for FAQ-specific appearance */
74
+ .faq-list .accordion-item {
75
+ margin-bottom: 0.5rem;
76
+ border: 1px solid #e5e7eb; /* border-gray-200 */
77
+ border-radius: 0.5rem; /* rounded-lg */
78
+ background: #fff;
79
+ }
80
+
81
+ .faq-list .accordion-title {
82
+ padding: 1rem 1.5rem; /* px-6 py-4 */
83
+ font-weight: 500; /* font-medium */
84
+ background-color: #f9fafb; /* bg-gray-50 */
85
+ color: #1f2937; /* text-gray-800 */
86
+ transition: background-color 0.15s ease-in-out;
87
+ }
88
+
89
+ .faq-list .accordion-title:hover {
90
+ background-color: #f3f4f6; /* hover:bg-gray-100 */
91
+ }
92
+
93
+ .faq-list .accordion-title:focus {
94
+ outline: 2px solid #3b82f6;
95
+ outline-offset: 2px;
96
+ background-color: #f3f4f6;
97
+ }
98
+
99
+ .faq-list .accordion-content {
100
+ padding: 1rem 1.5rem; /* px-6 py-4 */
101
+ background-color: white;
102
+ transition: background-color 0.15s ease-in-out;
103
+ }
104
+
105
+ .faq-list .accordion-content:hover {
106
+ background-color: var(--accent2-color, #fefefe);
107
+ }
108
+
109
+ .sr-only {
110
+ position: absolute;
111
+ width: 1px;
112
+ height: 1px;
113
+ padding: 0;
114
+ margin: -1px;
115
+ overflow: hidden;
116
+ clip: rect(0, 0, 0, 0);
117
+ white-space: nowrap;
118
+ border: 0;
119
+ }
120
+
121
+ .no-results {
122
+ text-align: center;
123
+ color: #6b7280; /* text-gray-500 */
124
+ padding: 2rem 0; /* py-8 */
125
+ }
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useMemo } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import { Accordion } from '../general/accordion';
5
+ import './faq-accordion.css';
6
+ const categoryIcons = {
7
+ 'Getting Started': '🚀',
8
+ 'Process & Timeline': '⏱️',
9
+ 'Technical Details': '⚙️',
10
+ 'Content & Management': '📝',
11
+ 'Support & Maintenance': '🛠️',
12
+ 'Ownership & Legal': '📋',
13
+ 'Services': '💼'
14
+ };
15
+ FAQAccordion.propTypes = {
16
+ faqsData: PropTypes.shape({
17
+ mainEntity: PropTypes.arrayOf(PropTypes.shape({
18
+ name: PropTypes.string,
19
+ category: PropTypes.string,
20
+ acceptedAnswer: PropTypes.shape({
21
+ text: PropTypes.string,
22
+ }),
23
+ })),
24
+ }).isRequired,
25
+ };
26
+ export function FAQAccordion({ faqsData }) {
27
+ const [searchTerm, setSearchTerm] = useState('');
28
+ const [expandedStates, setExpandedStates] = useState(faqsData.mainEntity?.map(() => false) || []);
29
+ const filteredFaqs = useMemo(() => {
30
+ if (!faqsData.mainEntity)
31
+ return [];
32
+ if (!searchTerm)
33
+ return faqsData.mainEntity;
34
+ return faqsData.mainEntity.filter((faq) => faq.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
35
+ faq.acceptedAnswer.text.toLowerCase().includes(searchTerm.toLowerCase()));
36
+ }, [faqsData.mainEntity, searchTerm]);
37
+ const expandAll = () => {
38
+ setExpandedStates(expandedStates.map(() => true));
39
+ };
40
+ const collapseAll = () => {
41
+ setExpandedStates(expandedStates.map(() => false));
42
+ };
43
+ const handleToggle = (index, open) => {
44
+ setExpandedStates(prev => prev.map((state, i) => i === index ? open : state));
45
+ };
46
+ // Transform FAQ data to Accordion format
47
+ const accordionItems = filteredFaqs.map((faq, index) => {
48
+ const content = _jsx("div", { dangerouslySetInnerHTML: { __html: faq.acceptedAnswer.text } });
49
+ return {
50
+ title: `${categoryIcons[faq.category] || '❓'} ${faq.name}`,
51
+ content,
52
+ open: expandedStates[index] || undefined
53
+ };
54
+ });
55
+ return (_jsxs("div", { className: "faq-container", role: "region", "aria-label": "Frequently Asked Questions", children: [_jsxs("div", { className: "faq-toolbar", children: [_jsxs("div", { className: "search-box", children: [_jsx("input", { type: "text", placeholder: "Search FAQs...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), className: "search-input", "aria-describedby": "search-help" }), _jsx("div", { id: "search-help", className: "sr-only", children: "Search through frequently asked questions by typing keywords" })] }), _jsxs("div", { className: "expand-buttons", children: [_jsx("button", { onClick: expandAll, className: "expand-button expand-all", "aria-label": "Expand all FAQ answers", title: "Expand all answers", children: "+" }), _jsx("button", { onClick: collapseAll, className: "expand-button collapse-all", "aria-label": "Collapse all FAQ answers", title: "Collapse all answers", children: "\u2212" })] })] }), _jsx("div", { className: "faq-list", "aria-live": "polite", "aria-atomic": "false", children: _jsx(Accordion, { items: accordionItems, onToggle: handleToggle }) })] }));
56
+ }
@@ -23,7 +23,6 @@ GoogleSearch.propTypes = {
23
23
  };
24
24
  export function GoogleSearch(props) {
25
25
  if (typeof document !== 'undefined') {
26
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
27
26
  const gsearch = (function () {
28
27
  const gcse = document.createElement("script");
29
28
  gcse.type = "text/javascript";
@@ -1,5 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- export function SchemaBlogPosting({ post }) {
2
+ import PropTypes from 'prop-types';
3
+ SchemaBlogPosting.propTypes = {
4
+ post: PropTypes.object.isRequired,
5
+ };
6
+ export function SchemaBlogPosting(props) {
7
+ const { post } = props;
3
8
  return (_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: {
4
9
  __html: JSON.stringify(post),
5
10
  } }));
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export function SchemaFAQ({ faqsData }) {
3
+ return (_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: {
4
+ __html: JSON.stringify(faqsData),
5
+ } }));
6
+ }
@@ -1,5 +1,38 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- export function RecipeSchema({ recipe }) {
2
+ import PropTypes from 'prop-types';
3
+ /**
4
+ * Recipe Schema Component
5
+ * Generates JSON-LD structured data for recipes
6
+ * https://schema.org/Recipe
7
+ */
8
+ RecipeSchema.propTypes = {
9
+ recipe: PropTypes.shape({
10
+ '@context': PropTypes.string.isRequired,
11
+ '@type': PropTypes.string.isRequired,
12
+ name: PropTypes.string.isRequired,
13
+ description: PropTypes.string,
14
+ author: PropTypes.shape({
15
+ '@type': PropTypes.string.isRequired,
16
+ name: PropTypes.string.isRequired,
17
+ }),
18
+ datePublished: PropTypes.string,
19
+ image: PropTypes.string,
20
+ recipeYield: PropTypes.string,
21
+ prepTime: PropTypes.string,
22
+ cookTime: PropTypes.string,
23
+ totalTime: PropTypes.string,
24
+ recipeCategory: PropTypes.string,
25
+ recipeCuisine: PropTypes.string,
26
+ recipeIngredient: PropTypes.arrayOf(PropTypes.string),
27
+ recipeInstructions: PropTypes.arrayOf(PropTypes.shape({
28
+ '@type': PropTypes.string.isRequired,
29
+ text: PropTypes.string.isRequired,
30
+ })),
31
+ license: PropTypes.string,
32
+ }).isRequired,
33
+ };
34
+ export function RecipeSchema(props) {
35
+ const { recipe } = props;
3
36
  return (_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: JSON.stringify(recipe) } }));
4
37
  }
5
38
  export default RecipeSchema;
@@ -1,6 +1,24 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- export function ServicesSchema({ provider, services }) {
3
- const serviceObjects = services.map(service => ({
2
+ import PropTypes from 'prop-types';
3
+ ServicesSchema.propTypes = {
4
+ provider: PropTypes.shape({
5
+ name: PropTypes.string.isRequired,
6
+ url: PropTypes.string.isRequired,
7
+ logo: PropTypes.string,
8
+ telephone: PropTypes.string,
9
+ email: PropTypes.string,
10
+ }).isRequired,
11
+ services: PropTypes.arrayOf(PropTypes.shape({
12
+ name: PropTypes.string.isRequired,
13
+ description: PropTypes.string.isRequired,
14
+ url: PropTypes.string,
15
+ image: PropTypes.string,
16
+ areaServed: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
17
+ })).isRequired,
18
+ };
19
+ export function ServicesSchema(props) {
20
+ const { provider, services } = props;
21
+ const serviceObjects = services.map((service) => ({
4
22
  '@type': 'Service',
5
23
  name: service.name,
6
24
  description: service.description,
@@ -5,7 +5,7 @@ import PropTypes from "prop-types";
5
5
  import { Carousel } from '../carousel/carousel';
6
6
  import { SmartImage } from "../cms/smartimage";
7
7
  import { defaultEbayProps, ebaySunglassCategory, getEbayItems, getEbayItem, getShoppingCartItem } from "./ebay.functions";
8
- import { AddToShoppingCart } from "./shoppingcart.functions";
8
+ import { addToShoppingCart } from "./shoppingcart.functions";
9
9
  import { AddToCartButton, /* GoToCartButton */ ViewItemDetails } from "./shoppingcart.components";
10
10
  import { getCloudinaryRemoteFetchURL as getImg } from "../cms/cloudinary";
11
11
  import { Loading, ToggleLoading } from "../general/loading";
@@ -143,7 +143,7 @@ export function EbayListItem(props) {
143
143
  ? _jsx(EbayItemHeader, { url: itemURL, target: itemURLTarget, title: thisItem.title })
144
144
  : _jsx(EbayItemHeader, { title: thisItem.title }) }), _jsxs("div", { className: "ebayItemDetails grid12", children: [_jsxs("div", { children: [_jsx("b", { children: "Item ID: " }), thisItem.legacyItemId] }), _jsxs("div", { children: [_jsx("b", { children: "Quantity: " }), thisItem.categories[0].categoryId == ebaySunglassCategory ? 1 : 10] }), _jsxs("div", { children: [_jsx("b", { children: "Condition: " }), thisItem.condition] }), _jsxs("div", { children: [_jsx("b", { children: "Seller: " }), thisItem.seller.username, " (", thisItem.seller.feedbackScore, ")", _jsx("br", {}), thisItem.seller.feedbackPercentage, "% positive"] }), _jsxs("div", { children: [_jsx("b", { children: "Buying Options: " }), thisItem.buyingOptions[0]] }), _jsxs("div", { children: [_jsx("b", { children: "Location: " }), thisItem.itemLocation.postalCode + ", " + thisItem.itemLocation.country] }), _jsxs("div", { children: [_jsx("b", { children: "Listing Date: " }), thisItem.itemCreationDate] })] }), _jsx("div", { className: "ebayItemPrice", children: itemURL
145
145
  ? _jsxs("a", { href: itemURL, target: itemURLTarget, rel: "noreferrer", children: ["$", thisItem.price.value + " " + thisItem.price.currency] })
146
- : "$" + thisItem.price.value + " " + thisItem.price.currency }), _jsx("br", {}), _jsxs("div", { className: "ebayItemAddToCart", children: [_jsx(ViewItemDetails, { href: "/store", itemID: thisItem.legacyItemId }), _jsx(AddToCartButton, { handler: AddToShoppingCart, item: shoppingCartItem, itemID: thisItem.legacyItemId })] })] })] }));
146
+ : "$" + thisItem.price.value + " " + thisItem.price.currency }), _jsx("br", {}), _jsxs("div", { className: "ebayItemAddToCart", children: [_jsx(ViewItemDetails, { href: "/store", itemID: thisItem.legacyItemId }), _jsx(AddToCartButton, { handler: addToShoppingCart, item: shoppingCartItem, itemID: thisItem.legacyItemId })] })] })] }));
147
147
  }
148
148
  EbayItemHeader.propTypes = {
149
149
  title: PropTypes.string.isRequired,
@@ -195,7 +195,7 @@ export function EbayItemDetail(props) {
195
195
  ? _jsx(EbayItemHeader, { url: itemURL, title: thisItem.title })
196
196
  : _jsx(EbayItemHeader, { title: thisItem.title }) }), _jsx("br", {}), _jsx("div", { className: "ebayItemPhotoCarousel grid-s1-e7", children: _jsx(Carousel, { cards: images, draggable: true, imgFit: "contain" }) }), _jsxs("div", { className: "grid-s7-e13", children: [_jsx("div", { className: "ebayItemDetails grid12", children: _jsx("div", { dangerouslySetInnerHTML: { __html: thisItem.description.replace(/(<br\s*\/?>\s*){2,}/gi, '') } }) }), _jsx("br", {}), _jsxs("div", { className: "ebayItemDetails grid12", children: [_jsxs("div", { children: [_jsx("b", { children: "Item ID: " }), thisItem.legacyItemId] }), _jsxs("div", { children: [_jsx("b", { children: "Quantity: " }), thisItem.categoryId == ebaySunglassCategory ? 1 : 10] }), _jsxs("div", { children: [_jsx("b", { children: "Category: " }), thisItem.categoryPath] }), _jsxs("div", { children: [_jsx("b", { children: "Condition: " }), thisItem.condition] }), _jsxs("div", { children: [_jsx("b", { children: "Seller: " }), thisItem.seller.username, " (", thisItem.seller.feedbackScore, ")", _jsx("br", {}), thisItem.seller.feedbackPercentage, "% positive"] }), _jsxs("div", { children: [_jsx("b", { children: "Buying Options: " }), thisItem.buyingOptions[0]] }), _jsxs("div", { children: [_jsx("b", { children: "Location: " }), thisItem.itemLocation.city + ", " + thisItem.itemLocation.stateOrProvince] }), _jsxs("div", { children: [_jsx("b", { children: "Listing Date: " }), thisItem.itemCreationDate] }), _jsx("br", {})] }), _jsx("div", { className: "ebayItemPrice", children: itemURL
197
197
  ? _jsxs("a", { href: itemURL, target: itemURLTarget, rel: "noreferrer", children: ["$", thisItem.price.value + " " + thisItem.price.currency] })
198
- : "$" + thisItem.price.value + " " + thisItem.price.currency }), _jsx("br", {}), _jsx("div", { className: "ebayItemAddToCart", children: _jsx(AddToCartButton, { handler: AddToShoppingCart, item: shoppingCartItem, itemID: thisItem.legacyItemId }) })] })] }) }));
198
+ : "$" + thisItem.price.value + " " + thisItem.price.currency }), _jsx("br", {}), _jsx("div", { className: "ebayItemAddToCart", children: _jsx(AddToCartButton, { handler: addToShoppingCart, item: shoppingCartItem, itemID: thisItem.legacyItemId }) })] })] }) }));
199
199
  }
200
200
  else {
201
201
  return (_jsx(_Fragment, { children: _jsx("div", { id: "ebayItems", className: "ebayItems", children: _jsx("div", { className: "centered", children: "Loading..." }) }) }));
@@ -11,7 +11,7 @@ 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";
14
- import { getCart, getShippingInfo, SetShippingInfo, setDiscountCodes, getRemoteDiscountCodes, getCheckoutData, RemoveFromShoppingCart, ClearShoppingCart, formatAsUSD, getCartItemCount } from "./shoppingcart.functions";
14
+ import { getCart, getShippingInfo, setShippingInfo, setDiscountCodes, getRemoteDiscountCodes, getCheckoutData, removeFromShoppingCart, clearShoppingCart, formatAsUSD, getCartItemCount } from "./shoppingcart.functions";
15
15
  import { usePixelatedConfig } from '../config/config.client';
16
16
  import { SmartImage } from '../cms/smartimage';
17
17
  import shippingToData from "./shipping.to.json";
@@ -20,10 +20,13 @@ const debug = false;
20
20
  /* ================================================ */
21
21
  /* ========== SHOPPING CART UI COMPONENT ========== */
22
22
  /* ================================================ */
23
+ ShoppingCart.propTypes = {
24
+ payPalClientID: PropTypes.string.isRequired,
25
+ };
23
26
  export function ShoppingCart(props) {
24
27
  const [shoppingCart, setShoppingCart] = useState();
25
- const [shippingInfo, setShippingInfo] = useState();
26
- const [checkoutInfo, setCheckoutInfo] = useState();
28
+ const [shippingData, setShippingData] = useState();
29
+ const [checkoutData, setcheckoutData] = useState();
27
30
  const [orderData, setOrderData] = useState();
28
31
  const [progressStep, setProgressStep] = useState("EmptyCart");
29
32
  function SetProgressStep(step) {
@@ -61,7 +64,7 @@ export function ShoppingCart(props) {
61
64
  setCart(shoppingCart ?? []);
62
65
  }, [shoppingCart]); */
63
66
  /* useEffect(() => {
64
- // UPDATE LOCALSTORAGE IF SHIPPINGINFO STATE CHANGES
67
+ // UPDATE LOCALSTORAGE IF SHIPPINGDATA STATE CHANGES
65
68
  setShippingInfo(shippingInfo);
66
69
  }, [shippingInfo]); */
67
70
  useEffect(() => {
@@ -69,11 +72,11 @@ export function ShoppingCart(props) {
69
72
  (async () => {
70
73
  setDiscountCodes(await getRemoteDiscountCodes());
71
74
  })();
72
- // UPDATE SHOPPINGCART AND SHIPPINGINFO STATES IF LOCALSTORAGE CHANGES
75
+ // UPDATE SHOPPINGCART AND SHIPPINGDATA STATES IF LOCALSTORAGE CHANGES
73
76
  function handleStorageChange() {
74
77
  setShoppingCart(getCart());
75
- setShippingInfo(getShippingInfo());
76
- setCheckoutInfo(getCheckoutData());
78
+ setShippingData(getShippingInfo());
79
+ setcheckoutData(getCheckoutData());
77
80
  SetProgressStep();
78
81
  }
79
82
  window.addEventListener('storage', handleStorageChange);
@@ -85,11 +88,11 @@ export function ShoppingCart(props) {
85
88
  useEffect(() => {
86
89
  // LOAD THE SHIPPING INFO FORM WITH VALUES IF SHIPPING INFO HAS ALREADY BEEN SAVED
87
90
  const form = document.getElementById("address_to");
88
- if (shippingInfo && form) {
89
- for (const key in shippingInfo) {
91
+ if (shippingData && form) {
92
+ for (const key in shippingData) {
90
93
  const input = form.elements[key];
91
94
  if (input) { // Check if the form element exists
92
- input.value = shippingInfo[key].toString();
95
+ input.value = shippingData[key].toString();
93
96
  }
94
97
  }
95
98
  }
@@ -113,7 +116,7 @@ export function ShoppingCart(props) {
113
116
  const formElement = document.getElementById(formID);
114
117
  const formData = new FormData(formElement);
115
118
  const formObject = Object.fromEntries(formData);
116
- SetShippingInfo(formObject);
119
+ setShippingInfo(formObject);
117
120
  }
118
121
  handleOnApprove.propTypes = {
119
122
  data: PropTypes.object.isRequired
@@ -121,9 +124,8 @@ export function ShoppingCart(props) {
121
124
  function handleOnApprove(props) {
122
125
  if (debug)
123
126
  console.log("Handling onApprove");
124
- // eslint-disable-next-line react/prop-types
125
127
  setOrderData(props.data);
126
- ClearShoppingCart();
128
+ clearShoppingCart();
127
129
  // SetProgressStep();
128
130
  SetProgressStep("ThankYou");
129
131
  }
@@ -144,20 +146,27 @@ export function ShoppingCart(props) {
144
146
  }
145
147
  else if (progressStep === "Checkout") {
146
148
  // ========== CHECKOUT ==========
147
- return (_jsxs("div", { className: "pixCart", children: [_jsx(CalloutHeader, { title: "Checkout Summary : " }), checkoutInfo && _jsx(CheckoutItems, { checkoutData: checkoutInfo }), _jsx("br", {}), _jsx(FormButton, { className: "pixCartButton", type: "button", id: "backToCart", text: "<= Back To Cart", onClick: () => SetProgressStep("ShippingInfo") }), _jsx("br", {}), _jsx(PayPal, { payPalClientID: props.payPalClientID, checkoutData: getCheckoutData(), onApprove: handleOnApprove })] }));
149
+ return (_jsxs("div", { className: "pixCart", children: [_jsx(CalloutHeader, { title: "Checkout Summary : " }), checkoutData && _jsx(CheckoutItems, { ...checkoutData }), _jsx("br", {}), _jsx(FormButton, { className: "pixCartButton", type: "button", id: "backToCart", text: "<= Back To Cart", onClick: () => SetProgressStep("ShippingInfo") }), _jsx("br", {}), _jsx(PayPal, { payPalClientID: props.payPalClientID, checkoutData: getCheckoutData(), onApprove: handleOnApprove })] }));
148
150
  }
149
151
  else if (progressStep === "ShippingInfo") {
150
152
  // ========== SHOPPING CART ==========
151
153
  // ========== SHIPPING INFO ==========
152
- return (_jsxs("div", { className: "pixCart", children: [_jsx(CalloutHeader, { title: "Shopping Cart : " }), paintCartItems(shoppingCart ?? []), _jsx("br", {}), _jsx("div", { children: _jsx(FormButton, { className: "pixCartButton", type: "button", id: "backToCart", text: "Clear Cart", onClick: () => ClearShoppingCart() }) }), _jsx("br", {}), _jsx("br", {}), _jsx("hr", {}), _jsx("br", {}), _jsx("br", {}), _jsxs("div", { children: [_jsx(CalloutHeader, { title: "Shipping To : " }), _jsx(FormEngine, { name: "address_to", id: "address_to", formData: shippingToData, onSubmitHandler: onShippingSubmit })] })] }));
154
+ return (_jsxs("div", { className: "pixCart", children: [_jsx(CalloutHeader, { title: "Shopping Cart : " }), paintCartItems(shoppingCart ?? []), _jsx("br", {}), _jsx("div", { children: _jsx(FormButton, { className: "pixCartButton", type: "button", id: "backToCart", text: "Clear Cart", onClick: () => clearShoppingCart() }) }), _jsx("br", {}), _jsx("br", {}), _jsx("hr", {}), _jsx("br", {}), _jsx("br", {}), _jsxs("div", { children: [_jsx(CalloutHeader, { title: "Shipping To : " }), _jsx(FormEngine, { name: "address_to", id: "address_to", formData: shippingToData, onSubmitHandler: onShippingSubmit })] })] }));
153
155
  }
154
156
  else {
155
157
  // ========== EMPTY SHOPPING CART ==========
156
158
  return (_jsxs("div", { className: "pixCart", children: [_jsx(CalloutHeader, { title: "Shopping Cart : " }), _jsx("br", {}), _jsx("div", { className: "centered", children: "No items in your shopping cart" }), _jsx("div", { id: "paypal-button-container", className: "paypal-button-container" })] }));
157
159
  }
158
160
  }
159
- ShoppingCartItem.PropTypes = {
160
- item: PropTypes.object.isRequired
161
+ ShoppingCartItem.propTypes = {
162
+ item: PropTypes.shape({
163
+ itemID: PropTypes.string.isRequired,
164
+ itemURL: PropTypes.string,
165
+ itemTitle: PropTypes.string.isRequired,
166
+ itemImageURL: PropTypes.string,
167
+ itemQuantity: PropTypes.number.isRequired,
168
+ itemCost: PropTypes.number.isRequired,
169
+ }).isRequired
161
170
  };
162
171
  export function ShoppingCartItem(props) {
163
172
  const thisItem = props.item;
@@ -171,30 +180,53 @@ export function ShoppingCartItem(props) {
171
180
  _jsx(SmartImage, { src: thisItem.itemImageURL, title: thisItem.itemTitle, alt: thisItem.itemTitle, cloudinaryEnv: config?.cloudinary?.product_env, cloudinaryDomain: config?.cloudinary?.baseUrl, cloudinaryTransforms: config?.cloudinary?.transforms }))
172
181
  : _jsx(_Fragment, {}) }), _jsxs("div", { className: "grid-s4-e11", children: [_jsx("div", { className: "pixCartItemHeader", children: _jsx("span", { children: thisItem.itemURL
173
182
  ? _jsx("a", { href: thisItem.itemURL, target: thisItemTarget, rel: "noopener noreferrer", children: _jsx("h2", { className: "", children: thisItem.itemTitle }) })
174
- : _jsx("h2", { className: "", children: thisItem.itemTitle }) }) }), _jsxs("div", { className: "pixCartItemDetails grid12", children: [_jsx("br", {}), _jsxs("div", { children: [_jsx("b", { children: "Item ID: " }), thisItem.itemID] }), _jsxs("div", { children: [_jsx("b", { children: "Quantity: " }), thisItem.itemQuantity] }), _jsx("br", {}), _jsx("div", { children: _jsx(FormButton, { className: "pixCartButton", type: "button", id: `btn-rm-${thisItem.itemID}`, text: "Remove Item From Cart", onClick: () => RemoveFromShoppingCart(thisItem) }) })] })] }), _jsx("div", { className: "grid-s11-e13", children: _jsx("div", { className: "pixCartItemPrice", children: formatAsUSD(thisItem.itemCost) }) })] }));
183
+ : _jsx("h2", { className: "", children: thisItem.itemTitle }) }) }), _jsxs("div", { className: "pixCartItemDetails grid12", children: [_jsx("br", {}), _jsxs("div", { children: [_jsx("b", { children: "Item ID: " }), thisItem.itemID] }), _jsxs("div", { children: [_jsx("b", { children: "Quantity: " }), thisItem.itemQuantity] }), _jsx("br", {}), _jsx("div", { children: _jsx(FormButton, { className: "pixCartButton", type: "button", id: `btn-rm-${thisItem.itemID}`, text: "Remove Item From Cart", onClick: () => removeFromShoppingCart(thisItem) }) })] })] }), _jsx("div", { className: "grid-s11-e13", children: _jsx("div", { className: "pixCartItemPrice", children: formatAsUSD(thisItem.itemCost) }) })] }));
175
184
  }
185
+ CheckoutItems.propTypes = {
186
+ items: PropTypes.arrayOf(PropTypes.shape({
187
+ itemID: PropTypes.string.isRequired,
188
+ itemURL: PropTypes.string,
189
+ itemTitle: PropTypes.string.isRequired,
190
+ itemImageURL: PropTypes.string,
191
+ itemQuantity: PropTypes.number.isRequired,
192
+ itemCost: PropTypes.number.isRequired,
193
+ })).isRequired,
194
+ shippingTo: PropTypes.shape({
195
+ name: PropTypes.string.isRequired,
196
+ street1: PropTypes.string.isRequired,
197
+ city: PropTypes.string.isRequired,
198
+ state: PropTypes.string.isRequired,
199
+ zip: PropTypes.string.isRequired,
200
+ }).isRequired,
201
+ subtotal_discount: PropTypes.number.isRequired,
202
+ subtotal: PropTypes.number.isRequired,
203
+ shippingCost: PropTypes.number.isRequired,
204
+ handlingFee: PropTypes.number.isRequired,
205
+ salesTax: PropTypes.number.isRequired,
206
+ total: PropTypes.number.isRequired,
207
+ };
176
208
  export function CheckoutItems(props) {
177
- const items = props.checkoutData.items.map((item) => (_jsxs("div", { children: [item.itemQuantity, " X - ", item.itemTitle, " ( ", formatAsUSD(item.itemCost), " )"] }, item.itemID)));
178
- const to = props.checkoutData.shippingTo;
209
+ const { items, shippingTo, subtotal_discount, subtotal, shippingCost, handlingFee, salesTax, total } = props;
210
+ const to = shippingTo;
179
211
  const addr = _jsxs(_Fragment, { children: [_jsx("div", { children: to.name }), _jsx("div", { children: to.street1 }), _jsxs("div", { children: [to.city, ", ", to.state, " ", to.zip] })] });
180
212
  let checkoutTableData = [{
181
213
  "Name": "Shopping Cart Items : ",
182
214
  "Value": items,
183
215
  }, {
184
216
  "Name": "Subtotal Discount : ",
185
- "Value": formatAsUSD(props.checkoutData.subtotal_discount),
217
+ "Value": formatAsUSD(subtotal_discount),
186
218
  }, {
187
219
  "Name": "Subtotal : ",
188
- "Value": formatAsUSD(props.checkoutData.subtotal),
220
+ "Value": formatAsUSD(subtotal),
189
221
  }, {
190
222
  "Name": "Shipping Address : ",
191
223
  "Value": addr,
192
224
  }, {
193
225
  "Name": "Shipping Cost : ",
194
- "Value": formatAsUSD(props.checkoutData.shippingCost),
226
+ "Value": formatAsUSD(shippingCost),
195
227
  }, {
196
228
  "Name": "Handling Fee : ",
197
- "Value": formatAsUSD(props.checkoutData.handlingFee),
229
+ "Value": formatAsUSD(handlingFee),
198
230
  }, /* {
199
231
  "Name": "Insurance Cost : ",
200
232
  "Value": formatAsUSD(checkoutData.insuranceCost ?? 0),
@@ -204,16 +236,19 @@ export function CheckoutItems(props) {
204
236
  }, */
205
237
  {
206
238
  "Name": "Sales Tax : ",
207
- "Value": formatAsUSD(props.checkoutData.salesTax),
239
+ "Value": formatAsUSD(salesTax),
208
240
  }, {
209
241
  "Name": "TOTAL : ",
210
- "Value": formatAsUSD(props.checkoutData.total),
242
+ "Value": formatAsUSD(total),
211
243
  }];
212
- if (props.checkoutData.subtotal_discount == 0) {
244
+ if (subtotal_discount == 0) {
213
245
  checkoutTableData = checkoutTableData.filter(obj => obj.Name !== "Subtotal Discount : ");
214
246
  }
215
247
  return (_jsx(Table, { id: "pixCheckout", data: checkoutTableData }));
216
248
  }
249
+ CartButton.propTypes = {
250
+ href: PropTypes.string.isRequired,
251
+ };
217
252
  export function CartButton(props) {
218
253
  const config = usePixelatedConfig();
219
254
  const [cartCount, setCartCount] = useState(0);
@@ -238,9 +273,18 @@ export function CartButton(props) {
238
273
  }, [cartCount]);
239
274
  return (_jsx("div", { className: "pixCart", children: _jsxs("button", { className: "pixCartButton", type: "button", id: "pixCartButton", onClick: () => window.location.href = props.href, children: [_jsx(SmartImage, { src: "/images/icons/cart-icon.png", title: "View Shopping Cart", alt: "View Shopping Cart", cloudinaryEnv: config?.cloudinary?.product_env, cloudinaryDomain: config?.cloudinary?.baseUrl, cloudinaryTransforms: config?.cloudinary?.transforms }), _jsxs("span", { children: ["\u00A0", `(${cartCount})`] })] }) }));
240
275
  }
276
+ ViewItemDetails.propTypes = {
277
+ href: PropTypes.string.isRequired,
278
+ itemID: PropTypes.string.isRequired,
279
+ };
241
280
  export function ViewItemDetails(props) {
242
281
  return (_jsx("div", { children: _jsx(FormButton, { className: "pixCartButton", type: "button", id: `btn-item-${props.itemID}`, text: "View Item Details", onClick: () => window.location.href = `${props.href}/${props.itemID}` }) }));
243
282
  }
283
+ AddToCartButton.propTypes = {
284
+ handler: PropTypes.func.isRequired,
285
+ item: PropTypes.object.isRequired,
286
+ itemID: PropTypes.string.isRequired,
287
+ };
244
288
  export function AddToCartButton(props) {
245
289
  const [modalContent, setModalContent] = useState();
246
290
  useEffect(() => {
@@ -251,8 +295,12 @@ export function AddToCartButton(props) {
251
295
  props.handler(props.item);
252
296
  handleModalOpen(e.nativeEvent, "-" + props.itemID);
253
297
  }
254
- return (_jsxs("div", { children: [_jsx(FormButton, { className: "pixCartButton", type: "button", id: `btn-add-${props.itemID}`, text: "Add to Shopping Cart", onClick: (e) => handleClick(e) }), _jsx(Modal, { modalContent: modalContent, modalID: "-" + props.itemID })] }));
298
+ return (_jsxs("div", { children: [_jsx(FormButton, { className: "pixCartButton", type: "button", id: `btn-add-${props.itemID}`, text: "Add to Shopping Cart", onClick: (e) => handleClick(e) }), modalContent && _jsx(Modal, { modalContent: modalContent, modalID: "-" + props.itemID })] }));
255
299
  }
300
+ GoToCartButton.propTypes = {
301
+ href: PropTypes.string.isRequired,
302
+ itemID: PropTypes.string.isRequired,
303
+ };
256
304
  export function GoToCartButton(props) {
257
305
  return (_jsx("div", { children: _jsx(FormButton, { className: "pixCartButton", type: "button", id: `btn-cart-${props.itemID}`, text: "Go to Shopping Cart", onClick: () => window.location.href = props.href }) }));
258
306
  }
@@ -127,7 +127,7 @@ export function getCartSubTotal(cart) {
127
127
  }
128
128
  return formatAsHundredths(cartSubTotal);
129
129
  }
130
- export function AddToShoppingCart(thisItem) {
130
+ export function addToShoppingCart(thisItem) {
131
131
  let cart = getCart();
132
132
  if (alreadyInCart(cart, thisItem.itemID)) {
133
133
  const index = getIndexInCart(cart, thisItem.itemID);
@@ -153,7 +153,7 @@ export function AddToShoppingCart(thisItem) {
153
153
  localStorage.setItem(shoppingCartKey, JSON.stringify(cart));
154
154
  window.dispatchEvent(new Event('storage'));
155
155
  }
156
- export function RemoveFromShoppingCart(thisItem) {
156
+ export function removeFromShoppingCart(thisItem) {
157
157
  let cart = getCart();
158
158
  if (alreadyInCart(cart, thisItem.itemID)) {
159
159
  cart.splice(getIndexInCart(cart, thisItem.itemID), 1);
@@ -161,7 +161,7 @@ export function RemoveFromShoppingCart(thisItem) {
161
161
  localStorage.setItem(shoppingCartKey, JSON.stringify(cart));
162
162
  window.dispatchEvent(new Event('storage'));
163
163
  }
164
- export function ClearShoppingCart() {
164
+ export function clearShoppingCart() {
165
165
  localStorage.removeItem(shoppingCartKey);
166
166
  localStorage.removeItem(shippingInfoKey);
167
167
  window.dispatchEvent(new Event('storage'));
@@ -171,7 +171,7 @@ export function getShippingInfo() {
171
171
  const ship = localStorage.getItem(shippingInfoKey);
172
172
  return ship ? JSON.parse(ship) : [];
173
173
  }
174
- export function SetShippingInfo(shippingFormData) {
174
+ export function setShippingInfo(shippingFormData) {
175
175
  localStorage.setItem(shippingInfoKey, JSON.stringify(shippingFormData));
176
176
  window.dispatchEvent(new Event('storage'));
177
177
  }
@@ -3,7 +3,16 @@ import { useState, useEffect } from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import { FontSelector } from './FontSelector';
5
5
  import './CompoundFontSelector.css';
6
- export function CompoundFontSelector({ id, name, label, required = false, value = '', onChange }) {
6
+ CompoundFontSelector.propTypes = {
7
+ id: PropTypes.string.isRequired,
8
+ name: PropTypes.string.isRequired,
9
+ label: PropTypes.string.isRequired,
10
+ required: PropTypes.bool,
11
+ value: PropTypes.string,
12
+ onChange: PropTypes.func,
13
+ };
14
+ export function CompoundFontSelector(props) {
15
+ const { id, name, label, required = false, value = '', onChange } = props;
7
16
  // Parse the compound value into primary, fallback, generic parts
8
17
  const parseCompoundValue = (val) => {
9
18
  const parts = val.split(',').map(s => s.trim());
@@ -13,10 +22,10 @@ export function CompoundFontSelector({ id, name, label, required = false, value
13
22
  generic: parts[2] || ''
14
23
  };
15
24
  };
16
- const [fonts, setFonts] = useState(parseCompoundValue(value));
25
+ const [fonts, setFonts] = useState(parseCompoundValue(value || ''));
17
26
  // Update fonts when value changes externally
18
27
  useEffect(() => {
19
- setFonts(parseCompoundValue(value));
28
+ setFonts(parseCompoundValue(value || ''));
20
29
  }, [value]);
21
30
  // Combine fonts into a single font stack value
22
31
  const combineFonts = (fontParts) => {
@@ -29,7 +38,7 @@ export function CompoundFontSelector({ id, name, label, required = false, value
29
38
  const combinedValue = combineFonts(updatedFonts);
30
39
  onChange?.(combinedValue);
31
40
  };
32
- return (_jsxs("div", { className: "compound-font-selector", children: [_jsx("label", { children: label }), _jsxs("div", { className: "compound-container", children: [_jsx(FontSelector, { id: `${id}-primary`, name: `${name}-primary`, label: "Primary Font", fontType: "google", required: required, placeholder: "Select Google Font", value: fonts.primary, onChange: (val) => handleFontChange('primary', val) }), _jsx(FontSelector, { id: `${id}-fallback`, name: `${name}-fallback`, label: "Fallback Font", fontType: "websafe", required: false, placeholder: "Select web-safe font", value: fonts.fallback, onChange: (val) => handleFontChange('fallback', val) }), _jsx(FontSelector, { id: `${id}-generic`, name: `${name}-generic`, label: "Generic Family", fontType: "generic", required: false, placeholder: "Select generic family", value: fonts.generic, onChange: (val) => handleFontChange('generic', val) })] })] }));
41
+ return (_jsxs("div", { className: "compound-font-selector", children: [_jsx("label", { children: label }), _jsxs("div", { className: "compound-container", children: [_jsx(FontSelector, { id: `${id}-primary`, name: `${name}-primary`, label: "Primary Font", fontType: "google", required: !!required, placeholder: "Select Google Font", value: fonts.primary, onChange: (val) => handleFontChange('primary', val) }), _jsx(FontSelector, { id: `${id}-fallback`, name: `${name}-fallback`, label: "Fallback Font", fontType: "websafe", required: false, placeholder: "Select web-safe font", value: fonts.fallback, onChange: (val) => handleFontChange('fallback', val) }), _jsx(FontSelector, { id: `${id}-generic`, name: `${name}-generic`, label: "Generic Family", fontType: "generic", required: false, placeholder: "Select generic family", value: fonts.generic, onChange: (val) => handleFontChange('generic', val) })] })] }));
33
42
  }
34
43
  CompoundFontSelector.propTypes = {
35
44
  id: PropTypes.string.isRequired,