@qwickapps/react-framework 1.3.5 → 1.4.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 (320) hide show
  1. package/README.md +1681 -2
  2. package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts +66 -0
  3. package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts.map +1 -0
  4. package/dist/components/ErrorBoundary.d.ts +7 -0
  5. package/dist/components/ErrorBoundary.d.ts.map +1 -1
  6. package/dist/components/Html.d.ts +28 -18
  7. package/dist/components/Html.d.ts.map +1 -1
  8. package/dist/components/Logo.d.ts +12 -35
  9. package/dist/components/Logo.d.ts.map +1 -1
  10. package/dist/components/Markdown.d.ts +18 -13
  11. package/dist/components/Markdown.d.ts.map +1 -1
  12. package/dist/components/QwickApp.d.ts +16 -3
  13. package/dist/components/QwickApp.d.ts.map +1 -1
  14. package/dist/components/QwickIcon.d.ts +23 -0
  15. package/dist/components/QwickIcon.d.ts.map +1 -0
  16. package/dist/components/SafeSpan.d.ts +12 -5
  17. package/dist/components/SafeSpan.d.ts.map +1 -1
  18. package/dist/components/Scaffold.d.ts.map +1 -1
  19. package/dist/components/base/ModelView.d.ts +101 -0
  20. package/dist/components/base/ModelView.d.ts.map +1 -0
  21. package/dist/components/base/index.d.ts +11 -0
  22. package/dist/components/base/index.d.ts.map +1 -0
  23. package/dist/components/blocks/Article.d.ts +12 -2
  24. package/dist/components/blocks/Article.d.ts.map +1 -1
  25. package/dist/components/blocks/Code.d.ts +13 -2
  26. package/dist/components/blocks/Code.d.ts.map +1 -1
  27. package/dist/components/blocks/CoverImageHeader.d.ts.map +1 -1
  28. package/dist/components/blocks/FeatureCard.d.ts.map +1 -1
  29. package/dist/components/blocks/FeatureGrid.d.ts.map +1 -1
  30. package/dist/components/blocks/Footer.d.ts.map +1 -1
  31. package/dist/components/blocks/HeroBlock.d.ts +27 -13
  32. package/dist/components/blocks/HeroBlock.d.ts.map +1 -1
  33. package/dist/components/blocks/Image.d.ts +41 -0
  34. package/dist/components/blocks/Image.d.ts.map +1 -0
  35. package/dist/components/blocks/PageBannerHeader.d.ts.map +1 -1
  36. package/dist/components/blocks/Section.d.ts +16 -2
  37. package/dist/components/blocks/Section.d.ts.map +1 -1
  38. package/dist/components/blocks/Text.d.ts +41 -0
  39. package/dist/components/blocks/Text.d.ts.map +1 -0
  40. package/dist/components/blocks/index.d.ts +4 -0
  41. package/dist/components/blocks/index.d.ts.map +1 -1
  42. package/dist/components/buttons/Button.d.ts +23 -7
  43. package/dist/components/buttons/Button.d.ts.map +1 -1
  44. package/dist/components/forms/FormBlock.d.ts +19 -13
  45. package/dist/components/forms/FormBlock.d.ts.map +1 -1
  46. package/dist/components/index.d.ts +4 -0
  47. package/dist/components/index.d.ts.map +1 -1
  48. package/dist/components/input/ChoiceInputField.d.ts +17 -11
  49. package/dist/components/input/ChoiceInputField.d.ts.map +1 -1
  50. package/dist/components/input/HtmlInputField.d.ts +17 -11
  51. package/dist/components/input/HtmlInputField.d.ts.map +1 -1
  52. package/dist/components/input/SelectInputField.d.ts +16 -10
  53. package/dist/components/input/SelectInputField.d.ts.map +1 -1
  54. package/dist/components/input/SwitchInputField.d.ts +16 -10
  55. package/dist/components/input/SwitchInputField.d.ts.map +1 -1
  56. package/dist/components/input/TextField.d.ts.map +1 -1
  57. package/dist/components/input/TextInputField.d.ts +16 -11
  58. package/dist/components/input/TextInputField.d.ts.map +1 -1
  59. package/dist/components/layout/GridCell.d.ts +23 -6
  60. package/dist/components/layout/GridCell.d.ts.map +1 -1
  61. package/dist/components/layout/GridLayout.d.ts +24 -23
  62. package/dist/components/layout/GridLayout.d.ts.map +1 -1
  63. package/dist/components/pages/FormPage.d.ts.map +1 -1
  64. package/dist/components/pages/Page.d.ts +49 -87
  65. package/dist/components/pages/Page.d.ts.map +1 -1
  66. package/dist/components/pages/index.d.ts +2 -2
  67. package/dist/components/pages/index.d.ts.map +1 -1
  68. package/dist/config/AppConfig.d.ts +49 -0
  69. package/dist/config/AppConfig.d.ts.map +1 -0
  70. package/dist/config/AppConfigBuilder.d.ts +75 -0
  71. package/dist/config/AppConfigBuilder.d.ts.map +1 -0
  72. package/dist/config/index.d.ts +13 -0
  73. package/dist/config/index.d.ts.map +1 -0
  74. package/dist/config/types.d.ts +130 -0
  75. package/dist/config/types.d.ts.map +1 -0
  76. package/dist/config.d.ts +15 -0
  77. package/dist/config.d.ts.map +1 -0
  78. package/dist/config.esm.js +451 -0
  79. package/dist/config.js +455 -0
  80. package/dist/contexts/PrintModeContext.d.ts +27 -0
  81. package/dist/contexts/PrintModeContext.d.ts.map +1 -0
  82. package/dist/contexts/QwickAppContext.d.ts +2 -2
  83. package/dist/contexts/QwickAppContext.d.ts.map +1 -1
  84. package/dist/contexts/index.d.ts +2 -0
  85. package/dist/contexts/index.d.ts.map +1 -1
  86. package/dist/hooks/index.d.ts +2 -0
  87. package/dist/hooks/index.d.ts.map +1 -1
  88. package/dist/hooks/usePrintMode.d.ts +39 -0
  89. package/dist/hooks/usePrintMode.d.ts.map +1 -0
  90. package/dist/index.css +1 -1
  91. package/dist/index.d.ts +1 -0
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.esm.css +1 -1
  94. package/dist/index.esm.js +10951 -6238
  95. package/dist/index.js +11014 -6287
  96. package/dist/schemas/CodeSchema.d.ts +2 -1
  97. package/dist/schemas/CodeSchema.d.ts.map +1 -1
  98. package/dist/schemas/CollapsibleLayoutSchema.d.ts +2 -1
  99. package/dist/schemas/CollapsibleLayoutSchema.d.ts.map +1 -1
  100. package/dist/schemas/ContentSchema.d.ts +2 -1
  101. package/dist/schemas/ContentSchema.d.ts.map +1 -1
  102. package/dist/schemas/GridCellSchema.d.ts +25 -0
  103. package/dist/schemas/GridCellSchema.d.ts.map +1 -0
  104. package/dist/schemas/GridLayoutSchema.d.ts +23 -0
  105. package/dist/schemas/GridLayoutSchema.d.ts.map +1 -0
  106. package/dist/schemas/HtmlSchema.d.ts +14 -0
  107. package/dist/schemas/HtmlSchema.d.ts.map +1 -0
  108. package/dist/schemas/ImageSchema.d.ts +32 -0
  109. package/dist/schemas/ImageSchema.d.ts.map +1 -0
  110. package/dist/schemas/LogoSchema.d.ts +35 -0
  111. package/dist/schemas/LogoSchema.d.ts.map +1 -0
  112. package/dist/schemas/MarkdownSchema.d.ts +14 -0
  113. package/dist/schemas/MarkdownSchema.d.ts.map +1 -0
  114. package/dist/schemas/PageTemplateSchema.d.ts +31 -0
  115. package/dist/schemas/PageTemplateSchema.d.ts.map +1 -0
  116. package/dist/schemas/PrintConfigSchema.d.ts +31 -0
  117. package/dist/schemas/PrintConfigSchema.d.ts.map +1 -0
  118. package/dist/schemas/SectionSchema.d.ts +2 -1
  119. package/dist/schemas/SectionSchema.d.ts.map +1 -1
  120. package/dist/schemas/TextSchema.d.ts +37 -0
  121. package/dist/schemas/TextSchema.d.ts.map +1 -0
  122. package/dist/schemas/ViewModelSchema.d.ts +23 -0
  123. package/dist/schemas/ViewModelSchema.d.ts.map +1 -0
  124. package/dist/schemas/index.d.ts +15 -1
  125. package/dist/schemas/index.d.ts.map +1 -1
  126. package/dist/schemas/transformers/ComponentTransformer.d.ts +116 -0
  127. package/dist/schemas/transformers/ComponentTransformer.d.ts.map +1 -0
  128. package/dist/schemas/transformers/ReactNodeTransformer.d.ts +53 -0
  129. package/dist/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -0
  130. package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts +66 -0
  131. package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts.map +1 -0
  132. package/dist/schemas/transformers/registry.d.ts +15 -0
  133. package/dist/schemas/transformers/registry.d.ts.map +1 -0
  134. package/dist/schemas/types/Serializable.d.ts +46 -0
  135. package/dist/schemas/types/Serializable.d.ts.map +1 -0
  136. package/dist/utils/htmlTransform.d.ts.map +1 -1
  137. package/dist/utils/reactUtils.d.ts +12 -3
  138. package/dist/utils/reactUtils.d.ts.map +1 -1
  139. package/package.json +17 -3
  140. package/src/{components/__tests__ → __tests__/components}/AccessibilityProvider.test.tsx +1 -1
  141. package/src/{components/__tests__ → __tests__/components}/Article.test.tsx +1 -1
  142. package/src/{components/__tests__ → __tests__/components}/Breadcrumbs.test.tsx +1 -1
  143. package/src/{components/__tests__ → __tests__/components}/Button.test.tsx +1 -1
  144. package/src/{components/__tests__ → __tests__/components}/CardListGrid.test.tsx +2 -2
  145. package/src/{components/__tests__ → __tests__/components}/ChoiceInputField.test.tsx +1 -1
  146. package/src/{components/__tests__ → __tests__/components}/Code.test.tsx +1 -1
  147. package/src/{components/__tests__ → __tests__/components}/Content.integration.test.tsx +1 -1
  148. package/src/{components/__tests__ → __tests__/components}/Content.test.tsx +1 -1
  149. package/src/{components/__tests__ → __tests__/components}/CoverImageHeader.test.tsx +2 -2
  150. package/src/{components/__tests__ → __tests__/components}/ErrorBoundary.test.tsx +1 -1
  151. package/src/{components/__tests__ → __tests__/components}/FeatureCard.integration.test.tsx +2 -2
  152. package/src/{components/__tests__ → __tests__/components}/FeatureGrid.integration.test.tsx +2 -2
  153. package/src/{components/__tests__ → __tests__/components}/FeatureGrid.test.tsx +2 -2
  154. package/src/{components/__tests__ → __tests__/components}/Footer.test.tsx +4 -4
  155. package/src/{components/__tests__ → __tests__/components}/FormBlock.test.tsx +1 -1
  156. package/src/{components/__tests__ → __tests__/components}/HeroBlock.integration.test.tsx +2 -2
  157. package/src/{components/__tests__ → __tests__/components}/HeroBlock.test.tsx +233 -7
  158. package/src/{components/__tests__ → __tests__/components}/Html.test.tsx +11 -2
  159. package/src/{components/__tests__ → __tests__/components}/HtmlInputField.test.tsx +3 -3
  160. package/src/__tests__/components/Logo.test.js +3 -3
  161. package/src/{components/__tests__ → __tests__/components}/Markdown.test.tsx +1 -1
  162. package/src/{components/__tests__ → __tests__/components}/PageBannerHeader.test.tsx +3 -3
  163. package/src/{components/__tests__ → __tests__/components}/PaletteSwitcher.test.tsx +3 -3
  164. package/src/{components/__tests__ → __tests__/components}/ProductCard.test.tsx +4 -4
  165. package/src/{components/__tests__ → __tests__/components}/SafeSpan.integration.test.tsx +2 -2
  166. package/src/{components/__tests__ → __tests__/components}/SafeSpan.simple.test.tsx +1 -1
  167. package/src/{components/__tests__ → __tests__/components}/SafeSpan.test.tsx +1 -1
  168. package/src/{components/__tests__ → __tests__/components}/Section.integration.test.tsx +1 -1
  169. package/src/{components/__tests__ → __tests__/components}/Section.test.tsx +1 -1
  170. package/src/{components/__tests__ → __tests__/components}/SelectInputField.test.tsx +1 -1
  171. package/src/{components/__tests__ → __tests__/components}/TextInputField.test.tsx +3 -3
  172. package/src/{components/__tests__ → __tests__/components}/ThemeSwitcher.test.tsx +3 -3
  173. package/src/__tests__/components/base/ModelView.test.tsx +220 -0
  174. package/src/__tests__/components/blocks/Code.performance.test.tsx +625 -0
  175. package/src/__tests__/components/blocks/Code.serialization.test.tsx +507 -0
  176. package/src/__tests__/components/blocks/HeroBlock.serialization.test.tsx +414 -0
  177. package/src/__tests__/components/blocks/Image.serialization.test.tsx +257 -0
  178. package/src/__tests__/components/blocks/Section.serialization.test.tsx +553 -0
  179. package/src/__tests__/components/blocks/Text.performance.test.tsx +442 -0
  180. package/src/__tests__/components/blocks/Text.serialization.test.tsx +491 -0
  181. package/src/__tests__/components/buttons/Button.serialization.test.tsx +443 -0
  182. package/src/__tests__/components/input/FormComponents.serialization.test.tsx +482 -0
  183. package/src/__tests__/components/input/SelectInputField.serialization.test.tsx +439 -0
  184. package/src/__tests__/components/input/TextInputField.serialization.test.tsx +359 -0
  185. package/src/{components/layout/CollapsibleLayout/__tests__ → __tests__/components/layout}/CollapsibleLayout.test.tsx +4 -4
  186. package/src/__tests__/components/layout/GridCell.serialization.test.tsx +403 -0
  187. package/src/__tests__/components/layout/GridLayout.serialization.test.tsx +311 -0
  188. package/src/__tests__/hooks/usePrintMode.test.ts +89 -0
  189. package/src/__tests__/schemas/PageTemplateSchema.test.ts +161 -0
  190. package/src/__tests__/schemas/PrintConfigSchema.test.ts +127 -0
  191. package/src/__tests__/schemas/ViewModelSchema.test.ts +80 -0
  192. package/src/__tests__/schemas/transformers/ComponentSerializationPatterns.test.tsx +602 -0
  193. package/src/__tests__/schemas/transformers/ComponentTransformer.htmlPatterns.test.ts +301 -0
  194. package/src/__tests__/schemas/transformers/ComponentTransformer.test.ts +521 -0
  195. package/src/__tests__/schemas/transformers/CrossBrowserCompatibility.test.ts +586 -0
  196. package/src/__tests__/schemas/transformers/MockSerializableComponent.ts +103 -0
  197. package/src/__tests__/schemas/transformers/RealWorldScenarios.test.tsx +1165 -0
  198. package/src/__tests__/schemas/transformers/SerializationErrorHandling.test.ts +602 -0
  199. package/src/__tests__/schemas/transformers/SerializationIntegration.test.tsx +691 -0
  200. package/src/__tests__/schemas/transformers/SerializationPerformance.test.ts +460 -0
  201. package/src/__tests__/schemas/transformers/TestAutomation.test.ts +597 -0
  202. package/src/{utils/__tests__ → __tests__/utils}/nested-dom-fix.test.tsx +1 -1
  203. package/src/components/ErrorBoundary.tsx +8 -8
  204. package/src/components/Html.tsx +147 -44
  205. package/src/components/Logo.tsx +198 -100
  206. package/src/components/Markdown.tsx +125 -16
  207. package/src/components/QwickApp.tsx +64 -31
  208. package/src/components/QwickIcon.tsx +59 -0
  209. package/src/components/SafeSpan.tsx +65 -10
  210. package/src/components/Scaffold.tsx +2 -8
  211. package/src/components/base/ModelView.tsx +199 -0
  212. package/src/components/base/index.ts +11 -0
  213. package/src/components/blocks/Article.tsx +57 -18
  214. package/src/components/blocks/Code.md +529 -0
  215. package/src/components/blocks/Code.tsx +102 -15
  216. package/src/components/blocks/CoverImageHeader.tsx +9 -4
  217. package/src/components/blocks/FeatureCard.tsx +1 -2
  218. package/src/components/blocks/FeatureGrid.tsx +19 -1
  219. package/src/components/blocks/Footer.tsx +13 -1
  220. package/src/components/blocks/HeroBlock.tsx +87 -20
  221. package/src/components/blocks/Image.tsx +395 -0
  222. package/src/components/blocks/PageBannerHeader.tsx +14 -12
  223. package/src/components/blocks/ProductCard.tsx +1 -1
  224. package/src/components/blocks/Section.tsx +113 -8
  225. package/src/components/blocks/Text.tsx +285 -0
  226. package/src/components/blocks/index.ts +4 -0
  227. package/src/components/buttons/Button.tsx +184 -15
  228. package/src/components/forms/FormBlock.tsx +70 -17
  229. package/src/components/index.ts +5 -0
  230. package/src/components/input/ChoiceInputField.tsx +48 -18
  231. package/src/components/input/HtmlInputField.tsx +48 -18
  232. package/src/components/input/SelectInputField.tsx +48 -16
  233. package/src/components/input/SwitchInputField.tsx +48 -17
  234. package/src/components/input/TextField.tsx +41 -1
  235. package/src/components/input/TextInputField.tsx +52 -18
  236. package/src/components/layout/GridCell.tsx +118 -9
  237. package/src/components/layout/GridLayout.tsx +125 -24
  238. package/src/components/pages/FormPage.tsx +0 -1
  239. package/src/components/pages/Page.css +304 -332
  240. package/src/components/pages/Page.tsx +307 -255
  241. package/src/components/pages/index.ts +2 -2
  242. package/src/config/AppConfig.ts +133 -0
  243. package/src/config/AppConfigBuilder.ts +421 -0
  244. package/src/config/__tests__/AppConfig.test.ts +385 -0
  245. package/src/config/__tests__/AppConfigBuilder.test.ts +432 -0
  246. package/src/config/index.ts +24 -0
  247. package/src/config/types.ts +170 -0
  248. package/src/config.ts +25 -0
  249. package/src/contexts/PrintModeContext.tsx +332 -0
  250. package/src/contexts/QwickAppContext.tsx +2 -2
  251. package/src/contexts/index.ts +2 -0
  252. package/src/hooks/index.ts +5 -1
  253. package/src/hooks/usePrintMode.ts +73 -0
  254. package/src/index.ts +3 -0
  255. package/src/schemas/CodeSchema.ts +3 -3
  256. package/src/schemas/CollapsibleLayoutSchema.ts +2 -1
  257. package/src/schemas/ContentSchema.ts +2 -1
  258. package/src/schemas/GridCellSchema.ts +164 -0
  259. package/src/schemas/GridLayoutSchema.ts +133 -0
  260. package/src/schemas/HtmlSchema.ts +47 -0
  261. package/src/schemas/ImageSchema.ts +235 -0
  262. package/src/schemas/LogoSchema.ts +241 -0
  263. package/src/schemas/MarkdownSchema.ts +47 -0
  264. package/src/schemas/PageTemplateSchema.ts +186 -0
  265. package/src/schemas/PrintConfigSchema.ts +207 -0
  266. package/src/schemas/README.md +661 -0
  267. package/src/schemas/SectionSchema.ts +2 -1
  268. package/src/schemas/TextSchema.ts +329 -0
  269. package/src/schemas/ViewModelSchema.ts +115 -0
  270. package/src/schemas/index.ts +21 -2
  271. package/src/schemas/transformers/ComponentTransformer.ts +403 -0
  272. package/src/schemas/transformers/ReactNodeTransformer.ts +236 -0
  273. package/src/schemas/transformers/registry.ts +72 -0
  274. package/src/schemas/types/Serializable.ts +51 -0
  275. package/src/stories/AccessibilityProvider.stories.tsx +253 -253
  276. package/src/stories/Article.stories.tsx +433 -433
  277. package/src/stories/Button.stories.tsx +1 -1
  278. package/src/stories/CardListGrid.stories.tsx +451 -451
  279. package/src/stories/ChoiceInputField.stories.tsx +503 -503
  280. package/src/stories/Code.stories.tsx +1 -1
  281. package/src/stories/CollapsibleLayout.stories.tsx +1414 -1414
  282. package/src/stories/Content.stories.tsx +393 -393
  283. package/src/stories/CoverImageHeader.stories.tsx +701 -701
  284. package/src/stories/DataBinding.advanced.stories.tsx +432 -432
  285. package/src/stories/DataProvider.stories.tsx +1192 -1192
  286. package/src/stories/FeatureCard.stories.tsx +557 -557
  287. package/src/stories/FeatureGrid.stories.tsx +594 -594
  288. package/src/stories/Footer.stories.tsx +640 -640
  289. package/src/stories/FormBlock.stories.tsx +760 -760
  290. package/src/stories/FormComponents.stories.tsx +349 -541
  291. package/src/stories/GridCell.stories.tsx +417 -0
  292. package/src/stories/GridLayout.stories.tsx +353 -0
  293. package/src/stories/HeroBlock.stories.tsx +862 -373
  294. package/src/stories/HtmlInputField.stories.tsx +474 -474
  295. package/src/stories/Image.stories.tsx +819 -0
  296. package/src/stories/Introduction.stories.tsx +667 -667
  297. package/src/stories/LayoutBlocks.stories.tsx +324 -324
  298. package/src/stories/Logo.stories.tsx +165 -6
  299. package/src/stories/Markdown.stories.tsx +137 -137
  300. package/src/stories/ModelView.stories.tsx +477 -0
  301. package/src/stories/Page.stories.tsx +688 -688
  302. package/src/stories/PageBannerHeader.stories.tsx +864 -864
  303. package/src/stories/PaletteSwitcher.stories.tsx +119 -119
  304. package/src/stories/ProductCard.stories.tsx +424 -424
  305. package/src/stories/QwickApp.stories.tsx +368 -368
  306. package/src/stories/ResponsiveMenu.stories.tsx +249 -249
  307. package/src/stories/SafeSpan.stories.tsx +531 -531
  308. package/src/stories/Section.stories.tsx +90 -2
  309. package/src/stories/SelectInputField.stories.tsx +524 -524
  310. package/src/stories/Text.stories.tsx +560 -0
  311. package/src/stories/TextInputField.stories.tsx +443 -443
  312. package/src/stories/ThemeSwitcher.stories.tsx +123 -123
  313. package/src/utils/htmlTransform.tsx +74 -53
  314. package/src/utils/reactUtils.tsx +57 -6
  315. package/dist/index.bundled.css +0 -12
  316. /package/src/{hooks/__tests__ → __tests__/hooks}/useDataBinding.test.tsx.disabled +0 -0
  317. /package/src/{schemas/__tests__ → __tests__/schemas}/builders.test.ts +0 -0
  318. /package/src/{utils/__tests__ → __tests__/utils}/createDataDrivenComponent.test.tsx.disabled +0 -0
  319. /package/src/{utils/__tests__ → __tests__/utils}/htmlTransform.test.tsx +0 -0
  320. /package/src/{utils/__tests__ → __tests__/utils}/optional-logging.test.ts +0 -0
