@qwickapps/react-framework 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +44 -0
- package/README.md +794 -0
- package/dist/components/AccessibilityChecker.d.ts +12 -0
- package/dist/components/AccessibilityChecker.d.ts.map +1 -0
- package/dist/components/Html.d.ts +48 -0
- package/dist/components/Html.d.ts.map +1 -0
- package/dist/components/Logo.d.ts +79 -0
- package/dist/components/Logo.d.ts.map +1 -0
- package/dist/components/Markdown.d.ts +47 -0
- package/dist/components/Markdown.d.ts.map +1 -0
- package/dist/components/QwickApp.d.ts +56 -0
- package/dist/components/QwickApp.d.ts.map +1 -0
- package/dist/components/QwickAppsLogo.d.ts +25 -0
- package/dist/components/QwickAppsLogo.d.ts.map +1 -0
- package/dist/components/ResponsiveMenu.d.ts +38 -0
- package/dist/components/ResponsiveMenu.d.ts.map +1 -0
- package/dist/components/SafeSpan.d.ts +23 -0
- package/dist/components/SafeSpan.d.ts.map +1 -0
- package/dist/components/Scaffold.d.ts +57 -0
- package/dist/components/Scaffold.d.ts.map +1 -0
- package/dist/components/blocks/Article.d.ts +23 -0
- package/dist/components/blocks/Article.d.ts.map +1 -0
- package/dist/components/blocks/CardListGrid.d.ts +23 -0
- package/dist/components/blocks/CardListGrid.d.ts.map +1 -0
- package/dist/components/blocks/Code.d.ts +21 -0
- package/dist/components/blocks/Code.d.ts.map +1 -0
- package/dist/components/blocks/Content.d.ts +24 -0
- package/dist/components/blocks/Content.d.ts.map +1 -0
- package/dist/components/blocks/CoverImageHeader.d.ts +44 -0
- package/dist/components/blocks/CoverImageHeader.d.ts.map +1 -0
- package/dist/components/blocks/FeatureCard.d.ts +66 -0
- package/dist/components/blocks/FeatureCard.d.ts.map +1 -0
- package/dist/components/blocks/FeatureGrid.d.ts +48 -0
- package/dist/components/blocks/FeatureGrid.d.ts.map +1 -0
- package/dist/components/blocks/Footer.d.ts +56 -0
- package/dist/components/blocks/Footer.d.ts.map +1 -0
- package/dist/components/blocks/HeroBlock.d.ts +33 -0
- package/dist/components/blocks/HeroBlock.d.ts.map +1 -0
- package/dist/components/blocks/PageBannerHeader.d.ts +30 -0
- package/dist/components/blocks/PageBannerHeader.d.ts.map +1 -0
- package/dist/components/blocks/ProductCard.d.ts +57 -0
- package/dist/components/blocks/ProductCard.d.ts.map +1 -0
- package/dist/components/blocks/Section.d.ts +40 -0
- package/dist/components/blocks/Section.d.ts.map +1 -0
- package/dist/components/blocks/index.d.ts +37 -0
- package/dist/components/blocks/index.d.ts.map +1 -0
- package/dist/components/buttons/Button.d.ts +38 -0
- package/dist/components/buttons/Button.d.ts.map +1 -0
- package/dist/components/buttons/PaletteSwitcher.d.ts +24 -0
- package/dist/components/buttons/PaletteSwitcher.d.ts.map +1 -0
- package/dist/components/buttons/ThemeSwitcher.d.ts +24 -0
- package/dist/components/buttons/ThemeSwitcher.d.ts.map +1 -0
- package/dist/components/buttons/index.d.ts +11 -0
- package/dist/components/buttons/index.d.ts.map +1 -0
- package/dist/components/forms/FormBlock.d.ts +45 -0
- package/dist/components/forms/FormBlock.d.ts.map +1 -0
- package/dist/components/forms/index.d.ts +8 -0
- package/dist/components/forms/index.d.ts.map +1 -0
- package/dist/components/index.d.ts +32 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/input/ChoiceInputField.d.ts +30 -0
- package/dist/components/input/ChoiceInputField.d.ts.map +1 -0
- package/dist/components/input/HtmlInputField.d.ts +29 -0
- package/dist/components/input/HtmlInputField.d.ts.map +1 -0
- package/dist/components/input/SelectInputField.d.ts +29 -0
- package/dist/components/input/SelectInputField.d.ts.map +1 -0
- package/dist/components/input/TextField.d.ts +18 -0
- package/dist/components/input/TextField.d.ts.map +1 -0
- package/dist/components/input/TextInputField.d.ts +32 -0
- package/dist/components/input/TextInputField.d.ts.map +1 -0
- package/dist/components/input/index.d.ts +17 -0
- package/dist/components/input/index.d.ts.map +1 -0
- package/dist/components/layout/GridCell.d.ts +16 -0
- package/dist/components/layout/GridCell.d.ts.map +1 -0
- package/dist/components/layout/GridCellWrapper.d.ts +46 -0
- package/dist/components/layout/GridCellWrapper.d.ts.map +1 -0
- package/dist/components/layout/GridLayout.d.ts +38 -0
- package/dist/components/layout/GridLayout.d.ts.map +1 -0
- package/dist/components/layout/index.d.ts +12 -0
- package/dist/components/layout/index.d.ts.map +1 -0
- package/dist/components/menu/Menu.d.ts +1 -0
- package/dist/components/menu/Menu.d.ts.map +1 -0
- package/dist/components/menu/MenuItem.d.ts +31 -0
- package/dist/components/menu/MenuItem.d.ts.map +1 -0
- package/dist/components/menu/index.d.ts +7 -0
- package/dist/components/menu/index.d.ts.map +1 -0
- package/dist/components/pages/FormPage.d.ts +66 -0
- package/dist/components/pages/FormPage.d.ts.map +1 -0
- package/dist/components/pages/Page.d.ts +124 -0
- package/dist/components/pages/Page.d.ts.map +1 -0
- package/dist/components/pages/index.d.ts +11 -0
- package/dist/components/pages/index.d.ts.map +1 -0
- package/dist/contexts/DataContext.d.ts +139 -0
- package/dist/contexts/DataContext.d.ts.map +1 -0
- package/dist/contexts/DimensionsContext.d.ts +42 -0
- package/dist/contexts/DimensionsContext.d.ts.map +1 -0
- package/dist/contexts/PaletteContext.d.ts +53 -0
- package/dist/contexts/PaletteContext.d.ts.map +1 -0
- package/dist/contexts/QwickAppContext.d.ts +71 -0
- package/dist/contexts/QwickAppContext.d.ts.map +1 -0
- package/dist/contexts/ThemeContext.d.ts +65 -0
- package/dist/contexts/ThemeContext.d.ts.map +1 -0
- package/dist/contexts/index.d.ts +9 -0
- package/dist/contexts/index.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +10 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/useBaseProps.d.ts +101 -0
- package/dist/hooks/useBaseProps.d.ts.map +1 -0
- package/dist/hooks/useDataBinding.d.ts +22 -0
- package/dist/hooks/useDataBinding.d.ts.map +1 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.css +1 -0
- package/dist/index.esm.js +24143 -0
- package/dist/index.js +24245 -0
- package/dist/palettes/PaletteAutumn.d.ts +10 -0
- package/dist/palettes/PaletteAutumn.d.ts.map +1 -0
- package/dist/palettes/PaletteCosmic.d.ts +10 -0
- package/dist/palettes/PaletteCosmic.d.ts.map +1 -0
- package/dist/palettes/PaletteDefault.d.ts +10 -0
- package/dist/palettes/PaletteDefault.d.ts.map +1 -0
- package/dist/palettes/PaletteOcean.d.ts +10 -0
- package/dist/palettes/PaletteOcean.d.ts.map +1 -0
- package/dist/palettes/PaletteSpring.d.ts +10 -0
- package/dist/palettes/PaletteSpring.d.ts.map +1 -0
- package/dist/palettes/PaletteWinter.d.ts +10 -0
- package/dist/palettes/PaletteWinter.d.ts.map +1 -0
- package/dist/palettes/index.d.ts +13 -0
- package/dist/palettes/index.d.ts.map +1 -0
- package/dist/schemas/ActionSchema.d.ts +21 -0
- package/dist/schemas/ActionSchema.d.ts.map +1 -0
- package/dist/schemas/ArticleSchema.d.ts +13 -0
- package/dist/schemas/ArticleSchema.d.ts.map +1 -0
- package/dist/schemas/Builders.d.ts +7 -0
- package/dist/schemas/Builders.d.ts.map +1 -0
- package/dist/schemas/ButtonSchema.d.ts +19 -0
- package/dist/schemas/ButtonSchema.d.ts.map +1 -0
- package/dist/schemas/CardListGridSchema.d.ts +17 -0
- package/dist/schemas/CardListGridSchema.d.ts.map +1 -0
- package/dist/schemas/ChoiceInputFieldSchema.d.ts +18 -0
- package/dist/schemas/ChoiceInputFieldSchema.d.ts.map +1 -0
- package/dist/schemas/CodeSchema.d.ts +18 -0
- package/dist/schemas/CodeSchema.d.ts.map +1 -0
- package/dist/schemas/ContentSchema.d.ts +20 -0
- package/dist/schemas/ContentSchema.d.ts.map +1 -0
- package/dist/schemas/CoverImageHeaderSchema.d.ts +28 -0
- package/dist/schemas/CoverImageHeaderSchema.d.ts.map +1 -0
- package/dist/schemas/FeatureCardSchema.d.ts +28 -0
- package/dist/schemas/FeatureCardSchema.d.ts.map +1 -0
- package/dist/schemas/FeatureGridSchema.d.ts +17 -0
- package/dist/schemas/FeatureGridSchema.d.ts.map +1 -0
- package/dist/schemas/FeatureItemSchema.d.ts +16 -0
- package/dist/schemas/FeatureItemSchema.d.ts.map +1 -0
- package/dist/schemas/FooterItemSchema.d.ts +15 -0
- package/dist/schemas/FooterItemSchema.d.ts.map +1 -0
- package/dist/schemas/FooterSchema.d.ts +20 -0
- package/dist/schemas/FooterSchema.d.ts.map +1 -0
- package/dist/schemas/FooterSectionSchema.d.ts +15 -0
- package/dist/schemas/FooterSectionSchema.d.ts.map +1 -0
- package/dist/schemas/FormBlockSchema.d.ts +19 -0
- package/dist/schemas/FormBlockSchema.d.ts.map +1 -0
- package/dist/schemas/HeaderActionSchema.d.ts +17 -0
- package/dist/schemas/HeaderActionSchema.d.ts.map +1 -0
- package/dist/schemas/HeroBlockSchema.d.ts +22 -0
- package/dist/schemas/HeroBlockSchema.d.ts.map +1 -0
- package/dist/schemas/HtmlInputFieldSchema.d.ts +18 -0
- package/dist/schemas/HtmlInputFieldSchema.d.ts.map +1 -0
- package/dist/schemas/MetadataItemSchema.d.ts +13 -0
- package/dist/schemas/MetadataItemSchema.d.ts.map +1 -0
- package/dist/schemas/PageBannerHeaderSchema.d.ts +28 -0
- package/dist/schemas/PageBannerHeaderSchema.d.ts.map +1 -0
- package/dist/schemas/PaletteSwitcherSchema.d.ts +16 -0
- package/dist/schemas/PaletteSwitcherSchema.d.ts.map +1 -0
- package/dist/schemas/ProductCardSchema.d.ts +39 -0
- package/dist/schemas/ProductCardSchema.d.ts.map +1 -0
- package/dist/schemas/SafeSpanSchema.d.ts +13 -0
- package/dist/schemas/SafeSpanSchema.d.ts.map +1 -0
- package/dist/schemas/SectionSchema.d.ts +17 -0
- package/dist/schemas/SectionSchema.d.ts.map +1 -0
- package/dist/schemas/SelectInputFieldSchema.d.ts +27 -0
- package/dist/schemas/SelectInputFieldSchema.d.ts.map +1 -0
- package/dist/schemas/TextInputFieldSchema.d.ts +22 -0
- package/dist/schemas/TextInputFieldSchema.d.ts.map +1 -0
- package/dist/schemas/ThemeSwitcherSchema.d.ts +19 -0
- package/dist/schemas/ThemeSwitcherSchema.d.ts.map +1 -0
- package/dist/schemas/index.d.ts +33 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/types.d.ts +7 -0
- package/dist/schemas/types.d.ts.map +1 -0
- package/dist/templates/TemplateResolver.d.ts +52 -0
- package/dist/templates/TemplateResolver.d.ts.map +1 -0
- package/dist/templates/index.d.ts +7 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/tests/ConsoleWarningTest.d.ts +5 -0
- package/dist/tests/ConsoleWarningTest.d.ts.map +1 -0
- package/dist/tests/StorageKeyTest.d.ts +6 -0
- package/dist/tests/StorageKeyTest.d.ts.map +1 -0
- package/dist/tests/ThemeStorageKeyTest.d.ts +6 -0
- package/dist/tests/ThemeStorageKeyTest.d.ts.map +1 -0
- package/dist/types/CacheProvider.d.ts +18 -0
- package/dist/types/CacheProvider.d.ts.map +1 -0
- package/dist/types/ContentProxy.d.ts +47 -0
- package/dist/types/ContentProxy.d.ts.map +1 -0
- package/dist/types/DataBinding.d.ts +7 -0
- package/dist/types/DataBinding.d.ts.map +1 -0
- package/dist/types/DataProvider.d.ts +7 -0
- package/dist/types/DataProvider.d.ts.map +1 -0
- package/dist/types/DataTypes.d.ts +185 -0
- package/dist/types/DataTypes.d.ts.map +1 -0
- package/dist/types/TemplateProvider.d.ts +10 -0
- package/dist/types/TemplateProvider.d.ts.map +1 -0
- package/dist/types/TemplateResolver.d.ts +23 -0
- package/dist/types/TemplateResolver.d.ts.map +1 -0
- package/dist/types/index.d.ts +81 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/utils/breakpoints.d.ts +35 -0
- package/dist/utils/breakpoints.d.ts.map +1 -0
- package/dist/utils/customPaletteManager.d.ts +8 -0
- package/dist/utils/customPaletteManager.d.ts.map +1 -0
- package/dist/utils/dimensions.d.ts +34 -0
- package/dist/utils/dimensions.d.ts.map +1 -0
- package/dist/utils/htmlTransform.d.ts +44 -0
- package/dist/utils/htmlTransform.d.ts.map +1 -0
- package/dist/utils/index.d.ts +15 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/paletteUtils.d.ts +38 -0
- package/dist/utils/paletteUtils.d.ts.map +1 -0
- package/dist/utils/persistenceUtils.d.ts +31 -0
- package/dist/utils/persistenceUtils.d.ts.map +1 -0
- package/dist/utils/reactUtils.d.ts +24 -0
- package/dist/utils/reactUtils.d.ts.map +1 -0
- package/dist/utils/spacing.d.ts +34 -0
- package/dist/utils/spacing.d.ts.map +1 -0
- package/dist/utils/themePerformanceMonitor.d.ts +32 -0
- package/dist/utils/themePerformanceMonitor.d.ts.map +1 -0
- package/dist/utils/themeUtils.d.ts +27 -0
- package/dist/utils/themeUtils.d.ts.map +1 -0
- package/package.json +141 -0
- package/src/__tests__/components/Logo.test.js +172 -0
- package/src/__tests__/contexts/DataContext.test.js +505 -0
- package/src/__tests__/contexts/PaletteContext.test.js +115 -0
- package/src/__tests__/contexts/ThemeContext.test.js +123 -0
- package/src/__tests__/utils/paletteUtils.test.js +142 -0
- package/src/__tests__/utils/themeUtils.test.js +142 -0
- package/src/components/AccessibilityChecker.tsx +264 -0
- package/src/components/Html.tsx +191 -0
- package/src/components/Logo.css +217 -0
- package/src/components/Logo.tsx +370 -0
- package/src/components/Markdown.tsx +191 -0
- package/src/components/QwickApp.css +257 -0
- package/src/components/QwickApp.tsx +157 -0
- package/src/components/QwickAppsLogo.tsx +77 -0
- package/src/components/ResponsiveMenu.css +416 -0
- package/src/components/ResponsiveMenu.tsx +310 -0
- package/src/components/SafeSpan.tsx +128 -0
- package/src/components/Scaffold.css +541 -0
- package/src/components/Scaffold.tsx +463 -0
- package/src/components/__tests__/Article.test.tsx +419 -0
- package/src/components/__tests__/Button.test.tsx +702 -0
- package/src/components/__tests__/CardListGrid.test.tsx +478 -0
- package/src/components/__tests__/ChoiceInputField.test.tsx +864 -0
- package/src/components/__tests__/Code.test.tsx +595 -0
- package/src/components/__tests__/Content.integration.test.tsx +193 -0
- package/src/components/__tests__/Content.test.tsx +504 -0
- package/src/components/__tests__/CoverImageHeader.test.tsx +456 -0
- package/src/components/__tests__/FeatureCard.integration.test.tsx +384 -0
- package/src/components/__tests__/FeatureGrid.integration.test.tsx +364 -0
- package/src/components/__tests__/FeatureGrid.test.tsx +494 -0
- package/src/components/__tests__/Footer.test.tsx +544 -0
- package/src/components/__tests__/FormBlock.test.tsx +857 -0
- package/src/components/__tests__/HeroBlock.integration.test.tsx +272 -0
- package/src/components/__tests__/HeroBlock.test.tsx +463 -0
- package/src/components/__tests__/Html.test.tsx +174 -0
- package/src/components/__tests__/HtmlInputField.test.tsx +856 -0
- package/src/components/__tests__/Markdown.test.tsx +233 -0
- package/src/components/__tests__/PageBannerHeader.test.tsx +614 -0
- package/src/components/__tests__/PaletteSwitcher.test.tsx +864 -0
- package/src/components/__tests__/ProductCard.test.tsx +377 -0
- package/src/components/__tests__/SafeSpan.integration.test.tsx +123 -0
- package/src/components/__tests__/SafeSpan.simple.test.tsx +65 -0
- package/src/components/__tests__/SafeSpan.test.tsx +388 -0
- package/src/components/__tests__/Section.integration.test.tsx +288 -0
- package/src/components/__tests__/Section.test.tsx +494 -0
- package/src/components/__tests__/SelectInputField.test.tsx +886 -0
- package/src/components/__tests__/TextInputField.test.tsx +749 -0
- package/src/components/__tests__/ThemeSwitcher.test.tsx +777 -0
- package/src/components/blocks/Article.tsx +194 -0
- package/src/components/blocks/CardListGrid.tsx +132 -0
- package/src/components/blocks/Code.tsx +313 -0
- package/src/components/blocks/Content.tsx +265 -0
- package/src/components/blocks/CoverImageHeader.css +17 -0
- package/src/components/blocks/CoverImageHeader.tsx +435 -0
- package/src/components/blocks/FeatureCard.tsx +321 -0
- package/src/components/blocks/FeatureGrid.tsx +147 -0
- package/src/components/blocks/Footer.tsx +343 -0
- package/src/components/blocks/HeroBlock.tsx +280 -0
- package/src/components/blocks/PageBannerHeader.tsx +471 -0
- package/src/components/blocks/ProductCard.tsx +472 -0
- package/src/components/blocks/Section.tsx +209 -0
- package/src/components/blocks/index.ts +37 -0
- package/src/components/buttons/Button.tsx +233 -0
- package/src/components/buttons/PaletteSwitcher.tsx +268 -0
- package/src/components/buttons/ThemeSwitcher.tsx +283 -0
- package/src/components/buttons/index.ts +11 -0
- package/src/components/forms/FormBlock.tsx +291 -0
- package/src/components/forms/index.ts +7 -0
- package/src/components/index.ts +37 -0
- package/src/components/input/ChoiceInputField.tsx +188 -0
- package/src/components/input/HtmlInputField.tsx +326 -0
- package/src/components/input/SelectInputField.tsx +197 -0
- package/src/components/input/TextField.tsx +47 -0
- package/src/components/input/TextInputField.tsx +144 -0
- package/src/components/input/index.ts +17 -0
- package/src/components/layout/GridCell.tsx +46 -0
- package/src/components/layout/GridCellWrapper.tsx +87 -0
- package/src/components/layout/GridLayout.tsx +169 -0
- package/src/components/layout/index.ts +13 -0
- package/src/components/menu/Menu.tsx +0 -0
- package/src/components/menu/MenuItem.tsx +32 -0
- package/src/components/menu/index.ts +6 -0
- package/src/components/pages/FormPage.tsx +108 -0
- package/src/components/pages/Page.css +460 -0
- package/src/components/pages/Page.tsx +345 -0
- package/src/components/pages/index.ts +11 -0
- package/src/contexts/DataContext.tsx +355 -0
- package/src/contexts/DimensionsContext.tsx +154 -0
- package/src/contexts/PaletteContext.tsx +217 -0
- package/src/contexts/QwickAppContext.tsx +95 -0
- package/src/contexts/ThemeContext.tsx +376 -0
- package/src/contexts/index.ts +9 -0
- package/src/hooks/__tests__/useDataBinding.test.tsx.disabled +229 -0
- package/src/hooks/index.ts +11 -0
- package/src/hooks/useBaseProps.ts +267 -0
- package/src/hooks/useDataBinding.ts +77 -0
- package/src/index.ts +23 -0
- package/src/palettes/PaletteAutumn.css +172 -0
- package/src/palettes/PaletteAutumn.ts +16 -0
- package/src/palettes/PaletteCosmic.css +172 -0
- package/src/palettes/PaletteCosmic.ts +16 -0
- package/src/palettes/PaletteDefault.css +178 -0
- package/src/palettes/PaletteDefault.ts +17 -0
- package/src/palettes/PaletteOcean.css +172 -0
- package/src/palettes/PaletteOcean.ts +16 -0
- package/src/palettes/PaletteSpring.css +160 -0
- package/src/palettes/PaletteSpring.ts +16 -0
- package/src/palettes/PaletteWinter.css +172 -0
- package/src/palettes/PaletteWinter.ts +16 -0
- package/src/palettes/index.css +12 -0
- package/src/palettes/index.ts +29 -0
- package/src/schemas/ActionSchema.ts +140 -0
- package/src/schemas/ArticleSchema.ts +35 -0
- package/src/schemas/ButtonSchema.ts +99 -0
- package/src/schemas/CardListGridSchema.ts +102 -0
- package/src/schemas/ChoiceInputFieldSchema.ts +89 -0
- package/src/schemas/CodeSchema.ts +88 -0
- package/src/schemas/ContentSchema.ts +128 -0
- package/src/schemas/CoverImageHeaderSchema.ts +208 -0
- package/src/schemas/FeatureCardSchema.ts +161 -0
- package/src/schemas/FeatureGridSchema.ts +87 -0
- package/src/schemas/FeatureItemSchema.ts +68 -0
- package/src/schemas/FooterItemSchema.ts +57 -0
- package/src/schemas/FooterSchema.ts +116 -0
- package/src/schemas/FooterSectionSchema.ts +50 -0
- package/src/schemas/FormBlockSchema.ts +102 -0
- package/src/schemas/HeaderActionSchema.ts +83 -0
- package/src/schemas/HeroBlockSchema.ts +149 -0
- package/src/schemas/HtmlInputFieldSchema.ts +88 -0
- package/src/schemas/MetadataItemSchema.ts +35 -0
- package/src/schemas/PageBannerHeaderSchema.ts +206 -0
- package/src/schemas/PaletteSwitcherSchema.ts +66 -0
- package/src/schemas/ProductCardSchema.ts +264 -0
- package/src/schemas/SafeSpanSchema.ts +36 -0
- package/src/schemas/SectionSchema.ts +106 -0
- package/src/schemas/SelectInputFieldSchema.ts +137 -0
- package/src/schemas/TextInputFieldSchema.ts +129 -0
- package/src/schemas/ThemeSwitcherSchema.ts +97 -0
- package/src/schemas/__tests__/builders.test.ts +313 -0
- package/src/schemas/index.ts +34 -0
- package/src/setupTests.js +60 -0
- package/src/stories/Article.stories.tsx +549 -0
- package/src/stories/Button.stories.tsx +498 -0
- package/src/stories/CardListGrid.stories.tsx +539 -0
- package/src/stories/ChoiceInputField.stories.tsx +591 -0
- package/src/stories/Code.stories.tsx +711 -0
- package/src/stories/Content.stories.tsx +463 -0
- package/src/stories/CoverImageHeader.stories.tsx +794 -0
- package/src/stories/DataBinding.advanced.stories.tsx +548 -0
- package/src/stories/DataBinding.stories.tsx +452 -0
- package/src/stories/DataProvider.stories.tsx +1361 -0
- package/src/stories/FeatureCard.stories.tsx +642 -0
- package/src/stories/FeatureGrid.stories.tsx +669 -0
- package/src/stories/Footer.stories.tsx +724 -0
- package/src/stories/FormBlock.stories.tsx +834 -0
- package/src/stories/HeroBlock.stories.tsx +442 -0
- package/src/stories/Html.stories.tsx +264 -0
- package/src/stories/HtmlInputField.stories.tsx +558 -0
- package/src/stories/Introduction.stories.tsx +721 -0
- package/src/stories/LayoutBlocks.stories.tsx +382 -0
- package/src/stories/LayoutSystem.stories.tsx +253 -0
- package/src/stories/Logo.stories.tsx +400 -0
- package/src/stories/Markdown.stories.tsx +349 -0
- package/src/stories/Page.stories.tsx +762 -0
- package/src/stories/PageBannerHeader.stories.tsx +949 -0
- package/src/stories/PaletteSwitcher.stories.tsx +156 -0
- package/src/stories/ProductCard.stories.tsx +504 -0
- package/src/stories/QwickApp.stories.tsx +461 -0
- package/src/stories/ResponsiveMenu.stories.tsx +299 -0
- package/src/stories/SafeSpan.stories.tsx +612 -0
- package/src/stories/Section.stories.tsx +613 -0
- package/src/stories/SelectInputField.stories.tsx +605 -0
- package/src/stories/TextInputField.stories.tsx +526 -0
- package/src/stories/ThemeSwitcher.stories.tsx +170 -0
- package/src/stories/form/FormComponents.stories.tsx +588 -0
- package/src/templates/TemplateResolver.ts +156 -0
- package/src/templates/index.ts +6 -0
- package/src/tests/ConsoleWarningTest.tsx +30 -0
- package/src/tests/StorageKeyTest.tsx +110 -0
- package/src/tests/ThemeStorageKeyTest.tsx +114 -0
- package/src/types/CacheProvider.ts +14 -0
- package/src/types/ContentProxy.ts +99 -0
- package/src/types/DataTypes.ts +196 -0
- package/src/types/TemplateProvider.ts +9 -0
- package/src/types/TemplateResolver.ts +26 -0
- package/src/types/index.ts +99 -0
- package/src/utils/__tests__/createDataDrivenComponent.test.tsx.disabled +193 -0
- package/src/utils/__tests__/htmlTransform.test.tsx +255 -0
- package/src/utils/breakpoints.ts +87 -0
- package/src/utils/customPaletteManager.js +214 -0
- package/src/utils/dimensions.ts +147 -0
- package/src/utils/htmlTransform.tsx +323 -0
- package/src/utils/index.ts +16 -0
- package/src/utils/logger.ts +28 -0
- package/src/utils/paletteUtils.ts +78 -0
- package/src/utils/persistenceUtils.ts +107 -0
- package/src/utils/reactUtils.tsx +37 -0
- package/src/utils/spacing.ts +155 -0
- package/src/utils/themePerformanceMonitor.js +113 -0
- package/src/utils/themeUtils.ts +67 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChoiceInputField - Dynamic option inputs management component
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent interface for:
|
|
5
|
+
* - Dynamic list of option inputs
|
|
6
|
+
* - Adding new options
|
|
7
|
+
* - Rich text editing for each option
|
|
8
|
+
* - Data binding support
|
|
9
|
+
*
|
|
10
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import {
|
|
15
|
+
Alert,
|
|
16
|
+
Box,
|
|
17
|
+
Button,
|
|
18
|
+
Paper,
|
|
19
|
+
Typography
|
|
20
|
+
} from '@mui/material';
|
|
21
|
+
import { Add as AddIcon } from '@mui/icons-material';
|
|
22
|
+
import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
|
|
23
|
+
import { QWICKAPP_COMPONENT, useBaseProps } from '../../hooks';
|
|
24
|
+
import { useDataBinding } from '../../hooks';
|
|
25
|
+
import HtmlInputField from './HtmlInputField';
|
|
26
|
+
import ChoiceInputFieldModel from '../../schemas/ChoiceInputFieldSchema';
|
|
27
|
+
|
|
28
|
+
type ChoiceInputFieldViewProps = ModelProps<ChoiceInputFieldModel> & {
|
|
29
|
+
/** Handler for option value changes */
|
|
30
|
+
onOptionChange?: (optionIndex: number, value: string) => void;
|
|
31
|
+
/** Handler for adding new options */
|
|
32
|
+
onAddOption?: () => void;
|
|
33
|
+
/** Focus handler */
|
|
34
|
+
onFocus?: (optionIndex?: number) => void;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export interface ChoiceInputFieldProps extends ChoiceInputFieldViewProps, WithDataBinding {}
|
|
38
|
+
|
|
39
|
+
// View component - handles the actual rendering
|
|
40
|
+
function ChoiceInputFieldView({
|
|
41
|
+
label = 'Options',
|
|
42
|
+
options = [],
|
|
43
|
+
onOptionChange,
|
|
44
|
+
onAddOption,
|
|
45
|
+
onFocus,
|
|
46
|
+
disabled = false,
|
|
47
|
+
placeholder = 'Enter option text. HTML formatting supported.',
|
|
48
|
+
optionLabelPrefix = 'Option',
|
|
49
|
+
rows = 2,
|
|
50
|
+
addButtonText = 'Add Option',
|
|
51
|
+
...restProps
|
|
52
|
+
}: ChoiceInputFieldViewProps) {
|
|
53
|
+
const { styleProps, htmlProps } = useBaseProps(restProps);
|
|
54
|
+
|
|
55
|
+
// Return empty state if no options and no handlers
|
|
56
|
+
if (options.length === 0 && !onAddOption) {
|
|
57
|
+
return (
|
|
58
|
+
<Paper
|
|
59
|
+
{...htmlProps}
|
|
60
|
+
{...styleProps}
|
|
61
|
+
variant="outlined"
|
|
62
|
+
sx={{
|
|
63
|
+
p: 3,
|
|
64
|
+
textAlign: 'center',
|
|
65
|
+
opacity: 0.6,
|
|
66
|
+
...styleProps.sx
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
<Typography variant="body2" color="text.secondary">
|
|
70
|
+
No options provided
|
|
71
|
+
</Typography>
|
|
72
|
+
</Paper>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<Box
|
|
78
|
+
{...htmlProps}
|
|
79
|
+
{...styleProps}
|
|
80
|
+
sx={{
|
|
81
|
+
display: 'flex',
|
|
82
|
+
flexDirection: 'column',
|
|
83
|
+
gap: 1,
|
|
84
|
+
...styleProps.sx
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
{label && (
|
|
88
|
+
<Typography variant="subtitle2" gutterBottom>
|
|
89
|
+
{label}
|
|
90
|
+
</Typography>
|
|
91
|
+
)}
|
|
92
|
+
|
|
93
|
+
{options.map((option, optionIndex) => (
|
|
94
|
+
<Box key={optionIndex}>
|
|
95
|
+
<HtmlInputField
|
|
96
|
+
label={`${optionLabelPrefix} ${optionIndex + 1}`}
|
|
97
|
+
value={option}
|
|
98
|
+
onChange={onOptionChange ? (value: string) => onOptionChange(optionIndex, value) : undefined}
|
|
99
|
+
onFocus={onFocus ? () => onFocus(optionIndex) : undefined}
|
|
100
|
+
rows={rows}
|
|
101
|
+
disabled={disabled}
|
|
102
|
+
placeholder={placeholder}
|
|
103
|
+
/>
|
|
104
|
+
</Box>
|
|
105
|
+
))}
|
|
106
|
+
|
|
107
|
+
{onAddOption && (
|
|
108
|
+
<Button
|
|
109
|
+
startIcon={<AddIcon />}
|
|
110
|
+
onClick={onAddOption}
|
|
111
|
+
size="small"
|
|
112
|
+
disabled={disabled}
|
|
113
|
+
variant="text"
|
|
114
|
+
sx={{ mt: 1, alignSelf: 'flex-start' }}
|
|
115
|
+
>
|
|
116
|
+
{addButtonText}
|
|
117
|
+
</Button>
|
|
118
|
+
)}
|
|
119
|
+
</Box>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* ChoiceInputField component with data binding support
|
|
125
|
+
* Supports both traditional props and dataSource-driven rendering
|
|
126
|
+
*/
|
|
127
|
+
function ChoiceInputField(props: ChoiceInputFieldProps) {
|
|
128
|
+
const { dataSource, bindingOptions, ...restProps } = props;
|
|
129
|
+
|
|
130
|
+
// If no dataSource, use traditional props
|
|
131
|
+
if (!dataSource) {
|
|
132
|
+
return <ChoiceInputFieldView {...restProps} />;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Use data binding
|
|
136
|
+
const { dataSource: _source, loading, error, cached, ...choiceInputFieldProps } = useDataBinding<ChoiceInputFieldModel>(
|
|
137
|
+
dataSource,
|
|
138
|
+
restProps as Partial<ChoiceInputFieldModel>,
|
|
139
|
+
ChoiceInputFieldModel.getSchema(),
|
|
140
|
+
{ cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Show loading state
|
|
144
|
+
if (loading) {
|
|
145
|
+
return (
|
|
146
|
+
<Paper
|
|
147
|
+
variant="outlined"
|
|
148
|
+
sx={{
|
|
149
|
+
p: 3,
|
|
150
|
+
textAlign: 'center'
|
|
151
|
+
}}
|
|
152
|
+
>
|
|
153
|
+
<Typography variant="body2">Loading Choice Input Field...</Typography>
|
|
154
|
+
<Typography variant="caption" color="text.secondary">
|
|
155
|
+
Loading options from data source...
|
|
156
|
+
</Typography>
|
|
157
|
+
</Paper>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (error) {
|
|
162
|
+
console.error('Error loading choice input field:', error);
|
|
163
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
164
|
+
return (
|
|
165
|
+
<Paper
|
|
166
|
+
variant="outlined"
|
|
167
|
+
sx={{
|
|
168
|
+
p: 3,
|
|
169
|
+
textAlign: 'center',
|
|
170
|
+
borderColor: 'error.main'
|
|
171
|
+
}}
|
|
172
|
+
>
|
|
173
|
+
<Typography variant="body2" color="error">
|
|
174
|
+
Error loading choice input field: {error.message}
|
|
175
|
+
</Typography>
|
|
176
|
+
</Paper>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return <ChoiceInputFieldView {...choiceInputFieldProps} />;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Mark as QwickApp component
|
|
186
|
+
(ChoiceInputField as any)[QWICKAPP_COMPONENT] = true;
|
|
187
|
+
|
|
188
|
+
export default ChoiceInputField;
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HtmlInputField - Custom HTML text field with formatting controls
|
|
3
|
+
*
|
|
4
|
+
* Provides HTML editing capabilities with:
|
|
5
|
+
* - Formatting toolbar (bold, italic, underline, code)
|
|
6
|
+
* - HTML preview mode
|
|
7
|
+
* - Help system with supported tags
|
|
8
|
+
* - HTML sanitization for security
|
|
9
|
+
* - Data binding support
|
|
10
|
+
*
|
|
11
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { useState } from 'react';
|
|
15
|
+
import {
|
|
16
|
+
Box,
|
|
17
|
+
TextField,
|
|
18
|
+
IconButton,
|
|
19
|
+
Tooltip,
|
|
20
|
+
Typography,
|
|
21
|
+
Collapse,
|
|
22
|
+
Alert,
|
|
23
|
+
ButtonGroup,
|
|
24
|
+
Divider,
|
|
25
|
+
Paper
|
|
26
|
+
} from '@mui/material';
|
|
27
|
+
import {
|
|
28
|
+
FormatBold as BoldIcon,
|
|
29
|
+
FormatItalic as ItalicIcon,
|
|
30
|
+
FormatUnderlined as UnderlineIcon,
|
|
31
|
+
Code as CodeIcon,
|
|
32
|
+
Visibility as PreviewIcon,
|
|
33
|
+
VisibilityOff as EditIcon,
|
|
34
|
+
Help as HelpIcon
|
|
35
|
+
} from '@mui/icons-material';
|
|
36
|
+
import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
|
|
37
|
+
import SafeSpan from '../SafeSpan';
|
|
38
|
+
import sanitizeHtml from 'sanitize-html';
|
|
39
|
+
import { QWICKAPP_COMPONENT, useBaseProps } from '../../hooks';
|
|
40
|
+
import { useDataBinding } from '../../hooks';
|
|
41
|
+
import HtmlInputFieldModel from '../../schemas/HtmlInputFieldSchema';
|
|
42
|
+
|
|
43
|
+
type HtmlInputFieldViewProps = ModelProps<HtmlInputFieldModel> & {
|
|
44
|
+
/** Change handler */
|
|
45
|
+
onChange?: (value: string) => void;
|
|
46
|
+
/** Focus handler */
|
|
47
|
+
onFocus?: () => void;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export interface HtmlInputFieldProps extends HtmlInputFieldViewProps, WithDataBinding {}
|
|
51
|
+
|
|
52
|
+
// View component - handles the actual rendering
|
|
53
|
+
function HtmlInputFieldView({
|
|
54
|
+
label,
|
|
55
|
+
value = '',
|
|
56
|
+
onChange,
|
|
57
|
+
onFocus,
|
|
58
|
+
required = false,
|
|
59
|
+
placeholder = '',
|
|
60
|
+
multiline = true,
|
|
61
|
+
rows = 4,
|
|
62
|
+
disabled = false,
|
|
63
|
+
...restProps
|
|
64
|
+
}: HtmlInputFieldViewProps) {
|
|
65
|
+
const { styleProps, htmlProps, restProps: otherProps } = useBaseProps(restProps);
|
|
66
|
+
const [showPreview, setShowPreview] = useState(false);
|
|
67
|
+
const [showHelp, setShowHelp] = useState(false);
|
|
68
|
+
|
|
69
|
+
// Return empty state if no onChange handler
|
|
70
|
+
if (!onChange) {
|
|
71
|
+
return (
|
|
72
|
+
<Paper
|
|
73
|
+
{...htmlProps}
|
|
74
|
+
{...styleProps}
|
|
75
|
+
variant="outlined"
|
|
76
|
+
sx={{
|
|
77
|
+
p: 3,
|
|
78
|
+
textAlign: 'center',
|
|
79
|
+
opacity: 0.6,
|
|
80
|
+
...styleProps.sx
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
<Typography variant="body2" color="text.secondary">
|
|
84
|
+
No onChange handler provided for {label}
|
|
85
|
+
</Typography>
|
|
86
|
+
</Paper>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Sanitize HTML content using default configuration
|
|
91
|
+
const sanitizeHtmlContent = (htmlContent: string) => {
|
|
92
|
+
return sanitizeHtml(htmlContent);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Handle text formatting
|
|
96
|
+
const insertFormatting = (openTag: string, closeTag: string) => {
|
|
97
|
+
const textarea = document.getElementById(`html-textfield-${label}`) as HTMLTextAreaElement;
|
|
98
|
+
if (textarea) {
|
|
99
|
+
const start = textarea.selectionStart;
|
|
100
|
+
const end = textarea.selectionEnd;
|
|
101
|
+
const selectedText = value.substring(start, end);
|
|
102
|
+
|
|
103
|
+
let newText;
|
|
104
|
+
if (selectedText) {
|
|
105
|
+
// Wrap selected text
|
|
106
|
+
newText = value.substring(0, start) + openTag + selectedText + closeTag + value.substring(end);
|
|
107
|
+
} else {
|
|
108
|
+
// Insert tags at cursor position
|
|
109
|
+
newText = value.substring(0, start) + openTag + closeTag + value.substring(start);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
onChange(newText);
|
|
113
|
+
|
|
114
|
+
// Set cursor position after the opening tag
|
|
115
|
+
setTimeout(() => {
|
|
116
|
+
const newPosition = selectedText ? end + openTag.length + closeTag.length : start + openTag.length;
|
|
117
|
+
textarea.setSelectionRange(newPosition, newPosition);
|
|
118
|
+
textarea.focus();
|
|
119
|
+
}, 0);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const formatButtons = [
|
|
124
|
+
{ icon: BoldIcon, tooltip: 'Bold', openTag: '<b>', closeTag: '</b>' },
|
|
125
|
+
{ icon: ItalicIcon, tooltip: 'Italic', openTag: '<i>', closeTag: '</i>' },
|
|
126
|
+
{ icon: UnderlineIcon, tooltip: 'Underline', openTag: '<u>', closeTag: '</u>' },
|
|
127
|
+
{ icon: CodeIcon, tooltip: 'Code', openTag: '<code>', closeTag: '</code>' }
|
|
128
|
+
];
|
|
129
|
+
|
|
130
|
+
const helpContent = (
|
|
131
|
+
<Alert severity="info" sx={{ mt: 1 }}>
|
|
132
|
+
<Typography variant="body2" gutterBottom>
|
|
133
|
+
<strong>Supported HTML tags:</strong>
|
|
134
|
+
</Typography>
|
|
135
|
+
<Typography variant="body2" component="div">
|
|
136
|
+
• <code><b></code> or <code><strong></code> - Bold text<br/>
|
|
137
|
+
• <code><i></code> or <code><em></code> - Italic text<br/>
|
|
138
|
+
• <code><u></code> - Underlined text<br/>
|
|
139
|
+
• <code><code></code> - Code formatting<br/>
|
|
140
|
+
• <code><br></code> - Line break<br/>
|
|
141
|
+
• <code><span style="color: red"></code> - Colored text
|
|
142
|
+
</Typography>
|
|
143
|
+
</Alert>
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<Box
|
|
148
|
+
{...htmlProps}
|
|
149
|
+
{...styleProps}
|
|
150
|
+
sx={{ mb: 2, ...styleProps.sx }}
|
|
151
|
+
>
|
|
152
|
+
{/* Toolbar */}
|
|
153
|
+
<Box sx={{ display: 'flex', alignItems: 'center', mb: 1, gap: 1 }}>
|
|
154
|
+
<Typography variant="body2" color="text.secondary">
|
|
155
|
+
{label} {required && '*'}
|
|
156
|
+
</Typography>
|
|
157
|
+
|
|
158
|
+
<Box sx={{ flexGrow: 1 }} />
|
|
159
|
+
|
|
160
|
+
{/* Formatting buttons */}
|
|
161
|
+
<ButtonGroup size="small" variant="outlined">
|
|
162
|
+
{formatButtons.map(({ icon: Icon, tooltip, openTag, closeTag }) => (
|
|
163
|
+
<Tooltip key={tooltip} title={tooltip}>
|
|
164
|
+
<IconButton
|
|
165
|
+
size="small"
|
|
166
|
+
onClick={() => insertFormatting(openTag, closeTag)}
|
|
167
|
+
disabled={disabled}
|
|
168
|
+
sx={{ p: 0.5 }}
|
|
169
|
+
>
|
|
170
|
+
<Icon fontSize="small" />
|
|
171
|
+
</IconButton>
|
|
172
|
+
</Tooltip>
|
|
173
|
+
))}
|
|
174
|
+
</ButtonGroup>
|
|
175
|
+
|
|
176
|
+
<Divider orientation="vertical" flexItem />
|
|
177
|
+
|
|
178
|
+
{/* Preview toggle */}
|
|
179
|
+
<Tooltip title={showPreview ? "Edit HTML" : "Preview HTML"}>
|
|
180
|
+
<IconButton
|
|
181
|
+
size="small"
|
|
182
|
+
onClick={() => setShowPreview(!showPreview)}
|
|
183
|
+
color={showPreview ? "primary" : "default"}
|
|
184
|
+
disabled={disabled}
|
|
185
|
+
sx={{ p: 0.5 }}
|
|
186
|
+
>
|
|
187
|
+
{showPreview ? <EditIcon fontSize="small" /> : <PreviewIcon fontSize="small" />}
|
|
188
|
+
</IconButton>
|
|
189
|
+
</Tooltip>
|
|
190
|
+
|
|
191
|
+
{/* Help toggle */}
|
|
192
|
+
<Tooltip title="HTML Help">
|
|
193
|
+
<IconButton
|
|
194
|
+
size="small"
|
|
195
|
+
onClick={() => setShowHelp(!showHelp)}
|
|
196
|
+
color={showHelp ? "primary" : "default"}
|
|
197
|
+
disabled={disabled}
|
|
198
|
+
sx={{ p: 0.5 }}
|
|
199
|
+
>
|
|
200
|
+
<HelpIcon fontSize="small" />
|
|
201
|
+
</IconButton>
|
|
202
|
+
</Tooltip>
|
|
203
|
+
</Box>
|
|
204
|
+
|
|
205
|
+
{/* Help content */}
|
|
206
|
+
<Collapse in={showHelp}>
|
|
207
|
+
{helpContent}
|
|
208
|
+
</Collapse>
|
|
209
|
+
|
|
210
|
+
{/* Input field or preview */}
|
|
211
|
+
{showPreview ? (
|
|
212
|
+
<Box
|
|
213
|
+
sx={{
|
|
214
|
+
border: 1,
|
|
215
|
+
borderColor: 'divider',
|
|
216
|
+
borderRadius: 1,
|
|
217
|
+
p: 2,
|
|
218
|
+
minHeight: multiline ? `${rows * 1.5}em` : '1.5em',
|
|
219
|
+
backgroundColor: 'background.paper'
|
|
220
|
+
}}
|
|
221
|
+
>
|
|
222
|
+
<Typography variant="body2" color="text.secondary" gutterBottom>
|
|
223
|
+
HTML Preview:
|
|
224
|
+
</Typography>
|
|
225
|
+
<Box
|
|
226
|
+
sx={{
|
|
227
|
+
'& code': {
|
|
228
|
+
backgroundColor: 'action.hover',
|
|
229
|
+
padding: '2px 4px',
|
|
230
|
+
borderRadius: 0.5,
|
|
231
|
+
fontFamily: 'monospace'
|
|
232
|
+
}
|
|
233
|
+
}}
|
|
234
|
+
>
|
|
235
|
+
<SafeSpan html={sanitizeHtmlContent(value)} placeholder="No content" />
|
|
236
|
+
</Box>
|
|
237
|
+
</Box>
|
|
238
|
+
) : (
|
|
239
|
+
<TextField
|
|
240
|
+
id={`html-textfield-${label}`}
|
|
241
|
+
value={value}
|
|
242
|
+
onChange={(e) => {
|
|
243
|
+
const sanitizedValue = sanitizeHtmlContent(e.target.value);
|
|
244
|
+
onChange(sanitizedValue);
|
|
245
|
+
}}
|
|
246
|
+
onFocus={onFocus}
|
|
247
|
+
placeholder={placeholder}
|
|
248
|
+
multiline={multiline}
|
|
249
|
+
rows={multiline ? rows : undefined}
|
|
250
|
+
fullWidth
|
|
251
|
+
variant="outlined"
|
|
252
|
+
required={required}
|
|
253
|
+
disabled={disabled}
|
|
254
|
+
{...otherProps}
|
|
255
|
+
/>
|
|
256
|
+
)}
|
|
257
|
+
</Box>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* HtmlInputField component with data binding support
|
|
263
|
+
* Supports both traditional props and dataSource-driven rendering
|
|
264
|
+
*/
|
|
265
|
+
function HtmlInputField(props: HtmlInputFieldProps) {
|
|
266
|
+
const { dataSource, bindingOptions, ...restProps } = props;
|
|
267
|
+
|
|
268
|
+
// If no dataSource, use traditional props
|
|
269
|
+
if (!dataSource) {
|
|
270
|
+
return <HtmlInputFieldView {...restProps} />;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Use data binding
|
|
274
|
+
const { dataSource: _source, loading, error, cached, ...htmlInputFieldProps } = useDataBinding<HtmlInputFieldModel>(
|
|
275
|
+
dataSource,
|
|
276
|
+
restProps as Partial<HtmlInputFieldModel>,
|
|
277
|
+
HtmlInputFieldModel.getSchema(),
|
|
278
|
+
{ cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
// Show loading state
|
|
282
|
+
if (loading) {
|
|
283
|
+
return (
|
|
284
|
+
<Paper
|
|
285
|
+
variant="outlined"
|
|
286
|
+
sx={{
|
|
287
|
+
p: 3,
|
|
288
|
+
textAlign: 'center'
|
|
289
|
+
}}
|
|
290
|
+
>
|
|
291
|
+
<Typography variant="body2">Loading HtmlInputField...</Typography>
|
|
292
|
+
<Typography variant="caption" color="text.secondary">
|
|
293
|
+
Loading HTML input field from data source...
|
|
294
|
+
</Typography>
|
|
295
|
+
</Paper>
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (error) {
|
|
300
|
+
console.error('Error loading HtmlInputField:', error);
|
|
301
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
302
|
+
return (
|
|
303
|
+
<Paper
|
|
304
|
+
variant="outlined"
|
|
305
|
+
sx={{
|
|
306
|
+
p: 3,
|
|
307
|
+
textAlign: 'center',
|
|
308
|
+
borderColor: 'error.main'
|
|
309
|
+
}}
|
|
310
|
+
>
|
|
311
|
+
<Typography variant="body2" color="error">
|
|
312
|
+
Error loading HtmlInputField: {error.message}
|
|
313
|
+
</Typography>
|
|
314
|
+
</Paper>
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return <HtmlInputFieldView {...htmlInputFieldProps} />;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Mark as QwickApp component
|
|
324
|
+
(HtmlInputField as any)[QWICKAPP_COMPONENT] = true;
|
|
325
|
+
|
|
326
|
+
export default HtmlInputField;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SelectInputField - Select dropdown component with data binding support
|
|
3
|
+
*
|
|
4
|
+
* Provides a standardized select field with:
|
|
5
|
+
* - Consistent Material-UI styling
|
|
6
|
+
* - Data binding capabilities
|
|
7
|
+
* - Comprehensive option support
|
|
8
|
+
* - Focus and error handling
|
|
9
|
+
*
|
|
10
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
FormControl,
|
|
15
|
+
FormHelperText,
|
|
16
|
+
InputLabel,
|
|
17
|
+
MenuItem,
|
|
18
|
+
Paper,
|
|
19
|
+
Select,
|
|
20
|
+
SelectChangeEvent,
|
|
21
|
+
Typography
|
|
22
|
+
} from '@mui/material';
|
|
23
|
+
import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
|
|
24
|
+
import { QWICKAPP_COMPONENT, useBaseProps } from '../../hooks';
|
|
25
|
+
import { useDataBinding } from '../../hooks';
|
|
26
|
+
import SelectInputFieldModel, { SelectOption } from '../../schemas/SelectInputFieldSchema';
|
|
27
|
+
|
|
28
|
+
type SelectInputFieldViewProps = ModelProps<SelectInputFieldModel> & {
|
|
29
|
+
/** Change handler */
|
|
30
|
+
onChange?: (value: string | number) => void;
|
|
31
|
+
/** Focus handler */
|
|
32
|
+
onFocus?: () => void;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export interface SelectInputFieldProps extends SelectInputFieldViewProps, WithDataBinding {}
|
|
36
|
+
|
|
37
|
+
// Export SelectOption for external use
|
|
38
|
+
export { SelectOption };
|
|
39
|
+
|
|
40
|
+
// View component - handles the actual rendering
|
|
41
|
+
function SelectInputFieldView({
|
|
42
|
+
label,
|
|
43
|
+
value = '',
|
|
44
|
+
onChange,
|
|
45
|
+
onFocus,
|
|
46
|
+
options = [],
|
|
47
|
+
required = false,
|
|
48
|
+
disabled = false,
|
|
49
|
+
error,
|
|
50
|
+
helperText,
|
|
51
|
+
placeholder,
|
|
52
|
+
...restProps
|
|
53
|
+
}: SelectInputFieldViewProps) {
|
|
54
|
+
const { styleProps, htmlProps } = useBaseProps(restProps);
|
|
55
|
+
|
|
56
|
+
const handleChange = (event: SelectChangeEvent<string | number>) => {
|
|
57
|
+
if (onChange) {
|
|
58
|
+
onChange(event.target.value);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Return error state if no options provided
|
|
63
|
+
if (!options.length) {
|
|
64
|
+
return (
|
|
65
|
+
<Paper
|
|
66
|
+
{...htmlProps}
|
|
67
|
+
{...styleProps}
|
|
68
|
+
variant="outlined"
|
|
69
|
+
sx={{
|
|
70
|
+
p: 2,
|
|
71
|
+
textAlign: 'center',
|
|
72
|
+
opacity: 0.6,
|
|
73
|
+
borderColor: 'error.main',
|
|
74
|
+
...styleProps.sx
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
<Typography variant="body2" color="error">
|
|
78
|
+
No options provided for select field
|
|
79
|
+
</Typography>
|
|
80
|
+
</Paper>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<FormControl
|
|
86
|
+
{...htmlProps}
|
|
87
|
+
{...styleProps}
|
|
88
|
+
fullWidth
|
|
89
|
+
error={!!error}
|
|
90
|
+
required={required}
|
|
91
|
+
disabled={disabled}
|
|
92
|
+
sx={{
|
|
93
|
+
...styleProps.sx
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
<InputLabel shrink={!!value || !!placeholder}>
|
|
97
|
+
{label}
|
|
98
|
+
</InputLabel>
|
|
99
|
+
<Select
|
|
100
|
+
value={value}
|
|
101
|
+
onChange={handleChange}
|
|
102
|
+
onFocus={onFocus}
|
|
103
|
+
displayEmpty={!!placeholder}
|
|
104
|
+
renderValue={value !== '' ? undefined : () => (
|
|
105
|
+
<span style={{ opacity: 0.6 }}>{placeholder}</span>
|
|
106
|
+
)}
|
|
107
|
+
>
|
|
108
|
+
{placeholder && (
|
|
109
|
+
<MenuItem value="" disabled>
|
|
110
|
+
<em>{placeholder}</em>
|
|
111
|
+
</MenuItem>
|
|
112
|
+
)}
|
|
113
|
+
{options.map((option) => (
|
|
114
|
+
<MenuItem
|
|
115
|
+
key={option.value}
|
|
116
|
+
value={option.value}
|
|
117
|
+
disabled={option.disabled}
|
|
118
|
+
>
|
|
119
|
+
{option.label}
|
|
120
|
+
</MenuItem>
|
|
121
|
+
))}
|
|
122
|
+
</Select>
|
|
123
|
+
{(error || helperText) && (
|
|
124
|
+
<FormHelperText>
|
|
125
|
+
{error || helperText}
|
|
126
|
+
</FormHelperText>
|
|
127
|
+
)}
|
|
128
|
+
</FormControl>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* SelectInputField component with data binding support
|
|
134
|
+
* Supports both traditional props and dataSource-driven rendering
|
|
135
|
+
*/
|
|
136
|
+
function SelectInputField(props: SelectInputFieldProps) {
|
|
137
|
+
const { dataSource, bindingOptions, ...restProps } = props;
|
|
138
|
+
|
|
139
|
+
// If no dataSource, use traditional props
|
|
140
|
+
if (!dataSource) {
|
|
141
|
+
return <SelectInputFieldView {...restProps} />;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Use data binding
|
|
145
|
+
const { dataSource: _source, loading, error, cached, ...selectInputFieldProps } = useDataBinding<SelectInputFieldModel>(
|
|
146
|
+
dataSource,
|
|
147
|
+
restProps as Partial<SelectInputFieldModel>,
|
|
148
|
+
SelectInputFieldModel.getSchema(),
|
|
149
|
+
{ cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
// Show loading state
|
|
153
|
+
if (loading) {
|
|
154
|
+
return (
|
|
155
|
+
<Paper
|
|
156
|
+
variant="outlined"
|
|
157
|
+
sx={{
|
|
158
|
+
p: 2,
|
|
159
|
+
textAlign: 'center'
|
|
160
|
+
}}
|
|
161
|
+
>
|
|
162
|
+
<Typography variant="body2">Loading SelectInputField...</Typography>
|
|
163
|
+
<Typography variant="caption" color="text.secondary">
|
|
164
|
+
Loading select field configuration from data source...
|
|
165
|
+
</Typography>
|
|
166
|
+
</Paper>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (error) {
|
|
171
|
+
console.error('Error loading select input field:', error);
|
|
172
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
173
|
+
return (
|
|
174
|
+
<Paper
|
|
175
|
+
variant="outlined"
|
|
176
|
+
sx={{
|
|
177
|
+
p: 2,
|
|
178
|
+
textAlign: 'center',
|
|
179
|
+
borderColor: 'error.main'
|
|
180
|
+
}}
|
|
181
|
+
>
|
|
182
|
+
<Typography variant="body2" color="error">
|
|
183
|
+
Error loading select field: {error.message}
|
|
184
|
+
</Typography>
|
|
185
|
+
</Paper>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return <SelectInputFieldView {...selectInputFieldProps} />;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Mark as QwickApp component
|
|
195
|
+
(SelectInputField as any)[QWICKAPP_COMPONENT] = true;
|
|
196
|
+
|
|
197
|
+
export default SelectInputField;
|