@qwickapps/react-framework 1.3.3 → 1.3.5

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.
Files changed (43) hide show
  1. package/README.md +227 -0
  2. package/dist/components/blocks/Content.d.ts.map +1 -1
  3. package/dist/components/blocks/ProductCard.d.ts.map +1 -1
  4. package/dist/components/forms/FormBlock.d.ts +1 -1
  5. package/dist/components/forms/FormBlock.d.ts.map +1 -1
  6. package/dist/components/input/SwitchInputField.d.ts +28 -0
  7. package/dist/components/input/SwitchInputField.d.ts.map +1 -0
  8. package/dist/components/input/index.d.ts +2 -0
  9. package/dist/components/input/index.d.ts.map +1 -1
  10. package/dist/components/layout/CollapsibleLayout/CollapsibleLayout.d.ts +34 -0
  11. package/dist/components/layout/CollapsibleLayout/CollapsibleLayout.d.ts.map +1 -0
  12. package/dist/components/layout/CollapsibleLayout/index.d.ts +9 -0
  13. package/dist/components/layout/CollapsibleLayout/index.d.ts.map +1 -0
  14. package/dist/components/layout/index.d.ts +2 -0
  15. package/dist/components/layout/index.d.ts.map +1 -1
  16. package/dist/contexts/ThemeContext.d.ts.map +1 -1
  17. package/dist/index.esm.js +963 -105
  18. package/dist/index.js +967 -101
  19. package/dist/schemas/CollapsibleLayoutSchema.d.ts +31 -0
  20. package/dist/schemas/CollapsibleLayoutSchema.d.ts.map +1 -0
  21. package/dist/schemas/SwitchInputFieldSchema.d.ts +18 -0
  22. package/dist/schemas/SwitchInputFieldSchema.d.ts.map +1 -0
  23. package/dist/types/CollapsibleLayout.d.ts +142 -0
  24. package/dist/types/CollapsibleLayout.d.ts.map +1 -0
  25. package/dist/types/index.d.ts +1 -0
  26. package/dist/types/index.d.ts.map +1 -1
  27. package/package.json +1 -1
  28. package/src/components/blocks/Content.tsx +25 -77
  29. package/src/components/blocks/ProductCard.tsx +50 -51
  30. package/src/components/forms/FormBlock.tsx +2 -2
  31. package/src/components/input/SwitchInputField.tsx +165 -0
  32. package/src/components/input/index.ts +2 -0
  33. package/src/components/layout/CollapsibleLayout/CollapsibleLayout.tsx +554 -0
  34. package/src/components/layout/CollapsibleLayout/__tests__/CollapsibleLayout.test.tsx +1469 -0
  35. package/src/components/layout/CollapsibleLayout/index.tsx +17 -0
  36. package/src/components/layout/index.ts +4 -1
  37. package/src/components/pages/FormPage.tsx +1 -1
  38. package/src/contexts/ThemeContext.tsx +1 -2
  39. package/src/schemas/CollapsibleLayoutSchema.ts +276 -0
  40. package/src/schemas/SwitchInputFieldSchema.ts +99 -0
  41. package/src/stories/CollapsibleLayout.stories.tsx +1566 -0
  42. package/src/types/CollapsibleLayout.ts +231 -0
  43. package/src/types/index.ts +1 -0
package/dist/index.esm.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
- import { CircularProgress, Button as Button$1, Paper, Typography, useTheme as useTheme$1, Box, Container as Container$8, Stack, Tooltip, IconButton, Snackbar, Alert, useMediaQuery, Avatar, Chip, Menu, MenuItem, Grid, Divider, Link, ListItemIcon, ListItemText, Card, CardContent, ButtonGroup, Collapse, TextField as TextField$1, FormControl, InputLabel, Select, FormHelperText } from '@mui/material';
3
- import React, { useMemo, useContext, useState, useEffect, createContext, useRef, useCallback, Component, useReducer, cloneElement } from 'react';
2
+ import { CircularProgress, Button as Button$1, Paper, Typography, useTheme as useTheme$1, Box, Container as Container$8, Stack, Tooltip, IconButton, Snackbar, Alert, useMediaQuery, Avatar, Chip, Menu, MenuItem, Grid, Divider, Collapse, Link, ListItemIcon, ListItemText, Card, CardContent, ButtonGroup, TextField as TextField$1, FormControl, InputLabel, Select, FormHelperText, FormControlLabel, Switch } from '@mui/material';
3
+ import React, { useMemo, useContext, useState, useEffect, createContext, useId, useCallback, useRef, Component, useReducer, cloneElement } from 'react';
4
4
  import { MustacheTemplateProvider, MemoryCacheProvider, CachedDataProvider, Field, Editor, FieldType, Schema, Model, DataType } from '@qwickapps/schema';
5
5
  import { IsOptional, IsString, IsIn, IsUrl, IsArray, ValidateNested, IsNumber, Min, Max, IsBoolean, IsNotEmpty, IsObject } from 'class-validator';
6
6
  import { Type } from 'class-transformer';
7
7
  import 'reflect-metadata';
8
- import { Check, ContentCopy, MoreVert, Schedule, Visibility, Launch, LightMode, DarkMode, SettingsSystemDaydream, Palette, Circle, VisibilityOff, Help, FormatBold, FormatItalic, FormatUnderlined, Code as Code$1, Add, RadioButtonUnchecked } from '@mui/icons-material';
8
+ import { Check, ContentCopy, MoreVert, ExpandMore, ExpandLess, Schedule, Visibility, Launch, LightMode, DarkMode, SettingsSystemDaydream, Palette, Circle, VisibilityOff, Help, FormatBold, FormatItalic, FormatUnderlined, Code as Code$1, Add, RadioButtonUnchecked } from '@mui/icons-material';
9
9
  import { createTheme, ThemeProvider as ThemeProvider$1 } from '@mui/material/styles';
10
10
  import { useLocation, useNavigate } from 'react-router-dom';
11
11
 
@@ -13760,72 +13760,62 @@ function ContentView({
13760
13760
  return 3;
13761
13761
  }
13762
13762
  };
