@qwickapps/react-framework 1.3.5 → 1.4.1

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 +1691 -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
@@ -1,15 +1,17 @@
1
1
  /**
2
- * SelectInputField - Select dropdown component with data binding support
2
+ * SelectInputField - Select dropdown component with serialization support
3
3
  *
4
- * Provides a standardized select field with:
4
+ * Features:
5
+ * - Complete select dropdown functionality with options
6
+ * - Form validation and error handling
7
+ * - Data binding support for dynamic content
8
+ * - Full serialization support via ModelView
5
9
  * - Consistent Material-UI styling
6
- * - Data binding capabilities
7
- * - Comprehensive option support
8
- * - Focus and error handling
9
10
  *
10
11
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
11
12
  */
12
13
 
14
+ import React, { ReactElement } from 'react';
13
15
  import {
14
16
  FormControl,
15
17
  FormHelperText,
@@ -21,9 +23,9 @@ import {
21
23
  Typography
22
24
  } from '@mui/material';
23
25
  import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
24
- import { QWICKAPP_COMPONENT, useBaseProps } from '../../hooks';
25
- import { useDataBinding } from '../../hooks';
26
+ import { QWICKAPP_COMPONENT, useBaseProps, useDataBinding } from '../../hooks';
26
27
  import SelectInputFieldModel, { SelectOption } from '../../schemas/SelectInputFieldSchema';
28
+ import { ModelView } from '../base/ModelView';
27
29
 
28
30
  type SelectInputFieldViewProps = ModelProps<SelectInputFieldModel> & {
29
31
  /** Change handler */
@@ -129,21 +131,51 @@ function SelectInputFieldView({
129
131
  );
130
132
  }
131
133
 
132
- /**
133
- * SelectInputField component with data binding support
134
- * Supports both traditional props and dataSource-driven rendering
135
- */
136
- function SelectInputField(props: SelectInputFieldProps) {
137
- const { dataSource, bindingOptions, ...restProps } = props;
134
+ // Main component with data binding support and serialization capability
135
+ export class SelectInputField extends ModelView<SelectInputFieldProps, SelectInputFieldModel> {
136
+ // Component self-declaration for serialization
137
+ static readonly tagName = 'SelectInputField';
138
+ static readonly version = '1.0.0';
139
+
140
+ // Deserialization: JSON data → React element
141
+ static fromJson(jsonData: any): ReactElement {
142
+ return <SelectInputField {...jsonData} />;
143
+ }
144
+
145
+ // Component-specific serialization properties
146
+ protected getComponentSpecificProps(): any {
147
+ return {
148
+ label: this.props.label,
149
+ value: this.props.value,
150
+ options: this.props.options,
151
+ required: this.props.required,
152
+ disabled: this.props.disabled,
153
+ error: this.props.error,
154
+ helperText: this.props.helperText,
155
+ placeholder: this.props.placeholder,
156
+ // Event handlers don't serialize
157
+ };
158
+ }
138
159
 
139
- // If no dataSource, use traditional props
140
- if (!dataSource) {
160
+ // SelectInputField component renders traditional props view
161
+ protected renderView(): React.ReactElement {
162
+ const { dataSource, bindingOptions, ...restProps } = this.props;
141
163
  return <SelectInputFieldView {...restProps} />;
142
164
  }
143
165
 
166
+ // SelectInputField component renders data-bound view
167
+ protected renderWithDataBinding(): React.ReactElement {
168
+ return <SelectInputFieldWithDataBinding {...this.props} />;
169
+ }
170
+ }
171
+
172
+ // Helper component to handle data binding with hooks (since we can't use hooks in class components)
173
+ function SelectInputFieldWithDataBinding(props: SelectInputFieldProps) {
174
+ const { dataSource, bindingOptions, ...restProps } = props;
175
+
144
176
  // Use data binding
145
177
  const { dataSource: _source, loading, error, cached, ...selectInputFieldProps } = useDataBinding<SelectInputFieldModel>(
146
- dataSource,
178
+ dataSource!,
147
179
  restProps as Partial<SelectInputFieldModel>,
148
180
  SelectInputFieldModel.getSchema(),
149
181
  { cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
@@ -1,16 +1,17 @@
1
1
  /**
2
- * SwitchInputField - Switch toggle component with data binding support
2
+ * SwitchInputField - Switch toggle component with serialization support
3
3
  *
4
- * Provides a standardized switch field with:
4
+ * Features:
5
+ * - Complete switch toggle functionality
6
+ * - Form validation and error handling
7
+ * - Data binding support for dynamic content
8
+ * - Full serialization support via ModelView
5
9
  * - Consistent Material-UI styling
6
- * - Data binding capabilities
7
- * - Label and helper text support
8
- * - Focus and error handling
9
10
  *
10
11
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
11
12
  */
12
13
 
13
- import React from 'react';
14
+ import React, { ReactElement } from 'react';
14
15
  import {
15
16
  FormControl,
16
17
  FormControlLabel,
@@ -20,9 +21,9 @@ import {
20
21
  Typography
21
22
  } from '@mui/material';
22
23
  import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
23
- import { QWICKAPP_COMPONENT, useBaseProps } from '../../hooks';
24
- import { useDataBinding } from '../../hooks';
24
+ import { QWICKAPP_COMPONENT, useBaseProps, useDataBinding } from '../../hooks';
25
25
  import SwitchInputFieldModel from '../../schemas/SwitchInputFieldSchema';
26
+ import { ModelView } from '../base/ModelView';
26
27
 
27
28
  type SwitchInputFieldViewProps = ModelProps<SwitchInputFieldModel> & {
28
29
  /** Change handler */
@@ -90,21 +91,51 @@ function SwitchInputFieldView({
90
91
  );
91
92
  }
92
93
 
93
- /**
94
- * SwitchInputField component with data binding support
95
- * Supports both traditional props and dataSource-driven rendering
96
- */
97
- function SwitchInputField(props: SwitchInputFieldProps) {
98
- const { dataSource, bindingOptions, ...restProps } = props;
94
+ // Main component with data binding support and serialization capability
95
+ export class SwitchInputField extends ModelView<SwitchInputFieldProps, SwitchInputFieldModel> {
96
+ // Component self-declaration for serialization
97
+ static readonly tagName = 'SwitchInputField';
98
+ static readonly version = '1.0.0';
99
+
100
+ // Deserialization: JSON data → React element
101
+ static fromJson(jsonData: any): ReactElement {
102
+ return <SwitchInputField {...jsonData} />;
103
+ }
104
+
105
+ // Component-specific serialization properties
106
+ protected getComponentSpecificProps(): any {
107
+ return {
108
+ label: this.props.label,
109
+ checked: this.props.checked,
110
+ required: this.props.required,
111
+ disabled: this.props.disabled,
112
+ error: this.props.error,
113
+ helperText: this.props.helperText,
114
+ size: this.props.size,
115
+ color: this.props.color,
116
+ // Event handlers don't serialize
117
+ };
118
+ }
99
119
 
100
- // If no dataSource, use traditional props
101
- if (!dataSource) {
120
+ // SwitchInputField component renders traditional props view
121
+ protected renderView(): React.ReactElement {
122
+ const { dataSource, bindingOptions, ...restProps } = this.props;
102
123
  return <SwitchInputFieldView {...restProps} />;
103
124
  }
104
125
 
126
+ // SwitchInputField component renders data-bound view
127
+ protected renderWithDataBinding(): React.ReactElement {
128
+ return <SwitchInputFieldWithDataBinding {...this.props} />;
129
+ }
130
+ }
131
+
132
+ // Helper component to handle data binding with hooks (since we can't use hooks in class components)
133
+ function SwitchInputFieldWithDataBinding(props: SwitchInputFieldProps) {
134
+ const { dataSource, bindingOptions, ...restProps } = props;
135
+
105
136
  // Use data binding
106
137
  const bindingResult = useDataBinding<SwitchInputFieldModel>(
107
- dataSource,
138
+ dataSource!,
108
139
  restProps as Partial<SwitchInputFieldModel>,
109
140
  SwitchInputFieldModel.getSchema(),
110
141
  { cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
@@ -20,13 +20,53 @@ export interface TextFieldProps extends WithBaseProps<Omit<MuiTextFieldProps, 's
20
20
  export const TextField = React.forwardRef<HTMLDivElement, TextFieldProps>((props, ref) => {
21
21
  const { gridProps, styleProps, htmlProps, restProps } = useBaseProps(props);
22
22
 
23
+ // Extract commonly used props we may inspect
24
+ const { placeholder, value, defaultValue, slotProps, InputLabelProps, InputProps, variant = 'outlined', ...other } = restProps as any;
25
+
26
+ // Determine whether label should shrink automatically when a placeholder is shown.
27
+ // MUI does not shrink the label for outlined variant with just a placeholder (and empty value) by default.
28
+ // We standardize that behavior for consistency across admin surfaces.
29
+ const hasContent = (() => {
30
+ if (value != null && value !== '') return true;
31
+ if (defaultValue != null && defaultValue !== '') return true;
32
+ return false;
33
+ })();
34
+
35
+ const autoShrink = !!placeholder && !hasContent;
36
+
37
+ // Allow explicit user override: if consumer supplied slotProps.inputLabel.shrink or InputLabelProps.shrink, respect it.
38
+ const userShrink = slotProps?.inputLabel?.shrink ?? InputLabelProps?.shrink;
39
+ const finalShrink = userShrink !== undefined ? userShrink : autoShrink;
40
+
41
+ const mergedSlotProps = {
42
+ ...slotProps,
43
+ inputLabel: {
44
+ ...(slotProps?.inputLabel || {}),
45
+ ...(finalShrink ? { shrink: true } : {}),
46
+ },
47
+ };
48
+
49
+ // Prepare InputProps (for OutlinedInput) to ensure notch appears when we auto-shrink.
50
+ let mergedInputProps = InputProps || {};
51
+ if (variant === 'outlined' && finalShrink && placeholder && !hasContent) {
52
+ if (mergedInputProps.notched === undefined) {
53
+ mergedInputProps = { ...mergedInputProps, notched: true };
54
+ }
55
+ }
56
+
23
57
  // Mark as QwickApp component
24
58
  (TextField as any)[QWICKAPP_COMPONENT] = true;
25
59
 
26
60
  return (
27
61
  <MuiTextField
28
62
  ref={ref}
29
- {...restProps}
63
+ placeholder={placeholder}
64
+ value={value}
65
+ defaultValue={defaultValue}
66
+ variant={variant}
67
+ slotProps={mergedSlotProps}
68
+ InputProps={mergedInputProps}
69
+ {...other}
30
70
  {...htmlProps}
31
71
  {...styleProps}
32
72
  // Store grid props as data attributes for ColumnLayout to pick up
@@ -1,22 +1,22 @@
1
1
  /**
2
- * TextInputField - Reusable text input component with consistent styling
2
+ * TextInputField - Reusable text input component with serialization support
3
3
  *
4
- * Provides a standardized text field with:
4
+ * Features:
5
+ * - Complete text field functionality (single/multiline, input types)
6
+ * - Form validation and error handling
7
+ * - Data binding support for dynamic content
8
+ * - Full serialization support via ModelView
5
9
  * - Consistent Material-UI styling
6
- * - Data binding support
7
- * - Focus handling
8
- * - Validation and error states
9
- * - Support for multiline/textarea mode
10
10
  *
11
11
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
12
12
  */
13
13
 
14
- import React from 'react';
14
+ import React, { ReactElement } from 'react';
15
15
  import { TextField, TextFieldProps, Paper, Typography } from '@mui/material';
16
16
  import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
17
- import { QWICKAPP_COMPONENT, useBaseProps } from '../../hooks';
18
- import { useDataBinding } from '../../hooks';
17
+ import { QWICKAPP_COMPONENT, useBaseProps, useDataBinding } from '../../hooks';
19
18
  import TextInputFieldModel from '../../schemas/TextInputFieldSchema';
19
+ import { ModelView } from '../base/ModelView';
20
20
 
21
21
  type TextInputFieldViewProps = ModelProps<TextInputFieldModel> & {
22
22
  /** Change handler */
@@ -76,21 +76,55 @@ function TextInputFieldView({
76
76
  );
77
77
  }
78
78
 
79
- /**
80
- * TextInputField component with data binding support
81
- * Supports both traditional props and dataSource-driven rendering
82
- */
83
- function TextInputField(props: TextInputFieldProps) {
84
- const { dataSource, bindingOptions, ...restProps } = props;
79
+ // Main component with data binding support and serialization capability
80
+ export class TextInputField extends ModelView<TextInputFieldProps, TextInputFieldModel> {
81
+ // Component self-declaration for serialization
82
+ static readonly tagName = 'TextInputField';
83
+ static readonly version = '1.0.0';
84
+
85
+ // Deserialization: JSON data → React element
86
+ static fromJson(jsonData: any): ReactElement {
87
+ return <TextInputField {...jsonData} />;
88
+ }
89
+
90
+ // Component-specific serialization properties
91
+ protected getComponentSpecificProps(): any {
92
+ return {
93
+ label: this.props.label,
94
+ value: this.props.value,
95
+ required: this.props.required,
96
+ disabled: this.props.disabled,
97
+ error: this.props.error,
98
+ helperText: this.props.helperText,
99
+ placeholder: this.props.placeholder,
100
+ type: this.props.type,
101
+ multiline: this.props.multiline,
102
+ rows: this.props.rows,
103
+ maxRows: this.props.maxRows,
104
+ // Event handlers don't serialize
105
+ // textFieldProps don't serialize (they're component-specific overrides)
106
+ };
107
+ }
85
108
 
86
- // If no dataSource, use traditional props
87
- if (!dataSource) {
109
+ // TextInputField component renders traditional props view
110
+ protected renderView(): React.ReactElement {
111
+ const { dataSource, bindingOptions, ...restProps } = this.props;
88
112
  return <TextInputFieldView {...restProps} />;
89
113
  }
90
114
 
115
+ // TextInputField component renders data-bound view
116
+ protected renderWithDataBinding(): React.ReactElement {
117
+ return <TextInputFieldWithDataBinding {...this.props} />;
118
+ }
119
+ }
120
+
121
+ // Helper component to handle data binding with hooks (since we can't use hooks in class components)
122
+ function TextInputFieldWithDataBinding(props: TextInputFieldProps) {
123
+ const { dataSource, bindingOptions, ...restProps } = props;
124
+
91
125
  // Use data binding
92
126
  const { dataSource: _source, loading, error, cached, ...textInputFieldProps } = useDataBinding<TextInputFieldModel>(
93
- dataSource,
127
+ dataSource!,
94
128
  restProps as Partial<TextInputFieldModel>,
95
129
  TextInputFieldModel.getSchema(),
96
130
  { cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
@@ -1,25 +1,37 @@
1
1
  /**
2
- * GridCell - Simple cell wrapper for GridLayout
2
+ * GridCell - Simple cell wrapper for GridLayout with serialization support
3
3
  *
4
4
  * A lightweight wrapper that applies grid props to any content
5
5
  * Uses the base props pattern for consistency
6
+ * Full serialization support via ModelView including nested components
7
+ *
8
+ * Usage:
9
+ * - Traditional: <GridCell span={6} background="primary">...</GridCell>
10
+ * - Data-driven: <GridCell dataSource="layout.cell" />
11
+ * - Serializable: ComponentTransformer.serialize(<GridCell ... />)
6
12
  *
7
13
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
14
  */
9
15
 
10
- import React from 'react';
16
+ import React, { ReactElement, ReactNode } from 'react';
11
17
  import { Box } from '@mui/material';
18
+ import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
12
19
  import { useBaseProps, WithBaseProps, QWICKAPP_COMPONENT } from '../../hooks/useBaseProps';
20
+ import { useDataBinding } from '../../hooks';
21
+ import GridCellModel from '../../schemas/GridCellSchema';
22
+ import { ModelView } from '../base/ModelView';
23
+ import { ComponentTransformer } from '../../schemas/transformers/ComponentTransformer';
13
24
 
14
- export interface GridCellProps extends WithBaseProps {
15
- children: React.ReactNode;
16
- }
25
+ type GridCellViewProps = ModelProps<GridCellModel>;
26
+
27
+ export interface GridCellProps extends GridCellViewProps, WithDataBinding {}
17
28
 
18
- export const GridCell: React.FC<GridCellProps> = (props) => {
29
+ // View component - handles the actual rendering
30
+ function GridCellView(props: GridCellViewProps) {
19
31
  const { gridProps, styleProps, htmlProps, restProps } = useBaseProps(props);
20
32
 
21
33
  // Mark as QwickApp component
22
- (GridCell as any)[QWICKAPP_COMPONENT] = true;
34
+ (GridCellView as any)[QWICKAPP_COMPONENT] = true;
23
35
 
24
36
  return (
25
37
  <Box
@@ -39,8 +51,105 @@ export const GridCell: React.FC<GridCellProps> = (props) => {
39
51
  {(restProps as any).children}
40
52
  </Box>
41
53
  );
42
- };
54
+ }
55
+
56
+ // Main component with data binding support and serialization capability
57
+ export class GridCell extends ModelView<GridCellProps, GridCellModel> {
58
+ // Component self-declaration for serialization
59
+ static readonly tagName = 'GridCell';
60
+ static readonly version = '1.0.0';
61
+
62
+ // Deserialization: JSON data → React element
63
+ static fromJson(jsonData: any): ReactElement {
64
+ return <GridCell {...jsonData} />;
65
+ }
66
+
67
+ // Component-specific serialization properties
68
+ protected getComponentSpecificProps(): any {
69
+ return {
70
+ // Grid responsive properties
71
+ span: this.props.span,
72
+ xs: this.props.xs,
73
+ sm: this.props.sm,
74
+ md: this.props.md,
75
+ lg: this.props.lg,
76
+ xl: this.props.xl,
77
+ // Styling properties
78
+ background: this.props.background,
79
+ padding: this.props.padding,
80
+ margin: this.props.margin,
81
+ height: this.props.height,
82
+ width: this.props.width,
83
+ className: this.props.className
84
+ };
85
+ }
86
+
87
+ // GridCell supports nested components
88
+ protected hasNestedComponents(children: ReactNode): boolean {
89
+ return true;
90
+ }
91
+
92
+ // Override serializeChildren to handle nested components properly
93
+ protected serializeChildren(children: ReactNode): any {
94
+ if (typeof children === 'string') {
95
+ return children;
96
+ }
97
+
98
+ if (children !== undefined) {
99
+ return ComponentTransformer.serialize(children);
100
+ }
101
+
102
+ return undefined;
103
+ }
104
+
105
+ // GridCell component renders traditional props view
106
+ protected renderView(): React.ReactElement {
107
+ const { dataSource, bindingOptions, ...restProps } = this.props;
108
+ return <GridCellView {...restProps} />;
109
+ }
110
+
111
+ // GridCell component renders data-bound view
112
+ protected renderWithDataBinding(): React.ReactElement {
113
+ return <GridCellWithDataBinding {...this.props} />;
114
+ }
115
+ }
116
+
117
+ // Helper component to handle data binding with hooks (since we can't use hooks in class components)
118
+ function GridCellWithDataBinding(props: GridCellProps) {
119
+ const { dataSource, bindingOptions, ...restProps } = props;
120
+
121
+ // Use data binding
122
+ const { dataSource: _source, loading, error, cached, ...cellProps } = useDataBinding<GridCellModel>(
123
+ dataSource!,
124
+ restProps as Partial<GridCellModel>,
125
+ GridCellModel.getSchema(),
126
+ { cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
127
+ );
128
+
129
+ // Show loading state
130
+ if (loading) {
131
+ return (
132
+ <Box sx={{ p: 2, textAlign: 'center', opacity: 0.6 }}>
133
+ Loading Cell...
134
+ </Box>
135
+ );
136
+ }
137
+
138
+ if (error) {
139
+ console.error('Error loading grid cell:', error);
140
+ if (process.env.NODE_ENV !== 'production') {
141
+ return (
142
+ <Box sx={{ p: 2, textAlign: 'center', borderColor: 'error.main', border: 1 }}>
143
+ Error Loading Cell: {error.message}
144
+ </Box>
145
+ );
146
+ }
147
+ return null;
148
+ }
149
+
150
+ console.log('Resolved props for GridCell:', cellProps);
151
+ return <GridCellView {...cellProps} />;
152
+ }
43
153
 
44
- GridCell.displayName = 'GridCell';
45
154
 
46
155
  export default GridCell;
@@ -1,43 +1,40 @@
1
1
  /**
2
- * GridLayout - Flexible grid layout component
2
+ * GridLayout - Flexible grid layout component with serialization support
3
3
  *
4
4
  * Works with any component that has grid props (span, xs, sm, md, lg, xl)
5
5
  * Automatically wraps components in Grid when grid props are detected
6
+ * Full serialization support via ModelView including nested components
7
+ *
8
+ * Usage:
9
+ * - Traditional: <GridLayout columns={3} spacing="medium">...</GridLayout>
10
+ * - Data-driven: <GridLayout dataSource="layouts.main" />
11
+ * - Serializable: ComponentTransformer.serialize(<GridLayout ... />)
6
12
  *
7
13
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
14
  */
9
15
 
10
- import React from 'react';
16
+ import React, { ReactElement, ReactNode } from 'react';
11
17
  import { Grid, SxProps, Theme } from '@mui/material';
18
+ import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
12
19
  import { SpacingValue, resolveSpacing } from '../../utils/spacing';
13
20
  import { DimensionValue, resolveDimension } from '../../utils/dimensions';
14
21
  import { QWICKAPP_COMPONENT } from '../../hooks/useBaseProps';
22
+ import { useDataBinding } from '../../hooks';
23
+ import GridLayoutModel from '../../schemas/GridLayoutSchema';
24
+ import { ModelView } from '../base/ModelView';
25
+ import { ComponentTransformer } from '../../schemas/transformers/ComponentTransformer';
15
26
 
16
- export interface GridLayoutProps {
17
- /** Layout children - any components with grid props work */
18
- children: React.ReactNode;
19
- /** Number of equal-width columns (auto-distribution) */
20
- columns?: 1 | 2 | 3 | 4 | 5 | 6;
21
- /** Spacing between columns */
22
- spacing?: SpacingValue;
23
- /** Equal height columns */
24
- equalHeight?: boolean;
25
- /** Layout dimensions */
26
- height?: DimensionValue;
27
- width?: DimensionValue;
28
- minHeight?: DimensionValue;
29
- minWidth?: DimensionValue;
30
- maxHeight?: DimensionValue;
31
- maxWidth?: DimensionValue;
32
- /** Additional CSS class */
33
- className?: string;
27
+ type GridLayoutViewProps = ModelProps<GridLayoutModel> & {
34
28
  /** Custom styles */
35
29
  sx?: SxProps<Theme>;
36
30
  /** Inline styles */
37
31
  style?: React.CSSProperties;
38
- }
32
+ };
33
+
34
+ export interface GridLayoutProps extends GridLayoutViewProps, WithDataBinding {}
39
35
 
40
- export const GridLayout: React.FC<GridLayoutProps> = ({
36
+ // View component - handles the actual rendering
37
+ function GridLayoutView({
41
38
  children,
42
39
  columns,
43
40
  spacing = 'small',
@@ -51,7 +48,11 @@ export const GridLayout: React.FC<GridLayoutProps> = ({
51
48
  className,
52
49
  sx,
53
50
  style,
54
- }) => {
51
+ ...restProps
52
+ }: GridLayoutViewProps) {
53
+ // Mark as QwickApp component
54
+ (GridLayoutView as any)[QWICKAPP_COMPONENT] = true;
55
+
55
56
  const resolvedSpacing = resolveSpacing(spacing, 'gap');
56
57
 
57
58
  // Process children to handle grid props
@@ -164,6 +165,106 @@ export const GridLayout: React.FC<GridLayoutProps> = ({
164
165
  {processChildren()}
165
166
  </Grid>
166
167
  );
167
- };
168
+ }
169
+
170
+ // Main component with data binding support and serialization capability
171
+ export class GridLayout extends ModelView<GridLayoutProps, GridLayoutModel> {
172
+ // Component self-declaration for serialization
173
+ static readonly tagName = 'GridLayout';
174
+ static readonly version = '1.0.0';
175
+
176
+ // Deserialization: JSON data → React element
177
+ static fromJson(jsonData: any): ReactElement {
178
+ return <GridLayout {...jsonData} />;
179
+ }
180
+
181
+ // Component-specific serialization properties
182
+ protected getComponentSpecificProps(): any {
183
+ return {
184
+ columns: this.props.columns,
185
+ spacing: this.props.spacing,
186
+ equalHeight: this.props.equalHeight,
187
+ height: this.props.height,
188
+ width: this.props.width,
189
+ minHeight: this.props.minHeight,
190
+ minWidth: this.props.minWidth,
191
+ maxHeight: this.props.maxHeight,
192
+ maxWidth: this.props.maxWidth,
193
+ className: this.props.className,
194
+ style: this.props.style,
195
+ sx: this.props.sx
196
+ };
197
+ }
198
+
199
+ // GridLayout supports nested components
200
+ protected hasNestedComponents(children: ReactNode): boolean {
201
+ return true;
202
+ }
203
+
204
+ // Override serializeChildren to handle nested components properly
205
+ protected serializeChildren(children: ReactNode): any {
206
+ if (typeof children === 'string') {
207
+ return children;
208
+ }
209
+
210
+ if (children !== undefined) {
211
+ return ComponentTransformer.serialize(children);
212
+ }
213
+
214
+ return undefined;
215
+ }
216
+
217
+ // GridLayout component renders traditional props view
218
+ protected renderView(): React.ReactElement {
219
+ const { dataSource, bindingOptions, ...restProps } = this.props;
220
+ return <GridLayoutView {...restProps} />;
221
+ }
222
+
223
+ // GridLayout component renders data-bound view
224
+ protected renderWithDataBinding(): React.ReactElement {
225
+ return <GridLayoutWithDataBinding {...this.props} />;
226
+ }
227
+ }
228
+
229
+ // Helper component to handle data binding with hooks (since we can't use hooks in class components)
230
+ function GridLayoutWithDataBinding(props: GridLayoutProps) {
231
+ const { dataSource, bindingOptions, ...restProps } = props;
232
+
233
+ // Use data binding
234
+ const { dataSource: _source, loading, error, cached, ...gridProps } = useDataBinding<GridLayoutModel>(
235
+ dataSource!,
236
+ restProps as Partial<GridLayoutModel>,
237
+ GridLayoutModel.getSchema(),
238
+ { cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
239
+ );
240
+
241
+ // Show loading state
242
+ if (loading) {
243
+ return (
244
+ <Grid container sx={{ p: 3, textAlign: 'center' }}>
245
+ <Grid size={12}>
246
+ Loading Grid Layout...
247
+ </Grid>
248
+ </Grid>
249
+ );
250
+ }
251
+
252
+ if (error) {
253
+ console.error('Error loading grid layout:', error);
254
+ if (process.env.NODE_ENV !== 'production') {
255
+ return (
256
+ <Grid container sx={{ p: 3, textAlign: 'center', borderColor: 'error.main', border: 1 }}>
257
+ <Grid size={12}>
258
+ Error Loading Grid Layout: {error.message}
259
+ </Grid>
260
+ </Grid>
261
+ );
262
+ }
263
+ return null;
264
+ }
265
+
266
+ console.log('Resolved props for GridLayout:', gridProps);
267
+ return <GridLayoutView {...gridProps} />;
268
+ }
168
269
 
169
270
  export default GridLayout;