@qwickapps/react-framework 1.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 (441) hide show
  1. package/LICENSE +44 -0
  2. package/README.md +794 -0
  3. package/dist/components/AccessibilityChecker.d.ts +12 -0
  4. package/dist/components/AccessibilityChecker.d.ts.map +1 -0
  5. package/dist/components/Html.d.ts +48 -0
  6. package/dist/components/Html.d.ts.map +1 -0
  7. package/dist/components/Logo.d.ts +79 -0
  8. package/dist/components/Logo.d.ts.map +1 -0
  9. package/dist/components/Markdown.d.ts +47 -0
  10. package/dist/components/Markdown.d.ts.map +1 -0
  11. package/dist/components/QwickApp.d.ts +56 -0
  12. package/dist/components/QwickApp.d.ts.map +1 -0
  13. package/dist/components/QwickAppsLogo.d.ts +25 -0
  14. package/dist/components/QwickAppsLogo.d.ts.map +1 -0
  15. package/dist/components/ResponsiveMenu.d.ts +38 -0
  16. package/dist/components/ResponsiveMenu.d.ts.map +1 -0
  17. package/dist/components/SafeSpan.d.ts +23 -0
  18. package/dist/components/SafeSpan.d.ts.map +1 -0
  19. package/dist/components/Scaffold.d.ts +57 -0
  20. package/dist/components/Scaffold.d.ts.map +1 -0
  21. package/dist/components/blocks/Article.d.ts +23 -0
  22. package/dist/components/blocks/Article.d.ts.map +1 -0
  23. package/dist/components/blocks/CardListGrid.d.ts +23 -0
  24. package/dist/components/blocks/CardListGrid.d.ts.map +1 -0
  25. package/dist/components/blocks/Code.d.ts +21 -0
  26. package/dist/components/blocks/Code.d.ts.map +1 -0
  27. package/dist/components/blocks/Content.d.ts +24 -0
  28. package/dist/components/blocks/Content.d.ts.map +1 -0
  29. package/dist/components/blocks/CoverImageHeader.d.ts +44 -0
  30. package/dist/components/blocks/CoverImageHeader.d.ts.map +1 -0
  31. package/dist/components/blocks/FeatureCard.d.ts +66 -0
  32. package/dist/components/blocks/FeatureCard.d.ts.map +1 -0
  33. package/dist/components/blocks/FeatureGrid.d.ts +48 -0
  34. package/dist/components/blocks/FeatureGrid.d.ts.map +1 -0
  35. package/dist/components/blocks/Footer.d.ts +56 -0
  36. package/dist/components/blocks/Footer.d.ts.map +1 -0
  37. package/dist/components/blocks/HeroBlock.d.ts +33 -0
  38. package/dist/components/blocks/HeroBlock.d.ts.map +1 -0
  39. package/dist/components/blocks/PageBannerHeader.d.ts +30 -0
  40. package/dist/components/blocks/PageBannerHeader.d.ts.map +1 -0
  41. package/dist/components/blocks/ProductCard.d.ts +57 -0
  42. package/dist/components/blocks/ProductCard.d.ts.map +1 -0
  43. package/dist/components/blocks/Section.d.ts +40 -0
  44. package/dist/components/blocks/Section.d.ts.map +1 -0
  45. package/dist/components/blocks/index.d.ts +37 -0
  46. package/dist/components/blocks/index.d.ts.map +1 -0
  47. package/dist/components/buttons/Button.d.ts +38 -0
  48. package/dist/components/buttons/Button.d.ts.map +1 -0
  49. package/dist/components/buttons/PaletteSwitcher.d.ts +24 -0
  50. package/dist/components/buttons/PaletteSwitcher.d.ts.map +1 -0
  51. package/dist/components/buttons/ThemeSwitcher.d.ts +24 -0
  52. package/dist/components/buttons/ThemeSwitcher.d.ts.map +1 -0
  53. package/dist/components/buttons/index.d.ts +11 -0
  54. package/dist/components/buttons/index.d.ts.map +1 -0
  55. package/dist/components/forms/FormBlock.d.ts +45 -0
  56. package/dist/components/forms/FormBlock.d.ts.map +1 -0
  57. package/dist/components/forms/index.d.ts +8 -0
  58. package/dist/components/forms/index.d.ts.map +1 -0
  59. package/dist/components/index.d.ts +32 -0
  60. package/dist/components/index.d.ts.map +1 -0
  61. package/dist/components/input/ChoiceInputField.d.ts +30 -0
  62. package/dist/components/input/ChoiceInputField.d.ts.map +1 -0
  63. package/dist/components/input/HtmlInputField.d.ts +29 -0
  64. package/dist/components/input/HtmlInputField.d.ts.map +1 -0
  65. package/dist/components/input/SelectInputField.d.ts +29 -0
  66. package/dist/components/input/SelectInputField.d.ts.map +1 -0
  67. package/dist/components/input/TextField.d.ts +18 -0
  68. package/dist/components/input/TextField.d.ts.map +1 -0
  69. package/dist/components/input/TextInputField.d.ts +32 -0
  70. package/dist/components/input/TextInputField.d.ts.map +1 -0
  71. package/dist/components/input/index.d.ts +17 -0
  72. package/dist/components/input/index.d.ts.map +1 -0
  73. package/dist/components/layout/GridCell.d.ts +16 -0
  74. package/dist/components/layout/GridCell.d.ts.map +1 -0
  75. package/dist/components/layout/GridCellWrapper.d.ts +46 -0
  76. package/dist/components/layout/GridCellWrapper.d.ts.map +1 -0
  77. package/dist/components/layout/GridLayout.d.ts +38 -0
  78. package/dist/components/layout/GridLayout.d.ts.map +1 -0
  79. package/dist/components/layout/index.d.ts +12 -0
  80. package/dist/components/layout/index.d.ts.map +1 -0
  81. package/dist/components/menu/Menu.d.ts +1 -0
  82. package/dist/components/menu/Menu.d.ts.map +1 -0
  83. package/dist/components/menu/MenuItem.d.ts +31 -0
  84. package/dist/components/menu/MenuItem.d.ts.map +1 -0
  85. package/dist/components/menu/index.d.ts +7 -0
  86. package/dist/components/menu/index.d.ts.map +1 -0
  87. package/dist/components/pages/FormPage.d.ts +66 -0
  88. package/dist/components/pages/FormPage.d.ts.map +1 -0
  89. package/dist/components/pages/Page.d.ts +124 -0
  90. package/dist/components/pages/Page.d.ts.map +1 -0
  91. package/dist/components/pages/index.d.ts +11 -0
  92. package/dist/components/pages/index.d.ts.map +1 -0
  93. package/dist/contexts/DataContext.d.ts +139 -0
  94. package/dist/contexts/DataContext.d.ts.map +1 -0
  95. package/dist/contexts/DimensionsContext.d.ts +42 -0
  96. package/dist/contexts/DimensionsContext.d.ts.map +1 -0
  97. package/dist/contexts/PaletteContext.d.ts +53 -0
  98. package/dist/contexts/PaletteContext.d.ts.map +1 -0
  99. package/dist/contexts/QwickAppContext.d.ts +71 -0
  100. package/dist/contexts/QwickAppContext.d.ts.map +1 -0
  101. package/dist/contexts/ThemeContext.d.ts +65 -0
  102. package/dist/contexts/ThemeContext.d.ts.map +1 -0
  103. package/dist/contexts/index.d.ts +9 -0
  104. package/dist/contexts/index.d.ts.map +1 -0
  105. package/dist/hooks/index.d.ts +10 -0
  106. package/dist/hooks/index.d.ts.map +1 -0
  107. package/dist/hooks/useBaseProps.d.ts +101 -0
  108. package/dist/hooks/useBaseProps.d.ts.map +1 -0
  109. package/dist/hooks/useDataBinding.d.ts +22 -0
  110. package/dist/hooks/useDataBinding.d.ts.map +1 -0
  111. package/dist/index.css +1 -0
  112. package/dist/index.d.ts +8 -0
  113. package/dist/index.d.ts.map +1 -0
  114. package/dist/index.esm.css +1 -0
  115. package/dist/index.esm.js +24143 -0
  116. package/dist/index.js +24245 -0
  117. package/dist/palettes/PaletteAutumn.d.ts +10 -0
  118. package/dist/palettes/PaletteAutumn.d.ts.map +1 -0
  119. package/dist/palettes/PaletteCosmic.d.ts +10 -0
  120. package/dist/palettes/PaletteCosmic.d.ts.map +1 -0
  121. package/dist/palettes/PaletteDefault.d.ts +10 -0
  122. package/dist/palettes/PaletteDefault.d.ts.map +1 -0
  123. package/dist/palettes/PaletteOcean.d.ts +10 -0
  124. package/dist/palettes/PaletteOcean.d.ts.map +1 -0
  125. package/dist/palettes/PaletteSpring.d.ts +10 -0
  126. package/dist/palettes/PaletteSpring.d.ts.map +1 -0
  127. package/dist/palettes/PaletteWinter.d.ts +10 -0
  128. package/dist/palettes/PaletteWinter.d.ts.map +1 -0
  129. package/dist/palettes/index.d.ts +13 -0
  130. package/dist/palettes/index.d.ts.map +1 -0
  131. package/dist/schemas/ActionSchema.d.ts +21 -0
  132. package/dist/schemas/ActionSchema.d.ts.map +1 -0
  133. package/dist/schemas/ArticleSchema.d.ts +13 -0
  134. package/dist/schemas/ArticleSchema.d.ts.map +1 -0
  135. package/dist/schemas/Builders.d.ts +7 -0
  136. package/dist/schemas/Builders.d.ts.map +1 -0
  137. package/dist/schemas/ButtonSchema.d.ts +19 -0
  138. package/dist/schemas/ButtonSchema.d.ts.map +1 -0
  139. package/dist/schemas/CardListGridSchema.d.ts +17 -0
  140. package/dist/schemas/CardListGridSchema.d.ts.map +1 -0
  141. package/dist/schemas/ChoiceInputFieldSchema.d.ts +18 -0
  142. package/dist/schemas/ChoiceInputFieldSchema.d.ts.map +1 -0
  143. package/dist/schemas/CodeSchema.d.ts +18 -0
  144. package/dist/schemas/CodeSchema.d.ts.map +1 -0
  145. package/dist/schemas/ContentSchema.d.ts +20 -0
  146. package/dist/schemas/ContentSchema.d.ts.map +1 -0
  147. package/dist/schemas/CoverImageHeaderSchema.d.ts +28 -0
  148. package/dist/schemas/CoverImageHeaderSchema.d.ts.map +1 -0
  149. package/dist/schemas/FeatureCardSchema.d.ts +28 -0
  150. package/dist/schemas/FeatureCardSchema.d.ts.map +1 -0
  151. package/dist/schemas/FeatureGridSchema.d.ts +17 -0
  152. package/dist/schemas/FeatureGridSchema.d.ts.map +1 -0
  153. package/dist/schemas/FeatureItemSchema.d.ts +16 -0
  154. package/dist/schemas/FeatureItemSchema.d.ts.map +1 -0
  155. package/dist/schemas/FooterItemSchema.d.ts +15 -0
  156. package/dist/schemas/FooterItemSchema.d.ts.map +1 -0
  157. package/dist/schemas/FooterSchema.d.ts +20 -0
  158. package/dist/schemas/FooterSchema.d.ts.map +1 -0
  159. package/dist/schemas/FooterSectionSchema.d.ts +15 -0
  160. package/dist/schemas/FooterSectionSchema.d.ts.map +1 -0
  161. package/dist/schemas/FormBlockSchema.d.ts +19 -0
  162. package/dist/schemas/FormBlockSchema.d.ts.map +1 -0
  163. package/dist/schemas/HeaderActionSchema.d.ts +17 -0
  164. package/dist/schemas/HeaderActionSchema.d.ts.map +1 -0
  165. package/dist/schemas/HeroBlockSchema.d.ts +22 -0
  166. package/dist/schemas/HeroBlockSchema.d.ts.map +1 -0
  167. package/dist/schemas/HtmlInputFieldSchema.d.ts +18 -0
  168. package/dist/schemas/HtmlInputFieldSchema.d.ts.map +1 -0
  169. package/dist/schemas/MetadataItemSchema.d.ts +13 -0
  170. package/dist/schemas/MetadataItemSchema.d.ts.map +1 -0
  171. package/dist/schemas/PageBannerHeaderSchema.d.ts +28 -0
  172. package/dist/schemas/PageBannerHeaderSchema.d.ts.map +1 -0
  173. package/dist/schemas/PaletteSwitcherSchema.d.ts +16 -0
  174. package/dist/schemas/PaletteSwitcherSchema.d.ts.map +1 -0
  175. package/dist/schemas/ProductCardSchema.d.ts +39 -0
  176. package/dist/schemas/ProductCardSchema.d.ts.map +1 -0
  177. package/dist/schemas/SafeSpanSchema.d.ts +13 -0
  178. package/dist/schemas/SafeSpanSchema.d.ts.map +1 -0
  179. package/dist/schemas/SectionSchema.d.ts +17 -0
  180. package/dist/schemas/SectionSchema.d.ts.map +1 -0
  181. package/dist/schemas/SelectInputFieldSchema.d.ts +27 -0
  182. package/dist/schemas/SelectInputFieldSchema.d.ts.map +1 -0
  183. package/dist/schemas/TextInputFieldSchema.d.ts +22 -0
  184. package/dist/schemas/TextInputFieldSchema.d.ts.map +1 -0
  185. package/dist/schemas/ThemeSwitcherSchema.d.ts +19 -0
  186. package/dist/schemas/ThemeSwitcherSchema.d.ts.map +1 -0
  187. package/dist/schemas/index.d.ts +33 -0
  188. package/dist/schemas/index.d.ts.map +1 -0
  189. package/dist/schemas/types.d.ts +7 -0
  190. package/dist/schemas/types.d.ts.map +1 -0
  191. package/dist/templates/TemplateResolver.d.ts +52 -0
  192. package/dist/templates/TemplateResolver.d.ts.map +1 -0
  193. package/dist/templates/index.d.ts +7 -0
  194. package/dist/templates/index.d.ts.map +1 -0
  195. package/dist/tests/ConsoleWarningTest.d.ts +5 -0
  196. package/dist/tests/ConsoleWarningTest.d.ts.map +1 -0
  197. package/dist/tests/StorageKeyTest.d.ts +6 -0
  198. package/dist/tests/StorageKeyTest.d.ts.map +1 -0
  199. package/dist/tests/ThemeStorageKeyTest.d.ts +6 -0
  200. package/dist/tests/ThemeStorageKeyTest.d.ts.map +1 -0
  201. package/dist/types/CacheProvider.d.ts +18 -0
  202. package/dist/types/CacheProvider.d.ts.map +1 -0
  203. package/dist/types/ContentProxy.d.ts +47 -0
  204. package/dist/types/ContentProxy.d.ts.map +1 -0
  205. package/dist/types/DataBinding.d.ts +7 -0
  206. package/dist/types/DataBinding.d.ts.map +1 -0
  207. package/dist/types/DataProvider.d.ts +7 -0
  208. package/dist/types/DataProvider.d.ts.map +1 -0
  209. package/dist/types/DataTypes.d.ts +185 -0
  210. package/dist/types/DataTypes.d.ts.map +1 -0
  211. package/dist/types/TemplateProvider.d.ts +10 -0
  212. package/dist/types/TemplateProvider.d.ts.map +1 -0
  213. package/dist/types/TemplateResolver.d.ts +23 -0
  214. package/dist/types/TemplateResolver.d.ts.map +1 -0
  215. package/dist/types/index.d.ts +81 -0
  216. package/dist/types/index.d.ts.map +1 -0
  217. package/dist/utils/breakpoints.d.ts +35 -0
  218. package/dist/utils/breakpoints.d.ts.map +1 -0
  219. package/dist/utils/customPaletteManager.d.ts +8 -0
  220. package/dist/utils/customPaletteManager.d.ts.map +1 -0
  221. package/dist/utils/dimensions.d.ts +34 -0
  222. package/dist/utils/dimensions.d.ts.map +1 -0
  223. package/dist/utils/htmlTransform.d.ts +44 -0
  224. package/dist/utils/htmlTransform.d.ts.map +1 -0
  225. package/dist/utils/index.d.ts +15 -0
  226. package/dist/utils/index.d.ts.map +1 -0
  227. package/dist/utils/logger.d.ts +14 -0
  228. package/dist/utils/logger.d.ts.map +1 -0
  229. package/dist/utils/paletteUtils.d.ts +38 -0
  230. package/dist/utils/paletteUtils.d.ts.map +1 -0
  231. package/dist/utils/persistenceUtils.d.ts +31 -0
  232. package/dist/utils/persistenceUtils.d.ts.map +1 -0
  233. package/dist/utils/reactUtils.d.ts +24 -0
  234. package/dist/utils/reactUtils.d.ts.map +1 -0
  235. package/dist/utils/spacing.d.ts +34 -0
  236. package/dist/utils/spacing.d.ts.map +1 -0
  237. package/dist/utils/themePerformanceMonitor.d.ts +32 -0
  238. package/dist/utils/themePerformanceMonitor.d.ts.map +1 -0
  239. package/dist/utils/themeUtils.d.ts +27 -0
  240. package/dist/utils/themeUtils.d.ts.map +1 -0
  241. package/package.json +141 -0
  242. package/src/__tests__/components/Logo.test.js +172 -0
  243. package/src/__tests__/contexts/DataContext.test.js +505 -0
  244. package/src/__tests__/contexts/PaletteContext.test.js +115 -0
  245. package/src/__tests__/contexts/ThemeContext.test.js +123 -0
  246. package/src/__tests__/utils/paletteUtils.test.js +142 -0
  247. package/src/__tests__/utils/themeUtils.test.js +142 -0
  248. package/src/components/AccessibilityChecker.tsx +264 -0
  249. package/src/components/Html.tsx +191 -0
  250. package/src/components/Logo.css +217 -0
  251. package/src/components/Logo.tsx +370 -0
  252. package/src/components/Markdown.tsx +191 -0
  253. package/src/components/QwickApp.css +257 -0
  254. package/src/components/QwickApp.tsx +157 -0
  255. package/src/components/QwickAppsLogo.tsx +77 -0
  256. package/src/components/ResponsiveMenu.css +416 -0
  257. package/src/components/ResponsiveMenu.tsx +310 -0
  258. package/src/components/SafeSpan.tsx +128 -0
  259. package/src/components/Scaffold.css +541 -0
  260. package/src/components/Scaffold.tsx +463 -0
  261. package/src/components/__tests__/Article.test.tsx +419 -0
  262. package/src/components/__tests__/Button.test.tsx +702 -0
  263. package/src/components/__tests__/CardListGrid.test.tsx +478 -0
  264. package/src/components/__tests__/ChoiceInputField.test.tsx +864 -0
  265. package/src/components/__tests__/Code.test.tsx +595 -0
  266. package/src/components/__tests__/Content.integration.test.tsx +193 -0
  267. package/src/components/__tests__/Content.test.tsx +504 -0
  268. package/src/components/__tests__/CoverImageHeader.test.tsx +456 -0
  269. package/src/components/__tests__/FeatureCard.integration.test.tsx +384 -0
  270. package/src/components/__tests__/FeatureGrid.integration.test.tsx +364 -0
  271. package/src/components/__tests__/FeatureGrid.test.tsx +494 -0
  272. package/src/components/__tests__/Footer.test.tsx +544 -0
  273. package/src/components/__tests__/FormBlock.test.tsx +857 -0
  274. package/src/components/__tests__/HeroBlock.integration.test.tsx +272 -0
  275. package/src/components/__tests__/HeroBlock.test.tsx +463 -0
  276. package/src/components/__tests__/Html.test.tsx +174 -0
  277. package/src/components/__tests__/HtmlInputField.test.tsx +856 -0
  278. package/src/components/__tests__/Markdown.test.tsx +233 -0
  279. package/src/components/__tests__/PageBannerHeader.test.tsx +614 -0
  280. package/src/components/__tests__/PaletteSwitcher.test.tsx +864 -0
  281. package/src/components/__tests__/ProductCard.test.tsx +377 -0
  282. package/src/components/__tests__/SafeSpan.integration.test.tsx +123 -0
  283. package/src/components/__tests__/SafeSpan.simple.test.tsx +65 -0
  284. package/src/components/__tests__/SafeSpan.test.tsx +388 -0
  285. package/src/components/__tests__/Section.integration.test.tsx +288 -0
  286. package/src/components/__tests__/Section.test.tsx +494 -0
  287. package/src/components/__tests__/SelectInputField.test.tsx +886 -0
  288. package/src/components/__tests__/TextInputField.test.tsx +749 -0
  289. package/src/components/__tests__/ThemeSwitcher.test.tsx +777 -0
  290. package/src/components/blocks/Article.tsx +194 -0
  291. package/src/components/blocks/CardListGrid.tsx +132 -0
  292. package/src/components/blocks/Code.tsx +313 -0
  293. package/src/components/blocks/Content.tsx +265 -0
  294. package/src/components/blocks/CoverImageHeader.css +17 -0
  295. package/src/components/blocks/CoverImageHeader.tsx +435 -0
  296. package/src/components/blocks/FeatureCard.tsx +321 -0
  297. package/src/components/blocks/FeatureGrid.tsx +147 -0
  298. package/src/components/blocks/Footer.tsx +343 -0
  299. package/src/components/blocks/HeroBlock.tsx +280 -0
  300. package/src/components/blocks/PageBannerHeader.tsx +471 -0
  301. package/src/components/blocks/ProductCard.tsx +472 -0
  302. package/src/components/blocks/Section.tsx +209 -0
  303. package/src/components/blocks/index.ts +37 -0
  304. package/src/components/buttons/Button.tsx +233 -0
  305. package/src/components/buttons/PaletteSwitcher.tsx +268 -0
  306. package/src/components/buttons/ThemeSwitcher.tsx +283 -0
  307. package/src/components/buttons/index.ts +11 -0
  308. package/src/components/forms/FormBlock.tsx +291 -0
  309. package/src/components/forms/index.ts +7 -0
  310. package/src/components/index.ts +37 -0
  311. package/src/components/input/ChoiceInputField.tsx +188 -0
  312. package/src/components/input/HtmlInputField.tsx +326 -0
  313. package/src/components/input/SelectInputField.tsx +197 -0
  314. package/src/components/input/TextField.tsx +47 -0
  315. package/src/components/input/TextInputField.tsx +144 -0
  316. package/src/components/input/index.ts +17 -0
  317. package/src/components/layout/GridCell.tsx +46 -0
  318. package/src/components/layout/GridCellWrapper.tsx +87 -0
  319. package/src/components/layout/GridLayout.tsx +169 -0
  320. package/src/components/layout/index.ts +13 -0
  321. package/src/components/menu/Menu.tsx +0 -0
  322. package/src/components/menu/MenuItem.tsx +32 -0
  323. package/src/components/menu/index.ts +6 -0
  324. package/src/components/pages/FormPage.tsx +108 -0
  325. package/src/components/pages/Page.css +460 -0
  326. package/src/components/pages/Page.tsx +345 -0
  327. package/src/components/pages/index.ts +11 -0
  328. package/src/contexts/DataContext.tsx +355 -0
  329. package/src/contexts/DimensionsContext.tsx +154 -0
  330. package/src/contexts/PaletteContext.tsx +217 -0
  331. package/src/contexts/QwickAppContext.tsx +95 -0
  332. package/src/contexts/ThemeContext.tsx +376 -0
  333. package/src/contexts/index.ts +9 -0
  334. package/src/hooks/__tests__/useDataBinding.test.tsx.disabled +229 -0
  335. package/src/hooks/index.ts +11 -0
  336. package/src/hooks/useBaseProps.ts +267 -0
  337. package/src/hooks/useDataBinding.ts +77 -0
  338. package/src/index.ts +23 -0
  339. package/src/palettes/PaletteAutumn.css +172 -0
  340. package/src/palettes/PaletteAutumn.ts +16 -0
  341. package/src/palettes/PaletteCosmic.css +172 -0
  342. package/src/palettes/PaletteCosmic.ts +16 -0
  343. package/src/palettes/PaletteDefault.css +178 -0
  344. package/src/palettes/PaletteDefault.ts +17 -0
  345. package/src/palettes/PaletteOcean.css +172 -0
  346. package/src/palettes/PaletteOcean.ts +16 -0
  347. package/src/palettes/PaletteSpring.css +160 -0
  348. package/src/palettes/PaletteSpring.ts +16 -0
  349. package/src/palettes/PaletteWinter.css +172 -0
  350. package/src/palettes/PaletteWinter.ts +16 -0
  351. package/src/palettes/index.css +12 -0
  352. package/src/palettes/index.ts +29 -0
  353. package/src/schemas/ActionSchema.ts +140 -0
  354. package/src/schemas/ArticleSchema.ts +35 -0
  355. package/src/schemas/ButtonSchema.ts +99 -0
  356. package/src/schemas/CardListGridSchema.ts +102 -0
  357. package/src/schemas/ChoiceInputFieldSchema.ts +89 -0
  358. package/src/schemas/CodeSchema.ts +88 -0
  359. package/src/schemas/ContentSchema.ts +128 -0
  360. package/src/schemas/CoverImageHeaderSchema.ts +208 -0
  361. package/src/schemas/FeatureCardSchema.ts +161 -0
  362. package/src/schemas/FeatureGridSchema.ts +87 -0
  363. package/src/schemas/FeatureItemSchema.ts +68 -0
  364. package/src/schemas/FooterItemSchema.ts +57 -0
  365. package/src/schemas/FooterSchema.ts +116 -0
  366. package/src/schemas/FooterSectionSchema.ts +50 -0
  367. package/src/schemas/FormBlockSchema.ts +102 -0
  368. package/src/schemas/HeaderActionSchema.ts +83 -0
  369. package/src/schemas/HeroBlockSchema.ts +149 -0
  370. package/src/schemas/HtmlInputFieldSchema.ts +88 -0
  371. package/src/schemas/MetadataItemSchema.ts +35 -0
  372. package/src/schemas/PageBannerHeaderSchema.ts +206 -0
  373. package/src/schemas/PaletteSwitcherSchema.ts +66 -0
  374. package/src/schemas/ProductCardSchema.ts +264 -0
  375. package/src/schemas/SafeSpanSchema.ts +36 -0
  376. package/src/schemas/SectionSchema.ts +106 -0
  377. package/src/schemas/SelectInputFieldSchema.ts +137 -0
  378. package/src/schemas/TextInputFieldSchema.ts +129 -0
  379. package/src/schemas/ThemeSwitcherSchema.ts +97 -0
  380. package/src/schemas/__tests__/builders.test.ts +313 -0
  381. package/src/schemas/index.ts +34 -0
  382. package/src/setupTests.js +60 -0
  383. package/src/stories/Article.stories.tsx +549 -0
  384. package/src/stories/Button.stories.tsx +498 -0
  385. package/src/stories/CardListGrid.stories.tsx +539 -0
  386. package/src/stories/ChoiceInputField.stories.tsx +591 -0
  387. package/src/stories/Code.stories.tsx +711 -0
  388. package/src/stories/Content.stories.tsx +463 -0
  389. package/src/stories/CoverImageHeader.stories.tsx +794 -0
  390. package/src/stories/DataBinding.advanced.stories.tsx +548 -0
  391. package/src/stories/DataBinding.stories.tsx +452 -0
  392. package/src/stories/DataProvider.stories.tsx +1361 -0
  393. package/src/stories/FeatureCard.stories.tsx +642 -0
  394. package/src/stories/FeatureGrid.stories.tsx +669 -0
  395. package/src/stories/Footer.stories.tsx +724 -0
  396. package/src/stories/FormBlock.stories.tsx +834 -0
  397. package/src/stories/HeroBlock.stories.tsx +442 -0
  398. package/src/stories/Html.stories.tsx +264 -0
  399. package/src/stories/HtmlInputField.stories.tsx +558 -0
  400. package/src/stories/Introduction.stories.tsx +721 -0
  401. package/src/stories/LayoutBlocks.stories.tsx +382 -0
  402. package/src/stories/LayoutSystem.stories.tsx +253 -0
  403. package/src/stories/Logo.stories.tsx +400 -0
  404. package/src/stories/Markdown.stories.tsx +349 -0
  405. package/src/stories/Page.stories.tsx +762 -0
  406. package/src/stories/PageBannerHeader.stories.tsx +949 -0
  407. package/src/stories/PaletteSwitcher.stories.tsx +156 -0
  408. package/src/stories/ProductCard.stories.tsx +504 -0
  409. package/src/stories/QwickApp.stories.tsx +461 -0
  410. package/src/stories/ResponsiveMenu.stories.tsx +299 -0
  411. package/src/stories/SafeSpan.stories.tsx +612 -0
  412. package/src/stories/Section.stories.tsx +613 -0
  413. package/src/stories/SelectInputField.stories.tsx +605 -0
  414. package/src/stories/TextInputField.stories.tsx +526 -0
  415. package/src/stories/ThemeSwitcher.stories.tsx +170 -0
  416. package/src/stories/form/FormComponents.stories.tsx +588 -0
  417. package/src/templates/TemplateResolver.ts +156 -0
  418. package/src/templates/index.ts +6 -0
  419. package/src/tests/ConsoleWarningTest.tsx +30 -0
  420. package/src/tests/StorageKeyTest.tsx +110 -0
  421. package/src/tests/ThemeStorageKeyTest.tsx +114 -0
  422. package/src/types/CacheProvider.ts +14 -0
  423. package/src/types/ContentProxy.ts +99 -0
  424. package/src/types/DataTypes.ts +196 -0
  425. package/src/types/TemplateProvider.ts +9 -0
  426. package/src/types/TemplateResolver.ts +26 -0
  427. package/src/types/index.ts +99 -0
  428. package/src/utils/__tests__/createDataDrivenComponent.test.tsx.disabled +193 -0
  429. package/src/utils/__tests__/htmlTransform.test.tsx +255 -0
  430. package/src/utils/breakpoints.ts +87 -0
  431. package/src/utils/customPaletteManager.js +214 -0
  432. package/src/utils/dimensions.ts +147 -0
  433. package/src/utils/htmlTransform.tsx +323 -0
  434. package/src/utils/index.ts +16 -0
  435. package/src/utils/logger.ts +28 -0
  436. package/src/utils/paletteUtils.ts +78 -0
  437. package/src/utils/persistenceUtils.ts +107 -0
  438. package/src/utils/reactUtils.tsx +37 -0
  439. package/src/utils/spacing.ts +155 -0
  440. package/src/utils/themePerformanceMonitor.js +113 -0
  441. package/src/utils/themeUtils.ts +67 -0
