@qwickapps/react-framework 1.4.1 → 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.
- package/QUICK_START_GUIDE.md +82 -0
- package/README.md +221 -21
- package/dist/components/Html.d.ts.map +1 -1
- package/dist/components/Markdown.d.ts +1 -2
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/SafeSpan.d.ts +1 -2
- package/dist/components/SafeSpan.d.ts.map +1 -1
- package/dist/components/base/Container.d.ts +32 -0
- package/dist/components/base/Container.d.ts.map +1 -0
- package/dist/components/base/ContainerView.d.ts +65 -0
- package/dist/components/base/ContainerView.d.ts.map +1 -0
- package/dist/components/base/ModelView.d.ts +37 -46
- package/dist/components/base/ModelView.d.ts.map +1 -1
- package/dist/components/base/index.d.ts +3 -2
- package/dist/components/base/index.d.ts.map +1 -1
- package/dist/components/blocks/Article.d.ts +1 -2
- package/dist/components/blocks/Article.d.ts.map +1 -1
- package/dist/components/blocks/Code-factory.d.ts +22 -0
- package/dist/components/blocks/Code-factory.d.ts.map +1 -0
- package/dist/components/blocks/Code-old.d.ts +31 -0
- package/dist/components/blocks/Code-old.d.ts.map +1 -0
- package/dist/components/blocks/Code.d.ts +30 -18
- package/dist/components/blocks/Code.d.ts.map +1 -1
- package/dist/components/blocks/HeroBlock.d.ts +1 -2
- package/dist/components/blocks/HeroBlock.d.ts.map +1 -1
- package/dist/components/blocks/Image.d.ts +1 -2
- package/dist/components/blocks/Image.d.ts.map +1 -1
- package/dist/components/blocks/Section.d.ts +1 -2
- package/dist/components/blocks/Section.d.ts.map +1 -1
- package/dist/components/blocks/Text.d.ts +35 -27
- package/dist/components/blocks/Text.d.ts.map +1 -1
- package/dist/components/buttons/Button.d.ts +1 -2
- package/dist/components/buttons/Button.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/input/ChoiceInputField.d.ts +1 -2
- package/dist/components/input/ChoiceInputField.d.ts.map +1 -1
- package/dist/components/input/HtmlInputField.d.ts +1 -2
- package/dist/components/input/HtmlInputField.d.ts.map +1 -1
- package/dist/components/input/SelectInputField.d.ts +1 -2
- package/dist/components/input/SelectInputField.d.ts.map +1 -1
- package/dist/components/pages/Page.d.ts +29 -47
- package/dist/components/pages/Page.d.ts.map +1 -1
- package/dist/components/pages/index.d.ts +2 -3
- package/dist/components/pages/index.d.ts.map +1 -1
- package/dist/components/shared/createSerializableView.d.ts +68 -0
- package/dist/components/shared/createSerializableView.d.ts.map +1 -0
- package/dist/components/shared/viewProps.d.ts +37 -0
- package/dist/components/shared/viewProps.d.ts.map +1 -0
- package/dist/index.esm.js +21782 -22580
- package/dist/index.js +21782 -22579
- package/dist/qa/ConsoleWarningTest.d.ts +5 -0
- package/dist/qa/ConsoleWarningTest.d.ts.map +1 -0
- package/dist/qa/StorageKeyTest.d.ts +6 -0
- package/dist/qa/StorageKeyTest.d.ts.map +1 -0
- package/dist/qa/ThemeStorageKeyTest.d.ts +6 -0
- package/dist/qa/ThemeStorageKeyTest.d.ts.map +1 -0
- package/dist/schemas/CodeSchema.d.ts +2 -2
- package/dist/schemas/CodeSchema.d.ts.map +1 -1
- package/dist/schemas/ContainerSchema.d.ts +12 -0
- package/dist/schemas/ContainerSchema.d.ts.map +1 -0
- package/dist/schemas/PageTemplateSchema.d.ts +3 -3
- package/dist/schemas/PageTemplateSchema.d.ts.map +1 -1
- package/dist/schemas/ViewModelSchema.d.ts +46 -6
- package/dist/schemas/ViewModelSchema.d.ts.map +1 -1
- package/dist/schemas/ViewSchema.d.ts +65 -0
- package/dist/schemas/ViewSchema.d.ts.map +1 -0
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/transformers/ComponentTransformer.d.ts +27 -15
- package/dist/schemas/transformers/ComponentTransformer.d.ts.map +1 -1
- package/dist/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -1
- package/dist/schemas/transformers/registry.d.ts +3 -0
- package/dist/schemas/transformers/registry.d.ts.map +1 -1
- package/dist/src/__tests__/schemas/transformers/MockSerializableComponent.d.ts +66 -0
- package/dist/src/__tests__/schemas/transformers/MockSerializableComponent.d.ts.map +1 -0
- package/dist/src/components/AccessibilityChecker.d.ts +12 -0
- package/dist/src/components/AccessibilityChecker.d.ts.map +1 -0
- package/dist/src/components/AccessibilityProvider.d.ts +64 -0
- package/dist/src/components/AccessibilityProvider.d.ts.map +1 -0
- package/dist/src/components/Breadcrumbs.d.ts +39 -0
- package/dist/src/components/Breadcrumbs.d.ts.map +1 -0
- package/dist/src/components/ErrorBoundary.d.ts +46 -0
- package/dist/src/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/src/components/Html.d.ts +58 -0
- package/dist/src/components/Html.d.ts.map +1 -0
- package/dist/src/components/Logo.d.ts +56 -0
- package/dist/src/components/Logo.d.ts.map +1 -0
- package/dist/src/components/Markdown.d.ts +51 -0
- package/dist/src/components/Markdown.d.ts.map +1 -0
- package/dist/src/components/QwickApp.d.ts +69 -0
- package/dist/src/components/QwickApp.d.ts.map +1 -0
- package/dist/src/components/QwickAppsLogo.d.ts +25 -0
- package/dist/src/components/QwickAppsLogo.d.ts.map +1 -0
- package/dist/src/components/QwickIcon.d.ts +23 -0
- package/dist/src/components/QwickIcon.d.ts.map +1 -0
- package/dist/src/components/ResponsiveMenu.d.ts +38 -0
- package/dist/src/components/ResponsiveMenu.d.ts.map +1 -0
- package/dist/src/components/SafeSpan.d.ts +29 -0
- package/dist/src/components/SafeSpan.d.ts.map +1 -0
- package/dist/src/components/Scaffold.d.ts +57 -0
- package/dist/src/components/Scaffold.d.ts.map +1 -0
- package/dist/src/components/base/Container.d.ts +33 -0
- package/dist/src/components/base/Container.d.ts.map +1 -0
- package/dist/src/components/base/ModelView.d.ts +92 -0
- package/dist/src/components/base/ModelView.d.ts.map +1 -0
- package/dist/src/components/base/index.d.ts +12 -0
- package/dist/src/components/base/index.d.ts.map +1 -0
- package/dist/src/components/blocks/Article.d.ts +32 -0
- package/dist/src/components/blocks/Article.d.ts.map +1 -0
- package/dist/src/components/blocks/CardListGrid.d.ts +23 -0
- package/dist/src/components/blocks/CardListGrid.d.ts.map +1 -0
- package/dist/src/components/blocks/Code.d.ts +37 -0
- package/dist/src/components/blocks/Code.d.ts.map +1 -0
- package/dist/src/components/blocks/Content.d.ts +24 -0
- package/dist/src/components/blocks/Content.d.ts.map +1 -0
- package/dist/src/components/blocks/CoverImageHeader.d.ts +44 -0
- package/dist/src/components/blocks/CoverImageHeader.d.ts.map +1 -0
- package/dist/src/components/blocks/FeatureCard.d.ts +66 -0
- package/dist/src/components/blocks/FeatureCard.d.ts.map +1 -0
- package/dist/src/components/blocks/FeatureGrid.d.ts +48 -0
- package/dist/src/components/blocks/FeatureGrid.d.ts.map +1 -0
- package/dist/src/components/blocks/Footer.d.ts +56 -0
- package/dist/src/components/blocks/Footer.d.ts.map +1 -0
- package/dist/src/components/blocks/HeroBlock.d.ts +55 -0
- package/dist/src/components/blocks/HeroBlock.d.ts.map +1 -0
- package/dist/src/components/blocks/Image.d.ts +40 -0
- package/dist/src/components/blocks/Image.d.ts.map +1 -0
- package/dist/src/components/blocks/PageBannerHeader.d.ts +30 -0
- package/dist/src/components/blocks/PageBannerHeader.d.ts.map +1 -0
- package/dist/src/components/blocks/ProductCard.d.ts +57 -0
- package/dist/src/components/blocks/ProductCard.d.ts.map +1 -0
- package/dist/src/components/blocks/Section.d.ts +45 -0
- package/dist/src/components/blocks/Section.d.ts.map +1 -0
- package/dist/src/components/blocks/Text.d.ts +34 -0
- package/dist/src/components/blocks/Text.d.ts.map +1 -0
- package/dist/src/components/blocks/index.d.ts +41 -0
- package/dist/src/components/blocks/index.d.ts.map +1 -0
- package/dist/src/components/buttons/Button.d.ts +41 -0
- package/dist/src/components/buttons/Button.d.ts.map +1 -0
- package/dist/src/components/buttons/PaletteSwitcher.d.ts +24 -0
- package/dist/src/components/buttons/PaletteSwitcher.d.ts.map +1 -0
- package/dist/src/components/buttons/ThemeSwitcher.d.ts +24 -0
- package/dist/src/components/buttons/ThemeSwitcher.d.ts.map +1 -0
- package/dist/src/components/buttons/index.d.ts +11 -0
- package/dist/src/components/buttons/index.d.ts.map +1 -0
- package/dist/src/components/forms/FormBlock.d.ts +51 -0
- package/dist/src/components/forms/FormBlock.d.ts.map +1 -0
- package/dist/src/components/forms/index.d.ts +8 -0
- package/dist/src/components/forms/index.d.ts.map +1 -0
- package/dist/src/components/index.d.ts +41 -0
- package/dist/src/components/index.d.ts.map +1 -0
- package/dist/src/components/input/ChoiceInputField.d.ts +29 -0
- package/dist/src/components/input/ChoiceInputField.d.ts.map +1 -0
- package/dist/src/components/input/HtmlInputField.d.ts +33 -0
- package/dist/src/components/input/HtmlInputField.d.ts.map +1 -0
- package/dist/src/components/input/SelectInputField.d.ts +31 -0
- package/dist/src/components/input/SelectInputField.d.ts.map +1 -0
- package/dist/src/components/input/SwitchInputField.d.ts +27 -0
- package/dist/src/components/input/SwitchInputField.d.ts.map +1 -0
- package/dist/src/components/input/TextField.d.ts +18 -0
- package/dist/src/components/input/TextField.d.ts.map +1 -0
- package/dist/src/components/input/TextInputField.d.ts +34 -0
- package/dist/src/components/input/TextInputField.d.ts.map +1 -0
- package/dist/src/components/input/index.d.ts +19 -0
- package/dist/src/components/input/index.d.ts.map +1 -0
- package/dist/src/components/layout/CollapsibleLayout/CollapsibleLayout.d.ts +34 -0
- package/dist/src/components/layout/CollapsibleLayout/CollapsibleLayout.d.ts.map +1 -0
- package/dist/src/components/layout/CollapsibleLayout/index.d.ts +9 -0
- package/dist/src/components/layout/CollapsibleLayout/index.d.ts.map +1 -0
- package/dist/src/components/layout/GridCell.d.ts +32 -0
- package/dist/src/components/layout/GridCell.d.ts.map +1 -0
- package/dist/src/components/layout/GridCellWrapper.d.ts +46 -0
- package/dist/src/components/layout/GridCellWrapper.d.ts.map +1 -0
- package/dist/src/components/layout/GridLayout.d.ts +50 -0
- package/dist/src/components/layout/GridLayout.d.ts.map +1 -0
- package/dist/src/components/layout/index.d.ts +14 -0
- package/dist/src/components/layout/index.d.ts.map +1 -0
- package/dist/src/components/menu/Menu.d.ts +1 -0
- package/dist/src/components/menu/Menu.d.ts.map +1 -0
- package/dist/src/components/menu/MenuItem.d.ts +31 -0
- package/dist/src/components/menu/MenuItem.d.ts.map +1 -0
- package/dist/src/components/menu/index.d.ts +7 -0
- package/dist/src/components/menu/index.d.ts.map +1 -0
- package/dist/src/components/pages/FormPage.d.ts +66 -0
- package/dist/src/components/pages/FormPage.d.ts.map +1 -0
- package/dist/src/components/pages/Page.d.ts +68 -0
- package/dist/src/components/pages/Page.d.ts.map +1 -0
- package/dist/src/components/pages/index.d.ts +10 -0
- package/dist/src/components/pages/index.d.ts.map +1 -0
- package/dist/src/components/shared/createSerializableView.d.ts +81 -0
- package/dist/src/components/shared/createSerializableView.d.ts.map +1 -0
- package/dist/src/components/shared/viewProps.d.ts +37 -0
- package/dist/src/components/shared/viewProps.d.ts.map +1 -0
- package/dist/src/config/AppConfig.d.ts +49 -0
- package/dist/src/config/AppConfig.d.ts.map +1 -0
- package/dist/src/config/AppConfigBuilder.d.ts +75 -0
- package/dist/src/config/AppConfigBuilder.d.ts.map +1 -0
- package/dist/src/config/index.d.ts +13 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/config/types.d.ts +130 -0
- package/dist/src/config/types.d.ts.map +1 -0
- package/dist/src/config.d.ts +15 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/contexts/DataContext.d.ts +139 -0
- package/dist/src/contexts/DataContext.d.ts.map +1 -0
- package/dist/src/contexts/DimensionsContext.d.ts +42 -0
- package/dist/src/contexts/DimensionsContext.d.ts.map +1 -0
- package/dist/src/contexts/PaletteContext.d.ts +53 -0
- package/dist/src/contexts/PaletteContext.d.ts.map +1 -0
- package/dist/src/contexts/PrintModeContext.d.ts +27 -0
- package/dist/src/contexts/PrintModeContext.d.ts.map +1 -0
- package/dist/src/contexts/QwickAppContext.d.ts +71 -0
- package/dist/src/contexts/QwickAppContext.d.ts.map +1 -0
- package/dist/src/contexts/ThemeContext.d.ts +65 -0
- package/dist/src/contexts/ThemeContext.d.ts.map +1 -0
- package/dist/src/contexts/index.d.ts +11 -0
- package/dist/src/contexts/index.d.ts.map +1 -0
- package/dist/src/hooks/index.d.ts +12 -0
- package/dist/src/hooks/index.d.ts.map +1 -0
- package/dist/src/hooks/useBaseProps.d.ts +101 -0
- package/dist/src/hooks/useBaseProps.d.ts.map +1 -0
- package/dist/src/hooks/useDataBinding.d.ts +22 -0
- package/dist/src/hooks/useDataBinding.d.ts.map +1 -0
- package/dist/src/hooks/usePrintMode.d.ts +39 -0
- package/dist/src/hooks/usePrintMode.d.ts.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/palettes/PaletteAutumn.d.ts +10 -0
- package/dist/src/palettes/PaletteAutumn.d.ts.map +1 -0
- package/dist/src/palettes/PaletteCosmic.d.ts +10 -0
- package/dist/src/palettes/PaletteCosmic.d.ts.map +1 -0
- package/dist/src/palettes/PaletteDefault.d.ts +10 -0
- package/dist/src/palettes/PaletteDefault.d.ts.map +1 -0
- package/dist/src/palettes/PaletteOcean.d.ts +10 -0
- package/dist/src/palettes/PaletteOcean.d.ts.map +1 -0
- package/dist/src/palettes/PaletteSpring.d.ts +10 -0
- package/dist/src/palettes/PaletteSpring.d.ts.map +1 -0
- package/dist/src/palettes/PaletteWinter.d.ts +10 -0
- package/dist/src/palettes/PaletteWinter.d.ts.map +1 -0
- package/dist/src/palettes/index.d.ts +13 -0
- package/dist/src/palettes/index.d.ts.map +1 -0
- package/dist/src/schemas/ActionSchema.d.ts +21 -0
- package/dist/src/schemas/ActionSchema.d.ts.map +1 -0
- package/dist/src/schemas/ArticleSchema.d.ts +13 -0
- package/dist/src/schemas/ArticleSchema.d.ts.map +1 -0
- package/dist/src/schemas/ButtonSchema.d.ts +19 -0
- package/dist/src/schemas/ButtonSchema.d.ts.map +1 -0
- package/dist/src/schemas/CardListGridSchema.d.ts +17 -0
- package/dist/src/schemas/CardListGridSchema.d.ts.map +1 -0
- package/dist/src/schemas/ChoiceInputFieldSchema.d.ts +18 -0
- package/dist/src/schemas/ChoiceInputFieldSchema.d.ts.map +1 -0
- package/dist/src/schemas/CodeSchema.d.ts +18 -0
- package/dist/src/schemas/CodeSchema.d.ts.map +1 -0
- package/dist/src/schemas/CollapsibleLayoutSchema.d.ts +32 -0
- package/dist/src/schemas/CollapsibleLayoutSchema.d.ts.map +1 -0
- package/dist/src/schemas/ContainerSchema.d.ts +12 -0
- package/dist/src/schemas/ContainerSchema.d.ts.map +1 -0
- package/dist/src/schemas/ContentSchema.d.ts +21 -0
- package/dist/src/schemas/ContentSchema.d.ts.map +1 -0
- package/dist/src/schemas/CoverImageHeaderSchema.d.ts +28 -0
- package/dist/src/schemas/CoverImageHeaderSchema.d.ts.map +1 -0
- package/dist/src/schemas/FeatureCardSchema.d.ts +28 -0
- package/dist/src/schemas/FeatureCardSchema.d.ts.map +1 -0
- package/dist/src/schemas/FeatureGridSchema.d.ts +17 -0
- package/dist/src/schemas/FeatureGridSchema.d.ts.map +1 -0
- package/dist/src/schemas/FeatureItemSchema.d.ts +16 -0
- package/dist/src/schemas/FeatureItemSchema.d.ts.map +1 -0
- package/dist/src/schemas/FooterItemSchema.d.ts +15 -0
- package/dist/src/schemas/FooterItemSchema.d.ts.map +1 -0
- package/dist/src/schemas/FooterSchema.d.ts +20 -0
- package/dist/src/schemas/FooterSchema.d.ts.map +1 -0
- package/dist/src/schemas/FooterSectionSchema.d.ts +15 -0
- package/dist/src/schemas/FooterSectionSchema.d.ts.map +1 -0
- package/dist/src/schemas/FormBlockSchema.d.ts +19 -0
- package/dist/src/schemas/FormBlockSchema.d.ts.map +1 -0
- package/dist/src/schemas/GridCellSchema.d.ts +23 -0
- package/dist/src/schemas/GridCellSchema.d.ts.map +1 -0
- package/dist/src/schemas/GridLayoutSchema.d.ts +21 -0
- package/dist/src/schemas/GridLayoutSchema.d.ts.map +1 -0
- package/dist/src/schemas/HeaderActionSchema.d.ts +17 -0
- package/dist/src/schemas/HeaderActionSchema.d.ts.map +1 -0
- package/dist/src/schemas/HeroBlockSchema.d.ts +22 -0
- package/dist/src/schemas/HeroBlockSchema.d.ts.map +1 -0
- package/dist/src/schemas/HtmlInputFieldSchema.d.ts +18 -0
- package/dist/src/schemas/HtmlInputFieldSchema.d.ts.map +1 -0
- package/dist/src/schemas/HtmlSchema.d.ts +14 -0
- package/dist/src/schemas/HtmlSchema.d.ts.map +1 -0
- package/dist/src/schemas/ImageSchema.d.ts +32 -0
- package/dist/src/schemas/ImageSchema.d.ts.map +1 -0
- package/dist/src/schemas/LogoSchema.d.ts +35 -0
- package/dist/src/schemas/LogoSchema.d.ts.map +1 -0
- package/dist/src/schemas/MarkdownSchema.d.ts +14 -0
- package/dist/src/schemas/MarkdownSchema.d.ts.map +1 -0
- package/dist/src/schemas/MetadataItemSchema.d.ts +13 -0
- package/dist/src/schemas/MetadataItemSchema.d.ts.map +1 -0
- package/dist/src/schemas/PageBannerHeaderSchema.d.ts +28 -0
- package/dist/src/schemas/PageBannerHeaderSchema.d.ts.map +1 -0
- package/dist/src/schemas/PageTemplateSchema.d.ts +31 -0
- package/dist/src/schemas/PageTemplateSchema.d.ts.map +1 -0
- package/dist/src/schemas/PaletteSwitcherSchema.d.ts +16 -0
- package/dist/src/schemas/PaletteSwitcherSchema.d.ts.map +1 -0
- package/dist/src/schemas/PrintConfigSchema.d.ts +31 -0
- package/dist/src/schemas/PrintConfigSchema.d.ts.map +1 -0
- package/dist/src/schemas/ProductCardSchema.d.ts +39 -0
- package/dist/src/schemas/ProductCardSchema.d.ts.map +1 -0
- package/dist/src/schemas/SafeSpanSchema.d.ts +13 -0
- package/dist/src/schemas/SafeSpanSchema.d.ts.map +1 -0
- package/dist/src/schemas/SectionSchema.d.ts +16 -0
- package/dist/src/schemas/SectionSchema.d.ts.map +1 -0
- package/dist/src/schemas/SelectInputFieldSchema.d.ts +27 -0
- package/dist/src/schemas/SelectInputFieldSchema.d.ts.map +1 -0
- package/dist/src/schemas/SwitchInputFieldSchema.d.ts +18 -0
- package/dist/src/schemas/SwitchInputFieldSchema.d.ts.map +1 -0
- package/dist/src/schemas/TextInputFieldSchema.d.ts +22 -0
- package/dist/src/schemas/TextInputFieldSchema.d.ts.map +1 -0
- package/dist/src/schemas/TextSchema.d.ts +37 -0
- package/dist/src/schemas/TextSchema.d.ts.map +1 -0
- package/dist/src/schemas/ThemeSwitcherSchema.d.ts +19 -0
- package/dist/src/schemas/ThemeSwitcherSchema.d.ts.map +1 -0
- package/dist/src/schemas/ViewSchema.d.ts +66 -0
- package/dist/src/schemas/ViewSchema.d.ts.map +1 -0
- package/dist/src/schemas/index.d.ts +47 -0
- package/dist/src/schemas/index.d.ts.map +1 -0
- package/dist/src/schemas/transformers/ComponentTransformer.d.ts +128 -0
- package/dist/src/schemas/transformers/ComponentTransformer.d.ts.map +1 -0
- package/dist/src/schemas/transformers/ReactNodeTransformer.d.ts +53 -0
- package/dist/src/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -0
- package/dist/src/schemas/transformers/registry.d.ts +18 -0
- package/dist/src/schemas/transformers/registry.d.ts.map +1 -0
- package/dist/src/schemas/types/Serializable.d.ts +46 -0
- package/dist/src/schemas/types/Serializable.d.ts.map +1 -0
- package/dist/src/stories/_templates/SerializationTemplate.d.ts +44 -0
- package/dist/src/stories/_templates/SerializationTemplate.d.ts.map +1 -0
- package/dist/src/templates/TemplateResolver.d.ts +52 -0
- package/dist/src/templates/TemplateResolver.d.ts.map +1 -0
- package/dist/src/templates/index.d.ts +7 -0
- package/dist/src/templates/index.d.ts.map +1 -0
- package/dist/src/types/CacheProvider.d.ts +18 -0
- package/dist/src/types/CacheProvider.d.ts.map +1 -0
- package/dist/src/types/CollapsibleLayout.d.ts +142 -0
- package/dist/src/types/CollapsibleLayout.d.ts.map +1 -0
- package/dist/src/types/ContentProxy.d.ts +47 -0
- package/dist/src/types/ContentProxy.d.ts.map +1 -0
- package/dist/src/types/DataTypes.d.ts +185 -0
- package/dist/src/types/DataTypes.d.ts.map +1 -0
- package/dist/src/types/TemplateProvider.d.ts +10 -0
- package/dist/src/types/TemplateProvider.d.ts.map +1 -0
- package/dist/src/types/TemplateResolver.d.ts +23 -0
- package/dist/src/types/TemplateResolver.d.ts.map +1 -0
- package/dist/src/types/index.d.ts +82 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/utils/breakpoints.d.ts +35 -0
- package/dist/src/utils/breakpoints.d.ts.map +1 -0
- package/dist/src/utils/cssUtils.d.ts +17 -0
- package/dist/src/utils/cssUtils.d.ts.map +1 -0
- package/dist/src/utils/customPaletteManager.d.ts +8 -0
- package/dist/src/utils/customPaletteManager.d.ts.map +1 -0
- package/dist/src/utils/dimensions.d.ts +34 -0
- package/dist/src/utils/dimensions.d.ts.map +1 -0
- package/dist/src/utils/htmlTransform.d.ts +44 -0
- package/dist/src/utils/htmlTransform.d.ts.map +1 -0
- package/dist/src/utils/index.d.ts +16 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/logger.d.ts +26 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/paletteUtils.d.ts +38 -0
- package/dist/src/utils/paletteUtils.d.ts.map +1 -0
- package/dist/src/utils/persistenceUtils.d.ts +31 -0
- package/dist/src/utils/persistenceUtils.d.ts.map +1 -0
- package/dist/src/utils/reactUtils.d.ts +33 -0
- package/dist/src/utils/reactUtils.d.ts.map +1 -0
- package/dist/src/utils/spacing.d.ts +34 -0
- package/dist/src/utils/spacing.d.ts.map +1 -0
- package/dist/src/utils/themePerformanceMonitor.d.ts +32 -0
- package/dist/src/utils/themePerformanceMonitor.d.ts.map +1 -0
- package/dist/src/utils/themeUtils.d.ts +27 -0
- package/dist/src/utils/themeUtils.d.ts.map +1 -0
- package/dist/utils/cssUtils.d.ts +17 -0
- package/dist/utils/cssUtils.d.ts.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +5 -2
- package/scripts/bundle-css.cjs +27 -0
- package/scripts/create-project.sh +28 -0
- package/scripts/create-qwickapps-project.js +284 -0
- package/src/__tests__/components/base/Container.test.tsx +966 -0
- package/src/__tests__/schemas/PageTemplateSchema.test.ts +1 -1
- package/src/__tests__/schemas/ViewSchema.test.ts +805 -0
- package/src/__tests__/schemas/builders.test.ts +2 -2
- package/src/__tests__/schemas/transformers/ComponentTransformer.test.ts +19 -19
- package/src/__tests__/schemas/transformers/CrossBrowserCompatibility.test.ts +13 -13
- package/src/__tests__/schemas/transformers/SerializationErrorHandling.test.ts +39 -39
- package/src/__tests__/schemas/transformers/SerializationPerformance.test.ts +14 -14
- package/src/__tests__/schemas/transformers/TestAutomation.test.ts +8 -8
- package/src/__tests__/schemas/transformers/nested-serialization.test.tsx +181 -0
- package/src/__tests__/schemas/transformers/round-trip-component-serialization.test.tsx +458 -0
- package/src/__tests__/test_image_accessibility.test.tsx +226 -0
- package/src/__tests__/utils/optional-logging.test.ts +3 -3
- package/src/components/Html.tsx +24 -15
- package/src/components/Logo.tsx +2 -2
- package/src/components/Markdown.tsx +2 -7
- package/src/components/SafeSpan.tsx +2 -7
- package/src/components/base/Container.tsx +61 -0
- package/src/components/base/ModelView.tsx +225 -91
- package/src/components/base/index.ts +3 -2
- package/src/components/blocks/Article.tsx +2 -7
- package/src/components/blocks/CardListGrid.tsx +2 -2
- package/src/components/blocks/Code.tsx +91 -179
- package/src/components/blocks/Content.tsx +2 -2
- package/src/components/blocks/CoverImageHeader.tsx +2 -2
- package/src/components/blocks/HeroBlock.tsx +54 -146
- package/src/components/blocks/Image.tsx +82 -196
- package/src/components/blocks/PageBannerHeader.tsx +2 -2
- package/src/components/blocks/Section.tsx +79 -181
- package/src/components/blocks/Text.tsx +100 -198
- package/src/components/buttons/Button.tsx +85 -183
- package/src/components/buttons/PaletteSwitcher.tsx +2 -2
- package/src/components/buttons/ThemeSwitcher.tsx +2 -2
- package/src/components/forms/FormBlock.tsx +2 -2
- package/src/components/index.ts +5 -0
- package/src/components/input/ChoiceInputField.tsx +76 -160
- package/src/components/input/HtmlInputField.tsx +141 -264
- package/src/components/input/SelectInputField.tsx +48 -153
- package/src/components/input/SwitchInputField.tsx +41 -139
- package/src/components/input/TextInputField.tsx +39 -116
- package/src/components/layout/GridCell.tsx +36 -122
- package/src/components/layout/GridLayout.tsx +55 -127
- package/src/components/pages/Page.tsx +268 -276
- package/src/components/pages/index.ts +2 -3
- package/src/components/shared/createSerializableView.tsx +280 -0
- package/src/components/shared/viewProps.ts +207 -0
- package/src/config/__tests__/AppConfigBuilder.test.ts +2 -2
- package/src/contexts/DataContext.tsx +1 -1
- package/src/schemas/ButtonSchema.ts +3 -2
- package/src/schemas/CardListGridSchema.ts +3 -2
- package/src/schemas/ChoiceInputFieldSchema.ts +3 -2
- package/src/schemas/CodeSchema.ts +8 -6
- package/src/schemas/ContainerSchema.ts +25 -0
- package/src/schemas/FeatureCardSchema.ts +1 -1
- package/src/schemas/FormBlockSchema.ts +3 -2
- package/src/schemas/GridCellSchema.ts +4 -10
- package/src/schemas/GridLayoutSchema.ts +8 -14
- package/src/schemas/HeroBlockSchema.ts +3 -2
- package/src/schemas/HtmlInputFieldSchema.ts +3 -2
- package/src/schemas/ImageSchema.ts +3 -2
- package/src/schemas/PageTemplateSchema.ts +5 -5
- package/src/schemas/SectionSchema.ts +4 -12
- package/src/schemas/SelectInputFieldSchema.ts +3 -2
- package/src/schemas/SwitchInputFieldSchema.ts +2 -2
- package/src/schemas/TextInputFieldSchema.ts +3 -2
- package/src/schemas/ViewSchema.ts +570 -0
- package/src/schemas/index.ts +1 -1
- package/src/schemas/transformers/ComponentTransformer.ts +185 -163
- package/src/schemas/transformers/ReactNodeTransformer.ts +31 -28
- package/src/schemas/transformers/registry.ts +17 -10
- package/src/stories/Button.stories.tsx +24 -0
- package/src/stories/ChoiceInputField.stories.tsx +28 -1
- package/src/stories/Code.stories.tsx +61 -1
- package/src/stories/Container.stories.tsx +954 -0
- package/src/stories/FormBlock.stories.tsx +54 -0
- package/src/stories/FormComponents.stories.tsx +8 -13
- package/src/stories/GridCell.stories.tsx +23 -64
- package/src/stories/GridLayout.stories.tsx +22 -47
- package/src/stories/HeroBlock.stories.tsx +28 -0
- package/src/stories/HtmlInputField.stories.tsx +23 -1
- package/src/stories/Image.stories.tsx +45 -233
- package/src/stories/Markdown.stories.tsx +1 -1
- package/src/stories/Section.stories.tsx +38 -4
- package/src/stories/SelectInputField.stories.tsx +26 -1
- package/src/stories/Text.stories.tsx +22 -54
- package/src/stories/TextInputField.stories.tsx +24 -1
- package/src/stories/_templates/SerializationTemplate.tsx +165 -0
- package/src/templates/TemplateResolver.ts +2 -2
- package/src/types/CollapsibleLayout.ts +2 -2
- package/src/utils/cssUtils.ts +49 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/logger.ts +13 -13
- package/src/__tests__/components/base/ModelView.test.tsx +0 -220
- package/src/__tests__/schemas/ViewModelSchema.test.ts +0 -80
- package/src/components/blocks/Code.md +0 -529
- package/src/schemas/README.md +0 -661
- package/src/schemas/ViewModelSchema.ts +0 -115
- package/src/tests/ConsoleWarningTest.tsx +0 -30
- package/src/tests/StorageKeyTest.tsx +0 -110
- package/src/tests/ThemeStorageKeyTest.tsx +0 -114
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createSerializableView - Factory for schema-driven components
|
|
3
|
+
*
|
|
4
|
+
* Creates functional components that:
|
|
5
|
+
* - Normalize schema props using normalizeViewProps
|
|
6
|
+
* - Apply useBaseProps exactly once for style/html/grid processing
|
|
7
|
+
* - Optionally integrate data binding (gated by enabled flag)
|
|
8
|
+
* - Attach static tagName/version/fromJson/toJson for serialization
|
|
9
|
+
*
|
|
10
|
+
* Works seamlessly with existing BaseComponentProps system and provides
|
|
11
|
+
* the foundation for the new schema-driven architecture.
|
|
12
|
+
*
|
|
13
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import React, { ComponentType, ReactElement, ReactNode } from 'react';
|
|
17
|
+
// SerializableConstructor type is defined inline below
|
|
18
|
+
import { useBaseProps, useDataBinding, QWICKAPP_COMPONENT } from '../../hooks';
|
|
19
|
+
import { normalizeViewProps, ViewProps } from './viewProps';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Helper function to convert React children to text content
|
|
23
|
+
* Used for content-prop strategy to map JSX children to content strings
|
|
24
|
+
*/
|
|
25
|
+
function toText(node: ReactNode): string | undefined {
|
|
26
|
+
if (node == null || typeof node === 'boolean') return undefined;
|
|
27
|
+
if (typeof node === 'string' || typeof node === 'number') return String(node);
|
|
28
|
+
if (Array.isArray(node)) return node.map(toText).filter(Boolean).join('');
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Children handling strategy for serialization
|
|
34
|
+
*/
|
|
35
|
+
type ChildrenStrategy =
|
|
36
|
+
| { mode: 'react-children' }
|
|
37
|
+
| { mode: 'content-prop'; propName?: string };
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Component factory configuration
|
|
41
|
+
*/
|
|
42
|
+
interface CreateSerializableViewConfig<P extends ViewProps> {
|
|
43
|
+
/** Component tag name for serialization */
|
|
44
|
+
tagName: string;
|
|
45
|
+
/** Component version for serialization */
|
|
46
|
+
version: string;
|
|
47
|
+
/** Component role: 'view' for display components, 'container' for layout components */
|
|
48
|
+
role: 'view' | 'container';
|
|
49
|
+
/** View function that renders the component */
|
|
50
|
+
View: ComponentType<P>;
|
|
51
|
+
/** Children handling strategy - defaults to 'react-children' */
|
|
52
|
+
childrenStrategy?: ChildrenStrategy;
|
|
53
|
+
/** Optional prop finalizer function */
|
|
54
|
+
finalize?: (props: P) => P;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Serializable component interface with all required static properties
|
|
59
|
+
*/
|
|
60
|
+
export interface SerializableComponent<P extends ViewProps> {
|
|
61
|
+
(props: P): ReactElement;
|
|
62
|
+
tagName: string;
|
|
63
|
+
version: string;
|
|
64
|
+
fromJson: (data: any) => ReactElement;
|
|
65
|
+
toJson: (props: P) => any;
|
|
66
|
+
displayName?: string;
|
|
67
|
+
[QWICKAPP_COMPONENT]: symbol;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Create a serializable view component using the factory pattern
|
|
72
|
+
*
|
|
73
|
+
* @param config - Factory configuration
|
|
74
|
+
* @returns Serializable component with attached static methods
|
|
75
|
+
*/
|
|
76
|
+
export function createSerializableView<P extends ViewProps>(
|
|
77
|
+
config: CreateSerializableViewConfig<P>
|
|
78
|
+
): SerializableComponent<P> {
|
|
79
|
+
const { tagName, version, role, View, childrenStrategy = { mode: 'react-children' }, finalize } = config;
|
|
80
|
+
|
|
81
|
+
// Create the main component function
|
|
82
|
+
function SerializableViewComponent(props: P): ReactElement {
|
|
83
|
+
const { dataSource, bindingOptions, children, ...schemaProps } = props as any;
|
|
84
|
+
|
|
85
|
+
// Step 1: Handle content-prop strategy (map JSX children → content)
|
|
86
|
+
let propsForProcessing = schemaProps;
|
|
87
|
+
if (childrenStrategy.mode === 'content-prop') {
|
|
88
|
+
const propName = childrenStrategy.propName || 'content';
|
|
89
|
+
if (propsForProcessing[propName] == null) {
|
|
90
|
+
const textContent = toText(children);
|
|
91
|
+
if (typeof textContent === 'string') {
|
|
92
|
+
propsForProcessing = { ...propsForProcessing, [propName]: textContent };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Step 2: Normalize schema props to runtime-friendly format
|
|
98
|
+
const normalizedProps = normalizeViewProps(propsForProcessing);
|
|
99
|
+
|
|
100
|
+
// Step 2: ALWAYS call all hooks first (Rules of Hooks)
|
|
101
|
+
const { loading, error, ...resolvedProps } = useDataBinding(
|
|
102
|
+
dataSource || undefined, // Pass undefined if no dataSource
|
|
103
|
+
normalizedProps,
|
|
104
|
+
undefined, // Schema - let the hook infer it
|
|
105
|
+
dataSource ? { cache: true, cacheTTL: 300000, strict: false, ...bindingOptions } : { enabled: false }
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// Determine which props to use based on data binding state
|
|
109
|
+
let boundProps = normalizedProps;
|
|
110
|
+
if (dataSource && !error) {
|
|
111
|
+
boundProps = { ...normalizedProps, ...resolvedProps };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Step 3: Apply useBaseProps for style/html/grid processing (ALWAYS call this hook)
|
|
115
|
+
const { gridProps, styleProps, htmlProps, restProps } = useBaseProps(boundProps);
|
|
116
|
+
|
|
117
|
+
// Step 4: Handle special states AFTER all hooks have been called
|
|
118
|
+
if (dataSource && loading) {
|
|
119
|
+
return <div>Loading...</div> as ReactElement;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (dataSource && error) {
|
|
123
|
+
console.error('Data binding error:', error);
|
|
124
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
125
|
+
return <div style={{ color: 'red', padding: '1rem', border: '1px solid red' }}>
|
|
126
|
+
Error loading data: {error.message}
|
|
127
|
+
</div> as ReactElement;
|
|
128
|
+
}
|
|
129
|
+
// In production, continue with fallback props (already set above)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Step 5: Prepare final props and apply optional finalize function
|
|
133
|
+
let viewProps = {
|
|
134
|
+
...restProps,
|
|
135
|
+
...styleProps,
|
|
136
|
+
...htmlProps,
|
|
137
|
+
// Grid props are passed separately if needed by container components
|
|
138
|
+
...(role === 'container' && gridProps ? { gridProps } : {}),
|
|
139
|
+
} as P;
|
|
140
|
+
|
|
141
|
+
// Apply finalize function if provided
|
|
142
|
+
if (finalize) {
|
|
143
|
+
viewProps = finalize(viewProps);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Step 6: Render with appropriate children strategy
|
|
147
|
+
if (childrenStrategy.mode === 'content-prop') {
|
|
148
|
+
// For content-prop components, don't pass children to the view
|
|
149
|
+
return <View {...viewProps} />;
|
|
150
|
+
} else {
|
|
151
|
+
// For react-children components, pass children through
|
|
152
|
+
return <View {...viewProps}>{children}</View>;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Attach static properties for serialization
|
|
157
|
+
const component = SerializableViewComponent as unknown as SerializableComponent<P>;
|
|
158
|
+
|
|
159
|
+
// Component identification
|
|
160
|
+
component.tagName = tagName;
|
|
161
|
+
component.version = version;
|
|
162
|
+
component[QWICKAPP_COMPONENT] = QWICKAPP_COMPONENT;
|
|
163
|
+
|
|
164
|
+
// Serialization methods
|
|
165
|
+
component.fromJson = function fromJson(data: any): ReactElement {
|
|
166
|
+
const { tagName: dataTagName, version: dataVersion, data: componentData } = data;
|
|
167
|
+
|
|
168
|
+
// Validate deserialization data
|
|
169
|
+
if (dataTagName !== tagName) {
|
|
170
|
+
throw new Error(`Tag name mismatch: expected ${tagName}, got ${dataTagName}`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (dataVersion !== version) {
|
|
174
|
+
console.warn(`Version mismatch for ${tagName}: expected ${version}, got ${dataVersion}`);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Handle deserialization based on children strategy
|
|
178
|
+
if (childrenStrategy.mode === 'content-prop') {
|
|
179
|
+
const propName = childrenStrategy.propName || 'content';
|
|
180
|
+
const { children: _ignored, ...rest } = componentData || {};
|
|
181
|
+
const contentData = { ...rest, [propName]: componentData?.[propName] || '' };
|
|
182
|
+
return React.createElement(component as ComponentType<P>, contentData as P);
|
|
183
|
+
} else {
|
|
184
|
+
// For react-children strategy, recursively deserialize children
|
|
185
|
+
const deserializedData = { ...componentData };
|
|
186
|
+
if (componentData.children !== undefined) {
|
|
187
|
+
// Import ComponentTransformer here to avoid circular dependency
|
|
188
|
+
const { ComponentTransformer } = require('../../schemas/transformers/ComponentTransformer');
|
|
189
|
+
deserializedData.children = ComponentTransformer.deserialize(componentData.children);
|
|
190
|
+
}
|
|
191
|
+
return React.createElement(component as ComponentType<P>, deserializedData as P);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
component.toJson = function toJson(props: P): any {
|
|
196
|
+
// Handle serialization based on children strategy
|
|
197
|
+
if (childrenStrategy.mode === 'content-prop') {
|
|
198
|
+
const propName = childrenStrategy.propName || 'content';
|
|
199
|
+
const { children: _ignored, ...rest } = props || {};
|
|
200
|
+
const contentValue = (props as any)?.[propName] ?? toText((props as any)?.children);
|
|
201
|
+
|
|
202
|
+
// Clean props for content-prop serialization
|
|
203
|
+
const cleanProps: any = {};
|
|
204
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
205
|
+
if (typeof value === 'function' && key.startsWith('on')) {
|
|
206
|
+
cleanProps[key] = value.toString();
|
|
207
|
+
} else if (typeof value !== 'function' && value !== undefined && value !== null) {
|
|
208
|
+
cleanProps[key] = value;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
tagName,
|
|
214
|
+
version,
|
|
215
|
+
data: { ...cleanProps, [propName]: contentValue || '' },
|
|
216
|
+
};
|
|
217
|
+
} else {
|
|
218
|
+
// Handle react-children strategy (existing logic)
|
|
219
|
+
const cleanProps: any = {};
|
|
220
|
+
|
|
221
|
+
for (const [key, value] of Object.entries(props)) {
|
|
222
|
+
if (typeof value === 'function' && key.startsWith('on')) {
|
|
223
|
+
// Convert event handlers to string representation
|
|
224
|
+
cleanProps[key] = value.toString();
|
|
225
|
+
} else if (typeof value === 'function') {
|
|
226
|
+
// Skip non-event handler functions
|
|
227
|
+
continue;
|
|
228
|
+
} else if (key === 'children') {
|
|
229
|
+
// IMPORTANT: Include children as-is for recursive serialization by ComponentTransformer
|
|
230
|
+
// The ComponentTransformer.serializeNode() will handle the recursive serialization
|
|
231
|
+
cleanProps[key] = value;
|
|
232
|
+
} else if (value !== undefined && value !== null) {
|
|
233
|
+
// Include all other serializable props
|
|
234
|
+
cleanProps[key] = value;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
tagName,
|
|
240
|
+
version,
|
|
241
|
+
data: cleanProps,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// Set display name for debugging
|
|
247
|
+
component.displayName = `SerializableView(${tagName})`;
|
|
248
|
+
|
|
249
|
+
return component;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Type helper for components created with createSerializableView
|
|
254
|
+
*/
|
|
255
|
+
export type SerializableViewComponent<P extends ViewProps> = SerializableComponent<P>;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Type guard to check if a component is serializable
|
|
259
|
+
*/
|
|
260
|
+
export function isSerializableComponent(component: any): component is SerializableComponent<any> {
|
|
261
|
+
return component &&
|
|
262
|
+
typeof component === 'function' &&
|
|
263
|
+
typeof component.tagName === 'string' &&
|
|
264
|
+
typeof component.version === 'string' &&
|
|
265
|
+
typeof component.fromJson === 'function' &&
|
|
266
|
+
typeof component.toJson === 'function' &&
|
|
267
|
+
component[QWICKAPP_COMPONENT] === QWICKAPP_COMPONENT;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Extract component metadata for registration
|
|
272
|
+
*/
|
|
273
|
+
export function getComponentMetadata(component: SerializableComponent<any>) {
|
|
274
|
+
return {
|
|
275
|
+
tagName: component.tagName,
|
|
276
|
+
version: component.version,
|
|
277
|
+
fromJson: component.fromJson,
|
|
278
|
+
toJson: component.toJson,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ViewProps - Runtime-friendly props derived from ViewSchema
|
|
3
|
+
*
|
|
4
|
+
* Provides normalized view props that integrate seamlessly with the existing
|
|
5
|
+
* BaseComponentProps system and useBaseProps hook. Handles type conversion
|
|
6
|
+
* from schema strings to proper React prop types including event handlers,
|
|
7
|
+
* styling props, and grid values.
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
13
|
+
import type { SchemaProps, WithDataBinding } from '@qwickapps/schema';
|
|
14
|
+
import { BaseComponentProps } from '../../hooks/useBaseProps';
|
|
15
|
+
import { ViewSchema } from '../../schemas/ViewSchema';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* ViewProps - Single source of truth for all base component props
|
|
19
|
+
*
|
|
20
|
+
* Extends SchemaProps<ViewSchema> to get all base properties with proper types
|
|
21
|
+
* and adds WithDataBinding for CMS integration. ViewSchema is the authoritative
|
|
22
|
+
* source for all base props including styling, grid, events, accessibility, etc.
|
|
23
|
+
*/
|
|
24
|
+
export interface ViewProps extends SchemaProps<ViewSchema>, WithDataBinding {
|
|
25
|
+
// Add children prop for components that need it
|
|
26
|
+
children?: React.ReactNode;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Type for string event handlers in schema
|
|
31
|
+
*/
|
|
32
|
+
type EventHandlerValue = string | React.MouseEventHandler<any> | React.FocusEventHandler<any> | undefined;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Runtime event handler conversion map
|
|
36
|
+
*/
|
|
37
|
+
interface EventHandlers {
|
|
38
|
+
onClick?: React.MouseEventHandler<any>;
|
|
39
|
+
onMouseEnter?: React.MouseEventHandler<any>;
|
|
40
|
+
onMouseLeave?: React.MouseEventHandler<any>;
|
|
41
|
+
onFocus?: React.FocusEventHandler<any>;
|
|
42
|
+
onBlur?: React.FocusEventHandler<any>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Convert string event handlers to React function handlers
|
|
47
|
+
* @param eventHandlers - Object containing string or function event handlers
|
|
48
|
+
* @returns Object with converted function handlers
|
|
49
|
+
*/
|
|
50
|
+
function parseEventHandlers(eventHandlers: Record<string, EventHandlerValue>): EventHandlers {
|
|
51
|
+
const result: EventHandlers = {};
|
|
52
|
+
|
|
53
|
+
for (const [key, value] of Object.entries(eventHandlers)) {
|
|
54
|
+
if (typeof value === 'string' && value.trim()) {
|
|
55
|
+
try {
|
|
56
|
+
// Convert string to function - safe eval for event handlers
|
|
57
|
+
// This creates a function that executes the string as code
|
|
58
|
+
const func = new Function('event', value);
|
|
59
|
+
result[key as keyof EventHandlers] = func as any;
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.warn(`Invalid event handler string for ${key}:`, value, error);
|
|
62
|
+
// Keep as undefined for invalid handlers
|
|
63
|
+
}
|
|
64
|
+
} else if (typeof value === 'function') {
|
|
65
|
+
// Already a function, use as-is
|
|
66
|
+
result[key as keyof EventHandlers] = value as any;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Parse SX props from string or object
|
|
75
|
+
* @param sx - SX prop as string or object
|
|
76
|
+
* @returns Parsed SX props
|
|
77
|
+
*/
|
|
78
|
+
function parseSxProps(sx: string | SxProps<Theme> | undefined): SxProps<Theme> | undefined {
|
|
79
|
+
if (!sx) return undefined;
|
|
80
|
+
|
|
81
|
+
if (typeof sx === 'string') {
|
|
82
|
+
try {
|
|
83
|
+
return JSON.parse(sx);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.warn('Invalid sx JSON string:', sx, error);
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return sx;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Parse style props from string or object
|
|
95
|
+
* @param style - Style prop as string or object
|
|
96
|
+
* @returns Parsed style props
|
|
97
|
+
*/
|
|
98
|
+
function parseStyleProps(style: string | React.CSSProperties | undefined): React.CSSProperties | undefined {
|
|
99
|
+
if (!style) return undefined;
|
|
100
|
+
|
|
101
|
+
if (typeof style === 'string') {
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(style);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.warn('Invalid style JSON string:', style, error);
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return style;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Coerce grid values from strings to numbers/keywords
|
|
115
|
+
* @param value - Grid value as string or number
|
|
116
|
+
* @returns Coerced value
|
|
117
|
+
*/
|
|
118
|
+
function coerceGridValue(value: string | number | undefined): number | 'auto' | 'grow' | undefined {
|
|
119
|
+
if (value === undefined || value === null) return undefined;
|
|
120
|
+
|
|
121
|
+
if (typeof value === 'number') return value;
|
|
122
|
+
|
|
123
|
+
if (typeof value === 'string') {
|
|
124
|
+
// Handle keyword values
|
|
125
|
+
if (value === 'auto' || value === 'grow') return value;
|
|
126
|
+
|
|
127
|
+
// Try to parse as number
|
|
128
|
+
const parsed = parseInt(value, 10);
|
|
129
|
+
if (!isNaN(parsed) && parsed > 0) return parsed;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Normalize ViewProps for runtime use
|
|
137
|
+
*
|
|
138
|
+
* Converts schema-friendly string props to runtime-friendly React props:
|
|
139
|
+
* - Parses sx/style JSON strings
|
|
140
|
+
* - Converts string event handlers to functions
|
|
141
|
+
* - Coerces grid span/breakpoint values from strings to numbers/keywords
|
|
142
|
+
* - Maintains compatibility with BaseComponentProps system
|
|
143
|
+
*
|
|
144
|
+
* @param props - Raw ViewProps from schema
|
|
145
|
+
* @returns Normalized props compatible with useBaseProps
|
|
146
|
+
*/
|
|
147
|
+
export function normalizeViewProps<T extends ViewProps>(props: T): T & BaseComponentProps {
|
|
148
|
+
const {
|
|
149
|
+
sx,
|
|
150
|
+
style,
|
|
151
|
+
onClick,
|
|
152
|
+
onMouseEnter,
|
|
153
|
+
onMouseLeave,
|
|
154
|
+
onFocus,
|
|
155
|
+
onBlur,
|
|
156
|
+
span,
|
|
157
|
+
xs,
|
|
158
|
+
sm,
|
|
159
|
+
md,
|
|
160
|
+
lg,
|
|
161
|
+
xl,
|
|
162
|
+
backgroundColor,
|
|
163
|
+
...restProps
|
|
164
|
+
} = props;
|
|
165
|
+
|
|
166
|
+
// Parse style and sx props
|
|
167
|
+
const normalizedSx = parseSxProps(sx);
|
|
168
|
+
const normalizedStyle = parseStyleProps(style);
|
|
169
|
+
|
|
170
|
+
// Parse event handlers
|
|
171
|
+
const eventHandlers = parseEventHandlers({
|
|
172
|
+
onClick,
|
|
173
|
+
onMouseEnter,
|
|
174
|
+
onMouseLeave,
|
|
175
|
+
onFocus,
|
|
176
|
+
onBlur,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Coerce grid values
|
|
180
|
+
const normalizedGridProps = {
|
|
181
|
+
span: coerceGridValue(span),
|
|
182
|
+
xs: coerceGridValue(xs),
|
|
183
|
+
sm: coerceGridValue(sm),
|
|
184
|
+
md: coerceGridValue(md),
|
|
185
|
+
lg: coerceGridValue(lg),
|
|
186
|
+
xl: coerceGridValue(xl),
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Canonicalize background prop (backgroundColor → background)
|
|
190
|
+
const canonicalBackground = (restProps as any).background ?? backgroundColor;
|
|
191
|
+
|
|
192
|
+
// Return normalized props with proper typing
|
|
193
|
+
const normalized = {
|
|
194
|
+
...restProps,
|
|
195
|
+
...normalizedGridProps,
|
|
196
|
+
sx: normalizedSx,
|
|
197
|
+
style: normalizedStyle,
|
|
198
|
+
...eventHandlers,
|
|
199
|
+
// Set canonical background prop
|
|
200
|
+
background: canonicalBackground,
|
|
201
|
+
} as T & BaseComponentProps;
|
|
202
|
+
|
|
203
|
+
// Remove backgroundColor to avoid duplication
|
|
204
|
+
delete (normalized as any).backgroundColor;
|
|
205
|
+
|
|
206
|
+
return normalized;
|
|
207
|
+
}
|
|
@@ -107,7 +107,7 @@ describe('AppConfigBuilder', () => {
|
|
|
107
107
|
.withId('custom-app')
|
|
108
108
|
.withShortName('Custom')
|
|
109
109
|
.withDescription('A custom application')
|
|
110
|
-
.withVersion('
|
|
110
|
+
.withVersion('1.0.0')
|
|
111
111
|
.withLogo('./custom-logo.svg')
|
|
112
112
|
.withPort(4000)
|
|
113
113
|
.withPreviewPort(5000)
|
|
@@ -118,7 +118,7 @@ describe('AppConfigBuilder', () => {
|
|
|
118
118
|
|
|
119
119
|
expect(config.app.shortName).toBe('Custom');
|
|
120
120
|
expect(config.app.description).toBe('A custom application');
|
|
121
|
-
expect(config.app.version).toBe('
|
|
121
|
+
expect(config.app.version).toBe('1.0.0');
|
|
122
122
|
expect(config.app.logo).toBe('./custom-logo.svg');
|
|
123
123
|
expect(config.build.port).toBe(4000);
|
|
124
124
|
expect(config.build.previewPort).toBe(5000);
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
import { IsBoolean, IsOptional, IsString, IsIn } from 'class-validator';
|
|
8
8
|
import 'reflect-metadata';
|
|
9
|
-
import { Editor, Field, Schema,
|
|
9
|
+
import { Editor, Field, Schema, FieldType } from '@qwickapps/schema';
|
|
10
|
+
import { ViewSchema } from './ViewSchema';
|
|
10
11
|
|
|
11
12
|
@Schema('Button', '1.0.0')
|
|
12
|
-
export class ButtonModel extends
|
|
13
|
+
export class ButtonModel extends ViewSchema {
|
|
13
14
|
@Field()
|
|
14
15
|
@Editor({
|
|
15
16
|
field_type: FieldType.TEXT,
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
import { IsArray, IsOptional, IsNumber, IsIn, IsBoolean, IsObject, IsString } from 'class-validator';
|
|
8
8
|
import 'reflect-metadata';
|
|
9
|
-
import { Editor, Field, Schema,
|
|
9
|
+
import { Editor, Field, Schema, FieldType } from '@qwickapps/schema';
|
|
10
|
+
import { ContainerSchema } from './ContainerSchema';
|
|
10
11
|
|
|
11
12
|
@Schema('CardListGrid', '1.0.0')
|
|
12
|
-
export class CardListGridModel extends
|
|
13
|
+
export class CardListGridModel extends ContainerSchema {
|
|
13
14
|
@Field()
|
|
14
15
|
@Editor({
|
|
15
16
|
field_type: FieldType.REPEATER,
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
import { IsArray, IsBoolean, IsNumber, IsOptional, IsString } from 'class-validator';
|
|
8
8
|
import 'reflect-metadata';
|
|
9
|
-
import { Editor, Field, Schema,
|
|
9
|
+
import { Editor, Field, Schema, FieldType } from '@qwickapps/schema';
|
|
10
|
+
import { ViewSchema } from './ViewSchema';
|
|
10
11
|
|
|
11
12
|
@Schema('ChoiceInputField', '1.0.0')
|
|
12
|
-
export class ChoiceInputFieldModel extends
|
|
13
|
+
export class ChoiceInputFieldModel extends ViewSchema {
|
|
13
14
|
@Field()
|
|
14
15
|
@Editor({
|
|
15
16
|
field_type: FieldType.TEXT,
|
|
@@ -7,19 +7,21 @@
|
|
|
7
7
|
import type { ReactNode } from 'react';
|
|
8
8
|
import { IsBoolean, IsOptional, IsString } from 'class-validator';
|
|
9
9
|
import 'reflect-metadata';
|
|
10
|
-
import { Editor, Field, Schema,
|
|
10
|
+
import { Editor, Field, Schema, FieldType } from '@qwickapps/schema';
|
|
11
|
+
import ViewSchema from './ViewSchema';
|
|
11
12
|
|
|
12
13
|
@Schema('Code', '1.0.0')
|
|
13
|
-
export class CodeModel extends
|
|
14
|
+
export class CodeModel extends ViewSchema {
|
|
14
15
|
@Field()
|
|
15
16
|
@Editor({
|
|
16
17
|
field_type: FieldType.TEXTAREA,
|
|
17
|
-
label: '
|
|
18
|
-
description: '
|
|
18
|
+
label: 'Content',
|
|
19
|
+
description: 'Raw code text. If provided, React children are ignored in serialization.',
|
|
19
20
|
placeholder: 'Enter code content...'
|
|
20
21
|
})
|
|
21
|
-
@
|
|
22
|
-
|
|
22
|
+
@IsOptional()
|
|
23
|
+
@IsString()
|
|
24
|
+
content?: string;
|
|
23
25
|
|
|
24
26
|
@Field()
|
|
25
27
|
@Editor({
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ContainerSchema - Comprehensive base class for all container components
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Editor, Field, FieldType, Schema } from '@qwickapps/schema';
|
|
8
|
+
import { IsOptional, IsString } from 'class-validator';
|
|
9
|
+
import type { ReactNode } from 'react';
|
|
10
|
+
import 'reflect-metadata';
|
|
11
|
+
import ViewSchema from './ViewSchema';
|
|
12
|
+
|
|
13
|
+
@Schema('ContainerSchema', '1.0.0')
|
|
14
|
+
export class ContainerSchema extends ViewSchema {
|
|
15
|
+
@Field()
|
|
16
|
+
@Editor({
|
|
17
|
+
field_type: FieldType.TEXTAREA,
|
|
18
|
+
label: 'Content',
|
|
19
|
+
description: 'Main content shown when expanded (HTML supported)',
|
|
20
|
+
placeholder: 'Enter main content...'
|
|
21
|
+
})
|
|
22
|
+
@IsOptional()
|
|
23
|
+
@IsString()
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
}
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
import { IsBoolean, IsIn, IsOptional, IsString } from 'class-validator';
|
|
8
8
|
import 'reflect-metadata';
|
|
9
|
-
import { Editor, Field, Schema,
|
|
9
|
+
import { Editor, Field, Schema, FieldType } from '@qwickapps/schema';
|
|
10
|
+
import { ContainerSchema } from './ContainerSchema';
|
|
10
11
|
|
|
11
12
|
@Schema('FormBlock', '1.0.0')
|
|
12
|
-
export class FormBlockModel extends
|
|
13
|
+
export class FormBlockModel extends ContainerSchema {
|
|
13
14
|
@Field()
|
|
14
15
|
@Editor({
|
|
15
16
|
field_type: FieldType.TEXT,
|
|
@@ -7,18 +7,12 @@
|
|
|
7
7
|
import type { ReactNode } from 'react';
|
|
8
8
|
import { IsOptional, IsString, IsNumber, IsIn } from 'class-validator';
|
|
9
9
|
import 'reflect-metadata';
|
|
10
|
-
import { Editor, Field, Schema,
|
|
10
|
+
import { Editor, Field, Schema, FieldType } from '@qwickapps/schema';
|
|
11
|
+
import { ContainerSchema } from './ContainerSchema';
|
|
11
12
|
|
|
12
13
|
@Schema('GridCell', '1.0.0')
|
|
13
|
-
export class GridCellModel extends
|
|
14
|
-
|
|
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
|
|
14
|
+
export class GridCellModel extends ContainerSchema {
|
|
15
|
+
// children field inherited from ContainerSchema
|
|
22
16
|
|
|
23
17
|
// Grid responsive properties
|
|
24
18
|
@Field()
|