@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
@@ -0,0 +1,332 @@
1
+ /**
2
+ * PrintModeContext - App-level print state management
3
+ *
4
+ * Handles print mode state transitions at the application level,
5
+ * allowing pages to simply consume and react to print state changes.
6
+ *
7
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
+ */
9
+
10
+ import React, { createContext, useContext, useCallback, useReducer, useEffect } from 'react';
11
+ import { useQwickApp } from './QwickAppContext';
12
+ import { useTheme } from './ThemeContext';
13
+ import { usePalette } from './PaletteContext';
14
+ import { PrintConfigSchema } from '../schemas/PrintConfigSchema';
15
+
16
+ export type PrintModeStateType =
17
+ | 'normal'
18
+ | 'applying_print_config'
19
+ | 'entering_print_mode'
20
+ | 'view_loading'
21
+ | 'config_applied'
22
+ | 'print_mode'
23
+ | 'exiting_print_mode'
24
+ | 'restoring_config';
25
+
26
+ interface PrintModeState {
27
+ printModeState: PrintModeStateType;
28
+ printConfig: PrintConfigSchema;
29
+ originalTheme: string | null;
30
+ originalPalette: string | null;
31
+ }
32
+
33
+ type PrintModeAction =
34
+ | { type: 'TRIGGER_PRINT'; config?: Partial<PrintConfigSchema> }
35
+ | { type: 'APPLY_CONFIG' }
36
+ | { type: 'ENTER_PRINT_MODE' }
37
+ | { type: 'VIEW_LOADING' }
38
+ | { type: 'VIEW_READY' }
39
+ | { type: 'CONFIG_APPLIED' }
40
+ | { type: 'EXIT_PRINT_MODE' }
41
+ | { type: 'RESTORE_CONFIG' }
42
+ | { type: 'RETURN_TO_NORMAL' }
43
+ | { type: 'SET_ORIGINAL_THEME'; theme: string }
44
+ | { type: 'SET_ORIGINAL_PALETTE'; palette: string };
45
+
46
+ const DEFAULT_PRINT_CONFIG: PrintConfigSchema = {
47
+ theme: 'light',
48
+ palette: undefined,
49
+ hideScaffolding: true,
50
+ hideInteractiveElements: false,
51
+ optimizeForMonochrome: false,
52
+ showPrintDate: true,
53
+ pageMargins: '12mm',
54
+ };
55
+
56
+ function printModeReducer(state: PrintModeState, action: PrintModeAction): PrintModeState {
57
+
58
+ switch (action.type) {
59
+ case 'TRIGGER_PRINT':
60
+ if (state.printModeState === 'normal') {
61
+ return {
62
+ ...state,
63
+ printModeState: 'applying_print_config',
64
+ printConfig: action.config ? { ...DEFAULT_PRINT_CONFIG, ...action.config } : DEFAULT_PRINT_CONFIG,
65
+ };
66
+ }
67
+ return state;
68
+
69
+ case 'APPLY_CONFIG':
70
+ if (state.printModeState === 'applying_print_config') {
71
+ return { ...state, printModeState: 'entering_print_mode' };
72
+ }
73
+ return state;
74
+
75
+ case 'VIEW_LOADING':
76
+ // Can transition to view_loading from entering_print_mode
77
+ // Ignore if already in view_loading or other states
78
+ if (state.printModeState === 'entering_print_mode') {
79
+ return { ...state, printModeState: 'view_loading' };
80
+ }
81
+ return state;
82
+
83
+ case 'VIEW_READY':
84
+ // Can transition to config_applied from view_loading, then wait for theme/palette changes
85
+ if (state.printModeState === 'view_loading') {
86
+ return { ...state, printModeState: 'config_applied' };
87
+ } else if (state.printModeState === 'exiting_print_mode') {
88
+ return { ...state, printModeState: 'restoring_config' };
89
+ }
90
+ return state;
91
+
92
+ case 'CONFIG_APPLIED':
93
+ if (state.printModeState === 'config_applied') {
94
+ return { ...state, printModeState: 'print_mode' };
95
+ }
96
+ return state;
97
+
98
+ case 'EXIT_PRINT_MODE':
99
+ // Exit from any print-related state
100
+ if (state.printModeState !== 'normal' && state.printModeState !== 'exiting_print_mode' && state.printModeState !== 'restoring_config') {
101
+ return { ...state, printModeState: 'exiting_print_mode' };
102
+ }
103
+ return state;
104
+
105
+ case 'RESTORE_CONFIG':
106
+ if (state.printModeState === 'restoring_config') {
107
+ return { ...state, printModeState: 'normal' };
108
+ }
109
+ return state;
110
+
111
+ case 'SET_ORIGINAL_THEME':
112
+ return { ...state, originalTheme: action.theme };
113
+
114
+ case 'SET_ORIGINAL_PALETTE':
115
+ return { ...state, originalPalette: action.palette };
116
+
117
+ default:
118
+ return state;
119
+ }
120
+ }
121
+
122
+ interface PrintModeContextValue {
123
+ // State
124
+ printModeState: PrintModeStateType;
125
+ isPrintMode: boolean;
126
+ printConfig: PrintConfigSchema;
127
+
128
+ // Actions
129
+ triggerPrint: (config?: Partial<PrintConfigSchema>) => void;
130
+ exitPrintMode: () => void;
131
+ onViewLoading: () => void;
132
+ onViewReady: () => void;
133
+ }
134
+
135
+ const PrintModeContext = createContext<PrintModeContextValue | null>(null);
136
+
137
+ export const usePrintMode = (): PrintModeContextValue => {
138
+ const context = useContext(PrintModeContext);
139
+ if (!context) {
140
+ throw new Error('usePrintMode must be used within a PrintModeProvider');
141
+ }
142
+ return context;
143
+ };
144
+
145
+ interface PrintModeProviderProps {
146
+ children: React.ReactNode;
147
+ }
148
+
149
+ export const PrintModeProvider: React.FC<PrintModeProviderProps> = ({ children }) => {
150
+ const [state, dispatch] = useReducer(printModeReducer, {
151
+ printModeState: 'normal',
152
+ printConfig: DEFAULT_PRINT_CONFIG,
153
+ originalTheme: null,
154
+ originalPalette: null,
155
+ });
156
+
157
+ const { updateConfig: updateQwickAppConfig } = useQwickApp();
158
+ const { setCurrentTheme, getCurrentTheme } = useTheme();
159
+ const { setCurrentPalette, getCurrentPalette } = usePalette();
160
+
161
+ // Computed derived state - only true when actually in print view
162
+ const isPrintMode = state.printModeState === 'entering_print_mode' ||
163
+ state.printModeState === 'view_loading' ||
164
+ state.printModeState === 'config_applied' ||
165
+ state.printModeState === 'print_mode';
166
+
167
+ // Actions
168
+ const triggerPrint = useCallback((config?: Partial<PrintConfigSchema>) => {
169
+ dispatch({ type: 'TRIGGER_PRINT', config });
170
+ }, []);
171
+
172
+ const exitPrintMode = useCallback(() => {
173
+ dispatch({ type: 'EXIT_PRINT_MODE' });
174
+ }, []);
175
+
176
+ const onViewLoading = useCallback(() => {
177
+ dispatch({ type: 'VIEW_LOADING' });
178
+ }, []);
179
+
180
+ const onViewReady = useCallback(() => {
181
+ dispatch({ type: 'VIEW_READY' });
182
+ }, []);
183
+
184
+ // Effect to handle configuration application
185
+ useEffect(() => {
186
+ if (state.printModeState === 'applying_print_config') {
187
+ // Apply print configuration
188
+ if (state.printConfig.hideScaffolding) {
189
+ updateQwickAppConfig({ enableScaffolding: false });
190
+ }
191
+
192
+ if (state.printConfig.theme) {
193
+ dispatch({ type: 'SET_ORIGINAL_THEME', theme: getCurrentTheme() });
194
+ setCurrentTheme(state.printConfig.theme as any);
195
+ }
196
+
197
+ if (state.printConfig.palette) {
198
+ dispatch({ type: 'SET_ORIGINAL_PALETTE', palette: getCurrentPalette() });
199
+ setCurrentPalette(state.printConfig.palette);
200
+ }
201
+
202
+ if (typeof document !== 'undefined') {
203
+ document.body.classList.add('print-mode');
204
+
205
+ if (state.printConfig.optimizeForMonochrome) {
206
+ document.body.classList.add('print-monochrome');
207
+ }
208
+
209
+ if (state.printConfig.hideInteractiveElements) {
210
+ document.body.classList.add('print-hide-interactive');
211
+ }
212
+
213
+ // Apply custom page margins if specified
214
+ if (state.printConfig.pageMargins && state.printConfig.pageMargins !== '12mm') {
215
+ let printStyleElement = document.querySelector('#qwick-print-margins');
216
+ if (!printStyleElement) {
217
+ printStyleElement = document.createElement('style');
218
+ printStyleElement.id = 'qwick-print-margins';
219
+ document.head.appendChild(printStyleElement);
220
+ }
221
+ printStyleElement.textContent = `
222
+ @media print {
223
+ @page {
224
+ margin: ${state.printConfig.pageMargins};
225
+ }
226
+ }
227
+ `;
228
+ }
229
+ }
230
+
231
+ // Transition to entering print mode
232
+ dispatch({ type: 'APPLY_CONFIG' });
233
+ }
234
+ }, [state.printModeState, state.printConfig, updateQwickAppConfig, getCurrentTheme, getCurrentPalette, setCurrentTheme, setCurrentPalette]);
235
+
236
+ // Effect to detect when theme/palette changes are complete
237
+ useEffect(() => {
238
+ if (state.printModeState === 'config_applied') {
239
+ // Wait one render cycle to ensure theme/palette changes are applied
240
+ const rafId = requestAnimationFrame(() => {
241
+ dispatch({ type: 'CONFIG_APPLIED' });
242
+ });
243
+
244
+ return () => cancelAnimationFrame(rafId);
245
+ }
246
+ }, [state.printModeState]);
247
+
248
+ // Effect to transition from exiting_print_mode to restoring_config
249
+ useEffect(() => {
250
+ if (state.printModeState === 'exiting_print_mode') {
251
+ // Use VIEW_READY action to transition to restoring_config
252
+ dispatch({ type: 'VIEW_READY' });
253
+ }
254
+ }, [state.printModeState]);
255
+
256
+ // Effect to handle configuration restoration
257
+ useEffect(() => {
258
+ if (state.printModeState === 'restoring_config') {
259
+ // Restore QwickApp configuration
260
+ updateQwickAppConfig({ enableScaffolding: true });
261
+
262
+ // Restore original theme and palette
263
+ if (state.originalTheme) {
264
+ setCurrentTheme(state.originalTheme as any);
265
+ }
266
+
267
+ if (state.originalPalette) {
268
+ setCurrentPalette(state.originalPalette);
269
+ }
270
+
271
+ // Remove print mode classes and custom styles
272
+ if (typeof document !== 'undefined') {
273
+ document.body.classList.remove('print-mode', 'print-monochrome', 'print-hide-interactive');
274
+
275
+ // Remove custom margins style
276
+ const printStyleElement = document.querySelector('#qwick-print-margins');
277
+ if (printStyleElement) {
278
+ printStyleElement.remove();
279
+ }
280
+ }
281
+
282
+ // Return to normal
283
+ dispatch({ type: 'RESTORE_CONFIG' });
284
+ }
285
+ }, [state.printModeState, state.originalTheme, state.originalPalette, updateQwickAppConfig, setCurrentTheme, setCurrentPalette]);
286
+
287
+ // Effect to handle print dialog
288
+ useEffect(() => {
289
+ if (state.printModeState === 'print_mode') {
290
+ if (typeof window !== 'undefined') {
291
+ window.print();
292
+ }
293
+ }
294
+ }, [state.printModeState]);
295
+
296
+ // Effect to handle browser print events (stable handlers using refs)
297
+ useEffect(() => {
298
+ const handleBeforePrint = () => {
299
+ triggerPrint();
300
+ };
301
+
302
+ const handleAfterPrint = () => {
303
+ exitPrintMode();
304
+ };
305
+
306
+ if (typeof window !== 'undefined') {
307
+ window.addEventListener('beforeprint', handleBeforePrint);
308
+ window.addEventListener('afterprint', handleAfterPrint);
309
+
310
+ return () => {
311
+ window.removeEventListener('beforeprint', handleBeforePrint);
312
+ window.removeEventListener('afterprint', handleAfterPrint);
313
+ };
314
+ }
315
+ }, []); // Empty dependency array for stable event handlers
316
+
317
+ const contextValue: PrintModeContextValue = {
318
+ printModeState: state.printModeState,
319
+ isPrintMode,
320
+ printConfig: state.printConfig,
321
+ triggerPrint,
322
+ exitPrintMode,
323
+ onViewLoading,
324
+ onViewReady,
325
+ };
326
+
327
+ return (
328
+ <PrintModeContext.Provider value={contextValue}>
329
+ {children}
330
+ </PrintModeContext.Provider>
331
+ );
332
+ };
@@ -12,8 +12,8 @@ import type { MenuItem } from '../components/menu';
12
12
  import type { ScaffoldProps } from '../components/Scaffold';
