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