@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,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML Transform Utilities Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { render } from '@testing-library/react';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import {
|
|
8
|
+
transformElement,
|
|
9
|
+
transformHtmlToReact,
|
|
10
|
+
stripHeaderFromContent,
|
|
11
|
+
defaultArticleRules,
|
|
12
|
+
defaultMarkdownRules
|
|
13
|
+
} from '../htmlTransform';
|
|
14
|
+
|
|
15
|
+
// Helper function to create DOM elements for testing
|
|
16
|
+
function createElementFromHTML(html: string): Element {
|
|
17
|
+
const parser = new DOMParser();
|
|
18
|
+
const doc = parser.parseFromString(html, 'text/html');
|
|
19
|
+
return doc.body.firstElementChild!;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe('HTML Transform Utilities', () => {
|
|
23
|
+
|
|
24
|
+
describe('stripHeaderFromContent', () => {
|
|
25
|
+
it('removes blog headers from HTML content', () => {
|
|
26
|
+
const html = '<header class="blog-header"><h1>Title</h1></header><p>Content</p>';
|
|
27
|
+
const result = stripHeaderFromContent(html);
|
|
28
|
+
expect(result).not.toContain('<header');
|
|
29
|
+
expect(result).toContain('<p>Content</p>');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('removes standalone h1 elements', () => {
|
|
33
|
+
const html = '<h1>Main Title</h1><p>Content follows</p>';
|
|
34
|
+
const result = stripHeaderFromContent(html);
|
|
35
|
+
expect(result).not.toContain('<h1>Main Title</h1>');
|
|
36
|
+
expect(result).toContain('<p>Content follows</p>');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('preserves content when no headers present', () => {
|
|
40
|
+
const html = '<p>Just content</p><div>More content</div>';
|
|
41
|
+
const result = stripHeaderFromContent(html);
|
|
42
|
+
expect(result).toBe(html);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('handles multiple header types', () => {
|
|
46
|
+
const html = '<header class="blog-header">Header 1</header><div class="blog-header">Header 2</div><p>Content</p>';
|
|
47
|
+
const result = stripHeaderFromContent(html);
|
|
48
|
+
expect(result).not.toContain('Header 1');
|
|
49
|
+
expect(result).not.toContain('Header 2');
|
|
50
|
+
expect(result).toContain('<p>Content</p>');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe('transformElement', () => {
|
|
55
|
+
it('transforms pre+code elements to Code components', () => {
|
|
56
|
+
const element = createElementFromHTML('<pre><code class="language-javascript">console.log("test");</code></pre>');
|
|
57
|
+
const result = transformElement(element, 'test-key', { rules: defaultArticleRules });
|
|
58
|
+
|
|
59
|
+
const { container } = render(<>{result}</>);
|
|
60
|
+
expect(container.textContent).toContain('console.log("test");');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('transforms blog sections to Section components', () => {
|
|
64
|
+
const element = createElementFromHTML('<section class="blog-section"><h2>Section Title</h2><p>Content</p></section>');
|
|
65
|
+
const result = transformElement(element, 'test-key', { rules: defaultArticleRules });
|
|
66
|
+
|
|
67
|
+
const { container } = render(<>{result}</>);
|
|
68
|
+
expect(container.textContent).toContain('Section Title');
|
|
69
|
+
expect(container.textContent).toContain('Content');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('transforms button elements to Button components', () => {
|
|
73
|
+
const element = createElementFromHTML('<button data-variant="contained">Click Me</button>');
|
|
74
|
+
const result = transformElement(element, 'test-key', { rules: defaultArticleRules });
|
|
75
|
+
|
|
76
|
+
const { container } = render(<>{result}</>);
|
|
77
|
+
expect(container.textContent).toContain('Click Me');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('handles standalone code blocks', () => {
|
|
81
|
+
const element = createElementFromHTML('<code>multi\nline\ncode</code>');
|
|
82
|
+
const result = transformElement(element, 'test-key', { rules: defaultArticleRules });
|
|
83
|
+
|
|
84
|
+
const { container } = render(<>{result}</>);
|
|
85
|
+
expect(container.textContent).toContain('multi\nline\ncode');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('preserves inline code in paragraphs', () => {
|
|
89
|
+
const element = createElementFromHTML('<p>Text with <code>inline code</code> here</p>');
|
|
90
|
+
const result = transformElement(element, 'test-key', { rules: defaultArticleRules });
|
|
91
|
+
|
|
92
|
+
const { container } = render(<>{result}</>);
|
|
93
|
+
expect(container.textContent).toContain('inline code');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('handles void elements correctly', () => {
|
|
97
|
+
const element = createElementFromHTML('<img src="test.jpg" alt="test" />');
|
|
98
|
+
const result = transformElement(element, 'test-key', { rules: defaultArticleRules });
|
|
99
|
+
|
|
100
|
+
const { container } = render(<>{result}</>);
|
|
101
|
+
const img = container.querySelector('img');
|
|
102
|
+
expect(img).toHaveAttribute('src', 'test.jpg');
|
|
103
|
+
expect(img).toHaveAttribute('alt', 'test');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('falls back to SafeSpan for unknown elements', () => {
|
|
107
|
+
const element = createElementFromHTML('<div class="unknown">Some content</div>');
|
|
108
|
+
const result = transformElement(element, 'test-key', { rules: defaultArticleRules });
|
|
109
|
+
|
|
110
|
+
const { container } = render(<>{result}</>);
|
|
111
|
+
expect(container.textContent).toContain('Some content');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('transformHtmlToReact', () => {
|
|
116
|
+
it('transforms entire HTML documents', () => {
|
|
117
|
+
const html = '<h1>Title</h1><p>Paragraph</p><pre><code>code block</code></pre>';
|
|
118
|
+
const components = transformHtmlToReact(html, { rules: defaultArticleRules });
|
|
119
|
+
|
|
120
|
+
expect(components).toHaveLength(3); // h1, p, and code block
|
|
121
|
+
|
|
122
|
+
const { container } = render(<>{components}</>);
|
|
123
|
+
expect(container.textContent).toContain('Title');
|
|
124
|
+
expect(container.textContent).toContain('Paragraph');
|
|
125
|
+
expect(container.textContent).toContain('code block');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('returns empty array for empty HTML', () => {
|
|
129
|
+
const components = transformHtmlToReact('', { rules: defaultArticleRules });
|
|
130
|
+
expect(components).toEqual([]);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('handles whitespace-only HTML', () => {
|
|
134
|
+
const components = transformHtmlToReact(' \n ', { rules: defaultArticleRules });
|
|
135
|
+
expect(components).toEqual([]);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('transforms complex nested structures', () => {
|
|
139
|
+
const html = `
|
|
140
|
+
<div class="container">
|
|
141
|
+
<section class="blog-section">
|
|
142
|
+
<h2>Section</h2>
|
|
143
|
+
<pre><code class="language-python">print("hello")</code></pre>
|
|
144
|
+
</section>
|
|
145
|
+
</div>
|
|
146
|
+
`;
|
|
147
|
+
const components = transformHtmlToReact(html, { rules: defaultArticleRules });
|
|
148
|
+
|
|
149
|
+
const { container } = render(<>{components}</>);
|
|
150
|
+
expect(container.textContent).toContain('Section');
|
|
151
|
+
expect(container.textContent).toContain('print("hello")');
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
describe('defaultArticleRules', () => {
|
|
156
|
+
it('includes pre+code transformation rule', () => {
|
|
157
|
+
const preRule = defaultArticleRules.find(rule => rule.selector === 'pre');
|
|
158
|
+
expect(preRule).toBeDefined();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('includes standalone code transformation rule', () => {
|
|
162
|
+
const codeRule = defaultArticleRules.find(rule => rule.selector === 'code');
|
|
163
|
+
expect(codeRule).toBeDefined();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('includes blog section transformation rule', () => {
|
|
167
|
+
const sectionRule = defaultArticleRules.find(rule => rule.selector === 'section.blog-section');
|
|
168
|
+
expect(sectionRule).toBeDefined();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('includes button transformation rule', () => {
|
|
172
|
+
const buttonRule = defaultArticleRules.find(rule => rule.selector === 'button');
|
|
173
|
+
expect(buttonRule).toBeDefined();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
describe('defaultMarkdownRules', () => {
|
|
178
|
+
it('includes pre+code transformation rule', () => {
|
|
179
|
+
const preRule = defaultMarkdownRules.find(rule => rule.selector === 'pre');
|
|
180
|
+
expect(preRule).toBeDefined();
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('includes code rule that preserves inline code', () => {
|
|
184
|
+
const codeRule = defaultMarkdownRules.find(rule => rule.selector === 'code');
|
|
185
|
+
expect(codeRule).toBeDefined();
|
|
186
|
+
|
|
187
|
+
// Test that inline code returns null (no transformation)
|
|
188
|
+
const element = createElementFromHTML('<code>inline</code>');
|
|
189
|
+
const result = codeRule!.transform(element, 'test');
|
|
190
|
+
expect(result).toBeNull();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('has fewer rules than article rules (more conservative)', () => {
|
|
194
|
+
expect(defaultMarkdownRules.length).toBeLessThan(defaultArticleRules.length);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
describe('Custom Transform Rules', () => {
|
|
199
|
+
it('applies custom transformation rules', () => {
|
|
200
|
+
const customRules = [{
|
|
201
|
+
selector: 'em',
|
|
202
|
+
transform: (element: Element, key: string) => (
|
|
203
|
+
<strong key={key}>EMPHASIZED: {element.textContent}</strong>
|
|
204
|
+
)
|
|
205
|
+
}];
|
|
206
|
+
|
|
207
|
+
const element = createElementFromHTML('<em>italic text</em>');
|
|
208
|
+
const result = transformElement(element, 'test', { rules: customRules });
|
|
209
|
+
|
|
210
|
+
const { container } = render(<>{result}</>);
|
|
211
|
+
expect(container.textContent).toContain('EMPHASIZED: italic text');
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('combines custom rules with default rules', () => {
|
|
215
|
+
const customRules = [...defaultArticleRules, {
|
|
216
|
+
selector: 'span.highlight',
|
|
217
|
+
transform: (element: Element, key: string) => (
|
|
218
|
+
<mark key={key}>{element.textContent}</mark>
|
|
219
|
+
)
|
|
220
|
+
}];
|
|
221
|
+
|
|
222
|
+
const html = '<span class="highlight">highlighted</span><pre><code>code</code></pre>';
|
|
223
|
+
const components = transformHtmlToReact(html, { rules: customRules });
|
|
224
|
+
|
|
225
|
+
const { container } = render(<>{components}</>);
|
|
226
|
+
expect(container.textContent).toContain('highlighted');
|
|
227
|
+
expect(container.textContent).toContain('code');
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
describe('Error Handling', () => {
|
|
232
|
+
it('handles malformed HTML elements', () => {
|
|
233
|
+
const element = createElementFromHTML('<div>unclosed content');
|
|
234
|
+
const result = transformElement(element, 'test', { rules: defaultArticleRules });
|
|
235
|
+
|
|
236
|
+
const { container } = render(<>{result}</>);
|
|
237
|
+
expect(container.textContent).toContain('unclosed content');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('handles elements with missing attributes', () => {
|
|
241
|
+
const element = createElementFromHTML('<button>No attributes</button>');
|
|
242
|
+
const result = transformElement(element, 'test', { rules: defaultArticleRules });
|
|
243
|
+
|
|
244
|
+
const { container } = render(<>{result}</>);
|
|
245
|
+
expect(container.textContent).toContain('No attributes');
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('handles empty elements', () => {
|
|
249
|
+
const element = createElementFromHTML('<div></div>');
|
|
250
|
+
const result = transformElement(element, 'test', { rules: defaultArticleRules });
|
|
251
|
+
|
|
252
|
+
expect(result).toBeDefined();
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Breakpoint utilities for QwickApps React Framework
|
|
3
|
+
*
|
|
4
|
+
* Consolidates all breakpoint-related logic and type conversions
|
|
5
|
+
* to ensure consistency across components.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { MUIBreakpoint, BreakpointValue, ExtendedBreakpoint } from '../types';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Standard MUI breakpoint pixel values
|
|
14
|
+
*/
|
|
15
|
+
export const MUI_BREAKPOINT_VALUES: Record<MUIBreakpoint, number> = {
|
|
16
|
+
xs: 0,
|
|
17
|
+
sm: 600,
|
|
18
|
+
md: 900,
|
|
19
|
+
lg: 1200,
|
|
20
|
+
xl: 1536,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Mapping from extended names to MUI breakpoint names
|
|
25
|
+
*/
|
|
26
|
+
const EXTENDED_TO_MUI_MAP: Record<ExtendedBreakpoint, MUIBreakpoint> = {
|
|
27
|
+
'extra-small': 'xs',
|
|
28
|
+
'small': 'sm',
|
|
29
|
+
'medium': 'md',
|
|
30
|
+
'large': 'lg',
|
|
31
|
+
'extra-large': 'xl',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Converts any breakpoint value to MUI breakpoint format
|
|
36
|
+
* Handles extended names, MUI names, and false values
|
|
37
|
+
*/
|
|
38
|
+
export function mapToMUIBreakpoint(value?: BreakpointValue): MUIBreakpoint | false {
|
|
39
|
+
if (value === false || value === undefined) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Direct MUI breakpoint
|
|
44
|
+
if (value in MUI_BREAKPOINT_VALUES) {
|
|
45
|
+
return value as MUIBreakpoint;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Extended breakpoint name
|
|
49
|
+
if (value in EXTENDED_TO_MUI_MAP) {
|
|
50
|
+
return EXTENDED_TO_MUI_MAP[value as ExtendedBreakpoint];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Default fallback
|
|
54
|
+
return 'lg';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Gets the pixel value for a breakpoint
|
|
59
|
+
*/
|
|
60
|
+
export function getBreakpointPixelValue(breakpoint: MUIBreakpoint | BreakpointValue): number {
|
|
61
|
+
const muiBreakpoint = mapToMUIBreakpoint(breakpoint as BreakpointValue);
|
|
62
|
+
if (muiBreakpoint === false) {
|
|
63
|
+
return Infinity; // No max width
|
|
64
|
+
}
|
|
65
|
+
return MUI_BREAKPOINT_VALUES[muiBreakpoint];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Type guard to check if a value is a valid MUI breakpoint
|
|
70
|
+
*/
|
|
71
|
+
export function isMUIBreakpoint(value: unknown): value is MUIBreakpoint {
|
|
72
|
+
return typeof value === 'string' && value in MUI_BREAKPOINT_VALUES;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Type guard to check if a value is an extended breakpoint name
|
|
77
|
+
*/
|
|
78
|
+
export function isExtendedBreakpoint(value: unknown): value is ExtendedBreakpoint {
|
|
79
|
+
return typeof value === 'string' && value in EXTENDED_TO_MUI_MAP;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Type guard to check if a value is any valid breakpoint
|
|
84
|
+
*/
|
|
85
|
+
export function isBreakpointValue(value: unknown): value is BreakpointValue {
|
|
86
|
+
return value === false || isMUIBreakpoint(value) || isExtendedBreakpoint(value);
|
|
87
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Palette Manager - Create and manage custom color palettes
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Saves a custom palette to localStorage
|
|
9
|
+
* @param {Object} palette - Palette object with id, name, colors, etc.
|
|
10
|
+
*/
|
|
11
|
+
export const saveCustomPalette = (palette) => {
|
|
12
|
+
const customPalettes = getCustomPalettes();
|
|
13
|
+
const updatedPalettes = customPalettes.filter(p => p.id !== palette.id);
|
|
14
|
+
updatedPalettes.push(palette);
|
|
15
|
+
|
|
16
|
+
localStorage.setItem('qwickapps-custom-palettes', JSON.stringify(updatedPalettes));
|
|
17
|
+
|
|
18
|
+
// Dispatch event to notify components
|
|
19
|
+
window.dispatchEvent(new CustomEvent('custom-palettes-changed', {
|
|
20
|
+
detail: { palettes: updatedPalettes }
|
|
21
|
+
}));
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Gets all custom palettes from localStorage
|
|
26
|
+
* @returns {Array} Array of custom palette objects
|
|
27
|
+
*/
|
|
28
|
+
export const getCustomPalettes = () => {
|
|
29
|
+
try {
|
|
30
|
+
const stored = localStorage.getItem('qwickapps-custom-palettes');
|
|
31
|
+
return stored ? JSON.parse(stored) : [];
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.warn('Failed to load custom palettes:', error);
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Deletes a custom palette
|
|
40
|
+
* @param {string} paletteId - ID of the palette to delete
|
|
41
|
+
*/
|
|
42
|
+
export const deleteCustomPalette = (paletteId) => {
|
|
43
|
+
const customPalettes = getCustomPalettes();
|
|
44
|
+
const updatedPalettes = customPalettes.filter(p => p.id !== paletteId);
|
|
45
|
+
|
|
46
|
+
localStorage.setItem('qwickapps-custom-palettes', JSON.stringify(updatedPalettes));
|
|
47
|
+
|
|
48
|
+
// Dispatch event to notify components
|
|
49
|
+
window.dispatchEvent(new CustomEvent('custom-palettes-changed', {
|
|
50
|
+
detail: { palettes: updatedPalettes }
|
|
51
|
+
}));
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Exports a palette to a JSON file
|
|
56
|
+
* @param {Object} palette - Palette to export
|
|
57
|
+
*/
|
|
58
|
+
export const exportPalette = (palette) => {
|
|
59
|
+
const dataStr = JSON.stringify(palette, null, 2);
|
|
60
|
+
const dataBlob = new Blob([dataStr], { type: 'application/json' });
|
|
61
|
+
|
|
62
|
+
const link = document.createElement('a');
|
|
63
|
+
link.href = URL.createObjectURL(dataBlob);
|
|
64
|
+
link.download = `qwickapps-palette-${palette.id}.json`;
|
|
65
|
+
link.click();
|
|
66
|
+
|
|
67
|
+
URL.revokeObjectURL(link.href);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Imports a palette from a JSON file
|
|
72
|
+
* @param {File} file - JSON file containing palette data
|
|
73
|
+
* @returns {Promise<Object>} Parsed palette object
|
|
74
|
+
*/
|
|
75
|
+
export const importPalette = (file) => {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
const reader = new FileReader();
|
|
78
|
+
|
|
79
|
+
reader.onload = (event) => {
|
|
80
|
+
try {
|
|
81
|
+
const palette = JSON.parse(event.target.result);
|
|
82
|
+
|
|
83
|
+
// Basic validation
|
|
84
|
+
if (!palette.id || !palette.name || !palette.primaryColor) {
|
|
85
|
+
reject(new Error('Invalid palette format'));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Ensure unique ID
|
|
90
|
+
const customPalettes = getCustomPalettes();
|
|
91
|
+
if (customPalettes.find(p => p.id === palette.id)) {
|
|
92
|
+
palette.id = `${palette.id}-${Date.now()}`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
resolve(palette);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
reject(new Error('Failed to parse palette file'));
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
reader.onerror = () => reject(new Error('Failed to read file'));
|
|
102
|
+
reader.readAsText(file);
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Creates a new custom palette from current theme colors
|
|
108
|
+
* @param {string} name - Name for the new palette
|
|
109
|
+
* @param {string} description - Description for the palette
|
|
110
|
+
* @returns {Object} New palette object
|
|
111
|
+
*/
|
|
112
|
+
export const createPaletteFromCurrentTheme = (name, description) => {
|
|
113
|
+
const root = document.documentElement;
|
|
114
|
+
const style = getComputedStyle(root);
|
|
115
|
+
|
|
116
|
+
// Extract current colors
|
|
117
|
+
const palette = {
|
|
118
|
+
id: `custom-${Date.now()}`,
|
|
119
|
+
name,
|
|
120
|
+
description,
|
|
121
|
+
isCustom: true,
|
|
122
|
+
createdAt: new Date().toISOString(),
|
|
123
|
+
primaryColor: style.getPropertyValue('--palette-primary-main').trim(),
|
|
124
|
+
colors: {
|
|
125
|
+
primary: {
|
|
126
|
+
main: style.getPropertyValue('--palette-primary-main').trim(),
|
|
127
|
+
light: style.getPropertyValue('--palette-primary-light').trim(),
|
|
128
|
+
dark: style.getPropertyValue('--palette-primary-dark').trim(),
|
|
129
|
+
},
|
|
130
|
+
secondary: {
|
|
131
|
+
main: style.getPropertyValue('--palette-secondary-main').trim(),
|
|
132
|
+
light: style.getPropertyValue('--palette-secondary-light').trim(),
|
|
133
|
+
dark: style.getPropertyValue('--palette-secondary-dark').trim(),
|
|
134
|
+
},
|
|
135
|
+
background: {
|
|
136
|
+
main: style.getPropertyValue('--palette-background-main').trim(),
|
|
137
|
+
secondary: style.getPropertyValue('--palette-background-dark').trim(),
|
|
138
|
+
},
|
|
139
|
+
surface: {
|
|
140
|
+
main: style.getPropertyValue('--palette-surface-main').trim(),
|
|
141
|
+
variant: style.getPropertyValue('--palette-surface-variant').trim(),
|
|
142
|
+
elevated: style.getPropertyValue('--palette-surface-elevated').trim(),
|
|
143
|
+
},
|
|
144
|
+
text: {
|
|
145
|
+
primary: style.getPropertyValue('--palette-text-primary').trim(),
|
|
146
|
+
secondary: style.getPropertyValue('--palette-text-secondary').trim(),
|
|
147
|
+
disabled: style.getPropertyValue('--palette-text-disabled').trim(),
|
|
148
|
+
},
|
|
149
|
+
border: {
|
|
150
|
+
main: style.getPropertyValue('--palette-border-main').trim(),
|
|
151
|
+
light: style.getPropertyValue('--palette-border-light').trim(),
|
|
152
|
+
medium: style.getPropertyValue('--palette-border-medium').trim(),
|
|
153
|
+
},
|
|
154
|
+
success: {
|
|
155
|
+
main: style.getPropertyValue('--palette-success-main').trim(),
|
|
156
|
+
light: style.getPropertyValue('--palette-success-light').trim(),
|
|
157
|
+
dark: style.getPropertyValue('--palette-success-dark').trim(),
|
|
158
|
+
},
|
|
159
|
+
error: {
|
|
160
|
+
main: style.getPropertyValue('--palette-error-main').trim(),
|
|
161
|
+
light: style.getPropertyValue('--palette-error-light').trim(),
|
|
162
|
+
dark: style.getPropertyValue('--palette-error-dark').trim(),
|
|
163
|
+
},
|
|
164
|
+
warning: {
|
|
165
|
+
main: style.getPropertyValue('--palette-warning-main').trim(),
|
|
166
|
+
light: style.getPropertyValue('--palette-warning-light').trim(),
|
|
167
|
+
dark: style.getPropertyValue('--palette-warning-dark').trim(),
|
|
168
|
+
},
|
|
169
|
+
info: {
|
|
170
|
+
main: style.getPropertyValue('--palette-info-main').trim(),
|
|
171
|
+
light: style.getPropertyValue('--palette-info-light').trim(),
|
|
172
|
+
dark: style.getPropertyValue('--palette-info-dark').trim(),
|
|
173
|
+
},
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
return palette;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Applies a custom palette dynamically
|
|
182
|
+
* @param {Object} palette - Custom palette object
|
|
183
|
+
*/
|
|
184
|
+
export const applyCustomPalette = (palette) => {
|
|
185
|
+
const root = document.documentElement;
|
|
186
|
+
|
|
187
|
+
// Apply colors to CSS custom properties
|
|
188
|
+
if (palette.colors) {
|
|
189
|
+
const { colors } = palette;
|
|
190
|
+
|
|
191
|
+
// Apply primary colors
|
|
192
|
+
if (colors.primary) {
|
|
193
|
+
root.style.setProperty('--palette-primary-main', colors.primary.main);
|
|
194
|
+
root.style.setProperty('--palette-primary-light', colors.primary.light);
|
|
195
|
+
root.style.setProperty('--palette-primary-dark', colors.primary.dark);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Apply secondary colors
|
|
199
|
+
if (colors.secondary) {
|
|
200
|
+
root.style.setProperty('--palette-secondary-main', colors.secondary.main);
|
|
201
|
+
root.style.setProperty('--palette-secondary-light', colors.secondary.light);
|
|
202
|
+
root.style.setProperty('--palette-secondary-dark', colors.secondary.dark);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Apply background colors
|
|
206
|
+
if (colors.background) {
|
|
207
|
+
root.style.setProperty('--palette-background-main', colors.background.main);
|
|
208
|
+
root.style.setProperty('--palette-background-dark', colors.background.secondary);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Apply other color categories as needed...
|
|
212
|
+
// (This could be expanded to apply all color categories)
|
|
213
|
+
}
|
|
214
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dimension utilities for QwickApps React Framework
|
|
3
|
+
*
|
|
4
|
+
* Provides standardized dimension value resolution with t-shirt sizing
|
|
5
|
+
* and MUI breakpoint compatibility
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { DimensionValue, TShirtSize, MUIBreakpoint } from '../types';
|
|
11
|
+
|
|
12
|
+
// Re-export the type for backward compatibility
|
|
13
|
+
export type { DimensionValue };
|
|
14
|
+
import { MUI_BREAKPOINT_VALUES } from './breakpoints';
|
|
15
|
+
|
|
16
|
+
export type DimensionContext = 'width' | 'height' | 'maxWidth' | 'maxHeight' | 'minWidth' | 'minHeight';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* T-shirt size mappings for different dimension contexts
|
|
20
|
+
*/
|
|
21
|
+
const TSHIRT_SIZES: Record<DimensionContext, Record<TShirtSize, number>> = {
|
|
22
|
+
width: {
|
|
23
|
+
tiny: 120,
|
|
24
|
+
small: 200,
|
|
25
|
+
medium: 300,
|
|
26
|
+
large: 400,
|
|
27
|
+
'x-large': 500,
|
|
28
|
+
huge: 600,
|
|
29
|
+
},
|
|
30
|
+
height: {
|
|
31
|
+
tiny: 200,
|
|
32
|
+
small: 300,
|
|
33
|
+
medium: 400,
|
|
34
|
+
large: 500,
|
|
35
|
+
'x-large': 600,
|
|
36
|
+
huge: 800,
|
|
37
|
+
},
|
|
38
|
+
maxWidth: {
|
|
39
|
+
tiny: 300,
|
|
40
|
+
small: 600,
|
|
41
|
+
medium: 900,
|
|
42
|
+
large: 1200,
|
|
43
|
+
'x-large': 1536,
|
|
44
|
+
huge: 1920,
|
|
45
|
+
},
|
|
46
|
+
maxHeight: {
|
|
47
|
+
tiny: 200,
|
|
48
|
+
small: 400,
|
|
49
|
+
medium: 600,
|
|
50
|
+
large: 800,
|
|
51
|
+
'x-large': 1000,
|
|
52
|
+
huge: 1200,
|
|
53
|
+
},
|
|
54
|
+
minWidth: {
|
|
55
|
+
tiny: 50,
|
|
56
|
+
small: 100,
|
|
57
|
+
medium: 200,
|
|
58
|
+
large: 300,
|
|
59
|
+
'x-large': 400,
|
|
60
|
+
huge: 500,
|
|
61
|
+
},
|
|
62
|
+
minHeight: {
|
|
63
|
+
tiny: 50,
|
|
64
|
+
small: 100,
|
|
65
|
+
medium: 200,
|
|
66
|
+
large: 300,
|
|
67
|
+
'x-large': 400,
|
|
68
|
+
huge: 500,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* CSS value pattern for validation
|
|
74
|
+
*/
|
|
75
|
+
const CSS_VALUE_PATTERN = /^(\d+(\.\d+)?(px|%|em|rem|vh|vw|fr|ch|ex)|auto|inherit|initial|unset|min-content|max-content|fit-content)$/;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Resolves a dimension value to a valid CSS value
|
|
79
|
+
*/
|
|
80
|
+
export function resolveDimension(
|
|
81
|
+
value: DimensionValue,
|
|
82
|
+
context: DimensionContext = 'width'
|
|
83
|
+
): string | number | undefined {
|
|
84
|
+
if (value === undefined || value === null) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Number values are returned as-is
|
|
89
|
+
if (typeof value === 'number') {
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Auto and grow are always valid
|
|
94
|
+
if (value === 'auto') {
|
|
95
|
+
return 'auto';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (value === 'grow') {
|
|
99
|
+
return '1'; // Flex grow: 1 for CSS flexbox
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Check for t-shirt sizes
|
|
103
|
+
const tshirtSizes = TSHIRT_SIZES[context];
|
|
104
|
+
if (tshirtSizes && value in tshirtSizes) {
|
|
105
|
+
return tshirtSizes[value as TShirtSize];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Check for MUI breakpoint values (for maxWidth/width contexts)
|
|
109
|
+
if ((context === 'maxWidth' || context === 'width') && value in MUI_BREAKPOINT_VALUES) {
|
|
110
|
+
return MUI_BREAKPOINT_VALUES[value as MUIBreakpoint];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Validate CSS string values
|
|
114
|
+
if (typeof value === 'string') {
|
|
115
|
+
if (CSS_VALUE_PATTERN.test(value)) {
|
|
116
|
+
return value;
|
|
117
|
+
} else {
|
|
118
|
+
console.warn(
|
|
119
|
+
`[QwickApps] Invalid CSS dimension value: "${value}". Using as-is but consider using a valid CSS value or t-shirt size.`
|
|
120
|
+
);
|
|
121
|
+
return value;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Resolves multiple dimension props at once
|
|
130
|
+
*/
|
|
131
|
+
export function resolveDimensions(props: {
|
|
132
|
+
width?: DimensionValue;
|
|
133
|
+
height?: DimensionValue;
|
|
134
|
+
minWidth?: DimensionValue;
|
|
135
|
+
minHeight?: DimensionValue;
|
|
136
|
+
maxWidth?: DimensionValue;
|
|
137
|
+
maxHeight?: DimensionValue;
|
|
138
|
+
}) {
|
|
139
|
+
return {
|
|
140
|
+
width: resolveDimension(props.width, 'width'),
|
|
141
|
+
height: resolveDimension(props.height, 'height'),
|
|
142
|
+
minWidth: resolveDimension(props.minWidth, 'minWidth'),
|
|
143
|
+
minHeight: resolveDimension(props.minHeight, 'minHeight'),
|
|
144
|
+
maxWidth: resolveDimension(props.maxWidth, 'maxWidth'),
|
|
145
|
+
maxHeight: resolveDimension(props.maxHeight, 'maxHeight'),
|
|
146
|
+
};
|
|
147
|
+
}
|