13
13
 
14
14
  export interface QwickAppProps {
15
- /** Application name displayed in header/title */
16
- appName: string;
15
+ /** Application name displayed in header/title (optional when config is provided) */
16
+ appName?: string;
17
17
  /** Custom logo component - overrides the default logo */
18
18
  logo?: React.ReactNode;
19
19
  /** App identifier used for storage keys */
@@ -7,3 +7,5 @@ export { PaletteProvider, usePalette } from './PaletteContext';
7
7
  export type { PaletteConfig, PaletteContextValue } from './PaletteContext';
8
8
  export { ThemeProvider, useTheme } from './ThemeContext';
9
9
  export type { ActualThemeMode, ThemeContextValue, ThemeMode } from './ThemeContext';
10
+ export { PrintModeProvider, usePrintMode } from './PrintModeContext';
11
+ export type { PrintModeStateType } from './PrintModeContext';
@@ -8,4 +8,8 @@ export type { BaseComponentProps, WithBaseProps } from './useBaseProps';
8
8
 
9
9
  // Data Binding hooks for AI-driven component system
10
10
  export { useDataBinding } from './useDataBinding';
11
- export { QWICKAPP_COMPONENT } from './useBaseProps';
11
+ export { QWICKAPP_COMPONENT } from './useBaseProps';
12
+
13
+ // Print mode detection and management (legacy hook - use PrintModeProvider instead)
14
+ export { usePrintMode as usePrintModeHook } from './usePrintMode';
15
+ export type { PrintModeState } from './usePrintMode';
@@ -0,0 +1,73 @@
1
+ /**
2
+ * usePrintMode hook - Simple wrapper around PrintModeContext
3
+ *
4
+ * @deprecated Use usePrintMode from PrintModeContext directly
5
+ * This file maintained for backward compatibility during migration
6
+ *
7
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
+ */
9
+
10
+ import { usePrintMode as usePrintModeContext } from '../contexts/PrintModeContext';
11
+ import { PrintConfigSchema } from '../schemas/PrintConfigSchema';
12
+
13
+ export type PrintModeStateType =
14
+ | 'normal'
15
+ | 'applying_print_config'
16
+ | 'entering_print_mode'
17
+ | 'view_loading'
18
+ | 'config_applied'
19
+ | 'print_mode'
20
+ | 'exiting_print_mode'
21
+ | 'restoring_config';
22
+
23
+ export interface PrintModeState {
24
+ /** Whether the app is currently in print mode */
25
+ isPrintMode: boolean;
26
+ /** Print configuration to apply */
27
+ printConfig: PrintConfigSchema;
28
+ /** Current state of the print mode state machine */
29
+ printModeState: PrintModeStateType;
30
+ /** Manually enter print mode */
31
+ enterPrintMode: (config?: Partial<PrintConfigSchema>) => void;
32
+ /** Exit print mode */
33
+ exitPrintMode: () => void;
34
+ /** Toggle print mode */
35
+ togglePrintMode: (config?: Partial<PrintConfigSchema>) => void;
36
+ /** Enter print mode and trigger print dialog */
37
+ triggerPrint: (config?: Partial<PrintConfigSchema>) => void;
38
+ /** Callback to signal current view is loading */
39
+ onViewLoading: () => void;
40
+ /** Callback to signal current view is ready */
41
+ onViewReady: () => void;
42
+ }
43
+
44
+ /**
45
+ * Hook to access print mode state from app-level context
46
+ *
47
+ * @param initialConfig - Initial print configuration (ignored, use context provider config)
48
+ * @returns Print mode state and controls
49
+ */
50
+ export function usePrintMode(initialConfig?: Partial<PrintConfigSchema>): PrintModeState {
51
+ const context = usePrintModeContext();
52
+
53
+ // Map context interface to legacy interface
54
+ return {
55
+ isPrintMode: context.isPrintMode,
56
+ printConfig: context.printConfig,
57
+ printModeState: context.printModeState,
58
+ enterPrintMode: context.triggerPrint,
59
+ exitPrintMode: context.exitPrintMode,
60
+ togglePrintMode: (config?: Partial<PrintConfigSchema>) => {
61
+ if (context.isPrintMode) {
62
+ context.exitPrintMode();
63
+ } else {
64
+ context.triggerPrint(config);
65
+ }
66
+ },
67
+ triggerPrint: context.triggerPrint,
68
+ onViewLoading: context.onViewLoading,
69
+ onViewReady: context.onViewReady,
70
+ };
71
+ }
72
+
73
+ export default usePrintMode;
package/src/index.ts CHANGED
@@ -19,5 +19,8 @@ export * from './utils';
19
19
  // Types (includes ContentTypes)
20
20
  export * from './types';
21
21
 
22
+ // Configuration
23
+ export * from './config';
24
+
22
25
  // Schemas (includes component schemas and builders)
23
26
  export * from './schemas';
@@ -4,6 +4,7 @@
4
4
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
5
5
  */
6
6
 
7
+ import type { ReactNode } from 'react';
7
8
  import { IsBoolean, IsOptional, IsString } from 'class-validator';
8
9
  import 'reflect-metadata';
9
10
  import { Editor, Field, Schema, Model, FieldType } from '@qwickapps/schema';
@@ -17,8 +18,8 @@ export class CodeModel extends Model {
17
18
  description: 'The code content to display with syntax highlighting',
18
19
  placeholder: 'Enter code content...'
19
20
  })
