@qwickapps/react-framework 1.3.4 → 1.4.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/README.md +1688 -2
- package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts +66 -0
- package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.d.ts +7 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/Html.d.ts +28 -18
- package/dist/components/Html.d.ts.map +1 -1
- package/dist/components/Logo.d.ts +12 -35
- package/dist/components/Logo.d.ts.map +1 -1
- package/dist/components/Markdown.d.ts +18 -13
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/QwickApp.d.ts +16 -3
- package/dist/components/QwickApp.d.ts.map +1 -1
- package/dist/components/QwickIcon.d.ts +23 -0
- package/dist/components/QwickIcon.d.ts.map +1 -0
- package/dist/components/SafeSpan.d.ts +12 -5
- package/dist/components/SafeSpan.d.ts.map +1 -1
- package/dist/components/Scaffold.d.ts.map +1 -1
- package/dist/components/base/ModelView.d.ts +101 -0
- package/dist/components/base/ModelView.d.ts.map +1 -0
- package/dist/components/base/index.d.ts +11 -0
- package/dist/components/base/index.d.ts.map +1 -0
- package/dist/components/blocks/Article.d.ts +12 -2
- package/dist/components/blocks/Article.d.ts.map +1 -1
- package/dist/components/blocks/Code.d.ts +13 -2
- package/dist/components/blocks/Code.d.ts.map +1 -1
- package/dist/components/blocks/Content.d.ts.map +1 -1
- package/dist/components/blocks/CoverImageHeader.d.ts.map +1 -1
- package/dist/components/blocks/FeatureCard.d.ts.map +1 -1
- package/dist/components/blocks/FeatureGrid.d.ts.map +1 -1
- package/dist/components/blocks/Footer.d.ts.map +1 -1
- package/dist/components/blocks/HeroBlock.d.ts +27 -13
- package/dist/components/blocks/HeroBlock.d.ts.map +1 -1
- package/dist/components/blocks/Image.d.ts +41 -0
- package/dist/components/blocks/Image.d.ts.map +1 -0
- package/dist/components/blocks/PageBannerHeader.d.ts.map +1 -1
- package/dist/components/blocks/ProductCard.d.ts.map +1 -1
- package/dist/components/blocks/Section.d.ts +16 -2
- package/dist/components/blocks/Section.d.ts.map +1 -1
- package/dist/components/blocks/Text.d.ts +41 -0
- package/dist/components/blocks/Text.d.ts.map +1 -0
- package/dist/components/blocks/index.d.ts +4 -0
- package/dist/components/blocks/index.d.ts.map +1 -1
- package/dist/components/buttons/Button.d.ts +23 -7
- package/dist/components/buttons/Button.d.ts.map +1 -1
- package/dist/components/forms/FormBlock.d.ts +19 -13
- package/dist/components/forms/FormBlock.d.ts.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/input/ChoiceInputField.d.ts +17 -11
- package/dist/components/input/ChoiceInputField.d.ts.map +1 -1
- package/dist/components/input/HtmlInputField.d.ts +17 -11
- package/dist/components/input/HtmlInputField.d.ts.map +1 -1
- package/dist/components/input/SelectInputField.d.ts +16 -10
- package/dist/components/input/SelectInputField.d.ts.map +1 -1
- package/dist/components/input/SwitchInputField.d.ts +16 -10
- package/dist/components/input/SwitchInputField.d.ts.map +1 -1
- package/dist/components/input/TextField.d.ts.map +1 -1
- package/dist/components/input/TextInputField.d.ts +16 -11
- package/dist/components/input/TextInputField.d.ts.map +1 -1
- package/dist/components/layout/GridCell.d.ts +23 -6
- package/dist/components/layout/GridCell.d.ts.map +1 -1
- package/dist/components/layout/GridLayout.d.ts +24 -23
- package/dist/components/layout/GridLayout.d.ts.map +1 -1
- package/dist/components/pages/FormPage.d.ts.map +1 -1
- package/dist/components/pages/Page.d.ts +49 -87
- package/dist/components/pages/Page.d.ts.map +1 -1
- package/dist/components/pages/index.d.ts +2 -2
- package/dist/components/pages/index.d.ts.map +1 -1
- package/dist/config/AppConfig.d.ts +49 -0
- package/dist/config/AppConfig.d.ts.map +1 -0
- package/dist/config/AppConfigBuilder.d.ts +75 -0
- package/dist/config/AppConfigBuilder.d.ts.map +1 -0
- package/dist/config/index.d.ts +13 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/types.d.ts +130 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.esm.js +451 -0
- package/dist/config.js +455 -0
- package/dist/contexts/PrintModeContext.d.ts +27 -0
- package/dist/contexts/PrintModeContext.d.ts.map +1 -0
- package/dist/contexts/QwickAppContext.d.ts +2 -2
- package/dist/contexts/QwickAppContext.d.ts.map +1 -1
- package/dist/contexts/ThemeContext.d.ts.map +1 -1
- package/dist/contexts/index.d.ts +2 -0
- package/dist/contexts/index.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/usePrintMode.d.ts +39 -0
- package/dist/hooks/usePrintMode.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +20722 -16021
- package/dist/index.js +20725 -16010
- package/dist/schemas/CodeSchema.d.ts +2 -1
- package/dist/schemas/CodeSchema.d.ts.map +1 -1
- package/dist/schemas/CollapsibleLayoutSchema.d.ts +2 -1
- package/dist/schemas/CollapsibleLayoutSchema.d.ts.map +1 -1
- package/dist/schemas/ContentSchema.d.ts +2 -1
- package/dist/schemas/ContentSchema.d.ts.map +1 -1
- package/dist/schemas/GridCellSchema.d.ts +25 -0
- package/dist/schemas/GridCellSchema.d.ts.map +1 -0
- package/dist/schemas/GridLayoutSchema.d.ts +23 -0
- package/dist/schemas/GridLayoutSchema.d.ts.map +1 -0
- package/dist/schemas/HtmlSchema.d.ts +14 -0
- package/dist/schemas/HtmlSchema.d.ts.map +1 -0
- package/dist/schemas/ImageSchema.d.ts +32 -0
- package/dist/schemas/ImageSchema.d.ts.map +1 -0
- package/dist/schemas/LogoSchema.d.ts +35 -0
- package/dist/schemas/LogoSchema.d.ts.map +1 -0
- package/dist/schemas/MarkdownSchema.d.ts +14 -0
- package/dist/schemas/MarkdownSchema.d.ts.map +1 -0
- package/dist/schemas/PageTemplateSchema.d.ts +31 -0
- package/dist/schemas/PageTemplateSchema.d.ts.map +1 -0
- package/dist/schemas/PrintConfigSchema.d.ts +31 -0
- package/dist/schemas/PrintConfigSchema.d.ts.map +1 -0
- package/dist/schemas/SectionSchema.d.ts +2 -1
- package/dist/schemas/SectionSchema.d.ts.map +1 -1
- package/dist/schemas/TextSchema.d.ts +37 -0
- package/dist/schemas/TextSchema.d.ts.map +1 -0
- package/dist/schemas/ViewModelSchema.d.ts +23 -0
- package/dist/schemas/ViewModelSchema.d.ts.map +1 -0
- package/dist/schemas/index.d.ts +15 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/transformers/ComponentTransformer.d.ts +116 -0
- package/dist/schemas/transformers/ComponentTransformer.d.ts.map +1 -0
- package/dist/schemas/transformers/ReactNodeTransformer.d.ts +53 -0
- package/dist/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -0
- package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts +66 -0
- package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts.map +1 -0
- package/dist/schemas/transformers/registry.d.ts +15 -0
- package/dist/schemas/transformers/registry.d.ts.map +1 -0
- package/dist/schemas/types/Serializable.d.ts +46 -0
- package/dist/schemas/types/Serializable.d.ts.map +1 -0
- package/dist/utils/htmlTransform.d.ts.map +1 -1
- package/dist/utils/reactUtils.d.ts +12 -3
- package/dist/utils/reactUtils.d.ts.map +1 -1
- package/package.json +17 -3
- package/src/{components/__tests__ → __tests__/components}/AccessibilityProvider.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Article.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Breadcrumbs.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Button.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/CardListGrid.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/ChoiceInputField.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Code.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Content.integration.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Content.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/CoverImageHeader.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/ErrorBoundary.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/FeatureCard.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/FeatureGrid.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/FeatureGrid.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/Footer.test.tsx +4 -4
- package/src/{components/__tests__ → __tests__/components}/FormBlock.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/HeroBlock.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/HeroBlock.test.tsx +233 -7
- package/src/{components/__tests__ → __tests__/components}/Html.test.tsx +11 -2
- package/src/{components/__tests__ → __tests__/components}/HtmlInputField.test.tsx +3 -3
- package/src/__tests__/components/Logo.test.js +3 -3
- package/src/{components/__tests__ → __tests__/components}/Markdown.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/PageBannerHeader.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/PaletteSwitcher.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/ProductCard.test.tsx +4 -4
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.simple.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Section.integration.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Section.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/SelectInputField.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/TextInputField.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/ThemeSwitcher.test.tsx +3 -3
- package/src/__tests__/components/base/ModelView.test.tsx +220 -0
- package/src/__tests__/components/blocks/Code.performance.test.tsx +625 -0
- package/src/__tests__/components/blocks/Code.serialization.test.tsx +507 -0
- package/src/__tests__/components/blocks/HeroBlock.serialization.test.tsx +414 -0
- package/src/__tests__/components/blocks/Image.serialization.test.tsx +257 -0
- package/src/__tests__/components/blocks/Section.serialization.test.tsx +553 -0
- package/src/__tests__/components/blocks/Text.performance.test.tsx +442 -0
- package/src/__tests__/components/blocks/Text.serialization.test.tsx +491 -0
- package/src/__tests__/components/buttons/Button.serialization.test.tsx +443 -0
- package/src/__tests__/components/input/FormComponents.serialization.test.tsx +482 -0
- package/src/__tests__/components/input/SelectInputField.serialization.test.tsx +439 -0
- package/src/__tests__/components/input/TextInputField.serialization.test.tsx +359 -0
- package/src/{components/layout/CollapsibleLayout/__tests__ → __tests__/components/layout}/CollapsibleLayout.test.tsx +4 -4
- package/src/__tests__/components/layout/GridCell.serialization.test.tsx +403 -0
- package/src/__tests__/components/layout/GridLayout.serialization.test.tsx +311 -0
- package/src/__tests__/hooks/usePrintMode.test.ts +89 -0
- package/src/__tests__/schemas/PageTemplateSchema.test.ts +161 -0
- package/src/__tests__/schemas/PrintConfigSchema.test.ts +127 -0
- package/src/__tests__/schemas/ViewModelSchema.test.ts +80 -0
- package/src/__tests__/schemas/transformers/ComponentSerializationPatterns.test.tsx +602 -0
- package/src/__tests__/schemas/transformers/ComponentTransformer.htmlPatterns.test.ts +301 -0
- package/src/__tests__/schemas/transformers/ComponentTransformer.test.ts +521 -0
- package/src/__tests__/schemas/transformers/CrossBrowserCompatibility.test.ts +586 -0
- package/src/__tests__/schemas/transformers/MockSerializableComponent.ts +103 -0
- package/src/__tests__/schemas/transformers/RealWorldScenarios.test.tsx +1165 -0
- package/src/__tests__/schemas/transformers/SerializationErrorHandling.test.ts +602 -0
- package/src/__tests__/schemas/transformers/SerializationIntegration.test.tsx +691 -0
- package/src/__tests__/schemas/transformers/SerializationPerformance.test.ts +460 -0
- package/src/__tests__/schemas/transformers/TestAutomation.test.ts +597 -0
- package/src/{utils/__tests__ → __tests__/utils}/nested-dom-fix.test.tsx +1 -1
- package/src/components/ErrorBoundary.tsx +8 -8
- package/src/components/Html.tsx +147 -44
- package/src/components/Logo.tsx +198 -100
- package/src/components/Markdown.tsx +125 -16
- package/src/components/QwickApp.tsx +64 -31
- package/src/components/QwickIcon.tsx +59 -0
- package/src/components/SafeSpan.tsx +65 -10
- package/src/components/Scaffold.tsx +2 -8
- package/src/components/base/ModelView.tsx +199 -0
- package/src/components/base/index.ts +11 -0
- package/src/components/blocks/Article.tsx +57 -18
- package/src/components/blocks/Code.md +529 -0
- package/src/components/blocks/Code.tsx +102 -15
- package/src/components/blocks/Content.tsx +25 -77
- package/src/components/blocks/CoverImageHeader.tsx +9 -4
- package/src/components/blocks/FeatureCard.tsx +1 -2
- package/src/components/blocks/FeatureGrid.tsx +19 -1
- package/src/components/blocks/Footer.tsx +13 -1
- package/src/components/blocks/HeroBlock.tsx +87 -20
- package/src/components/blocks/Image.tsx +395 -0
- package/src/components/blocks/PageBannerHeader.tsx +14 -12
- package/src/components/blocks/ProductCard.tsx +51 -52
- package/src/components/blocks/Section.tsx +113 -8
- package/src/components/blocks/Text.tsx +285 -0
- package/src/components/blocks/index.ts +4 -0
- package/src/components/buttons/Button.tsx +184 -15
- package/src/components/forms/FormBlock.tsx +70 -17
- package/src/components/index.ts +5 -0
- package/src/components/input/ChoiceInputField.tsx +48 -18
- package/src/components/input/HtmlInputField.tsx +48 -18
- package/src/components/input/SelectInputField.tsx +48 -16
- package/src/components/input/SwitchInputField.tsx +48 -17
- package/src/components/input/TextField.tsx +41 -1
- package/src/components/input/TextInputField.tsx +52 -18
- package/src/components/layout/GridCell.tsx +118 -9
- package/src/components/layout/GridLayout.tsx +125 -24
- package/src/components/pages/FormPage.tsx +0 -1
- package/src/components/pages/Page.css +304 -332
- package/src/components/pages/Page.tsx +307 -255
- package/src/components/pages/index.ts +2 -2
- package/src/config/AppConfig.ts +133 -0
- package/src/config/AppConfigBuilder.ts +421 -0
- package/src/config/__tests__/AppConfig.test.ts +385 -0
- package/src/config/__tests__/AppConfigBuilder.test.ts +432 -0
- package/src/config/index.ts +24 -0
- package/src/config/types.ts +170 -0
- package/src/config.ts +25 -0
- package/src/contexts/PrintModeContext.tsx +332 -0
- package/src/contexts/QwickAppContext.tsx +2 -2
- package/src/contexts/ThemeContext.tsx +1 -2
- package/src/contexts/index.ts +2 -0
- package/src/hooks/index.ts +5 -1
- package/src/hooks/usePrintMode.ts +73 -0
- package/src/index.ts +3 -0
- package/src/schemas/CodeSchema.ts +3 -3
- package/src/schemas/CollapsibleLayoutSchema.ts +2 -1
- package/src/schemas/ContentSchema.ts +2 -1
- package/src/schemas/GridCellSchema.ts +164 -0
- package/src/schemas/GridLayoutSchema.ts +133 -0
- package/src/schemas/HtmlSchema.ts +47 -0
- package/src/schemas/ImageSchema.ts +235 -0
- package/src/schemas/LogoSchema.ts +241 -0
- package/src/schemas/MarkdownSchema.ts +47 -0
- package/src/schemas/PageTemplateSchema.ts +186 -0
- package/src/schemas/PrintConfigSchema.ts +207 -0
- package/src/schemas/README.md +661 -0
- package/src/schemas/SectionSchema.ts +2 -1
- package/src/schemas/TextSchema.ts +329 -0
- package/src/schemas/ViewModelSchema.ts +115 -0
- package/src/schemas/index.ts +21 -2
- package/src/schemas/transformers/ComponentTransformer.ts +403 -0
- package/src/schemas/transformers/ReactNodeTransformer.ts +236 -0
- package/src/schemas/transformers/registry.ts +72 -0
- package/src/schemas/types/Serializable.ts +51 -0
- package/src/stories/AccessibilityProvider.stories.tsx +253 -253
- package/src/stories/Article.stories.tsx +433 -433
- package/src/stories/Button.stories.tsx +1 -1
- package/src/stories/CardListGrid.stories.tsx +451 -451
- package/src/stories/ChoiceInputField.stories.tsx +503 -503
- package/src/stories/Code.stories.tsx +1 -1
- package/src/stories/CollapsibleLayout.stories.tsx +1414 -1414
- package/src/stories/Content.stories.tsx +393 -393
- package/src/stories/CoverImageHeader.stories.tsx +701 -701
- package/src/stories/DataBinding.advanced.stories.tsx +432 -432
- package/src/stories/DataProvider.stories.tsx +1192 -1192
- package/src/stories/FeatureCard.stories.tsx +557 -557
- package/src/stories/FeatureGrid.stories.tsx +594 -594
- package/src/stories/Footer.stories.tsx +640 -640
- package/src/stories/FormBlock.stories.tsx +760 -760
- package/src/stories/FormComponents.stories.tsx +349 -541
- package/src/stories/GridCell.stories.tsx +417 -0
- package/src/stories/GridLayout.stories.tsx +353 -0
- package/src/stories/HeroBlock.stories.tsx +862 -373
- package/src/stories/HtmlInputField.stories.tsx +474 -474
- package/src/stories/Image.stories.tsx +819 -0
- package/src/stories/Introduction.stories.tsx +667 -667
- package/src/stories/LayoutBlocks.stories.tsx +324 -324
- package/src/stories/Logo.stories.tsx +165 -6
- package/src/stories/Markdown.stories.tsx +137 -137
- package/src/stories/ModelView.stories.tsx +477 -0
- package/src/stories/Page.stories.tsx +688 -688
- package/src/stories/PageBannerHeader.stories.tsx +864 -864
- package/src/stories/PaletteSwitcher.stories.tsx +119 -119
- package/src/stories/ProductCard.stories.tsx +424 -424
- package/src/stories/QwickApp.stories.tsx +368 -368
- package/src/stories/ResponsiveMenu.stories.tsx +249 -249
- package/src/stories/SafeSpan.stories.tsx +531 -531
- package/src/stories/Section.stories.tsx +90 -2
- package/src/stories/SelectInputField.stories.tsx +524 -524
- package/src/stories/Text.stories.tsx +560 -0
- package/src/stories/TextInputField.stories.tsx +443 -443
- package/src/stories/ThemeSwitcher.stories.tsx +123 -123
- package/src/utils/htmlTransform.tsx +74 -53
- package/src/utils/reactUtils.tsx +57 -6
- package/dist/index.bundled.css +0 -12
- /package/src/{hooks/__tests__ → __tests__/hooks}/useDataBinding.test.tsx.disabled +0 -0
- /package/src/{schemas/__tests__ → __tests__/schemas}/builders.test.ts +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/createDataDrivenComponent.test.tsx.disabled +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/htmlTransform.test.tsx +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/optional-logging.test.ts +0 -0
package/src/components/Html.tsx
CHANGED
|
@@ -23,37 +23,37 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
import { Box } from '@mui/material';
|
|
26
|
-
import React from 'react';
|
|
27
|
-
import {
|
|
26
|
+
import React, { ReactElement } from 'react';
|
|
27
|
+
import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
|
|
28
|
+
import { QWICKAPP_COMPONENT, useBaseProps, useDataBinding } from '../hooks';
|
|
29
|
+
import { ComponentTransformer } from '../schemas/transformers/ComponentTransformer';
|
|
30
|
+
import HtmlModel from '../schemas/HtmlSchema';
|
|
31
|
+
import { ModelView } from './base/ModelView';
|
|
28
32
|
import SafeSpan from './SafeSpan';
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
/** Custom transformation configuration */
|
|
33
|
+
|
|
34
|
+
// Legacy types for backward compatibility (now unused internally but maintained for API)
|
|
35
|
+
export interface TransformConfig {
|
|
36
|
+
rules?: any[];
|
|
37
|
+
sanitize?: boolean;
|
|
38
|
+
sanitizeOptions?: any;
|
|
39
|
+
fallbackComponent?: (element: Element, key: string) => React.ReactNode;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type HtmlViewProps = ModelProps<HtmlModel> & {
|
|
43
|
+
/** Custom transformation configuration (legacy - now handled by ComponentTransformer) */
|
|
40
44
|
transformConfig?: TransformConfig;
|
|
41
|
-
/** Whether to
|
|
42
|
-
stripHeaders?: boolean;
|
|
43
|
-
/** Whether to sanitize HTML (default: true) */
|
|
45
|
+
/** Whether to sanitize HTML (legacy - now handled internally) */
|
|
44
46
|
sanitize?: boolean;
|
|
45
|
-
/** Custom sanitization options */
|
|
47
|
+
/** Custom sanitization options (legacy - now handled internally) */
|
|
46
48
|
sanitizeOptions?: any;
|
|
47
|
-
/**
|
|
48
|
-
placeholder?: string;
|
|
49
|
-
/** Container element type */
|
|
49
|
+
/** Container element type (React.ElementType for internal use, string in model for serialization) */
|
|
50
50
|
component?: React.ElementType;
|
|
51
|
-
}
|
|
51
|
+
};
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
export interface HtmlProps extends HtmlViewProps, WithDataBinding {}
|
|
54
|
+
|
|
55
|
+
// View component - handles the actual rendering
|
|
56
|
+
function HtmlView({
|
|
57
57
|
children = '',
|
|
58
58
|
transformConfig,
|
|
59
59
|
stripHeaders = false,
|
|
@@ -62,11 +62,11 @@ export function Html({
|
|
|
62
62
|
placeholder,
|
|
63
63
|
component = 'div',
|
|
64
64
|
...restProps
|
|
65
|
-
}:
|
|
65
|
+
}: HtmlViewProps) {
|
|
66
66
|
const { styleProps, htmlProps, restProps: otherProps } = useBaseProps(restProps);
|
|
67
67
|
|
|
68
68
|
// Mark as QwickApp component
|
|
69
|
-
(
|
|
69
|
+
(HtmlView as any)[QWICKAPP_COMPONENT] = true;
|
|
70
70
|
|
|
71
71
|
// Return placeholder if no HTML content
|
|
72
72
|
if (!children || !children.trim()) {
|
|
@@ -95,25 +95,16 @@ export function Html({
|
|
|
95
95
|
let processedHtml = children;
|
|
96
96
|
|
|
97
97
|
if (stripHeaders) {
|
|
98
|
-
|
|
98
|
+
// Simple header stripping - remove h1, h2, etc. tags
|
|
99
|
+
processedHtml = processedHtml.replace(/<h[1-6][^>]*>.*?<\/h[1-6]>/gi, '');
|
|
99
100
|
}
|
|
100
101
|
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
<SafeSpan
|
|
108
|
-
key={key}
|
|
109
|
-
html={element.outerHTML}
|
|
110
|
-
placeholder="Invalid HTML content"
|
|
111
|
-
/>
|
|
112
|
-
)
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
// Transform HTML to React components
|
|
116
|
-
const components = transformHtmlToReact(processedHtml, config);
|
|
102
|
+
// Note: transformConfig, sanitize, and sanitizeOptions are legacy props
|
|
103
|
+
// maintained for backward compatibility. The new ComponentTransformer system
|
|
104
|
+
// handles transformation through registered patterns automatically.
|
|
105
|
+
|
|
106
|
+
// Transform HTML to React components using ComponentTransformer
|
|
107
|
+
const components = ComponentTransformer.transformHTML(processedHtml);
|
|
117
108
|
|
|
118
109
|
// Return transformed components
|
|
119
110
|
return (
|
|
@@ -188,4 +179,116 @@ export function Html({
|
|
|
188
179
|
}
|
|
189
180
|
}
|
|
190
181
|
|
|
182
|
+
// Main component with data binding support and serialization capability
|
|
183
|
+
export class Html extends ModelView<HtmlProps, HtmlModel> {
|
|
184
|
+
// Component self-declaration for serialization
|
|
185
|
+
static readonly tagName = 'Html';
|
|
186
|
+
static readonly version = '1.0.0';
|
|
187
|
+
|
|
188
|
+
// Deserialization: JSON data → React element
|
|
189
|
+
static fromJson(jsonData: any): ReactElement {
|
|
190
|
+
return <Html {...jsonData} />;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Component-specific serialization properties
|
|
194
|
+
protected getComponentSpecificProps(): any {
|
|
195
|
+
return {
|
|
196
|
+
children: this.props.children,
|
|
197
|
+
stripHeaders: this.props.stripHeaders,
|
|
198
|
+
placeholder: this.props.placeholder
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Html component renders traditional props view
|
|
203
|
+
protected renderView(): React.ReactElement {
|
|
204
|
+
const { dataSource, bindingOptions, ...restProps } = this.props;
|
|
205
|
+
return <HtmlView {...restProps} />;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Html component renders data-bound view
|
|
209
|
+
protected renderWithDataBinding(): React.ReactElement {
|
|
210
|
+
return <HtmlWithDataBinding {...this.props} />;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Register HTML patterns that Html component can handle
|
|
214
|
+
static registerPatternHandlers(registry: any): void {
|
|
215
|
+
// Register div elements with specific classes for Html transformation
|
|
216
|
+
if (!registry.hasPattern('div.html-content')) {
|
|
217
|
+
registry.registerPattern('div.html-content', Html.transformHtmlDiv);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Register elements with data-html attribute
|
|
221
|
+
if (!registry.hasPattern('[data-html]')) {
|
|
222
|
+
registry.registerPattern('[data-html]', Html.transformDataHtml);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Transform div with html-content class to Html component
|
|
227
|
+
private static transformHtmlDiv(element: Element): any {
|
|
228
|
+
const stripHeaders = element.getAttribute('data-strip-headers') === 'true';
|
|
229
|
+
const placeholder = element.getAttribute('data-placeholder');
|
|
230
|
+
|
|
231
|
+
return {
|
|
232
|
+
tagName: 'Html',
|
|
233
|
+
props: {
|
|
234
|
+
children: element.innerHTML,
|
|
235
|
+
stripHeaders,
|
|
236
|
+
placeholder: placeholder || undefined
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Transform elements with data-html attribute to Html component
|
|
242
|
+
private static transformDataHtml(element: Element): any {
|
|
243
|
+
const htmlContent = element.getAttribute('data-html') || element.innerHTML;
|
|
244
|
+
const stripHeaders = element.getAttribute('data-strip-headers') === 'true';
|
|
245
|
+
const placeholder = element.getAttribute('data-placeholder');
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
tagName: 'Html',
|
|
249
|
+
props: {
|
|
250
|
+
children: htmlContent,
|
|
251
|
+
stripHeaders,
|
|
252
|
+
placeholder: placeholder || undefined
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Helper component to handle data binding with hooks (since we can't use hooks in class components)
|
|
259
|
+
function HtmlWithDataBinding(props: HtmlProps) {
|
|
260
|
+
const { dataSource, bindingOptions, ...restProps } = props;
|
|
261
|
+
|
|
262
|
+
// Use data binding
|
|
263
|
+
const { dataSource: _source, loading, error, cached, ...htmlProps } = useDataBinding<HtmlModel>(
|
|
264
|
+
dataSource!,
|
|
265
|
+
restProps as Partial<HtmlModel>,
|
|
266
|
+
HtmlModel.getSchema(),
|
|
267
|
+
{ cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
// Show loading state
|
|
271
|
+
if (loading) {
|
|
272
|
+
return (
|
|
273
|
+
<Box sx={{ p: 2, textAlign: 'center', opacity: 0.6 }}>
|
|
274
|
+
Loading HTML content...
|
|
275
|
+
</Box>
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (error) {
|
|
280
|
+
console.error('Error loading HTML content:', error);
|
|
281
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
282
|
+
return (
|
|
283
|
+
<Box sx={{ p: 2, border: '1px solid red', borderRadius: 1, backgroundColor: 'rgba(255, 0, 0, 0.1)' }}>
|
|
284
|
+
<strong>Error Loading HTML:</strong> {error.message}
|
|
285
|
+
</Box>
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return <HtmlView {...htmlProps} />;
|
|
292
|
+
}
|
|
293
|
+
|
|
191
294
|
export default Html;
|
package/src/components/Logo.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dynamic Logo Component - Generic theme-aware logo
|
|
2
|
+
* Dynamic Logo Component - Generic theme-aware logo with image support
|
|
3
3
|
*
|
|
4
4
|
* Features:
|
|
5
5
|
* - Automatic text width calculation with dynamic SVG sizing
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - Accessibility support with proper ARIA labels
|
|
11
11
|
* - Customizable styling via CSS classes for each text part
|
|
12
12
|
* - Text formatting with escape sequences
|
|
13
|
+
* - Image support with flexible positioning
|
|
13
14
|
*
|
|
14
15
|
* Text Formatting (TWO PARTS MAXIMUM):
|
|
15
16
|
* - Use \n for line breaks (second part appears on new line)
|
|
@@ -35,78 +36,49 @@
|
|
|
35
36
|
*/
|
|
36
37
|
|
|
37
38
|
import React, { useRef, useEffect, useState, useCallback } from 'react';
|
|
38
|
-
import {
|
|
39
|
+
import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
|
|
40
|
+
import { QWICKAPP_COMPONENT, useBaseProps, useDataBinding } from '../hooks';
|
|
41
|
+
import LogoModel from '../schemas/LogoSchema';
|
|
42
|
+
import { LogoVariant, LogoSize, LogoBadgeShape, PositionType, BadgeOffset } from '../schemas/LogoSchema';
|
|
39
43
|
import './Logo.css';
|
|
40
44
|
|
|
41
|
-
|
|
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;
|
|
45
|
+
type LogoViewProps = ModelProps<LogoModel> & {
|
|
66
46
|
/** Click handler for the logo */
|
|
67
|
-
onClick?: (event: React.MouseEvent<SVGSVGElement>) => void;
|
|
47
|
+
onClick?: (event: React.MouseEvent<SVGSVGElement | HTMLDivElement>) => void;
|
|
68
48
|
/** Additional inline styles */
|
|
69
49
|
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
50
|
/** Additional CSS class names */
|
|
75
51
|
className?: string;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
interface LogoProps extends LogoViewProps, WithDataBinding {}
|
|
91
55
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
56
|
+
// View component - handles the actual rendering
|
|
57
|
+
function LogoView({
|
|
58
|
+
name = 'Qwick Apps',
|
|
59
|
+
variant = 'default',
|
|
60
|
+
size = 'medium',
|
|
61
|
+
badge = 'top-right',
|
|
62
|
+
badgeShape = 'circle',
|
|
63
|
+
badgeOffsetX,
|
|
64
|
+
badgeOffsetY,
|
|
65
|
+
fontFamily = 'Segoe UI, sans-serif',
|
|
66
|
+
fontWeight = 'bold',
|
|
67
|
+
firstPartClass = 'logo-first-part',
|
|
68
|
+
secondPartClass = 'logo-second-part',
|
|
69
|
+
image,
|
|
70
|
+
imagePosition = 'start',
|
|
71
|
+
onClick,
|
|
72
|
+
style,
|
|
73
|
+
className,
|
|
74
|
+
...restProps
|
|
75
|
+
}: LogoViewProps) {
|
|
76
|
+
const { styleProps, htmlProps, restProps: otherProps } = useBaseProps(restProps);
|
|
107
77
|
|
|
108
|
-
//
|
|
109
|
-
(
|
|
78
|
+
// Convert separate offset values to BadgeOffset object
|
|
79
|
+
const badgeOffset: BadgeOffset | undefined = (badgeOffsetX !== undefined || badgeOffsetY !== undefined)
|
|
80
|
+
? { x: badgeOffsetX, y: badgeOffsetY }
|
|
81
|
+
: undefined;
|
|
110
82
|
|
|
111
83
|
const textRef = useRef<SVGTextElement>(null);
|
|
112
84
|
const [calculatedBadgePosition, setCalculatedBadgePosition] = useState({ x: 155, y: 20 });
|
|
@@ -209,7 +181,7 @@ const Logo: React.FC<LogoProps> = (props) => {
|
|
|
209
181
|
x = textBBox.x + textBBox.width + scaledOffset;
|
|
210
182
|
y = textBBox.y + scaledOffset;
|
|
211
183
|
break;
|
|
212
|
-
case 'center-left'
|
|
184
|
+
case 'start': // was 'center-left'
|
|
213
185
|
x = textBBox.x - scaledOffset;
|
|
214
186
|
y = textBBox.y + textBBox.height / 2;
|
|
215
187
|
break;
|
|
@@ -217,7 +189,7 @@ const Logo: React.FC<LogoProps> = (props) => {
|
|
|
217
189
|
x = textBBox.x + textBBox.width / 2;
|
|
218
190
|
y = textBBox.y + textBBox.height / 2;
|
|
219
191
|
break;
|
|
220
|
-
case 'center-right'
|
|
192
|
+
case 'end': // was 'center-right'
|
|
221
193
|
x = textBBox.x + textBBox.width + scaledOffset;
|
|
222
194
|
y = textBBox.y + textBBox.height / 2;
|
|
223
195
|
break;
|
|
@@ -330,41 +302,167 @@ const Logo: React.FC<LogoProps> = (props) => {
|
|
|
330
302
|
);
|
|
331
303
|
}
|
|
332
304
|
};
|
|
305
|
+
|
|
306
|
+
// Render image if provided
|
|
307
|
+
const renderImage = (): React.ReactNode => {
|
|
308
|
+
if (!image || imagePosition === 'none') return null;
|
|
309
|
+
|
|
310
|
+
// If image is a string, assume it's an image path
|
|
311
|
+
if (typeof image === 'string') {
|
|
312
|
+
const imageSize = fontSize; // Scale image with font size
|
|
313
|
+
return (
|
|
314
|
+
<img
|
|
315
|
+
src={image}
|
|
316
|
+
alt=""
|
|
317
|
+
style={{
|
|
318
|
+
width: imageSize,
|
|
319
|
+
height: imageSize,
|
|
320
|
+
objectFit: 'contain'
|
|
321
|
+
}}
|
|
322
|
+
className="logo-image"
|
|
323
|
+
/>
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// If image is a React node, render it directly
|
|
328
|
+
return <div className="logo-image-container">{image}</div>;
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
// Determine layout based on image position
|
|
332
|
+
const renderWithImage = () => {
|
|
333
|
+
const logoSvg = (
|
|
334
|
+
<svg
|
|
335
|
+
width={svgWidth}
|
|
336
|
+
height={height}
|
|
337
|
+
viewBox={`0 0 ${svgWidth} ${height}`}
|
|
338
|
+
fill="none"
|
|
339
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
340
|
+
className={`logo-svg dynamic-logo ${sizeClass} ${variantClass}`.trim()}
|
|
341
|
+
style={{ height: `${height}px` }}
|
|
342
|
+
role="img"
|
|
343
|
+
aria-label={ariaLabel}
|
|
344
|
+
>
|
|
345
|
+
<text ref={textRef} fontFamily={fontFamily} fontSize={fontSize} fontWeight={fontWeight}>
|
|
346
|
+
<tspan x="15" y={isNewLine ? height * 0.4 : height * 0.7} className={firstPartClass}>{firstPart}</tspan>
|
|
347
|
+
{secondPart && (
|
|
348
|
+
<tspan
|
|
349
|
+
x={isNewLine ? "15" : undefined}
|
|
350
|
+
dy={isNewLine ? fontSize * 1.2 : undefined}
|
|
351
|
+
className={secondPartClass}
|
|
352
|
+
>
|
|
353
|
+
{isNewLine ? secondPart : (hasExplicitSpaces ? ` ${secondPart}` : secondPart)}
|
|
354
|
+
</tspan>
|
|
355
|
+
)}
|
|
356
|
+
</text>
|
|
357
|
+
{renderBadgeShape()}
|
|
358
|
+
</svg>
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
const imageElement = renderImage();
|
|
362
|
+
|
|
363
|
+
if (!imageElement) {
|
|
364
|
+
return logoSvg;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Create container with image positioned based on imagePosition
|
|
368
|
+
let containerStyle: React.CSSProperties = {
|
|
369
|
+
display: 'flex',
|
|
370
|
+
alignItems: 'center',
|
|
371
|
+
gap: '8px',
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
let containerClass = 'logo-container';
|
|
375
|
+
|
|
376
|
+
switch (imagePosition) {
|
|
377
|
+
case 'start':
|
|
378
|
+
containerStyle.flexDirection = 'row';
|
|
379
|
+
containerClass += ' logo-image-start';
|
|
380
|
+
break;
|
|
381
|
+
case 'end':
|
|
382
|
+
containerStyle.flexDirection = 'row-reverse';
|
|
383
|
+
containerClass += ' logo-image-end';
|
|
384
|
+
break;
|
|
385
|
+
case 'top-center':
|
|
386
|
+
containerStyle.flexDirection = 'column';
|
|
387
|
+
containerClass += ' logo-image-top';
|
|
388
|
+
break;
|
|
389
|
+
case 'bottom-center':
|
|
390
|
+
containerStyle.flexDirection = 'column-reverse';
|
|
391
|
+
containerClass += ' logo-image-bottom';
|
|
392
|
+
break;
|
|
393
|
+
default:
|
|
394
|
+
// For other positions, default to start
|
|
395
|
+
containerStyle.flexDirection = 'row';
|
|
396
|
+
containerClass += ' logo-image-start';
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return (
|
|
401
|
+
<div
|
|
402
|
+
{...htmlProps}
|
|
403
|
+
{...styleProps}
|
|
404
|
+
className={`${containerClass} ${className || ''}`.trim()}
|
|
405
|
+
style={{
|
|
406
|
+
...containerStyle,
|
|
407
|
+
cursor: onClick ? 'pointer' : 'default',
|
|
408
|
+
...style
|
|
409
|
+
}}
|
|
410
|
+
onClick={onClick}
|
|
411
|
+
>
|
|
412
|
+
{imageElement}
|
|
413
|
+
{logoSvg}
|
|
414
|
+
</div>
|
|
415
|
+
);
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
return renderWithImage();
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Main Logo component with data binding support
|
|
422
|
+
function Logo(props: LogoProps) {
|
|
423
|
+
const { dataSource, bindingOptions, ...restProps } = props;
|
|
333
424
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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>
|
|
425
|
+
// If no dataSource, use traditional props
|
|
426
|
+
if (!dataSource) {
|
|
427
|
+
return <LogoView {...restProps} />;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Use data binding
|
|
431
|
+
const { dataSource: _source, loading, error, cached, ...logoProps } = useDataBinding<LogoModel>(
|
|
432
|
+
dataSource,
|
|
433
|
+
restProps as Partial<LogoModel>,
|
|
434
|
+
LogoModel.getSchema(),
|
|
435
|
+
{ cache: true, cacheTTL: 300000, strict: false, ...bindingOptions }
|
|
367
436
|
);
|
|
368
|
-
|
|
437
|
+
|
|
438
|
+
// Show loading state
|
|
439
|
+
if (loading) {
|
|
440
|
+
return (
|
|
441
|
+
<div style={{ opacity: 0.5, textAlign: 'center', padding: '16px' }}>
|
|
442
|
+
Loading logo...
|
|
443
|
+
</div>
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Show error state
|
|
448
|
+
if (error) {
|
|
449
|
+
console.error('Error loading logo:', error);
|
|
450
|
+
return (
|
|
451
|
+
<div style={{ color: 'red', textAlign: 'center', padding: '16px' }}>
|
|
452
|
+
Error loading logo: {error.message}
|
|
453
|
+
</div>
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
console.log('Resolved props for Logo:', logoProps);
|
|
458
|
+
return <LogoView {...logoProps} />;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Mark as QwickApp component
|
|
462
|
+
(Logo as any)[QWICKAPP_COMPONENT] = true;
|
|
463
|
+
|
|
464
|
+
// Export types for external use
|
|
465
|
+
export type { LogoVariant, LogoSize, LogoBadgeShape, PositionType, BadgeOffset };
|
|
466
|
+
export type { LogoProps, LogoViewProps };
|
|
369
467
|
|
|
370
468
|
export default Logo;
|