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