@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
|
@@ -19,62 +19,62 @@ import PaletteSwitcher from '../components/buttons/PaletteSwitcher';
|
|
|
19
19
|
|
|
20
20
|
// Advanced CMS data with complex scenarios - using dotted notation for testing JsonDataProvider conversion
|
|
21
21
|
const advancedCmsData = {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
22
|
+
// Multi-language content
|
|
23
|
+
'content.en.welcome': {
|
|
24
|
+
html: '<h2>Welcome to QwickApps</h2><p>The future of app development is here.</p>',
|
|
25
|
+
placeholder: 'Loading welcome message...'
|
|
26
|
+
},
|
|
27
|
+
'content.es.welcome': {
|
|
28
|
+
html: '<h2>Bienvenidos a QwickApps</h2><p>El futuro del desarrollo de aplicaciones está aquí.</p>',
|
|
29
|
+
placeholder: 'Cargando mensaje de bienvenida...'
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
// Dynamic content with variables
|
|
33
|
+
'user.greeting': {
|
|
34
|
+
html: '<p>Hello <strong>{{userName}}</strong>, welcome back!</p>',
|
|
35
|
+
placeholder: 'Loading personalized greeting...'
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
// Time-sensitive content
|
|
39
|
+
'announcements.current': {
|
|
40
|
+
html: '<div class="announcement"><p><strong> New Feature Alert:</strong> Dynamic data binding with schema validation is now available!</p></div>',
|
|
41
|
+
placeholder: 'Loading current announcements...'
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
// A/B testing variants
|
|
45
|
+
'cta.variant-a': {
|
|
46
|
+
html: '<p class="cta-primary"><strong>Start Building Today!</strong> - Try our free plan.</p>',
|
|
47
|
+
placeholder: 'Loading call-to-action...'
|
|
48
|
+
},
|
|
49
|
+
'cta.variant-b': {
|
|
50
|
+
html: '<p class="cta-secondary"><strong>Join 10,000+ Developers</strong> - Get started now.</p>',
|
|
51
|
+
placeholder: 'Loading call-to-action...'
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// Rich media content
|
|
55
|
+
'blog.featured-post': {
|
|
56
|
+
html: `
|
|
57
|
+
<article>
|
|
58
|
+
<h3>Building Scalable Apps with QwickApps React Framework</h3>
|
|
59
|
+
<p class="meta">Published on January 15, 2025 • 8 min read</p>
|
|
60
|
+
<p>Learn how our <strong>data-binding system</strong> enables dynamic, scalable applications with type-safe CMS integration and validation...</p>
|
|
61
|
+
<a href="/blog/scalable-apps" class="read-more">Continue reading →</a>
|
|
62
|
+
</article>
|
|
63
|
+
`,
|
|
64
|
+
placeholder: 'Loading featured blog post...'
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
// Malicious content for sanitization testing
|
|
68
|
+
'security.malicious': {
|
|
69
|
+
html: '<script>alert("XSS attempt")</script><p>This content includes <strong>malicious scripts</strong> that should be automatically sanitized.</p><img src="x" onerror="alert(\'XSS\')" />',
|
|
70
|
+
placeholder: 'Loading content...'
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
// Performance testing - Large content
|
|
74
|
+
'performance.large-content': {
|
|
75
|
+
html: '<div>' + 'Very long content paragraph. '.repeat(100) + '</div>',
|
|
76
|
+
placeholder: 'Loading large content...'
|
|
77
|
+
}
|
|
78
78
|
};
|
|
79
79
|
|
|
80
80
|
// Create cached data provider for performance
|
|
@@ -82,13 +82,13 @@ const jsonProvider = new JsonDataProvider({ data: advancedCmsData });
|
|
|
82
82
|
const cachedDataProvider = new CachedDataProvider(jsonProvider, { maxSize: 100, defaultTTL: 60000 });
|
|
83
83
|
|
|
84
84
|
const meta: Meta<typeof SafeSpan> = {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
85
|
+
title: 'Framework/Advanced Data Binding',
|
|
86
|
+
component: SafeSpan,
|
|
87
|
+
parameters: {
|
|
88
|
+
layout: 'padded',
|
|
89
|
+
docs: {
|
|
90
|
+
description: {
|
|
91
|
+
component: `
|
|
92
92
|
# Advanced Data Binding Examples
|
|
93
93
|
|
|
94
94
|
This section demonstrates advanced use cases for the data binding system including:
|
|
@@ -116,17 +116,17 @@ All HTML content is automatically sanitized:
|
|
|
116
116
|
- Dangerous attributes are filtered
|
|
117
117
|
- Only safe HTML elements are allowed
|
|
118
118
|
- XSS protection is built-in
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
119
|
+
`
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
decorators: [
|
|
124
|
+
(Story) => (
|
|
125
|
+
<DataProvider dataSource={{ dataProvider: cachedDataProvider }}>
|
|
126
|
+
<Story />
|
|
127
|
+
</DataProvider>
|
|
128
|
+
)
|
|
129
|
+
]
|
|
130
130
|
};
|
|
131
131
|
|
|
132
132
|
export default meta;
|
|
@@ -134,415 +134,415 @@ type Story = StoryObj<typeof meta>;
|
|
|
134
134
|
|
|
135
135
|
// Multi-language Support
|
|
136
136
|
export const MultiLanguageContent: Story = {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
137
|
+
render: () => {
|
|
138
|
+
const [language, setLanguage] = useState<'en' | 'es'>('en');
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<Section>
|
|
142
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1rem' }}>
|
|
143
|
+
<Typography variant='h4'>Multilanguage Support</Typography>
|
|
144
|
+
<div style={{ display: 'flex', gap: '8px' }}>
|
|
145
|
+
<ThemeSwitcher />
|
|
146
|
+
<PaletteSwitcher />
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
<Typography variant='body1' gutterBottom>
|
|
150
|
+
Switch between English and Spanish content dynamically using the data binding system.
|
|
151
|
+
</Typography>
|
|
152
|
+
<br/>
|
|
153
|
+
<Card variant="outlined" style={{ padding: '1rem', marginBottom: '1rem' }}>
|
|
154
|
+
<GridLayout>
|
|
155
|
+
<Button variant={language === 'en' ? 'contained' : 'outlined'} onClick={() => setLanguage('en')}>English</Button>
|
|
156
|
+
<Button variant={language === 'es' ? 'contained' : 'outlined'} onClick={() => setLanguage('es')}>Español</Button>
|
|
157
|
+
<SafeSpan span={12} dataSource={`content.${language}.welcome`} />
|
|
158
|
+
</GridLayout>
|
|
159
|
+
</Card>
|
|
160
|
+
<Code title='Source Code'>{`<GridLayout>
|
|
161
|
+
<Button variant={language === 'en' ? 'contained' : 'outlined'} onClick={() => setLanguage('en')}>English</Button>
|
|
162
|
+
<Button variant={language === 'es' ? 'contained' : 'outlined'} onClick={() => setLanguage('es')}>Español</Button>
|
|
163
|
+
<SafeSpan span={12} dataSource={\`content.\${language}.welcome\`} />
|
|
164
164
|
</GridLayout>`}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
165
|
+
</Code>
|
|
166
|
+
<Code title='Multi-language Content'>{`'content.en.welcome': [
|
|
167
|
+
{
|
|
168
|
+
html: '<h2>Welcome to QwickApps</h2><p>The future of app development is here.</p>'
|
|
169
|
+
}
|
|
170
170
|
],
|
|
171
171
|
'content.es.welcome': [
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
{
|
|
173
|
+
html: '<h2>Bienvenidos a QwickApps</h2><p>El futuro del desarrollo de aplicaciones está aquí.</p>'
|
|
174
|
+
}
|
|
175
175
|
]`}</Code>
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
176
|
+
</Section>
|
|
177
|
+
);
|
|
178
|
+
},
|
|
179
|
+
parameters: {
|
|
180
|
+
docs: {
|
|
181
|
+
description: {
|
|
182
|
+
story: 'Demonstrates multi-language content switching using dynamic dataSource paths.'
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
186
|
};
|
|
187
187
|
|
|
188
188
|
// A/B Testing
|
|
189
189
|
export const ABTestingVariants: Story = {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
190
|
+
render: () => {
|
|
191
|
+
const [variant, setVariant] = useState<'a' | 'b'>('a');
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<Section>
|
|
195
|
+
<Typography variant="h4">A/B Testing Variants</Typography>
|
|
196
|
+
<Typography variant="body1" gutterBottom>
|
|
197
|
+
A/B testing implementation using dynamic dataSource selection for conversion optimization.
|
|
198
|
+
</Typography>
|
|
199
|
+
|
|
200
|
+
<GridLayout>
|
|
201
|
+
<Typography variant="h6">Select A/B Test Variant:</Typography>
|
|
202
|
+
<GridLayout columns={2} spacing="medium">
|
|
203
|
+
<Button variant={variant === 'a' ? 'contained' : 'outlined'} onClick={() => setVariant('a')}>
|
|
204
|
+
Variant A (Start Building)
|
|
205
|
+
</Button>
|
|
206
|
+
<Button variant={variant === 'b' ? 'contained' : 'outlined'} onClick={() => setVariant('b')}>
|
|
207
|
+
Variant B (Join Community)
|
|
208
|
+
</Button>
|
|
209
|
+
</GridLayout>
|
|
210
|
+
|
|
211
|
+
<Card variant="outlined" style={{ padding: '1.5rem', backgroundColor: '#e3f2fd' }}>
|
|
212
|
+
<SafeSpan dataSource={`cta.variant-${variant}`} />
|
|
213
|
+
</Card>
|
|
214
|
+
</GridLayout>
|
|
215
|
+
|
|
216
|
+
<Code title="A/B Testing Implementation">{`const [variant, setVariant] = useState<'a' | 'b'>('a');
|
|
217
217
|
|
|
218
218
|
return (
|
|
219
|
-
|
|
219
|
+
<SafeSpan dataSource={\`cta.variant-\${variant}\`} />
|
|
220
220
|
);`}</Code>
|
|
221
221
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
<Code title="A/B Test Data Structure">{`'cta.variant-a': [
|
|
223
|
+
{
|
|
224
|
+
html: '<p class="cta-primary"><strong>Start Building Today!</strong> - Try our free plan.</p>'
|
|
225
|
+
}
|
|
226
226
|
],
|
|
227
227
|
'cta.variant-b': [
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
228
|
+
{
|
|
229
|
+
html: '<p class="cta-secondary"><strong>Join 10,000+ Developers</strong> - Get started now.</p>'
|
|
230
|
+
}
|
|
231
231
|
]`}</Code>
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
232
|
+
</Section>
|
|
233
|
+
);
|
|
234
|
+
},
|
|
235
|
+
parameters: {
|
|
236
|
+
docs: {
|
|
237
|
+
description: {
|
|
238
|
+
story: 'A/B testing implementation using dynamic dataSource selection for conversion optimization.'
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
242
|
};
|
|
243
243
|
|
|
244
244
|
// Rich Media Content
|
|
245
245
|
export const RichMediaContent: Story = {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
246
|
+
render: () => (
|
|
247
|
+
<Section>
|
|
248
|
+
<Typography variant="h4">Rich Media Content</Typography>
|
|
249
|
+
<Typography variant="body1" gutterBottom>
|
|
250
|
+
Complex HTML content with multiple elements, perfect for blog posts and articles.
|
|
251
|
+
</Typography>
|
|
252
|
+
|
|
253
|
+
<Card variant="outlined" style={{ padding: '1rem', backgroundColor: '#f8f9fa' }}>
|
|
254
|
+
<SafeSpan dataSource="blog.featured-post" />
|
|
255
|
+
</Card>
|
|
256
|
+
|
|
257
|
+
<Code title="Usage">{`<SafeSpan dataSource="blog.featured-post" />`}</Code>
|
|
258
|
+
|
|
259
|
+
<Code title="Rich Media Data Structure">{`'blog.featured-post': [
|
|
260
|
+
{
|
|
261
|
+
html: \`
|
|
262
|
+
<article>
|
|
263
|
+
<h3>Building Scalable Apps with QwickApps React Framework</h3>
|
|
264
|
+
<p class="meta">Published on January 15, 2025 • 8 min read</p>
|
|
265
|
+
<p>Learn how our <strong>data-binding system</strong> enables dynamic applications...</p>
|
|
266
|
+
<a href="/blog/scalable-apps" class="read-more">Continue reading →</a>
|
|
267
|
+
</article>
|
|
268
|
+
\`,
|
|
269
|
+
placeholder: 'Loading featured blog post...'
|
|
270
|
+
}
|
|
271
271
|
]`}</Code>
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
272
|
+
</Section>
|
|
273
|
+
),
|
|
274
|
+
parameters: {
|
|
275
|
+
docs: {
|
|
276
|
+
description: {
|
|
277
|
+
story: 'Complex HTML content with multiple elements, perfect for blog posts and articles.'
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
281
|
};
|
|
282
282
|
|
|
283
283
|
// Security Testing
|
|
284
284
|
export const SecurityAndSanitization: Story = {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
285
|
+
render: () => (
|
|
286
|
+
<Section>
|
|
287
|
+
<Typography variant="h4">Security and Sanitization</Typography>
|
|
288
|
+
<Typography variant="body1" gutterBottom>
|
|
289
|
+
Demonstrates automatic HTML sanitization to prevent XSS attacks and malicious content.
|
|
290
|
+
</Typography>
|
|
291
|
+
|
|
292
|
+
<Card variant="outlined" style={{ padding: '1rem', marginBottom: '1rem', backgroundColor: '#fff3cd' }}>
|
|
293
|
+
<Typography variant="body2">
|
|
294
|
+
<strong> Security Test:</strong> The content below contains malicious scripts that are automatically sanitized.
|
|
295
|
+
</Typography>
|
|
296
|
+
</Card>
|
|
297
|
+
|
|
298
|
+
<Card variant="outlined" style={{ padding: '1rem', marginBottom: '1rem', backgroundColor: '#f8f9fa' }}>
|
|
299
|
+
<SafeSpan dataSource="security.malicious" />
|
|
300
|
+
</Card>
|
|
301
|
+
|
|
302
|
+
<Card variant="outlined" style={{ padding: '1rem', marginBottom: '1rem', backgroundColor: '#d4edda' }}>
|
|
303
|
+
<Typography variant="h6" gutterBottom>What was filtered:</Typography>
|
|
304
|
+
<ul>
|
|
305
|
+
<li><script> tags removed</li>
|
|
306
|
+
<li>onerror attributes removed</li>
|
|
307
|
+
<li>Only safe HTML elements preserved</li>
|
|
308
|
+
</ul>
|
|
309
|
+
</Card>
|
|
310
|
+
|
|
311
|
+
<Code title="Malicious Content (Auto-Sanitized)">{`<SafeSpan dataSource="security.malicious" />`}</Code>
|
|
312
|
+
|
|
313
|
+
<Code title="Malicious Data Source">{`'security.malicious': [
|
|
314
|
+
{
|
|
315
|
+
html: '<script>alert("XSS attempt")</script><p>Safe content with <strong>formatting</strong></p><img src="x" onerror="alert(\\'XSS\\')" />',
|
|
316
|
+
placeholder: 'Loading content...'
|
|
317
|
+
}
|
|
318
318
|
]`}</Code>
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
319
|
+
</Section>
|
|
320
|
+
),
|
|
321
|
+
parameters: {
|
|
322
|
+
docs: {
|
|
323
|
+
description: {
|
|
324
|
+
story: 'Demonstrates automatic HTML sanitization to prevent XSS attacks and malicious content.'
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
328
|
};
|
|
329
329
|
|
|
330
330
|
// Performance Testing
|
|
331
331
|
export const PerformanceOptimization: Story = {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
332
|
+
render: () => (
|
|
333
|
+
<Section>
|
|
334
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1rem' }}>
|
|
335
|
+
<Typography variant="h4">Performance Optimization</Typography>
|
|
336
|
+
<div style={{ display: 'flex', gap: '8px' }}>
|
|
337
|
+
<ThemeSwitcher />
|
|
338
|
+
<PaletteSwitcher />
|
|
339
|
+
</div>
|
|
340
|
+
</div>
|
|
341
|
+
<Typography variant="body1" gutterBottom>
|
|
342
|
+
Performance optimization with caching for large content blocks.
|
|
343
|
+
</Typography>
|
|
344
|
+
|
|
345
|
+
<Card variant="outlined" style={{ padding: '1rem', marginBottom: '1rem' }}>
|
|
346
|
+
<Typography variant="body2" color="text.primary">
|
|
347
|
+
<strong> Performance Test:</strong> Large content with caching enabled for optimal performance.
|
|
348
|
+
</Typography>
|
|
349
|
+
</Card>
|
|
350
|
+
|
|
351
|
+
<Card variant="outlined" style={{ maxHeight: '200px', overflow: 'auto', padding: '1rem', marginBottom: '1rem' }}>
|
|
352
|
+
<SafeSpan dataSource="performance.large-content" />
|
|
353
|
+
</Card>
|
|
354
|
+
|
|
355
|
+
<Card variant="outlined" style={{ padding: '1rem', marginBottom: '1rem' }}>
|
|
356
|
+
<Typography variant="h6" gutterBottom>Performance Features:</Typography>
|
|
357
|
+
<ul>
|
|
358
|
+
<li>Memory caching with 5-minute TTL</li>
|
|
359
|
+
<li>Automatic content chunking for large data</li>
|
|
360
|
+
<li>Efficient re-rendering on data changes</li>
|
|
361
|
+
</ul>
|
|
362
|
+
</Card>
|
|
363
|
+
|
|
364
|
+
<Code title="Cached Performance">{`<DataProvider dataSource={{ dataProvider: cachedDataProvider }}>
|
|
365
|
+
<SafeSpan dataSource="performance.large-content" />
|
|
366
366
|
</DataProvider>`}</Code>
|
|
367
367
|
|
|
368
|
-
|
|
368
|
+
<Code title="Cache Configuration">{`const jsonProvider = new JsonDataProvider({ data: advancedCmsData });
|
|
369
369
|
const cacheProvider = new MemoryCacheProvider<any[]>({
|
|
370
|
-
|
|
371
|
-
|
|
370
|
+
maxSize: 100,
|
|
371
|
+
defaultTtl: 60000
|
|
372
372
|
});
|
|
373
373
|
const cachedDataProvider = new CachedDataProvider(jsonProvider, cacheProvider);`}</Code>
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
374
|
+
</Section>
|
|
375
|
+
),
|
|
376
|
+
parameters: {
|
|
377
|
+
docs: {
|
|
378
|
+
description: {
|
|
379
|
+
story: 'Performance optimization with caching for large content blocks.'
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
383
|
};
|
|
384
384
|
|
|
385
385
|
// Custom Hook Usage
|
|
386
386
|
export const CustomHookExample: Story = {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
387
|
+
render: () => {
|
|
388
|
+
const CustomComponent: React.FC<{ dataSource: string }> = ({ dataSource }) => {
|
|
389
|
+
const { loading, error } = useDataBinding(
|
|
390
|
+
dataSource,
|
|
391
|
+
{
|
|
392
|
+
html: '<p>Fallback HTML content</p>',
|
|
393
|
+
placeholder: 'Fallback placeholder'
|
|
394
|
+
},
|
|
395
|
+
undefined,
|
|
396
|
+
{ strict: true, cache: true }
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
if (loading) {
|
|
400
|
+
return (
|
|
401
|
+
<Card variant="outlined" style={{ padding: '1rem', backgroundColor: '#f8f9fa' }}>
|
|
402
|
+
<Typography variant="body2">Loading content...</Typography>
|
|
403
|
+
</Card>
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (error) {
|
|
408
|
+
return (
|
|
409
|
+
<Card variant="outlined" style={{ padding: '1rem', backgroundColor: '#f8d7da' }}>
|
|
410
|
+
<Typography variant="body2" color="error">
|
|
411
|
+
<strong>Error:</strong> {error.message}
|
|
412
|
+
</Typography>
|
|
413
|
+
</Card>
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return (
|
|
418
|
+
<Card variant="outlined" style={{ padding: '1rem', backgroundColor: '#d4edda' }}>
|
|
419
|
+
<SafeSpan dataSource={dataSource} />
|
|
420
|
+
<Typography variant="caption" color="textSecondary" style={{ marginTop: '0.5rem', display: 'block' }}>
|
|
421
|
+
Loaded via custom useDataBinding hook
|
|
422
|
+
</Typography>
|
|
423
|
+
</Card>
|
|
424
|
+
);
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
return (
|
|
428
|
+
<Section>
|
|
429
|
+
<Typography variant="h4">Custom Hook Implementation</Typography>
|
|
430
|
+
<Typography variant="body1" gutterBottom>
|
|
431
|
+
Custom implementation using the useDataBinding hook directly with advanced options like validation and caching.
|
|
432
|
+
</Typography>
|
|
433
|
+
|
|
434
|
+
<CustomComponent dataSource="announcements.current" />
|
|
435
|
+
|
|
436
|
+
<Code title="Custom Hook Usage">{`const CustomComponent: React.FC<{ dataSource: string }> = ({ dataSource }) => {
|
|
437
|
+
const { loading, error } = useDataBinding(
|
|
438
|
+
dataSource,
|
|
439
|
+
{
|
|
440
|
+
html: '<p>Fallback HTML content</p>',
|
|
441
|
+
placeholder: 'Fallback placeholder'
|
|
442
|
+
},
|
|
443
|
+
undefined,
|
|
444
|
+
{ strict: true, cache: true }
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
if (loading) return <LoadingComponent />;
|
|
448
|
+
if (error) return <ErrorComponent error={error} />;
|
|
449
|
+
|
|
450
|
+
return <SafeSpan dataSource={dataSource} />;
|
|
451
451
|
};`}</Code>
|
|
452
452
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
453
|
+
<Code title="Hook Options">{`const options = {
|
|
454
|
+
strict: true, // Enable strict schema validation
|
|
455
|
+
cache: true, // Enable caching for performance
|
|
456
|
+
fallback: { // Custom fallback data
|
|
457
|
+
html: '<p>Custom fallback content</p>',
|
|
458
|
+
placeholder: 'Custom placeholder'
|
|
459
|
+
}
|
|
460
460
|
};`}</Code>
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
461
|
+
</Section>
|
|
462
|
+
);
|
|
463
|
+
},
|
|
464
|
+
parameters: {
|
|
465
|
+
docs: {
|
|
466
|
+
description: {
|
|
467
|
+
story: 'Custom implementation using the useDataBinding hook directly with advanced options like validation and caching.'
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
471
|
};
|
|
472
472
|
|
|
473
473
|
// Error Handling
|
|
474
474
|
export const ErrorHandlingScenarios: Story = {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
475
|
+
render: () => (
|
|
476
|
+
<Section>
|
|
477
|
+
<Typography variant="h4">Error Handling Scenarios</Typography>
|
|
478
|
+
<Typography variant="body1" gutterBottom>
|
|
479
|
+
Various error handling scenarios showing how the system gracefully degrades when data is missing or invalid.
|
|
480
|
+
</Typography>
|
|
481
|
+
|
|
482
|
+
<GridLayout spacing="large">
|
|
483
|
+
<div>
|
|
484
|
+
<Typography variant="h6">Non-existent Data Source</Typography>
|
|
485
|
+
<Card variant="outlined" style={{ padding: '1rem', backgroundColor: '#fff3cd' }}>
|
|
486
|
+
<SafeSpan
|
|
487
|
+
dataSource="does.not.exist"
|
|
488
|
+
placeholder="Fallback when data source doesn't exist"
|
|
489
|
+
/>
|
|
490
|
+
</Card>
|
|
491
|
+
</div>
|
|
492
|
+
|
|
493
|
+
<div>
|
|
494
|
+
<Typography variant="h6">Empty Data Source</Typography>
|
|
495
|
+
<Card variant="outlined" style={{ padding: '1rem', backgroundColor: '#f8d7da' }}>
|
|
496
|
+
<SafeSpan
|
|
497
|
+
dataSource="empty.data"
|
|
498
|
+
html="<p>Fallback HTML when data is empty</p>"
|
|
499
|
+
/>
|
|
500
|
+
</Card>
|
|
501
|
+
</div>
|
|
502
|
+
|
|
503
|
+
<div>
|
|
504
|
+
<Typography variant="h6">Graceful Degradation</Typography>
|
|
505
|
+
<Card variant="outlined" style={{ padding: '1rem', backgroundColor: '#d4edda' }}>
|
|
506
|
+
<SafeSpan
|
|
507
|
+
dataSource="malformed.data"
|
|
508
|
+
bindingOptions={{
|
|
509
|
+
fallback: {
|
|
510
|
+
html: '<p>Graceful fallback for <strong>malformed data</strong></p>',
|
|
511
|
+
placeholder: 'Fallback placeholder'
|
|
512
|
+
}
|
|
513
|
+
}}
|
|
514
|
+
/>
|
|
515
|
+
</Card>
|
|
516
|
+
</div>
|
|
517
|
+
</GridLayout>
|
|
518
|
+
|
|
519
|
+
<Code title="Non-existent Data Source">{`<SafeSpan
|
|
520
|
+
dataSource="does.not.exist"
|
|
521
|
+
placeholder="Fallback when data source doesn't exist"
|
|
522
522
|
/>`}</Code>
|
|
523
523
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
524
|
+
<Code title="Custom Fallback Options">{`<SafeSpan
|
|
525
|
+
dataSource="malformed.data"
|
|
526
|
+
bindingOptions={{
|
|
527
|
+
fallback: {
|
|
528
|
+
html: '<p>Graceful fallback for <strong>malformed data</strong></p>',
|
|
529
|
+
placeholder: 'Fallback placeholder'
|
|
530
|
+
}
|
|
531
|
+
}}
|
|
532
532
|
/>`}</Code>
|
|
533
533
|
|
|
534
|
-
|
|
534
|
+
<Code title="Error Handling Strategy">{`// System handles errors gracefully:
|
|
535
535
|
// 1. Uses fallback props when data source fails
|
|
536
536
|
// 2. Shows placeholder text when content is empty
|
|
537
537
|
// 3. Applies custom fallback options when specified
|
|
538
538
|
// 4. Never breaks the UI - always renders something useful`}</Code>
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
539
|
+
</Section>
|
|
540
|
+
),
|
|
541
|
+
parameters: {
|
|
542
|
+
docs: {
|
|
543
|
+
description: {
|
|
544
|
+
story: 'Various error handling scenarios showing how the system gracefully degrades when data is missing or invalid.'
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
548
|
};
|