@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,463 @@
1
+ /**
2
+ * Unit tests for HeroBlock component
3
+ *
4
+ * Tests both traditional props usage and data binding functionality
5
+ * with the new schema system.
6
+ */
7
+
8
+ import React from 'react';
9
+ import { render, screen, fireEvent } from '@testing-library/react';
10
+ import '@testing-library/jest-dom';
11
+ import HeroBlock from '../blocks/HeroBlock';
12
+ import type { ButtonProps } from '../buttons/Button';
13
+ import { DataProvider } from '../../contexts/DataContext';
14
+ import { JsonDataProvider } from '@qwickapps/schema';
15
+ import { ThemeProvider, PaletteProvider } from '../../contexts';
16
+
17
+ // Test data for data binding
18
+ const sampleCmsData = {
19
+ 'hero.main': [{
20
+ title: 'Welcome to QwickApps',
21
+ subtitle: 'Build amazing applications faster with our comprehensive framework',
22
+ backgroundImage: '/images/hero-bg.jpg',
23
+ backgroundColor: 'primary',
24
+ actions: [
25
+ { label: 'Get Started', variant: 'primary', buttonSize: 'large', href: '/getting-started' },
26
+ { label: 'View Documentation', variant: 'outlined', buttonSize: 'large', href: '/docs' }
27
+ ],
28
+ textAlign: 'center',
29
+ blockHeight: 'large',
30
+ overlayOpacity: 0.6
31
+ }],
32
+ 'hero.startup': [{
33
+ title: 'Launch Your Startup',
34
+ subtitle: 'From idea to production in days, not months',
35
+ backgroundColor: 'secondary',
36
+ actions: [
37
+ { label: 'Start Building', variant: 'contained', buttonSize: 'large' }
38
+ ],
39
+ textAlign: 'left',
40
+ blockHeight: 'medium'
41
+ }],
42
+ 'hero.minimal': [{
43
+ title: 'Simple & Powerful',
44
+ backgroundColor: 'default',
45
+ textAlign: 'center',
46
+ blockHeight: 'small'
47
+ }],
48
+ 'hero.empty': [{}]
49
+ };
50
+
51
+ // Sample actions for testing
52
+ const sampleActions: ButtonProps[] = [
53
+ { label: 'Primary Action', variant: 'primary', buttonSize: 'large' },
54
+ { label: 'Secondary Action', variant: 'outlined', buttonSize: 'medium', href: '/docs' },
55
+ { label: 'Text Action', variant: 'text', onClick: jest.fn() }
56
+ ];
57
+
58
+ // Wrapper component for tests that need providers
59
+ const TestWrapper: React.FC<{ children: React.ReactNode; dataProvider?: any }> = ({
60
+ children,
61
+ dataProvider
62
+ }) => (
63
+ <ThemeProvider>
64
+ <PaletteProvider>
65
+ {dataProvider ? (
66
+ <DataProvider dataSource={dataProvider}>
67
+ {children}
68
+ </DataProvider>
69
+ ) : (
70
+ children
71
+ )}
72
+ </PaletteProvider>
73
+ </ThemeProvider>
74
+ );
75
+
76
+ describe('HeroBlock', () => {
77
+ describe.skip('Traditional Props Usage', () => {
78
+ it('renders basic hero with title only', () => {
79
+ render(
80
+ <TestWrapper>
81
+ <HeroBlock title="Welcome" />
82
+ </TestWrapper>
83
+ );
84
+
85
+ expect(screen.getByText('Welcome')).toBeInTheDocument();
86
+ const heroSection = document.querySelector('section');
87
+ expect(heroSection).toBeInTheDocument();
88
+ });
89
+
90
+ it('renders hero with title and subtitle', () => {
91
+ render(
92
+ <TestWrapper>
93
+ <HeroBlock
94
+ title="Welcome to QwickApps"
95
+ subtitle="Build amazing applications faster"
96
+ />
97
+ </TestWrapper>
98
+ );
99
+
100
+ expect(screen.getByText('Welcome to QwickApps')).toBeInTheDocument();
101
+ expect(screen.getByText('Build amazing applications faster')).toBeInTheDocument();
102
+ });
103
+
104
+ it('renders hero with actions', () => {
105
+ render(
106
+ <TestWrapper>
107
+ <HeroBlock
108
+ title="Hero with Actions"
109
+ actions={sampleActions}
110
+ />
111
+ </TestWrapper>
112
+ );
113
+
114
+ expect(screen.getByText('Hero with Actions')).toBeInTheDocument();
115
+ expect(screen.getByText('Primary Action')).toBeInTheDocument();
116
+ expect(screen.getByText('Secondary Action')).toBeInTheDocument();
117
+ expect(screen.getByText('Text Action')).toBeInTheDocument();
118
+ });
119
+
120
+ it('handles different background colors', () => {
121
+ const backgroundColors = ['default', 'primary', 'secondary', 'surface'] as const;
122
+
123
+ backgroundColors.forEach(color => {
124
+ const { unmount } = render(
125
+ <TestWrapper>
126
+ <HeroBlock
127
+ title={`Hero with ${color} background`}
128
+ backgroundColor={color}
129
+ />
130
+ </TestWrapper>
131
+ );
132
+
133
+ expect(screen.getByText(`Hero with ${color} background`)).toBeInTheDocument();
134
+
135
+ unmount();
136
+ });
137
+ });
138
+
139
+ it('handles different text alignments', () => {
140
+ const alignments = ['left', 'center', 'right'] as const;
141
+
142
+ alignments.forEach(alignment => {
143
+ const { unmount } = render(
144
+ <TestWrapper>
145
+ <HeroBlock
146
+ title={`${alignment} aligned hero`}
147
+ textAlign={alignment}
148
+ />
149
+ </TestWrapper>
150
+ );
151
+
152
+ expect(screen.getByText(`${alignment} aligned hero`)).toBeInTheDocument();
153
+
154
+ unmount();
155
+ });
156
+ });
157
+
158
+ it('handles different block heights', () => {
159
+ const heights = ['small', 'medium', 'large', 'viewport'] as const;
160
+
161
+ heights.forEach(height => {
162
+ const { unmount } = render(
163
+ <TestWrapper>
164
+ <HeroBlock
165
+ title={`${height} height hero`}
166
+ blockHeight={height}
167
+ />
168
+ </TestWrapper>
169
+ );
170
+
171
+ expect(screen.getByText(`${height} height hero`)).toBeInTheDocument();
172
+
173
+ unmount();
174
+ });
175
+ });
176
+
177
+ it('renders hero with background image', () => {
178
+ render(
179
+ <TestWrapper>
180
+ <HeroBlock
181
+ title="Hero with Background"
182
+ backgroundImage="/images/hero.jpg"
183
+ overlayOpacity={0.8}
184
+ />
185
+ </TestWrapper>
186
+ );
187
+
188
+ expect(screen.getByText('Hero with Background')).toBeInTheDocument();
189
+ });
190
+
191
+ it('renders hero with background gradient', () => {
192
+ render(
193
+ <TestWrapper>
194
+ <HeroBlock
195
+ title="Hero with Gradient"
196
+ backgroundGradient="linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)"
197
+ />
198
+ </TestWrapper>
199
+ );
200
+
201
+ expect(screen.getByText('Hero with Gradient')).toBeInTheDocument();
202
+ });
203
+
204
+ it('handles action click events', () => {
205
+ const handleClick = jest.fn();
206
+ const actionsWithClick: ButtonProps[] = [
207
+ { label: 'Click Me', onClick: handleClick }
208
+ ];
209
+
210
+ render(
211
+ <TestWrapper>
212
+ <HeroBlock
213
+ title="Hero with Click"
214
+ actions={actionsWithClick}
215
+ />
216
+ </TestWrapper>
217
+ );
218
+
219
+ const button = screen.getByText('Click Me');
220
+ fireEvent.click(button);
221
+
222
+ expect(handleClick).toHaveBeenCalledTimes(1);
223
+ });
224
+
225
+ it('supports grid props', () => {
226
+ const { container } = render(
227
+ <TestWrapper>
228
+ <HeroBlock
229
+ title="Hero with Grid"
230
+ span={12}
231
+ xs={12}
232
+ md={8}
233
+ />
234
+ </TestWrapper>
235
+ );
236
+
237
+ const element = container.querySelector('[data-grid-span]');
238
+ expect(element).toHaveAttribute('data-grid-span', '12');
239
+ expect(element).toBeInTheDocument();
240
+ });
241
+
242
+ it('renders with custom CSS classes and styles', () => {
243
+ const { container } = render(
244
+ <TestWrapper>
245
+ <HeroBlock
246
+ title="Custom Hero"
247
+ className="custom-hero"
248
+ sx={{ backgroundColor: 'red' }}
249
+ />
250
+ </TestWrapper>
251
+ );
252
+
253
+ expect(screen.getByText('Custom Hero')).toBeInTheDocument();
254
+ });
255
+
256
+ it('renders with additional children content', () => {
257
+ render(
258
+ <TestWrapper>
259
+ <HeroBlock title="Hero with Children">
260
+ <div>Additional content</div>
261
+ <p>More details here</p>
262
+ </HeroBlock>
263
+ </TestWrapper>
264
+ );
265
+
266
+ expect(screen.getByText('Hero with Children')).toBeInTheDocument();
267
+ expect(screen.getByText('Additional content')).toBeInTheDocument();
268
+ expect(screen.getByText('More details here')).toBeInTheDocument();
269
+ });
270
+ });
271
+
272
+ describe.skip('Data Binding Usage', () => {
273
+ let dataProvider: JsonDataProvider;
274
+
275
+ beforeEach(() => {
276
+ dataProvider = new JsonDataProvider({ data: sampleCmsData });
277
+ });
278
+
279
+ it('renders with dataSource prop (main hero)', async () => {
280
+ render(
281
+ <TestWrapper dataProvider={dataProvider}>
282
+ <HeroBlock dataSource="hero.main" />
283
+ </TestWrapper>
284
+ );
285
+
286
+ await screen.findByText('Welcome to QwickApps');
287
+ expect(screen.getByText('Build amazing applications faster with our comprehensive framework')).toBeInTheDocument();
288
+ expect(screen.getByText('Get Started')).toBeInTheDocument();
289
+ expect(screen.getByText('View Documentation')).toBeInTheDocument();
290
+ });
291
+
292
+ it('renders with dataSource prop (startup hero)', async () => {
293
+ render(
294
+ <TestWrapper dataProvider={dataProvider}>
295
+ <HeroBlock dataSource="hero.startup" />
296
+ </TestWrapper>
297
+ );
298
+
299
+ await screen.findByText('Launch Your Startup');
300
+ expect(screen.getByText('From idea to production in days, not months')).toBeInTheDocument();
301
+ expect(screen.getByText('Start Building')).toBeInTheDocument();
302
+ });
303
+
304
+ it('shows loading state while data is loading', () => {
305
+ render(
306
+ <TestWrapper dataProvider={dataProvider}>
307
+ <HeroBlock dataSource="hero.nonexistent" />
308
+ </TestWrapper>
309
+ );
310
+
311
+ expect(screen.getByText('Loading Hero...')).toBeInTheDocument();
312
+ });
313
+
314
+ it('uses fallback props when dataSource has no content', async () => {
315
+ render(
316
+ <TestWrapper dataProvider={dataProvider}>
317
+ <HeroBlock
318
+ dataSource="nonexistent.hero"
319
+ title="Fallback Title"
320
+ subtitle="Fallback Subtitle"
321
+ />
322
+ </TestWrapper>
323
+ );
324
+
325
+ await screen.findByText('Fallback Title');
326
+ expect(screen.getByText('Fallback Subtitle')).toBeInTheDocument();
327
+ });
328
+
329
+ it('handles minimal hero from data', async () => {
330
+ render(
331
+ <TestWrapper dataProvider={dataProvider}>
332
+ <HeroBlock dataSource="hero.minimal" />
333
+ </TestWrapper>
334
+ );
335
+
336
+ await screen.findByText('Simple & Powerful');
337
+ });
338
+
339
+ it('works with custom binding options', async () => {
340
+ render(
341
+ <TestWrapper dataProvider={dataProvider}>
342
+ <HeroBlock
343
+ dataSource="hero.main"
344
+ bindingOptions={{ cache: false, strict: true }}
345
+ />
346
+ </TestWrapper>
347
+ );
348
+
349
+ await screen.findByText('Welcome to QwickApps');
350
+ });
351
+
352
+ it('handles empty data from CMS', async () => {
353
+ render(
354
+ <TestWrapper dataProvider={dataProvider}>
355
+ <HeroBlock
356
+ dataSource="hero.empty"
357
+ title="Fallback for Empty Data"
358
+ />
359
+ </TestWrapper>
360
+ );
361
+
362
+ await screen.findByText('Fallback for Empty Data');
363
+ });
364
+ });
365
+
366
+ describe.skip('Edge Cases', () => {
367
+ it('handles hero without title gracefully', () => {
368
+ render(
369
+ <TestWrapper>
370
+ <HeroBlock
371
+ subtitle="Subtitle only hero"
372
+ backgroundColor="default"
373
+ />
374
+ </TestWrapper>
375
+ );
376
+
377
+ expect(screen.getByText('Subtitle only hero')).toBeInTheDocument();
378
+ });
379
+
380
+ it('handles empty actions array', () => {
381
+ render(
382
+ <TestWrapper>
383
+ <HeroBlock
384
+ title="Hero without actions"
385
+ actions={[]}
386
+ />
387
+ </TestWrapper>
388
+ );
389
+
390
+ expect(screen.getByText('Hero without actions')).toBeInTheDocument();
391
+ });
392
+
393
+ it('handles very long title and subtitle', () => {
394
+ const longTitle = 'Very '.repeat(20) + 'Long Hero Title';
395
+ const longSubtitle = 'Very '.repeat(30) + 'Long Hero Subtitle';
396
+
397
+ render(
398
+ <TestWrapper>
399
+ <HeroBlock
400
+ title={longTitle}
401
+ subtitle={longSubtitle}
402
+ />
403
+ </TestWrapper>
404
+ );
405
+
406
+ expect(screen.getByText(longTitle)).toBeInTheDocument();
407
+ expect(screen.getByText(longSubtitle)).toBeInTheDocument();
408
+ });
409
+
410
+ it('handles special characters in content', () => {
411
+ render(
412
+ <TestWrapper>
413
+ <HeroBlock
414
+ title={'Special: &<>"\' Characters'}
415
+ subtitle={'Subtitle with & < > " \' chars'}
416
+ />
417
+ </TestWrapper>
418
+ );
419
+
420
+ expect(screen.getByText(/Special:.*Characters/)).toBeInTheDocument();
421
+ expect(screen.getByText(/Subtitle with.*chars/)).toBeInTheDocument();
422
+ });
423
+
424
+ it('handles extreme overlay opacity values', () => {
425
+ render(
426
+ <TestWrapper>
427
+ <HeroBlock
428
+ title="Extreme Overlay"
429
+ backgroundImage="/test.jpg"
430
+ overlayOpacity={0}
431
+ />
432
+ </TestWrapper>
433
+ );
434
+
435
+ expect(screen.getByText('Extreme Overlay')).toBeInTheDocument();
436
+ });
437
+
438
+ it('handles invalid blockHeight values by using default', () => {
439
+ render(
440
+ <TestWrapper>
441
+ <HeroBlock
442
+ title="Default Height Hero"
443
+ // @ts-expect-error Testing invalid value
444
+ blockHeight="invalid"
445
+ />
446
+ </TestWrapper>
447
+ );
448
+
449
+ expect(screen.getByText('Default Height Hero')).toBeInTheDocument();
450
+ });
451
+
452
+ it('handles hero without any props', () => {
453
+ render(
454
+ <TestWrapper>
455
+ <HeroBlock />
456
+ </TestWrapper>
457
+ );
458
+
459
+ const heroSection = document.querySelector('section');
460
+ expect(heroSection).toBeInTheDocument();
461
+ });
462
+ });
463
+ });
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Html Component Tests
3
+ */
4
+
5
+ import { render, screen } from '@testing-library/react';
6
+ import { Html } from '../Html';
7
+
8
+ describe('Html Component', () => {
9
+ // Test empty content handling
10
+ describe('Empty Content', () => {
11
+ it('renders nothing when children is empty', () => {
12
+ const { container } = render(<Html>{''}</Html>);
13
+ expect(container.firstChild).toBeNull();
14
+ });
15
+
16
+ it('renders placeholder when children is empty and placeholder is provided', () => {
17
+ render(<Html placeholder="No content available">{''}</Html>);
18
+ expect(screen.getByText('No content available')).toBeInTheDocument();
19
+ });
20
+
21
+ it('renders placeholder with proper styling', () => {
22
+ render(<Html placeholder="Loading content...">{''}</Html>);
23
+ const placeholder = screen.getByText('Loading content...');
24
+ expect(placeholder).toBeInTheDocument();
25
+ });
26
+ });
27
+
28
+ // Test basic HTML rendering
29
+ describe('Basic HTML Rendering', () => {
30
+ it('renders simple HTML content', () => {
31
+ render(<Html>{'<p>Hello World</p>'}</Html>);
32
+ expect(screen.getByText('Hello World')).toBeInTheDocument();
33
+ });
34
+
35
+ it('renders multiple paragraphs', () => {
36
+ const html = '<p>First paragraph</p><p>Second paragraph</p>';
37
+ render(<Html>{html}</Html>);
38
+ expect(screen.getByText('First paragraph')).toBeInTheDocument();
39
+ expect(screen.getByText('Second paragraph')).toBeInTheDocument();
40
+ });
41
+
42
+ it('handles headers correctly', () => {
43
+ const html = '<h1>Main Title</h1><h2>Subtitle</h2>';
44
+ render(<Html>{html}</Html>);
45
+ expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent('Main Title');
46
+ expect(screen.getByRole('heading', { level: 2 })).toHaveTextContent('Subtitle');
47
+ });
48
+ });
49
+
50
+ // Test code transformation
51
+ describe('Code Block Transformation', () => {
52
+ it('transforms pre+code blocks to Code component', () => {
53
+ const html = '<pre><code class="language-javascript">console.log("Hello");</code></pre>';
54
+ render(<Html>{html}</Html>);
55
+ expect(screen.getByText('console.log("Hello");')).toBeInTheDocument();
56
+ });
57
+
58
+ it('handles code blocks without language class', () => {
59
+ const html = '<pre><code>plain text code</code></pre>';
60
+ render(<Html>{html}</Html>);
61
+ expect(screen.getByText('plain text code')).toBeInTheDocument();
62
+ });
63
+
64
+ it('transforms standalone complex code blocks', () => {
65
+ const html = '<code>line1\nline2</code>';
66
+ render(<Html>{html}</Html>);
67
+ expect(screen.getByText(/line1/)).toBeInTheDocument();
68
+ expect(screen.getByText(/line2/)).toBeInTheDocument();
69
+ });
70
+
71
+ it('preserves inline code elements', () => {
72
+ const html = '<p>This has <code>inline code</code> in it.</p>';
73
+ render(<Html>{html}</Html>);
74
+ expect(screen.getByText('inline code')).toBeInTheDocument();
75
+ // SafeSpan wraps the p tag content, so we check the combination
76
+ const paragraph = screen.getByText('inline code').closest('p');
77
+ expect(paragraph).toBeInTheDocument();
78
+ });
79
+ });
80
+
81
+ // Test section transformation
82
+ describe('Section Transformation', () => {
83
+ it('transforms blog sections to Section component', () => {
84
+ const html = '<section class="blog-section" data-padding="large"><h2>Section Title</h2><p>Content</p></section>';
85
+ render(<Html>{html}</Html>);
86
+ expect(screen.getByText('Section Title')).toBeInTheDocument();
87
+ expect(screen.getByText('Content')).toBeInTheDocument();
88
+ });
89
+
90
+ it('handles sections without titles', () => {
91
+ const html = '<section class="blog-section"><p>Just content</p></section>';
92
+ render(<Html>{html}</Html>);
93
+ expect(screen.getByText('Just content')).toBeInTheDocument();
94
+ });
95
+ });
96
+
97
+ // Test button transformation
98
+ describe('Button Transformation', () => {
99
+ it('transforms button elements to Button components', () => {
100
+ const html = '<button data-variant="contained">Click Me</button>';
101
+ render(<Html>{html}</Html>);
102
+ expect(screen.getByRole('button')).toHaveTextContent('Click Me');
103
+ });
104
+
105
+ it('handles disabled buttons', () => {
106
+ const html = '<button disabled>Disabled Button</button>';
107
+ render(<Html>{html}</Html>);
108
+ expect(screen.getByRole('button')).toBeDisabled();
109
+ });
110
+ });
111
+
112
+ // Test header stripping
113
+ describe('Header Stripping', () => {
114
+ it('strips headers when stripHeaders is true', () => {
115
+ const html = '<header class="blog-header"><h1>Page Title</h1></header><p>Content</p>';
116
+ render(<Html stripHeaders>{html}</Html>);
117
+ expect(screen.queryByText('Page Title')).not.toBeInTheDocument();
118
+ expect(screen.getByText('Content')).toBeInTheDocument();
119
+ });
120
+
121
+ it('preserves headers when stripHeaders is false', () => {
122
+ const html = '<header class="blog-header"><h1>Page Title</h1></header><p>Content</p>';
123
+ render(<Html stripHeaders={false}>{html}</Html>);
124
+ expect(screen.getByText('Page Title')).toBeInTheDocument();
125
+ expect(screen.getByText('Content')).toBeInTheDocument();
126
+ });
127
+ });
128
+
129
+ // Test error handling
130
+ describe('Error Handling', () => {
131
+ it('handles malformed HTML gracefully', () => {
132
+ const html = '<p>Unclosed paragraph<div>Mixed content</p></div>';
133
+ const { container } = render(<Html>{html}</Html>);
134
+ expect(container.firstChild).not.toBeNull();
135
+ });
136
+
137
+ it('sanitizes dangerous content by default', () => {
138
+ const html = '<script>alert("hack")</script><p>Safe content</p>';
139
+ render(<Html>{html}</Html>);
140
+ expect(screen.getByText('Safe content')).toBeInTheDocument();
141
+ expect(screen.queryByText('alert("hack")')).not.toBeInTheDocument();
142
+ });
143
+ });
144
+
145
+ // Test custom props
146
+ describe('Custom Props', () => {
147
+ it('accepts custom component prop', () => {
148
+ const { container } = render(<Html component="article">{'<p>Content</p>'}</Html>);
149
+ expect(container.firstChild?.nodeName).toBe('ARTICLE');
150
+ });
151
+
152
+ it('accepts custom className', () => {
153
+ const { container } = render(<Html className="custom-html">{'<p>Content</p>'}</Html>);
154
+ expect(container.firstChild).toHaveClass('custom-html');
155
+ });
156
+
157
+ it('accepts custom styles', () => {
158
+ const { container } = render(
159
+ <Html sx={{ backgroundColor: 'red' }}>{'<p>Content</p>'}</Html>
160
+ );
161
+ expect(container.firstChild).toHaveClass('MuiBox-root');
162
+ });
163
+ });
164
+
165
+ // Test sanitization options
166
+ describe('Sanitization', () => {
167
+ it('can disable sanitization', () => {
168
+ // Note: This test verifies the prop is accepted; actual script execution is browser-dependent
169
+ const html = '<p onmouseover="alert(\'test\')">Hover me</p>';
170
+ render(<Html sanitize={false}>{html}</Html>);
171
+ expect(screen.getByText('Hover me')).toBeInTheDocument();
172
+ });
173
+ });
174
+ });