@qwickapps/react-framework 1.3.3 → 1.3.4

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 (37) hide show
  1. package/README.md +220 -0
  2. package/dist/components/forms/FormBlock.d.ts +1 -1
  3. package/dist/components/forms/FormBlock.d.ts.map +1 -1
  4. package/dist/components/input/SwitchInputField.d.ts +28 -0
  5. package/dist/components/input/SwitchInputField.d.ts.map +1 -0
  6. package/dist/components/input/index.d.ts +2 -0
  7. package/dist/components/input/index.d.ts.map +1 -1
  8. package/dist/components/layout/CollapsibleLayout/CollapsibleLayout.d.ts +34 -0
  9. package/dist/components/layout/CollapsibleLayout/CollapsibleLayout.d.ts.map +1 -0
  10. package/dist/components/layout/CollapsibleLayout/index.d.ts +9 -0
  11. package/dist/components/layout/CollapsibleLayout/index.d.ts.map +1 -0
  12. package/dist/components/layout/index.d.ts +2 -0
  13. package/dist/components/layout/index.d.ts.map +1 -1
  14. package/dist/index.esm.js +876 -6
  15. package/dist/index.js +880 -2
  16. package/dist/schemas/CollapsibleLayoutSchema.d.ts +31 -0
  17. package/dist/schemas/CollapsibleLayoutSchema.d.ts.map +1 -0
  18. package/dist/schemas/SwitchInputFieldSchema.d.ts +18 -0
  19. package/dist/schemas/SwitchInputFieldSchema.d.ts.map +1 -0
  20. package/dist/types/CollapsibleLayout.d.ts +142 -0
  21. package/dist/types/CollapsibleLayout.d.ts.map +1 -0
  22. package/dist/types/index.d.ts +1 -0
  23. package/dist/types/index.d.ts.map +1 -1
  24. package/package.json +1 -1
  25. package/src/components/forms/FormBlock.tsx +2 -2
  26. package/src/components/input/SwitchInputField.tsx +165 -0
  27. package/src/components/input/index.ts +2 -0
  28. package/src/components/layout/CollapsibleLayout/CollapsibleLayout.tsx +554 -0
  29. package/src/components/layout/CollapsibleLayout/__tests__/CollapsibleLayout.test.tsx +1469 -0
  30. package/src/components/layout/CollapsibleLayout/index.tsx +17 -0
  31. package/src/components/layout/index.ts +4 -1
  32. package/src/components/pages/FormPage.tsx +1 -1
  33. package/src/schemas/CollapsibleLayoutSchema.ts +276 -0
  34. package/src/schemas/SwitchInputFieldSchema.ts +99 -0
  35. package/src/stories/CollapsibleLayout.stories.tsx +1566 -0
  36. package/src/types/CollapsibleLayout.ts +231 -0
  37. package/src/types/index.ts +1 -0
package/dist/index.js CHANGED
@@ -15336,6 +15336,689 @@ const GridCell = props => {
15336
15336
  };
15337
15337
  GridCell.displayName = 'GridCell';
15338
15338
 
