@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,1361 @@
1
+ /**
2
+ * DataProvider Stories
3
+ *
4
+ * Comprehensive visual documentation and testing for the DataProvider system including:
5
+ * - JsonDataProvider with inline and external data
6
+ * - Template resolution with mustache syntax
7
+ * - Deep nested property access with visual examples
8
+ * - Caching behavior and performance demonstrations
9
+ * - Interactive configuration playground
10
+ * - Error handling and loading states
11
+ * - QwickApp integration with Material UI components
12
+ * - Dynamic data updates and real-time metrics
13
+ */
14
+
15
+ import {
16
+ Alert,
17
+ Box,
18
+ Card,
19
+ CardContent,
20
+ Checkbox,
21
+ Chip,
22
+ FormControlLabel,
23
+ Paper,
24
+ Slider,
25
+ Typography
26
+ } from '@mui/material';
27
+ import { CachedDataProvider, JsonDataProvider } from '@qwickapps/schema';
28
+ import type { Meta, StoryObj } from '@storybook/react';
29
+ import md5 from "md5";
30
+ import React, { useEffect, useState } from 'react';
31
+ import {
32
+ Button,
33
+ Code,
34
+ DataProvider,
35
+ GridCell,
36
+ GridLayout,
37
+ QwickApp,
38
+ Section,
39
+ t,
40
+ T,
41
+ useData,
42
+ useResolveTemplate
43
+ } from '../index';
44
+
45
+ const meta: Meta<typeof DataProvider> = {
46
+ title: 'Framework/DataProvider',
47
+ component: DataProvider,
48
+ parameters: {
49
+ layout: 'fullscreen',
50
+ docs: {
51
+ description: {
52
+ component: `
53
+ # DataProvider System
54
+
55
+ The DataProvider system enables automatic data templating throughout your React component tree using mustache template syntax. This powerful system allows you to inject dynamic data anywhere in your application with a simple, intuitive syntax.
56
+
57
+ ## 🎯 Template Support Overview
58
+
59
+ The DataProvider system supports powerful template resolution using mustache syntax:
60
+
61
+ ### Basic Template Syntax
62
+ - **Simple Properties**: \`{{company.name}}\` → "QwickApps"
63
+ - **Nested Properties**: \`{{company.profile.industry}}\` → "Software Development"
64
+ - **Deep Nesting**: \`{{company.profile.address.city}}\` → "San Francisco"
65
+ - **Array Access**: \`{{features.0.title}}\` → "Lightning Fast Development"
66
+
67
+ ### Advanced Features
68
+ - **Smart Caching**: Intelligent TTL and LRU cache management
69
+ - **Error Handling**: Graceful fallbacks for missing properties
70
+ - **React Integration**: Hooks and components for seamless integration
71
+ - **Type Safety**: Full TypeScript support with ContentProxy
72
+ - **Performance**: Optimized for high-throughput applications
73
+
74
+ ## 🚀 Quick Start
75
+
76
+ \`\`\`tsx
77
+ import { JsonDataProvider, QwickApp, t } from '@qwickapps/react-framework';
78
+
79
+ const provider = new JsonDataProvider({
80
+ data: {
81
+ company: [{ name: 'QwickApps', founded: 2025 }]
82
+ }
83
+ });
84
+
85
+ <QwickApp dataSource={{ dataProvider: provider }}>
86
+ {t\`Welcome to {{company.name}}!\`}
87
+ </QwickApp>
88
+ \`\`\`
89
+
90
+ ## 📚 What You'll Learn
91
+
92
+ The stories below demonstrate comprehensive usage patterns, from basic template resolution to advanced caching strategies and interactive configuration playgrounds.
93
+ `
94
+ }
95
+ }
96
+ },
97
+ argTypes: {
98
+ dataSource: {
99
+ description: 'Content provider instance (JsonDataProvider, etc.)',
100
+ control: { type: undefined }, // Not directly controllable in UI
101
+ table: {
102
+ type: { summary: 'IDataProvider' },
103
+ defaultValue: { summary: 'JsonDataProvider instance' }
104
+ }
105
+ },
106
+ children: {
107
+ description: 'React components that will have access to content context',
108
+ control: { type: undefined },
109
+ table: {
110
+ type: { summary: 'ReactNode' }
111
+ }
112
+ }
113
+ },
114
+ };
115
+
116
+ export default meta;
117
+ type Story = StoryObj<typeof DataProvider>;
118
+
119
+ // Sample data for stories - enhanced with additional nesting and realistic data
120
+ const sampleCompanyData = [
121
+ {
122
+ name: 'QwickApps',
123
+ founded: 2025,
124
+ slogan: 'Build Better Apps Faster',
125
+ description: 'Building the future of app development with revolutionary tools and frameworks',
126
+ profile: {
127
+ industry: 'Software Development',
128
+ size: 'Startup',
129
+ address: {
130
+ street: '123 Tech Street',
131
+ city: 'San Francisco',
132
+ state: 'CA',
133
+ country: 'USA',
134
+ coordinates: {
135
+ lat: 37.7749,
136
+ lng: -122.4194
137
+ }
138
+ },
139
+ contact: {
140
+ email: 'hello@qwickapps.com',
141
+ phone: '+1-555-QWICK',
142
+ social: {
143
+ website: 'https://qwickapps.com',
144
+ twitter: '@qwickapps',
145
+ github: 'qwickapps',
146
+ linkedin: 'qwickapps'
147
+ }
148
+ }
149
+ },
150
+ metrics: {
151
+ users: 10000,
152
+ apps: 500,
153
+ downloads: 50000,
154
+ revenue: 50000000,
155
+ growth: 0.25,
156
+ employees: 150,
157
+ satisfaction: 98
158
+ }
159
+ }
160
+ ];
161
+
162
+ // Additional sample data sets for comprehensive testing
163
+ const nestedTestData = {
164
+ company: [
165
+ {
166
+ name: 'TechCorp Advanced',
167
+ profile: {
168
+ industry: 'Technology',
169
+ size: 'Enterprise',
170
+ location: {
171
+ city: 'San Francisco',
172
+ state: 'CA',
173
+ country: 'USA',
174
+ timezone: 'PST'
175
+ },
176
+ contact: {
177
+ email: 'hello@techcorp.com',
178
+ phone: '+1-555-0123',
179
+ social: {
180
+ website: 'https://techcorp.com',
181
+ twitter: '@techcorp',
182
+ linkedin: 'techcorp'
183
+ }
184
+ }
185
+ },
186
+ metrics: {
187
+ employees: 150,
188
+ revenue: 50000000,
189
+ growth: 0.25,
190
+ founded: 2020
191
+ }
192
+ }
193
+ ],
194
+ stats: [
195
+ {
196
+ users: 10000,
197
+ projects: 500,
198
+ downloads: 50000,
199
+ satisfaction: 98
200
+ }
201
+ ]
202
+ };
203
+
204
+ const sampleFeaturesData = [
205
+ {
206
+ title: 'Lightning Fast Development',
207
+ description: 'Build production-ready applications in minutes, not months',
208
+ icon: '⚡',
209
+ priority: 'high',
210
+ category: 'development'
211
+ },
212
+ {
213
+ title: 'Type-Safe Architecture',
214
+ description: 'Full TypeScript support with compile-time safety',
215
+ icon: '🛡️',
216
+ priority: 'high',
217
+ category: 'architecture'
218
+ },
219
+ {
220
+ title: 'Visual Page Builder',
221
+ description: 'Drag-and-drop interface for rapid prototyping',
222
+ icon: '🎨',
223
+ priority: 'medium',
224
+ category: 'design'
225
+ },
226
+ {
227
+ title: 'Real-time Collaboration',
228
+ description: 'Work together with your team in real-time',
229
+ icon: '👥',
230
+ priority: 'medium',
231
+ category: 'collaboration'
232
+ }
233
+ ];
234
+
235
+ const sampleTeamData = [
236
+ {
237
+ name: 'Raajkumar Subramaniam',
238
+ role: 'Founder & CEO',
239
+ email: 'raajkumars@qwickapps.com',
240
+ bio: 'Former Google engineer with 25+ years in developer tools',
241
+ avatar: `https://gravatar.com/avatar/${md5('raajkumars@qwickapps.com')}?s=100`,
242
+ social: {
243
+ linkedin: 'raajkumars',
244
+ twitter: 'raajkumar_dev'
245
+ }
246
+ },
247
+ {
248
+ name: 'Architect Claude',
249
+ role: 'Chief Architect',
250
+ email: 'qwickapps.architect@qwickapps.com',
251
+ bio: 'Senior software architect with deep expertise in large-scale system design, and strategic technical decision-making for the QwickApps React Framework.',
252
+ avatar: `https://gravatar.com/avatar/${md5('qwickapps.architect@qwickapps.com')}?s=100&d=robohash`,
253
+ social: {
254
+ github: 'qwickapps.architect',
255
+ twitter: 'qwickapps_architect'
256
+ }
257
+ },
258
+ {
259
+ name: 'Coder Claude',
260
+ role: 'Senior Software Engineer',
261
+ email: 'qwickapps.coder@qwickapps.com',
262
+ bio: 'Full-stack engineer specializing in implementing features and building solutions for the QwickApps ecosystem.',
263
+ avatar: `https://gravatar.com/avatar/${md5('qwickapps.coder@qwickapps.com')}?s=100&d=robohash`,
264
+ social: {
265
+ github: 'qwickapps.coder',
266
+ twitter: 'qwickapps_coder'
267
+ }
268
+ },
269
+ {
270
+ name: 'Reviewer Claude',
271
+ role: 'Senior QA Manager',
272
+ email: 'qwickapps.reviewer@qwickapps.com',
273
+ bio: 'Elite software engineering expert specializing in code review and architectural assessment for the QwickApps Ecosystem.',
274
+ avatar: `https://gravatar.com/avatar/${md5('qwickapps.reviewer@qwickapps.com')}?s=100&d=robohash`,
275
+ social: {
276
+ github: 'qwickapps.reviewer',
277
+ twitter: 'qwickapps_reviewer'
278
+ }
279
+ },
280
+ {
281
+ name: 'Devops Claude',
282
+ role: 'Senior DevOps Engineer',
283
+ email: 'qwickapps.devops@qwickapps.com',
284
+ bio: 'DevOps specialist with expertise in technical documentation, project organization, and maintaining comprehensive documentation across large monorepos.',
285
+ avatar: `https://gravatar.com/avatar/${md5('qwickapps.devops@qwickapps.com')}?s=100&d=robohash`,
286
+ social: {
287
+ github: 'qwickapps.devops',
288
+ twitter: 'qwickapps_devops'
289
+ }
290
+ },
291
+ {
292
+ name: 'Writer Claude',
293
+ role: 'Senior Content Writer',
294
+ email: 'qwickapps.writer@qwickapps.com',
295
+ bio: 'Specialized technical content creator with deep expertise in developer education and the QwickApps ecosystem',
296
+ avatar: `https://gravatar.com/avatar/${md5('qwickapps.writer@qwickapps.com')}?s=100&d=robohash`,
297
+ social: {
298
+ github: 'qwickapps.writer',
299
+ twitter: 'qwickapps_writer'
300
+ }
301
+ },
302
+ {
303
+ name: 'GitHub Copilot',
304
+ role: 'Release Manager',
305
+ email: 'qwickapps.copilot@qwickapps.com',
306
+ bio: 'Expert in unit testing, code review, and managing staging/production deployments.',
307
+ avatar: `https://gravatar.com/avatar/${md5('qwickapps.copilot@qwickapps.com')}?s=100&d=robohash`,
308
+ social: {
309
+ github: 'qwickapps.copilot',
310
+ twitter: 'qwickapps_copilot'
311
+ }
312
+ },
313
+ {
314
+ name: 'Chat GPT',
315
+ role: 'Board Member',
316
+ email: 'qwickapps.chatgpt@qwickapps.com',
317
+ bio: 'Consultant for AI-driven development workflows and best practices.',
318
+ avatar: `https://gravatar.com/avatar/${md5('qwickapps.chatgpt@qwickapps.com')}?s=100&d=robohash`,
319
+ social: {
320
+ github: 'qwickapps.chatgpt',
321
+ twitter: 'qwickapps_chatgpt'
322
+ }
323
+ }
324
+ ];
325
+
326
+
327
+
328
+ /**
329
+ * Basic DataProvider usage with JsonDataProvider
330
+ */
331
+ export const BasicUsage: Story = {
332
+ render: () => {
333
+ const provider = new JsonDataProvider({
334
+ data: {
335
+ company: sampleCompanyData,
336
+ features: sampleFeaturesData
337
+ }
338
+ });
339
+
340
+ return (
341
+ <DataProvider dataSource={{ dataProvider: provider }}>
342
+ <Section>
343
+ <Typography variant="h4">DataProvider Basic Usage</Typography>
344
+ <Typography variant="body1">This story demonstrates basic DataProvider functionality with inline data.</Typography>
345
+
346
+ <Section >
347
+ <Typography variant="h5">{t`{{company.name}}`}</Typography>
348
+ <Typography variant="body1">{t`{{company.slogan}}`}</Typography>
349
+ <small>{t`Founded {{company.founded}} • {{company.profile.industry}}`}</small>
350
+ </Section>
351
+
352
+ <Section>
353
+ <Typography variant="h5">Our Features</Typography>
354
+ {sampleFeaturesData.map((feature, index) => (
355
+ <Section key={index} style={{ marginBottom: '15px', padding: '10px', border: '1px solid #ddd', borderRadius: '4px' }}>
356
+ <Typography variant="h6">{feature.icon} {feature.title}</Typography>
357
+ <Typography variant="body1">{feature.description}</Typography>
358
+ </Section>
359
+ ))}
360
+ </Section>
361
+ </Section>
362
+ </DataProvider>
363
+ );
364
+ }
365
+ };
366
+
367
+ // Enhanced ProviderDemo component using MUI components
368
+ const ProviderDemo = ({ provider, title }: { provider: any; title: string }) => {
369
+ const [stats, setStats] = useState(() => {
370
+ if ('getCacheStats' in provider && typeof provider.getCacheStats === 'function') {
371
+ return provider.getCacheStats();
372
+ }
373
+ return { size: 0, maxSize: 0, keys: [] };
374
+ });
375
+ const [refreshKey, setRefreshKey] = useState(0);
376
+
377
+ useEffect(() => {
378
+ const interval = setInterval(() => {
379
+ if ('getCacheStats' in provider && typeof provider.getCacheStats === 'function') {
380
+ setStats(provider.getCacheStats());
381
+ }
382
+ }, 1000);
383
+ return () => clearInterval(interval);
384
+ }, [provider]);
385
+
386
+ return (
387
+ <DataProvider dataSource={{ dataProvider: provider }}>
388
+ <Card elevation={2} sx={{ mb: 3 }}>
389
+ <CardContent>
390
+ <Box display="flex" justifyContent="space-between" alignItems="center" mb={2}>
391
+ <Typography variant="h6" component="h3">{title}</Typography>
392
+ <Chip label={`Cache: ${stats.size}/${stats.maxSize} items`} size="small" />
393
+ </Box>
394
+
395
+ <GridLayout spacing={2}>
396
+ <GridCell>
397
+ <Paper elevation={1} sx={{ p: 2 }}>
398
+ <Typography variant="subtitle1" gutterBottom>Company Info</Typography>
399
+ <Typography variant="body2">{t`Name: {{company.name}}`}</Typography>
400
+ <Typography variant="body2">{t`Founded: {{company.founded}}`}</Typography>
401
+ <Typography variant="body2">{t`Description: {{company.description}}`}</Typography>
402
+ </Paper>
403
+ </GridCell>
404
+ <GridCell>
405
+ <Paper elevation={1} sx={{ p: 2 }}>
406
+ <Typography variant="subtitle1" gutterBottom>Statistics</Typography>
407
+ <Typography variant="body2">{t`Users: {{stats.users}}`}</Typography>
408
+ <Typography variant="body2">{t`Projects: {{stats.projects}}`}</Typography>
409
+ <Typography variant="body2">{t`Downloads: {{stats.downloads}}`}</Typography>
410
+ </Paper>
411
+ </GridCell>
412
+ </GridLayout>
413
+ <hr />
414
+ <Box display="flex" gap={1} >
415
+ <Button
416
+ variant="outlined"
417
+ onClick={() => {
418
+ if ('clearCache' in provider && typeof provider.clearCache === 'function') {
419
+ provider.clearCache();
420
+ }
421
+ if ('getCacheStats' in provider && typeof provider.getCacheStats === 'function') {
422
+ setStats(provider.getCacheStats());
423
+ }
424
+ }}
425
+ >
426
+ Clear Cache
427
+ </Button>
428
+ <Button
429
+ variant="outlined"
430
+ onClick={() => setRefreshKey(prev => prev + 1)}
431
+ >
432
+ Force Refresh ({refreshKey})
433
+ </Button>
434
+ </Box>
435
+ </CardContent>
436
+ </Card>
437
+ </DataProvider>
438
+ );
439
+ };
440
+
441
+ // Component for testing hooks with MUI styling
442
+ const DataHooksDemo = () => {
443
+ const { data: companies, loading: companiesLoading } = useData('company');
444
+ const { resolved: welcomeMessage } = useResolveTemplate('Welcome to {{company.name}}, founded in {{company.founded}}!');
445
+
446
+ if (companiesLoading) {
447
+ return (
448
+ <Box sx={{ p: 3 }}>
449
+ <Typography>Loading content...</Typography>
450
+ </Box>
451
+ );
452
+ }
453
+
454
+ return (
455
+ <Box sx={{ p: 3, maxWidth: '800px' }}>
456
+ <Typography variant="h4" gutterBottom>DataProvider Hooks Demo</Typography>
457
+
458
+ <Paper elevation={1} sx={{ p: 2, mb: 3, bgcolor: 'grey.50' }}>
459
+ <Typography variant="h6" gutterBottom>useResolveTemplate Hook</Typography>
460
+ <Typography variant="h6" sx={{ fontWeight: 'normal' }}>{welcomeMessage}</Typography>
461
+ </Paper>
462
+
463
+ <Box mb={3}>
464
+ <Typography variant="h6" gutterBottom>useData Hook (All Companies)</Typography>
465
+ <GridLayout columns={1} spacing={2}>
466
+ {(Array.isArray(companies) ? companies : []).map((company, index) => (
467
+ <GridCell key={index}>
468
+ <Card variant="outlined">
469
+ <CardContent>
470
+ <Typography variant="h6">{company.name}</Typography>
471
+ <Typography color="text.secondary" gutterBottom>
472
+ {t`{{company.slogan}}`}
473
+ </Typography>
474
+ <Typography variant="body2">{t`Industry: {{company.profile.industry}} | Founded: {{company.founded}}`}</Typography>
475
+ </CardContent>
476
+ </Card>
477
+ </GridCell>
478
+ ))}
479
+ </GridLayout>
480
+ </Box>
481
+ </Box>
482
+ );
483
+ };
484
+
485
+ // Component for demonstrating t function with QwickApps React Framework components
486
+ const TaggedTemplateFunctionDemo = () => {
487
+ return (
488
+ <Box sx={{ p: 3, maxWidth: '800px' }}>
489
+ <Typography variant="h4" gutterBottom>Tagged Template Function Demo</Typography>
490
+
491
+ <Section>
492
+ <Typography variant="h5" gutterBottom>Basic Templates</Typography>
493
+ <Typography>Simple property access using mustache syntax:</Typography>
494
+
495
+ <GridLayout columns={1} spacing={0}>
496
+ <ul>
497
+ <li>{t`Company Name: {{company.name}}`}</li>
498
+ <li>{t`Founded: {{company.founded}}`}</li>
499
+ <li>{t`Slogan: {{company.slogan}}`}</li>
500
+ </ul>
501
+ </GridLayout>
502
+
503
+ <Code title="Basic Template Usage" language='tsx'>
504
+ {`<ul>
505
+ <li>{t\`Company Name: {{company.name}}\`}</li>
506
+ <li>{t\`Founded: {{company.founded}}\`}</li>
507
+ <li>{t\`Slogan: {{company.slogan}}\`}</li>
508
+ </ul>`}
509
+ </Code>
510
+ </Section>
511
+
512
+ <Section>
513
+ <Typography variant="h5" gutterBottom>Deep Nested Properties</Typography>
514
+ <Typography>Access deeply nested object properties with dot notation:</Typography>
515
+
516
+ <GridLayout columns={1} spacing={2}>
517
+ <ul>
518
+ <li><b>Industry: </b>{t`{{company.profile.industry}}`}</li>
519
+ <li><b>Location: </b>{t`{{company.profile.address.city}}, {{company.profile.address.state}}`}</li>
520
+ <li><b>Contact: </b>{t`{{company.profile.contact.email}}`}</li>
521
+ <li><b>Social: </b>{t`{{company.profile.contact.social.twitter}}`}</li>
522
+ </ul>
523
+ </GridLayout>
524
+
525
+ <Code title="Nested Property Access" language='tsx'>
526
+ {`<ul>
527
+ <li><b>Industry:</b>{t\`{{company.profile.industry}}\`}</li>
528
+ <li><b>Location:</b>{t\`{{company.profile.address.city}}, {{company.profile.address.state}}\`}</li>
529
+ <li><b>Contact:</b>{t\`{{company.profile.contact.email}}\`}</li>
530
+ </ul>`}
531
+ </Code>
532
+ </Section>
533
+
534
+ <Section>
535
+ <Typography variant="h5" gutterBottom>Complex Templates</Typography>
536
+ <Typography>Combine multiple properties in sophisticated template strings:</Typography>
537
+
538
+ <GridLayout columns={1}>
539
+ {t`{{company.name}} is a {{company.profile.industry}} company founded in {{company.founded}}. We're located in {{company.profile.address.city}}, {{company.profile.address.state}} and our mission is: "{{company.slogan}}"`}
540
+ {t`📊 Metrics: {{company.metrics.users}} users, {{company.metrics.apps}} apps, {{company.metrics.downloads}} downloads`}
541
+ </GridLayout>
542
+ <Box sx={{ pt: 2 }} />
543
+ <Code title="Complex Template Strings" language='tsx'>
544
+ {`<GridLayout columns={1}>
545
+ {t\`{{company.name}} is a {{company.profile.industry}} company founded in {{company.founded}}. We're located in {{company.profile.address.city}}, {{company.profile.address.state}} and our mission is: "{{company.slogan}}"\`}
546
+ {t\`📊 Metrics: {{company.metrics.users}} users, {{company.metrics.apps}} apps, {{company.metrics.downloads}} downloads\`}
547
+ </GridLayout>`}
548
+ </Code>
549
+ </Section>
550
+
551
+ <Section>
552
+ <Typography variant="h5">Template with Custom Wrapper</Typography>
553
+ <Typography>Templates can be wrapped with custom components. For example: the <code>blockquote</code> element can be used to create a quote-like appearance.</Typography>
554
+ {t.wrap(({ children }) => (
555
+ <blockquote style={{
556
+ padding: '15px',
557
+ borderLeft: '4px solid #007acc',
558
+ backgroundColor: '#f8f9fa',
559
+ margin: '10px 0',
560
+ fontStyle: 'italic'
561
+ }}>
562
+ {children}
563
+ </blockquote>
564
+ ))`"{{company.slogan}}" - {{company.name}} Team`}
565
+ <Code title="Template with Custom Wrapper" language='tsx'>
566
+ {`{t.wrap(({ children }) => (
567
+ <blockquote style={{
568
+ padding: '15px',
569
+ borderLeft: '4px solid #007acc',
570
+ backgroundColor: '#f8f9fa',
571
+ margin: '10px 0',
572
+ fontStyle: 'italic'
573
+ }}>
574
+ {children}
575
+ </blockquote>
576
+ ))\`"{{company.slogan}}" - {{company.name}} Team\`}`}
577
+ </Code>
578
+ </Section>
579
+ </Box>
580
+ );
581
+ };
582
+
583
+ // Interactive demo component
584
+ const InteractiveDemo = () => {
585
+ const [template, setTemplate] = useState('Hello {{company.name}}! You were founded in {{company.founded}}.');
586
+ const { resolved } = useResolveTemplate(template);
587
+
588
+ return (
589
+ <div style={{ padding: '20px', maxWidth: '800px' }}>
590
+ <h2>Interactive Template Editor</h2>
591
+ <p>Try editing the template below to see live template resolution:</p>
592
+
593
+ <div style={{ marginBottom: '20px' }}>
594
+ <label htmlFor="template-input" style={{ display: 'block', marginBottom: '8px', fontWeight: 'bold' }}>
595
+ Template (use {'{fieldGroup.property}'} syntax):
596
+ </label>
597
+ <textarea
598
+ id="template-input"
599
+ value={template}
600
+ onChange={(e) => setTemplate(e.target.value)}
601
+ style={{
602
+ width: '100%',
603
+ height: '100px',
604
+ padding: '10px',
605
+ borderRadius: '4px',
606
+ border: '1px solid #ccc',
607
+ fontFamily: 'monospace',
608
+ fontSize: '14px'
609
+ }}
610
+ placeholder="Enter your template here..."
611
+ />
612
+ </div>
613
+
614
+ <div style={{ padding: '15px', backgroundColor: '#f0f8ff', borderRadius: '8px' }}>
615
+ <h4>Resolved Output:</h4>
616
+ <div style={{
617
+ padding: '10px',
618
+ backgroundColor: 'white',
619
+ borderRadius: '4px',
620
+ minHeight: '40px',
621
+ display: 'flex',
622
+ alignItems: 'center',
623
+ fontSize: '16px'
624
+ }}>
625
+ {resolved}
626
+ </div>
627
+ </div>
628
+
629
+ <div style={{ marginTop: '20px', fontSize: '14px', color: '#666' }}>
630
+ <h4>Available Template Variables:</h4>
631
+ <ul style={{ columns: 2, columnGap: '30px' }}>
632
+ <li><code>{'{{company.name}}'}</code> - Company name</li>
633
+ <li><code>{'{{company.founded}}'}</code> - Year founded</li>
634
+ <li><code>{'{{company.slogan}}'}</code> - Company slogan</li>
635
+ <li><code>{'{{company.profile.industry}}'}</code> - Industry</li>
636
+ <li><code>{'{{company.profile.address.city}}'}</code> - City</li>
637
+ <li><code>{'{{company.profile.contact.email}}'}</code> - Email</li>
638
+ <li><code>{'{{company.metrics.users}}'}</code> - User count</li>
639
+ <li><code>{'{{features.0.title}}'}</code> - First feature title</li>
640
+ </ul>
641
+ </div>
642
+ </div>
643
+ );
644
+ };
645
+
646
+ // Error handling demo
647
+ const ErrorHandlingDemo = () => {
648
+
649
+ const errorProvider = new JsonDataProvider({
650
+ data: {
651
+ // Empty data to test missing properties
652
+ }
653
+ });
654
+
655
+ const provider = new CachedDataProvider(errorProvider, { maxSize: 50, defaultTTL: 30000 });
656
+
657
+ return (
658
+ <DataProvider dataSource={{ dataProvider: provider }}>
659
+ <div style={{ padding: '20px', maxWidth: '800px' }}>
660
+ <h2>Error Handling & Fallbacks Demo</h2>
661
+
662
+ <div style={{ marginBottom: '20px' }}>
663
+ <h3>Missing Properties (with fallbacks)</h3>
664
+ <div style={{ padding: '15px', backgroundColor: '#fff3cd', borderRadius: '8px', marginBottom: '10px' }}>
665
+ {t`Welcome to {{company.name}}!`}
666
+ </div>
667
+ <div style={{ padding: '15px', backgroundColor: '#fff3cd', borderRadius: '8px', marginBottom: '10px' }}>
668
+ {t`Our motto: "{{company.slogan}}"`}
669
+ </div>
670
+ </div>
671
+
672
+ <div style={{ marginBottom: '20px' }}>
673
+ <h3>Missing Properties (no fallbacks)</h3>
674
+ <div style={{ padding: '15px', backgroundColor: '#f8d7da', borderRadius: '8px', marginBottom: '10px' }}>
675
+ {t`Founded: {{company.founded}}`} (will be empty)
676
+ </div>
677
+ <div style={{ padding: '15px', backgroundColor: '#f8d7da', borderRadius: '8px', marginBottom: '10px' }}>
678
+ {t`Email: {{company.email}}`} (will be empty)
679
+ </div>
680
+ </div>
681
+
682
+ <div>
683
+ <h3>Template with Fallback Content</h3>
684
+ <div style={{ padding: '15px', backgroundColor: '#e1f5fe', borderRadius: '8px' }}>
685
+ <p>This template references missing data and should show the fallback:</p>
686
+ <T template="{{nonexistent.data}}" fallback="[No data available - this is the fallback content]" />
687
+ </div>
688
+ </div>
689
+ </div>
690
+ </DataProvider>
691
+ );
692
+ };
693
+
694
+ /**
695
+ * QwickApp integration with DataProvider
696
+ */
697
+ export const QwickAppIntegration: Story = {
698
+ render: () => {
699
+ const provider = new JsonDataProvider({
700
+ data: {
701
+ company: sampleCompanyData,
702
+ features: sampleFeaturesData.slice(0, 2), // Fewer features for cleaner display
703
+ team: sampleTeamData
704
+ }
705
+ });
706
+
707
+ return (
708
+ <QwickApp
709
+ appName="DataProvider Demo"
710
+ appId="com.qwickapps.content-demo"
711
+ dataSource={{ dataProvider: provider }}
712
+ enableScaffolding={true}
713
+ showThemeSwitcher={true}
714
+ navigationItems={[
715
+ { id: 'home', label: 'Home', href: '#' },
716
+ { id: 'features', label: 'Features', href: '#features' },
717
+ { id: 'team', label: 'Team', href: '#team' }
718
+ ]}
719
+ >
720
+ <div style={{ padding: '20px' }}>
721
+ <section style={{ textAlign: 'center', marginBottom: '40px' }}>
722
+ <h1>{t`Welcome to {{company.name}}`}</h1>
723
+ <p style={{ fontSize: '20px', color: '#666' }}>
724
+ {t`{{company.slogan}}`}
725
+ </p>
726
+ <p>
727
+ {t`We're a {{company.profile.industry}} company based in {{company.profile.address.city}}, {{company.profile.address.state}}, founded in {{company.founded}}.`}
728
+ </p>
729
+ </section>
730
+
731
+ <section id="features" style={{ marginBottom: '40px' }}>
732
+ <h2>Features</h2>
733
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: '20px' }}>
734
+ {sampleFeaturesData.slice(0, 2).map((feature, index) => (
735
+ <div key={index} style={{
736
+ padding: '20px',
737
+ border: '1px solid #ddd',
738
+ borderRadius: '8px',
739
+ textAlign: 'center'
740
+ }}>
741
+ <div style={{ fontSize: '48px', marginBottom: '10px' }}>
742
+ {feature.icon}
743
+ </div>
744
+ <h3>{feature.title}</h3>
745
+ <p>{feature.description}</p>
746
+ </div>
747
+ ))}
748
+ </div>
749
+ </section>
750
+
751
+ <section id="team">
752
+ <h2>Team</h2>
753
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '20px' }}>
754
+ {sampleTeamData.map((member, index) => (
755
+ <div key={index} style={{
756
+ padding: '20px',
757
+ border: '1px solid #ddd',
758
+ borderRadius: '8px',
759
+ textAlign: 'center'
760
+ }}>
761
+ <img
762
+ src={member.avatar}
763
+ alt=""
764
+ style={{ borderRadius: '50%', marginBottom: '10px' }}
765
+ />
766
+ <h3>{member.name}</h3>
767
+ <p style={{ fontWeight: 'bold', color: '#666' }}>
768
+ {member.role}
769
+ </p>
770
+ <p>{member.bio}</p>
771
+ </div>
772
+ ))}
773
+ </div>
774
+ </section>
775
+ </div>
776
+ </QwickApp>
777
+ );
778
+ }
779
+ };
780
+
781
+ /**
782
+ * Demonstration of React hooks for content
783
+ */
784
+ export const ReactHooks: Story = {
785
+ render: () => {
786
+ const provider = new JsonDataProvider({
787
+ data: {
788
+ company: sampleCompanyData,
789
+ features: sampleFeaturesData
790
+ }
791
+ });
792
+
793
+ return (
794
+ <DataProvider dataSource={{ dataProvider: provider }}>
795
+ <DataHooksDemo />
796
+ </DataProvider>
797
+ );
798
+ }
799
+ };
800
+
801
+ /**
802
+ * Tagged template function demonstration
803
+ */
804
+ export const TaggedTemplateFunction: Story = {
805
+ render: () => {
806
+ const provider = new JsonDataProvider({
807
+ data: {
808
+ company: sampleCompanyData,
809
+ features: sampleFeaturesData
810
+ }
811
+ });
812
+
813
+ return (
814
+ <DataProvider dataSource={{ dataProvider: provider }}>
815
+ <TaggedTemplateFunctionDemo />
816
+ </DataProvider>
817
+ );
818
+ }
819
+ };
820
+
821
+ /**
822
+ * Interactive template editor
823
+ */
824
+ export const InteractiveEditor: Story = {
825
+ render: () => {
826
+ const provider = new JsonDataProvider({
827
+ data: {
828
+ company: sampleCompanyData,
829
+ features: sampleFeaturesData
830
+ }
831
+ });
832
+
833
+ return (
834
+ <DataProvider dataSource={{ dataProvider: provider }}>
835
+ <InteractiveDemo />
836
+ </DataProvider>
837
+ );
838
+ }
839
+ };
840
+
841
+ /**
842
+ * Error handling and fallbacks
843
+ */
844
+ export const ErrorHandling: Story = {
845
+ render: () => <ErrorHandlingDemo />
846
+ };
847
+
848
+ /**
849
+ * External JSON file loading (simulated with fetch mock)
850
+ */
851
+ export const ExternalJSON: Story = {
852
+ render: () => {
853
+ // Mock fetch for this story
854
+ const originalFetch = global.fetch;
855
+ global.fetch = ((url: string) => {
856
+ if (url.includes('company.json')) {
857
+ return Promise.resolve({
858
+ ok: true,
859
+ json: () => Promise.resolve(sampleCompanyData)
860
+ });
861
+ }
862
+ if (url.includes('features.json')) {
863
+ return Promise.resolve({
864
+ ok: true,
865
+ json: () => Promise.resolve(sampleFeaturesData)
866
+ });
867
+ }
868
+ return Promise.reject(new Error('Not found'));
869
+ }) as typeof fetch;
870
+
871
+ const provider = new JsonDataProvider({
872
+ baseUrl: '/api/content'
873
+ });
874
+
875
+ React.useEffect(() => {
876
+ return () => {
877
+ global.fetch = originalFetch;
878
+ };
879
+ }, []);
880
+
881
+ return (
882
+ <DataProvider dataSource={{ dataProvider: provider }}>
883
+ <div style={{ padding: '20px', maxWidth: '600px' }}>
884
+ <h1>External JSON Loading</h1>
885
+ <p>This story demonstrates loading content from external JSON files.</p>
886
+ <p><small>Note: In this demo, fetch is mocked to simulate external API calls.</small></p>
887
+
888
+ <div style={{ marginBottom: '20px' }}>
889
+ <h2>{t`{{company.name}}`}</h2>
890
+ <p>{t`{{company.slogan}}`}</p>
891
+ </div>
892
+
893
+ <div>
894
+ <h3>Features</h3>
895
+ <p>First feature: {t`{{features.0.title}}`}</p>
896
+ <p>Second feature: {t`{{features.1.title}}`}</p>
897
+ <p>Company: {t`{{company.0.name}}`}</p>
898
+ </div>
899
+ </div>
900
+ </DataProvider>
901
+ );
902
+ }
903
+ };
904
+
905
+ /**
906
+ * Performance demonstration with caching
907
+ */
908
+ export const PerformanceDemo: Story = {
909
+ render: () => {
910
+ const [renderCount, setRenderCount] = useState(1);
911
+ const [cacheStats, setCacheStats] = useState<{ totalEntries: number; maxSize: number; expiredEntries: number }>({ totalEntries: 0, maxSize: 100, expiredEntries: 0 });
912
+ const [forceRefresh, setForceRefresh] = useState(0);
913
+ const [lastAction, setLastAction] = useState('Initial load');
914
+
915
+ // Create provider only once using useMemo
916
+ const provider = React.useMemo(() => {
917
+ const jsonProvider = new JsonDataProvider({
918
+ data: {
919
+ company: nestedTestData.company,
920
+ stats: nestedTestData.stats
921
+ }
922
+ });
923
+
924
+ return new CachedDataProvider(jsonProvider, { maxSize: 100, defaultTTL: 60000 });
925
+ }, []);
926
+
927
+ // Update cache stats when requested
928
+ const updateCacheStats = () => {
929
+ const stats = provider.getCacheStats();
930
+ // Map stats to expected shape for cacheStats state
931
+ setCacheStats({
932
+ totalEntries: stats.totalEntries ?? stats.totalEntries ?? 0,
933
+ maxSize: stats.maxSize ?? 100,
934
+ expiredEntries: stats.expiredEntries ?? stats.expiredEntries ?? 0
935
+ });
936
+ console.log('[Performance Demo] Cache stats updated:', stats);
937
+ };
938
+
939
+ // Initialize cache stats on mount
940
+ React.useEffect(() => {
941
+ // Small delay to let initial content load
942
+ setTimeout(() => {
943
+ updateCacheStats();
944
+ }, 100);
945
+ }, []);
946
+
947
+ // Update cache stats when content changes
948
+ React.useEffect(() => {
949
+ updateCacheStats();
950
+ }, [forceRefresh]);
951
+
952
+ const triggerRender = (action: string) => {
953
+ setRenderCount(prev => prev + 1);
954
+ setLastAction(action);
955
+ setForceRefresh(prev => prev + 1);
956
+ };
957
+
958
+ return (
959
+ <DataProvider dataSource={{ dataProvider: provider }}>
960
+ <div style={{ padding: '20px', maxWidth: '800px' }}>
961
+ <h1>Performance & Caching Demo</h1>
962
+
963
+ <div style={{
964
+ padding: '20px',
965
+ backgroundColor: '#e7f3ff',
966
+ borderRadius: '8px',
967
+ marginBottom: '20px',
968
+ border: '2px solid #2196f3'
969
+ }}>
970
+ <h3 style={{ marginTop: 0, color: '#1976d2' }}>📊 Performance Metrics</h3>
971
+
972
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))', gap: '15px', marginBottom: '15px' }}>
973
+ <div style={{ textAlign: 'center', padding: '10px', backgroundColor: 'white', borderRadius: '4px' }}>
974
+ <div style={{ fontSize: '24px', fontWeight: 'bold', color: '#4caf50' }}>{renderCount}</div>
975
+ <div style={{ fontSize: '12px', color: '#666' }}>Renders</div>
976
+ </div>
977
+
978
+ {/* <div style={{ textAlign: 'center', padding: '10px', backgroundColor: 'white', borderRadius: '4px' }}>
979
+ <div style={{ fontSize: '24px', fontWeight: 'bold', color: '#2196f3' }}>{cacheStats.expiredEntries.length > 0 ? '✓' : '○'}</div>
980
+ <div style={{ fontSize: '12px', color: '#666' }}>Cache Status</div>
981
+ <div style={{ fontSize: '10px', color: '#999', fontStyle: 'italic' }}>{cacheStats.expiredEntries.length > 0 ? 'Active' : 'Empty'}</div>
982
+ </div> */}
983
+
984
+ <div style={{ textAlign: 'center', padding: '10px', backgroundColor: 'white', borderRadius: '4px' }}>
985
+ <div style={{ fontSize: '24px', fontWeight: 'bold', color: '#ff9800' }}>{renderCount > 1 ? '⚡' : '○'}</div>
986
+ <div style={{ fontSize: '12px', color: '#666' }}>Performance</div>
987
+ <div style={{ fontSize: '10px', color: '#999', fontStyle: 'italic' }}>{renderCount > 1 ? 'Cached' : 'Loading'}</div>
988
+ </div>
989
+
990
+ <div style={{ textAlign: 'center', padding: '10px', backgroundColor: 'white', borderRadius: '4px' }}>
991
+ <div style={{ fontSize: '24px', fontWeight: 'bold', color: '#9c27b0' }}>{cacheStats.totalEntries}/{cacheStats.maxSize}</div>
992
+ <div style={{ fontSize: '12px', color: '#666' }}>Cache Usage</div>
993
+ </div>
994
+ </div>
995
+
996
+ <div style={{ marginBottom: '15px' }}>
997
+ <strong>Last Action:</strong> <span style={{ color: '#1976d2' }}>{lastAction}</span>
998
+ </div>
999
+
1000
+ {/* <div style={{ marginBottom: '15px' }}>
1001
+ <strong>Cached Field Groups:</strong>
1002
+ <div style={{ marginTop: '5px' }}>
1003
+ {cacheStats.expiredEntries.length > 0 ? (
1004
+ cacheStats.expiredEntries.map(key => (
1005
+ <span key={key} style={{
1006
+ display: 'inline-block',
1007
+ margin: '2px 5px 2px 0',
1008
+ padding: '2px 8px',
1009
+ backgroundColor: '#4caf50',
1010
+ color: 'white',
1011
+ borderRadius: '12px',
1012
+ fontSize: '12px'
1013
+ }}>
1014
+ {key}
1015
+ </span>
1016
+ ))
1017
+ ) : (
1018
+ <span style={{ color: '#666', fontStyle: 'italic' }}>No cached data yet</span>
1019
+ )}
1020
+ </div>
1021
+ </div> */}
1022
+
1023
+ <small style={{ color: '#666' }}>
1024
+ 💡 Open browser console to see detailed cache behavior logs.
1025
+ </small>
1026
+ </div>
1027
+
1028
+ <div style={{ display: 'flex', gap: '10px', marginBottom: '20px', flexWrap: 'wrap' }}>
1029
+ <button
1030
+ onClick={() => triggerRender('Manual re-render')}
1031
+ style={{
1032
+ padding: '12px 24px',
1033
+ backgroundColor: '#4caf50',
1034
+ color: 'white',
1035
+ border: 'none',
1036
+ borderRadius: '6px',
1037
+ cursor: 'pointer',
1038
+ fontWeight: 'bold',
1039
+ fontSize: '14px'
1040
+ }}
1041
+ >
1042
+ 🔄 Render Again
1043
+ </button>
1044
+
1045
+ <button
1046
+ onClick={() => {
1047
+ provider.clearCache();
1048
+ triggerRender('Cache cleared');
1049
+ }}
1050
+ style={{
1051
+ padding: '12px 24px',
1052
+ backgroundColor: '#f44336',
1053
+ color: 'white',
1054
+ border: 'none',
1055
+ borderRadius: '6px',
1056
+ cursor: 'pointer',
1057
+ fontWeight: 'bold',
1058
+ fontSize: '14px'
1059
+ }}
1060
+ >
1061
+ 🗋 Clear Cache
1062
+ </button>
1063
+
1064
+ <button
1065
+ onClick={() => {
1066
+ // Reset all metrics
1067
+ setRenderCount(1);
1068
+ setLastAction('Reset all metrics');
1069
+ provider.clearCache();
1070
+ updateCacheStats();
1071
+ }}
1072
+ style={{
1073
+ padding: '12px 24px',
1074
+ backgroundColor: '#9c27b0',
1075
+ color: 'white',
1076
+ border: 'none',
1077
+ borderRadius: '6px',
1078
+ cursor: 'pointer',
1079
+ fontWeight: 'bold',
1080
+ fontSize: '14px'
1081
+ }}
1082
+ >
1083
+ 🔄 Reset All
1084
+ </button>
1085
+ </div>
1086
+
1087
+ <div style={{
1088
+ padding: '20px',
1089
+ backgroundColor: '#f8f9fa',
1090
+ borderRadius: '8px',
1091
+ marginBottom: '20px'
1092
+ }}>
1093
+ <h3>Cached Data Demo</h3>
1094
+ <p style={{ marginBottom: '15px' }}>The data below is loaded through the DataProvider. Watch the cache metrics as you interact:</p>
1095
+
1096
+ <div key={forceRefresh} style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '15px' }}>
1097
+ <div style={{ padding: '15px', backgroundColor: 'white', borderRadius: '6px', border: '1px solid #ddd' }}>
1098
+ <h4 style={{ marginTop: 0, color: '#1976d2' }}>Company Info</h4>
1099
+ <p><strong>Name:</strong> {t`{{company.name}}`}</p>
1100
+ <p><strong>Slogan:</strong> {t`{{company.slogan}}`}</p>
1101
+ <p><strong>Founded:</strong> {t`{{company.founded}}`}</p>
1102
+ {/* <p><small style={{ color: '#666' }}>Loaded from: {cacheStats.expiredEntries.includes('company') ? '💾 Cache' : '🔄 Fresh fetch'}</small></p> */}
1103
+ </div>
1104
+
1105
+ <div style={{ padding: '15px', backgroundColor: 'white', borderRadius: '6px', border: '1px solid #ddd' }}>
1106
+ <h4 style={{ marginTop: 0, color: '#4caf50' }}>Features</h4>
1107
+ <p><strong>First:</strong> {t`{{features.0.title}}`}</p>
1108
+ <p><strong>Second:</strong> {t`{{features.1.title}}`}</p>
1109
+ <p><strong>Icon:</strong> {t`{{features.0.icon}}`}</p>
1110
+ {/* <p><small style={{ color: '#666' }}>Loaded from: {cacheStats.expiredEntries.includes('features') ? '💾 Cache' : '🔄 Fresh fetch'}</small></p> */}
1111
+ </div>
1112
+ </div>
1113
+ </div>
1114
+
1115
+ <div style={{
1116
+ padding: '15px',
1117
+ backgroundColor: '#fff3e0',
1118
+ borderRadius: '6px',
1119
+ fontSize: '14px'
1120
+ }}>
1121
+ <h4 style={{ marginTop: 0 }}>📝 How to Test:</h4>
1122
+ <ol style={{ marginBottom: 0, paddingLeft: '20px' }}>
1123
+ <li><strong>Watch "Cache Usage"</strong> - Shows {cacheStats.totalEntries}/{cacheStats.maxSize} cached items</li>
1124
+ <li><strong>Click "Render Again"</strong> - Forces content reload, updates "Loaded from" indicators</li>
1125
+ <li><strong>Click "Clear Cache"</strong> - Watch cache usage drop to 0/100, then rebuild</li>
1126
+ <li><strong>Check "Cached Field Groups"</strong> - Green badges show what's currently cached</li>
1127
+ <li><strong>Browser console logs</strong> - See JsonDataProvider cache hit/miss messages</li>
1128
+ <li><strong>"Loaded from" indicators</strong> - Shows if data came from cache 💾 or fresh fetch 🔄</li>
1129
+ </ol>
1130
+ </div>
1131
+ </div>
1132
+ </DataProvider>
1133
+ );
1134
+ }
1135
+ };
1136
+
1137
+ /**
1138
+ * Deep nested property access demonstration with enhanced MUI styling
1139
+ */
1140
+ export const NestedProperties: Story = {
1141
+ render: () => {
1142
+ const provider = new JsonDataProvider({
1143
+ data: nestedTestData,
1144
+ enableLogging: true
1145
+ });
1146
+
1147
+ return (
1148
+ <DataProvider dataSource={{ dataProvider: provider }}>
1149
+ <Box sx={{ p: 3 }}>
1150
+ <Typography variant="h4" gutterBottom>Deep Nested Property Access</Typography>
1151
+ <Typography variant="body1" paragraph>
1152
+ JsonDataProvider supports deep nested property access using dot notation.
1153
+ </Typography>
1154
+
1155
+ <GridLayout columns={2} spacing={3}>
1156
+ <GridCell>
1157
+ <Card sx={{ bgcolor: 'primary.50' }}>
1158
+ <CardContent>
1159
+ <Typography variant="h6" gutterBottom>Basic Properties</Typography>
1160
+ <Typography variant="body2" paragraph>{t`Company: {{company.name}}`}</Typography>
1161
+ <Typography variant="body2" paragraph>{t`Industry: {{company.profile.industry}}`}</Typography>
1162
+ <Typography variant="body2">{t`Size: {{company.profile.size}}`}</Typography>
1163
+ </CardContent>
1164
+ </Card>
1165
+ </GridCell>
1166
+
1167
+ <GridCell>
1168
+ <Card sx={{ bgcolor: 'success.50' }}>
1169
+ <CardContent>
1170
+ <Typography variant="h6" gutterBottom>Location Details</Typography>
1171
+ <Typography variant="body2" paragraph>{t`City: {{company.profile.location.city}}`}</Typography>
1172
+ <Typography variant="body2" paragraph>{t`State: {{company.profile.location.state}}`}</Typography>
1173
+ <Typography variant="body2" paragraph>{t`Country: {{company.profile.location.country}}`}</Typography>
1174
+ <Typography variant="body2">{t`Timezone: {{company.profile.location.timezone}}`}</Typography>
1175
+ </CardContent>
1176
+ </Card>
1177
+ </GridCell>
1178
+
1179
+ <GridCell>
1180
+ <Card sx={{ bgcolor: 'warning.50' }}>
1181
+ <CardContent>
1182
+ <Typography variant="h6" gutterBottom>Contact Information</Typography>
1183
+ <Typography variant="body2" paragraph>{t`Email: {{company.profile.contact.email}}`}</Typography>
1184
+ <Typography variant="body2" paragraph>{t`Phone: {{company.profile.contact.phone}}`}</Typography>
1185
+ <Typography variant="body2" paragraph>{t`Website: {{company.profile.contact.social.website}}`}</Typography>
1186
+ <Typography variant="body2">{t`Twitter: {{company.profile.contact.social.twitter}}`}</Typography>
1187
+ </CardContent>
1188
+ </Card>
1189
+ </GridCell>
1190
+
1191
+ <GridCell>
1192
+ <Card sx={{ bgcolor: 'secondary.50' }}>
1193
+ <CardContent>
1194
+ <Typography variant="h6" gutterBottom>Business Metrics</Typography>
1195
+ <Typography variant="body2" paragraph>{t`Employees: {{company.metrics.employees}}`}</Typography>
1196
+ <Typography variant="body2" paragraph>{t`Revenue: {{company.metrics.revenue}}`}</Typography>
1197
+ <Typography variant="body2" paragraph>{t`Growth: {{company.metrics.growth}}%`}</Typography>
1198
+ <Typography variant="body2">{t`Founded: {{company.metrics.founded}}`}</Typography>
1199
+ </CardContent>
1200
+ </Card>
1201
+ </GridCell>
1202
+ </GridLayout>
1203
+
1204
+ <Paper elevation={2} sx={{ p: 3, mt: 4 }}>
1205
+ <Typography variant="h6" gutterBottom>Complex Template:</Typography>
1206
+ <Paper variant="outlined" sx={{ p: 2, mt: 2, bgcolor: 'grey.50' }}>
1207
+ {t`{{company.name}} is a {{company.profile.industry}} company based in {{company.profile.location.city}}, {{company.profile.location.state}}. Founded in {{company.metrics.founded}}, we now have {{company.metrics.employees}} employees and generated {{company.metrics.revenue}} in revenue. Contact us at {{company.profile.contact.email}} or visit {{company.profile.contact.social.website}}.`}
1208
+ </Paper>
1209
+ </Paper>
1210
+ </Box>
1211
+ </DataProvider>
1212
+ );
1213
+ }
1214
+ };
1215
+
1216
+ /**
1217
+ * Caching behavior demonstration with side-by-side providers
1218
+ */
1219
+ export const CachingBehavior: Story = {
1220
+ render: () => {
1221
+ const dataProvider = new JsonDataProvider({ data: nestedTestData })
1222
+ const fastCacheProvider = new CachedDataProvider(dataProvider, {
1223
+ defaultTTL: 3000, // 3 seconds
1224
+ maxSize: 5,
1225
+ enableLogging: true
1226
+ });
1227
+
1228
+ const slowCacheProvider = new CachedDataProvider(dataProvider, {
1229
+ defaultTTL: 10000, // 10 seconds
1230
+ maxSize: 5,
1231
+ enableLogging: true
1232
+ });
1233
+
1234
+ return (
1235
+ <Box sx={{ p: 3 }}>
1236
+ <Typography variant="h4" gutterBottom>Caching Behavior</Typography>
1237
+ <Typography variant="body1" paragraph>
1238
+ Compare different caching configurations. Check the browser console to see cache logs.
1239
+ </Typography>
1240
+
1241
+ <GridLayout columns={2} spacing={3}>
1242
+ <GridCell>
1243
+ <Typography variant="h6" gutterBottom>Fast Cache (3s timeout)</Typography>
1244
+ <ProviderDemo provider={fastCacheProvider} title="Fast Cache Provider" />
1245
+ </GridCell>
1246
+ <GridCell>
1247
+ <Typography variant="h6" gutterBottom>Slow Cache (10s timeout)</Typography>
1248
+ <ProviderDemo provider={slowCacheProvider} title="Slow Cache Provider" />
1249
+ </GridCell>
1250
+ </GridLayout>
1251
+
1252
+ <Alert severity="info" sx={{ mt: 2 }}>
1253
+ <Typography variant="subtitle2" gutterBottom>💡 Try This:</Typography>
1254
+ <ol>
1255
+ <li>Open browser console to see cache logs</li>
1256
+ <li>Click "Force Refresh" buttons to trigger content loading</li>
1257
+ <li>Notice how fast cache expires content more quickly</li>
1258
+ <li>Click "Clear Cache" to manually invalidate cache</li>
1259
+ </ol>
1260
+ </Alert>
1261
+ </Box>
1262
+ );
1263
+ }
1264
+ };
1265
+
1266
+ /**
1267
+ * Interactive configuration playground with real-time settings
1268
+ */
1269
+ export const ConfigurationPlayground: Story = {
1270
+ render: () => {
1271
+ const [config, setConfig] = useState({
1272
+ cacheTimeout: 5000,
1273
+ maxCacheSize: 10,
1274
+ enableLogging: true
1275
+ });
1276
+
1277
+ const [provider, setProvider] = useState(() => new JsonDataProvider({
1278
+ data: nestedTestData,
1279
+ ...config
1280
+ }));
1281
+
1282
+ const updateConfig = (newConfig: Partial<typeof config>) => {
1283
+ const updatedConfig = { ...config, ...newConfig };
1284
+ setConfig(updatedConfig);
1285
+ setProvider(new JsonDataProvider({
1286
+ data: nestedTestData,
1287
+ ...updatedConfig
1288
+ }));
1289
+ };
1290
+
1291
+ return (
1292
+ <Box sx={{ p: 3 }}>
1293
+ <Typography variant="h4" gutterBottom>Configuration Playground</Typography>
1294
+ <Typography variant="body1" paragraph>
1295
+ Experiment with different JsonDataProvider configuration options.
1296
+ </Typography>
1297
+
1298
+ <GridLayout spacing={3} equalHeight>
1299
+ <GridCell span={12}>
1300
+ <Alert severity="success" sx={{ mt: 2 }}>
1301
+ <Typography variant="subtitle2" gutterBottom>💡 Tips:</Typography>
1302
+ <ul style={{ margin: 0, paddingLeft: '20px' }}>
1303
+ <li>Lower cache timeout = more frequent cache invalidation</li>
1304
+ <li>Smaller max cache size = more aggressive LRU eviction</li>
1305
+ <li>Enable logging to see cache behavior in console</li>
1306
+ <li>Watch cache stats update in real-time</li>
1307
+ </ul>
1308
+ </Alert>
1309
+ </GridCell>
1310
+ <Card>
1311
+ <CardContent>
1312
+ <Typography variant="h6" gutterBottom>Configuration</Typography>
1313
+
1314
+ <Box sx={{ mb: 3 }}>
1315
+ <Typography gutterBottom>Cache Timeout (ms): {config.cacheTimeout}</Typography>
1316
+ <Slider
1317
+ value={config.cacheTimeout}
1318
+ min={1000}
1319
+ max={30000}
1320
+ step={1000}
1321
+ onChange={(_, value) => updateConfig({ cacheTimeout: value as number })}
1322
+ />
1323
+ </Box>
1324
+
1325
+ <Box sx={{ mb: 3 }}>
1326
+ <Typography gutterBottom>Max Cache Size: {config.maxCacheSize}</Typography>
1327
+ <Slider
1328
+ value={config.maxCacheSize}
1329
+ min={1}
1330
+ max={50}
1331
+ step={1}
1332
+ onChange={(_, value) => updateConfig({ maxCacheSize: value as number })}
1333
+ />
1334
+ </Box>
1335
+
1336
+ <FormControlLabel
1337
+ control={
1338
+ <Checkbox
1339
+ checked={config.enableLogging}
1340
+ onChange={(e) => updateConfig({ enableLogging: e.target.checked })}
1341
+ />
1342
+ }
1343
+ label="Enable Logging"
1344
+ sx={{ mb: 2 }}
1345
+ />
1346
+
1347
+ <Paper variant="outlined" sx={{ p: 2, bgcolor: 'grey.50' }}>
1348
+ <Typography variant="subtitle2" gutterBottom>Current Config:</Typography>
1349
+ <Typography variant="body2" component="pre" sx={{ fontFamily: 'monospace', fontSize: '0.75rem' }}>
1350
+ {JSON.stringify(config, null, 2)}
1351
+ </Typography>
1352
+ </Paper>
1353
+ </CardContent>
1354
+ </Card>
1355
+
1356
+ <ProviderDemo provider={provider} title="Configured Provider" />
1357
+ </GridLayout>
1358
+ </Box>
1359
+ );
1360
+ }
1361
+ };