@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,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ContentResolver provides a unified interface to fetch and render content
|
|
3
|
+
* using data providers, template resolvers, and optional caching.
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
6
|
+
*/
|
|
7
|
+
import { Logger } from '@qwickapps/logging';
|
|
8
|
+
import { CachedDataProvider, DataResponse, ICacheProvider, IDataProvider, MemoryCacheProvider, Model, MustacheTemplateProvider, SelectOptions } from '@qwickapps/schema';
|
|
9
|
+
import {
|
|
10
|
+
DataProxy,
|
|
11
|
+
ITemplateResolver,
|
|
12
|
+
TemplateProvider,
|
|
13
|
+
TemplateResolverConfig
|
|
14
|
+
} from "../types";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* ContentResolver - Combines data, template, and cache providers
|
|
18
|
+
*
|
|
19
|
+
* This class follows the orchestrator pattern:
|
|
20
|
+
* - Delegates data fetching to IDataProvider
|
|
21
|
+
* - Delegates template resolution to ITemplateResolver
|
|
22
|
+
* - Optionally wraps data provider with ICacheProvider
|
|
23
|
+
* - Creates ContentProxy objects for framework compatibility
|
|
24
|
+
*
|
|
25
|
+
* Usage:
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const resolver = new ContentResolver({
|
|
28
|
+
* dataProvider: new JsonDataProvider({ data: {...} }),
|
|
29
|
+
* templateResolver: new MustacheTemplateResolver(),
|
|
30
|
+
* cacheProvider: new MemoryCacheProvider({ maxSize: 50, defaultTtl: 60000 })
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Or with boolean cacheProvider (uses default MemoryCacheProvider)
|
|
34
|
+
* const resolver = new ContentResolver({
|
|
35
|
+
* dataProvider: new JsonDataProvider({ data: {...} }),
|
|
36
|
+
* cacheProvider: true
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* // Or no caching
|
|
40
|
+
* const resolver = new ContentResolver({
|
|
41
|
+
* dataProvider: new JsonDataProvider({ data: {...} }),
|
|
42
|
+
* cacheProvider: false // or omit entirely
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export class TemplateResolver implements ITemplateResolver {
|
|
47
|
+
private dataProvider: IDataProvider;
|
|
48
|
+
private templateResolver: TemplateProvider;
|
|
49
|
+
private cacheProvider?: ICacheProvider<any[]>;
|
|
50
|
+
private enableLogging: boolean;
|
|
51
|
+
private log: Logger;
|
|
52
|
+
|
|
53
|
+
constructor(config: TemplateResolverConfig) {
|
|
54
|
+
this.log = new Logger({
|
|
55
|
+
namespace: 'ContentResolver',
|
|
56
|
+
enabled: config.enableLogging || false
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
this.enableLogging = config.enableLogging || false;
|
|
60
|
+
this.templateResolver = config.templateResolver || new MustacheTemplateProvider();
|
|
61
|
+
if (config.cacheProvider === true) {
|
|
62
|
+
const cacheProvider = new MemoryCacheProvider<any[]>({enableLogging: config.enableLogging || false});
|
|
63
|
+
this.dataProvider = new CachedDataProvider(config.dataProvider);
|
|
64
|
+
} else if (config.cacheProvider === false) {
|
|
65
|
+
this.dataProvider = config.dataProvider;
|
|
66
|
+
} else {
|
|
67
|
+
const cacheProvider = new MemoryCacheProvider<any[]>({enableLogging: config.enableLogging || false});
|
|
68
|
+
this.dataProvider = new CachedDataProvider(config.dataProvider);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
this.log.debug('ContentResolver initialized', {
|
|
73
|
+
dataProvider: config.dataProvider ? config.dataProvider.constructor.name : 'none',
|
|
74
|
+
templateResolver: this.templateResolver.constructor.name,
|
|
75
|
+
cacheProvider: config.cacheProvider ?
|
|
76
|
+
(config.cacheProvider === true ? 'MemoryCacheProvider(default)' : config.cacheProvider.constructor.name) :
|
|
77
|
+
'disabled'
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async get<T extends Model>(slug: string): Promise<DataResponse<T>> {
|
|
82
|
+
return this.dataProvider.get<T>(slug);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async select<T extends Model>(schema: string, options?: SelectOptions): Promise<DataResponse<T[]>> {
|
|
86
|
+
return this.dataProvider.select<T>(schema, options);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resolve template with lazy context loading
|
|
91
|
+
*/
|
|
92
|
+
async resolveTemplate(template: string): Promise < string > {
|
|
93
|
+
this.log.debug(`Resolving template: ${template}`);
|
|
94
|
+
|
|
95
|
+
if(!template || !template.includes('{{')) {
|
|
96
|
+
// No mustache syntax, return as-is
|
|
97
|
+
return template;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Create lazy context proxy
|
|
101
|
+
const context = await this.createLazyContext(template);
|
|
102
|
+
|
|
103
|
+
// Resolve using template resolver
|
|
104
|
+
try {
|
|
105
|
+
const resolved = this.templateResolver.resolve(template, context);
|
|
106
|
+
this.log.debug(`Template resolved: ${template} -> ${resolved}`);
|
|
107
|
+
return resolved;
|
|
108
|
+
} catch (error) {
|
|
109
|
+
this.log.debug(`Template resolution failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Create lazy loading context for template resolution
|
|
116
|
+
* Only fetches data when accessed by mustache template
|
|
117
|
+
*/
|
|
118
|
+
private async createLazyContext(template: string): Promise<any> {
|
|
119
|
+
// Extract field group IDs from template
|
|
120
|
+
const mustachePattern = /\{\{([^}]+)\}\}/g;
|
|
121
|
+
const matches = Array.from(template.matchAll(mustachePattern));
|
|
122
|
+
const fieldGroups = new Set<string>();
|
|
123
|
+
|
|
124
|
+
for (const match of matches) {
|
|
125
|
+
const fullPath = match[1].trim();
|
|
126
|
+
const [fieldGroupId] = fullPath.split('.');
|
|
127
|
+
fieldGroups.add(fieldGroupId);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Fetch all needed data
|
|
131
|
+
const contextData: Record<string, any> = {};
|
|
132
|
+
|
|
133
|
+
for (const fieldGroupId of fieldGroups) {
|
|
134
|
+
try {
|
|
135
|
+
// First try to get it as an array using select
|
|
136
|
+
const arrayData = await this.select(fieldGroupId);
|
|
137
|
+
|
|
138
|
+
if (arrayData.data && arrayData.data.length > 0) {
|
|
139
|
+
// Use first item for template context - use data directly
|
|
140
|
+
contextData[fieldGroupId] = arrayData.data[0];
|
|
141
|
+
} else {
|
|
142
|
+
// Fallback to get single item
|
|
143
|
+
const data = await this.get(fieldGroupId);
|
|
144
|
+
if (data.data) {
|
|
145
|
+
contextData[fieldGroupId] = data.data;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
this.log.error(`Failed to load data for ${fieldGroupId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
150
|
+
// Continue with other field groups
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return contextData;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quick test to verify console warning functionality
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { PaletteProvider, PaletteSwitcher } from '../index';
|
|
7
|
+
import { Typography, Box } from '@mui/material';
|
|
8
|
+
|
|
9
|
+
export default function ConsoleWarningTest() {
|
|
10
|
+
return (
|
|
11
|
+
<Box sx={{ p: 3 }}>
|
|
12
|
+
<Typography variant="h5" gutterBottom>
|
|
13
|
+
Console Warning Test
|
|
14
|
+
</Typography>
|
|
15
|
+
<Typography variant="body1" sx={{ mb: 2 }}>
|
|
16
|
+
Open your browser's developer console to see the warning message for auto-generated storage keys.
|
|
17
|
+
</Typography>
|
|
18
|
+
|
|
19
|
+
{/* This should trigger the console warning */}
|
|
20
|
+
<PaletteProvider>
|
|
21
|
+
<Box sx={{ p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 1 }}>
|
|
22
|
+
<Typography variant="h6" gutterBottom>
|
|
23
|
+
Auto Key (Default - triggers warning)
|
|
24
|
+
</Typography>
|
|
25
|
+
<PaletteSwitcher />
|
|
26
|
+
</Box>
|
|
27
|
+
</PaletteProvider>
|
|
28
|
+
</Box>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Key Strategy Test Component
|
|
3
|
+
* Demonstrates the three different storage strategies
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { PaletteProvider, PaletteSwitcher, usePalette } from '../index';
|
|
8
|
+
import { Box, Typography, Paper } from '@mui/material';
|
|
9
|
+
|
|
10
|
+
function PaletteInfo({
|
|
11
|
+
title,
|
|
12
|
+
appId,
|
|
13
|
+
description
|
|
14
|
+
}: {
|
|
15
|
+
title: string;
|
|
16
|
+
appId: string | true | false;
|
|
17
|
+
description: string;
|
|
18
|
+
}) {
|
|
19
|
+
const { currentPalette } = usePalette();
|
|
20
|
+
|
|
21
|
+
// Helper to show what the actual storage key would be
|
|
22
|
+
const getActualKey = () => {
|
|
23
|
+
if (appId === false) return null;
|
|
24
|
+
if (appId === true || appId === undefined) {
|
|
25
|
+
return 'qwickapps-react-framework-palette';
|
|
26
|
+
}
|
|
27
|
+
return `${appId}.palette`;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const actualKey = getActualKey();
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Paper sx={{ p: 2, mb: 2 }}>
|
|
34
|
+
<Typography variant="h6" gutterBottom>
|
|
35
|
+
{title}
|
|
36
|
+
</Typography>
|
|
37
|
+
<Typography variant="body2" sx={{ mb: 1, color: 'text.secondary' }}>
|
|
38
|
+
{description}
|
|
39
|
+
</Typography>
|
|
40
|
+
<Typography variant="body2" sx={{ mb: 1 }}>
|
|
41
|
+
Config: <code>{String(appId)}</code>
|
|
42
|
+
</Typography>
|
|
43
|
+
<Typography variant="body2" sx={{ mb: 1 }}>
|
|
44
|
+
Actual Key: <code>{actualKey || 'none (no persistence)'}</code>
|
|
45
|
+
</Typography>
|
|
46
|
+
<Typography variant="body2" sx={{ mb: 2 }}>
|
|
47
|
+
Current Palette: <strong>{currentPalette}</strong>
|
|
48
|
+
</Typography>
|
|
49
|
+
<Typography variant="body2" sx={{ mb: 2 }}>
|
|
50
|
+
localStorage: <code>{actualKey ? (localStorage.getItem(actualKey) || 'null') : 'disabled'}</code>
|
|
51
|
+
</Typography>
|
|
52
|
+
<PaletteSwitcher />
|
|
53
|
+
</Paper>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default function StorageKeyTest() {
|
|
58
|
+
return (
|
|
59
|
+
<Box sx={{ p: 3, maxWidth: 900, margin: '0 auto' }}>
|
|
60
|
+
<Typography variant="h4" gutterBottom>
|
|
61
|
+
Storage Key Strategy Test
|
|
62
|
+
</Typography>
|
|
63
|
+
|
|
64
|
+
<Typography variant="body1" sx={{ mb: 3 }}>
|
|
65
|
+
This test demonstrates the three storage strategies. Change palettes in each section
|
|
66
|
+
and notice the different behaviors. Reload the page to see persistence differences.
|
|
67
|
+
</Typography>
|
|
68
|
+
|
|
69
|
+
<PaletteProvider appId="com.test.explicit-key">
|
|
70
|
+
<PaletteInfo
|
|
71
|
+
title="1. Explicit App ID Strategy"
|
|
72
|
+
appId="com.test.explicit-key"
|
|
73
|
+
description="Uses appId to generate storage key 'com.test.explicit-key.palette'. Recommended for production apps."
|
|
74
|
+
/>
|
|
75
|
+
</PaletteProvider>
|
|
76
|
+
|
|
77
|
+
<PaletteProvider appId={true}>
|
|
78
|
+
<PaletteInfo
|
|
79
|
+
title="2. Default Key Strategy"
|
|
80
|
+
appId={true}
|
|
81
|
+
description="Uses default key 'qwickapps-react-framework-palette'. Good for development/demos. Shows console warning."
|
|
82
|
+
/>
|
|
83
|
+
</PaletteProvider>
|
|
84
|
+
|
|
85
|
+
<PaletteProvider appId={false}>
|
|
86
|
+
<PaletteInfo
|
|
87
|
+
title="3. No Persistence Strategy"
|
|
88
|
+
appId={false}
|
|
89
|
+
description="Session-only storage, no localStorage persistence. Settings reset on page reload."
|
|
90
|
+
/>
|
|
91
|
+
</PaletteProvider>
|
|
92
|
+
|
|
93
|
+
<Paper sx={{ p: 2, mt: 3, backgroundColor: 'var(--palette-surface-variant)' }}>
|
|
94
|
+
<Typography variant="h6" gutterBottom>
|
|
95
|
+
Test Instructions:
|
|
96
|
+
</Typography>
|
|
97
|
+
<Typography variant="body2" component="div">
|
|
98
|
+
<ol style={{ paddingLeft: '20px' }}>
|
|
99
|
+
<li>Select different palettes in each section above</li>
|
|
100
|
+
<li>Notice the three different behaviors: explicit app ID, default key with warning, and no persistence</li>
|
|
101
|
+
<li>Section 1 uses custom appId, Section 2 uses default key with warning, Section 3 has no persistence</li>
|
|
102
|
+
<li>Reload the page - Sections 1 & 2 remember their selections, Section 3 resets</li>
|
|
103
|
+
<li>Open browser DevTools → Application → Local Storage to see the different keys</li>
|
|
104
|
+
<li>Check the console to see the warning for the default key usage</li>
|
|
105
|
+
</ol>
|
|
106
|
+
</Typography>
|
|
107
|
+
</Paper>
|
|
108
|
+
</Box>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Storage Key Strategy Test Component
|
|
3
|
+
* Demonstrates the three different storage strategies for ThemeProvider
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { ThemeProvider, ThemeSwitcher, useTheme } from '../index';
|
|
8
|
+
import { Box, Typography, Paper } from '@mui/material';
|
|
9
|
+
|
|
10
|
+
function ThemeInfo({
|
|
11
|
+
title,
|
|
12
|
+
appId,
|
|
13
|
+
description
|
|
14
|
+
}: {
|
|
15
|
+
title: string;
|
|
16
|
+
appId: string | true | false;
|
|
17
|
+
description: string;
|
|
18
|
+
}) {
|
|
19
|
+
const { currentTheme, actualThemeMode } = useTheme();
|
|
20
|
+
|
|
21
|
+
// Helper to show what the actual storage key would be
|
|
22
|
+
const getActualKey = () => {
|
|
23
|
+
if (appId === false) return null;
|
|
24
|
+
if (appId === true) {
|
|
25
|
+
return 'qwickapps-react-framework-theme';
|
|
26
|
+
}
|
|
27
|
+
return `${appId}.theme`;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const actualKey = getActualKey();
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Paper sx={{ p: 2, mb: 2 }}>
|
|
34
|
+
<Typography variant="h6" gutterBottom>
|
|
35
|
+
{title}
|
|
36
|
+
</Typography>
|
|
37
|
+
<Typography variant="body2" sx={{ mb: 1, color: 'text.secondary' }}>
|
|
38
|
+
{description}
|
|
39
|
+
</Typography>
|
|
40
|
+
<Typography variant="body2" sx={{ mb: 1 }}>
|
|
41
|
+
Config: <code>{String(appId)}</code>
|
|
42
|
+
</Typography>
|
|
43
|
+
<Typography variant="body2" sx={{ mb: 1 }}>
|
|
44
|
+
Actual Key: <code>{actualKey || 'none (no persistence)'}</code>
|
|
45
|
+
</Typography>
|
|
46
|
+
<Typography variant="body2" sx={{ mb: 1 }}>
|
|
47
|
+
Theme Mode: <strong>{currentTheme}</strong>
|
|
48
|
+
</Typography>
|
|
49
|
+
<Typography variant="body2" sx={{ mb: 2 }}>
|
|
50
|
+
Actual Theme: <strong>{actualThemeMode}</strong>
|
|
51
|
+
</Typography>
|
|
52
|
+
<Typography variant="body2" sx={{ mb: 2 }}>
|
|
53
|
+
localStorage: <code>{actualKey ? (localStorage.getItem(actualKey) || 'null') : 'disabled'}</code>
|
|
54
|
+
</Typography>
|
|
55
|
+
<ThemeSwitcher />
|
|
56
|
+
</Paper>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default function ThemeStorageKeyTest() {
|
|
61
|
+
return (
|
|
62
|
+
<Box sx={{ p: 3, maxWidth: 900, margin: '0 auto' }}>
|
|
63
|
+
<Typography variant="h4" gutterBottom>
|
|
64
|
+
Theme Storage Key Strategy Test
|
|
65
|
+
</Typography>
|
|
66
|
+
|
|
67
|
+
<Typography variant="body1" sx={{ mb: 3 }}>
|
|
68
|
+
This test demonstrates the three storage strategies for ThemeProvider. Change themes in each section
|
|
69
|
+
and notice the different behaviors. Reload the page to see persistence differences.
|
|
70
|
+
</Typography>
|
|
71
|
+
|
|
72
|
+
<ThemeProvider appId="com.test.explicit-theme">
|
|
73
|
+
<ThemeInfo
|
|
74
|
+
title="1. Explicit App ID Strategy"
|
|
75
|
+
appId="com.test.explicit-theme"
|
|
76
|
+
description="Uses appId to generate storage key 'com.test.explicit-theme.theme'. Recommended for production apps."
|
|
77
|
+
/>
|
|
78
|
+
</ThemeProvider>
|
|
79
|
+
|
|
80
|
+
<ThemeProvider>
|
|
81
|
+
<ThemeInfo
|
|
82
|
+
title="2. Default Key Strategy"
|
|
83
|
+
appId={true}
|
|
84
|
+
description="Uses default key 'qwickapps-react-framework-theme'. Good for development/demos. Shows console warning."
|
|
85
|
+
/>
|
|
86
|
+
</ThemeProvider>
|
|
87
|
+
|
|
88
|
+
<ThemeProvider appId={false}>
|
|
89
|
+
<ThemeInfo
|
|
90
|
+
title="3. No Persistence Strategy"
|
|
91
|
+
appId={false}
|
|
92
|
+
description="Disables localStorage persistence. Theme resets to 'system' on page reload."
|
|
93
|
+
/>
|
|
94
|
+
</ThemeProvider>
|
|
95
|
+
|
|
96
|
+
<Paper sx={{ p: 2, mt: 3, backgroundColor: 'var(--palette-surface-variant)' }}>
|
|
97
|
+
<Typography variant="h6" gutterBottom>
|
|
98
|
+
Test Instructions:
|
|
99
|
+
</Typography>
|
|
100
|
+
<Typography variant="body2" component="div">
|
|
101
|
+
<ol style={{ paddingLeft: '20px' }}>
|
|
102
|
+
<li>Select different themes in each section above</li>
|
|
103
|
+
<li>Notice that sections 1 & 2 save to localStorage with different keys, section 3 doesn't persist</li>
|
|
104
|
+
<li>Section 1 uses custom appId, Section 2 uses default key with warning, Section 3 has no persistence</li>
|
|
105
|
+
<li>Reload the page - sections 1 & 2 remember their selections, section 3 resets to system</li>
|
|
106
|
+
<li>Open browser DevTools → Application → Local Storage to see the different keys</li>
|
|
107
|
+
<li>Check the console to see the warning for the default key usage</li>
|
|
108
|
+
<li>Try switching your OS theme preference to see "system" mode behavior</li>
|
|
109
|
+
</ol>
|
|
110
|
+
</Typography>
|
|
111
|
+
</Paper>
|
|
112
|
+
</Box>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure cache provider interface - Single Responsibility: Caching only
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface ICacheProvider<T> {
|
|
6
|
+
/** Get cached value by key */
|
|
7
|
+
get(key: string): T | null;
|
|
8
|
+
/** Set cached value with optional TTL */
|
|
9
|
+
set(key: string, value: T, ttl?: number): void;
|
|
10
|
+
/** Clear cache entry or all entries */
|
|
11
|
+
clear(key?: string): void;
|
|
12
|
+
/** Get cache statistics */
|
|
13
|
+
getStats?(): { size: number; maxSize: number; keys: string[]; };
|
|
14
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataProxy class to enhance Data with nested property access
|
|
3
|
+
* This class wraps a Data object and provides a proxy to allow
|
|
4
|
+
* accessing nested properties using dot notation, e.g., {{company.name}}
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2024 QwickApps.com. All rights reserved.
|
|
7
|
+
*/
|
|
8
|
+
import { Data, Field, FieldGroup, Action } from "./DataTypes";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Enhanced data with nested property access for template resolution
|
|
12
|
+
* Supports deep nested access like {{company.profile.address.city}}
|
|
13
|
+
*/
|
|
14
|
+
export class DataProxy implements Data {
|
|
15
|
+
public name!: string;
|
|
16
|
+
public type!: string;
|
|
17
|
+
public title?: string;
|
|
18
|
+
public subtitle?: string;
|
|
19
|
+
public overline?: string;
|
|
20
|
+
public icon?: string;
|
|
21
|
+
public fields?: Field[];
|
|
22
|
+
public fieldGroups?: FieldGroup[];
|
|
23
|
+
public actions?: Action[];
|
|
24
|
+
public repeatable?: boolean;
|
|
25
|
+
public minRows?: number;
|
|
26
|
+
public maxRows?: number;
|
|
27
|
+
public autoCreate?: boolean;
|
|
28
|
+
|
|
29
|
+
private data: Record<string, any>;
|
|
30
|
+
|
|
31
|
+
constructor(content: Data, data: Record<string, any> = {}) {
|
|
32
|
+
Object.assign(this, content);
|
|
33
|
+
this.data = data;
|
|
34
|
+
|
|
35
|
+
// Create proxy to enable nested property access
|
|
36
|
+
return new Proxy(this, {
|
|
37
|
+
get: (target, prop: string | symbol) => {
|
|
38
|
+
// Return existing properties first
|
|
39
|
+
if (prop in target || typeof prop === 'symbol') {
|
|
40
|
+
return target[prop as keyof DataProxy];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Handle nested property access for data
|
|
44
|
+
return this.getNestedValue(String(prop));
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get nested value from data using dot notation
|
|
51
|
+
* Supports: company.name, user.profile.avatar.url, etc.
|
|
52
|
+
*/
|
|
53
|
+
private getNestedValue(path: string): any {
|
|
54
|
+
const keys = path.split('.');
|
|
55
|
+
let current = this.data;
|
|
56
|
+
|
|
57
|
+
for (const key of keys) {
|
|
58
|
+
if (current === null || current === undefined) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
current = current[key];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return current;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Set nested value in data using dot notation
|
|
69
|
+
*/
|
|
70
|
+
public setNestedValue(path: string, value: any): void {
|
|
71
|
+
const keys = path.split('.');
|
|
72
|
+
const lastKey = keys.pop()!;
|
|
73
|
+
let current = this.data;
|
|
74
|
+
|
|
75
|
+
// Create nested objects as needed
|
|
76
|
+
for (const key of keys) {
|
|
77
|
+
if (!(key in current) || typeof current[key] !== 'object') {
|
|
78
|
+
current[key] = {};
|
|
79
|
+
}
|
|
80
|
+
current = current[key];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
current[lastKey] = value;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get all data including nested structures
|
|
88
|
+
*/
|
|
89
|
+
public getData(): Record<string, any> {
|
|
90
|
+
return this.data;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Update data while preserving nested structure
|
|
95
|
+
*/
|
|
96
|
+
public updateData(newData: Record<string, any>): void {
|
|
97
|
+
this.data = { ...this.data, ...newData };
|
|
98
|
+
}
|
|
99
|
+
}
|