15339
+ /**
15340
+ * CollapsibleLayout Schema - Data model for collapsible layout component
15341
+ *
15342
+ * Advanced expandable/collapsible container with header controls, animations,
15343
+ * content management, and state persistence capabilities.
15344
+ *
15345
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
15346
+ */
15347
+ let CollapsibleLayoutModel = class CollapsibleLayoutModel extends schema.Model {};
15348
+ __decorate([schema.Field({
15349
+ defaultValue: false
15350
+ }), schema.Editor({
15351
+ field_type: schema.FieldType.BOOLEAN,
15352
+ label: 'Collapsed',
15353
+ description: 'Whether the layout is currently collapsed'
15354
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "collapsed", void 0);
15355
+ __decorate([schema.Field({
15356
+ defaultValue: false
15357
+ }), schema.Editor({
15358
+ field_type: schema.FieldType.BOOLEAN,
15359
+ label: 'Default Collapsed',
15360
+ description: 'Initial collapsed state for uncontrolled usage'
15361
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "defaultCollapsed", void 0);
15362
+ __decorate([schema.Field(), schema.Editor({
15363
+ field_type: schema.FieldType.TEXT,
15364
+ label: 'Title',
15365
+ description: 'Main title displayed in the header',
15366
+ placeholder: 'Enter title...'
15367
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "title", void 0);
15368
+ __decorate([schema.Field(), schema.Editor({
15369
+ field_type: schema.FieldType.TEXT,
15370
+ label: 'Subtitle',
15371
+ description: 'Secondary text displayed below the title',
15372
+ placeholder: 'Enter subtitle...'
15373
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "subtitle", void 0);
15374
+ __decorate([schema.Field(), schema.Editor({
15375
+ field_type: schema.FieldType.TEXT,
15376
+ label: 'Lead Icon',
15377
+ description: 'Icon displayed before the title (icon identifier or HTML)',
15378
+ placeholder: 'Icon identifier...'
15379
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "leadIcon", void 0);
15380
+ __decorate([schema.Field(), schema.Editor({
15381
+ field_type: schema.FieldType.TEXTAREA,
15382
+ label: 'Header Actions',
15383
+ description: 'Additional controls displayed in header (HTML/React content)',
15384
+ placeholder: 'Enter header actions HTML...'
15385
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "headerActions", void 0);
15386
+ __decorate([schema.Field(), schema.Editor({
15387
+ field_type: schema.FieldType.TEXTAREA,
15388
+ label: 'Collapsed View',
15389
+ description: 'Summary content shown when collapsed (HTML supported)',
15390
+ placeholder: 'Enter collapsed view content...'
15391
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "collapsedView", void 0);
15392
+ __decorate([schema.Field(), schema.Editor({
15393
+ field_type: schema.FieldType.TEXTAREA,
15394
+ label: 'Content',
15395
+ description: 'Main content shown when expanded (HTML supported)',
15396
+ placeholder: 'Enter main content...'
15397
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "children", void 0);
15398
+ __decorate([schema.Field(), schema.Editor({
15399
+ field_type: schema.FieldType.TEXTAREA,
15400
+ label: 'Footer View',
15401
+ description: 'Always visible footer content (HTML supported)',
15402
+ placeholder: 'Enter footer content...'
15403
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "footerView", void 0);
15404
+ __decorate([schema.Field({
15405
+ defaultValue: 'header'
15406
+ }), schema.Editor({
15407
+ field_type: schema.FieldType.SELECT,
15408
+ label: 'Trigger Area',
15409
+ description: 'Area that responds to clicks for toggle functionality',
15410
+ validation: {
15411
+ options: [{
15412
+ label: 'Button Only',
15413
+ value: 'button'
15414
+ }, {
15415
+ label: 'Header Area',
15416
+ value: 'header'
15417
+ }, {
15418
+ label: 'Button and Header',
15419
+ value: 'both'
15420
+ }]
15421
+ }
15422
+ }), classValidator.IsOptional(), classValidator.IsIn(['button', 'header', 'both']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "triggerArea", void 0);
15423
+ __decorate([schema.Field({
15424
+ defaultValue: 'slide'
15425
+ }), schema.Editor({
15426
+ field_type: schema.FieldType.SELECT,
15427
+ label: 'Animation Style',
15428
+ description: 'Animation variant for expand/collapse transitions',
15429
+ validation: {
15430
+ options: [{
15431
+ label: 'Fade',
15432
+ value: 'fade'
15433
+ }, {
15434
+ label: 'Slide',
15435
+ value: 'slide'
15436
+ }, {
15437
+ label: 'Scale',
15438
+ value: 'scale'
15439
+ }]
15440
+ }
15441
+ }), classValidator.IsOptional(), classValidator.IsIn(['fade', 'slide', 'scale']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "animationStyle", void 0);
15442
+ __decorate([schema.Field({
15443
+ defaultValue: false
15444
+ }), schema.Editor({
15445
+ field_type: schema.FieldType.BOOLEAN,
15446
+ label: 'Persist State',
15447
+ description: 'Save collapse state in local storage'
15448
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "persistState", void 0);
15449
+ __decorate([schema.Field(), schema.Editor({
15450
+ field_type: schema.FieldType.TEXT,
15451
+ label: 'Collapsed Icon',
15452
+ description: 'Icon shown when content is collapsed (default: VisibilityIcon)',
15453
+ placeholder: 'Icon identifier...'
15454
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "collapsedIcon", void 0);
15455
+ __decorate([schema.Field(), schema.Editor({
15456
+ field_type: schema.FieldType.TEXT,
15457
+ label: 'Expanded Icon',
15458
+ description: 'Icon shown when content is expanded (default: VisibilityOffIcon)',
15459
+ placeholder: 'Icon identifier...'
15460
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "expandedIcon", void 0);
15461
+ __decorate([schema.Field({
15462
+ defaultValue: true
15463
+ }), schema.Editor({
15464
+ field_type: schema.FieldType.BOOLEAN,
15465
+ label: 'Show Divider',
15466
+ description: 'Show divider lines between header, content, and footer sections'
15467
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "showDivider", void 0);
15468
+ __decorate([schema.Field({
15469
+ defaultValue: 'default'
15470
+ }), schema.Editor({
15471
+ field_type: schema.FieldType.SELECT,
15472
+ label: 'Variant',
15473
+ description: 'Visual style variant for the layout container',
15474
+ validation: {
15475
+ options: [{
15476
+ label: 'Default',
15477
+ value: 'default'
15478
+ }, {
15479
+ label: 'Outlined',
15480
+ value: 'outlined'
15481
+ }, {
15482
+ label: 'Elevated',
15483
+ value: 'elevated'
15484
+ }, {
15485
+ label: 'Filled',
15486
+ value: 'filled'
15487
+ }]
15488
+ }
15489
+ }), classValidator.IsOptional(), classValidator.IsIn(['default', 'outlined', 'elevated', 'filled']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "variant", void 0);
15490
+ __decorate([schema.Field({
15491
+ defaultValue: 'comfortable'
15492
+ }), schema.Editor({
15493
+ field_type: schema.FieldType.SELECT,
15494
+ label: 'Header Spacing',
15495
+ description: 'Padding/spacing within the header area',
15496
+ validation: {
15497
+ options: [{
15498
+ label: 'Compact',
15499
+ value: 'compact'
15500
+ }, {
15501
+ label: 'Comfortable',
15502
+ value: 'comfortable'
15503
+ }, {
15504
+ label: 'Spacious',
15505
+ value: 'spacious'
15506
+ }]
15507
+ }
15508
+ }), classValidator.IsOptional(), classValidator.IsIn(['compact', 'comfortable', 'spacious']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "headerSpacing", void 0);
15509
+ __decorate([schema.Field({
15510
+ defaultValue: 'comfortable'
15511
+ }), schema.Editor({
15512
+ field_type: schema.FieldType.SELECT,
15513
+ label: 'Content Spacing',
15514
+ description: 'Padding/spacing within the content area',
15515
+ validation: {
15516
+ options: [{
15517
+ label: 'Compact',
15518
+ value: 'compact'
15519
+ }, {
15520
+ label: 'Comfortable',
15521
+ value: 'comfortable'
15522
+ }, {
15523
+ label: 'Spacious',
15524
+ value: 'spacious'
15525
+ }]
15526
+ }
15527
+ }), classValidator.IsOptional(), classValidator.IsIn(['compact', 'comfortable', 'spacious']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "contentSpacing", void 0);
15528
+ CollapsibleLayoutModel = __decorate([schema.Schema('CollapsibleLayout', '1.0.0')], CollapsibleLayoutModel);
15529
+ var CollapsibleLayoutModel$1 = CollapsibleLayoutModel;
15530
+
15531
+ /**
15532
+ * TypeScript type definitions for CollapsibleLayout component
15533
+ *
15534
+ * Provides TypeScript interfaces that extend the schema model with React-specific types
15535
+ * and component-level functionality for the CollapsibleLayout component.
15536
+ *
15537
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
15538
+ */
15539
+ /**
15540
+ * Type guard to check if a component has CollapsibleLayout props
15541
+ */
15542
+ function isCollapsibleLayoutProps(props) {
15543
+ return props && typeof props === 'object' && ('collapsed' in props || 'defaultCollapsed' in props);
15544
+ }
15545
+ /**
15546
+ * Default props for CollapsibleLayout component
15547
+ */
15548
+ const defaultCollapsibleLayoutProps = {
15549
+ // Note: collapsed is intentionally omitted so components can be uncontrolled
15550
+ defaultCollapsed: false,
15551
+ triggerArea: 'both',
15552
+ animationStyle: 'slide',
15553
+ persistState: false,
15554
+ showDivider: true,
15555
+ variant: 'default',
15556
+ headerSpacing: 'comfortable',
15557
+ contentSpacing: 'comfortable',
15558
+ animationDuration: 300,
15559
+ disableAnimations: false,
15560
+ toggleAriaLabel: 'Toggle content visibility'
15561
+ };
15562
+ const animationConfigs = {
15563
+ fade: {
15564
+ duration: 300,
15565
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
15566
+ opacity: [0, 1]
15567
+ },
15568
+ slide: {
15569
+ duration: 300,
15570
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
15571
+ transform: 'translateY(-10px)'
15572
+ },
15573
+ scale: {
15574
+ duration: 200,
15575
+ easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)',
15576
+ transform: 'scale(0.95)',
15577
+ opacity: [0, 1]
15578
+ }
15579
+ };
15580
+ const spacingConfigs = {
15581
+ compact: {
15582
+ padding: '8px 12px',
15583
+ gap: '4px'
15584
+ },
15585
+ comfortable: {
15586
+ padding: '16px 20px',
15587
+ gap: '8px'
15588
+ },
15589
+ spacious: {
15590
+ padding: '24px 32px',
15591
+ gap: '16px'
15592
+ }
15593
+ };
15594
+
15595
+ /**
15596
+ * Custom hook for managing collapsible state - simplified approach
15597
+ */
15598
+ function useCollapsibleState(controlled, collapsedProp, defaultCollapsedProp, onToggleProp, persistState, storageKey) {
15599
+ const id = React.useId();
15600
+ const finalStorageKey = storageKey || `collapsible-${id}`;
15601
+ // For controlled components, use the prop; for uncontrolled, use internal state
15602
+ const [internalCollapsed, setInternalCollapsed] = React.useState(() => {
15603
+ if (controlled) {
15604
+ return collapsedProp ?? false;
15605
+ }
15606
+ // Try localStorage first if persistence is enabled
15607
+ if (persistState && typeof window !== 'undefined') {
15608
+ const stored = localStorage.getItem(finalStorageKey);
15609
+ if (stored !== null) {
15610
+ return JSON.parse(stored);
15611
+ }
15612
+ }
15613
+ return defaultCollapsedProp ?? false;
15614
+ });
15615
+ // Sync with controlled prop changes
15616
+ React.useEffect(() => {
15617
+ if (controlled && collapsedProp !== undefined) {
15618
+ setInternalCollapsed(collapsedProp);
15619
+ }
15620
+ }, [controlled, collapsedProp]);
15621
+ // Persist to localStorage for uncontrolled components
15622
+ React.useEffect(() => {
15623
+ if (!controlled && persistState && typeof window !== 'undefined') {
15624
+ localStorage.setItem(finalStorageKey, JSON.stringify(internalCollapsed));
15625
+ }
15626
+ }, [controlled, internalCollapsed, persistState, finalStorageKey]);
15627
+ const toggle = React.useCallback(() => {
15628
+ const currentState = controlled ? collapsedProp ?? false : internalCollapsed;
15629
+ const newCollapsed = !currentState;
15630
+ // Always update internal state for visual updates
15631
+ setInternalCollapsed(newCollapsed);
15632
+ // Call callback to notify parent
15633
+ onToggleProp?.(newCollapsed);
15634
+ }, [controlled, collapsedProp, internalCollapsed, onToggleProp]);
15635
+ const setCollapsed = React.useCallback(collapsed => {
15636
+ setInternalCollapsed(collapsed);
15637
+ onToggleProp?.(collapsed);
15638
+ }, [onToggleProp]);
15639
+ // Return the appropriate state
15640
+ const finalCollapsed = controlled ? collapsedProp ?? false : internalCollapsed;
15641
+ return {
15642
+ collapsed: finalCollapsed,
15643
+ toggle,
15644
+ setCollapsed,
15645
+ isControlled: controlled
15646
+ };
15647
+ }
15648
+ /**
15649
+ * Core CollapsibleLayout View component
15650
+ */
15651
+ function CollapsibleLayoutView({
15652
+ // State props
15653
+ collapsed: collapsedProp,
15654
+ defaultCollapsed = false,
15655
+ onToggle,
15656
+ // Content props
15657
+ title,
15658
+ subtitle,
15659
+ leadIcon,
15660
+ headerActions,
15661
+ collapsedView,
15662
+ children,
15663
+ footerView,
15664
+ // Behavior props
15665
+ triggerArea = 'both',
15666
+ animationStyle = 'slide',
15667
+ persistState = false,
15668
+ storageKey,
15669
+ animationDuration = 300,
15670
+ disableAnimations = false,
15671
+ // Icons
15672
+ collapsedIcon,
15673
+ expandedIcon,
15674
+ // Layout props
15675
+ showDivider = true,
15676
+ variant = 'default',
15677
+ headerSpacing = 'comfortable',
15678
+ contentSpacing = 'comfortable',
15679
+ // Accessibility
15680
+ toggleAriaLabel = 'Toggle content visibility',
15681
+ 'aria-describedby': ariaDescribedBy,
15682
+ contentAriaProps = {},
15683
+ // CSS classes
15684
+ containerClassName,
15685
+ headerClassName,
15686
+ contentClassName,
15687
+ footerClassName,
15688
+ ...restProps
15689
+ }) {
15690
+ const theme = material.useTheme();
15691
+ const {
15692
+ styleProps,
15693
+ htmlProps,
15694
+ restProps: otherProps
15695
+ } = useBaseProps(restProps);
15696
+ // Mark as QwickApp component
15697
+ CollapsibleLayoutView[QWICKAPP_COMPONENT] = true;
15698
+ // Determine controlled vs uncontrolled usage
15699
+ const controlled = collapsedProp !== undefined;
15700
+ // State management
15701
+ const {
15702
+ collapsed,
15703
+ toggle,
15704
+ setCollapsed
15705
+ } = useCollapsibleState(controlled, collapsedProp, defaultCollapsed, onToggle, persistState, storageKey);
15706
+ // Get spacing configurations
15707
+ const headerSpacingConfig = spacingConfigs[headerSpacing];
15708
+ const contentSpacingConfig = spacingConfigs[contentSpacing];
15709
+ // Get animation configuration
15710
+ const animationConfig = animationConfigs[animationStyle];
15711
+ // Generate unique IDs for accessibility
15712
+ const headerId = React.useId();
15713
+ const contentId = React.useId();
15714
+ // Handle click events
15715
+ const handleHeaderClick = React.useCallback(event => {
15716
+ if (triggerArea === 'header' || triggerArea === 'both') {
15717
+ event.preventDefault();
15718
+ toggle();
15719
+ }
15720
+ }, [triggerArea, toggle]);
15721
+ const handleButtonClick = React.useCallback(event => {
15722
+ event.stopPropagation();
15723
+ toggle();
15724
+ }, [toggle]);
15725
+ // Render icons
15726
+ const renderIcon = React.useCallback((icon, defaultIcon) => {
15727
+ if (/*#__PURE__*/React.isValidElement(icon)) {
15728
+ return icon;
15729
+ }
15730
+ if (typeof icon === 'string') {
15731
+ return jsxRuntime.jsx(Html, {
15732
+ children: icon
15733
+ });
15734
+ }
15735
+ return defaultIcon;
15736
+ }, []);
15737
+ const toggleIcon = renderIcon(collapsed ? collapsedIcon : expandedIcon, collapsed ? jsxRuntime.jsx(iconsMaterial.ExpandMore, {}) : jsxRuntime.jsx(iconsMaterial.ExpandLess, {}));
15738
+ // Container styles based on variant
15739
+ const containerSx = React.useMemo(() => {
15740
+ const baseSx = {
15741
+ width: '100%',
15742
+ position: 'relative',
15743
+ ...styleProps.sx
15744
+ };
15745
+ switch (variant) {
15746
+ case 'outlined':
15747
+ return {
15748
+ ...baseSx,
15749
+ border: `1px solid ${theme.palette.divider}`,
15750
+ borderRadius: 1,
15751
+ backgroundColor: 'var(--theme-surface)'
15752
+ };
15753
+ case 'elevated':
15754
+ return {
15755
+ ...baseSx,
15756
+ boxShadow: theme.shadows[2],
15757
+ borderRadius: 1,
15758
+ backgroundColor: theme.palette.background.paper
15759
+ };
15760
+ case 'filled':
15761
+ return {
15762
+ ...baseSx,
15763
+ backgroundColor: 'var(--theme-surface-variant)',
15764
+ borderRadius: 1
15765
+ };
15766
+ default:
15767
+ return baseSx;
15768
+ }
15769
+ }, [variant, theme, styleProps.sx]);
15770
+ // Header styles
15771
+ const headerSx = React.useMemo(() => ({
15772
+ ...headerSpacingConfig,
15773
+ cursor: triggerArea === 'header' || triggerArea === 'both' ? 'pointer' : 'default',
15774
+ userSelect: 'none',
15775
+ display: 'flex',
15776
+ alignItems: 'center',
15777
+ justifyContent: 'space-between',
15778
+ '&:hover': triggerArea === 'header' || triggerArea === 'both' ? {
15779
+ backgroundColor: 'rgba(0, 0, 0, 0.04)'
15780
+ } : {}
15781
+ }), [headerSpacingConfig, triggerArea]);
15782
+ // Content styles
15783
+ const contentSx = React.useMemo(() => ({
15784
+ ...contentSpacingConfig
15785
+ }), [contentSpacingConfig]);
15786
+ // Animation props for Collapse component
15787
+ const collapseProps = React.useMemo(() => {
15788
+ if (disableAnimations) {
15789
+ return {
15790
+ timeout: 0
15791
+ };
15792
+ }
15793
+ const baseProps = {
15794
+ timeout: animationDuration
15795
+ };
15796
+ switch (animationStyle) {
15797
+ case 'fade':
15798
+ return {
15799
+ ...baseProps,
15800
+ sx: {
15801
+ '& .MuiCollapse-wrapper': {
15802
+ opacity: collapsed ? 0 : 1,
15803
+ transition: `opacity ${animationDuration}ms ${animationConfig.easing}`
15804
+ }
15805
+ }
15806
+ };
15807
+ case 'scale':
15808
+ return {
15809
+ ...baseProps,
15810
+ sx: {
15811
+ '& .MuiCollapse-wrapper': {
15812
+ transform: collapsed ? 'scale(0.95)' : 'scale(1)',
15813
+ opacity: collapsed ? 0 : 1,
15814
+ transition: `all ${animationDuration}ms ${animationConfig.easing}`
15815
+ }
15816
+ }
15817
+ };
15818
+ default:
15819
+ // slide
15820
+ return baseProps;
15821
+ }
15822
+ }, [disableAnimations, animationDuration, animationStyle, animationConfig, collapsed]);
15823
+ // Render content based on type
15824
+ const renderContent = React.useCallback(content => {
15825
+ if (!content) return null;
15826
+ if (typeof content === 'string') {
15827
+ return jsxRuntime.jsx(Html, {
15828
+ children: content
15829
+ });
15830
+ }
15831
+ return content;
15832
+ }, []);
15833
+ // Container content that will be wrapped
15834
+ const containerContent = jsxRuntime.jsxs(jsxRuntime.Fragment, {
15835
+ children: [(title || subtitle || leadIcon || headerActions || triggerArea === 'button' || triggerArea === 'both') && jsxRuntime.jsxs(jsxRuntime.Fragment, {
15836
+ children: [jsxRuntime.jsxs(material.Box, {
15837
+ id: headerId,
15838
+ className: headerClassName,
15839
+ sx: headerSx,
15840
+ onClick: handleHeaderClick,
15841
+ role: triggerArea === 'header' || triggerArea === 'both' ? 'button' : undefined,
15842
+ tabIndex: triggerArea === 'header' || triggerArea === 'both' ? 0 : undefined,
15843
+ "aria-expanded": !collapsed,
15844
+ "aria-controls": contentId,
15845
+ "aria-describedby": ariaDescribedBy,
15846
+ onKeyDown: e => {
15847
+ if ((triggerArea === 'header' || triggerArea === 'both') && (e.key === 'Enter' || e.key === ' ')) {
15848
+ e.preventDefault();
15849
+ toggle();
15850
+ }
15851
+ },
15852
+ children: [jsxRuntime.jsxs(material.Stack, {
15853
+ direction: "row",
15854
+ spacing: 2,
15855
+ alignItems: "center",
15856
+ sx: {
15857
+ minWidth: 0,
15858
+ flex: 1
15859
+ },
15860
+ children: [leadIcon && jsxRuntime.jsx(material.Box, {
15861
+ sx: {
15862
+ flexShrink: 0
15863
+ },
15864
+ children: renderContent(leadIcon)
15865
+ }), (title || subtitle) && jsxRuntime.jsxs(material.Box, {
15866
+ sx: {
15867
+ minWidth: 0,
15868
+ flex: 1
15869
+ },
15870
+ children: [title && jsxRuntime.jsx(material.Typography, {
15871
+ variant: "h6",
15872
+ component: "h3",
15873
+ sx: {
15874
+ fontWeight: 600,
15875
+ lineHeight: 1.2,
15876
+ ...(subtitle && {
15877
+ mb: 0.5
15878
+ })
15879
+ },
15880
+ children: title
15881
+ }), subtitle && jsxRuntime.jsx(material.Typography, {
15882
+ variant: "body2",
15883
+ color: "text.secondary",
15884
+ sx: {
15885
+ lineHeight: 1.3
15886
+ },
15887
+ children: subtitle
15888
+ })]
15889
+ })]
15890
+ }), jsxRuntime.jsxs(material.Stack, {
15891
+ direction: "row",
15892
+ spacing: 1,
15893
+ alignItems: "center",
15894
+ sx: {
15895
+ flexShrink: 0
15896
+ },
15897
+ children: [headerActions && jsxRuntime.jsx(material.Box, {
15898
+ children: renderContent(headerActions)
15899
+ }), jsxRuntime.jsx(material.IconButton, {
15900
+ onClick: handleButtonClick,
15901
+ size: "small",
15902
+ "aria-label": toggleAriaLabel,
15903
+ "aria-expanded": !collapsed,
15904
+ "aria-controls": contentId,
15905
+ children: toggleIcon
15906
+ })]
15907
+ })]
15908
+ }), showDivider && jsxRuntime.jsx(material.Divider, {})]
15909
+ }), collapsed && collapsedView && jsxRuntime.jsxs(jsxRuntime.Fragment, {
15910
+ children: [jsxRuntime.jsx(material.Box, {
15911
+ className: contentClassName,
15912
+ sx: contentSx,
15913
+ children: renderContent(collapsedView)
15914
+ }), showDivider && footerView && jsxRuntime.jsx(material.Divider, {})]
15915
+ }), jsxRuntime.jsxs(material.Collapse, {
15916
+ in: !collapsed,
15917
+ ...collapseProps,
15918
+ children: [jsxRuntime.jsx(material.Box, {
15919
+ id: contentId,
15920
+ className: contentClassName,
15921
+ sx: contentSx,
15922
+ role: "region",
15923
+ "aria-labelledby": title ? headerId : undefined,
15924
+ ...contentAriaProps,
15925
+ children: renderContent(children)
15926
+ }), showDivider && footerView && jsxRuntime.jsx(material.Divider, {})]
15927
+ }), footerView && jsxRuntime.jsx(material.Box, {
15928
+ className: footerClassName,
15929
+ sx: contentSx,
15930
+ children: renderContent(footerView)
15931
+ })]
15932
+ });
15933
+ // Return appropriate container based on variant
15934
+ if (variant === 'outlined') {
15935
+ return jsxRuntime.jsx(material.Paper, {
15936
+ variant: "outlined",
15937
+ elevation: 0,
15938
+ ...htmlProps,
15939
+ ...otherProps,
15940
+ className: containerClassName,
15941
+ sx: containerSx,
15942
+ children: containerContent
15943
+ });
15944
+ }
15945
+ if (variant === 'elevated') {
15946
+ return jsxRuntime.jsx(material.Paper, {
15947
+ elevation: 2,
15948
+ ...htmlProps,
15949
+ ...otherProps,
15950
+ className: containerClassName,
15951
+ sx: containerSx,
15952
+ children: containerContent
15953
+ });
15954
+ }
15955
+ // Default variant (default, filled)
15956
+ return jsxRuntime.jsx(material.Box, {
15957
+ ...htmlProps,
15958
+ ...otherProps,
15959
+ className: containerClassName,
15960
+ sx: containerSx,
15961
+ children: containerContent
15962
+ });
15963
+ }
15964
+ /**
15965
+ * Main CollapsibleLayout component with data binding support
15966
+ */
15967
+ function CollapsibleLayout(props) {
15968
+ const {
15969
+ dataSource,
15970
+ bindingOptions,
15971
+ ...restProps
15972
+ } = props;
15973
+ // If no dataSource, use traditional props
15974
+ if (!dataSource) {
15975
+ return jsxRuntime.jsx(CollapsibleLayoutView, {
15976
+ ...restProps
15977
+ });
15978
+ }
15979
+ // Use data binding
15980
+ const {
15981
+ dataSource: _source,
15982
+ loading,
15983
+ error,
15984
+ cached,
15985
+ ...collapsibleProps
15986
+ } = useDataBinding(dataSource, restProps, CollapsibleLayoutModel$1.getSchema(), {
15987
+ cache: true,
15988
+ cacheTTL: 300000,
15989
+ strict: false,
15990
+ ...bindingOptions
15991
+ });
15992
+ // Show loading state
15993
+ if (loading) {
15994
+ return jsxRuntime.jsx(CollapsibleLayoutView, {
15995
+ ...restProps,
15996
+ title: "Loading...",
15997
+ variant: "default",
15998
+ headerSpacing: "comfortable",
15999
+ contentSpacing: "comfortable"
16000
+ });
16001
+ }
16002
+ if (error) {
16003
+ console.error('Error loading collapsible layout:', error);
16004
+ {
16005
+ return jsxRuntime.jsx(CollapsibleLayoutView, {
16006
+ ...restProps,
16007
+ title: "Error Loading Layout",
16008
+ subtitle: error.message,
16009
+ variant: "outlined",
16010
+ headerSpacing: "comfortable",
16011
+ contentSpacing: "comfortable"
16012
+ });
16013
+ }
16014
+ }
16015
+ return jsxRuntime.jsx(CollapsibleLayoutView, {
16016
+ ...collapsibleProps
16017
+ });
16018
+ }
16019
+ // Set default props
16020
+ CollapsibleLayout.defaultProps = defaultCollapsibleLayoutProps;
16021
+
15339
16022
  /**
15340
16023
  * FeatureCard Schema - Schema definition for FeatureCard component
15341
16024
  *
@@ -18728,7 +19411,7 @@ function FormBlockView({
18728
19411
  title,
18729
19412
  description,
18730
19413
  coverImage,
18731
- form,
19414
+ children: form,
18732
19415
  footer,
18733
19416
  status,
18734
19417
  message,
@@ -19729,6 +20412,193 @@ function SelectInputField(props) {
19729
20412
  // Mark as QwickApp component
19730
20413
  SelectInputField[QWICKAPP_COMPONENT] = true;
19731
20414
 
20415
+ /**
20416
+ * SwitchInputField Schema - Data model for switch input field component
20417
+ *
20418
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
20419
+ */
20420
+ let SwitchInputFieldModel = class SwitchInputFieldModel extends schema.Model {};
20421
+ __decorate([schema.Field(), schema.Editor({
20422
+ field_type: schema.FieldType.TEXT,
20423
+ label: 'Label',
20424
+ description: 'The label text for the switch'
20425
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "label", void 0);
20426
+ __decorate([schema.Field({
20427
+ defaultValue: false
20428
+ }), schema.Editor({
20429
+ field_type: schema.FieldType.BOOLEAN,
20430
+ label: 'Checked',
20431
+ description: 'Whether the switch is checked'
20432
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], SwitchInputFieldModel.prototype, "checked", void 0);
20433
+ __decorate([schema.Field({
20434
+ defaultValue: false
20435
+ }), schema.Editor({
20436
+ field_type: schema.FieldType.BOOLEAN,
20437
+ label: 'Required',
20438
+ description: 'Whether the field is required'
20439
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], SwitchInputFieldModel.prototype, "required", void 0);
20440
+ __decorate([schema.Field({
20441
+ defaultValue: false
20442
+ }), schema.Editor({
20443
+ field_type: schema.FieldType.BOOLEAN,
20444
+ label: 'Disabled',
20445
+ description: 'Whether the field is disabled'
20446
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], SwitchInputFieldModel.prototype, "disabled", void 0);
20447
+ __decorate([schema.Field(), schema.Editor({
20448
+ field_type: schema.FieldType.TEXT,
20449
+ label: 'Error',
20450
+ description: 'Error message to display'
20451
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "error", void 0);
20452
+ __decorate([schema.Field(), schema.Editor({
20453
+ field_type: schema.FieldType.TEXT,
20454
+ label: 'Helper Text',
20455
+ description: 'Helper text to display below the switch'
20456
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "helperText", void 0);
20457
+ __decorate([schema.Field({
20458
+ defaultValue: 'medium'
20459
+ }), schema.Editor({
20460
+ field_type: schema.FieldType.SELECT,
20461
+ label: 'Size',
20462
+ description: 'Size of the switch'
20463
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "size", void 0);
20464
+ __decorate([schema.Field({
20465
+ defaultValue: 'primary'
20466
+ }), schema.Editor({
20467
+ field_type: schema.FieldType.SELECT,
20468
+ label: 'Color',
20469
+ description: 'Color theme of the switch'
20470
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "color", void 0);
20471
+ SwitchInputFieldModel = __decorate([schema.Schema('SwitchInputField', '1.0.0')], SwitchInputFieldModel);
20472
+ var SwitchInputFieldModel$1 = SwitchInputFieldModel;
20473
+
20474
+ // View component - handles the actual rendering
20475
+ function SwitchInputFieldView({
20476
+ label,
20477
+ checked = false,
20478
+ onChange,
20479
+ onFocus,
20480
+ required = false,
20481
+ disabled = false,
20482
+ error,
20483
+ helperText,
20484
+ size = 'medium',
20485
+ color = 'primary',
20486
+ ...restProps
20487
+ }) {
20488
+ const {
20489
+ styleProps,
20490
+ htmlProps
20491
+ } = useBaseProps(restProps);
20492
+ const handleChange = event => {
20493
+ if (onChange) {
20494
+ onChange(event.target.checked);
20495
+ }
20496
+ };
20497
+ return jsxRuntime.jsxs(material.FormControl, {
20498
+ ...htmlProps,
20499
+ ...styleProps,
20500
+ error: !!error,
20501
+ required: required,
20502
+ disabled: disabled,
20503
+ sx: {
20504
+ display: 'block',
20505
+ ...styleProps.sx
20506
+ },
20507
+ children: [jsxRuntime.jsx(material.FormControlLabel, {
20508
+ control: jsxRuntime.jsx(material.Switch, {
20509
+ checked: checked,
20510
+ onChange: handleChange,
20511
+ onFocus: onFocus,
20512
+ size: size,
20513
+ color: color,
20514
+ disabled: disabled
20515
+ }),
20516
+ label: label,
20517
+ disabled: disabled
20518
+ }), (error || helperText) && jsxRuntime.jsx(material.FormHelperText, {
20519
+ children: error || helperText
20520
+ })]
20521
+ });
20522
+ }
20523
+ /**
20524
+ * SwitchInputField component with data binding support
20525
+ * Supports both traditional props and dataSource-driven rendering
20526
+ */
20527
+ function SwitchInputField(props) {
20528
+ const {
20529
+ dataSource,
20530
+ bindingOptions,
20531
+ ...restProps
20532
+ } = props;
20533
+ // If no dataSource, use traditional props
20534
+ if (!dataSource) {
20535
+ return jsxRuntime.jsx(SwitchInputFieldView, {
20536
+ ...restProps
20537
+ });
20538
+ }
20539
+ // Use data binding
20540
+ const bindingResult = useDataBinding(dataSource, restProps, SwitchInputFieldModel$1.getSchema(), {
20541
+ cache: true,
20542
+ cacheTTL: 300000,
20543
+ strict: false,
20544
+ ...bindingOptions
20545
+ });
20546
+ // Check if we're still loading data using the metadata properties
20547
+ const bindingLoading = bindingResult.$loading;
20548
+ // Extract all the actual switch properties (excluding metadata)
20549
+ const {
20550
+ dataSource: _source,
20551
+ $loading,
20552
+ $error,
20553
+ $dataSource,
20554
+ $cached,
20555
+ cached,
20556
+ ...switchInputFieldProps
20557
+ } = bindingResult;
20558
+ const error = bindingResult.$error;
20559
+ // Show loading state while fetching data
20560
+ if (bindingLoading) {
20561
+ return jsxRuntime.jsxs(material.Paper, {
20562
+ variant: "outlined",
20563
+ sx: {
20564
+ p: 2,
20565
+ textAlign: 'center'
20566
+ },
20567
+ children: [jsxRuntime.jsx(material.Typography, {
20568
+ variant: "body2",
20569
+ children: "Loading SwitchInputField..."
20570
+ }), jsxRuntime.jsx(material.Typography, {
20571
+ variant: "caption",
20572
+ color: "text.secondary",
20573
+ children: "Loading switch field configuration from data source..."
20574
+ })]
20575
+ });
20576
+ }
20577
+ if (error) {
20578
+ console.error('Error loading switch input field:', error);
20579
+ {
20580
+ return jsxRuntime.jsx(material.Paper, {
20581
+ variant: "outlined",
20582
+ sx: {
20583
+ p: 2,
20584
+ textAlign: 'center',
20585
+ borderColor: 'error.main'
20586
+ },
20587
+ children: jsxRuntime.jsxs(material.Typography, {
20588
+ variant: "body2",
20589
+ color: "error",
20590
+ children: ["Error loading switch field: ", error.message]
20591
+ })
20592
+ });
20593
+ }
20594
+ }
20595
+ return jsxRuntime.jsx(SwitchInputFieldView, {
20596
+ ...switchInputFieldProps
20597
+ });
20598
+ }
20599
+ // Mark as QwickApp component
20600
+ SwitchInputField[QWICKAPP_COMPONENT] = true;
20601
+
19732
20602
  const TextField = /*#__PURE__*/React.forwardRef((props, ref) => {
19733
20603
  const {
19734
20604
  gridProps,
@@ -20225,7 +21095,7 @@ const FormPage = ({
20225
21095
  title: title,
20226
21096
  description: description,
20227
21097
  coverImage: coverImage,
20228
- form: form,
21098
+ children: form,
20229
21099
  footer: footer,
20230
21100
  status: status,
20231
21101
  message: message,
@@ -25018,6 +25888,8 @@ exports.Button = Button;
25018
25888
  exports.CardListGrid = CardListGrid;
25019
25889
  exports.ChoiceInputField = ChoiceInputField;
25020
25890
  exports.Code = Code;
25891
+ exports.CollapsibleLayout = CollapsibleLayout;
25892
+ exports.CollapsibleLayoutView = CollapsibleLayoutView;
25021
25893
  exports.Content = Content;
25022
25894
  exports.CoverImageHeader = CoverImageHeader;
25023
25895
  exports.DataProvider = DataProvider;
@@ -25053,16 +25925,19 @@ exports.QwickAppsLogo = QwickAppsLogo;
25053
25925
  exports.SafeSpan = SafeSpan;
25054
25926
  exports.Section = Section;
25055
25927
  exports.SelectInputField = SelectInputField;
25928
+ exports.SwitchInputField = SwitchInputField;
25056
25929
  exports.T = T;
25057
25930
  exports.TextField = TextField;
25058
25931
  exports.TextInputField = TextInputField;
25059
25932
  exports.ThemeProvider = ThemeProvider;
25060
25933
  exports.ThemeSwitcher = ThemeSwitcher;
25934
+ exports.animationConfigs = animationConfigs;
25061
25935
  exports.applyCustomPalette = applyCustomPalette;
25062
25936
  exports.clearUserPalettePreference = clearUserPalettePreference;
25063
25937
  exports.clearUserThemePreference = clearUserThemePreference;
25064
25938
  exports.createLogger = createLogger;
25065
25939
  exports.createPaletteFromCurrentTheme = createPaletteFromCurrentTheme;
25940
+ exports.defaultCollapsibleLayoutProps = defaultCollapsibleLayoutProps;
25066
25941
  exports.deleteCustomPalette = deleteCustomPalette;
25067
25942
  exports.exportPalette = exportPalette;
25068
25943
  exports.getCSSVariable = getCSSVariable;
@@ -25077,6 +25952,7 @@ exports.getThemePerformanceStats = getThemePerformanceStats;
25077
25952
  exports.importPalette = importPalette;
25078
25953
  exports.initializePalette = initializePalette;
25079
25954
  exports.initializeTheme = initializeTheme;
25955
+ exports.isCollapsibleLayoutProps = isCollapsibleLayoutProps;
25080
25956
  exports.loadUserPalettePreference = loadUserPalettePreference;
25081
25957
  exports.loadUserThemePreference = loadUserThemePreference;
25082
25958
  exports.logThemePerformanceStats = logThemePerformanceStats;
@@ -25094,10 +25970,12 @@ exports.saveUserThemePreference = saveUserThemePreference;
25094
25970
  exports.setCSSVariable = setCSSVariable;
25095
25971
  exports.setPalette = setPalette;
25096
25972
  exports.setTheme = setTheme;
25973
+ exports.spacingConfigs = spacingConfigs;
25097
25974
  exports.t = t;
25098
25975
  exports.useAccessibility = useAccessibility;
25099
25976
  exports.useBaseProps = useBaseProps;
25100
25977
  exports.useBreadcrumbs = useBreadcrumbs;
25978
+ exports.useCollapsibleState = useCollapsibleState;
25101
25979
  exports.useData = useData;
25102
25980
  exports.useDataBinding = useDataBinding;
25103
25981
  exports.useDataContext = useDataContext;