@@ -0,0 +1,661 @@
1
+ # QwickApps React Framework - Schema System
2
+
3
+ **Component Serialization & Data Binding Architecture**
4
+
5
+ ## Overview
6
+
7
+ The QwickApps Schema System provides comprehensive component serialization and data binding capabilities, enabling "WebView for React" functionality. This system allows React components to be serialized to JSON, transmitted across boundaries, and reconstructed while preserving full functionality and data binding.
8
+
9
+ ## Table of Contents
10
+
11
+ 1. [Architecture Overview](#architecture-overview)
12
+ 2. [Serialization System](#serialization-system)
13
+ 3. [Data Binding Integration](#data-binding-integration)
14
+ 4. [Component Schemas](#component-schemas)
15
+ 5. [Transformers](#transformers)
16
+ 6. [Usage Examples](#usage-examples)
17
+ 7. [Performance Characteristics](#performance-characteristics)
18
+ 8. [Testing](#testing)
19
+
20
+ ## Architecture Overview
21
+
22
+ ```
23
+ Schema System Architecture
24
+ ├── Serialization Layer
25
+ │ ├── Serializable Interface (types/Serializable.ts)
26
+ │ ├── ComponentTransformer (transformers/ComponentTransformer.ts)
27
+ │ ├── ReactNodeTransformer (transformers/ReactNodeTransformer.ts)
28
+ │ └── Registry System
29
+ ├── Data Binding Layer
30
+ │ ├── Schema Models (CodeSchema.ts, etc.)
31
+ │ ├── Model Base Classes
32
+ │ └── Binding Integration
33
+ └── Component Integration
34
+ ├── Class-Based Components
35
+ ├── View Delegation Pattern
36
+ └── Automatic Registration
37
+ ```
38
+
39
+ ## Serialization System
40
+
41
+ ### Core Interfaces
42
+
43
+ #### Serializable Interface
44
+ ```typescript
45
+ // types/Serializable.ts
46
+ interface Serializable {
47
+ toJson(): any; // Component instance → JSON data
48
+ }
49
+
50
+ interface SerializableConstructor {
51
+ readonly tagName: string; // Unique component identifier
52
+ readonly version: string; // Semantic version
53
+ fromJson(jsonData: any): ReactElement; // JSON data → React element
54
+ new (...args: any[]): Serializable;
55
+ }
56
+ ```
57
+
58
+ #### Data Format
59
+ Serialized components use a standardized structure:
60
+ ```json
61
+ {
62
+ "tag": "ComponentName",
63
+ "version": "1.0.0",
64
+ "data": {
65
+ "prop1": "value1",
66
+ "prop2": "value2",
67
+ "dataSource": "api/data/source",
68
+ "bindingOptions": { "cache": true }
69
+ }
70
+ }
71
+ ```
72
+
73
+ ### Component Self-Declaration Pattern
74
+
75
+ Components declare their own serialization identity:
76
+ ```typescript
77
+ export class MyComponent extends React.Component<MyComponentProps> implements Serializable {
78
+ // Self-declaration
79
+ static readonly tagName = 'MyComponent';
80
+ static readonly version = '1.0.0';
81
+
82
+ // Deserialization
83
+ static fromJson(jsonData: any): ReactElement {
84
+ return <MyComponent {...jsonData} />;
85
+ }
86
+
87
+ // Serialization
88
+ toJson(): any {
89
+ return {
90
+ title: this.props.title,
91
+ dataSource: this.props.dataSource,
92
+ bindingOptions: this.props.bindingOptions
93
+ };
94
+ }
95
+ }
96
+ ```
97
+
98
+ ## Transformers
99
+
100
+ ### ComponentTransformer - Primary Serialization Engine
101
+
102
+ Located: `transformers/ComponentTransformer.ts`
103
+
104
+ **Key Features:**
105
+ - Component registration and discovery
106
+ - Bidirectional transformation (serialize/deserialize)
107
+ - Fallback handling for unregistered components
108
+ - Performance optimization with caching
109
+
110
+ **Primary Methods:**
111
+ ```typescript
112
+ class ComponentTransformer {
113
+ // Register component for serialization
114
+ static registerComponent(componentClass: SerializableConstructor): void
115
+
116
+ // Serialize React nodes to JSON string
117
+ static serialize(node: ReactNode | ReactNode[]): string
118
+
119
+ // Deserialize JSON to React nodes
120
+ static deserialize(input: string | object | object[]): ReactNode | ReactNode[]
121
+
122
+ // Registry management
123
+ static getRegisteredComponents(): string[]
124
+ static clearRegistry(): void
125
+ }
126
+ ```
127
+
128
+ **Usage Example:**
129
+ ```typescript
130
+ import { ComponentTransformer } from './transformers/ComponentTransformer';
131
+
132
+ // Serialize component
133
+ const component = <Code language="javascript">console.log('Hello');</Code>;
134
+ const serialized = ComponentTransformer.serialize(component);
135
+
136
+ // Deserialize back to component
137
+ const deserialized = ComponentTransformer.deserialize(serialized);
138
+ ```
139
+
140
+ ### ReactNodeTransformer - Fallback System
141
+
142
+ Located: `transformers/ReactNodeTransformer.ts`
143
+
144
+ **Purpose:**
145
+ Handles serialization of unregistered components, HTML elements, and standard React content.
146
+
147
+ **Capabilities:**
148
+ - Primitive value serialization (strings, numbers, booleans)
149
+ - Array and object handling
150
+ - React element metadata preservation
151
+ - HTML element reconstruction
152
+ - Graceful fallback rendering
153
+
154
+ **Data Structures:**
155
+ ```typescript
156
+ // Primitive values
157
+ { type: 'primitive', value: 'Hello World' }
158
+
159
+ // React elements
160
+ {
161
+ type: 'react-element',
162
+ elementType: 'div',
163
+ props: { className: 'example', children: 'Content' },
164
+ key: 'unique-key'
165
+ }
166
+
167
+ // Arrays
168
+ { type: 'array', children: [/* serialized items */] }
169
+ ```
170
+
171
+ ## Data Binding Integration
172
+
173
+ ### Schema Models
174
+
175
+ Component schemas define data structures for binding:
176
+
177
+ ```typescript
178
+ // Example: CodeSchema.ts
179
+ @Schema('Code', '1.0.0')
180
+ export class CodeModel extends Model {
181
+ children?: string;
182
+ language?: string;
183
+ showCopy?: boolean;
184
+ showLineNumbers?: boolean;
185
+ title?: string;
186
+ wrapLines?: boolean;
187
+ codeBackground?: string;
188
+
189
+ static getSchema() {
190
+ return {
191
+ type: 'object',
192
+ properties: {
193
+ children: { type: 'string' },
194
+ language: { type: 'string', default: 'text' },
195
+ showCopy: { type: 'boolean', default: true },
196
+ // ... other properties
197
+ }
198
+ };
199
+ }
200
+ }
201
+ ```
202
+
203
+ ### Data Binding Preservation
204
+
205
+ Serializable components must preserve data binding configuration:
206
+ ```typescript
207
+ toJson(): any {
208
+ return {
209
+ // Component-specific props
210
+ title: this.props.title,
211
+ language: this.props.language,
212
+
213
+ // CRITICAL: Always preserve data binding
214
+ dataSource: this.props.dataSource,
215
+ bindingOptions: this.props.bindingOptions
216
+ };
217
+ }
218
+ ```
219
+
220
+ ### Binding Integration Pattern
221
+
222
+ ```typescript
223
+ // Component with data binding support
224
+ export interface ComponentProps extends WithDataBinding {
225
+ title: string;
226
+ // ... other props
227
+ }
228
+
229
+ export class Component extends React.Component<ComponentProps> implements Serializable {
230
+ render() {
231
+ // Route based on data binding presence
232
+ return this.props.dataSource ?
233
+ <ComponentWithDataBinding {...this.props} /> :
234
+ <ComponentView {...this.props} />;
235
+ }
236
+ }
237
+
238
+ // Data binding wrapper
239
+ function ComponentWithDataBinding(props: ComponentProps) {
240
+ const { dataSource, bindingOptions, ...restProps } = props;
241
+
242
+ const { loading, error, ...boundProps } = useDataBinding(
243
+ dataSource!,
244
+ restProps,
245
+ ComponentModel.getSchema(),
246
+ { cache: true, ...bindingOptions }
247
+ );
248
+
249
+ if (loading) return <LoadingState />;
250
+ if (error) return <ErrorState error={error} />;
251
+
252
+ return <ComponentView {...boundProps} />;
253
+ }
254
+ ```
255
+
256
+ ## Component Schemas
257
+
258
+ ### Schema Definition Pattern
259
+
260
+ ```typescript
261
+ // Base schema structure for all components
262
+ @Schema('ComponentName', '1.0.0')
263
+ export class ComponentModel extends Model {
264
+ // Core component properties
265
+ title?: string;
266
+ visible?: boolean;
267
+
268
+ // Data binding properties (inherited from WithDataBinding)
269
+ dataSource?: string;
270
+ bindingOptions?: BindingOptions;
271
+
272
+ // Component-specific properties
273
+ customProp?: string;
274
+
275
+ static getSchema() {
276
+ return {
277
+ type: 'object',
278
+ properties: {
279
+ title: { type: 'string' },
280
+ visible: { type: 'boolean', default: true },
281
+ customProp: { type: 'string' },
282
+ // Data binding schema included automatically
283
+ },
284
+ required: ['title']
285
+ };
286
+ }
287
+ }
288
+ ```
289
+
290
+ ### Schema Versioning
291
+
292
+ ```typescript
293
+ // Handle schema evolution with version migrations
294
+ @Schema('Component', '2.0.0')
295
+ export class ComponentModelV2 extends Model {
296
+ // New property structure
297
+ config?: ComponentConfig;
298
+
299
+ static migrateFromV1(v1Data: any): ComponentModelV2 {
300
+ return new ComponentModelV2({
301
+ title: v1Data.title,
302
+ config: {
303
+ theme: v1Data.oldThemeProp || 'default',
304
+ layout: v1Data.oldLayoutProp || 'standard'
305
+ }
306
+ });
307
+ }
308
+ }
309
+ ```
310
+
311
+ ## Usage Examples
312
+
313
+ ### Basic Serialization
314
+
315
+ ```typescript
316
+ import { Code } from '../components/blocks/Code';
317
+ import { ComponentTransformer } from './transformers/ComponentTransformer';
318
+
319
+ // Create component
320
+ const codeBlock = (
321
+ <Code language="typescript" showCopy={true}>
322
+ const example: string = 'Hello World';
323
+ console.log(example);
324
+ </Code>
325
+ );
326
+
327
+ // Serialize
328
+ const serializedJson = ComponentTransformer.serialize(codeBlock);
329
+ console.log('Serialized:', serializedJson);
330
+
331
+ // Deserialize
332
+ const reconstructed = ComponentTransformer.deserialize(serializedJson);
333
+ // reconstructed is a fully functional React component
334
+ ```
335
+
336
+ ### CMS Integration
337
+
338
+ ```typescript
339
+ // CMS provides serialized component data
340
+ const cmsResponse = {
341
+ components: [
342
+ {
343
+ tag: "Code",
344
+ version: "1.0.0",
345
+ data: {
346
+ children: "// CMS-provided code\nconst cms = 'integration';",
347
+ language: "javascript",
348
+ title: "CMS Example"
349
+ }
350
+ }
351
+ ]
352
+ };
353
+
354
+ // Render CMS components
355
+ const cmsComponents = cmsResponse.components.map((componentData, index) => (
356
+ <div key={index}>
357
+ {ComponentTransformer.deserialize(componentData)}
358
+ </div>
359
+ ));
360
+ ```
361
+
362
+ ### Data Binding with Serialization
363
+
364
+ ```typescript
365
+ // Component with data binding
366
+ const dataBoundCode = (
367
+ <Code
368
+ dataSource="api/code-examples/fibonacci"
369
+ bindingOptions={{ cache: true, cacheTTL: 300000 }}
370
+ language="javascript"
371
+ showCopy={true}
372
+ />
373
+ );
374
+
375
+ // Serialization preserves data binding
376
+ const serialized = ComponentTransformer.serialize(dataBoundCode);
377
+
378
+ // After deserialization, data binding continues to work
379
+ const deserialized = ComponentTransformer.deserialize(serialized);
380
+ // Component will still load data from "api/code-examples/fibonacci"
381
+ ```
382
+
383
+ ### Component Collections
384
+
385
+ ```typescript
386
+ // Serialize multiple components
387
+ const componentArray = [
388
+ <Code language="js">const a = 1;</Code>,
389
+ <Code language="py">print("hello")</Code>,
390
+ <Code language="html">&lt;div&gt;Hello&lt;/div&gt;</Code>
391
+ ];
392
+
393
+ const serializedArray = ComponentTransformer.serialize(componentArray);
394
+ const deserializedArray = ComponentTransformer.deserialize(serializedArray);
395
+ // Returns array of functional components
396
+ ```
397
+
398
+ ## Performance Characteristics
399
+
400
+ ### Benchmarks (QA Validated)
401
+
402
+ | Operation | Typical Performance | Large Data (1000+ components) | Memory Usage |
403
+ |-----------|-------------------|--------------------------------|--------------|
404
+ | **Serialization** | <1ms | <50ms | <10MB |
405
+ | **Deserialization** | <1ms | <50ms | <10MB |
406
+ | **Round-trip** | <3ms | <100ms | <20MB |
407
+ | **Registry Lookup** | <0.1ms | <0.1ms | Minimal |
408
+ | **Deep Nesting (30 levels)** | <5ms | N/A | <5MB |
409
+
410
+ ### Performance Optimizations
411
+
412
+ ```typescript
413
+ // Registry caching
414
+ const componentRegistry = new Map<string, SerializableConstructor>();
415
+
416
+ // Lazy processing
417
+ const serializeNode = memoize((node: ReactNode) => {
418
+ // Expensive serialization operations are cached
419
+ });
420
+
421
+ // Memory management
422
+ componentWillUnmount() {
423
+ // Automatic cleanup of cached references
424
+ }
425
+ ```
426
+
427
+ ### Performance Testing
428
+
429
+ ```typescript
430
+ // Performance validation test
431
+ test('serialization performance benchmark', () => {
432
+ const largeComponent = createLargeComponent(1000); // 1000 child components
433
+
434
+ const startTime = performance.now();
435
+ const serialized = ComponentTransformer.serialize(largeComponent);
436
+ const serializeTime = performance.now() - startTime;
437
+
438
+ const deserializeStart = performance.now();
439
+ const deserialized = ComponentTransformer.deserialize(serialized);
440
+ const deserializeTime = performance.now() - deserializeStart;
441
+
442
+ expect(serializeTime).toBeLessThan(50); // <50ms for 1000 components
443
+ expect(deserializeTime).toBeLessThan(50); // <50ms for 1000 components
444
+ });
445
+ ```
446
+
447
+ ## Error Handling
448
+
449
+ ### Graceful Degradation
450
+
451
+ ```typescript
452
+ // Unknown component handling
453
+ {
454
+ tag: "__react_node__", // Fallback tag
455
+ version: "1.0.0",
456
+ data: {
457
+ type: "react-element",
458
+ elementType: "div",
459
+ props: { children: "Fallback content" }
460
+ }
461
+ }
462
+
463
+ // Error recovery in deserialization
464
+ static fromJson(jsonData: any): ReactElement {
465
+ try {
466
+ return <Component {...jsonData} />;
467
+ } catch (error) {
468
+ console.warn('Component deserialization error:', error);
469
+ return <ErrorFallbackComponent error={error} />;
470
+ }
471
+ }
472
+ ```
473
+
474
+ ### Development vs Production
475
+
476
+ ```typescript
477
+ // Development: Detailed error information
478
+ if (process.env.NODE_ENV === 'development') {
479
+ console.error('Detailed serialization error:', error, stackTrace);
480
+ }
481
+
482
+ // Production: Silent fallback
483
+ return <SafeFallbackComponent />;
484
+ ```
485
+
486
+ ## Testing
487
+
488
+ ### Test Structure
489
+
490
+ ```
491
+ src/schemas/transformers/__tests__/
492
+ ├── ComponentTransformer.test.ts # Core transformer tests
493
+ ├── SerializationIntegration.test.tsx # Multi-component scenarios
494
+ ├── SerializationPerformance.test.ts # Performance benchmarks
495
+ ├── SerializationErrorHandling.test.ts # Error scenarios
496
+ ├── ComponentSerializationPatterns.test.tsx # Standardized patterns
497
+ ├── RealWorldScenarios.test.tsx # Production use cases
498
+ └── CrossBrowserCompatibility.test.ts # Browser compatibility
499
+ ```
500
+
501
+ ### Test Categories
502
+
503
+ #### 1. Unit Tests
504
+ ```typescript
505
+ describe('ComponentTransformer', () => {
506
+ test('should serialize component correctly', () => {
507
+ const component = <Code>test</Code>;
508
+ const serialized = ComponentTransformer.serialize(component);
509
+ expect(serialized).toBeTruthy();
510
+ });
511
+
512
+ test('should deserialize component correctly', () => {
513
+ const data = { tag: 'Code', version: '1.0.0', data: { children: 'test' } };
514
+ const component = ComponentTransformer.deserialize(data);
515
+ expect(component).toBeTruthy();
516
+ });
517
+ });
518
+ ```
519
+
520
+ #### 2. Integration Tests
521
+ ```typescript
522
+ test('should handle nested component serialization', () => {
523
+ const nested = (
524
+ <Code title="Parent">
525
+ <Code language="js">const nested = true;</Code>
526
+ </Code>
527
+ );
528
+
529
+ const serialized = ComponentTransformer.serialize(nested);
530
+ const deserialized = ComponentTransformer.deserialize(serialized);
531
+ expect(deserialized).toBeTruthy();
532
+ });
533
+ ```
534
+
535
+ #### 3. Performance Tests
536
+ ```typescript
537
+ test('should handle large component trees efficiently', () => {
538
+ const largeTree = createDeepComponentTree(1000);
539
+
540
+ const { duration } = measurePerformance(() => {
541
+ ComponentTransformer.serialize(largeTree);
542
+ });
543
+
544
+ expect(duration).toBeLessThan(50); // <50ms for 1000 components
545
+ });
546
+ ```
547
+
548
+ ### Generic Test Utilities
549
+
550
+ ```typescript
551
+ // Reusable test helper for component serialization
552
+ export function testComponentSerialization<T>(
553
+ componentName: string,
554
+ ComponentClass: any,
555
+ testCases: Array<{ name: string; props: T }>
556
+ ) {
557
+ describe(`${componentName} Serialization`, () => {
558
+ testCases.forEach(({ name, props }) => {
559
+ test(name, () => {
560
+ const component = React.createElement(ComponentClass, props);
561
+ const serialized = ComponentTransformer.serialize(component);
562
+ const deserialized = ComponentTransformer.deserialize(serialized);
563
+
564
+ expect(deserialized).toBeTruthy();
565
+ expect(JSON.parse(serialized).tag).toBe(ComponentClass.tagName);
566
+ });
567
+ });
568
+ });
569
+ }
570
+ ```
571
+
572
+ ## File Structure
573
+
574
+ ```
575
+ src/schemas/
576
+ ├── README.md # This file
577
+ ├── index.ts # Main exports
578
+ ├── types/
579
+ │ └── Serializable.ts # Core serialization interfaces
580
+ ├── transformers/
581
+ │ ├── ComponentTransformer.ts # Primary serialization engine
582
+ │ ├── ReactNodeTransformer.ts # Fallback transformer
583
+ │ ├── registry.ts # Component registration utilities
584
+ │ └── __tests__/ # Comprehensive test suites
585
+ ├── models/ # Schema model definitions
586
+ │ ├── CodeSchema.ts # Code component schema
587
+ │ └── [Other component schemas]
588
+ └── utils/
589
+ └── serializationUtils.ts # Utility functions
590
+ ```
591
+
592
+ ## Migration Guide
593
+
594
+ ### From Non-Serializable Components
595
+
596
+ 1. **Convert to Class Component** (if functional)
597
+ 2. **Implement Serializable Interface**
598
+ 3. **Add Static Properties** (tagName, version, fromJson)
599
+ 4. **Implement toJson Method**
600
+ 5. **Preserve Data Binding** (if applicable)
601
+ 6. **Add Comprehensive Tests**
602
+
603
+ See: [Component Serialization Migration Guide](/docs/SERIALIZATION_MIGRATION.md)
604
+
605
+ ## Best Practices
606
+
607
+ ### Implementation Guidelines
608
+ - Use semantic versioning for component evolution
609
+ - Always preserve `dataSource` and `bindingOptions` in serialization
610
+ - Exclude function props from serialization
611
+ - Handle edge cases with proper validation
612
+ - Implement comprehensive error handling
613
+ - Test with realistic data sizes and structures
614
+
615
+ ### Performance Guidelines
616
+ - Cache expensive serialization operations
617
+ - Use memoization for repeated transformations
618
+ - Implement lazy evaluation where possible
619
+ - Monitor memory usage in production
620
+ - Provide fallbacks for performance degradation
621
+
622
+ ### Security Guidelines
623
+ - Validate all deserialized data
624
+ - Sanitize user-generated content
625
+ - Use safe fallback components for unknown data
626
+ - Implement Content Security Policy compatibility
627
+ - Avoid eval() or similar unsafe operations
628
+
629
+ ## Contributing
630
+
631
+ ### Component Registration
632
+ New serializable components are automatically registered when imported. Follow the established patterns:
633
+
634
+ 1. **Implement Serializable interface**
635
+ 2. **Follow naming conventions** (PascalCase tagName)
636
+ 3. **Use semantic versioning**
637
+ 4. **Include comprehensive tests**
638
+ 5. **Document serialization behavior**
639
+
640
+ ### Testing Requirements
641
+ All serializable components must include:
642
+ - Basic serialization/deserialization tests
643
+ - Edge case handling tests
644
+ - Performance benchmark tests
645
+ - Data binding preservation tests (if applicable)
646
+ - Cross-browser compatibility validation
647
+
648
+ ## References
649
+
650
+ - [Component Serialization Guide](/docs/COMPONENT_SERIALIZATION_GUIDE.md) - Complete implementation guide
651
+ - [Serializable Component Templates](/docs/SERIALIZABLE_COMPONENT_TEMPLATE.md) - Copy-paste boilerplate
652
+ - [Architecture Documentation](/ARCHITECTURE.md#component-serialization-system-architecture) - System architecture
653
+ - [Code Component README](/src/components/blocks/Code.md) - Reference implementation
654
+
655
+ ---
656
+
657
+ ## License
658
+
659
+ Copyright (c) 2025 QwickApps.com. All rights reserved.
660
+
661
+ The QwickApps Schema System enables powerful "WebView for React" functionality while maintaining component integrity, performance, and developer experience across the entire framework ecosystem.
@@ -7,6 +7,7 @@
7
7
  import { IsOptional, IsString, IsIn } from 'class-validator';
8
8
  import 'reflect-metadata';
9
9
  import { Editor, Field, Schema, Model, FieldType } from '@qwickapps/schema';
10
+ import { ReactNode } from 'react';
10
11
 
11
12
  @Schema('Section', '1.0.0')
12
13
  export class SectionModel extends Model {
@@ -19,7 +20,7 @@ export class SectionModel extends Model {
19
20
  })
20
21
  @IsOptional()
21
22
  @IsString()
22
- children?: string;
23
+ children?: ReactNode | string;
23
24
 
24
25
  @Field()
25
26
  @Editor({