@qwickapps/react-framework 1.4.0 → 1.4.2

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 (486) hide show
  1. package/QUICK_START_GUIDE.md +82 -0
  2. package/README.md +231 -21
  3. package/dist/components/Html.d.ts.map +1 -1
  4. package/dist/components/Markdown.d.ts +1 -2
  5. package/dist/components/Markdown.d.ts.map +1 -1
  6. package/dist/components/SafeSpan.d.ts +1 -2
  7. package/dist/components/SafeSpan.d.ts.map +1 -1
  8. package/dist/components/base/Container.d.ts +32 -0
  9. package/dist/components/base/Container.d.ts.map +1 -0
  10. package/dist/components/base/ContainerView.d.ts +65 -0
  11. package/dist/components/base/ContainerView.d.ts.map +1 -0
  12. package/dist/components/base/ModelView.d.ts +37 -46
  13. package/dist/components/base/ModelView.d.ts.map +1 -1
  14. package/dist/components/base/index.d.ts +3 -2
  15. package/dist/components/base/index.d.ts.map +1 -1
  16. package/dist/components/blocks/Article.d.ts +1 -2
  17. package/dist/components/blocks/Article.d.ts.map +1 -1
  18. package/dist/components/blocks/Code-factory.d.ts +22 -0
  19. package/dist/components/blocks/Code-factory.d.ts.map +1 -0
  20. package/dist/components/blocks/Code-old.d.ts +31 -0
  21. package/dist/components/blocks/Code-old.d.ts.map +1 -0
  22. package/dist/components/blocks/Code.d.ts +30 -18
  23. package/dist/components/blocks/Code.d.ts.map +1 -1
  24. package/dist/components/blocks/HeroBlock.d.ts +1 -2
  25. package/dist/components/blocks/HeroBlock.d.ts.map +1 -1
  26. package/dist/components/blocks/Image.d.ts +1 -2
  27. package/dist/components/blocks/Image.d.ts.map +1 -1
  28. package/dist/components/blocks/Section.d.ts +1 -2
  29. package/dist/components/blocks/Section.d.ts.map +1 -1
  30. package/dist/components/blocks/Text.d.ts +35 -27
  31. package/dist/components/blocks/Text.d.ts.map +1 -1
  32. package/dist/components/buttons/Button.d.ts +1 -2
  33. package/dist/components/buttons/Button.d.ts.map +1 -1
  34. package/dist/components/index.d.ts +2 -0
  35. package/dist/components/index.d.ts.map +1 -1
  36. package/dist/components/input/ChoiceInputField.d.ts +1 -2
  37. package/dist/components/input/ChoiceInputField.d.ts.map +1 -1
  38. package/dist/components/input/HtmlInputField.d.ts +1 -2
  39. package/dist/components/input/HtmlInputField.d.ts.map +1 -1
  40. package/dist/components/input/SelectInputField.d.ts +1 -2
  41. package/dist/components/input/SelectInputField.d.ts.map +1 -1
  42. package/dist/components/pages/Page.d.ts +29 -47
  43. package/dist/components/pages/Page.d.ts.map +1 -1
  44. package/dist/components/pages/index.d.ts +2 -3
  45. package/dist/components/pages/index.d.ts.map +1 -1
  46. package/dist/components/shared/createSerializableView.d.ts +68 -0
  47. package/dist/components/shared/createSerializableView.d.ts.map +1 -0
  48. package/dist/components/shared/viewProps.d.ts +37 -0
  49. package/dist/components/shared/viewProps.d.ts.map +1 -0
  50. package/dist/index.esm.js +21782 -22580
  51. package/dist/index.js +21782 -22579
  52. package/dist/qa/ConsoleWarningTest.d.ts +5 -0
  53. package/dist/qa/ConsoleWarningTest.d.ts.map +1 -0
  54. package/dist/qa/StorageKeyTest.d.ts +6 -0
  55. package/dist/qa/StorageKeyTest.d.ts.map +1 -0
  56. package/dist/qa/ThemeStorageKeyTest.d.ts +6 -0
  57. package/dist/qa/ThemeStorageKeyTest.d.ts.map +1 -0
  58. package/dist/schemas/CodeSchema.d.ts +2 -2
  59. package/dist/schemas/CodeSchema.d.ts.map +1 -1
  60. package/dist/schemas/ContainerSchema.d.ts +12 -0
  61. package/dist/schemas/ContainerSchema.d.ts.map +1 -0
  62. package/dist/schemas/PageTemplateSchema.d.ts +3 -3
  63. package/dist/schemas/PageTemplateSchema.d.ts.map +1 -1
  64. package/dist/schemas/ViewModelSchema.d.ts +46 -6
  65. package/dist/schemas/ViewModelSchema.d.ts.map +1 -1
  66. package/dist/schemas/ViewSchema.d.ts +65 -0
  67. package/dist/schemas/ViewSchema.d.ts.map +1 -0
  68. package/dist/schemas/index.d.ts +1 -1
  69. package/dist/schemas/index.d.ts.map +1 -1
  70. package/dist/schemas/transformers/ComponentTransformer.d.ts +27 -15
  71. package/dist/schemas/transformers/ComponentTransformer.d.ts.map +1 -1
  72. package/dist/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -1
  73. package/dist/schemas/transformers/registry.d.ts +3 -0
  74. package/dist/schemas/transformers/registry.d.ts.map +1 -1
  75. package/dist/src/__tests__/schemas/transformers/MockSerializableComponent.d.ts +66 -0
  76. package/dist/src/__tests__/schemas/transformers/MockSerializableComponent.d.ts.map +1 -0
  77. package/dist/src/components/AccessibilityChecker.d.ts +12 -0
  78. package/dist/src/components/AccessibilityChecker.d.ts.map +1 -0
  79. package/dist/src/components/AccessibilityProvider.d.ts +64 -0
  80. package/dist/src/components/AccessibilityProvider.d.ts.map +1 -0
  81. package/dist/src/components/Breadcrumbs.d.ts +39 -0
  82. package/dist/src/components/Breadcrumbs.d.ts.map +1 -0
  83. package/dist/src/components/ErrorBoundary.d.ts +46 -0
  84. package/dist/src/components/ErrorBoundary.d.ts.map +1 -0
  85. package/dist/src/components/Html.d.ts +58 -0
  86. package/dist/src/components/Html.d.ts.map +1 -0
  87. package/dist/src/components/Logo.d.ts +56 -0
  88. package/dist/src/components/Logo.d.ts.map +1 -0
  89. package/dist/src/components/Markdown.d.ts +51 -0
  90. package/dist/src/components/Markdown.d.ts.map +1 -0
  91. package/dist/src/components/QwickApp.d.ts +69 -0
  92. package/dist/src/components/QwickApp.d.ts.map +1 -0
  93. package/dist/src/components/QwickAppsLogo.d.ts +25 -0
  94. package/dist/src/components/QwickAppsLogo.d.ts.map +1 -0
  95. package/dist/src/components/QwickIcon.d.ts +23 -0
  96. package/dist/src/components/QwickIcon.d.ts.map +1 -0
  97. package/dist/src/components/ResponsiveMenu.d.ts +38 -0
  98. package/dist/src/components/ResponsiveMenu.d.ts.map +1 -0
  99. package/dist/src/components/SafeSpan.d.ts +29 -0
  100. package/dist/src/components/SafeSpan.d.ts.map +1 -0
  101. package/dist/src/components/Scaffold.d.ts +57 -0
  102. package/dist/src/components/Scaffold.d.ts.map +1 -0
  103. package/dist/src/components/base/Container.d.ts +33 -0
  104. package/dist/src/components/base/Container.d.ts.map +1 -0
  105. package/dist/src/components/base/ModelView.d.ts +92 -0
  106. package/dist/src/components/base/ModelView.d.ts.map +1 -0
  107. package/dist/src/components/base/index.d.ts +12 -0
  108. package/dist/src/components/base/index.d.ts.map +1 -0
  109. package/dist/src/components/blocks/Article.d.ts +32 -0
  110. package/dist/src/components/blocks/Article.d.ts.map +1 -0
  111. package/dist/src/components/blocks/CardListGrid.d.ts +23 -0
  112. package/dist/src/components/blocks/CardListGrid.d.ts.map +1 -0
  113. package/dist/src/components/blocks/Code.d.ts +37 -0
  114. package/dist/src/components/blocks/Code.d.ts.map +1 -0
  115. package/dist/src/components/blocks/Content.d.ts +24 -0
  116. package/dist/src/components/blocks/Content.d.ts.map +1 -0
  117. package/dist/src/components/blocks/CoverImageHeader.d.ts +44 -0
  118. package/dist/src/components/blocks/CoverImageHeader.d.ts.map +1 -0
  119. package/dist/src/components/blocks/FeatureCard.d.ts +66 -0
  120. package/dist/src/components/blocks/FeatureCard.d.ts.map +1 -0
  121. package/dist/src/components/blocks/FeatureGrid.d.ts +48 -0
  122. package/dist/src/components/blocks/FeatureGrid.d.ts.map +1 -0
  123. package/dist/src/components/blocks/Footer.d.ts +56 -0
  124. package/dist/src/components/blocks/Footer.d.ts.map +1 -0
  125. package/dist/src/components/blocks/HeroBlock.d.ts +55 -0
  126. package/dist/src/components/blocks/HeroBlock.d.ts.map +1 -0
  127. package/dist/src/components/blocks/Image.d.ts +40 -0
  128. package/dist/src/components/blocks/Image.d.ts.map +1 -0
  129. package/dist/src/components/blocks/PageBannerHeader.d.ts +30 -0
  130. package/dist/src/components/blocks/PageBannerHeader.d.ts.map +1 -0
  131. package/dist/src/components/blocks/ProductCard.d.ts +57 -0
  132. package/dist/src/components/blocks/ProductCard.d.ts.map +1 -0
  133. package/dist/src/components/blocks/Section.d.ts +45 -0
  134. package/dist/src/components/blocks/Section.d.ts.map +1 -0
  135. package/dist/src/components/blocks/Text.d.ts +34 -0
  136. package/dist/src/components/blocks/Text.d.ts.map +1 -0
  137. package/dist/src/components/blocks/index.d.ts +41 -0
  138. package/dist/src/components/blocks/index.d.ts.map +1 -0
  139. package/dist/src/components/buttons/Button.d.ts +41 -0
  140. package/dist/src/components/buttons/Button.d.ts.map +1 -0
  141. package/dist/src/components/buttons/PaletteSwitcher.d.ts +24 -0
  142. package/dist/src/components/buttons/PaletteSwitcher.d.ts.map +1 -0
  143. package/dist/src/components/buttons/ThemeSwitcher.d.ts +24 -0
  144. package/dist/src/components/buttons/ThemeSwitcher.d.ts.map +1 -0
  145. package/dist/src/components/buttons/index.d.ts +11 -0
  146. package/dist/src/components/buttons/index.d.ts.map +1 -0
  147. package/dist/src/components/forms/FormBlock.d.ts +51 -0
  148. package/dist/src/components/forms/FormBlock.d.ts.map +1 -0
  149. package/dist/src/components/forms/index.d.ts +8 -0
  150. package/dist/src/components/forms/index.d.ts.map +1 -0
  151. package/dist/src/components/index.d.ts +41 -0
  152. package/dist/src/components/index.d.ts.map +1 -0
  153. package/dist/src/components/input/ChoiceInputField.d.ts +29 -0
  154. package/dist/src/components/input/ChoiceInputField.d.ts.map +1 -0
  155. package/dist/src/components/input/HtmlInputField.d.ts +33 -0
  156. package/dist/src/components/input/HtmlInputField.d.ts.map +1 -0
  157. package/dist/src/components/input/SelectInputField.d.ts +31 -0
  158. package/dist/src/components/input/SelectInputField.d.ts.map +1 -0
  159. package/dist/src/components/input/SwitchInputField.d.ts +27 -0
  160. package/dist/src/components/input/SwitchInputField.d.ts.map +1 -0
  161. package/dist/src/components/input/TextField.d.ts +18 -0
  162. package/dist/src/components/input/TextField.d.ts.map +1 -0
  163. package/dist/src/components/input/TextInputField.d.ts +34 -0
  164. package/dist/src/components/input/TextInputField.d.ts.map +1 -0
  165. package/dist/src/components/input/index.d.ts +19 -0
  166. package/dist/src/components/input/index.d.ts.map +1 -0
  167. package/dist/src/components/layout/CollapsibleLayout/CollapsibleLayout.d.ts +34 -0
  168. package/dist/src/components/layout/CollapsibleLayout/CollapsibleLayout.d.ts.map +1 -0
  169. package/dist/src/components/layout/CollapsibleLayout/index.d.ts +9 -0
  170. package/dist/src/components/layout/CollapsibleLayout/index.d.ts.map +1 -0
  171. package/dist/src/components/layout/GridCell.d.ts +32 -0
  172. package/dist/src/components/layout/GridCell.d.ts.map +1 -0
  173. package/dist/src/components/layout/GridCellWrapper.d.ts +46 -0
  174. package/dist/src/components/layout/GridCellWrapper.d.ts.map +1 -0
  175. package/dist/src/components/layout/GridLayout.d.ts +50 -0
  176. package/dist/src/components/layout/GridLayout.d.ts.map +1 -0
  177. package/dist/src/components/layout/index.d.ts +14 -0
  178. package/dist/src/components/layout/index.d.ts.map +1 -0
  179. package/dist/src/components/menu/Menu.d.ts +1 -0
  180. package/dist/src/components/menu/Menu.d.ts.map +1 -0
  181. package/dist/src/components/menu/MenuItem.d.ts +31 -0
  182. package/dist/src/components/menu/MenuItem.d.ts.map +1 -0
  183. package/dist/src/components/menu/index.d.ts +7 -0
  184. package/dist/src/components/menu/index.d.ts.map +1 -0
  185. package/dist/src/components/pages/FormPage.d.ts +66 -0
  186. package/dist/src/components/pages/FormPage.d.ts.map +1 -0
  187. package/dist/src/components/pages/Page.d.ts +68 -0
  188. package/dist/src/components/pages/Page.d.ts.map +1 -0
  189. package/dist/src/components/pages/index.d.ts +10 -0
  190. package/dist/src/components/pages/index.d.ts.map +1 -0
  191. package/dist/src/components/shared/createSerializableView.d.ts +81 -0
  192. package/dist/src/components/shared/createSerializableView.d.ts.map +1 -0
  193. package/dist/src/components/shared/viewProps.d.ts +37 -0
  194. package/dist/src/components/shared/viewProps.d.ts.map +1 -0
  195. package/dist/src/config/AppConfig.d.ts +49 -0
  196. package/dist/src/config/AppConfig.d.ts.map +1 -0
  197. package/dist/src/config/AppConfigBuilder.d.ts +75 -0
  198. package/dist/src/config/AppConfigBuilder.d.ts.map +1 -0
  199. package/dist/src/config/index.d.ts +13 -0
  200. package/dist/src/config/index.d.ts.map +1 -0
  201. package/dist/src/config/types.d.ts +130 -0
  202. package/dist/src/config/types.d.ts.map +1 -0
  203. package/dist/src/config.d.ts +15 -0
  204. package/dist/src/config.d.ts.map +1 -0
  205. package/dist/src/contexts/DataContext.d.ts +139 -0
  206. package/dist/src/contexts/DataContext.d.ts.map +1 -0
  207. package/dist/src/contexts/DimensionsContext.d.ts +42 -0
  208. package/dist/src/contexts/DimensionsContext.d.ts.map +1 -0
  209. package/dist/src/contexts/PaletteContext.d.ts +53 -0
  210. package/dist/src/contexts/PaletteContext.d.ts.map +1 -0
  211. package/dist/src/contexts/PrintModeContext.d.ts +27 -0
  212. package/dist/src/contexts/PrintModeContext.d.ts.map +1 -0
  213. package/dist/src/contexts/QwickAppContext.d.ts +71 -0
  214. package/dist/src/contexts/QwickAppContext.d.ts.map +1 -0
  215. package/dist/src/contexts/ThemeContext.d.ts +65 -0
  216. package/dist/src/contexts/ThemeContext.d.ts.map +1 -0
  217. package/dist/src/contexts/index.d.ts +11 -0
  218. package/dist/src/contexts/index.d.ts.map +1 -0
  219. package/dist/src/hooks/index.d.ts +12 -0
  220. package/dist/src/hooks/index.d.ts.map +1 -0
  221. package/dist/src/hooks/useBaseProps.d.ts +101 -0
  222. package/dist/src/hooks/useBaseProps.d.ts.map +1 -0
  223. package/dist/src/hooks/useDataBinding.d.ts +22 -0
  224. package/dist/src/hooks/useDataBinding.d.ts.map +1 -0
  225. package/dist/src/hooks/usePrintMode.d.ts +39 -0
  226. package/dist/src/hooks/usePrintMode.d.ts.map +1 -0
  227. package/dist/src/index.d.ts +9 -0
  228. package/dist/src/index.d.ts.map +1 -0
  229. package/dist/src/palettes/PaletteAutumn.d.ts +10 -0
  230. package/dist/src/palettes/PaletteAutumn.d.ts.map +1 -0
  231. package/dist/src/palettes/PaletteCosmic.d.ts +10 -0
  232. package/dist/src/palettes/PaletteCosmic.d.ts.map +1 -0
  233. package/dist/src/palettes/PaletteDefault.d.ts +10 -0
  234. package/dist/src/palettes/PaletteDefault.d.ts.map +1 -0
  235. package/dist/src/palettes/PaletteOcean.d.ts +10 -0
  236. package/dist/src/palettes/PaletteOcean.d.ts.map +1 -0
  237. package/dist/src/palettes/PaletteSpring.d.ts +10 -0
  238. package/dist/src/palettes/PaletteSpring.d.ts.map +1 -0
  239. package/dist/src/palettes/PaletteWinter.d.ts +10 -0
  240. package/dist/src/palettes/PaletteWinter.d.ts.map +1 -0
  241. package/dist/src/palettes/index.d.ts +13 -0
  242. package/dist/src/palettes/index.d.ts.map +1 -0
  243. package/dist/src/schemas/ActionSchema.d.ts +21 -0
  244. package/dist/src/schemas/ActionSchema.d.ts.map +1 -0
  245. package/dist/src/schemas/ArticleSchema.d.ts +13 -0
  246. package/dist/src/schemas/ArticleSchema.d.ts.map +1 -0
  247. package/dist/src/schemas/ButtonSchema.d.ts +19 -0
  248. package/dist/src/schemas/ButtonSchema.d.ts.map +1 -0
  249. package/dist/src/schemas/CardListGridSchema.d.ts +17 -0
  250. package/dist/src/schemas/CardListGridSchema.d.ts.map +1 -0
  251. package/dist/src/schemas/ChoiceInputFieldSchema.d.ts +18 -0
  252. package/dist/src/schemas/ChoiceInputFieldSchema.d.ts.map +1 -0
  253. package/dist/src/schemas/CodeSchema.d.ts +18 -0
  254. package/dist/src/schemas/CodeSchema.d.ts.map +1 -0
  255. package/dist/src/schemas/CollapsibleLayoutSchema.d.ts +32 -0
  256. package/dist/src/schemas/CollapsibleLayoutSchema.d.ts.map +1 -0
  257. package/dist/src/schemas/ContainerSchema.d.ts +12 -0
  258. package/dist/src/schemas/ContainerSchema.d.ts.map +1 -0
  259. package/dist/src/schemas/ContentSchema.d.ts +21 -0
  260. package/dist/src/schemas/ContentSchema.d.ts.map +1 -0
  261. package/dist/src/schemas/CoverImageHeaderSchema.d.ts +28 -0
  262. package/dist/src/schemas/CoverImageHeaderSchema.d.ts.map +1 -0
  263. package/dist/src/schemas/FeatureCardSchema.d.ts +28 -0
  264. package/dist/src/schemas/FeatureCardSchema.d.ts.map +1 -0
  265. package/dist/src/schemas/FeatureGridSchema.d.ts +17 -0
  266. package/dist/src/schemas/FeatureGridSchema.d.ts.map +1 -0
  267. package/dist/src/schemas/FeatureItemSchema.d.ts +16 -0
  268. package/dist/src/schemas/FeatureItemSchema.d.ts.map +1 -0
  269. package/dist/src/schemas/FooterItemSchema.d.ts +15 -0
  270. package/dist/src/schemas/FooterItemSchema.d.ts.map +1 -0
  271. package/dist/src/schemas/FooterSchema.d.ts +20 -0
  272. package/dist/src/schemas/FooterSchema.d.ts.map +1 -0
  273. package/dist/src/schemas/FooterSectionSchema.d.ts +15 -0
  274. package/dist/src/schemas/FooterSectionSchema.d.ts.map +1 -0
  275. package/dist/src/schemas/FormBlockSchema.d.ts +19 -0
  276. package/dist/src/schemas/FormBlockSchema.d.ts.map +1 -0
  277. package/dist/src/schemas/GridCellSchema.d.ts +23 -0
  278. package/dist/src/schemas/GridCellSchema.d.ts.map +1 -0
  279. package/dist/src/schemas/GridLayoutSchema.d.ts +21 -0
  280. package/dist/src/schemas/GridLayoutSchema.d.ts.map +1 -0
  281. package/dist/src/schemas/HeaderActionSchema.d.ts +17 -0
  282. package/dist/src/schemas/HeaderActionSchema.d.ts.map +1 -0
  283. package/dist/src/schemas/HeroBlockSchema.d.ts +22 -0
  284. package/dist/src/schemas/HeroBlockSchema.d.ts.map +1 -0
  285. package/dist/src/schemas/HtmlInputFieldSchema.d.ts +18 -0
  286. package/dist/src/schemas/HtmlInputFieldSchema.d.ts.map +1 -0
  287. package/dist/src/schemas/HtmlSchema.d.ts +14 -0
  288. package/dist/src/schemas/HtmlSchema.d.ts.map +1 -0
  289. package/dist/src/schemas/ImageSchema.d.ts +32 -0
  290. package/dist/src/schemas/ImageSchema.d.ts.map +1 -0
  291. package/dist/src/schemas/LogoSchema.d.ts +35 -0
  292. package/dist/src/schemas/LogoSchema.d.ts.map +1 -0
  293. package/dist/src/schemas/MarkdownSchema.d.ts +14 -0
  294. package/dist/src/schemas/MarkdownSchema.d.ts.map +1 -0
  295. package/dist/src/schemas/MetadataItemSchema.d.ts +13 -0
  296. package/dist/src/schemas/MetadataItemSchema.d.ts.map +1 -0
  297. package/dist/src/schemas/PageBannerHeaderSchema.d.ts +28 -0
  298. package/dist/src/schemas/PageBannerHeaderSchema.d.ts.map +1 -0
  299. package/dist/src/schemas/PageTemplateSchema.d.ts +31 -0
  300. package/dist/src/schemas/PageTemplateSchema.d.ts.map +1 -0
  301. package/dist/src/schemas/PaletteSwitcherSchema.d.ts +16 -0
  302. package/dist/src/schemas/PaletteSwitcherSchema.d.ts.map +1 -0
  303. package/dist/src/schemas/PrintConfigSchema.d.ts +31 -0
  304. package/dist/src/schemas/PrintConfigSchema.d.ts.map +1 -0
  305. package/dist/src/schemas/ProductCardSchema.d.ts +39 -0
  306. package/dist/src/schemas/ProductCardSchema.d.ts.map +1 -0
  307. package/dist/src/schemas/SafeSpanSchema.d.ts +13 -0
  308. package/dist/src/schemas/SafeSpanSchema.d.ts.map +1 -0
  309. package/dist/src/schemas/SectionSchema.d.ts +16 -0
  310. package/dist/src/schemas/SectionSchema.d.ts.map +1 -0
  311. package/dist/src/schemas/SelectInputFieldSchema.d.ts +27 -0
  312. package/dist/src/schemas/SelectInputFieldSchema.d.ts.map +1 -0
  313. package/dist/src/schemas/SwitchInputFieldSchema.d.ts +18 -0
  314. package/dist/src/schemas/SwitchInputFieldSchema.d.ts.map +1 -0
  315. package/dist/src/schemas/TextInputFieldSchema.d.ts +22 -0
  316. package/dist/src/schemas/TextInputFieldSchema.d.ts.map +1 -0
  317. package/dist/src/schemas/TextSchema.d.ts +37 -0
  318. package/dist/src/schemas/TextSchema.d.ts.map +1 -0
  319. package/dist/src/schemas/ThemeSwitcherSchema.d.ts +19 -0
  320. package/dist/src/schemas/ThemeSwitcherSchema.d.ts.map +1 -0
  321. package/dist/src/schemas/ViewSchema.d.ts +66 -0
  322. package/dist/src/schemas/ViewSchema.d.ts.map +1 -0
  323. package/dist/src/schemas/index.d.ts +47 -0
  324. package/dist/src/schemas/index.d.ts.map +1 -0
  325. package/dist/src/schemas/transformers/ComponentTransformer.d.ts +128 -0
  326. package/dist/src/schemas/transformers/ComponentTransformer.d.ts.map +1 -0
  327. package/dist/src/schemas/transformers/ReactNodeTransformer.d.ts +53 -0
  328. package/dist/src/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -0
  329. package/dist/src/schemas/transformers/registry.d.ts +18 -0
  330. package/dist/src/schemas/transformers/registry.d.ts.map +1 -0
  331. package/dist/src/schemas/types/Serializable.d.ts +46 -0
  332. package/dist/src/schemas/types/Serializable.d.ts.map +1 -0
  333. package/dist/src/stories/_templates/SerializationTemplate.d.ts +44 -0
  334. package/dist/src/stories/_templates/SerializationTemplate.d.ts.map +1 -0
  335. package/dist/src/templates/TemplateResolver.d.ts +52 -0
  336. package/dist/src/templates/TemplateResolver.d.ts.map +1 -0
  337. package/dist/src/templates/index.d.ts +7 -0
  338. package/dist/src/templates/index.d.ts.map +1 -0
  339. package/dist/src/types/CacheProvider.d.ts +18 -0
  340. package/dist/src/types/CacheProvider.d.ts.map +1 -0
  341. package/dist/src/types/CollapsibleLayout.d.ts +142 -0
  342. package/dist/src/types/CollapsibleLayout.d.ts.map +1 -0
  343. package/dist/src/types/ContentProxy.d.ts +47 -0
  344. package/dist/src/types/ContentProxy.d.ts.map +1 -0
  345. package/dist/src/types/DataTypes.d.ts +185 -0
  346. package/dist/src/types/DataTypes.d.ts.map +1 -0
  347. package/dist/src/types/TemplateProvider.d.ts +10 -0
  348. package/dist/src/types/TemplateProvider.d.ts.map +1 -0
  349. package/dist/src/types/TemplateResolver.d.ts +23 -0
  350. package/dist/src/types/TemplateResolver.d.ts.map +1 -0
  351. package/dist/src/types/index.d.ts +82 -0
  352. package/dist/src/types/index.d.ts.map +1 -0
  353. package/dist/src/utils/breakpoints.d.ts +35 -0
  354. package/dist/src/utils/breakpoints.d.ts.map +1 -0
  355. package/dist/src/utils/cssUtils.d.ts +17 -0
  356. package/dist/src/utils/cssUtils.d.ts.map +1 -0
  357. package/dist/src/utils/customPaletteManager.d.ts +8 -0
  358. package/dist/src/utils/customPaletteManager.d.ts.map +1 -0
  359. package/dist/src/utils/dimensions.d.ts +34 -0
  360. package/dist/src/utils/dimensions.d.ts.map +1 -0
  361. package/dist/src/utils/htmlTransform.d.ts +44 -0
  362. package/dist/src/utils/htmlTransform.d.ts.map +1 -0
  363. package/dist/src/utils/index.d.ts +16 -0
  364. package/dist/src/utils/index.d.ts.map +1 -0
  365. package/dist/src/utils/logger.d.ts +26 -0
  366. package/dist/src/utils/logger.d.ts.map +1 -0
  367. package/dist/src/utils/paletteUtils.d.ts +38 -0
  368. package/dist/src/utils/paletteUtils.d.ts.map +1 -0
  369. package/dist/src/utils/persistenceUtils.d.ts +31 -0
  370. package/dist/src/utils/persistenceUtils.d.ts.map +1 -0
  371. package/dist/src/utils/reactUtils.d.ts +33 -0
  372. package/dist/src/utils/reactUtils.d.ts.map +1 -0
  373. package/dist/src/utils/spacing.d.ts +34 -0
  374. package/dist/src/utils/spacing.d.ts.map +1 -0
  375. package/dist/src/utils/themePerformanceMonitor.d.ts +32 -0
  376. package/dist/src/utils/themePerformanceMonitor.d.ts.map +1 -0
  377. package/dist/src/utils/themeUtils.d.ts +27 -0
  378. package/dist/src/utils/themeUtils.d.ts.map +1 -0
  379. package/dist/utils/cssUtils.d.ts +17 -0
  380. package/dist/utils/cssUtils.d.ts.map +1 -0
  381. package/dist/utils/index.d.ts +1 -0
  382. package/dist/utils/index.d.ts.map +1 -1
  383. package/package.json +5 -2
  384. package/scripts/bundle-css.cjs +27 -0
  385. package/scripts/create-project.sh +28 -0
  386. package/scripts/create-qwickapps-project.js +284 -0
  387. package/src/__tests__/components/base/Container.test.tsx +966 -0
  388. package/src/__tests__/schemas/PageTemplateSchema.test.ts +1 -1
  389. package/src/__tests__/schemas/ViewSchema.test.ts +805 -0
  390. package/src/__tests__/schemas/builders.test.ts +2 -2
  391. package/src/__tests__/schemas/transformers/ComponentTransformer.test.ts +19 -19
  392. package/src/__tests__/schemas/transformers/CrossBrowserCompatibility.test.ts +13 -13
  393. package/src/__tests__/schemas/transformers/SerializationErrorHandling.test.ts +39 -39
  394. package/src/__tests__/schemas/transformers/SerializationPerformance.test.ts +14 -14
  395. package/src/__tests__/schemas/transformers/TestAutomation.test.ts +8 -8
  396. package/src/__tests__/schemas/transformers/nested-serialization.test.tsx +181 -0
  397. package/src/__tests__/schemas/transformers/round-trip-component-serialization.test.tsx +458 -0
  398. package/src/__tests__/test_image_accessibility.test.tsx +226 -0
  399. package/src/__tests__/utils/optional-logging.test.ts +3 -3
  400. package/src/components/Html.tsx +24 -15
  401. package/src/components/Logo.tsx +2 -2
  402. package/src/components/Markdown.tsx +2 -7
  403. package/src/components/SafeSpan.tsx +2 -7
  404. package/src/components/base/Container.tsx +61 -0
  405. package/src/components/base/ModelView.tsx +225 -91
  406. package/src/components/base/index.ts +3 -2
  407. package/src/components/blocks/Article.tsx +2 -7
  408. package/src/components/blocks/CardListGrid.tsx +2 -2
  409. package/src/components/blocks/Code.tsx +91 -179
  410. package/src/components/blocks/Content.tsx +2 -2
  411. package/src/components/blocks/CoverImageHeader.tsx +2 -2
  412. package/src/components/blocks/HeroBlock.tsx +54 -146
  413. package/src/components/blocks/Image.tsx +82 -196
  414. package/src/components/blocks/PageBannerHeader.tsx +2 -2
  415. package/src/components/blocks/Section.tsx +79 -181
  416. package/src/components/blocks/Text.tsx +100 -198
  417. package/src/components/buttons/Button.tsx +85 -183
  418. package/src/components/buttons/PaletteSwitcher.tsx +2 -2
  419. package/src/components/buttons/ThemeSwitcher.tsx +2 -2
  420. package/src/components/forms/FormBlock.tsx +2 -2
  421. package/src/components/index.ts +5 -0
  422. package/src/components/input/ChoiceInputField.tsx +76 -160
  423. package/src/components/input/HtmlInputField.tsx +141 -264
  424. package/src/components/input/SelectInputField.tsx +48 -153
  425. package/src/components/input/SwitchInputField.tsx +41 -139
  426. package/src/components/input/TextInputField.tsx +39 -116
  427. package/src/components/layout/GridCell.tsx +36 -122
  428. package/src/components/layout/GridLayout.tsx +55 -127
  429. package/src/components/pages/Page.tsx +268 -276
  430. package/src/components/pages/index.ts +2 -3
  431. package/src/components/shared/createSerializableView.tsx +280 -0
  432. package/src/components/shared/viewProps.ts +207 -0
  433. package/src/config/__tests__/AppConfigBuilder.test.ts +2 -2
  434. package/src/contexts/DataContext.tsx +1 -1
  435. package/src/schemas/ButtonSchema.ts +3 -2
  436. package/src/schemas/CardListGridSchema.ts +3 -2
  437. package/src/schemas/ChoiceInputFieldSchema.ts +3 -2
  438. package/src/schemas/CodeSchema.ts +8 -6
  439. package/src/schemas/ContainerSchema.ts +25 -0
  440. package/src/schemas/FeatureCardSchema.ts +1 -1
  441. package/src/schemas/FormBlockSchema.ts +3 -2
  442. package/src/schemas/GridCellSchema.ts +4 -10
  443. package/src/schemas/GridLayoutSchema.ts +8 -14
  444. package/src/schemas/HeroBlockSchema.ts +3 -2
  445. package/src/schemas/HtmlInputFieldSchema.ts +3 -2
  446. package/src/schemas/ImageSchema.ts +3 -2
  447. package/src/schemas/PageTemplateSchema.ts +5 -5
  448. package/src/schemas/SectionSchema.ts +4 -12
  449. package/src/schemas/SelectInputFieldSchema.ts +3 -2
  450. package/src/schemas/SwitchInputFieldSchema.ts +2 -2
  451. package/src/schemas/TextInputFieldSchema.ts +3 -2
  452. package/src/schemas/ViewSchema.ts +570 -0
  453. package/src/schemas/index.ts +1 -1
  454. package/src/schemas/transformers/ComponentTransformer.ts +185 -163
  455. package/src/schemas/transformers/ReactNodeTransformer.ts +31 -28
  456. package/src/schemas/transformers/registry.ts +17 -10
  457. package/src/stories/Button.stories.tsx +24 -0
  458. package/src/stories/ChoiceInputField.stories.tsx +28 -1
  459. package/src/stories/Code.stories.tsx +61 -1
  460. package/src/stories/Container.stories.tsx +954 -0
  461. package/src/stories/FormBlock.stories.tsx +54 -0
  462. package/src/stories/FormComponents.stories.tsx +8 -13
  463. package/src/stories/GridCell.stories.tsx +23 -64
  464. package/src/stories/GridLayout.stories.tsx +22 -47
  465. package/src/stories/HeroBlock.stories.tsx +28 -0
  466. package/src/stories/HtmlInputField.stories.tsx +23 -1
  467. package/src/stories/Image.stories.tsx +45 -233
  468. package/src/stories/Markdown.stories.tsx +1 -1
  469. package/src/stories/Section.stories.tsx +38 -4
  470. package/src/stories/SelectInputField.stories.tsx +26 -1
  471. package/src/stories/Text.stories.tsx +22 -54
  472. package/src/stories/TextInputField.stories.tsx +24 -1
  473. package/src/stories/_templates/SerializationTemplate.tsx +165 -0
  474. package/src/templates/TemplateResolver.ts +2 -2
  475. package/src/types/CollapsibleLayout.ts +2 -2
  476. package/src/utils/cssUtils.ts +49 -0
  477. package/src/utils/index.ts +1 -0
  478. package/src/utils/logger.ts +13 -13
  479. package/src/__tests__/components/base/ModelView.test.tsx +0 -220
  480. package/src/__tests__/schemas/ViewModelSchema.test.ts +0 -80
  481. package/src/components/blocks/Code.md +0 -529
  482. package/src/schemas/README.md +0 -661
  483. package/src/schemas/ViewModelSchema.ts +0 -115
  484. package/src/tests/ConsoleWarningTest.tsx +0 -30
  485. package/src/tests/StorageKeyTest.tsx +0 -110
  486. package/src/tests/ThemeStorageKeyTest.tsx +0 -114