13763
- // Content wrapper based on variant
13764
- const ContentWrapper = ({
13765
- children
13766
- }) => {
13767
- const paddingValue = getPadding();
13768
- const mappedMaxWidth = mapToMUIBreakpoint(contentMaxWidth === 'false' ? false : contentMaxWidth);
13769
- const commonSx = {
13770
- textAlign: centered ? 'center' : 'left',
13771
- maxWidth: mappedMaxWidth !== false ? theme.breakpoints.values[mappedMaxWidth] : '100%',
13772
- width: '100%',
13773
- ...(centered && contentMaxWidth && {
13774
- mx: 'auto'
13775
- }),
13776
- p: paddingValue,
13777
- ...styleProps.sx
13778
- };
13779
- switch (variant) {
13780
- case 'elevated':
13781
- return jsx(Paper, {
13782
- elevation: 4,
13783
- ...htmlProps,
13784
- ...otherProps,
13785
- sx: {
13786
- ...commonSx,
13787
- backgroundColor: theme.palette.background.paper
13788
- },
13789
- children: children
13790
- });
13791
- case 'outlined':
13792
- return jsx(Paper, {
13793
- variant: "outlined",
13794
- elevation: 0,
13795
- ...htmlProps,
13796
- ...otherProps,
13797
- sx: {
13798
- ...commonSx,
13799
- backgroundColor: 'var(--theme-surface)',
13800
- borderColor: 'var(--theme-border-main)',
13801
- // Use theme border color
13802
- borderWidth: 1,
13803
- borderStyle: 'solid'
13804
- },
13805
- children: children
13806
- });
13807
- case 'filled':
13808
- return jsx(Box, {
13809
- ...htmlProps,
13810
- ...otherProps,
13811
- sx: {
13812
- ...commonSx,
13813
- backgroundColor: 'var(--theme-surface-variant)',
13814
- // Use theme surface variant
13815
- borderRadius: 1
13816
- },
13817
- children: children
13818
- });
13819
- default:
13820
- return jsx(Box, {
13821
- ...htmlProps,
13822
- ...otherProps,
13823
- sx: commonSx,
13824
- children: children
13825
- });
13826
- }
13763
+ // Compute stable wrapper element (avoid recreating component type each render which caused remount & focus loss)
13764
+ const paddingValue = getPadding();
13765
+ const mappedMaxWidth = mapToMUIBreakpoint(contentMaxWidth === 'false' ? false : contentMaxWidth);
13766
+ const commonSx = {
13767
+ textAlign: centered ? 'center' : 'left',
13768
+ maxWidth: mappedMaxWidth !== false ? theme.breakpoints.values[mappedMaxWidth] : '100%',
13769
+ width: '100%',
13770
+ ...(centered && contentMaxWidth && {
13771
+ mx: 'auto'
13772
+ }),
13773
+ p: paddingValue,
13774
+ ...styleProps.sx
13775
+ };
13776
+ let Wrapper = Box;
13777
+ let wrapperProps = {
13778
+ ...htmlProps,
13779
+ ...otherProps,
13780
+ sx: commonSx
13827
13781
  };
13828
- return jsx(ContentWrapper, {
13782
+ if (variant === 'elevated') {
13783
+ Wrapper = Paper;
13784
+ wrapperProps = {
13785
+ ...wrapperProps,
13786
+ elevation: 4,
13787
+ sx: {
13788
+ ...commonSx,
13789
+ backgroundColor: theme.palette.background.paper
13790
+ }
13791
+ };
13792
+ } else if (variant === 'outlined') {
13793
+ Wrapper = Paper;
13794
+ wrapperProps = {
13795
+ ...wrapperProps,
13796
+ variant: 'outlined',
13797
+ elevation: 0,
13798
+ sx: {
13799
+ ...commonSx,
13800
+ backgroundColor: 'var(--theme-surface)',
13801
+ borderColor: 'var(--theme-border-main)',
13802
+ borderWidth: 1,
13803
+ borderStyle: 'solid'
13804
+ }
13805
+ };
13806
+ } else if (variant === 'filled') {
13807
+ Wrapper = Box;
13808
+ wrapperProps = {
13809
+ ...wrapperProps,
13810
+ sx: {
13811
+ ...commonSx,
13812
+ backgroundColor: 'var(--theme-surface-variant)',
13813
+ borderRadius: 1
13814
+ }
13815
+ };
13816
+ }
13817
+ return jsx(Wrapper, {
13818
+ ...wrapperProps,
13829
13819
  children: jsxs(Stack, {
13830
13820
  spacing: 2,
13831
13821
  children: [(title || subtitle) && jsxs(Box, {
@@ -15334,6 +15324,689 @@ const GridCell = props => {
15334
15324
  };
15335
15325
  GridCell.displayName = 'GridCell';
15336
15326
 
15327
+ /**
15328
+ * CollapsibleLayout Schema - Data model for collapsible layout component
15329
+ *
15330
+ * Advanced expandable/collapsible container with header controls, animations,
15331
+ * content management, and state persistence capabilities.
15332
+ *
15333
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
15334
+ */
15335
+ let CollapsibleLayoutModel = class CollapsibleLayoutModel extends Model {};
15336
+ __decorate([Field({
15337
+ defaultValue: false
15338
+ }), Editor({
15339
+ field_type: FieldType.BOOLEAN,
15340
+ label: 'Collapsed',
15341
+ description: 'Whether the layout is currently collapsed'
15342
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "collapsed", void 0);
15343
+ __decorate([Field({
15344
+ defaultValue: false
15345
+ }), Editor({
15346
+ field_type: FieldType.BOOLEAN,
15347
+ label: 'Default Collapsed',
15348
+ description: 'Initial collapsed state for uncontrolled usage'
15349
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "defaultCollapsed", void 0);
15350
+ __decorate([Field(), Editor({
15351
+ field_type: FieldType.TEXT,
15352
+ label: 'Title',
15353
+ description: 'Main title displayed in the header',
15354
+ placeholder: 'Enter title...'
15355
+ }), IsOptional(), IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "title", void 0);
15356
+ __decorate([Field(), Editor({
15357
+ field_type: FieldType.TEXT,
15358
+ label: 'Subtitle',
15359
+ description: 'Secondary text displayed below the title',
15360
+ placeholder: 'Enter subtitle...'
15361
+ }), IsOptional(), IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "subtitle", void 0);
15362
+ __decorate([Field(), Editor({
15363
+ field_type: FieldType.TEXT,
15364
+ label: 'Lead Icon',
15365
+ description: 'Icon displayed before the title (icon identifier or HTML)',
15366
+ placeholder: 'Icon identifier...'
15367
+ }), IsOptional(), IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "leadIcon", void 0);
15368
+ __decorate([Field(), Editor({
15369
+ field_type: FieldType.TEXTAREA,
15370
+ label: 'Header Actions',
15371
+ description: 'Additional controls displayed in header (HTML/React content)',
15372
+ placeholder: 'Enter header actions HTML...'
15373
+ }), IsOptional(), IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "headerActions", void 0);
15374
+ __decorate([Field(), Editor({
15375
+ field_type: FieldType.TEXTAREA,
15376
+ label: 'Collapsed View',
15377
+ description: 'Summary content shown when collapsed (HTML supported)',
15378
+ placeholder: 'Enter collapsed view content...'
15379
+ }), IsOptional(), IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "collapsedView", void 0);
15380
+ __decorate([Field(), Editor({
15381
+ field_type: FieldType.TEXTAREA,
15382
+ label: 'Content',
15383
+ description: 'Main content shown when expanded (HTML supported)',
15384
+ placeholder: 'Enter main content...'
15385
+ }), IsOptional(), IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "children", void 0);
15386
+ __decorate([Field(), Editor({
15387
+ field_type: FieldType.TEXTAREA,
15388
+ label: 'Footer View',
15389
+ description: 'Always visible footer content (HTML supported)',
15390
+ placeholder: 'Enter footer content...'
15391
+ }), IsOptional(), IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "footerView", void 0);
15392
+ __decorate([Field({
15393
+ defaultValue: 'header'
15394
+ }), Editor({
15395
+ field_type: FieldType.SELECT,
15396
+ label: 'Trigger Area',
15397
+ description: 'Area that responds to clicks for toggle functionality',
15398
+ validation: {
15399
+ options: [{
15400
+ label: 'Button Only',
15401
+ value: 'button'
15402
+ }, {
15403
+ label: 'Header Area',
15404
+ value: 'header'
15405
+ }, {
15406
+ label: 'Button and Header',
15407
+ value: 'both'
15408
+ }]
15409
+ }
15410
+ }), IsOptional(), IsIn(['button', 'header', 'both']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "triggerArea", void 0);
15411
+ __decorate([Field({
15412
+ defaultValue: 'slide'
15413
+ }), Editor({
15414
+ field_type: FieldType.SELECT,
15415
+ label: 'Animation Style',
15416
+ description: 'Animation variant for expand/collapse transitions',
15417
+ validation: {
15418
+ options: [{
15419
+ label: 'Fade',
15420
+ value: 'fade'
15421
+ }, {
15422
+ label: 'Slide',
15423
+ value: 'slide'
15424
+ }, {
15425
+ label: 'Scale',
15426
+ value: 'scale'
15427
+ }]
15428
+ }
15429
+ }), IsOptional(), IsIn(['fade', 'slide', 'scale']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "animationStyle", void 0);
15430
+ __decorate([Field({
15431
+ defaultValue: false
15432
+ }), Editor({
15433
+ field_type: FieldType.BOOLEAN,
15434
+ label: 'Persist State',
15435
+ description: 'Save collapse state in local storage'
15436
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "persistState", void 0);
15437
+ __decorate([Field(), Editor({
15438
+ field_type: FieldType.TEXT,
15439
+ label: 'Collapsed Icon',
15440
+ description: 'Icon shown when content is collapsed (default: VisibilityIcon)',
15441
+ placeholder: 'Icon identifier...'
15442
+ }), IsOptional(), IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "collapsedIcon", void 0);
15443
+ __decorate([Field(), Editor({
15444
+ field_type: FieldType.TEXT,
15445
+ label: 'Expanded Icon',
15446
+ description: 'Icon shown when content is expanded (default: VisibilityOffIcon)',
15447
+ placeholder: 'Icon identifier...'
15448
+ }), IsOptional(), IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "expandedIcon", void 0);
15449
+ __decorate([Field({
15450
+ defaultValue: true
15451
+ }), Editor({
15452
+ field_type: FieldType.BOOLEAN,
15453
+ label: 'Show Divider',
15454
+ description: 'Show divider lines between header, content, and footer sections'
15455
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "showDivider", void 0);
15456
+ __decorate([Field({
15457
+ defaultValue: 'default'
15458
+ }), Editor({
15459
+ field_type: FieldType.SELECT,
15460
+ label: 'Variant',
15461
+ description: 'Visual style variant for the layout container',
15462
+ validation: {
15463
+ options: [{
15464
+ label: 'Default',
15465
+ value: 'default'
15466
+ }, {
15467
+ label: 'Outlined',
15468
+ value: 'outlined'
15469
+ }, {
15470
+ label: 'Elevated',
15471
+ value: 'elevated'
15472
+ }, {
15473
+ label: 'Filled',
15474
+ value: 'filled'
15475
+ }]
15476
+ }
15477
+ }), IsOptional(), IsIn(['default', 'outlined', 'elevated', 'filled']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "variant", void 0);
15478
+ __decorate([Field({
15479
+ defaultValue: 'comfortable'
15480
+ }), Editor({
15481
+ field_type: FieldType.SELECT,
15482
+ label: 'Header Spacing',
15483
+ description: 'Padding/spacing within the header area',
15484
+ validation: {
15485
+ options: [{
15486
+ label: 'Compact',
15487
+ value: 'compact'
15488
+ }, {
15489
+ label: 'Comfortable',
15490
+ value: 'comfortable'
15491
+ }, {
15492
+ label: 'Spacious',
15493
+ value: 'spacious'
15494
+ }]
15495
+ }
15496
+ }), IsOptional(), IsIn(['compact', 'comfortable', 'spacious']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "headerSpacing", void 0);
15497
+ __decorate([Field({
15498
+ defaultValue: 'comfortable'
15499
+ }), Editor({
15500
+ field_type: FieldType.SELECT,
15501
+ label: 'Content Spacing',
15502
+ description: 'Padding/spacing within the content area',
15503
+ validation: {
15504
+ options: [{
15505
+ label: 'Compact',
15506
+ value: 'compact'
15507
+ }, {
15508
+ label: 'Comfortable',
15509
+ value: 'comfortable'
15510
+ }, {
15511
+ label: 'Spacious',
15512
+ value: 'spacious'
15513
+ }]
15514
+ }
15515
+ }), IsOptional(), IsIn(['compact', 'comfortable', 'spacious']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "contentSpacing", void 0);
15516
+ CollapsibleLayoutModel = __decorate([Schema('CollapsibleLayout', '1.0.0')], CollapsibleLayoutModel);
15517
+ var CollapsibleLayoutModel$1 = CollapsibleLayoutModel;
15518
+
15519
+ /**
15520
+ * TypeScript type definitions for CollapsibleLayout component
15521
+ *
15522
+ * Provides TypeScript interfaces that extend the schema model with React-specific types
15523
+ * and component-level functionality for the CollapsibleLayout component.
15524
+ *
15525
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
15526
+ */
15527
+ /**
15528
+ * Type guard to check if a component has CollapsibleLayout props
15529
+ */
15530
+ function isCollapsibleLayoutProps(props) {
15531
+ return props && typeof props === 'object' && ('collapsed' in props || 'defaultCollapsed' in props);
15532
+ }
15533
+ /**
15534
+ * Default props for CollapsibleLayout component
15535
+ */
15536
+ const defaultCollapsibleLayoutProps = {
15537
+ // Note: collapsed is intentionally omitted so components can be uncontrolled
15538
+ defaultCollapsed: false,
15539
+ triggerArea: 'both',
15540
+ animationStyle: 'slide',
15541
+ persistState: false,
15542
+ showDivider: true,
15543
+ variant: 'default',
15544
+ headerSpacing: 'comfortable',
15545
+ contentSpacing: 'comfortable',
15546
+ animationDuration: 300,
15547
+ disableAnimations: false,
15548
+ toggleAriaLabel: 'Toggle content visibility'
15549
+ };
15550
+ const animationConfigs = {
15551
+ fade: {
15552
+ duration: 300,
15553
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
15554
+ opacity: [0, 1]
15555
+ },
15556
+ slide: {
15557
+ duration: 300,
15558
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
15559
+ transform: 'translateY(-10px)'
15560
+ },
15561
+ scale: {
15562
+ duration: 200,
15563
+ easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)',
15564
+ transform: 'scale(0.95)',
15565
+ opacity: [0, 1]
15566
+ }
15567
+ };
15568
+ const spacingConfigs = {
15569
+ compact: {
15570
+ padding: '8px 12px',
15571
+ gap: '4px'
15572
+ },
15573
+ comfortable: {
15574
+ padding: '16px 20px',
15575
+ gap: '8px'
15576
+ },
15577
+ spacious: {
15578
+ padding: '24px 32px',
15579
+ gap: '16px'
15580
+ }
15581
+ };
15582
+
15583
+ /**
15584
+ * Custom hook for managing collapsible state - simplified approach
15585
+ */
15586
+ function useCollapsibleState(controlled, collapsedProp, defaultCollapsedProp, onToggleProp, persistState, storageKey) {
15587
+ const id = useId();
15588
+ const finalStorageKey = storageKey || `collapsible-${id}`;
15589
+ // For controlled components, use the prop; for uncontrolled, use internal state
15590
+ const [internalCollapsed, setInternalCollapsed] = useState(() => {
15591
+ if (controlled) {
15592
+ return collapsedProp ?? false;
15593
+ }
15594
+ // Try localStorage first if persistence is enabled
15595
+ if (persistState && typeof window !== 'undefined') {
15596
+ const stored = localStorage.getItem(finalStorageKey);
15597
+ if (stored !== null) {
15598
+ return JSON.parse(stored);
15599
+ }
15600
+ }
15601
+ return defaultCollapsedProp ?? false;
15602
+ });
15603
+ // Sync with controlled prop changes
15604
+ useEffect(() => {
15605
+ if (controlled && collapsedProp !== undefined) {
15606
+ setInternalCollapsed(collapsedProp);
15607
+ }
15608
+ }, [controlled, collapsedProp]);
15609
+ // Persist to localStorage for uncontrolled components
15610
+ useEffect(() => {
15611
+ if (!controlled && persistState && typeof window !== 'undefined') {
15612
+ localStorage.setItem(finalStorageKey, JSON.stringify(internalCollapsed));
15613
+ }
15614
+ }, [controlled, internalCollapsed, persistState, finalStorageKey]);
15615
+ const toggle = useCallback(() => {
15616
+ const currentState = controlled ? collapsedProp ?? false : internalCollapsed;
15617
+ const newCollapsed = !currentState;
15618
+ // Always update internal state for visual updates
15619
+ setInternalCollapsed(newCollapsed);
15620
+ // Call callback to notify parent
15621
+ onToggleProp?.(newCollapsed);
15622
+ }, [controlled, collapsedProp, internalCollapsed, onToggleProp]);
15623
+ const setCollapsed = useCallback(collapsed => {
15624
+ setInternalCollapsed(collapsed);
15625
+ onToggleProp?.(collapsed);
15626
+ }, [onToggleProp]);
15627
+ // Return the appropriate state
15628
+ const finalCollapsed = controlled ? collapsedProp ?? false : internalCollapsed;
15629
+ return {
15630
+ collapsed: finalCollapsed,
15631
+ toggle,
15632
+ setCollapsed,
15633
+ isControlled: controlled
15634
+ };
15635
+ }
15636
+ /**
15637
+ * Core CollapsibleLayout View component
15638
+ */
15639
+ function CollapsibleLayoutView({
15640
+ // State props
15641
+ collapsed: collapsedProp,
15642
+ defaultCollapsed = false,
15643
+ onToggle,
15644
+ // Content props
15645
+ title,
15646
+ subtitle,
15647
+ leadIcon,
15648
+ headerActions,
15649
+ collapsedView,
15650
+ children,
15651
+ footerView,
15652
+ // Behavior props
15653
+ triggerArea = 'both',
15654
+ animationStyle = 'slide',
15655
+ persistState = false,
15656
+ storageKey,
15657
+ animationDuration = 300,
15658
+ disableAnimations = false,
15659
+ // Icons
15660
+ collapsedIcon,
15661
+ expandedIcon,
15662
+ // Layout props
15663
+ showDivider = true,
15664
+ variant = 'default',
15665
+ headerSpacing = 'comfortable',
15666
+ contentSpacing = 'comfortable',
15667
+ // Accessibility
15668
+ toggleAriaLabel = 'Toggle content visibility',
15669
+ 'aria-describedby': ariaDescribedBy,
15670
+ contentAriaProps = {},
15671
+ // CSS classes
15672
+ containerClassName,
15673
+ headerClassName,
15674
+ contentClassName,
15675
+ footerClassName,
15676
+ ...restProps
15677
+ }) {
15678
+ const theme = useTheme$1();
15679
+ const {
15680
+ styleProps,
15681
+ htmlProps,
15682
+ restProps: otherProps
15683
+ } = useBaseProps(restProps);
15684
+ // Mark as QwickApp component
15685
+ CollapsibleLayoutView[QWICKAPP_COMPONENT] = true;
15686
+ // Determine controlled vs uncontrolled usage
15687
+ const controlled = collapsedProp !== undefined;
15688
+ // State management
15689
+ const {
15690
+ collapsed,
15691
+ toggle,
15692
+ setCollapsed
15693
+ } = useCollapsibleState(controlled, collapsedProp, defaultCollapsed, onToggle, persistState, storageKey);
15694
+ // Get spacing configurations
15695
+ const headerSpacingConfig = spacingConfigs[headerSpacing];
15696
+ const contentSpacingConfig = spacingConfigs[contentSpacing];
15697
+ // Get animation configuration
15698
+ const animationConfig = animationConfigs[animationStyle];
15699
+ // Generate unique IDs for accessibility
15700
+ const headerId = useId();
15701
+ const contentId = useId();
15702
+ // Handle click events
15703
+ const handleHeaderClick = useCallback(event => {
15704
+ if (triggerArea === 'header' || triggerArea === 'both') {
15705
+ event.preventDefault();
15706
+ toggle();
15707
+ }
15708
+ }, [triggerArea, toggle]);
15709
+ const handleButtonClick = useCallback(event => {
15710
+ event.stopPropagation();
15711
+ toggle();
15712
+ }, [toggle]);
15713
+ // Render icons
15714
+ const renderIcon = useCallback((icon, defaultIcon) => {
15715
+ if (/*#__PURE__*/React.isValidElement(icon)) {
15716
+ return icon;
15717
+ }
15718
+ if (typeof icon === 'string') {
15719
+ return jsx(Html, {
15720
+ children: icon
15721
+ });
15722
+ }
15723
+ return defaultIcon;
15724
+ }, []);
15725
+ const toggleIcon = renderIcon(collapsed ? collapsedIcon : expandedIcon, collapsed ? jsx(ExpandMore, {}) : jsx(ExpandLess, {}));
15726
+ // Container styles based on variant
15727
+ const containerSx = useMemo(() => {
15728
+ const baseSx = {
15729
+ width: '100%',
15730
+ position: 'relative',
15731
+ ...styleProps.sx
15732
+ };
15733
+ switch (variant) {
15734
+ case 'outlined':
15735
+ return {
15736
+ ...baseSx,
15737
+ border: `1px solid ${theme.palette.divider}`,
15738
+ borderRadius: 1,
15739
+ backgroundColor: 'var(--theme-surface)'
15740
+ };
15741
+ case 'elevated':
15742
+ return {
15743
+ ...baseSx,
15744
+ boxShadow: theme.shadows[2],
15745
+ borderRadius: 1,
15746
+ backgroundColor: theme.palette.background.paper
15747
+ };
15748
+ case 'filled':
15749
+ return {
15750
+ ...baseSx,
15751
+ backgroundColor: 'var(--theme-surface-variant)',
15752
+ borderRadius: 1
15753
+ };
15754
+ default:
15755
+ return baseSx;
15756
+ }
15757
+ }, [variant, theme, styleProps.sx]);
15758
+ // Header styles
15759
+ const headerSx = useMemo(() => ({
15760
+ ...headerSpacingConfig,
15761
+ cursor: triggerArea === 'header' || triggerArea === 'both' ? 'pointer' : 'default',
15762
+ userSelect: 'none',
15763
+ display: 'flex',
15764
+ alignItems: 'center',
15765
+ justifyContent: 'space-between',
15766
+ '&:hover': triggerArea === 'header' || triggerArea === 'both' ? {
15767
+ backgroundColor: 'rgba(0, 0, 0, 0.04)'
15768
+ } : {}
15769
+ }), [headerSpacingConfig, triggerArea]);
15770
+ // Content styles
15771
+ const contentSx = useMemo(() => ({
15772
+ ...contentSpacingConfig
15773
+ }), [contentSpacingConfig]);
15774
+ // Animation props for Collapse component
15775
+ const collapseProps = useMemo(() => {
15776
+ if (disableAnimations) {
15777
+ return {
15778
+ timeout: 0
15779
+ };
15780
+ }
15781
+ const baseProps = {
15782
+ timeout: animationDuration
15783
+ };
15784
+ switch (animationStyle) {
15785
+ case 'fade':
15786
+ return {
15787
+ ...baseProps,
15788
+ sx: {
15789
+ '& .MuiCollapse-wrapper': {
15790
+ opacity: collapsed ? 0 : 1,
15791
+ transition: `opacity ${animationDuration}ms ${animationConfig.easing}`
15792
+ }
15793
+ }
15794
+ };
15795
+ case 'scale':
15796
+ return {
15797
+ ...baseProps,
15798
+ sx: {
15799
+ '& .MuiCollapse-wrapper': {
15800
+ transform: collapsed ? 'scale(0.95)' : 'scale(1)',
15801
+ opacity: collapsed ? 0 : 1,
15802
+ transition: `all ${animationDuration}ms ${animationConfig.easing}`
15803
+ }
15804
+ }
15805
+ };
15806
+ default:
15807
+ // slide
15808
+ return baseProps;
15809
+ }
15810
+ }, [disableAnimations, animationDuration, animationStyle, animationConfig, collapsed]);
15811
+ // Render content based on type
15812
+ const renderContent = useCallback(content => {
15813
+ if (!content) return null;
15814
+ if (typeof content === 'string') {
15815
+ return jsx(Html, {
15816
+ children: content
15817
+ });
15818
+ }
15819
+ return content;
15820
+ }, []);
15821
+ // Container content that will be wrapped
15822
+ const containerContent = jsxs(Fragment, {
15823
+ children: [(title || subtitle || leadIcon || headerActions || triggerArea === 'button' || triggerArea === 'both') && jsxs(Fragment, {
15824
+ children: [jsxs(Box, {
15825
+ id: headerId,
15826
+ className: headerClassName,
15827
+ sx: headerSx,
15828
+ onClick: handleHeaderClick,
15829
+ role: triggerArea === 'header' || triggerArea === 'both' ? 'button' : undefined,
15830
+ tabIndex: triggerArea === 'header' || triggerArea === 'both' ? 0 : undefined,
15831
+ "aria-expanded": !collapsed,
15832
+ "aria-controls": contentId,
15833
+ "aria-describedby": ariaDescribedBy,
15834
+ onKeyDown: e => {
15835
+ if ((triggerArea === 'header' || triggerArea === 'both') && (e.key === 'Enter' || e.key === ' ')) {
15836
+ e.preventDefault();
15837
+ toggle();
15838
+ }
15839
+ },
15840
+ children: [jsxs(Stack, {
15841
+ direction: "row",
15842
+ spacing: 2,
15843
+ alignItems: "center",
15844
+ sx: {
15845
+ minWidth: 0,
15846
+ flex: 1
15847
+ },
15848
+ children: [leadIcon && jsx(Box, {
15849
+ sx: {
15850
+ flexShrink: 0
15851
+ },
15852
+ children: renderContent(leadIcon)
15853
+ }), (title || subtitle) && jsxs(Box, {
15854
+ sx: {
15855
+ minWidth: 0,
15856
+ flex: 1
15857
+ },
15858
+ children: [title && jsx(Typography, {
15859
+ variant: "h6",
15860
+ component: "h3",
15861
+ sx: {
15862
+ fontWeight: 600,
15863
+ lineHeight: 1.2,
15864
+ ...(subtitle && {
15865
+ mb: 0.5
15866
+ })
15867
+ },
15868
+ children: title
15869
+ }), subtitle && jsx(Typography, {
15870
+ variant: "body2",
15871
+ color: "text.secondary",
15872
+ sx: {
15873
+ lineHeight: 1.3
15874
+ },
15875
+ children: subtitle
15876
+ })]
15877
+ })]
15878
+ }), jsxs(Stack, {
15879
+ direction: "row",
15880
+ spacing: 1,
15881
+ alignItems: "center",
15882
+ sx: {
15883
+ flexShrink: 0
15884
+ },
15885
+ children: [headerActions && jsx(Box, {
15886
+ children: renderContent(headerActions)
15887
+ }), jsx(IconButton, {
15888
+ onClick: handleButtonClick,
15889
+ size: "small",
15890
+ "aria-label": toggleAriaLabel,
15891
+ "aria-expanded": !collapsed,
15892
+ "aria-controls": contentId,
15893
+ children: toggleIcon
15894
+ })]
15895
+ })]
15896
+ }), showDivider && jsx(Divider, {})]
15897
+ }), collapsed && collapsedView && jsxs(Fragment, {
15898
+ children: [jsx(Box, {
15899
+ className: contentClassName,
15900
+ sx: contentSx,
15901
+ children: renderContent(collapsedView)
15902
+ }), showDivider && footerView && jsx(Divider, {})]
15903
+ }), jsxs(Collapse, {
15904
+ in: !collapsed,
15905
+ ...collapseProps,
15906
+ children: [jsx(Box, {
15907
+ id: contentId,
15908
+ className: contentClassName,
15909
+ sx: contentSx,
15910
+ role: "region",
15911
+ "aria-labelledby": title ? headerId : undefined,
15912
+ ...contentAriaProps,
15913
+ children: renderContent(children)
15914
+ }), showDivider && footerView && jsx(Divider, {})]
15915
+ }), footerView && jsx(Box, {
15916
+ className: footerClassName,
15917
+ sx: contentSx,
15918
+ children: renderContent(footerView)
15919
+ })]
15920
+ });
15921
+ // Return appropriate container based on variant
15922
+ if (variant === 'outlined') {
15923
+ return jsx(Paper, {
15924
+ variant: "outlined",
15925
+ elevation: 0,
15926
+ ...htmlProps,
15927
+ ...otherProps,
15928
+ className: containerClassName,
15929
+ sx: containerSx,
15930
+ children: containerContent
15931
+ });
15932
+ }
15933
+ if (variant === 'elevated') {
15934
+ return jsx(Paper, {
15935
+ elevation: 2,
15936
+ ...htmlProps,
15937
+ ...otherProps,
15938
+ className: containerClassName,
15939
+ sx: containerSx,
15940
+ children: containerContent
15941
+ });
15942
+ }
15943
+ // Default variant (default, filled)
15944
+ return jsx(Box, {
15945
+ ...htmlProps,
15946
+ ...otherProps,
15947
+ className: containerClassName,
15948
+ sx: containerSx,
15949
+ children: containerContent
15950
+ });
15951
+ }
15952
+ /**
15953
+ * Main CollapsibleLayout component with data binding support
15954
+ */
15955
+ function CollapsibleLayout(props) {
15956
+ const {
15957
+ dataSource,
15958
+ bindingOptions,
15959
+ ...restProps
15960
+ } = props;
15961
+ // If no dataSource, use traditional props
15962
+ if (!dataSource) {
15963
+ return jsx(CollapsibleLayoutView, {
15964
+ ...restProps
15965
+ });
15966
+ }
15967
+ // Use data binding
15968
+ const {
15969
+ dataSource: _source,
15970
+ loading,
15971
+ error,
15972
+ cached,
15973
+ ...collapsibleProps
15974
+ } = useDataBinding(dataSource, restProps, CollapsibleLayoutModel$1.getSchema(), {
15975
+ cache: true,
15976
+ cacheTTL: 300000,
15977
+ strict: false,
15978
+ ...bindingOptions
15979
+ });
15980
+ // Show loading state
15981
+ if (loading) {
15982
+ return jsx(CollapsibleLayoutView, {
15983
+ ...restProps,
15984
+ title: "Loading...",
15985
+ variant: "default",
15986
+ headerSpacing: "comfortable",
15987
+ contentSpacing: "comfortable"
15988
+ });
15989
+ }
15990
+ if (error) {
15991
+ console.error('Error loading collapsible layout:', error);
15992
+ {
15993
+ return jsx(CollapsibleLayoutView, {
15994
+ ...restProps,
15995
+ title: "Error Loading Layout",
15996
+ subtitle: error.message,
15997
+ variant: "outlined",
15998
+ headerSpacing: "comfortable",
15999
+ contentSpacing: "comfortable"
16000
+ });
16001
+ }
16002
+ }
16003
+ return jsx(CollapsibleLayoutView, {
16004
+ ...collapsibleProps
16005
+ });
16006
+ }
16007
+ // Set default props
16008
+ CollapsibleLayout.defaultProps = defaultCollapsibleLayoutProps;
16009
+
15337
16010
  /**
15338
16011
  * FeatureCard Schema - Schema definition for FeatureCard component
15339
16012
  *
@@ -16454,7 +17127,9 @@ function ProductCardView({
16454
17127
  return actions;
16455
17128
  };
16456
17129
  const displayActions = actions || getDefaultActions();
16457
- const FeaturesList = () => {
17130
+ // INLINE WRAPPERS REFACTORED: Instead of inline component declarations (which cause remounts),
17131
+ // compute JSX fragments via plain variables/functions and inject directly.
17132
+ const featuresListElement = (() => {
16458
17133
  const featuresToShow = variant === 'compact' ? (product.features || []).slice(0, maxFeaturesCompact) : product.features || [];
16459
17134
  return jsxs(Box, {
16460
17135
  sx: {
@@ -16514,40 +17189,37 @@ function ProductCardView({
16514
17189
  })]
16515
17190
  })]
16516
17191
  });
16517
- };
16518
- const TechnologiesSection = () => {
16519
- if (!showTechnologies || variant === 'compact') return null;
16520
- return jsxs(Box, {
17192
+ })();
17193
+ const technologiesSectionElement = !showTechnologies || variant === 'compact' ? null : jsxs(Box, {
17194
+ sx: {
17195
+ mb: 3
17196
+ },
17197
+ children: [jsx(Typography, {
17198
+ variant: "h6",
17199
+ component: "h4",
16521
17200
  sx: {
16522
- mb: 3
17201
+ mb: 1.5,
17202
+ fontSize: '1rem',
17203
+ fontWeight: 600
16523
17204
  },
16524
- children: [jsx(Typography, {
16525
- variant: "h6",
16526
- component: "h4",
16527
- sx: {
16528
- mb: 1.5,
16529
- fontSize: '1rem',
16530
- fontWeight: 600
16531
- },
16532
- children: "Technologies:"
16533
- }), jsx(Box, {
17205
+ children: "Technologies:"
17206
+ }), jsx(Box, {
17207
+ sx: {
17208
+ display: 'flex',
17209
+ flexWrap: 'wrap',
17210
+ gap: 1
17211
+ },
17212
+ children: product.technologies.map((tech, index) => jsx(Chip, {
17213
+ label: tech,
17214
+ variant: "outlined",
17215
+ size: "small",
16534
17216
  sx: {
16535
- display: 'flex',
16536
- flexWrap: 'wrap',
16537
- gap: 1
16538
- },
16539
- children: product.technologies.map((tech, index) => jsx(Chip, {
16540
- label: tech,
16541
- variant: "outlined",
16542
- size: "small",
16543
- sx: {
16544
- fontSize: '0.8rem',
16545
- fontWeight: 500
16546
- }
16547
- }, index))
16548
- })]
16549
- });
16550
- };
17217
+ fontSize: '0.8rem',
17218
+ fontWeight: 500
17219
+ }
17220
+ }, index))
17221
+ })]
17222
+ });
16551
17223
  return jsxs(Box, {
16552
17224
  className: styleProps.className || "product-card",
16553
17225
  onClick: htmlProps.onClick || (variant === 'compact' ? handleProductClick : undefined),
@@ -16653,7 +17325,7 @@ function ProductCardView({
16653
17325
  },
16654
17326
  children: variant === 'detailed' ? product.description : product.shortDescription || product.description
16655
17327
  })]
16656
- }), jsx(FeaturesList, {}), jsx(TechnologiesSection, {}), jsx(Box, {
17328
+ }), featuresListElement, technologiesSectionElement, jsx(Box, {
16657
17329
  sx: {
16658
17330
  display: 'flex',
16659
17331
  gap: 1.5,
@@ -17514,7 +18186,6 @@ const ThemeProvider = ({
17514
18186
  }
17515
18187
  }
17516
18188
  });
17517
- // eslint-disable-next-line react-hooks/exhaustive-deps
17518
18189
  }, [actualThemeMode, paletteChangeCounter]); // paletteChangeCounter is needed to force theme rebuild // Re-create theme when palette changes
17519
18190
  // Theme preference management methods
17520
18191
  const setPreferredTheme = theme => {
@@ -18726,7 +19397,7 @@ function FormBlockView({
18726
19397
  title,
18727
19398
  description,
18728
19399
  coverImage,
18729
- form,
19400
+ children: form,
18730
19401
  footer,
18731
19402
  status,
18732
19403
  message,
@@ -19727,6 +20398,193 @@ function SelectInputField(props) {
19727
20398
  // Mark as QwickApp component
19728
20399
  SelectInputField[QWICKAPP_COMPONENT] = true;
19729
20400
 
20401
+ /**
20402
+ * SwitchInputField Schema - Data model for switch input field component
20403
+ *
20404
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
20405
+ */
20406
+ let SwitchInputFieldModel = class SwitchInputFieldModel extends Model {};
20407
+ __decorate([Field(), Editor({
20408
+ field_type: FieldType.TEXT,
20409
+ label: 'Label',
20410
+ description: 'The label text for the switch'
20411
+ }), IsOptional(), IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "label", void 0);
20412
+ __decorate([Field({
20413
+ defaultValue: false
20414
+ }), Editor({
20415
+ field_type: FieldType.BOOLEAN,
20416
+ label: 'Checked',
20417
+ description: 'Whether the switch is checked'
20418
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], SwitchInputFieldModel.prototype, "checked", void 0);
20419
+ __decorate([Field({
20420
+ defaultValue: false
20421
+ }), Editor({
20422
+ field_type: FieldType.BOOLEAN,
20423
+ label: 'Required',
20424
+ description: 'Whether the field is required'
20425
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], SwitchInputFieldModel.prototype, "required", void 0);
20426
+ __decorate([Field({
20427
+ defaultValue: false
20428
+ }), Editor({
20429
+ field_type: FieldType.BOOLEAN,
20430
+ label: 'Disabled',
20431
+ description: 'Whether the field is disabled'
20432
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], SwitchInputFieldModel.prototype, "disabled", void 0);
20433
+ __decorate([Field(), Editor({
20434
+ field_type: FieldType.TEXT,
20435
+ label: 'Error',
20436
+ description: 'Error message to display'
20437
+ }), IsOptional(), IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "error", void 0);
20438
+ __decorate([Field(), Editor({
20439
+ field_type: FieldType.TEXT,
20440
+ label: 'Helper Text',
20441
+ description: 'Helper text to display below the switch'
20442
+ }), IsOptional(), IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "helperText", void 0);
20443
+ __decorate([Field({
20444
+ defaultValue: 'medium'
20445
+ }), Editor({
20446
+ field_type: FieldType.SELECT,
20447
+ label: 'Size',
20448
+ description: 'Size of the switch'
20449
+ }), IsOptional(), IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "size", void 0);
20450
+ __decorate([Field({
20451
+ defaultValue: 'primary'
20452
+ }), Editor({
20453
+ field_type: FieldType.SELECT,
20454
+ label: 'Color',
20455
+ description: 'Color theme of the switch'
20456
+ }), IsOptional(), IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "color", void 0);
20457
+ SwitchInputFieldModel = __decorate([Schema('SwitchInputField', '1.0.0')], SwitchInputFieldModel);
20458
+ var SwitchInputFieldModel$1 = SwitchInputFieldModel;
20459
+
20460
+ // View component - handles the actual rendering
20461
+ function SwitchInputFieldView({
20462
+ label,
20463
+ checked = false,
20464
+ onChange,
20465
+ onFocus,
20466
+ required = false,
20467
+ disabled = false,
20468
+ error,
20469
+ helperText,
20470
+ size = 'medium',
20471
+ color = 'primary',
20472
+ ...restProps
20473
+ }) {
20474
+ const {
20475
+ styleProps,
20476
+ htmlProps
20477
+ } = useBaseProps(restProps);
20478
+ const handleChange = event => {
20479
+ if (onChange) {
20480
+ onChange(event.target.checked);
20481
+ }
20482
+ };
20483
+ return jsxs(FormControl, {
20484
+ ...htmlProps,
20485
+ ...styleProps,
20486
+ error: !!error,
20487
+ required: required,
20488
+ disabled: disabled,
20489
+ sx: {
20490
+ display: 'block',
20491
+ ...styleProps.sx
20492
+ },
20493
+ children: [jsx(FormControlLabel, {
20494
+ control: jsx(Switch, {
20495
+ checked: checked,
20496
+ onChange: handleChange,
20497
+ onFocus: onFocus,
20498
+ size: size,
20499
+ color: color,
20500
+ disabled: disabled
20501
+ }),
20502
+ label: label,
20503
+ disabled: disabled
20504
+ }), (error || helperText) && jsx(FormHelperText, {
20505
+ children: error || helperText
20506
+ })]
20507
+ });
20508
+ }
20509
+ /**
20510
+ * SwitchInputField component with data binding support
20511
+ * Supports both traditional props and dataSource-driven rendering
20512
+ */
20513
+ function SwitchInputField(props) {
20514
+ const {
20515
+ dataSource,
20516
+ bindingOptions,
20517
+ ...restProps
20518
+ } = props;
20519
+ // If no dataSource, use traditional props
20520
+ if (!dataSource) {
20521
+ return jsx(SwitchInputFieldView, {
20522
+ ...restProps
20523
+ });
20524
+ }
20525
+ // Use data binding
20526
+ const bindingResult = useDataBinding(dataSource, restProps, SwitchInputFieldModel$1.getSchema(), {
20527
+ cache: true,
20528
+ cacheTTL: 300000,
20529
+ strict: false,
20530
+ ...bindingOptions
20531
+ });
20532
+ // Check if we're still loading data using the metadata properties
20533
+ const bindingLoading = bindingResult.$loading;
20534
+ // Extract all the actual switch properties (excluding metadata)
20535
+ const {
20536
+ dataSource: _source,
20537
+ $loading,
20538
+ $error,
20539
+ $dataSource,
20540
+ $cached,
20541
+ cached,
20542
+ ...switchInputFieldProps
20543
+ } = bindingResult;
20544
+ const error = bindingResult.$error;
20545
+ // Show loading state while fetching data
20546
+ if (bindingLoading) {
20547
+ return jsxs(Paper, {
20548
+ variant: "outlined",
20549
+ sx: {
20550
+ p: 2,
20551
+ textAlign: 'center'
20552
+ },
20553
+ children: [jsx(Typography, {
20554
+ variant: "body2",
20555
+ children: "Loading SwitchInputField..."
20556
+ }), jsx(Typography, {
20557
+ variant: "caption",
20558
+ color: "text.secondary",
20559
+ children: "Loading switch field configuration from data source..."
20560
+ })]
20561
+ });
20562
+ }
20563
+ if (error) {
20564
+ console.error('Error loading switch input field:', error);
20565
+ {
20566
+ return jsx(Paper, {
20567
+ variant: "outlined",
20568
+ sx: {
20569
+ p: 2,
20570
+ textAlign: 'center',
20571
+ borderColor: 'error.main'
20572
+ },
20573
+ children: jsxs(Typography, {
20574
+ variant: "body2",
20575
+ color: "error",
20576
+ children: ["Error loading switch field: ", error.message]
20577
+ })
20578
+ });
20579
+ }
20580
+ }
20581
+ return jsx(SwitchInputFieldView, {
20582
+ ...switchInputFieldProps
20583
+ });
20584
+ }
20585
+ // Mark as QwickApp component
20586
+ SwitchInputField[QWICKAPP_COMPONENT] = true;
20587
+
19730
20588
  const TextField = /*#__PURE__*/React.forwardRef((props, ref) => {
19731
20589
  const {
19732
20590
  gridProps,
@@ -20223,7 +21081,7 @@ const FormPage = ({
20223
21081
  title: title,
20224
21082
  description: description,
20225
21083
  coverImage: coverImage,
20226
- form: form,
21084
+ children: form,
20227
21085
  footer: footer,
20228
21086
  status: status,
20229
21087
  message: message,
@@ -25006,4 +25864,4 @@ var ActionType;
25006
25864
  ActionType["CANCEL"] = "cancel";
25007
25865
  })(ActionType || (ActionType = {}));
25008
25866
 
25009
- export { AVAILABLE_PALETTES, AccessibilityProvider, ActionModel, ActionType, AllPalettes, Article, ArticleModel, BasePage, Breadcrumbs, Button, CardListGrid, CardListGridModel, ChoiceInputField, ChoiceInputFieldModel, Code, CodeModel, Content, ContentModel, CoverImageHeader, CoverImageHeaderModel, DataProvider, DataProxy, DimensionsProvider, ErrorBoundary, FeatureCard, FeatureCardActionModel, FeatureCardModel, FeatureGrid, FeatureGridModel, FeatureItemModel, Footer, FooterItemModel, FooterModel, FooterSectionModel, FormBlock, FormBlockModel, FormMethod, FormPage, GridCell, GridLayout, HeaderActionModel, HeroBlock, HeroBlockModel, Html, HtmlInputField, Logo, Markdown, MetadataItemModel, Page, PageBannerHeader, PageBannerHeaderModel, PaletteAutumn, PaletteCosmic, PaletteDefault, PaletteOcean, PaletteProvider, PaletteSpring, PaletteSwitcher, PaletteSwitcherModel, PaletteWinter, ProductCard, ProductCardActionModel, ProductCardModel, ProductModel, QWICKAPP_COMPONENT, QwickApp, QwickAppsLogo, SafeSpan, SafeSpanModel, Section, SectionModel, SelectInputField, T, TextField, TextInputField, TextInputFieldModel, ThemeProvider, ThemeSwitcher, ThemeSwitcherModel, applyCustomPalette, clearUserPalettePreference, clearUserThemePreference, createLogger, createPaletteFromCurrentTheme, deleteCustomPalette, exportPalette, getCSSVariable, getComputedTheme, getCurrentPalette, getCurrentTheme, getCustomPalettes, getPaletteConfig, getPaletteName, getSystemTheme, getThemePerformanceStats, importPalette, initializePalette, initializeTheme, loadUserPalettePreference, loadUserThemePreference, logThemePerformanceStats, loggers, resetThemePerformanceStats, resolveDimension, resolveDimensions, resolveSpacing, resolveSpacingProps, saveCustomPalette, savePalettePreference, saveThemePreference, saveUserPalettePreference, saveUserThemePreference, setCSSVariable, setPalette, setTheme, t, useAccessibility, useBaseProps, useBreadcrumbs, useData, useDataBinding, useDataContext, useDataProvider, useDimensions, usePalette, useQwickApp, useResolveTemplate, useSafeLocation, useSafeNavigate, useTemplate, useTheme, withAccessibility, withErrorBoundary };
25867
+ export { AVAILABLE_PALETTES, AccessibilityProvider, ActionModel, ActionType, AllPalettes, Article, ArticleModel, BasePage, Breadcrumbs, Button, CardListGrid, CardListGridModel, ChoiceInputField, ChoiceInputFieldModel, Code, CodeModel, CollapsibleLayout, CollapsibleLayoutView, Content, ContentModel, CoverImageHeader, CoverImageHeaderModel, DataProvider, DataProxy, DimensionsProvider, ErrorBoundary, FeatureCard, FeatureCardActionModel, FeatureCardModel, FeatureGrid, FeatureGridModel, FeatureItemModel, Footer, FooterItemModel, FooterModel, FooterSectionModel, FormBlock, FormBlockModel, FormMethod, FormPage, GridCell, GridLayout, HeaderActionModel, HeroBlock, HeroBlockModel, Html, HtmlInputField, Logo, Markdown, MetadataItemModel, Page, PageBannerHeader, PageBannerHeaderModel, PaletteAutumn, PaletteCosmic, PaletteDefault, PaletteOcean, PaletteProvider, PaletteSpring, PaletteSwitcher, PaletteSwitcherModel, PaletteWinter, ProductCard, ProductCardActionModel, ProductCardModel, ProductModel, QWICKAPP_COMPONENT, QwickApp, QwickAppsLogo, SafeSpan, SafeSpanModel, Section, SectionModel, SelectInputField, SwitchInputField, T, TextField, TextInputField, TextInputFieldModel, ThemeProvider, ThemeSwitcher, ThemeSwitcherModel, animationConfigs, applyCustomPalette, clearUserPalettePreference, clearUserThemePreference, createLogger, createPaletteFromCurrentTheme, defaultCollapsibleLayoutProps, deleteCustomPalette, exportPalette, getCSSVariable, getComputedTheme, getCurrentPalette, getCurrentTheme, getCustomPalettes, getPaletteConfig, getPaletteName, getSystemTheme, getThemePerformanceStats, importPalette, initializePalette, initializeTheme, isCollapsibleLayoutProps, loadUserPalettePreference, loadUserThemePreference, logThemePerformanceStats, loggers, resetThemePerformanceStats, resolveDimension, resolveDimensions, resolveSpacing, resolveSpacingProps, saveCustomPalette, savePalettePreference, saveThemePreference, saveUserPalettePreference, saveUserThemePreference, setCSSVariable, setPalette, setTheme, spacingConfigs, t, useAccessibility, useBaseProps, useBreadcrumbs, useCollapsibleState, useData, useDataBinding, useDataContext, useDataProvider, useDimensions, usePalette, useQwickApp, useResolveTemplate, useSafeLocation, useSafeNavigate, useTemplate, useTheme, withAccessibility, withErrorBoundary };