@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,377 @@
1
+ /**
2
+ * Unit tests for ProductCard 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, waitFor } from '@testing-library/react';
10
+ import '@testing-library/jest-dom';
11
+ import { ProductCard } from '../blocks/ProductCard';
12
+ import type { Product } from '../blocks/ProductCard';
13
+ import { DataProvider } from '../../contexts/DataContext';
14
+ import { JsonDataProvider } from '@qwickapps/schema';
15
+ import { ThemeProvider, PaletteProvider } from '../../contexts';
16
+
17
+ // Sample product data
18
+ const sampleProduct: Product = {
19
+ id: 'test-product',
20
+ name: 'Test Product',
21
+ category: 'Testing',
22
+ description: 'A comprehensive testing framework for modern applications',
23
+ shortDescription: 'Modern testing framework',
24
+ features: ['Easy setup', 'Fast execution', 'Comprehensive reporting'],
25
+ technologies: ['React', 'TypeScript', 'Jest'],
26
+ status: 'launched',
27
+ image: 'https://example.com/test-product.jpg',
28
+ url: 'https://example.com/product'
29
+ };
30
+
31
+ const sampleProductBeta: Product = {
32
+ id: 'beta-product',
33
+ name: 'Beta Product',
34
+ category: 'Development',
35
+ description: 'Beta version of our next-generation platform',
36
+ features: ['Cutting edge features', 'Early access', 'Community feedback'],
37
+ technologies: ['Next.js', 'GraphQL'],
38
+ status: 'beta'
39
+ };
40
+
41
+ const sampleProductComingSoon: Product = {
42
+ id: 'coming-soon-product',
43
+ name: 'Future Product',
44
+ category: 'Innovation',
45
+ description: 'Revolutionary new product coming soon',
46
+ features: ['AI-powered', 'Cloud-native', 'Scalable'],
47
+ technologies: ['AI/ML', 'Kubernetes'],
48
+ status: 'coming-soon'
49
+ };
50
+
51
+ // Test data for data binding
52
+ const sampleCmsData = {
53
+ 'products.main-product': [{
54
+ product: sampleProduct,
55
+ variant: 'detailed',
56
+ showImage: true,
57
+ showTechnologies: true
58
+ }],
59
+ 'products.compact-list': [{
60
+ product: sampleProductBeta,
61
+ variant: 'compact',
62
+ showImage: false,
63
+ maxFeaturesCompact: 2
64
+ }],
65
+ 'products.coming-soon': [{
66
+ product: sampleProductComingSoon,
67
+ variant: 'detailed'
68
+ }]
69
+ };
70
+
71
+ // Mock window.open for Jest
72
+ Object.defineProperty(window, 'open', {
73
+ writable: true,
74
+ value: jest.fn()
75
+ });
76
+
77
+ // Wrapper component for tests that need providers
78
+ const TestWrapper: React.FC<{ children: React.ReactNode; dataProvider?: any }> = ({
79
+ children,
80
+ dataProvider
81
+ }) => (
82
+ <ThemeProvider>
83
+ <PaletteProvider>
84
+ {dataProvider ? (
85
+ <DataProvider dataSource={dataProvider}>
86
+ {children}
87
+ </DataProvider>
88
+ ) : (
89
+ children
90
+ )}
91
+ </PaletteProvider>
92
+ </ThemeProvider>
93
+ );
94
+
95
+ describe.skip('ProductCard', () => {
96
+ describe('Traditional Props Usage', () => {
97
+ it('renders launched product correctly', () => {
98
+ render(
99
+ <TestWrapper>
100
+ <ProductCard product={sampleProduct} />
101
+ </TestWrapper>
102
+ );
103
+
104
+ expect(screen.getByText('Test Product')).toBeInTheDocument();
105
+ expect(screen.getByText('Testing')).toBeInTheDocument();
106
+ expect(screen.getByText('Modern testing framework')).toBeInTheDocument();
107
+ expect(screen.getByText('launched')).toBeInTheDocument();
108
+ expect(screen.getByText('Launch App')).toBeInTheDocument();
109
+ });
110
+
111
+ it('renders beta product with correct status', () => {
112
+ render(
113
+ <TestWrapper>
114
+ <ProductCard product={sampleProductBeta} />
115
+ </TestWrapper>
116
+ );
117
+
118
+ expect(screen.getByText('Beta Product')).toBeInTheDocument();
119
+ expect(screen.getByText('beta')).toBeInTheDocument();
120
+ expect(screen.getByText('Try Beta')).toBeInTheDocument();
121
+ });
122
+
123
+ it('renders coming soon product with disabled button', () => {
124
+ render(
125
+ <TestWrapper>
126
+ <ProductCard product={sampleProductComingSoon} />
127
+ </TestWrapper>
128
+ );
129
+
130
+ expect(screen.getByText('Future Product')).toBeInTheDocument();
131
+ expect(screen.getByText('coming soon')).toBeInTheDocument();
132
+
133
+ const comingSoonButton = screen.getByText('Coming Soon');
134
+ expect(comingSoonButton).toBeDisabled();
135
+ });
136
+
137
+ it('renders detailed variant correctly', () => {
138
+ render(
139
+ <TestWrapper>
140
+ <ProductCard product={sampleProduct} variant="detailed" />
141
+ </TestWrapper>
142
+ );
143
+
144
+ // Should show full description in detailed mode
145
+ expect(screen.getByText('A comprehensive testing framework for modern applications')).toBeInTheDocument();
146
+
147
+ // Should show technologies in detailed mode
148
+ expect(screen.getByText('Technologies:')).toBeInTheDocument();
149
+ expect(screen.getByText('React')).toBeInTheDocument();
150
+ expect(screen.getByText('TypeScript')).toBeInTheDocument();
151
+ });
152
+
153
+ it('renders compact variant correctly', () => {
154
+ render(
155
+ <TestWrapper>
156
+ <ProductCard product={sampleProduct} variant="compact" maxFeaturesCompact={2} />
157
+ </TestWrapper>
158
+ );
159
+
160
+ // Should show short description in compact mode
161
+ expect(screen.getByText('Modern testing framework')).toBeInTheDocument();
162
+
163
+ // Should limit features in compact mode
164
+ expect(screen.getByText('Easy setup')).toBeInTheDocument();
165
+ expect(screen.getByText('Fast execution')).toBeInTheDocument();
166
+ expect(screen.getByText('+1 more features')).toBeInTheDocument();
167
+
168
+ // Should not show technologies section in compact mode
169
+ expect(screen.queryByText('Technologies:')).not.toBeInTheDocument();
170
+ });
171
+
172
+ it('handles click events correctly', () => {
173
+ const mockClick = jest.fn();
174
+ render(
175
+ <TestWrapper>
176
+ <ProductCard product={sampleProduct} onClick={mockClick} variant="compact" />
177
+ </TestWrapper>
178
+ );
179
+
180
+ const card = screen.getByText('Test Product').closest('.product-card');
181
+ if (card) {
182
+ fireEvent.click(card);
183
+ expect(mockClick).toHaveBeenCalled();
184
+ }
185
+ });
186
+
187
+ it('renders without image when showImage is false', () => {
188
+ render(
189
+ <TestWrapper>
190
+ <ProductCard product={sampleProduct} showImage={false} />
191
+ </TestWrapper>
192
+ );
193
+
194
+ expect(screen.queryByAltText('Test Product')).not.toBeInTheDocument();
195
+ });
196
+
197
+ it('shows empty state when no product is provided', () => {
198
+ render(
199
+ <TestWrapper>
200
+ <ProductCard />
201
+ </TestWrapper>
202
+ );
203
+
204
+ expect(screen.getByText('No Product Available')).toBeInTheDocument();
205
+ expect(screen.getByText('Empty')).toBeInTheDocument();
206
+ expect(screen.getByText('No product data found in the specified data source')).toBeInTheDocument();
207
+ });
208
+ });
209
+
210
+ describe.skip('Data Binding Usage', () => {
211
+ let dataProvider: JsonDataProvider;
212
+
213
+ beforeEach(() => {
214
+ dataProvider = new JsonDataProvider({ data: sampleCmsData });
215
+ });
216
+
217
+ it('renders with dataSource prop (detailed variant)', async () => {
218
+ render(
219
+ <TestWrapper dataProvider={dataProvider}>
220
+ <ProductCard dataSource="products.main-product" />
221
+ </TestWrapper>
222
+ );
223
+
224
+ await waitFor(() => {
225
+ expect(screen.getByText('Test Product')).toBeInTheDocument();
226
+ });
227
+
228
+ expect(screen.getByText('Testing')).toBeInTheDocument();
229
+ expect(screen.getByText('A comprehensive testing framework for modern applications')).toBeInTheDocument();
230
+ expect(screen.getByText('Technologies:')).toBeInTheDocument();
231
+ });
232
+
233
+ it('renders with dataSource prop (compact variant)', async () => {
234
+ render(
235
+ <TestWrapper dataProvider={dataProvider}>
236
+ <ProductCard dataSource="products.compact-list" />
237
+ </TestWrapper>
238
+ );
239
+
240
+ await waitFor(() => {
241
+ expect(screen.getByText('Beta Product')).toBeInTheDocument();
242
+ });
243
+
244
+ expect(screen.getByText('Try Beta')).toBeInTheDocument();
245
+ // Should limit features to 2 in compact mode
246
+ expect(screen.getByText('Cutting edge features')).toBeInTheDocument();
247
+ expect(screen.getByText('Early access')).toBeInTheDocument();
248
+ expect(screen.getByText('+1 more features')).toBeInTheDocument();
249
+ });
250
+
251
+ it('shows loading state while data is loading', () => {
252
+ render(
253
+ <TestWrapper dataProvider={dataProvider}>
254
+ <ProductCard dataSource="products.nonexistent" />
255
+ </TestWrapper>
256
+ );
257
+
258
+ expect(screen.getByText('Loading Product...')).toBeInTheDocument();
259
+ expect(screen.getByText('Loading')).toBeInTheDocument();
260
+ });
261
+
262
+ it('includes data attributes when using dataSource', async () => {
263
+ const { container } = render(
264
+ <TestWrapper dataProvider={dataProvider}>
265
+ <ProductCard dataSource="products.main-product" />
266
+ </TestWrapper>
267
+ );
268
+
269
+ await waitFor(() => {
270
+ const card = container.querySelector('[data-component="ProductCard"]');
271
+ expect(card).toBeInTheDocument();
272
+ expect(card).toHaveAttribute('data-data-source', 'products.main-product');
273
+ expect(card).toHaveAttribute('data-variant', 'detailed');
274
+ });
275
+ });
276
+
277
+ it('uses fallback props when dataSource has no content', async () => {
278
+ render(
279
+ <TestWrapper dataProvider={dataProvider}>
280
+ <ProductCard
281
+ dataSource="products.nonexistent-key"
282
+ product={sampleProduct}
283
+ variant="compact"
284
+ />
285
+ </TestWrapper>
286
+ );
287
+
288
+ // Should eventually show the fallback product
289
+ await waitFor(() => {
290
+ expect(screen.getByText('Test Product')).toBeInTheDocument();
291
+ }, { timeout: 2000 });
292
+ });
293
+
294
+ it('handles different product statuses from data', async () => {
295
+ render(
296
+ <TestWrapper dataProvider={dataProvider}>
297
+ <ProductCard dataSource="products.coming-soon" />
298
+ </TestWrapper>
299
+ );
300
+
301
+ await waitFor(() => {
302
+ expect(screen.getByText('Future Product')).toBeInTheDocument();
303
+ });
304
+
305
+ expect(screen.getByText('coming soon')).toBeInTheDocument();
306
+
307
+ const comingSoonButton = screen.getByText('Coming Soon');
308
+ expect(comingSoonButton).toBeDisabled();
309
+ });
310
+
311
+ it('works with custom binding options', async () => {
312
+ render(
313
+ <TestWrapper dataProvider={dataProvider}>
314
+ <ProductCard
315
+ dataSource="products.main-product"
316
+ bindingOptions={{ cache: false, strict: true }}
317
+ />
318
+ </TestWrapper>
319
+ );
320
+
321
+ await waitFor(() => {
322
+ expect(screen.getByText('Test Product')).toBeInTheDocument();
323
+ });
324
+ });
325
+ });
326
+
327
+ describe('Edge Cases', () => {
328
+ it('handles missing product image gracefully', () => {
329
+ const productWithoutImage = { ...sampleProduct, image: undefined };
330
+
331
+ render(
332
+ <TestWrapper>
333
+ <ProductCard product={productWithoutImage} />
334
+ </TestWrapper>
335
+ );
336
+
337
+ expect(screen.queryByAltText('Test Product')).not.toBeInTheDocument();
338
+ expect(screen.getByText('Test Product')).toBeInTheDocument();
339
+ });
340
+
341
+ it('handles empty features array', () => {
342
+ const productWithNoFeatures = { ...sampleProduct, features: [] };
343
+
344
+ render(
345
+ <TestWrapper>
346
+ <ProductCard product={productWithNoFeatures} />
347
+ </TestWrapper>
348
+ );
349
+
350
+ expect(screen.getByText('Key Features:')).toBeInTheDocument();
351
+ // Should not show any feature items
352
+ expect(screen.queryByText('Easy setup')).not.toBeInTheDocument();
353
+ });
354
+
355
+ it('handles custom actions', () => {
356
+ const customActions = [
357
+ {
358
+ id: 'custom',
359
+ label: 'Custom Action',
360
+ onClick: jest.fn()
361
+ }
362
+ ];
363
+
364
+ render(
365
+ <TestWrapper>
366
+ <ProductCard product={sampleProduct} actions={customActions} />
367
+ </TestWrapper>
368
+ );
369
+
370
+ const customButton = screen.getByText('Custom Action');
371
+ expect(customButton).toBeInTheDocument();
372
+
373
+ fireEvent.click(customButton);
374
+ expect(customActions[0].onClick).toHaveBeenCalled();
375
+ });
376
+ });
377
+ });
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Integration tests for SafeSpan with data binding functionality
3
+ *
4
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
5
+ */
6
+
7
+ import React from 'react';
8
+ import { render, waitFor } from '@testing-library/react';
9
+ import SafeSpan from '../SafeSpan';
10
+ import { DataProvider } from '../../contexts/DataContext';
11
+ import { JsonDataProvider } from '@qwickapps/schema';
12
+
13
+ describe.skip('SafeSpan Integration (Traditional + Data Binding)', () => {
14
+ const testData = {
15
+ 'company.description': {
16
+ html: '<p>QwickApps helps you <strong>build apps faster</strong> with our comprehensive framework.</p>',
17
+ placeholder: 'Loading company description...'
18
+ },
19
+ 'empty.content': {}
20
+ };
21
+
22
+ const dataProvider = new JsonDataProvider({ data: testData });
23
+
24
+ it('should work as traditional SafeSpan without dataSource', () => {
25
+ const { container } = render(
26
+ <SafeSpan
27
+ html="<p>Traditional <strong>SafeSpan</strong> usage</p>"
28
+ placeholder="Traditional placeholder"
29
+ />
30
+ );
31
+
32
+ expect(container.innerHTML).toContain('Traditional <strong>SafeSpan</strong> usage');
33
+ });
34
+
35
+ it('should work with dataSource prop (data binding)', async () => {
36
+ const { container } = render(
37
+ <DataProvider dataSource={{ dataProvider }}>
38
+ <SafeSpan dataSource="company.description" />
39
+ </DataProvider>
40
+ );
41
+
42
+ await waitFor(() => {
43
+ expect(container.innerHTML).toContain('QwickApps helps you <strong>build apps faster</strong>');
44
+ });
45
+ });
46
+
47
+ it('should use fallback props when dataSource has no content', async () => {
48
+ const { container } = render(
49
+ <DataProvider dataSource={{ dataProvider }}>
50
+ <SafeSpan
51
+ dataSource="empty.content"
52
+ html="<p>Fallback HTML content</p>"
53
+ placeholder="Fallback placeholder"
54
+ />
55
+ </DataProvider>
56
+ );
57
+
58
+ await waitFor(() => {
59
+ expect(container.innerHTML).toContain('Fallback HTML content');
60
+ });
61
+ });
62
+
63
+ it('should sanitize malicious HTML content', () => {
64
+ const { container } = render(
65
+ <SafeSpan html="<script>alert('xss')</script><p>Safe content</p>" />
66
+ );
67
+
68
+ // Script tag should be removed, safe content should remain
69
+ expect(container.innerHTML).not.toContain('<script>');
70
+ expect(container.innerHTML).not.toContain("alert('xss')");
71
+ expect(container.innerHTML).toContain('Safe content');
72
+ });
73
+
74
+ it('should include data attributes when using dataSource', async () => {
75
+ const { container } = render(
76
+ <DataProvider dataSource={{ dataProvider }}>
77
+ <SafeSpan dataSource="company.description" />
78
+ </DataProvider>
79
+ );
80
+
81
+ await waitFor(() => {
82
+ const span = container.querySelector('span');
83
+ expect(span).toHaveAttribute('data-component', 'SafeSpan');
84
+ expect(span).toHaveAttribute('data-data-source', 'company.description');
85
+ });
86
+ });
87
+
88
+ it('should work with base props like grid attributes', () => {
89
+ const { container } = render(
90
+ <SafeSpan
91
+ html="<p>Test content</p>"
92
+ span={6}
93
+ xs={12}
94
+ md={8}
95
+ />
96
+ );
97
+
98
+ const span = container.querySelector('span');
99
+ expect(span).toHaveAttribute('data-grid-span', '6');
100
+ expect(span).toHaveAttribute('data-grid-xs', '12');
101
+ expect(span).toHaveAttribute('data-grid-md', '8');
102
+ });
103
+
104
+ it('should handle custom binding options', async () => {
105
+ const { container } = render(
106
+ <DataProvider dataSource={{ dataProvider }}>
107
+ <SafeSpan
108
+ dataSource="nonexistent.data"
109
+ bindingOptions={{
110
+ fallback: {
111
+ html: '<p>Custom fallback content</p>',
112
+ placeholder: 'Custom fallback placeholder'
113
+ }
114
+ }}
115
+ />
116
+ </DataProvider>
117
+ );
118
+
119
+ await waitFor(() => {
120
+ expect(container.innerHTML).toContain('Custom fallback content');
121
+ });
122
+ });
123
+ });
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Simple unit tests for SafeSpan component
3
+ * Focuses on core functionality without complex data binding scenarios
4
+ */
5
+
6
+ import React from 'react';
7
+ import { render, screen } from '@testing-library/react';
8
+ import '@testing-library/jest-dom';
9
+ import SafeSpan from '../SafeSpan';
10
+
11
+ describe('SafeSpan Simple Tests', () => {
12
+
13
+ describe('Basic Functionality', () => {
14
+
15
+ it('renders simple HTML content', () => {
16
+ render(<SafeSpan html="<p>Hello World</p>" />);
17
+ expect(screen.getByText('Hello World')).toBeInTheDocument();
18
+ });
19
+
20
+ it('renders placeholder when html is empty', () => {
21
+ render(<SafeSpan html="" placeholder="Loading..." />);
22
+ expect(screen.getByText('Loading...')).toBeInTheDocument();
23
+ });
24
+
25
+ it('returns null when both html and placeholder are empty', () => {
26
+ const { container } = render(<SafeSpan html="" />);
27
+ expect(container.firstChild).toBeNull();
28
+ });
29
+
30
+ it('sanitizes script tags', () => {
31
+ render(<SafeSpan html="<p>Safe</p><script>alert('xss')</script>" />);
32
+ expect(screen.getByText('Safe')).toBeInTheDocument();
33
+ expect(document.querySelector('script')).toBeNull();
34
+ });
35
+
36
+ it('preserves safe formatting', () => {
37
+ render(<SafeSpan html="<p><strong>Bold</strong> and <em>italic</em> text</p>" />);
38
+ expect(screen.getByText('Bold')).toBeInTheDocument();
39
+ expect(screen.getByText('italic')).toBeInTheDocument();
40
+
41
+ const boldElement = screen.getByText('Bold');
42
+ const italicElement = screen.getByText('italic');
43
+
44
+ expect(boldElement.tagName).toBe('STRONG');
45
+ expect(italicElement.tagName).toBe('EM');
46
+ });
47
+
48
+ it('removes dangerous event handlers', () => {
49
+ const { container } = render(
50
+ <SafeSpan html='<p onclick="alert(1)">Click me</p>' />
51
+ );
52
+
53
+ const paragraph = container.querySelector('p');
54
+ expect(paragraph).toBeInTheDocument();
55
+ expect(paragraph).not.toHaveAttribute('onclick');
56
+ });
57
+
58
+ it('works without data binding when no dataSource provided', () => {
59
+ render(<SafeSpan html="<p>Traditional usage</p>" />);
60
+ expect(screen.getByText('Traditional usage')).toBeInTheDocument();
61
+ });
62
+
63
+ });
64
+
65
+ });