@@ -1,156 +1,284 @@
1
1
  /**
2
- * Page Architecture - Clean separation with functional controller
3
- *
4
- * Copyright (c) 2025 QwickApps.com. All rights reserved.
2
+ * Page provides a unified Page component supporting:
3
+ * - Layout variants (width, padding, background)
4
+ * - Template-based metadata (title / description / slug)
5
+ * - Declarative print mode with dynamic header/footer sizing
6
+ * - Centralized context (route, loading/error flags, print controls)
7
+ * - Optional class-based extension (Page) for legacy / OOP style
8
+ *
9
+ * Typical usage (functional):
10
+ * <Page title="Orders" printConfig={{ printTitle: 'Orders' }}>
11
+ * <OrdersList />
12
+ * </Page>
13
+ *
14
+ * Class-based (override only what you need):
15
+ * class OrdersPage extends Page {
16
+ * protected getPageProps() { return { title: 'Orders' }; }
17
+ * protected renderPrintView() { return <PrintOnlyLayout />; }
18
+ * }
19
+ *
20
+ * Printing:
21
+ * const { triggerPrint } = usePageContext();
22
+ * triggerPrint(optionalOverrides);
23
+ *
24
+ * Copyright (c) 2025 QwickApps
5
25
  */
6
-
7
- import React, { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useState } from 'react';
26
+ import React, {
27
+ createContext,
28
+ useCallback,
29
+ useContext,
30
+ useEffect,
31
+ useLayoutEffect,
32
+ useMemo,
33
+ useState
34
+ } from 'react';
8
35
  import { t } from '../../contexts';