20
- @IsString()
21
- children?: string;
21
+ @IsString() // Schema validation: must be string for serialization
22
+ children?: ReactNode; // Runtime type: supports natural React usage
22
23
 
23
24
  @Field()
24
25
  @Editor({
@@ -84,5 +85,4 @@ export class CodeModel extends Model {
84
85
  codeBackground?: string;
85
86
  }
86
87
 
87
-
88
88
  export default CodeModel;
@@ -15,6 +15,7 @@ import {
15
15
  FieldType
16
16
  } from '@qwickapps/schema';
17
17
  import { IsOptional, IsString, IsBoolean, IsIn } from 'class-validator';
18
+ import { ReactNode } from 'react';
18
19
 
19
20
  @Schema('CollapsibleLayout', '1.0.0')
20
21
  export class CollapsibleLayoutModel extends Model {
@@ -115,7 +116,7 @@ export class CollapsibleLayoutModel extends Model {
115
116
  })
116
117
  @IsOptional()
117
118
  @IsString()
118
- children?: string;
119
+ children?: ReactNode | string;
119
120
 
120
121
  @Field()
121
122
  @Editor({
@@ -9,6 +9,7 @@ import { Type } from 'class-transformer';
9
9
  import 'reflect-metadata';
10
10
  import { Editor, Field, Schema, Model, FieldType } from '@qwickapps/schema';
11
11
  import { ActionModel } from './ActionSchema';
12
+ import { ReactNode } from 'react';
12
13
 
13
14
  @Schema('Content', '1.0.0')
14
15
  export class ContentModel extends Model {
@@ -43,7 +44,7 @@ export class ContentModel extends Model {
43
44
  })
44
45
  @IsOptional()
45
46
  @IsString()
46
- children?: string;
47
+ children?: ReactNode | string;
47
48
 
48
49
  @Field()
49
50
  @Editor({
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Schema for GridCell component - Grid layout cell wrapper
3
+ *
4
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
5
+ */
6
+
7
+ import type { ReactNode } from 'react';
8
+ import { IsOptional, IsString, IsNumber, IsIn } from 'class-validator';
9
+ import 'reflect-metadata';
10
+ import { Editor, Field, Schema, Model, FieldType } from '@qwickapps/schema';
11
+
12
+ @Schema('GridCell', '1.0.0')
13
+ export class GridCellModel extends Model {
14
+ @Field()
15
+ @Editor({
16
+ field_type: FieldType.TEXTAREA,
17
+ label: 'Children',
18
+ description: 'Content to display inside the grid cell',
19
+ placeholder: 'Nested components will be serialized automatically'
20
+ })
21
+ children?: ReactNode; // Runtime type: supports natural React usage
22
+
23
+ // Grid responsive properties
24
+ @Field()
25
+ @Editor({
26
+ field_type: FieldType.NUMBER,
27
+ label: 'Span',
28
+ description: 'Number of columns to span (1-12)',
29
+ placeholder: '12'
30
+ })
31
+ @IsOptional()
32
+ @IsNumber()
33
+ @IsIn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
34
+ span?: number;
35
+
36
+ @Field()
37
+ @Editor({
38
+ field_type: FieldType.NUMBER,
39
+ label: 'XS (Mobile)',
40
+ description: 'Columns on extra small screens (1-12)',
41
+ placeholder: '12'
42
+ })
43
+ @IsOptional()
44
+ @IsNumber()
45
+ @IsIn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
46
+ xs?: number;
47
+
48
+ @Field()
49
+ @Editor({
50
+ field_type: FieldType.NUMBER,
51
+ label: 'SM (Tablet)',
52
+ description: 'Columns on small screens (1-12)',
53
+ placeholder: '6'
54
+ })
55
+ @IsOptional()
56
+ @IsNumber()
57
+ @IsIn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
58
+ sm?: number;
59
+
60
+ @Field()
61
+ @Editor({
62
+ field_type: FieldType.NUMBER,
63
+ label: 'MD (Desktop)',
64
+ description: 'Columns on medium screens (1-12)',
65
+ placeholder: '4'
66
+ })
67
+ @IsOptional()
68
+ @IsNumber()
69
+ @IsIn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
70
+ md?: number;
71
+
72
+ @Field()
73
+ @Editor({
74
+ field_type: FieldType.NUMBER,
75
+ label: 'LG (Large Desktop)',
76
+ description: 'Columns on large screens (1-12)',
77
+ placeholder: '3'
78
+ })
79
+ @IsOptional()
80
+ @IsNumber()
81
+ @IsIn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
82
+ lg?: number;
83
+
84
+ @Field()
85
+ @Editor({
86
+ field_type: FieldType.NUMBER,
87
+ label: 'XL (Extra Large)',
88
+ description: 'Columns on extra large screens (1-12)',
89
+ placeholder: '2'
90
+ })
91
+ @IsOptional()
92
+ @IsNumber()
93
+ @IsIn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
94
+ xl?: number;
95
+
96
+ // Styling properties from WithBaseProps
97
+ @Field()
98
+ @Editor({
99
+ field_type: FieldType.TEXT,
100
+ label: 'Background',
101
+ description: 'Background color or theme color (e.g., "primary.main", "#ffffff")',
102
+ placeholder: 'transparent'
103
+ })
104
+ @IsOptional()
105
+ @IsString()
106
+ background?: string;
107
+
108
+ @Field()
109
+ @Editor({
110
+ field_type: FieldType.TEXT,
111
+ label: 'Padding',
112
+ description: 'Internal spacing (e.g., "medium", "16px", "1rem")',
113
+ placeholder: 'medium'
114
+ })
115
+ @IsOptional()
116
+ @IsString()
117
+ padding?: string;
118
+
119
+ @Field()
120
+ @Editor({
121
+ field_type: FieldType.TEXT,
122
+ label: 'Margin',
123
+ description: 'External spacing (e.g., "small", "8px", "0.5rem")',
124
+ placeholder: '0'
125
+ })
126
+ @IsOptional()
127
+ @IsString()
128
+ margin?: string;
129
+
130
+ @Field()
131
+ @Editor({
132
+ field_type: FieldType.TEXT,
133
+ label: 'Height',
134
+ description: 'Cell height (e.g., "200px", "medium")',
135
+ placeholder: 'auto'
136
+ })
137
+ @IsOptional()
138
+ @IsString()
139
+ height?: string;
140
+
141
+ @Field()
142
+ @Editor({
143
+ field_type: FieldType.TEXT,
144
+ label: 'Width',
145
+ description: 'Cell width (e.g., "100%", "300px")',
146
+ placeholder: '100%'
147
+ })
148
+ @IsOptional()
149
+ @IsString()
150
+ width?: string;
151
+
152
+ @Field()
153
+ @Editor({
154
+ field_type: FieldType.TEXT,
155
+ label: 'CSS Class',
156
+ description: 'Additional CSS class names',
157
+ placeholder: 'custom-cell-class'
158
+ })
159
+ @IsOptional()
160
+ @IsString()
161
+ className?: string;
162
+ }
163
+
164
+ export default GridCellModel;