@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,370 @@
1
+ /**
2
+ * Dynamic Logo Component - Generic theme-aware logo
3
+ *
4
+ * Features:
5
+ * - Automatic text width calculation with dynamic SVG sizing
6
+ * - Semantic badge positioning (top-left, top-right, center, etc.)
7
+ * - Customizable badge position via custom coordinates or relative offset
8
+ * - Multiple badge shapes: circle, star, square, heart
9
+ * - Theme-aware styling with multiple variants
10
+ * - Accessibility support with proper ARIA labels
11
+ * - Customizable styling via CSS classes for each text part
12
+ * - Text formatting with escape sequences
13
+ *
14
+ * Text Formatting (TWO PARTS MAXIMUM):
15
+ * - Use \n for line breaks (second part appears on new line)
16
+ * - Use \s for explicit spaces (useful for custom spacing)
17
+ * - Default: Two-word logos appear as one word in two colors (no space)
18
+ * - Limitation: Only TWO parts supported - multiple \n will not create more than two lines
19
+ * - Examples: "QwickApps" (one word, one color), "Qwick Apps" (two parts, two colors), "Qwick\sApps" (two parts with space), "Qwick\nApps" (two parts on two lines)
20
+ *
21
+ * Badge Positioning:
22
+ * - Semantic: Use 'top-left', 'top-right', 'center', etc. (automatically adapts to logo size)
23
+ * - Default: 'top-right' - positions at top-right of text
24
+ * - Offset: Use badgeOffset to fine-tune any position (automatically scales with size)
25
+ * - None: Use 'none' to hide the badge
26
+ * - Flexible: Combine any semantic position with custom offsets for precise control
27
+ *
28
+ * Text Styling:
29
+ * - Use firstPartClass and secondPartClass for custom CSS styling
30
+ * - Default classes: 'logo-first-part' and 'logo-second-part'
31
+ * - Font family and weight can be set via props for basic customization
32
+ * - Advanced styling (colors, effects, transforms) via CSS classes
33
+ *
34
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
35
+ */
36
+
37
+ import React, { useRef, useEffect, useState, useCallback } from 'react';
38
+ import { WithBaseProps, useBaseProps, QWICKAPP_COMPONENT } from '../hooks/useBaseProps';
39
+ import './Logo.css';
40
+
41
+ export type LogoVariant = 'default' | 'high-contrast' | 'monochrome' | 'on-primary';
42
+ export type LogoSize = 'tiny' | 'small' | 'medium' | 'large' | 'extra-large';
43
+ export type LogoBadgeShape = 'circle' | 'star' | 'square' | 'heart';
44
+ export type BadgePositionType =
45
+ | 'none'
46
+ | 'top-left'
47
+ | 'top-center'
48
+ | 'top-right'
49
+ | 'center-left'
50
+ | 'center'
51
+ | 'center-right'
52
+ | 'bottom-left'
53
+ | 'bottom-center'
54
+ | 'bottom-right';
55
+
56
+ export interface BadgeOffset {
57
+ /** Horizontal offset from the calculated position (positive = right, negative = left) */
58
+ x?: number;
59
+ /** Vertical offset from the calculated position (positive = down, negative = up) */
60
+ y?: number;
61
+ }
62
+
63
+ export interface LogoProps extends WithBaseProps, Omit<React.SVGProps<SVGSVGElement>, 'width' | 'height' | 'className' | 'style' | 'role' | 'onClick' | 'onMouseEnter' | 'onMouseLeave' | 'onFocus' | 'onBlur'> {
64
+ /** Logo name/text to display. Supports up to TWO parts with \n for line breaks and \s for explicit spaces. */
65
+ name?: string;
66
+ /** Click handler for the logo */
67
+ onClick?: (event: React.MouseEvent<SVGSVGElement>) => void;
68
+ /** Additional inline styles */
69
+ style?: React.CSSProperties;
70
+ /** Visual variant of the logo */
71
+ variant?: LogoVariant;
72
+ /** Size variant of the logo (controls both text size and visual height) */
73
+ size?: LogoSize;
74
+ /** Additional CSS class names */
75
+ className?: string;
76
+ /** Badge position and visibility. 'none' hides the badge, others show it at the specified position. */
77
+ badge?: BadgePositionType;
78
+ /** Shape of the badge */
79
+ badgeShape?: LogoBadgeShape;
80
+ /** Offset from the calculated badge position. Applied after position calculation. Automatically scales with logo size. */
81
+ badgeOffset?: BadgeOffset;
82
+ /** Font family for the logo text */
83
+ fontFamily?: string;
84
+ /** Font weight for the logo text */
85
+ fontWeight?: string | number;
86
+ /** CSS class name for the first part of the logo text. Defaults to 'logo-first-part'. */
87
+ firstPartClass?: string;
88
+ /** CSS class name for the second part of the logo text. Defaults to 'logo-second-part'. */
89
+ secondPartClass?: string;
90
+ }
91
+
92
+ const Logo: React.FC<LogoProps> = (props) => {
93
+ const { styleProps, htmlProps, restProps } = useBaseProps(props);
94
+ const {
95
+ name = 'Qwick Apps',
96
+ variant = 'default',
97
+ size = 'medium',
98
+ badge = 'top-right',
99
+ badgeShape = 'circle',
100
+ badgeOffset,
101
+ fontFamily = 'Segoe UI, sans-serif',
102
+ fontWeight = 'bold',
103
+ firstPartClass = 'logo-first-part',
104
+ secondPartClass = 'logo-second-part',
105
+ ...svgProps
106
+ } = restProps;
107
+
108
+ // Mark as QwickApp component
109
+ (Logo as any)[QWICKAPP_COMPONENT] = true;
110
+
111
+ const textRef = useRef<SVGTextElement>(null);
112
+ const [calculatedBadgePosition, setCalculatedBadgePosition] = useState({ x: 155, y: 20 });
113
+ const [svgWidth, setSvgWidth] = useState(180);
114
+
115
+ // Parse name with support for escape sequences to determine structure
116
+ const parseNameParts = useCallback((text: string) => {
117
+ // Handle line breaks first
118
+ if (text.includes('\\n')) {
119
+ const [first, ...rest] = text.split('\\n');
120
+ return {
121
+ firstPart: first.replace(/\\s/g, ' '),
122
+ secondPart: rest.join('\\n').replace(/\\s/g, ' '),
123
+ isNewLine: true
124
+ };
125
+ }
126
+
127
+ // Check if text contains explicit \s sequences
128
+ if (text.includes('\\s')) {
129
+ // Handle explicit spaces - split by \s and treat as two parts
130
+ const parts = text.split('\\s');
131
+ if (parts.length >= 2) {
132
+ return {
133
+ firstPart: parts[0],
134
+ secondPart: parts.slice(1).join(' '), // Join remaining parts with spaces
135
+ isNewLine: false
136
+ };
137
+ } else {
138
+ return { firstPart: parts[0], secondPart: '', isNewLine: false };
139
+ }
140
+ }
141
+
142
+ // Regular word splitting (no explicit \s)
143
+ const nameParts = text.trim().split(/\s+/);
144
+
145
+ if (nameParts.length === 1) {
146
+ return { firstPart: nameParts[0], secondPart: '', isNewLine: false };
147
+ } else if (nameParts.length === 2) {
148
+ return { firstPart: nameParts[0], secondPart: nameParts[1], isNewLine: false };
149
+ } else {
150
+ // More than 2 words: everything except last word goes to first part
151
+ return {
152
+ firstPart: nameParts.slice(0, -1).join(' '),
153
+ secondPart: nameParts[nameParts.length - 1],
154
+ isNewLine: false
155
+ };
156
+ }
157
+ }, []);
158
+
159
+ const { firstPart, secondPart, isNewLine } = parseNameParts(name);
160
+
161
+ // Check if original name contained explicit spaces
162
+ const hasExplicitSpaces = name.includes('\\s');
163
+
164
+ // Determine size class, font size, and component height (accounting for line breaks)
165
+ const sizeClass = `logo-${size}`;
166
+ const getSizeConfig = (size: LogoSize, hasLineBreak: boolean) => {
167
+ const baseConfig = {
168
+ 'tiny': { fontSize: 16, height: 32 },
169
+ 'small': { fontSize: 20, height: 40 },
170
+ 'medium': { fontSize: 28, height: 50 },
171
+ 'large': { fontSize: 36, height: 64 },
172
+ 'extra-large': { fontSize: 48, height: 84 }
173
+ };
174
+
175
+ const config = baseConfig[size] || baseConfig.medium;
176
+
177
+ // Add extra height for line breaks (approximately 1.4x the font size for proper spacing)
178
+ if (hasLineBreak) {
179
+ config.height += Math.round(config.fontSize * 1.4);
180
+ }
181
+
182
+ return config;
183
+ };
184
+ const { fontSize, height } = getSizeConfig(size, isNewLine);
185
+
186
+ // Calculate badge position based on semantic positioning system
187
+ const calculateBadgePosition = useCallback((textBBox: DOMRect, svgWidth: number, svgHeight: number) => {
188
+ // Scale factor based on font size (medium/28px is the baseline)
189
+ const scale = fontSize / 28; // 28 is the medium/default font size
190
+ const scaledOffset = 8 * scale;
191
+
192
+ // Scale custom offset based on size
193
+ const scaledOffsetX = (badgeOffset?.x ?? 0) * scale;
194
+ const scaledOffsetY = (badgeOffset?.y ?? 0) * scale;
195
+
196
+ // Calculate position based on semantic positioning
197
+ let x: number, y: number;
198
+
199
+ switch (badge) {
200
+ case 'top-left':
201
+ x = textBBox.x - scaledOffset;
202
+ y = textBBox.y + scaledOffset;
203
+ break;
204
+ case 'top-center':
205
+ x = textBBox.x + textBBox.width / 2;
206
+ y = textBBox.y + scaledOffset;
207
+ break;
208
+ case 'top-right':
209
+ x = textBBox.x + textBBox.width + scaledOffset;
210
+ y = textBBox.y + scaledOffset;
211
+ break;
212
+ case 'center-left':
213
+ x = textBBox.x - scaledOffset;
214
+ y = textBBox.y + textBBox.height / 2;
215
+ break;
216
+ case 'center':
217
+ x = textBBox.x + textBBox.width / 2;
218
+ y = textBBox.y + textBBox.height / 2;
219
+ break;
220
+ case 'center-right':
221
+ x = textBBox.x + textBBox.width + scaledOffset;
222
+ y = textBBox.y + textBBox.height / 2;
223
+ break;
224
+ case 'bottom-left':
225
+ x = textBBox.x - scaledOffset;
226
+ y = textBBox.y + textBBox.height - scaledOffset;
227
+ break;
228
+ case 'bottom-center':
229
+ x = textBBox.x + textBBox.width / 2;
230
+ y = textBBox.y + textBBox.height - scaledOffset;
231
+ break;
232
+ case 'bottom-right':
233
+ x = textBBox.x + textBBox.width + scaledOffset;
234
+ y = textBBox.y + textBBox.height - scaledOffset;
235
+ break;
236
+ default:
237
+ // Default: top-right of text
238
+ x = textBBox.x + textBBox.width + scaledOffset;
239
+ y = textBBox.y + scaledOffset;
240
+ break;
241
+ }
242
+
243
+ return {
244
+ x: x + scaledOffsetX,
245
+ y: y + scaledOffsetY
246
+ };
247
+ }, [badge, badgeOffset, fontSize]);
248
+
249
+ // Calculate badge position and SVG width based on text width
250
+ useEffect(() => {
251
+ if (textRef.current) {
252
+ const textBBox = textRef.current.getBBox();
253
+ // Calculate badge position using semantic positioning
254
+ const badgePos = calculateBadgePosition(textBBox, svgWidth, height);
255
+ // Ensure SVG is wide enough to accommodate text and badge
256
+ const requiredWidth = Math.max(180, textBBox.x + textBBox.width + 20);
257
+
258
+ setCalculatedBadgePosition(badgePos);
259
+ setSvgWidth(requiredWidth);
260
+ }
261
+ }, [name, badge, badgeOffset, calculateBadgePosition, fontSize, height, parseNameParts]);
262
+
263
+ // Determine CSS class for variant
264
+ let variantClass = '';
265
+ if (variant === 'high-contrast' || variant === 'monochrome' || variant === 'on-primary') {
266
+ variantClass = `logo-${variant}`;
267
+ } else if (variant !== 'default') {
268
+ variantClass = `logo-${variant}`;
269
+ } else {
270
+ variantClass = 'logo-default';
271
+ }
272
+
273
+ // Create aria-label from the logo name
274
+ const ariaLabel = `${name} Logo`;
275
+
276
+ // Render badge shape
277
+ const renderBadgeShape = (): React.ReactNode => {
278
+ if (badge === 'none') return null;
279
+
280
+ const baseProps = {
281
+ className: `logo-badge logo-badge-${badgeShape}`,
282
+ };
283
+
284
+ // Use the calculated position (which includes custom position logic)
285
+ const { x, y } = calculatedBadgePosition;
286
+
287
+ // Scale badge size based on font size
288
+ const scale = fontSize / 28; // 28 is the medium/default font size
289
+ const badgeRadius = 5 * scale;
290
+ const badgeSize = 10 * scale;
291
+
292
+ switch (badgeShape) {
293
+ case 'circle':
294
+ return (
295
+ <circle cx={x} cy={y} r={badgeRadius} {...baseProps}>
296
+ <animate attributeName="r" values={`${badgeRadius};${badgeRadius + 1};${badgeRadius}`} dur="1.5s" repeatCount="indefinite" />
297
+ </circle>
298
+ );
299
+ case 'star':
300
+ const starScale = scale;
301
+ return (
302
+ <polygon
303
+ points={`${x},${y-5*starScale} ${x+2*starScale},${y} ${x+7*starScale},${y} ${x+3*starScale},${y+3*starScale} ${x+5*starScale},${y+8*starScale} ${x},${y+5*starScale} ${x-5*starScale},${y+8*starScale} ${x-3*starScale},${y+3*starScale} ${x-7*starScale},${y} ${x-2*starScale},${y}`}
304
+ {...baseProps}
305
+ >
306
+ <animate attributeName="opacity" values="0.8;1;0.8" dur="1.5s" repeatCount="indefinite" />
307
+ </polygon>
308
+ );
309
+ case 'square':
310
+ return (
311
+ <rect x={x-badgeRadius} y={y-badgeRadius} width={badgeSize} height={badgeSize} {...baseProps}>
312
+ <animate attributeName="opacity" values="0.8;1;0.8" dur="1.5s" repeatCount="indefinite" />
313
+ </rect>
314
+ );
315
+ case 'heart':
316
+ const heartScale = scale;
317
+ return (
318
+ <path
319
+ d={`M${x},${y+6*heartScale} C${x},${y+6*heartScale} ${x-7*heartScale},${y} ${x-7*heartScale},${y-4*heartScale} C${x-7*heartScale},${y-6*heartScale} ${x-5*heartScale},${y-8*heartScale} ${x-3*heartScale},${y-8*heartScale} C${x-2*heartScale},${y-8*heartScale} ${x},${y-7*heartScale} ${x},${y-5*heartScale} C${x},${y-7*heartScale} ${x+2*heartScale},${y-8*heartScale} ${x+3*heartScale},${y-8*heartScale} C${x+5*heartScale},${y-8*heartScale} ${x+7*heartScale},${y-6*heartScale} ${x+7*heartScale},${y-4*heartScale} C${x+7*heartScale},${y} ${x},${y+6*heartScale} ${x},${y+6*heartScale} Z`}
320
+ {...baseProps}
321
+ >
322
+ <animate attributeName="fill-opacity" values="0.7;1;0.7" dur="1.5s" repeatCount="indefinite" />
323
+ </path>
324
+ );
325
+ default:
326
+ return (
327
+ <circle cx={x} cy={y} r={badgeRadius} {...baseProps}>
328
+ <animate attributeName="r" values={`${badgeRadius};${badgeRadius + 1};${badgeRadius}`} dur="1.5s" repeatCount="indefinite" />
329
+ </circle>
330
+ );
331
+ }
332
+ };
333
+
334
+ return (
335
+ <svg
336
+ width={svgWidth}
337
+ height={height}
338
+ viewBox={`0 0 ${svgWidth} ${height}`}
339
+ fill="none"
340
+ xmlns="http://www.w3.org/2000/svg"
341
+ {...htmlProps}
342
+ {...styleProps}
343
+ className={`logo dynamic-logo ${sizeClass} ${variantClass} ${styleProps.className || ''}`.trim()}
344
+ style={{
345
+ height: `${height}px`,
346
+ cursor: htmlProps.onClick ? 'pointer' : 'default',
347
+ ...styleProps.style
348
+ }}
349
+ role="img"
350
+ aria-label={ariaLabel}
351
+ {...svgProps}
352
+ >
353
+ <text ref={textRef} fontFamily={fontFamily} fontSize={fontSize} fontWeight={fontWeight}>
354
+ <tspan x="15" y={isNewLine ? height * 0.4 : height * 0.7} className={firstPartClass}>{firstPart}</tspan>
355
+ {secondPart && (
356
+ <tspan
357
+ x={isNewLine ? "15" : undefined}
358
+ dy={isNewLine ? fontSize * 1.2 : undefined}
359
+ className={secondPartClass}
360
+ >
361
+ {isNewLine ? secondPart : (hasExplicitSpaces ? ` ${secondPart}` : secondPart)}
362
+ </tspan>
363
+ )}
364
+ </text>
365
+ {renderBadgeShape()}
366
+ </svg>
367
+ );
368
+ };
369
+
370
+ export default Logo;
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Markdown Component - Transforms Markdown strings into Framework components
3
+ *
4
+ * Accepts Markdown string as children and converts it through a
5
+ * Markdown → HTML → React components pipeline using the Html component
6
+ * with Markdown-optimized transformation rules.
7
+ *
8
+ * Features:
9
+ * - Full Markdown syntax support via marked library
10
+ * - Transform rules optimized for Markdown content
11
+ * - Code block syntax highlighting
12
+ * - Preserves inline code elements (no transformation)
13
+ * - TypeScript support with proper props interface
14
+ * - Error handling and fallback to Html component
15
+ *
16
+ * Usage:
17
+ * - Basic: <Markdown>{markdownString}</Markdown>
18
+ * - Custom config: <Markdown htmlTransformConfig={customConfig}>{markdownString}</Markdown>
19
+ *
20
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
21
+ */
22
+
23
+ import { Box } from '@mui/material';
24
+ import { marked } from 'marked';
25
+ import React from 'react';
26
+ import { QWICKAPP_COMPONENT, useBaseProps, WithBaseProps } from '../hooks';
27
+ import Html from './Html';
28
+ import SafeSpan from './SafeSpan';
29
+ import { TransformConfig, defaultMarkdownRules } from '../utils/htmlTransform';
30
+
31
+ export interface MarkdownProps extends WithBaseProps {
32
+ /** Markdown content as string */
33
+ children: string;
34
+ /** Custom transformation configuration for HTML conversion */
35
+ htmlTransformConfig?: TransformConfig;
36
+ /** Whether to sanitize HTML output (default: true) */
37
+ sanitize?: boolean;
38
+ /** Custom sanitization options */
39
+ sanitizeOptions?: any;
40
+ /** Fallback content when Markdown is empty */
41
+ placeholder?: string;
42
+ /** Container element type */
43
+ component?: React.ElementType;
44
+ /** Marked options for Markdown parsing */
45
+ markedOptions?: marked.MarkedOptions;
46
+ }
47
+
48
+ /**
49
+ * Configure marked with security and GitHub Flavored Markdown support
50
+ */
51
+ const getMarkedOptions = (customOptions?: marked.MarkedOptions): marked.MarkedOptions => ({
52
+ // GitHub Flavored Markdown
53
+ gfm: true,
54
+ // Convert line breaks to <br> tags
55
+ breaks: false,
56
+ // Pedantic compliance to original markdown.pl
57
+ pedantic: false,
58
+ // Sanitize HTML (we handle this in Html component)
59
+ sanitize: false,
60
+ // Smart punctuation
61
+ smartypants: false,
62
+ // Custom renderer options
63
+ renderer: new marked.Renderer(),
64
+ // Override with user options
65
+ ...customOptions
66
+ });
67
+
68
+ /**
69
+ * Markdown component - converts Markdown to React components via Html
70
+ */
71
+ export function Markdown({
72
+ children = '',
73
+ htmlTransformConfig,
74
+ sanitize = true,
75
+ sanitizeOptions,
76
+ placeholder,
77
+ component = 'div',
78
+ markedOptions,
79
+ ...restProps
80
+ }: MarkdownProps) {
81
+ const { styleProps, htmlProps, restProps: otherProps } = useBaseProps(restProps);
82
+
83
+ // Mark as QwickApp component
84
+ (Markdown as any)[QWICKAPP_COMPONENT] = true;
85
+
86
+ // Return placeholder if no Markdown content
87
+ if (!children || !children.trim()) {
88
+ if (placeholder) {
89
+ return (
90
+ <Box
91
+ component={component}
92
+ {...htmlProps}
93
+ {...styleProps}
94
+ {...otherProps}
95
+ sx={{
96
+ opacity: 0.6,
97
+ fontStyle: 'italic',
98
+ ...styleProps.sx
99
+ }}
100
+ >
101
+ {placeholder}
102
+ </Box>
103
+ );
104
+ }
105
+ return null;
106
+ }
107
+
108
+ try {
109
+ // Configure marked
110
+ const options = getMarkedOptions(markedOptions);
111
+
112
+ // Convert Markdown to HTML
113
+ const htmlContent = marked(children, options);
114
+
115
+ // Use provided transform config or default markdown rules
116
+ const transformConfig: TransformConfig = htmlTransformConfig || {
117
+ rules: defaultMarkdownRules,
118
+ sanitize,
119
+ sanitizeOptions
120
+ };
121
+
122
+ // Pass HTML to Html component for transformation
123
+ return (
124
+ <Html
125
+ transformConfig={transformConfig}
126
+ sanitize={sanitize}
127
+ sanitizeOptions={sanitizeOptions}
128
+ component={component}
129
+ {...htmlProps}
130
+ {...styleProps}
131
+ {...otherProps}
132
+ >
133
+ {htmlContent}
134
+ </Html>
135
+ );
136
+
137
+ } catch (error) {
138
+ console.error('Error processing Markdown content:', error);
139
+
140
+ // Fallback handling
141
+ if (process.env.NODE_ENV !== 'production') {
142
+ return (
143
+ <Box
144
+ component={component}
145
+ {...htmlProps}
146
+ {...styleProps}
147
+ {...otherProps}
148
+ sx={{
149
+ p: 2,
150
+ border: '1px solid orange',
151
+ borderRadius: 1,
152
+ backgroundColor: 'rgba(255, 165, 0, 0.1)',
153
+ ...styleProps.sx
154
+ }}
155
+ >
156
+ <strong>Markdown Processing Error:</strong> {error instanceof Error ? error.message : 'Unknown error'}
157
+ <SafeSpan html={children} placeholder="Failed to process Markdown" />
158
+ </Box>
159
+ );
160
+ }
161
+
162
+ // Production fallback - try to use Html component with raw content
163
+ try {
164
+ return (
165
+ <Html
166
+ sanitize={sanitize}
167
+ sanitizeOptions={sanitizeOptions}
168
+ component={component}
169
+ {...htmlProps}
170
+ {...styleProps}
171
+ {...otherProps}
172
+ >
173
+ {children}
174
+ </Html>
175
+ );
176
+ } catch (htmlError) {
177
+ // Last resort fallback
178
+ return (
179
+ <SafeSpan
180
+ html={children}
181
+ placeholder={placeholder || "Content unavailable"}
182
+ {...htmlProps}
183
+ {...styleProps}
184
+ {...otherProps}
185
+ />
186
+ );
187
+ }
188
+ }
189
+ }
190
+
191
+ export default Markdown;