9
36
  import { useBaseProps, WithBaseProps } from '../../hooks/useBaseProps';
10
37
  import { usePrintMode } from '../../hooks/usePrintMode';
11
38
  import { PageTemplateSchema } from '../../schemas/PageTemplateSchema';
12
39
  import { PrintConfigSchema } from '../../schemas/PrintConfigSchema';
40
+ import { toCssLength } from '../../utils/cssUtils';
13
41
  import { useSafeLocation } from '../../utils/reactUtils';
14
42
  import { SafeSpan } from '../SafeSpan';
15
43
  import './Page.css';
44
+ import { Box } from '@mui/material';
16
45
 
46
+ /* -------------------------------------------------------------------------- */
47
+ /* Context */
48
+ /* -------------------------------------------------------------------------- */
17
49
  export interface PageContextValue {
18
- /** Current page route/path */
19
50
  route?: string;
20
- /** Whether the page is currently in print mode */
21
51
  isPrintMode: boolean;
22
- /** Current print configuration */
23
52
  printConfig: PrintConfigSchema;
24
- /** Trigger print mode and dialog */
25
53
  triggerPrint: (config?: Partial<PrintConfigSchema>) => void;
26
- /** Set page loading state */
27
54
  setLoading: (loading: boolean) => void;
28
- /** Set page error state */
29
55
  setError: (error: string | null) => void;
30
- /** Current page loading state */
31
56
  isLoading: boolean;
32
- /** Current page error state */
33
57
  error: string | null;
34
58
  }