@@ -0,0 +1,188 @@
1
+ /**
2
+ * ChoiceInputField - Dynamic option inputs management component
3
+ *
4
+ * Provides consistent interface for:
5
+ * - Dynamic list of option inputs
6
+ * - Adding new options
7
+ * - Rich text editing for each option
8
+ * - Data binding support
9
+ *
10
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
11
+ */
12
+
13
+ import React from 'react';
14
+ import {
15
+ Alert,
16
+ Box,
17
+ Button,
18
+ Paper,
19
+ Typography
20
+ } from '@mui/material';
21
+ import { Add as AddIcon } from '@mui/icons-material';
22
+ import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
23
+ import { QWICKAPP_COMPONENT, useBaseProps } from '../../hooks';
24
+ import { useDataBinding } from '../../hooks';
25
+ import HtmlInputField from './HtmlInputField';
26
+ import ChoiceInputFieldModel from '../../schemas/ChoiceInputFieldSchema';
27
+
28
+ type ChoiceInputFieldViewProps = ModelProps<ChoiceInputFieldModel> & {
29
+ /** Handler for option value changes */
30
+ onOptionChange?: (optionIndex: number, value: string) => void;
31
+ /** Handler for adding new options */
32
+ onAddOption?: () => void;
33
+ /** Focus handler */
34
+ onFocus?: (optionIndex?: number) => void;
35
+ };
36
+
37
+ export interface ChoiceInputFieldProps extends ChoiceInputFieldViewProps, WithDataBinding {}
38
+
39
+ // View component - handles the actual rendering
40
+ function ChoiceInputFieldView({
41
+ label = 'Options',
42
+ options = [],
43
+ onOptionChange,
44
+ onAddOption,
45
+ onFocus,
46
+ disabled = false,
47
+ placeholder = 'Enter option text. HTML formatting supported.',
48
+ optionLabelPrefix = 'Option',
49
+ rows = 2,
50
+ addButtonText = 'Add Option',
51
+ ...restProps
52
+ }: ChoiceInputFieldViewProps) {
53
+ const { styleProps, htmlProps } = useBaseProps(restProps);
54
+
55
+ // Return empty state if no options and no handlers
56
+ if (options.length === 0 && !onAddOption) {
57
+ return (
58
+ <Paper
59
+ {...htmlProps}
60
+ {...styleProps}
61
+ variant="outlined"
62
+ sx={{
63
+ p: 3,
64
+ textAlign: 'center',
65
+ opacity: 0.6,
66
+ ...styleProps.sx
67
+ }}
68
+ >
69
+ <Typography variant="body2" color="text.secondary">
70
+ No options provided
71
+ </Typography>
72
+ </Paper>
73
+ );
74
+ }
75
+
76
+ return (
77
+ <Box
78
+ {...htmlProps}
79
+ {...styleProps}
80
+ sx={{
81
+ display: 'flex',
82
+ flexDirection: 'column',
83
+ gap: 1,
84
+ ...styleProps.sx
85
+ }}
86
+ >
87
+ {label && (
88
+ <Typography variant="subtitle2" gutterBottom>
89
+ {label}
90
+ </Typography>
91
+ )}
92
+
93
+ {options.map((option, optionIndex) => (
94
+ <Box key={optionIndex}>
95
+ <HtmlInputField
96
+ label={`${optionLabelPrefix} ${optionIndex + 1}`}
97
+ value={option}
98
+ onChange={onOptionChange ? (value: string) => onOptionChange(optionIndex, value) : undefined}
99
+ onFocus={onFocus ? () => onFocus(optionIndex) : undefined}
100
+ rows={rows}
101
+ disabled={disabled}
102
+ placeholder={placeholder}
103
+ />
104
+ </Box>
105
+ ))}
106
+
107
+ {onAddOption && (
108
+ <Button
109
+ startIcon={<AddIcon />}
110
+ onClick={onAddOption}
111
+ size="small"
112
+ disabled={disabled}
113
+ variant="text"
114
+ sx={{ mt: 1, alignSelf: 'flex-start' }}
115
+ >
116
+ {addButtonText}
117
+ </Button>
118
+ )}
119
+ </Box>
120
+ );
121
+ }
122
+
123
+ /**
124
+ * ChoiceInputField component with data binding support
125
+ * Supports both traditional props and dataSource-driven rendering
126
+ */
127
+ function ChoiceInputField(props: ChoiceInputFieldProps) {
128
+ const { dataSource, bindingOptions, ...restProps } = props;
129
+
130
+ // If no dataSource, use traditional props
131
+ if (!dataSource) {
132
+ return <ChoiceInputFieldView {...restProps} />;
133
+ }
134
+
135
+ // Use data binding
136
+ const { dataSource: _source, loading, error, cached, ...choiceInputFieldProps } = useDataBinding<ChoiceInputFieldModel>(
137
+ dataSource,
138
+ restProps as Partial<ChoiceInputFieldModel>,
139
+ ChoiceInputFieldModel.getSchema(),
140
+ { cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
141
+ );
142
+
143
+ // Show loading state
144
+ if (loading) {
145
+ return (
146
+ <Paper
147
+ variant="outlined"
148
+ sx={{
149
+ p: 3,
150
+ textAlign: 'center'
151
+ }}
152
+ >
153
+ <Typography variant="body2">Loading Choice Input Field...</Typography>
154
+ <Typography variant="caption" color="text.secondary">
155
+ Loading options from data source...
156
+ </Typography>
157
+ </Paper>
158
+ );
159
+ }
160
+
161
+ if (error) {
162
+ console.error('Error loading choice input field:', error);
163
+ if (process.env.NODE_ENV !== 'production') {
164
+ return (
165
+ <Paper
166
+ variant="outlined"
167
+ sx={{
168
+ p: 3,
169
+ textAlign: 'center',
170
+ borderColor: 'error.main'
171
+ }}
172
+ >
173
+ <Typography variant="body2" color="error">
174
+ Error loading choice input field: {error.message}
175
+ </Typography>
176
+ </Paper>
177
+ );
178
+ }
179
+ return null;
180
+ }
181
+
182
+ return <ChoiceInputFieldView {...choiceInputFieldProps} />;
183
+ }
184
+
185
+ // Mark as QwickApp component
186
+ (ChoiceInputField as any)[QWICKAPP_COMPONENT] = true;
187
+
188
+ export default ChoiceInputField;
@@ -0,0 +1,326 @@
1
+ /**
2
+ * HtmlInputField - Custom HTML text field with formatting controls
3
+ *
4
+ * Provides HTML editing capabilities with:
5
+ * - Formatting toolbar (bold, italic, underline, code)
6
+ * - HTML preview mode
7
+ * - Help system with supported tags
8
+ * - HTML sanitization for security
9
+ * - Data binding support
10
+ *
11
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
12
+ */
13
+
14
+ import { useState } from 'react';
15
+ import {
16
+ Box,
17
+ TextField,
18
+ IconButton,
19
+ Tooltip,
20
+ Typography,
21
+ Collapse,
22
+ Alert,
23
+ ButtonGroup,
24
+ Divider,
25
+ Paper
26
+ } from '@mui/material';
27
+ import {
28
+ FormatBold as BoldIcon,
29
+ FormatItalic as ItalicIcon,
30
+ FormatUnderlined as UnderlineIcon,
31
+ Code as CodeIcon,
32
+ Visibility as PreviewIcon,
33
+ VisibilityOff as EditIcon,
34
+ Help as HelpIcon
35
+ } from '@mui/icons-material';
36
+ import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
37
+ import SafeSpan from '../SafeSpan';
38
+ import sanitizeHtml from 'sanitize-html';
39
+ import { QWICKAPP_COMPONENT, useBaseProps } from '../../hooks';
40
+ import { useDataBinding } from '../../hooks';
41
+ import HtmlInputFieldModel from '../../schemas/HtmlInputFieldSchema';
42
+
43
+ type HtmlInputFieldViewProps = ModelProps<HtmlInputFieldModel> & {
44
+ /** Change handler */
45
+ onChange?: (value: string) => void;
46
+ /** Focus handler */
47
+ onFocus?: () => void;
48
+ };
49
+
50
+ export interface HtmlInputFieldProps extends HtmlInputFieldViewProps, WithDataBinding {}
51
+
52
+ // View component - handles the actual rendering
53
+ function HtmlInputFieldView({
54
+ label,
55
+ value = '',
56
+ onChange,
57
+ onFocus,
58
+ required = false,
59
+ placeholder = '',
60
+ multiline = true,
61
+ rows = 4,
62
+ disabled = false,
63
+ ...restProps
64
+ }: HtmlInputFieldViewProps) {
65
+ const { styleProps, htmlProps, restProps: otherProps } = useBaseProps(restProps);
66
+ const [showPreview, setShowPreview] = useState(false);
67
+ const [showHelp, setShowHelp] = useState(false);
68
+
69
+ // Return empty state if no onChange handler
70
+ if (!onChange) {
71
+ return (
72
+ <Paper
73
+ {...htmlProps}
74
+ {...styleProps}
75
+ variant="outlined"
76
+ sx={{
77
+ p: 3,
78
+ textAlign: 'center',
79
+ opacity: 0.6,
80
+ ...styleProps.sx
81
+ }}
82
+ >
83
+ <Typography variant="body2" color="text.secondary">
84
+ No onChange handler provided for {label}
85
+ </Typography>
86
+ </Paper>
87
+ );
88
+ }
89
+
90
+ // Sanitize HTML content using default configuration
91
+ const sanitizeHtmlContent = (htmlContent: string) => {
92
+ return sanitizeHtml(htmlContent);
93
+ };
94
+
95
+ // Handle text formatting
96
+ const insertFormatting = (openTag: string, closeTag: string) => {
97
+ const textarea = document.getElementById(`html-textfield-${label}`) as HTMLTextAreaElement;
98
+ if (textarea) {
99
+ const start = textarea.selectionStart;
100
+ const end = textarea.selectionEnd;
101
+ const selectedText = value.substring(start, end);
102
+
103
+ let newText;
104
+ if (selectedText) {
105
+ // Wrap selected text
106
+ newText = value.substring(0, start) + openTag + selectedText + closeTag + value.substring(end);
107
+ } else {
108
+ // Insert tags at cursor position
109
+ newText = value.substring(0, start) + openTag + closeTag + value.substring(start);
110
+ }
111
+
112
+ onChange(newText);
113
+
114
+ // Set cursor position after the opening tag
115
+ setTimeout(() => {
116
+ const newPosition = selectedText ? end + openTag.length + closeTag.length : start + openTag.length;
117
+ textarea.setSelectionRange(newPosition, newPosition);
118
+ textarea.focus();
119
+ }, 0);
120
+ }
121
+ };
122
+
123
+ const formatButtons = [
124
+ { icon: BoldIcon, tooltip: 'Bold', openTag: '<b>', closeTag: '</b>' },
125
+ { icon: ItalicIcon, tooltip: 'Italic', openTag: '<i>', closeTag: '</i>' },
126
+ { icon: UnderlineIcon, tooltip: 'Underline', openTag: '<u>', closeTag: '</u>' },
127
+ { icon: CodeIcon, tooltip: 'Code', openTag: '<code>', closeTag: '</code>' }
128
+ ];
129
+
130
+ const helpContent = (
131
+ <Alert severity="info" sx={{ mt: 1 }}>
132
+ <Typography variant="body2" gutterBottom>
133
+ <strong>Supported HTML tags:</strong>
134
+ </Typography>
135
+ <Typography variant="body2" component="div">
136
+ • <code>&lt;b&gt;</code> or <code>&lt;strong&gt;</code> - Bold text<br/>
137
+ • <code>&lt;i&gt;</code> or <code>&lt;em&gt;</code> - Italic text<br/>
138
+ • <code>&lt;u&gt;</code> - Underlined text<br/>
139
+ • <code>&lt;code&gt;</code> - Code formatting<br/>
140
+ • <code>&lt;br&gt;</code> - Line break<br/>
141
+ • <code>&lt;span style="color: red"&gt;</code> - Colored text
142
+ </Typography>
143
+ </Alert>
144
+ );
145
+
146
+ return (
147
+ <Box
148
+ {...htmlProps}
149
+ {...styleProps}
150
+ sx={{ mb: 2, ...styleProps.sx }}
151
+ >
152
+ {/* Toolbar */}
153
+ <Box sx={{ display: 'flex', alignItems: 'center', mb: 1, gap: 1 }}>
154
+ <Typography variant="body2" color="text.secondary">
155
+ {label} {required && '*'}
156
+ </Typography>
157
+
158
+ <Box sx={{ flexGrow: 1 }} />
159
+
160
+ {/* Formatting buttons */}
161
+ <ButtonGroup size="small" variant="outlined">
162
+ {formatButtons.map(({ icon: Icon, tooltip, openTag, closeTag }) => (
163
+ <Tooltip key={tooltip} title={tooltip}>
164
+ <IconButton
165
+ size="small"
166
+ onClick={() => insertFormatting(openTag, closeTag)}
167
+ disabled={disabled}
168
+ sx={{ p: 0.5 }}
169
+ >
170
+ <Icon fontSize="small" />
171
+ </IconButton>
172
+ </Tooltip>
173
+ ))}
174
+ </ButtonGroup>
175
+
176
+ <Divider orientation="vertical" flexItem />
177
+
178
+ {/* Preview toggle */}
179
+ <Tooltip title={showPreview ? "Edit HTML" : "Preview HTML"}>
180
+ <IconButton
181
+ size="small"
182
+ onClick={() => setShowPreview(!showPreview)}
183
+ color={showPreview ? "primary" : "default"}
184
+ disabled={disabled}
185
+ sx={{ p: 0.5 }}
186
+ >
187
+ {showPreview ? <EditIcon fontSize="small" /> : <PreviewIcon fontSize="small" />}
188
+ </IconButton>
189
+ </Tooltip>
190
+
191
+ {/* Help toggle */}
192
+ <Tooltip title="HTML Help">
193
+ <IconButton
194
+ size="small"
195
+ onClick={() => setShowHelp(!showHelp)}
196
+ color={showHelp ? "primary" : "default"}
197
+ disabled={disabled}
198
+ sx={{ p: 0.5 }}
199
+ >
200
+ <HelpIcon fontSize="small" />
201
+ </IconButton>
202
+ </Tooltip>
203
+ </Box>
204
+
205
+ {/* Help content */}
206
+ <Collapse in={showHelp}>
207
+ {helpContent}
208
+ </Collapse>
209
+
210
+ {/* Input field or preview */}
211
+ {showPreview ? (
212
+ <Box
213
+ sx={{
214
+ border: 1,
215
+ borderColor: 'divider',
216
+ borderRadius: 1,
217
+ p: 2,
218
+ minHeight: multiline ? `${rows * 1.5}em` : '1.5em',
219
+ backgroundColor: 'background.paper'
220
+ }}
221
+ >
222
+ <Typography variant="body2" color="text.secondary" gutterBottom>
223
+ HTML Preview:
224
+ </Typography>
225
+ <Box
226
+ sx={{
227
+ '& code': {
228
+ backgroundColor: 'action.hover',
229
+ padding: '2px 4px',
230
+ borderRadius: 0.5,
231
+ fontFamily: 'monospace'
232
+ }
233
+ }}
234
+ >
235
+ <SafeSpan html={sanitizeHtmlContent(value)} placeholder="No content" />
236
+ </Box>
237
+ </Box>
238
+ ) : (
239
+ <TextField
240
+ id={`html-textfield-${label}`}
241
+ value={value}
242
+ onChange={(e) => {
243
+ const sanitizedValue = sanitizeHtmlContent(e.target.value);
244
+ onChange(sanitizedValue);
245
+ }}
246
+ onFocus={onFocus}
247
+ placeholder={placeholder}
248
+ multiline={multiline}
249
+ rows={multiline ? rows : undefined}
250
+ fullWidth
251
+ variant="outlined"
252
+ required={required}
253
+ disabled={disabled}
254
+ {...otherProps}
255
+ />
256
+ )}
257
+ </Box>
258
+ );
259
+ }
260
+
261
+ /**
262
+ * HtmlInputField component with data binding support
263
+ * Supports both traditional props and dataSource-driven rendering
264
+ */
265
+ function HtmlInputField(props: HtmlInputFieldProps) {
266
+ const { dataSource, bindingOptions, ...restProps } = props;
267
+
268
+ // If no dataSource, use traditional props
269
+ if (!dataSource) {
270
+ return <HtmlInputFieldView {...restProps} />;
271
+ }
272
+
273
+ // Use data binding
274
+ const { dataSource: _source, loading, error, cached, ...htmlInputFieldProps } = useDataBinding<HtmlInputFieldModel>(
275
+ dataSource,
276
+ restProps as Partial<HtmlInputFieldModel>,
277
+ HtmlInputFieldModel.getSchema(),
278
+ { cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
279
+ );
280
+
281
+ // Show loading state
282
+ if (loading) {
283
+ return (
284
+ <Paper
285
+ variant="outlined"
286
+ sx={{
287
+ p: 3,
288
+ textAlign: 'center'
289
+ }}
290
+ >
291
+ <Typography variant="body2">Loading HtmlInputField...</Typography>
292
+ <Typography variant="caption" color="text.secondary">
293
+ Loading HTML input field from data source...
294
+ </Typography>
295
+ </Paper>
296
+ );
297
+ }
298
+
299
+ if (error) {
300
+ console.error('Error loading HtmlInputField:', error);
301
+ if (process.env.NODE_ENV !== 'production') {
302
+ return (
303
+ <Paper
304
+ variant="outlined"
305
+ sx={{
306
+ p: 3,
307
+ textAlign: 'center',
308
+ borderColor: 'error.main'
309
+ }}
310
+ >
311
+ <Typography variant="body2" color="error">
312
+ Error loading HtmlInputField: {error.message}
313
+ </Typography>
314
+ </Paper>
315
+ );
316
+ }
317
+ return null;
318
+ }
319
+
320
+ return <HtmlInputFieldView {...htmlInputFieldProps} />;
321
+ }
322
+
323
+ // Mark as QwickApp component
324
+ (HtmlInputField as any)[QWICKAPP_COMPONENT] = true;
325
+
326
+ export default HtmlInputField;
@@ -0,0 +1,197 @@
1
+ /**
2
+ * SelectInputField - Select dropdown component with data binding support
3
+ *
4
+ * Provides a standardized select field with:
5
+ * - Consistent Material-UI styling
6
+ * - Data binding capabilities
7
+ * - Comprehensive option support
8
+ * - Focus and error handling
9
+ *
10
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
11
+ */
12
+
13
+ import {
14
+ FormControl,
15
+ FormHelperText,
16
+ InputLabel,
17
+ MenuItem,
18
+ Paper,
19
+ Select,
20
+ SelectChangeEvent,
21
+ Typography
22
+ } from '@mui/material';
23
+ import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
24
+ import { QWICKAPP_COMPONENT, useBaseProps } from '../../hooks';
25
+ import { useDataBinding } from '../../hooks';
26
+ import SelectInputFieldModel, { SelectOption } from '../../schemas/SelectInputFieldSchema';
27
+
28
+ type SelectInputFieldViewProps = ModelProps<SelectInputFieldModel> & {
29
+ /** Change handler */
30
+ onChange?: (value: string | number) => void;
31
+ /** Focus handler */
32
+ onFocus?: () => void;
33
+ };
34
+
35
+ export interface SelectInputFieldProps extends SelectInputFieldViewProps, WithDataBinding {}
36
+
37
+ // Export SelectOption for external use
38
+ export { SelectOption };
39
+
40
+ // View component - handles the actual rendering
41
+ function SelectInputFieldView({
42
+ label,
43
+ value = '',
44
+ onChange,
45
+ onFocus,
46
+ options = [],
47
+ required = false,
48
+ disabled = false,
49
+ error,
50
+ helperText,
51
+ placeholder,
52
+ ...restProps
53
+ }: SelectInputFieldViewProps) {
54
+ const { styleProps, htmlProps } = useBaseProps(restProps);
55
+
56
+ const handleChange = (event: SelectChangeEvent<string | number>) => {
57
+ if (onChange) {
58
+ onChange(event.target.value);
59
+ }
60
+ };
61
+
62
+ // Return error state if no options provided
63
+ if (!options.length) {
64
+ return (
65
+ <Paper
66
+ {...htmlProps}
67
+ {...styleProps}
68
+ variant="outlined"
69
+ sx={{
70
+ p: 2,
71
+ textAlign: 'center',
72
+ opacity: 0.6,
73
+ borderColor: 'error.main',
74
+ ...styleProps.sx
75
+ }}
76
+ >
77
+ <Typography variant="body2" color="error">
78
+ No options provided for select field
79
+ </Typography>
80
+ </Paper>
81
+ );
82
+ }
83
+
84
+ return (
85
+ <FormControl
86
+ {...htmlProps}
87
+ {...styleProps}
88
+ fullWidth
89
+ error={!!error}
90
+ required={required}
91
+ disabled={disabled}
92
+ sx={{
93
+ ...styleProps.sx
94
+ }}
95
+ >
96
+ <InputLabel shrink={!!value || !!placeholder}>
97
+ {label}
98
+ </InputLabel>
99
+ <Select
100
+ value={value}
101
+ onChange={handleChange}
102
+ onFocus={onFocus}
103
+ displayEmpty={!!placeholder}
104
+ renderValue={value !== '' ? undefined : () => (
105
+ <span style={{ opacity: 0.6 }}>{placeholder}</span>
106
+ )}
107
+ >
108
+ {placeholder && (
109
+ <MenuItem value="" disabled>
110
+ <em>{placeholder}</em>
111
+ </MenuItem>
112
+ )}
113
+ {options.map((option) => (
114
+ <MenuItem
115
+ key={option.value}
116
+ value={option.value}
117
+ disabled={option.disabled}
118
+ >
119
+ {option.label}
120
+ </MenuItem>
121
+ ))}
122
+ </Select>
123
+ {(error || helperText) && (
124
+ <FormHelperText>
125
+ {error || helperText}
126
+ </FormHelperText>
127
+ )}
128
+ </FormControl>
129
+ );
130
+ }
131
+
132
+ /**
133
+ * SelectInputField component with data binding support
134
+ * Supports both traditional props and dataSource-driven rendering
135
+ */
136
+ function SelectInputField(props: SelectInputFieldProps) {
137
+ const { dataSource, bindingOptions, ...restProps } = props;
138
+
139
+ // If no dataSource, use traditional props
140
+ if (!dataSource) {
141
+ return <SelectInputFieldView {...restProps} />;
142
+ }
143
+
144
+ // Use data binding
145
+ const { dataSource: _source, loading, error, cached, ...selectInputFieldProps } = useDataBinding<SelectInputFieldModel>(
146
+ dataSource,
147
+ restProps as Partial<SelectInputFieldModel>,
148
+ SelectInputFieldModel.getSchema(),
149
+ { cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
150
+ );
151
+
152
+ // Show loading state
153
+ if (loading) {
154
+ return (
155
+ <Paper
156
+ variant="outlined"
157
+ sx={{
158
+ p: 2,
159
+ textAlign: 'center'
160
+ }}
161
+ >
162
+ <Typography variant="body2">Loading SelectInputField...</Typography>
163
+ <Typography variant="caption" color="text.secondary">
164
+ Loading select field configuration from data source...
165
+ </Typography>
166
+ </Paper>
167
+ );
168
+ }
169
+
170
+ if (error) {
171
+ console.error('Error loading select input field:', error);
172
+ if (process.env.NODE_ENV !== 'production') {
173
+ return (
174
+ <Paper
175
+ variant="outlined"
176
+ sx={{
177
+ p: 2,
178
+ textAlign: 'center',
179
+ borderColor: 'error.main'
180
+ }}
181
+ >
182
+ <Typography variant="body2" color="error">
183
+ Error loading select field: {error.message}
184
+ </Typography>
185
+ </Paper>
186
+ );
187
+ }
188
+ return null;
189
+ }
190
+
191
+ return <SelectInputFieldView {...selectInputFieldProps} />;
192
+ }
193
+
194
+ // Mark as QwickApp component
195
+ (SelectInputField as any)[QWICKAPP_COMPONENT] = true;
196
+
197
+ export default SelectInputField;