@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,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic Logo Component - Generic theme-aware logo
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Automatic text width calculation with dynamic SVG sizing
|
|
6
|
+
* - Semantic badge positioning (top-left, top-right, center, etc.)
|
|
7
|
+
* - Customizable badge position via custom coordinates or relative offset
|
|
8
|
+
* - Multiple badge shapes: circle, star, square, heart
|
|
9
|
+
* - Theme-aware styling with multiple variants
|
|
10
|
+
* - Accessibility support with proper ARIA labels
|
|
11
|
+
* - Customizable styling via CSS classes for each text part
|
|
12
|
+
* - Text formatting with escape sequences
|
|
13
|
+
*
|
|
14
|
+
* Text Formatting (TWO PARTS MAXIMUM):
|
|
15
|
+
* - Use \n for line breaks (second part appears on new line)
|
|
16
|
+
* - Use \s for explicit spaces (useful for custom spacing)
|
|
17
|
+
* - Default: Two-word logos appear as one word in two colors (no space)
|
|
18
|
+
* - Limitation: Only TWO parts supported - multiple \n will not create more than two lines
|
|
19
|
+
* - Examples: "QwickApps" (one word, one color), "Qwick Apps" (two parts, two colors), "Qwick\sApps" (two parts with space), "Qwick\nApps" (two parts on two lines)
|
|
20
|
+
*
|
|
21
|
+
* Badge Positioning:
|
|
22
|
+
* - Semantic: Use 'top-left', 'top-right', 'center', etc. (automatically adapts to logo size)
|
|
23
|
+
* - Default: 'top-right' - positions at top-right of text
|
|
24
|
+
* - Offset: Use badgeOffset to fine-tune any position (automatically scales with size)
|
|
25
|
+
* - None: Use 'none' to hide the badge
|
|
26
|
+
* - Flexible: Combine any semantic position with custom offsets for precise control
|
|
27
|
+
*
|
|
28
|
+
* Text Styling:
|
|
29
|
+
* - Use firstPartClass and secondPartClass for custom CSS styling
|
|
30
|
+
* - Default classes: 'logo-first-part' and 'logo-second-part'
|
|
31
|
+
* - Font family and weight can be set via props for basic customization
|
|
32
|
+
* - Advanced styling (colors, effects, transforms) via CSS classes
|
|
33
|
+
*
|
|
34
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import React, { useRef, useEffect, useState, useCallback } from 'react';
|
|
38
|
+
import { WithBaseProps, useBaseProps, QWICKAPP_COMPONENT } from '../hooks/useBaseProps';
|
|
39
|
+
import './Logo.css';
|
|
40
|
+
|
|
41
|
+
export type LogoVariant = 'default' | 'high-contrast' | 'monochrome' | 'on-primary';
|
|
42
|
+
export type LogoSize = 'tiny' | 'small' | 'medium' | 'large' | 'extra-large';
|
|
43
|
+
export type LogoBadgeShape = 'circle' | 'star' | 'square' | 'heart';
|
|
44
|
+
export type BadgePositionType =
|
|
45
|
+
| 'none'
|
|
46
|
+
| 'top-left'
|
|
47
|
+
| 'top-center'
|
|
48
|
+
| 'top-right'
|
|
49
|
+
| 'center-left'
|
|
50
|
+
| 'center'
|
|
51
|
+
| 'center-right'
|
|
52
|
+
| 'bottom-left'
|
|
53
|
+
| 'bottom-center'
|
|
54
|
+
| 'bottom-right';
|
|
55
|
+
|
|
56
|
+
export interface BadgeOffset {
|
|
57
|
+
/** Horizontal offset from the calculated position (positive = right, negative = left) */
|
|
58
|
+
x?: number;
|
|
59
|
+
/** Vertical offset from the calculated position (positive = down, negative = up) */
|
|
60
|
+
y?: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface LogoProps extends WithBaseProps, Omit<React.SVGProps<SVGSVGElement>, 'width' | 'height' | 'className' | 'style' | 'role' | 'onClick' | 'onMouseEnter' | 'onMouseLeave' | 'onFocus' | 'onBlur'> {
|
|
64
|
+
/** Logo name/text to display. Supports up to TWO parts with \n for line breaks and \s for explicit spaces. */
|
|
65
|
+
name?: string;
|
|
66
|
+
/** Click handler for the logo */
|
|
67
|
+
onClick?: (event: React.MouseEvent<SVGSVGElement>) => void;
|
|
68
|
+
/** Additional inline styles */
|
|
69
|
+
style?: React.CSSProperties;
|
|
70
|
+
/** Visual variant of the logo */
|
|
71
|
+
variant?: LogoVariant;
|
|
72
|
+
/** Size variant of the logo (controls both text size and visual height) */
|
|
73
|
+
size?: LogoSize;
|
|
74
|
+
/** Additional CSS class names */
|
|
75
|
+
className?: string;
|
|
76
|
+
/** Badge position and visibility. 'none' hides the badge, others show it at the specified position. */
|
|
77
|
+
badge?: BadgePositionType;
|
|
78
|
+
/** Shape of the badge */
|
|
79
|
+
badgeShape?: LogoBadgeShape;
|
|
80
|
+
/** Offset from the calculated badge position. Applied after position calculation. Automatically scales with logo size. */
|
|
81
|
+
badgeOffset?: BadgeOffset;
|
|
82
|
+
/** Font family for the logo text */
|
|
83
|
+
fontFamily?: string;
|
|
84
|
+
/** Font weight for the logo text */
|
|
85
|
+
fontWeight?: string | number;
|
|
86
|
+
/** CSS class name for the first part of the logo text. Defaults to 'logo-first-part'. */
|
|
87
|
+
firstPartClass?: string;
|
|
88
|
+
/** CSS class name for the second part of the logo text. Defaults to 'logo-second-part'. */
|
|
89
|
+
secondPartClass?: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const Logo: React.FC<LogoProps> = (props) => {
|
|
93
|
+
const { styleProps, htmlProps, restProps } = useBaseProps(props);
|
|
94
|
+
const {
|
|
95
|
+
name = 'Qwick Apps',
|
|
96
|
+
variant = 'default',
|
|
97
|
+
size = 'medium',
|
|
98
|
+
badge = 'top-right',
|
|
99
|
+
badgeShape = 'circle',
|
|
100
|
+
badgeOffset,
|
|
101
|
+
fontFamily = 'Segoe UI, sans-serif',
|
|
102
|
+
fontWeight = 'bold',
|
|
103
|
+
firstPartClass = 'logo-first-part',
|
|
104
|
+
secondPartClass = 'logo-second-part',
|
|
105
|
+
...svgProps
|
|
106
|
+
} = restProps;
|
|
107
|
+
|
|
108
|
+
// Mark as QwickApp component
|
|
109
|
+
(Logo as any)[QWICKAPP_COMPONENT] = true;
|
|
110
|
+
|
|
111
|
+
const textRef = useRef<SVGTextElement>(null);
|
|
112
|
+
const [calculatedBadgePosition, setCalculatedBadgePosition] = useState({ x: 155, y: 20 });
|
|
113
|
+
const [svgWidth, setSvgWidth] = useState(180);
|
|
114
|
+
|
|
115
|
+
// Parse name with support for escape sequences to determine structure
|
|
116
|
+
const parseNameParts = useCallback((text: string) => {
|
|
117
|
+
// Handle line breaks first
|
|
118
|
+
if (text.includes('\\n')) {
|
|
119
|
+
const [first, ...rest] = text.split('\\n');
|
|
120
|
+
return {
|
|
121
|
+
firstPart: first.replace(/\\s/g, ' '),
|
|
122
|
+
secondPart: rest.join('\\n').replace(/\\s/g, ' '),
|
|
123
|
+
isNewLine: true
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Check if text contains explicit \s sequences
|
|
128
|
+
if (text.includes('\\s')) {
|
|
129
|
+
// Handle explicit spaces - split by \s and treat as two parts
|
|
130
|
+
const parts = text.split('\\s');
|
|
131
|
+
if (parts.length >= 2) {
|
|
132
|
+
return {
|
|
133
|
+
firstPart: parts[0],
|
|
134
|
+
secondPart: parts.slice(1).join(' '), // Join remaining parts with spaces
|
|
135
|
+
isNewLine: false
|
|
136
|
+
};
|
|
137
|
+
} else {
|
|
138
|
+
return { firstPart: parts[0], secondPart: '', isNewLine: false };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Regular word splitting (no explicit \s)
|
|
143
|
+
const nameParts = text.trim().split(/\s+/);
|
|
144
|
+
|
|
145
|
+
if (nameParts.length === 1) {
|
|
146
|
+
return { firstPart: nameParts[0], secondPart: '', isNewLine: false };
|
|
147
|
+
} else if (nameParts.length === 2) {
|
|
148
|
+
return { firstPart: nameParts[0], secondPart: nameParts[1], isNewLine: false };
|
|
149
|
+
} else {
|
|
150
|
+
// More than 2 words: everything except last word goes to first part
|
|
151
|
+
return {
|
|
152
|
+
firstPart: nameParts.slice(0, -1).join(' '),
|
|
153
|
+
secondPart: nameParts[nameParts.length - 1],
|
|
154
|
+
isNewLine: false
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}, []);
|
|
158
|
+
|
|
159
|
+
const { firstPart, secondPart, isNewLine } = parseNameParts(name);
|
|
160
|
+
|
|
161
|
+
// Check if original name contained explicit spaces
|
|
162
|
+
const hasExplicitSpaces = name.includes('\\s');
|
|
163
|
+
|
|
164
|
+
// Determine size class, font size, and component height (accounting for line breaks)
|
|
165
|
+
const sizeClass = `logo-${size}`;
|
|
166
|
+
const getSizeConfig = (size: LogoSize, hasLineBreak: boolean) => {
|
|
167
|
+
const baseConfig = {
|
|
168
|
+
'tiny': { fontSize: 16, height: 32 },
|
|
169
|
+
'small': { fontSize: 20, height: 40 },
|
|
170
|
+
'medium': { fontSize: 28, height: 50 },
|
|
171
|
+
'large': { fontSize: 36, height: 64 },
|
|
172
|
+
'extra-large': { fontSize: 48, height: 84 }
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const config = baseConfig[size] || baseConfig.medium;
|
|
176
|
+
|
|
177
|
+
// Add extra height for line breaks (approximately 1.4x the font size for proper spacing)
|
|
178
|
+
if (hasLineBreak) {
|
|
179
|
+
config.height += Math.round(config.fontSize * 1.4);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return config;
|
|
183
|
+
};
|
|
184
|
+
const { fontSize, height } = getSizeConfig(size, isNewLine);
|
|
185
|
+
|
|
186
|
+
// Calculate badge position based on semantic positioning system
|
|
187
|
+
const calculateBadgePosition = useCallback((textBBox: DOMRect, svgWidth: number, svgHeight: number) => {
|
|
188
|
+
// Scale factor based on font size (medium/28px is the baseline)
|
|
189
|
+
const scale = fontSize / 28; // 28 is the medium/default font size
|
|
190
|
+
const scaledOffset = 8 * scale;
|
|
191
|
+
|
|
192
|
+
// Scale custom offset based on size
|
|
193
|
+
const scaledOffsetX = (badgeOffset?.x ?? 0) * scale;
|
|
194
|
+
const scaledOffsetY = (badgeOffset?.y ?? 0) * scale;
|
|
195
|
+
|
|
196
|
+
// Calculate position based on semantic positioning
|
|
197
|
+
let x: number, y: number;
|
|
198
|
+
|
|
199
|
+
switch (badge) {
|
|
200
|
+
case 'top-left':
|
|
201
|
+
x = textBBox.x - scaledOffset;
|
|
202
|
+
y = textBBox.y + scaledOffset;
|
|
203
|
+
break;
|
|
204
|
+
case 'top-center':
|
|
205
|
+
x = textBBox.x + textBBox.width / 2;
|
|
206
|
+
y = textBBox.y + scaledOffset;
|
|
207
|
+
break;
|
|
208
|
+
case 'top-right':
|
|
209
|
+
x = textBBox.x + textBBox.width + scaledOffset;
|
|
210
|
+
y = textBBox.y + scaledOffset;
|
|
211
|
+
break;
|
|
212
|
+
case 'center-left':
|
|
213
|
+
x = textBBox.x - scaledOffset;
|
|
214
|
+
y = textBBox.y + textBBox.height / 2;
|
|
215
|
+
break;
|
|
216
|
+
case 'center':
|
|
217
|
+
x = textBBox.x + textBBox.width / 2;
|
|
218
|
+
y = textBBox.y + textBBox.height / 2;
|
|
219
|
+
break;
|
|
220
|
+
case 'center-right':
|
|
221
|
+
x = textBBox.x + textBBox.width + scaledOffset;
|
|
222
|
+
y = textBBox.y + textBBox.height / 2;
|
|
223
|
+
break;
|
|
224
|
+
case 'bottom-left':
|
|
225
|
+
x = textBBox.x - scaledOffset;
|
|
226
|
+
y = textBBox.y + textBBox.height - scaledOffset;
|
|
227
|
+
break;
|
|
228
|
+
case 'bottom-center':
|
|
229
|
+
x = textBBox.x + textBBox.width / 2;
|
|
230
|
+
y = textBBox.y + textBBox.height - scaledOffset;
|
|
231
|
+
break;
|
|
232
|
+
case 'bottom-right':
|
|
233
|
+
x = textBBox.x + textBBox.width + scaledOffset;
|
|
234
|
+
y = textBBox.y + textBBox.height - scaledOffset;
|
|
235
|
+
break;
|
|
236
|
+
default:
|
|
237
|
+
// Default: top-right of text
|
|
238
|
+
x = textBBox.x + textBBox.width + scaledOffset;
|
|
239
|
+
y = textBBox.y + scaledOffset;
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
x: x + scaledOffsetX,
|
|
245
|
+
y: y + scaledOffsetY
|
|
246
|
+
};
|
|
247
|
+
}, [badge, badgeOffset, fontSize]);
|
|
248
|
+
|
|
249
|
+
// Calculate badge position and SVG width based on text width
|
|
250
|
+
useEffect(() => {
|
|
251
|
+
if (textRef.current) {
|
|
252
|
+
const textBBox = textRef.current.getBBox();
|
|
253
|
+
// Calculate badge position using semantic positioning
|
|
254
|
+
const badgePos = calculateBadgePosition(textBBox, svgWidth, height);
|
|
255
|
+
// Ensure SVG is wide enough to accommodate text and badge
|
|
256
|
+
const requiredWidth = Math.max(180, textBBox.x + textBBox.width + 20);
|
|
257
|
+
|
|
258
|
+
setCalculatedBadgePosition(badgePos);
|
|
259
|
+
setSvgWidth(requiredWidth);
|
|
260
|
+
}
|
|
261
|
+
}, [name, badge, badgeOffset, calculateBadgePosition, fontSize, height, parseNameParts]);
|
|
262
|
+
|
|
263
|
+
// Determine CSS class for variant
|
|
264
|
+
let variantClass = '';
|
|
265
|
+
if (variant === 'high-contrast' || variant === 'monochrome' || variant === 'on-primary') {
|
|
266
|
+
variantClass = `logo-${variant}`;
|
|
267
|
+
} else if (variant !== 'default') {
|
|
268
|
+
variantClass = `logo-${variant}`;
|
|
269
|
+
} else {
|
|
270
|
+
variantClass = 'logo-default';
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Create aria-label from the logo name
|
|
274
|
+
const ariaLabel = `${name} Logo`;
|
|
275
|
+
|
|
276
|
+
// Render badge shape
|
|
277
|
+
const renderBadgeShape = (): React.ReactNode => {
|
|
278
|
+
if (badge === 'none') return null;
|
|
279
|
+
|
|
280
|
+
const baseProps = {
|
|
281
|
+
className: `logo-badge logo-badge-${badgeShape}`,
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
// Use the calculated position (which includes custom position logic)
|
|
285
|
+
const { x, y } = calculatedBadgePosition;
|
|
286
|
+
|
|
287
|
+
// Scale badge size based on font size
|
|
288
|
+
const scale = fontSize / 28; // 28 is the medium/default font size
|
|
289
|
+
const badgeRadius = 5 * scale;
|
|
290
|
+
const badgeSize = 10 * scale;
|
|
291
|
+
|
|
292
|
+
switch (badgeShape) {
|
|
293
|
+
case 'circle':
|
|
294
|
+
return (
|
|
295
|
+
<circle cx={x} cy={y} r={badgeRadius} {...baseProps}>
|
|
296
|
+
<animate attributeName="r" values={`${badgeRadius};${badgeRadius + 1};${badgeRadius}`} dur="1.5s" repeatCount="indefinite" />
|
|
297
|
+
</circle>
|
|
298
|
+
);
|
|
299
|
+
case 'star':
|
|
300
|
+
const starScale = scale;
|
|
301
|
+
return (
|
|
302
|
+
<polygon
|
|
303
|
+
points={`${x},${y-5*starScale} ${x+2*starScale},${y} ${x+7*starScale},${y} ${x+3*starScale},${y+3*starScale} ${x+5*starScale},${y+8*starScale} ${x},${y+5*starScale} ${x-5*starScale},${y+8*starScale} ${x-3*starScale},${y+3*starScale} ${x-7*starScale},${y} ${x-2*starScale},${y}`}
|
|
304
|
+
{...baseProps}
|
|
305
|
+
>
|
|
306
|
+
<animate attributeName="opacity" values="0.8;1;0.8" dur="1.5s" repeatCount="indefinite" />
|
|
307
|
+
</polygon>
|
|
308
|
+
);
|
|
309
|
+
case 'square':
|
|
310
|
+
return (
|
|
311
|
+
<rect x={x-badgeRadius} y={y-badgeRadius} width={badgeSize} height={badgeSize} {...baseProps}>
|
|
312
|
+
<animate attributeName="opacity" values="0.8;1;0.8" dur="1.5s" repeatCount="indefinite" />
|
|
313
|
+
</rect>
|
|
314
|
+
);
|
|
315
|
+
case 'heart':
|
|
316
|
+
const heartScale = scale;
|
|
317
|
+
return (
|
|
318
|
+
<path
|
|
319
|
+
d={`M${x},${y+6*heartScale} C${x},${y+6*heartScale} ${x-7*heartScale},${y} ${x-7*heartScale},${y-4*heartScale} C${x-7*heartScale},${y-6*heartScale} ${x-5*heartScale},${y-8*heartScale} ${x-3*heartScale},${y-8*heartScale} C${x-2*heartScale},${y-8*heartScale} ${x},${y-7*heartScale} ${x},${y-5*heartScale} C${x},${y-7*heartScale} ${x+2*heartScale},${y-8*heartScale} ${x+3*heartScale},${y-8*heartScale} C${x+5*heartScale},${y-8*heartScale} ${x+7*heartScale},${y-6*heartScale} ${x+7*heartScale},${y-4*heartScale} C${x+7*heartScale},${y} ${x},${y+6*heartScale} ${x},${y+6*heartScale} Z`}
|
|
320
|
+
{...baseProps}
|
|
321
|
+
>
|
|
322
|
+
<animate attributeName="fill-opacity" values="0.7;1;0.7" dur="1.5s" repeatCount="indefinite" />
|
|
323
|
+
</path>
|
|
324
|
+
);
|
|
325
|
+
default:
|
|
326
|
+
return (
|
|
327
|
+
<circle cx={x} cy={y} r={badgeRadius} {...baseProps}>
|
|
328
|
+
<animate attributeName="r" values={`${badgeRadius};${badgeRadius + 1};${badgeRadius}`} dur="1.5s" repeatCount="indefinite" />
|
|
329
|
+
</circle>
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
return (
|
|
335
|
+
<svg
|
|
336
|
+
width={svgWidth}
|
|
337
|
+
height={height}
|
|
338
|
+
viewBox={`0 0 ${svgWidth} ${height}`}
|
|
339
|
+
fill="none"
|
|
340
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
341
|
+
{...htmlProps}
|
|
342
|
+
{...styleProps}
|
|
343
|
+
className={`logo dynamic-logo ${sizeClass} ${variantClass} ${styleProps.className || ''}`.trim()}
|
|
344
|
+
style={{
|
|
345
|
+
height: `${height}px`,
|
|
346
|
+
cursor: htmlProps.onClick ? 'pointer' : 'default',
|
|
347
|
+
...styleProps.style
|
|
348
|
+
}}
|
|
349
|
+
role="img"
|
|
350
|
+
aria-label={ariaLabel}
|
|
351
|
+
{...svgProps}
|
|
352
|
+
>
|
|
353
|
+
<text ref={textRef} fontFamily={fontFamily} fontSize={fontSize} fontWeight={fontWeight}>
|
|
354
|
+
<tspan x="15" y={isNewLine ? height * 0.4 : height * 0.7} className={firstPartClass}>{firstPart}</tspan>
|
|
355
|
+
{secondPart && (
|
|
356
|
+
<tspan
|
|
357
|
+
x={isNewLine ? "15" : undefined}
|
|
358
|
+
dy={isNewLine ? fontSize * 1.2 : undefined}
|
|
359
|
+
className={secondPartClass}
|
|
360
|
+
>
|
|
361
|
+
{isNewLine ? secondPart : (hasExplicitSpaces ? ` ${secondPart}` : secondPart)}
|
|
362
|
+
</tspan>
|
|
363
|
+
)}
|
|
364
|
+
</text>
|
|
365
|
+
{renderBadgeShape()}
|
|
366
|
+
</svg>
|
|
367
|
+
);
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
export default Logo;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown Component - Transforms Markdown strings into Framework components
|
|
3
|
+
*
|
|
4
|
+
* Accepts Markdown string as children and converts it through a
|
|
5
|
+
* Markdown → HTML → React components pipeline using the Html component
|
|
6
|
+
* with Markdown-optimized transformation rules.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Full Markdown syntax support via marked library
|
|
10
|
+
* - Transform rules optimized for Markdown content
|
|
11
|
+
* - Code block syntax highlighting
|
|
12
|
+
* - Preserves inline code elements (no transformation)
|
|
13
|
+
* - TypeScript support with proper props interface
|
|
14
|
+
* - Error handling and fallback to Html component
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* - Basic: <Markdown>{markdownString}</Markdown>
|
|
18
|
+
* - Custom config: <Markdown htmlTransformConfig={customConfig}>{markdownString}</Markdown>
|
|
19
|
+
*
|
|
20
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { Box } from '@mui/material';
|
|
24
|
+
import { marked } from 'marked';
|
|
25
|
+
import React from 'react';
|
|
26
|
+
import { QWICKAPP_COMPONENT, useBaseProps, WithBaseProps } from '../hooks';
|
|
27
|
+
import Html from './Html';
|
|
28
|
+
import SafeSpan from './SafeSpan';
|
|
29
|
+
import { TransformConfig, defaultMarkdownRules } from '../utils/htmlTransform';
|
|
30
|
+
|
|
31
|
+
export interface MarkdownProps extends WithBaseProps {
|
|
32
|
+
/** Markdown content as string */
|
|
33
|
+
children: string;
|
|
34
|
+
/** Custom transformation configuration for HTML conversion */
|
|
35
|
+
htmlTransformConfig?: TransformConfig;
|
|
36
|
+
/** Whether to sanitize HTML output (default: true) */
|
|
37
|
+
sanitize?: boolean;
|
|
38
|
+
/** Custom sanitization options */
|
|
39
|
+
sanitizeOptions?: any;
|
|
40
|
+
/** Fallback content when Markdown is empty */
|
|
41
|
+
placeholder?: string;
|
|
42
|
+
/** Container element type */
|
|
43
|
+
component?: React.ElementType;
|
|
44
|
+
/** Marked options for Markdown parsing */
|
|
45
|
+
markedOptions?: marked.MarkedOptions;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Configure marked with security and GitHub Flavored Markdown support
|
|
50
|
+
*/
|
|
51
|
+
const getMarkedOptions = (customOptions?: marked.MarkedOptions): marked.MarkedOptions => ({
|
|
52
|
+
// GitHub Flavored Markdown
|
|
53
|
+
gfm: true,
|
|
54
|
+
// Convert line breaks to <br> tags
|
|
55
|
+
breaks: false,
|
|
56
|
+
// Pedantic compliance to original markdown.pl
|
|
57
|
+
pedantic: false,
|
|
58
|
+
// Sanitize HTML (we handle this in Html component)
|
|
59
|
+
sanitize: false,
|
|
60
|
+
// Smart punctuation
|
|
61
|
+
smartypants: false,
|
|
62
|
+
// Custom renderer options
|
|
63
|
+
renderer: new marked.Renderer(),
|
|
64
|
+
// Override with user options
|
|
65
|
+
...customOptions
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Markdown component - converts Markdown to React components via Html
|
|
70
|
+
*/
|
|
71
|
+
export function Markdown({
|
|
72
|
+
children = '',
|
|
73
|
+
htmlTransformConfig,
|
|
74
|
+
sanitize = true,
|
|
75
|
+
sanitizeOptions,
|
|
76
|
+
placeholder,
|
|
77
|
+
component = 'div',
|
|
78
|
+
markedOptions,
|
|
79
|
+
...restProps
|
|
80
|
+
}: MarkdownProps) {
|
|
81
|
+
const { styleProps, htmlProps, restProps: otherProps } = useBaseProps(restProps);
|
|
82
|
+
|
|
83
|
+
// Mark as QwickApp component
|
|
84
|
+
(Markdown as any)[QWICKAPP_COMPONENT] = true;
|
|
85
|
+
|
|
86
|
+
// Return placeholder if no Markdown content
|
|
87
|
+
if (!children || !children.trim()) {
|
|
88
|
+
if (placeholder) {
|
|
89
|
+
return (
|
|
90
|
+
<Box
|
|
91
|
+
component={component}
|
|
92
|
+
{...htmlProps}
|
|
93
|
+
{...styleProps}
|
|
94
|
+
{...otherProps}
|
|
95
|
+
sx={{
|
|
96
|
+
opacity: 0.6,
|
|
97
|
+
fontStyle: 'italic',
|
|
98
|
+
...styleProps.sx
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
{placeholder}
|
|
102
|
+
</Box>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
// Configure marked
|
|
110
|
+
const options = getMarkedOptions(markedOptions);
|
|
111
|
+
|
|
112
|
+
// Convert Markdown to HTML
|
|
113
|
+
const htmlContent = marked(children, options);
|
|
114
|
+
|
|
115
|
+
// Use provided transform config or default markdown rules
|
|
116
|
+
const transformConfig: TransformConfig = htmlTransformConfig || {
|
|
117
|
+
rules: defaultMarkdownRules,
|
|
118
|
+
sanitize,
|
|
119
|
+
sanitizeOptions
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Pass HTML to Html component for transformation
|
|
123
|
+
return (
|
|
124
|
+
<Html
|
|
125
|
+
transformConfig={transformConfig}
|
|
126
|
+
sanitize={sanitize}
|
|
127
|
+
sanitizeOptions={sanitizeOptions}
|
|
128
|
+
component={component}
|
|
129
|
+
{...htmlProps}
|
|
130
|
+
{...styleProps}
|
|
131
|
+
{...otherProps}
|
|
132
|
+
>
|
|
133
|
+
{htmlContent}
|
|
134
|
+
</Html>
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error('Error processing Markdown content:', error);
|
|
139
|
+
|
|
140
|
+
// Fallback handling
|
|
141
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
142
|
+
return (
|
|
143
|
+
<Box
|
|
144
|
+
component={component}
|
|
145
|
+
{...htmlProps}
|
|
146
|
+
{...styleProps}
|
|
147
|
+
{...otherProps}
|
|
148
|
+
sx={{
|
|
149
|
+
p: 2,
|
|
150
|
+
border: '1px solid orange',
|
|
151
|
+
borderRadius: 1,
|
|
152
|
+
backgroundColor: 'rgba(255, 165, 0, 0.1)',
|
|
153
|
+
...styleProps.sx
|
|
154
|
+
}}
|
|
155
|
+
>
|
|
156
|
+
<strong>Markdown Processing Error:</strong> {error instanceof Error ? error.message : 'Unknown error'}
|
|
157
|
+
<SafeSpan html={children} placeholder="Failed to process Markdown" />
|
|
158
|
+
</Box>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Production fallback - try to use Html component with raw content
|
|
163
|
+
try {
|
|
164
|
+
return (
|
|
165
|
+
<Html
|
|
166
|
+
sanitize={sanitize}
|
|
167
|
+
sanitizeOptions={sanitizeOptions}
|
|
168
|
+
component={component}
|
|
169
|
+
{...htmlProps}
|
|
170
|
+
{...styleProps}
|
|
171
|
+
{...otherProps}
|
|
172
|
+
>
|
|
173
|
+
{children}
|
|
174
|
+
</Html>
|
|
175
|
+
);
|
|
176
|
+
} catch (htmlError) {
|
|
177
|
+
// Last resort fallback
|
|
178
|
+
return (
|
|
179
|
+
<SafeSpan
|
|
180
|
+
html={children}
|
|
181
|
+
placeholder={placeholder || "Content unavailable"}
|
|
182
|
+
{...htmlProps}
|
|
183
|
+
{...styleProps}
|
|
184
|
+
{...otherProps}
|
|
185
|
+
/>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export default Markdown;
|