35
59
 
36
- // Create context for page-level state
37
60
  const PageContext = createContext<PageContextValue | null>(null);
38
61
 
39
62
  export const usePageContext = (): PageContextValue => {
40
- const context = useContext(PageContext);
41
- if (!context) {
42
- throw new Error('usePageContext must be used within a Page component');
43
- }
44
- return context;
63
+ const ctx = useContext(PageContext);
64
+ if (!ctx) throw new Error('usePageContext must be used within PageView');
65
+ return ctx;
45
66
  };
46
67
 
68
+ /* -------------------------------------------------------------------------- */
69
+ /* Meta Hook */
70
+ /* -------------------------------------------------------------------------- */
71
+ function usePageMeta(
72
+ title?: string,
73
+ description?: string,
74
+ opts?: { openGraph?: boolean; removeOnUnmount?: boolean }
75
+ ) {
76
+ const { openGraph = true, removeOnUnmount = false } = opts || {};
77
+
78
+ useEffect(() => {
79
+ const prevTitle = document.title;
80
+ let createdDesc = false;
81
+ let metaDesc = document.querySelector('meta[name="description"]') as HTMLMetaElement | null;
82
+
83
+ if (title && document.title !== title) {
84
+ document.title = title;
85
+ }
86
+
87
+ if (description) {
88
+ if (!metaDesc) {
89
+ metaDesc = document.createElement('meta');
90
+ metaDesc.name = 'description';
91
+ document.head.appendChild(metaDesc);
92
+ createdDesc = true;
93
+ }
94
+ if (metaDesc.content !== description) metaDesc.content = description;
95
+ }
96
+
97
+ let ogTitle: HTMLMetaElement | null = null;
98
+ let ogDesc: HTMLMetaElement | null = null;
99
+
100
+ if (openGraph) {
101
+ if (title) {
102
+ ogTitle = document.querySelector('meta[property="og:title"]');
103
+ if (!ogTitle) {
104
+ ogTitle = document.createElement('meta');
105
+ ogTitle.setAttribute('property', 'og:title');
106
+ document.head.appendChild(ogTitle);
107
+ }
108
+ if (ogTitle.content !== title) ogTitle.content = title;
109
+ }
110
+ if (description) {
111
+ ogDesc = document.querySelector('meta[property="og:description"]');
112
+ if (!ogDesc) {
113
+ ogDesc = document.createElement('meta');
114
+ ogDesc.setAttribute('property', 'og:description');
115
+ document.head.appendChild(ogDesc);
116
+ }
117
+ if (ogDesc.content !== description) ogDesc.content = description;
118
+ }
119
+ }
120
+
121
+ return () => {
122
+ if (removeOnUnmount) {
123
+ if (document.title === title) document.title = prevTitle;
124
+ if (description && metaDesc && (createdDesc || removeOnUnmount)) {
125
+ metaDesc.parentNode?.removeChild(metaDesc);
126
+ }
127
+ if (openGraph) {
128
+ if (ogTitle && removeOnUnmount) ogTitle.parentNode?.removeChild(ogTitle);
129
+ if (ogDesc && removeOnUnmount) ogDesc.parentNode?.removeChild(ogDesc);
130
+ }
131
+ }
132
+ };
133
+ }, [title, description, openGraph, removeOnUnmount]);
134
+ }
135
+
136
+ /* -------------------------------------------------------------------------- */
137
+ /* Public Props */
138
+ /* -------------------------------------------------------------------------- */
47
139
  export interface PageProps extends WithBaseProps {
48
- /** Current route/path for this page */
49
140
  route?: string;
50
- /** Page layout variant */
51
141
  variant?: 'default' | 'centered' | 'narrow' | 'wide' | 'fullwidth';
52
- /** Padding around page content */
53
142
  padding?: 'none' | 'small' | 'medium' | 'large';
54
- /** Background variant */
55
143
  background?: 'default' | 'surface' | 'alternate';
56
- /** Maximum width for content */
57
144
  maxWidth?: 'small' | 'medium' | 'large' | 'extra-large' | 'none';
58
- /** Print configuration for this page */
59
145
  printConfig?: Partial<PrintConfigSchema>;
60
- /** PageTemplate model instance */
61
146
  template?: PageTemplateSchema;
62
- /** Page title */
63
147
  title?: string;
64
- /** Page description for SEO */
65
148
  description?: string;
66
- /** Page name/heading */
67
149
  name?: string;
68
- /** Page slug for URL */
69
150
  slug?: string;
151
+ children?: React.ReactNode;
70
152
  }
71
153
 
72
- /**
73
- * PageWrapper - Internal component handling print mode detection and page infrastructure
74
- */
75
- interface PageWrapperProps extends PageProps {
76
- children: React.ReactNode;
154
+ /* -------------------------------------------------------------------------- */
155
+ /* Internal PageView */
156
+ /* -------------------------------------------------------------------------- */
157
+ interface PageViewProps extends PageProps {
158
+ renderView: () => React.ReactNode;
159
+ renderPrintView: () => React.ReactNode;
77
160
  }
78
161
 
79
- const PageWrapper: React.FC<PageWrapperProps> = (props) => {
80
- const {
81
- children,
82
- route: routeProp,
83
- variant = 'default',
84
- padding = 'medium',
85
- background = 'default',
86
- maxWidth = 'large',
87
- printConfig: printConfigProp,
88
- template,
89
- title: titleProp,
90
- description: descriptionProp,
91
- name: nameProp,
92
- slug: slugProp,
93
- ...restProps
94
- } = props;
95
-
96
- // Use base props hook to handle common properties
97
- const { styleProps, htmlProps } = useBaseProps(restProps);
98
-
99
- // Note: QwickApp context is available if needed for future enhancements
100
-
101
- // Resolve values from template or props (props take precedence)
102
- const resolvedValues = {
162
+ export const PageView: React.FC<PageViewProps> = ({
163
+ renderView,
164
+ renderPrintView,
165
+ template,
166
+ route: routeProp,
167
+ title: titleProp,
168
+ description: descriptionProp,
169
+ name: nameProp,
170
+ slug: slugProp,
171
+ printConfig: printConfigProp,
172
+ variant = 'default',
173
+ padding = 'medium',
174
+ background = 'default',
175
+ maxWidth = 'large',
176
+ children,
177
+ ...rest
178
+ }) => {
179
+ // Base props (single invocation early so we can merge styles/classNames)
180
+ const { htmlProps, styleProps } = useBaseProps(rest);
181
+
182
+ // State exposed via context
183
+ const [isLoading, setLoading] = useState(false);
184
+ const [error, setError] = useState<string | null>(null);
185
+
186
+ // Resolve template / prop derived metadata
187
+ const resolved = {
103
188
  route: routeProp ?? (template?.slug ? `/${template.slug}` : undefined),
104
189
  title: titleProp ?? template?.title ?? template?.name,
105
190
  description: descriptionProp ?? template?.description,
106
191
  name: nameProp ?? template?.name,
107
192
  slug: slugProp ?? template?.slug,
108
- printConfig: { ...template?.printConfig, ...printConfigProp },
193
+ printConfig: { ...template?.printConfig, ...printConfigProp }
109
194
  };
110
195
 
111
- // Page state management
112
- const [isLoading, setLoading] = useState(false);
113
- const [error, setError] = useState<string | null>(null);
196
+ // Update head metadata
197
+ usePageMeta(resolved.title, resolved.description);
114
198
 
115
- // Initialize print mode with page configuration
116
- const { isPrintMode, printConfig, onViewLoading, onViewReady, triggerPrint: triggerPrintBase } = usePrintMode();
117
- // Create page-specific trigger that applies page config
118
- const triggerPrint = useCallback((config?: Partial<PrintConfigSchema>) => {
119
- const mergedConfig = { ...resolvedValues.printConfig, ...config };
120
- triggerPrintBase(mergedConfig);
121
- }, [triggerPrintBase, resolvedValues.printConfig]);
199
+ // Print integration
200
+ const {
201
+ isPrintMode,
202
+ printConfig,
203
+ onViewLoading,
204
+ onViewReady,
205
+ triggerPrint: triggerPrintBase
206
+ } = usePrintMode();
207
+
208
+ const triggerPrint = useCallback(
209
+ (cfg?: Partial<PrintConfigSchema>) =>
210
+ triggerPrintBase({ ...resolved.printConfig, ...cfg }),
211
+ [triggerPrintBase, resolved.printConfig]
212
+ );
122
213
 
123
- // Auto-detect current route if available
124
- const location = useSafeLocation();
125
- const actualRoute = resolvedValues.route || location?.pathname || '';
214
+ // Sync print readiness with loading state
215
+ useLayoutEffect(() => {
216
+ if (!isPrintMode) return;
217
+ if (isLoading) onViewLoading();
218
+ else onViewReady();
219
+ }, [isPrintMode, isLoading, onViewLoading, onViewReady]);
126
220
 
127
- // Handle SEO and document head updates
221
+ // Inject dynamic print sizing styles (header/footer heights & background)
128
222
  useEffect(() => {
129
- if (resolvedValues.title) {
130
- document.title = resolvedValues.title;
223
+ if (!isPrintMode) return;
224
+ const styleId = 'qwickapps-print-page-setup';
225
+ const cfg = printConfig;
226
+ const size = (cfg as any).pageSize || 'auto';
227
+ const bg = cfg.printBackground || 'transparent';
228
+ const bgFirst = cfg.printBackgroundFirstPage || bg;
229
+
230
+ const hdrEl = document.querySelector('.page-print-header:not(.page-print-header-first-page)') as HTMLElement | null;
231
+ const ftrEl = document.querySelector('.page-print-footer:not(.page-print-footer-first-page)') as HTMLElement | null;
232
+ const hdr = hdrEl?.getBoundingClientRect ? Math.ceil(hdrEl.getBoundingClientRect().height) : 0;
233
+ const ftr = ftrEl?.getBoundingClientRect ? Math.ceil(ftrEl.getBoundingClientRect().height) : 0;
234
+ const headerH = hdr ? `${hdr}px` : toCssLength(cfg.printHeaderHeight || 0);
235
+ const footerH = ftr ? `${ftr}px` : toCssLength(cfg.printFooterHeight || 0);
236
+
237
+ const setCss = (h: string, f: string) =>
238
+ `@media print{@page{size:${size};margin:0;} .page-print-mode{--print-header-height:${h};--print-footer-height:${f};--print-background:${bg};--print-background-first-page:${bgFirst};}}`;
239
+
240
+ let el = document.getElementById(styleId) as HTMLStyleElement | null;
241
+ if (!el) {
242
+ el = document.createElement('style');
243
+ el.id = styleId;
244
+ document.head.appendChild(el);
131
245
  }
132
- // Update meta description
133
- if (resolvedValues.description) {
134
- let metaDescription = document.querySelector('meta[name="description"]');
135
- if (!metaDescription) {
136
- metaDescription = document.createElement('meta');
137
- metaDescription.setAttribute('name', 'description');
138
- document.head.appendChild(metaDescription);
139
- }
140
- metaDescription.setAttribute('content', resolvedValues.description);
246
+ el.textContent = setCss(headerH, footerH);
247
+
248
+ // Observe late size changes (images/fonts) while in print mode
249
+ let ro: ResizeObserver | null = null;
250
+ if (window.ResizeObserver) {
251
+ ro = new ResizeObserver(() => {
252
+ const hdrNow = hdrEl?.getBoundingClientRect ? Math.ceil(hdrEl.getBoundingClientRect().height) : 0;
253
+ const ftrNow = ftrEl?.getBoundingClientRect ? Math.ceil(ftrEl.getBoundingClientRect().height) : 0;
254
+ const finalCss = setCss(
255
+ hdrNow ? `${hdrNow}px` : headerH,
256
+ ftrNow ? `${ftrNow}px` : footerH
257
+ );
258
+ if (el && el.textContent !== finalCss) el.textContent = finalCss;
259
+ });
260
+ if (hdrEl) ro.observe(hdrEl);
261
+ if (ftrEl) ro.observe(ftrEl);
141
262
  }
142
- }, [resolvedValues.title, resolvedValues.description]);
143
263
 
144
- // Signal view state changes - let reducer handle valid transitions
145
- useLayoutEffect(() => {
146
- if (isPrintMode && isLoading) {
147
- onViewLoading();
148
- } else if (isPrintMode && !isLoading) {
149
- onViewReady();
150
- }
151
- }, [isPrintMode, isLoading, onViewLoading, onViewReady]);
264
+ const cleanup = () => {
265
+ const s = document.getElementById(styleId);
266
+ if (s?.parentNode) s.parentNode.removeChild(s);
267
+ ro?.disconnect();
268
+ };
152
269
 
153
- // Memoized context value
270
+ window.addEventListener('afterprint', cleanup, { once: true });
271
+ return () => {
272
+ window.removeEventListener('afterprint', cleanup);
273
+ cleanup();
274
+ };
275
+ }, [isPrintMode, printConfig]);
276
+
277
+ // Route (fallback to current location)
278
+ const location = useSafeLocation();
279
+ const actualRoute = resolved.route || location?.pathname || '';
280
+
281
+ // Context value
154
282
  const contextValue = useMemo<PageContextValue>(() => ({
155
283
  route: actualRoute,
156
284
  isPrintMode,
@@ -159,128 +287,45 @@ const PageWrapper: React.FC<PageWrapperProps> = (props) => {
159
287
  setLoading,
160
288
  setError,
161
289
  isLoading,
162
- error,
290
+ error
163
291
  }), [actualRoute, isPrintMode, printConfig, triggerPrint, isLoading, error]);
164
292
 
165
- // Inject dynamic @page margins during print to reserve header/footer space on every page
166
- useEffect(() => {
167
- const styleId = 'qwickapps-print-page-setup';
168
-
169
- const applyPrintPageSetup = () => {
170
- const configuredHeader = printConfig.printHeaderHeight || '0';
171
- const configuredFooter = printConfig.printFooterHeight || '0';
172
- const size = (printConfig as any).pageSize || 'auto';
173
- const bg = printConfig.printBackground || 'transparent';
174
- const bgFirst = printConfig.printBackgroundFirstPage || bg;
175
-
176
- // Measure actual rendered heights (fallback to configured)
177
- const getPx = (v: string | number) => typeof v === 'number' ? `${v}px` : (String(v).match(/(px|mm|cm|in|pt|pc)$/) ? String(v) : `${v}px`);
178
- const headerEl = document.querySelector('.page-print-header:not(.page-print-header-first-page)') as HTMLElement | null;
179
- const footerEl = document.querySelector('.page-print-footer:not(.page-print-footer-first-page)') as HTMLElement | null;
180
- const measuredHeaderPx = headerEl && headerEl.getBoundingClientRect ? Math.ceil(headerEl.getBoundingClientRect().height) : 0;
181
- const measuredFooterPx = footerEl && footerEl.getBoundingClientRect ? Math.ceil(footerEl.getBoundingClientRect().height) : 0;
182
- const headerH = measuredHeaderPx > 0 ? `${measuredHeaderPx}px` : getPx(configuredHeader);
183
- const footerH = measuredFooterPx > 0 ? `${measuredFooterPx}px` : getPx(configuredFooter);
184
-
185
- const css = `@media print{\n @page{\n size: ${String(size)};\n margin: 0;\n }\n .page-print-mode{\n --print-header-height: ${String(headerH)};\n --print-footer-height: ${String(footerH)};\n --print-background: ${String(bg)};\n --print-background-first-page: ${String(bgFirst)};\n}\n}`;
186
-
187
- let el = document.getElementById(styleId) as HTMLStyleElement | null;
188
- if (!el) {
189
- el = document.createElement('style');
190
- el.id = styleId;
191
- document.head.appendChild(el);
192
- }
193
- el.textContent = css;
194
-
195
- // Re-measure after layout settles once and update
196
- setTimeout(() => {
197
- const reHeaderEl = document.querySelector('.page-print-header:not(.page-print-header-first-page)') as HTMLElement | null;
198
- const reFooterEl = document.querySelector('.page-print-footer:not(.page-print-footer-first-page)') as HTMLElement | null;
199
- const reHeaderPx = reHeaderEl?.getBoundingClientRect ? Math.ceil(reHeaderEl.getBoundingClientRect().height) : 0;
200
- const reFooterPx = reFooterEl?.getBoundingClientRect ? Math.ceil(reFooterEl.getBoundingClientRect().height) : 0;
201
- if (reHeaderPx || reFooterPx) {
202
- const finalHeader = reHeaderPx ? `${reHeaderPx}px` : headerH;
203
- const finalFooter = reFooterPx ? `${reFooterPx}px` : footerH;
204
- const finalCss = `@media print{\n @page{\n size: ${String(size)};\n margin: 0;\n }\n .page-print-mode{\n --print-header-height: ${String(finalHeader)};\n --print-footer-height: ${String(finalFooter)};\n --print-background: ${String(bg)};\n --print-background-first-page: ${String(bgFirst)};\n }\n}`;
205
- let styleEl = document.getElementById(styleId) as HTMLStyleElement | null;
206
- if (!styleEl) {
207
- styleEl = document.createElement('style');
208
- styleEl.id = styleId;
209
- document.head.appendChild(styleEl);
210
- }
211
- styleEl.textContent = finalCss;
212
- }
213
- }, 60);
214
- };
215
-
216
- const removePrintPageSetup = () => {
217
- const el = document.getElementById(styleId);
218
- if (el && el.parentNode) el.parentNode.removeChild(el);
219
- };
220
-
221
- if (isPrintMode) {
222
- applyPrintPageSetup();
223
- // Cleanup after the print dialog closes
224
- const onAfterPrint = () => removePrintPageSetup();
225
- window.addEventListener('afterprint', onAfterPrint);
226
- return () => {
227
- window.removeEventListener('afterprint', onAfterPrint);
228
- removePrintPageSetup();
229
- };
230
- }
231
-
232
- // If leaving print mode, ensure cleanup
233
- removePrintPageSetup();
234
- }, [isPrintMode, printConfig.printHeaderHeight, printConfig.printFooterHeight, (printConfig as any).pageSize, printConfig.printBackground, printConfig.printBackgroundFirstPage]);
235
-
236
- // Calculate CSS variables for print configuration
237
-
238
- // Generate class names based on configuration
239
- const pageClasses = [
293
+ const classes = [
240
294
  'page',
241
295
  `page-variant-${variant}`,
242
296
  `page-padding-${padding}`,
243
297
  `page-background-${background}`,
244
298
  `page-max-width-${maxWidth}`,
245
- // Print mode classes
246
- isPrintMode ? 'page-print-mode' : '',
247
- // Print margin variants
248
- isPrintMode && printConfig.pageMargins === '0mm' ? 'page-print-borderless' : '',
249
- isPrintMode && printConfig.pageMargins === '6mm' ? 'page-print-compact' : '',
250
- isPrintMode && printConfig.pageMargins === '20mm' ? 'page-print-large' : '',
251
- isPrintMode && printConfig.pageMargins === '25mm' ? 'page-print-formal' : '',
252
- // Background class when custom background is specified
253
- isPrintMode && (printConfig.printBackground || printConfig.printBackgroundFirstPage) ? 'has-background' : '',
254
- // User classes
255
- styleProps.className,
299
+ isPrintMode && 'page-print-mode',
300
+ isPrintMode && printConfig.pageMargins === '0mm' && 'page-print-borderless',
301
+ isPrintMode && printConfig.pageMargins === '6mm' && 'page-print-compact',
302
+ isPrintMode && printConfig.pageMargins === '20mm' && 'page-print-large',
303
+ isPrintMode && printConfig.pageMargins === '25mm' && 'page-print-formal',
304
+ isPrintMode && (printConfig.printBackground || printConfig.printBackgroundFirstPage) && 'has-background',
305
+ styleProps.className
256
306
  ].filter(Boolean).join(' ');
257
307
 
308
+ // Resolve mode-specific render output (avoid falsey fallback for '')
309
+ const rendered = (isPrintMode ? renderPrintView : renderView)();
310
+ const mainContent = rendered != null ? rendered : children;
311
+
258
312
  return (
259
313
  <PageContext.Provider value={contextValue}>
260
- <div className={pageClasses} {...htmlProps}>
261
- {/* Custom print header - regular pages */}
314
+ <Box className={classes} sx={styleProps.sx} style={styleProps.style} {...htmlProps}>
262
315
  {isPrintMode && printConfig.printHeader && (
263
316
  <div className="page-print-header">
264
- {typeof printConfig.printHeader === 'string' ? (
265
- <SafeSpan html={t`${printConfig.printHeader}` as string} />
266
- ) : (
267
- printConfig.printHeader
268
- )}
317
+ {typeof printConfig.printHeader === 'string'
318
+ ? <SafeSpan html={t`${printConfig.printHeader}` as string} />
319
+ : printConfig.printHeader}
269
320
  </div>
270
321
  )}
271
-
272
- {/* Custom print header - first page only (rendered as a separate element for app control) */}
273
322
  {isPrintMode && printConfig.printHeaderFirstPage && (
274
- <div className="page-print-header page-print-header-first-page">
275
- {typeof printConfig.printHeaderFirstPage === 'string' ? (
276
- <SafeSpan html={t`${printConfig.printHeaderFirstPage}` as string} />
277
- ) : (
278
- printConfig.printHeaderFirstPage
279
- )}
280
- </div>
323
+ <div className="page-print-header page-print-header-first-page">
324
+ {typeof printConfig.printHeaderFirstPage === 'string'
325
+ ? <SafeSpan html={t`${printConfig.printHeaderFirstPage}` as string} />
326
+ : printConfig.printHeaderFirstPage}
327
+ </div>
281
328
  )}
282
-
283
- {/* Default print header - only if no custom header provided */}
284
329
  {isPrintMode && !printConfig.printHeader && printConfig.printTitle && (
285
330
  <div className="page-print-header">
286
331
  <h1>{printConfig.printTitle}</h1>
@@ -291,102 +336,49 @@ const PageWrapper: React.FC<PageWrapperProps> = (props) => {
291
336
  )}
292
337
  </div>
293
338
  )}
294
-
295
- {/* Page name as heading (if provided and different from title) */}
296
- {resolvedValues.name && resolvedValues.name !== resolvedValues.title && (
339
+ {resolved.name && resolved.name !== resolved.title && (
297
340
  <div className="page-heading">
298
- <h1>{resolvedValues.name}</h1>
341
+ <h1>{resolved.name}</h1>
299
342
  </div>
300
343
  )}
301
-
302
- {/* Page Content */}
303
344
  <div className="page-content">
304
- {children}
345
+ {mainContent}
305
346
  </div>
306
-
307
- {/* Custom print footer - regular pages */}
308
347
  {isPrintMode && printConfig.printFooter && (
309
348
  <div className="page-print-footer">
310
- {typeof printConfig.printFooter === 'string' ? (
311
- <SafeSpan html={t`${printConfig.printFooter}` as string} />
312
- ) : (
313
- printConfig.printFooter
314
- )}
349
+ {typeof printConfig.printFooter === 'string'
350
+ ? <SafeSpan html={t`${printConfig.printFooter}` as string} />
351
+ : printConfig.printFooter}
315
352
  </div>
316
353
  )}
317
-
318
- {/* Custom print footer - first page only (rendered as a separate element for app control) */}
319
354
  {isPrintMode && printConfig.printFooterFirstPage && (
320
355
  <div className="page-print-footer page-print-footer-first-page">
321
- {typeof printConfig.printFooterFirstPage === 'string' ? (
322
- <SafeSpan html={t`${printConfig.printFooterFirstPage}` as string} />
323
- ) : (
324
- printConfig.printFooterFirstPage
325
- )}
356
+ {typeof printConfig.printFooterFirstPage === 'string'
357
+ ? <SafeSpan html={t`${printConfig.printFooterFirstPage}` as string} />
358
+ : printConfig.printFooterFirstPage}
326
359
  </div>
327
360
  )}
328
- </div>
361
+ </Box>
329
362
  </PageContext.Provider>
330
363
  );
331
364
  };
332
365
 
333
- /**
334
- * Page - Functional component that controls print/normal view routing
335
- */
336
- interface PageWithViewsProps extends PageProps {
337
- /** Function to render normal view */
338
- renderView: () => React.ReactNode;
339
- /** Function to render print view */
340
- renderPrintView: () => React.ReactNode;
341
- }
342
-
343
- const Page: React.FC<PageWithViewsProps> = (props) => {
344
- const { renderView, renderPrintView, ...pageProps } = props;
366
+ /* -------------------------------------------------------------------------- */
367
+ /* Page Class */
368
+ /* -------------------------------------------------------------------------- */
369
+ export class Page<P extends PageProps = PageProps, S = {}> extends React.Component<P, S> {
370
+ protected getPageProps(): Partial<PageProps> { return {}; }
371
+ protected renderView(): React.ReactNode { return this.props.children; }
372
+ protected renderPrintView(): React.ReactNode { return this.renderView(); }
345
373
 
346
- return (
347
- <PageWrapper {...pageProps}>
348
- <PageController renderView={renderView} renderPrintView={renderPrintView} />
349
- </PageWrapper>
350
- );
351
- };
352
-
353
- // Controller component that uses context to get print mode state
354
- const PageController: React.FC<{
355
- renderView: () => React.ReactNode;
356
- renderPrintView: () => React.ReactNode;
357
- }> = ({ renderView, renderPrintView }) => {
358
- const { isPrintMode } = usePageContext();
359
- return <>{isPrintMode ? renderPrintView() : renderView()}</>;
360
- };
361
-
362
- /**
363
- * PageComponent - Base class for pages that provide view functions
364
- */
365
- export abstract class PageComponent<P = {}, S = {}> extends React.Component<P, S> {
366
- /**
367
- * Override this method to provide page configuration
368
- */
369
- abstract getPageProps(): PageProps;
370
-
371
- /**
372
- * Override this method to provide the normal view content
373
- */
374
- abstract renderView(): React.ReactNode;
375
-
376
- /**
377
- * Override this method to provide the print view content
378
- */
379
- abstract renderPrintView(): React.ReactNode;
380
-
381
- /**
382
- * Render method - uses functional Page as controller
383
- */
384
374
  render() {
385
- const pageProps = this.getPageProps();
386
-
375
+ const merged: PageProps = {
376
+ ...(this.props as PageProps),
377
+ ...(this.getPageProps() as PageProps)
378
+ };
387
379
  return (
388
- <Page
389
- {...pageProps}
380
+ <PageView
381
+ {...merged}
390
382
  renderView={() => this.renderView()}
391
383
  renderPrintView={() => this.renderPrintView()}
392
384
  />
@@ -3,9 +3,8 @@
3
3
  *
4
4
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
5
5
  */
6
- export { PageComponent, usePageContext } from './Page';
7
6
  export { default as FormPage } from './FormPage';
8
- export { default as Page } from './Page';
7
+ export { default as Page, usePageContext } from './Page';
9
8
 
10
9
  export type { FormPageProps } from './FormPage';
11
- export type { PageProps, PageContextValue } from './Page';
10
+ export type { PageContextValue, PageProps } from './Page';