@qwickapps/react-framework 1.3.2 → 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 (66) hide show
  1. package/README.md +326 -0
  2. package/dist/components/AccessibilityProvider.d.ts +64 -0
  3. package/dist/components/AccessibilityProvider.d.ts.map +1 -0
  4. package/dist/components/Breadcrumbs.d.ts +39 -0
  5. package/dist/components/Breadcrumbs.d.ts.map +1 -0
  6. package/dist/components/ErrorBoundary.d.ts +39 -0
  7. package/dist/components/ErrorBoundary.d.ts.map +1 -0
  8. package/dist/components/QwickApp.d.ts.map +1 -1
  9. package/dist/components/forms/FormBlock.d.ts +1 -1
  10. package/dist/components/forms/FormBlock.d.ts.map +1 -1
  11. package/dist/components/index.d.ts +3 -0
  12. package/dist/components/index.d.ts.map +1 -1
  13. package/dist/components/input/SwitchInputField.d.ts +28 -0
  14. package/dist/components/input/SwitchInputField.d.ts.map +1 -0
  15. package/dist/components/input/index.d.ts +2 -0
  16. package/dist/components/input/index.d.ts.map +1 -1
  17. package/dist/components/layout/CollapsibleLayout/CollapsibleLayout.d.ts +34 -0
  18. package/dist/components/layout/CollapsibleLayout/CollapsibleLayout.d.ts.map +1 -0
  19. package/dist/components/layout/CollapsibleLayout/index.d.ts +9 -0
  20. package/dist/components/layout/CollapsibleLayout/index.d.ts.map +1 -0
  21. package/dist/components/layout/index.d.ts +2 -0
  22. package/dist/components/layout/index.d.ts.map +1 -1
  23. package/dist/index.bundled.css +12 -0
  24. package/dist/index.esm.js +1678 -25
  25. package/dist/index.js +1689 -21
  26. package/dist/schemas/CollapsibleLayoutSchema.d.ts +31 -0
  27. package/dist/schemas/CollapsibleLayoutSchema.d.ts.map +1 -0
  28. package/dist/schemas/SwitchInputFieldSchema.d.ts +18 -0
  29. package/dist/schemas/SwitchInputFieldSchema.d.ts.map +1 -0
  30. package/dist/types/CollapsibleLayout.d.ts +142 -0
  31. package/dist/types/CollapsibleLayout.d.ts.map +1 -0
  32. package/dist/types/index.d.ts +1 -0
  33. package/dist/types/index.d.ts.map +1 -1
  34. package/package.json +1 -1
  35. package/src/components/AccessibilityProvider.tsx +466 -0
  36. package/src/components/Breadcrumbs.tsx +223 -0
  37. package/src/components/ErrorBoundary.tsx +216 -0
  38. package/src/components/QwickApp.tsx +17 -11
  39. package/src/components/__tests__/AccessibilityProvider.test.tsx +330 -0
  40. package/src/components/__tests__/Breadcrumbs.test.tsx +268 -0
  41. package/src/components/__tests__/ErrorBoundary.test.tsx +163 -0
  42. package/src/components/forms/FormBlock.tsx +2 -2
  43. package/src/components/index.ts +3 -0
  44. package/src/components/input/SwitchInputField.tsx +165 -0
  45. package/src/components/input/index.ts +2 -0
  46. package/src/components/layout/CollapsibleLayout/CollapsibleLayout.tsx +554 -0
  47. package/src/components/layout/CollapsibleLayout/__tests__/CollapsibleLayout.test.tsx +1469 -0
  48. package/src/components/layout/CollapsibleLayout/index.tsx +17 -0
  49. package/src/components/layout/index.ts +4 -1
  50. package/src/components/pages/FormPage.tsx +1 -1
  51. package/src/schemas/CollapsibleLayoutSchema.ts +276 -0
  52. package/src/schemas/SwitchInputFieldSchema.ts +99 -0
  53. package/src/stories/AccessibilityProvider.stories.tsx +284 -0
  54. package/src/stories/Breadcrumbs.stories.tsx +304 -0
  55. package/src/stories/CollapsibleLayout.stories.tsx +1566 -0
  56. package/src/stories/ErrorBoundary.stories.tsx +159 -0
  57. package/src/types/CollapsibleLayout.ts +231 -0
  58. package/src/types/index.ts +1 -0
  59. package/dist/schemas/Builders.d.ts +0 -7
  60. package/dist/schemas/Builders.d.ts.map +0 -1
  61. package/dist/schemas/types.d.ts +0 -7
  62. package/dist/schemas/types.d.ts.map +0 -1
  63. package/dist/types/DataBinding.d.ts +0 -7
  64. package/dist/types/DataBinding.d.ts.map +0 -1
  65. package/dist/types/DataProvider.d.ts +0 -7
  66. package/dist/types/DataProvider.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -15336,6 +15336,689 @@ const GridCell = props => {
15336
15336
  };
15337
15337
  GridCell.displayName = 'GridCell';
15338
15338
 
15339
+ /**
15340
+ * CollapsibleLayout Schema - Data model for collapsible layout component
15341
+ *
15342
+ * Advanced expandable/collapsible container with header controls, animations,
15343
+ * content management, and state persistence capabilities.
15344
+ *
15345
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
15346
+ */
15347
+ let CollapsibleLayoutModel = class CollapsibleLayoutModel extends schema.Model {};
15348
+ __decorate([schema.Field({
15349
+ defaultValue: false
15350
+ }), schema.Editor({
15351
+ field_type: schema.FieldType.BOOLEAN,
15352
+ label: 'Collapsed',
15353
+ description: 'Whether the layout is currently collapsed'
15354
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "collapsed", void 0);
15355
+ __decorate([schema.Field({
15356
+ defaultValue: false
15357
+ }), schema.Editor({
15358
+ field_type: schema.FieldType.BOOLEAN,
15359
+ label: 'Default Collapsed',
15360
+ description: 'Initial collapsed state for uncontrolled usage'
15361
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "defaultCollapsed", void 0);
15362
+ __decorate([schema.Field(), schema.Editor({
15363
+ field_type: schema.FieldType.TEXT,
15364
+ label: 'Title',
15365
+ description: 'Main title displayed in the header',
15366
+ placeholder: 'Enter title...'
15367
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "title", void 0);
15368
+ __decorate([schema.Field(), schema.Editor({
15369
+ field_type: schema.FieldType.TEXT,
15370
+ label: 'Subtitle',
15371
+ description: 'Secondary text displayed below the title',
15372
+ placeholder: 'Enter subtitle...'
15373
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "subtitle", void 0);
15374
+ __decorate([schema.Field(), schema.Editor({
15375
+ field_type: schema.FieldType.TEXT,
15376
+ label: 'Lead Icon',
15377
+ description: 'Icon displayed before the title (icon identifier or HTML)',
15378
+ placeholder: 'Icon identifier...'
15379
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "leadIcon", void 0);
15380
+ __decorate([schema.Field(), schema.Editor({
15381
+ field_type: schema.FieldType.TEXTAREA,
15382
+ label: 'Header Actions',
15383
+ description: 'Additional controls displayed in header (HTML/React content)',
15384
+ placeholder: 'Enter header actions HTML...'
15385
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "headerActions", void 0);
15386
+ __decorate([schema.Field(), schema.Editor({
15387
+ field_type: schema.FieldType.TEXTAREA,
15388
+ label: 'Collapsed View',
15389
+ description: 'Summary content shown when collapsed (HTML supported)',
15390
+ placeholder: 'Enter collapsed view content...'
15391
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "collapsedView", void 0);
15392
+ __decorate([schema.Field(), schema.Editor({
15393
+ field_type: schema.FieldType.TEXTAREA,
15394
+ label: 'Content',
15395
+ description: 'Main content shown when expanded (HTML supported)',
15396
+ placeholder: 'Enter main content...'
15397
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "children", void 0);
15398
+ __decorate([schema.Field(), schema.Editor({
15399
+ field_type: schema.FieldType.TEXTAREA,
15400
+ label: 'Footer View',
15401
+ description: 'Always visible footer content (HTML supported)',
15402
+ placeholder: 'Enter footer content...'
15403
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "footerView", void 0);
15404
+ __decorate([schema.Field({
15405
+ defaultValue: 'header'
15406
+ }), schema.Editor({
15407
+ field_type: schema.FieldType.SELECT,
15408
+ label: 'Trigger Area',
15409
+ description: 'Area that responds to clicks for toggle functionality',
15410
+ validation: {
15411
+ options: [{
15412
+ label: 'Button Only',
15413
+ value: 'button'
15414
+ }, {
15415
+ label: 'Header Area',
15416
+ value: 'header'
15417
+ }, {
15418
+ label: 'Button and Header',
15419
+ value: 'both'
15420
+ }]
15421
+ }
15422
+ }), classValidator.IsOptional(), classValidator.IsIn(['button', 'header', 'both']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "triggerArea", void 0);
15423
+ __decorate([schema.Field({
15424
+ defaultValue: 'slide'
15425
+ }), schema.Editor({
15426
+ field_type: schema.FieldType.SELECT,
15427
+ label: 'Animation Style',
15428
+ description: 'Animation variant for expand/collapse transitions',
15429
+ validation: {
15430
+ options: [{
15431
+ label: 'Fade',
15432
+ value: 'fade'
15433
+ }, {
15434
+ label: 'Slide',
15435
+ value: 'slide'
15436
+ }, {
15437
+ label: 'Scale',
15438
+ value: 'scale'
15439
+ }]
15440
+ }
15441
+ }), classValidator.IsOptional(), classValidator.IsIn(['fade', 'slide', 'scale']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "animationStyle", void 0);
15442
+ __decorate([schema.Field({
15443
+ defaultValue: false
15444
+ }), schema.Editor({
15445
+ field_type: schema.FieldType.BOOLEAN,
15446
+ label: 'Persist State',
15447
+ description: 'Save collapse state in local storage'
15448
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "persistState", void 0);
15449
+ __decorate([schema.Field(), schema.Editor({
15450
+ field_type: schema.FieldType.TEXT,
15451
+ label: 'Collapsed Icon',
15452
+ description: 'Icon shown when content is collapsed (default: VisibilityIcon)',
15453
+ placeholder: 'Icon identifier...'
15454
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "collapsedIcon", void 0);
15455
+ __decorate([schema.Field(), schema.Editor({
15456
+ field_type: schema.FieldType.TEXT,
15457
+ label: 'Expanded Icon',
15458
+ description: 'Icon shown when content is expanded (default: VisibilityOffIcon)',
15459
+ placeholder: 'Icon identifier...'
15460
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "expandedIcon", void 0);
15461
+ __decorate([schema.Field({
15462
+ defaultValue: true
15463
+ }), schema.Editor({
15464
+ field_type: schema.FieldType.BOOLEAN,
15465
+ label: 'Show Divider',
15466
+ description: 'Show divider lines between header, content, and footer sections'
15467
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], CollapsibleLayoutModel.prototype, "showDivider", void 0);
15468
+ __decorate([schema.Field({
15469
+ defaultValue: 'default'
15470
+ }), schema.Editor({
15471
+ field_type: schema.FieldType.SELECT,
15472
+ label: 'Variant',
15473
+ description: 'Visual style variant for the layout container',
15474
+ validation: {
15475
+ options: [{
15476
+ label: 'Default',
15477
+ value: 'default'
15478
+ }, {
15479
+ label: 'Outlined',
15480
+ value: 'outlined'
15481
+ }, {
15482
+ label: 'Elevated',
15483
+ value: 'elevated'
15484
+ }, {
15485
+ label: 'Filled',
15486
+ value: 'filled'
15487
+ }]
15488
+ }
15489
+ }), classValidator.IsOptional(), classValidator.IsIn(['default', 'outlined', 'elevated', 'filled']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "variant", void 0);
15490
+ __decorate([schema.Field({
15491
+ defaultValue: 'comfortable'
15492
+ }), schema.Editor({
15493
+ field_type: schema.FieldType.SELECT,
15494
+ label: 'Header Spacing',
15495
+ description: 'Padding/spacing within the header area',
15496
+ validation: {
15497
+ options: [{
15498
+ label: 'Compact',
15499
+ value: 'compact'
15500
+ }, {
15501
+ label: 'Comfortable',
15502
+ value: 'comfortable'
15503
+ }, {
15504
+ label: 'Spacious',
15505
+ value: 'spacious'
15506
+ }]
15507
+ }
15508
+ }), classValidator.IsOptional(), classValidator.IsIn(['compact', 'comfortable', 'spacious']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "headerSpacing", void 0);
15509
+ __decorate([schema.Field({
15510
+ defaultValue: 'comfortable'
15511
+ }), schema.Editor({
15512
+ field_type: schema.FieldType.SELECT,
15513
+ label: 'Content Spacing',
15514
+ description: 'Padding/spacing within the content area',
15515
+ validation: {
15516
+ options: [{
15517
+ label: 'Compact',
15518
+ value: 'compact'
15519
+ }, {
15520
+ label: 'Comfortable',
15521
+ value: 'comfortable'
15522
+ }, {
15523
+ label: 'Spacious',
15524
+ value: 'spacious'
15525
+ }]
15526
+ }
15527
+ }), classValidator.IsOptional(), classValidator.IsIn(['compact', 'comfortable', 'spacious']), __metadata("design:type", String)], CollapsibleLayoutModel.prototype, "contentSpacing", void 0);
15528
+ CollapsibleLayoutModel = __decorate([schema.Schema('CollapsibleLayout', '1.0.0')], CollapsibleLayoutModel);
15529
+ var CollapsibleLayoutModel$1 = CollapsibleLayoutModel;
15530
+
15531
+ /**
15532
+ * TypeScript type definitions for CollapsibleLayout component
15533
+ *
15534
+ * Provides TypeScript interfaces that extend the schema model with React-specific types
15535
+ * and component-level functionality for the CollapsibleLayout component.
15536
+ *
15537
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
15538
+ */
15539
+ /**
15540
+ * Type guard to check if a component has CollapsibleLayout props
15541
+ */
15542
+ function isCollapsibleLayoutProps(props) {
15543
+ return props && typeof props === 'object' && ('collapsed' in props || 'defaultCollapsed' in props);
15544
+ }
15545
+ /**
15546
+ * Default props for CollapsibleLayout component
15547
+ */
15548
+ const defaultCollapsibleLayoutProps = {
15549
+ // Note: collapsed is intentionally omitted so components can be uncontrolled
15550
+ defaultCollapsed: false,
15551
+ triggerArea: 'both',
15552
+ animationStyle: 'slide',
15553
+ persistState: false,
15554
+ showDivider: true,
15555
+ variant: 'default',
15556
+ headerSpacing: 'comfortable',
15557
+ contentSpacing: 'comfortable',
15558
+ animationDuration: 300,
15559
+ disableAnimations: false,
15560
+ toggleAriaLabel: 'Toggle content visibility'
15561
+ };
15562
+ const animationConfigs = {
15563
+ fade: {
15564
+ duration: 300,
15565
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
15566
+ opacity: [0, 1]
15567
+ },
15568
+ slide: {
15569
+ duration: 300,
15570
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
15571
+ transform: 'translateY(-10px)'
15572
+ },
15573
+ scale: {
15574
+ duration: 200,
15575
+ easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)',
15576
+ transform: 'scale(0.95)',
15577
+ opacity: [0, 1]
15578
+ }
15579
+ };
15580
+ const spacingConfigs = {
15581
+ compact: {
15582
+ padding: '8px 12px',
15583
+ gap: '4px'
15584
+ },
15585
+ comfortable: {
15586
+ padding: '16px 20px',
15587
+ gap: '8px'
15588
+ },
15589
+ spacious: {
15590
+ padding: '24px 32px',
15591
+ gap: '16px'
15592
+ }
15593
+ };
15594
+
15595
+ /**
15596
+ * Custom hook for managing collapsible state - simplified approach
15597
+ */
15598
+ function useCollapsibleState(controlled, collapsedProp, defaultCollapsedProp, onToggleProp, persistState, storageKey) {
15599
+ const id = React.useId();
15600
+ const finalStorageKey = storageKey || `collapsible-${id}`;
15601
+ // For controlled components, use the prop; for uncontrolled, use internal state
15602
+ const [internalCollapsed, setInternalCollapsed] = React.useState(() => {
15603
+ if (controlled) {
15604
+ return collapsedProp ?? false;
15605
+ }
15606
+ // Try localStorage first if persistence is enabled
15607
+ if (persistState && typeof window !== 'undefined') {
15608
+ const stored = localStorage.getItem(finalStorageKey);
15609
+ if (stored !== null) {
15610
+ return JSON.parse(stored);
15611
+ }
15612
+ }
15613
+ return defaultCollapsedProp ?? false;
15614
+ });
15615
+ // Sync with controlled prop changes
15616
+ React.useEffect(() => {
15617
+ if (controlled && collapsedProp !== undefined) {
15618
+ setInternalCollapsed(collapsedProp);
15619
+ }
15620
+ }, [controlled, collapsedProp]);
15621
+ // Persist to localStorage for uncontrolled components
15622
+ React.useEffect(() => {
15623
+ if (!controlled && persistState && typeof window !== 'undefined') {
15624
+ localStorage.setItem(finalStorageKey, JSON.stringify(internalCollapsed));
15625
+ }
15626
+ }, [controlled, internalCollapsed, persistState, finalStorageKey]);
15627
+ const toggle = React.useCallback(() => {
15628
+ const currentState = controlled ? collapsedProp ?? false : internalCollapsed;
15629
+ const newCollapsed = !currentState;
15630
+ // Always update internal state for visual updates
15631
+ setInternalCollapsed(newCollapsed);
15632
+ // Call callback to notify parent
15633
+ onToggleProp?.(newCollapsed);
15634
+ }, [controlled, collapsedProp, internalCollapsed, onToggleProp]);
15635
+ const setCollapsed = React.useCallback(collapsed => {
15636
+ setInternalCollapsed(collapsed);
15637
+ onToggleProp?.(collapsed);
15638
+ }, [onToggleProp]);
15639
+ // Return the appropriate state
15640
+ const finalCollapsed = controlled ? collapsedProp ?? false : internalCollapsed;
15641
+ return {
15642
+ collapsed: finalCollapsed,
15643
+ toggle,
15644
+ setCollapsed,
15645
+ isControlled: controlled
15646
+ };
15647
+ }
15648
+ /**
15649
+ * Core CollapsibleLayout View component
15650
+ */
15651
+ function CollapsibleLayoutView({
15652
+ // State props
15653
+ collapsed: collapsedProp,
15654
+ defaultCollapsed = false,
15655
+ onToggle,
15656
+ // Content props
15657
+ title,
15658
+ subtitle,
15659
+ leadIcon,
15660
+ headerActions,
15661
+ collapsedView,
15662
+ children,
15663
+ footerView,
15664
+ // Behavior props
15665
+ triggerArea = 'both',
15666
+ animationStyle = 'slide',
15667
+ persistState = false,
15668
+ storageKey,
15669
+ animationDuration = 300,
15670
+ disableAnimations = false,
15671
+ // Icons
15672
+ collapsedIcon,
15673
+ expandedIcon,
15674
+ // Layout props
15675
+ showDivider = true,
15676
+ variant = 'default',
15677
+ headerSpacing = 'comfortable',
15678
+ contentSpacing = 'comfortable',
15679
+ // Accessibility
15680
+ toggleAriaLabel = 'Toggle content visibility',
15681
+ 'aria-describedby': ariaDescribedBy,
15682
+ contentAriaProps = {},
15683
+ // CSS classes
15684
+ containerClassName,
15685
+ headerClassName,
15686
+ contentClassName,
15687
+ footerClassName,
15688
+ ...restProps
15689
+ }) {
15690
+ const theme = material.useTheme();
15691
+ const {
15692
+ styleProps,
15693
+ htmlProps,
15694
+ restProps: otherProps
15695
+ } = useBaseProps(restProps);
15696
+ // Mark as QwickApp component
15697
+ CollapsibleLayoutView[QWICKAPP_COMPONENT] = true;
15698
+ // Determine controlled vs uncontrolled usage
15699
+ const controlled = collapsedProp !== undefined;
15700
+ // State management
15701
+ const {
15702
+ collapsed,
15703
+ toggle,
15704
+ setCollapsed
15705
+ } = useCollapsibleState(controlled, collapsedProp, defaultCollapsed, onToggle, persistState, storageKey);
15706
+ // Get spacing configurations
15707
+ const headerSpacingConfig = spacingConfigs[headerSpacing];
15708
+ const contentSpacingConfig = spacingConfigs[contentSpacing];
15709
+ // Get animation configuration
15710
+ const animationConfig = animationConfigs[animationStyle];
15711
+ // Generate unique IDs for accessibility
15712
+ const headerId = React.useId();
15713
+ const contentId = React.useId();
15714
+ // Handle click events
15715
+ const handleHeaderClick = React.useCallback(event => {
15716
+ if (triggerArea === 'header' || triggerArea === 'both') {
15717
+ event.preventDefault();
15718
+ toggle();
15719
+ }
15720
+ }, [triggerArea, toggle]);
15721
+ const handleButtonClick = React.useCallback(event => {
15722
+ event.stopPropagation();
15723
+ toggle();
15724
+ }, [toggle]);
15725
+ // Render icons
15726
+ const renderIcon = React.useCallback((icon, defaultIcon) => {
15727
+ if (/*#__PURE__*/React.isValidElement(icon)) {
15728
+ return icon;
15729
+ }
15730
+ if (typeof icon === 'string') {
15731
+ return jsxRuntime.jsx(Html, {
15732
+ children: icon
15733
+ });
15734
+ }
15735
+ return defaultIcon;
15736
+ }, []);
15737
+ const toggleIcon = renderIcon(collapsed ? collapsedIcon : expandedIcon, collapsed ? jsxRuntime.jsx(iconsMaterial.ExpandMore, {}) : jsxRuntime.jsx(iconsMaterial.ExpandLess, {}));
15738
+ // Container styles based on variant
15739
+ const containerSx = React.useMemo(() => {
15740
+ const baseSx = {
15741
+ width: '100%',
15742
+ position: 'relative',
15743
+ ...styleProps.sx
15744
+ };
15745
+ switch (variant) {
15746
+ case 'outlined':
15747
+ return {
15748
+ ...baseSx,
15749
+ border: `1px solid ${theme.palette.divider}`,
15750
+ borderRadius: 1,
15751
+ backgroundColor: 'var(--theme-surface)'
15752
+ };
15753
+ case 'elevated':
15754
+ return {
15755
+ ...baseSx,
15756
+ boxShadow: theme.shadows[2],
15757
+ borderRadius: 1,
15758
+ backgroundColor: theme.palette.background.paper
15759
+ };
15760
+ case 'filled':
15761
+ return {
15762
+ ...baseSx,
15763
+ backgroundColor: 'var(--theme-surface-variant)',
15764
+ borderRadius: 1
15765
+ };
15766
+ default:
15767
+ return baseSx;
15768
+ }
15769
+ }, [variant, theme, styleProps.sx]);
15770
+ // Header styles
15771
+ const headerSx = React.useMemo(() => ({
15772
+ ...headerSpacingConfig,
15773
+ cursor: triggerArea === 'header' || triggerArea === 'both' ? 'pointer' : 'default',
15774
+ userSelect: 'none',
15775
+ display: 'flex',
15776
+ alignItems: 'center',
15777
+ justifyContent: 'space-between',
15778
+ '&:hover': triggerArea === 'header' || triggerArea === 'both' ? {
15779
+ backgroundColor: 'rgba(0, 0, 0, 0.04)'
15780
+ } : {}
15781
+ }), [headerSpacingConfig, triggerArea]);
15782
+ // Content styles
15783
+ const contentSx = React.useMemo(() => ({
15784
+ ...contentSpacingConfig
15785
+ }), [contentSpacingConfig]);
15786
+ // Animation props for Collapse component
15787
+ const collapseProps = React.useMemo(() => {
15788
+ if (disableAnimations) {
15789
+ return {
15790
+ timeout: 0
15791
+ };
15792
+ }
15793
+ const baseProps = {
15794
+ timeout: animationDuration
15795
+ };
15796
+ switch (animationStyle) {
15797
+ case 'fade':
15798
+ return {
15799
+ ...baseProps,
15800
+ sx: {
15801
+ '& .MuiCollapse-wrapper': {
15802
+ opacity: collapsed ? 0 : 1,
15803
+ transition: `opacity ${animationDuration}ms ${animationConfig.easing}`
15804
+ }
15805
+ }
15806
+ };
15807
+ case 'scale':
15808
+ return {
15809
+ ...baseProps,
15810
+ sx: {
15811
+ '& .MuiCollapse-wrapper': {
15812
+ transform: collapsed ? 'scale(0.95)' : 'scale(1)',
15813
+ opacity: collapsed ? 0 : 1,
15814
+ transition: `all ${animationDuration}ms ${animationConfig.easing}`
15815
+ }
15816
+ }
15817
+ };
15818
+ default:
15819
+ // slide
15820
+ return baseProps;
15821
+ }
15822
+ }, [disableAnimations, animationDuration, animationStyle, animationConfig, collapsed]);
15823
+ // Render content based on type
15824
+ const renderContent = React.useCallback(content => {
15825
+ if (!content) return null;
15826
+ if (typeof content === 'string') {
15827
+ return jsxRuntime.jsx(Html, {
15828
+ children: content
15829
+ });
15830
+ }
15831
+ return content;
15832
+ }, []);
15833
+ // Container content that will be wrapped
15834
+ const containerContent = jsxRuntime.jsxs(jsxRuntime.Fragment, {
15835
+ children: [(title || subtitle || leadIcon || headerActions || triggerArea === 'button' || triggerArea === 'both') && jsxRuntime.jsxs(jsxRuntime.Fragment, {
15836
+ children: [jsxRuntime.jsxs(material.Box, {
15837
+ id: headerId,
15838
+ className: headerClassName,
15839
+ sx: headerSx,
15840
+ onClick: handleHeaderClick,
15841
+ role: triggerArea === 'header' || triggerArea === 'both' ? 'button' : undefined,
15842
+ tabIndex: triggerArea === 'header' || triggerArea === 'both' ? 0 : undefined,
15843
+ "aria-expanded": !collapsed,
15844
+ "aria-controls": contentId,
15845
+ "aria-describedby": ariaDescribedBy,
15846
+ onKeyDown: e => {
15847
+ if ((triggerArea === 'header' || triggerArea === 'both') && (e.key === 'Enter' || e.key === ' ')) {
15848
+ e.preventDefault();
15849
+ toggle();
15850
+ }
15851
+ },
15852
+ children: [jsxRuntime.jsxs(material.Stack, {
15853
+ direction: "row",
15854
+ spacing: 2,
15855
+ alignItems: "center",
15856
+ sx: {
15857
+ minWidth: 0,
15858
+ flex: 1
15859
+ },
15860
+ children: [leadIcon && jsxRuntime.jsx(material.Box, {
15861
+ sx: {
15862
+ flexShrink: 0
15863
+ },
15864
+ children: renderContent(leadIcon)
15865
+ }), (title || subtitle) && jsxRuntime.jsxs(material.Box, {
15866
+ sx: {
15867
+ minWidth: 0,
15868
+ flex: 1
15869
+ },
15870
+ children: [title && jsxRuntime.jsx(material.Typography, {
15871
+ variant: "h6",
15872
+ component: "h3",
15873
+ sx: {
15874
+ fontWeight: 600,
15875
+ lineHeight: 1.2,
15876
+ ...(subtitle && {
15877
+ mb: 0.5
15878
+ })
15879
+ },
15880
+ children: title
15881
+ }), subtitle && jsxRuntime.jsx(material.Typography, {
15882
+ variant: "body2",
15883
+ color: "text.secondary",
15884
+ sx: {
15885
+ lineHeight: 1.3
15886
+ },
15887
+ children: subtitle
15888
+ })]
15889
+ })]
15890
+ }), jsxRuntime.jsxs(material.Stack, {
15891
+ direction: "row",
15892
+ spacing: 1,
15893
+ alignItems: "center",
15894
+ sx: {
15895
+ flexShrink: 0
15896
+ },
15897
+ children: [headerActions && jsxRuntime.jsx(material.Box, {
15898
+ children: renderContent(headerActions)
15899
+ }), jsxRuntime.jsx(material.IconButton, {
15900
+ onClick: handleButtonClick,
15901
+ size: "small",
15902
+ "aria-label": toggleAriaLabel,
15903
+ "aria-expanded": !collapsed,
15904
+ "aria-controls": contentId,
15905
+ children: toggleIcon
15906
+ })]
15907
+ })]
15908
+ }), showDivider && jsxRuntime.jsx(material.Divider, {})]
15909
+ }), collapsed && collapsedView && jsxRuntime.jsxs(jsxRuntime.Fragment, {
15910
+ children: [jsxRuntime.jsx(material.Box, {
15911
+ className: contentClassName,
15912
+ sx: contentSx,
15913
+ children: renderContent(collapsedView)
15914
+ }), showDivider && footerView && jsxRuntime.jsx(material.Divider, {})]
15915
+ }), jsxRuntime.jsxs(material.Collapse, {
15916
+ in: !collapsed,
15917
+ ...collapseProps,
15918
+ children: [jsxRuntime.jsx(material.Box, {
15919
+ id: contentId,
15920
+ className: contentClassName,
15921
+ sx: contentSx,
15922
+ role: "region",
15923
+ "aria-labelledby": title ? headerId : undefined,
15924
+ ...contentAriaProps,
15925
+ children: renderContent(children)
15926
+ }), showDivider && footerView && jsxRuntime.jsx(material.Divider, {})]
15927
+ }), footerView && jsxRuntime.jsx(material.Box, {
15928
+ className: footerClassName,
15929
+ sx: contentSx,
15930
+ children: renderContent(footerView)
15931
+ })]
15932
+ });
15933
+ // Return appropriate container based on variant
15934
+ if (variant === 'outlined') {
15935
+ return jsxRuntime.jsx(material.Paper, {
15936
+ variant: "outlined",
15937
+ elevation: 0,
15938
+ ...htmlProps,
15939
+ ...otherProps,
15940
+ className: containerClassName,
15941
+ sx: containerSx,
15942
+ children: containerContent
15943
+ });
15944
+ }
15945
+ if (variant === 'elevated') {
15946
+ return jsxRuntime.jsx(material.Paper, {
15947
+ elevation: 2,
15948
+ ...htmlProps,
15949
+ ...otherProps,
15950
+ className: containerClassName,
15951
+ sx: containerSx,
15952
+ children: containerContent
15953
+ });
15954
+ }
15955
+ // Default variant (default, filled)
15956
+ return jsxRuntime.jsx(material.Box, {
15957
+ ...htmlProps,
15958
+ ...otherProps,
15959
+ className: containerClassName,
15960
+ sx: containerSx,
15961
+ children: containerContent
15962
+ });
15963
+ }
15964
+ /**
15965
+ * Main CollapsibleLayout component with data binding support
15966
+ */
15967
+ function CollapsibleLayout(props) {
15968
+ const {
15969
+ dataSource,
15970
+ bindingOptions,
15971
+ ...restProps
15972
+ } = props;
15973
+ // If no dataSource, use traditional props
15974
+ if (!dataSource) {
15975
+ return jsxRuntime.jsx(CollapsibleLayoutView, {
15976
+ ...restProps
15977
+ });
15978
+ }
15979
+ // Use data binding
15980
+ const {
15981
+ dataSource: _source,
15982
+ loading,
15983
+ error,
15984
+ cached,
15985
+ ...collapsibleProps
15986
+ } = useDataBinding(dataSource, restProps, CollapsibleLayoutModel$1.getSchema(), {
15987
+ cache: true,
15988
+ cacheTTL: 300000,
15989
+ strict: false,
15990
+ ...bindingOptions
15991
+ });
15992
+ // Show loading state
15993
+ if (loading) {
15994
+ return jsxRuntime.jsx(CollapsibleLayoutView, {
15995
+ ...restProps,
15996
+ title: "Loading...",
15997
+ variant: "default",
15998
+ headerSpacing: "comfortable",
15999
+ contentSpacing: "comfortable"
16000
+ });
16001
+ }
16002
+ if (error) {
16003
+ console.error('Error loading collapsible layout:', error);
16004
+ {
16005
+ return jsxRuntime.jsx(CollapsibleLayoutView, {
16006
+ ...restProps,
16007
+ title: "Error Loading Layout",
16008
+ subtitle: error.message,
16009
+ variant: "outlined",
16010
+ headerSpacing: "comfortable",
16011
+ contentSpacing: "comfortable"
16012
+ });
16013
+ }
16014
+ }
16015
+ return jsxRuntime.jsx(CollapsibleLayoutView, {
16016
+ ...collapsibleProps
16017
+ });
16018
+ }
16019
+ // Set default props
16020
+ CollapsibleLayout.defaultProps = defaultCollapsibleLayoutProps;
16021
+
15339
16022
  /**
15340
16023
  * FeatureCard Schema - Schema definition for FeatureCard component
15341
16024
  *
@@ -18728,7 +19411,7 @@ function FormBlockView({
18728
19411
  title,
18729
19412
  description,
18730
19413
  coverImage,
18731
- form,
19414
+ children: form,
18732
19415
  footer,
18733
19416
  status,
18734
19417
  message,
@@ -19686,8 +20369,195 @@ function SelectInputField(props) {
19686
20369
  strict: false,
19687
20370
  ...bindingOptions
19688
20371
  });
19689
- // Show loading state
19690
- if (loading) {
20372
+ // Show loading state
20373
+ if (loading) {
20374
+ return jsxRuntime.jsxs(material.Paper, {
20375
+ variant: "outlined",
20376
+ sx: {
20377
+ p: 2,
20378
+ textAlign: 'center'
20379
+ },
20380
+ children: [jsxRuntime.jsx(material.Typography, {
20381
+ variant: "body2",
20382
+ children: "Loading SelectInputField..."
20383
+ }), jsxRuntime.jsx(material.Typography, {
20384
+ variant: "caption",
20385
+ color: "text.secondary",
20386
+ children: "Loading select field configuration from data source..."
20387
+ })]
20388
+ });
20389
+ }
20390
+ if (error) {
20391
+ console.error('Error loading select input field:', error);
20392
+ {
20393
+ return jsxRuntime.jsx(material.Paper, {
20394
+ variant: "outlined",
20395
+ sx: {
20396
+ p: 2,
20397
+ textAlign: 'center',
20398
+ borderColor: 'error.main'
20399
+ },
20400
+ children: jsxRuntime.jsxs(material.Typography, {
20401
+ variant: "body2",
20402
+ color: "error",
20403
+ children: ["Error loading select field: ", error.message]
20404
+ })
20405
+ });
20406
+ }
20407
+ }
20408
+ return jsxRuntime.jsx(SelectInputFieldView, {
20409
+ ...selectInputFieldProps
20410
+ });
20411
+ }
20412
+ // Mark as QwickApp component
20413
+ SelectInputField[QWICKAPP_COMPONENT] = true;
20414
+
20415
+ /**
20416
+ * SwitchInputField Schema - Data model for switch input field component
20417
+ *
20418
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
20419
+ */
20420
+ let SwitchInputFieldModel = class SwitchInputFieldModel extends schema.Model {};
20421
+ __decorate([schema.Field(), schema.Editor({
20422
+ field_type: schema.FieldType.TEXT,
20423
+ label: 'Label',
20424
+ description: 'The label text for the switch'
20425
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "label", void 0);
20426
+ __decorate([schema.Field({
20427
+ defaultValue: false
20428
+ }), schema.Editor({
20429
+ field_type: schema.FieldType.BOOLEAN,
20430
+ label: 'Checked',
20431
+ description: 'Whether the switch is checked'
20432
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], SwitchInputFieldModel.prototype, "checked", void 0);
20433
+ __decorate([schema.Field({
20434
+ defaultValue: false
20435
+ }), schema.Editor({
20436
+ field_type: schema.FieldType.BOOLEAN,
20437
+ label: 'Required',
20438
+ description: 'Whether the field is required'
20439
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], SwitchInputFieldModel.prototype, "required", void 0);
20440
+ __decorate([schema.Field({
20441
+ defaultValue: false
20442
+ }), schema.Editor({
20443
+ field_type: schema.FieldType.BOOLEAN,
20444
+ label: 'Disabled',
20445
+ description: 'Whether the field is disabled'
20446
+ }), classValidator.IsOptional(), classValidator.IsBoolean(), __metadata("design:type", Boolean)], SwitchInputFieldModel.prototype, "disabled", void 0);
20447
+ __decorate([schema.Field(), schema.Editor({
20448
+ field_type: schema.FieldType.TEXT,
20449
+ label: 'Error',
20450
+ description: 'Error message to display'
20451
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "error", void 0);
20452
+ __decorate([schema.Field(), schema.Editor({
20453
+ field_type: schema.FieldType.TEXT,
20454
+ label: 'Helper Text',
20455
+ description: 'Helper text to display below the switch'
20456
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "helperText", void 0);
20457
+ __decorate([schema.Field({
20458
+ defaultValue: 'medium'
20459
+ }), schema.Editor({
20460
+ field_type: schema.FieldType.SELECT,
20461
+ label: 'Size',
20462
+ description: 'Size of the switch'
20463
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "size", void 0);
20464
+ __decorate([schema.Field({
20465
+ defaultValue: 'primary'
20466
+ }), schema.Editor({
20467
+ field_type: schema.FieldType.SELECT,
20468
+ label: 'Color',
20469
+ description: 'Color theme of the switch'
20470
+ }), classValidator.IsOptional(), classValidator.IsString(), __metadata("design:type", String)], SwitchInputFieldModel.prototype, "color", void 0);
20471
+ SwitchInputFieldModel = __decorate([schema.Schema('SwitchInputField', '1.0.0')], SwitchInputFieldModel);
20472
+ var SwitchInputFieldModel$1 = SwitchInputFieldModel;
20473
+
20474
+ // View component - handles the actual rendering
20475
+ function SwitchInputFieldView({
20476
+ label,
20477
+ checked = false,
20478
+ onChange,
20479
+ onFocus,
20480
+ required = false,
20481
+ disabled = false,
20482
+ error,
20483
+ helperText,
20484
+ size = 'medium',
20485
+ color = 'primary',
20486
+ ...restProps
20487
+ }) {
20488
+ const {
20489
+ styleProps,
20490
+ htmlProps
20491
+ } = useBaseProps(restProps);
20492
+ const handleChange = event => {
20493
+ if (onChange) {
20494
+ onChange(event.target.checked);
20495
+ }
20496
+ };
20497
+ return jsxRuntime.jsxs(material.FormControl, {
20498
+ ...htmlProps,
20499
+ ...styleProps,
20500
+ error: !!error,
20501
+ required: required,
20502
+ disabled: disabled,
20503
+ sx: {
20504
+ display: 'block',
20505
+ ...styleProps.sx
20506
+ },
20507
+ children: [jsxRuntime.jsx(material.FormControlLabel, {
20508
+ control: jsxRuntime.jsx(material.Switch, {
20509
+ checked: checked,
20510
+ onChange: handleChange,
20511
+ onFocus: onFocus,
20512
+ size: size,
20513
+ color: color,
20514
+ disabled: disabled
20515
+ }),
20516
+ label: label,
20517
+ disabled: disabled
20518
+ }), (error || helperText) && jsxRuntime.jsx(material.FormHelperText, {
20519
+ children: error || helperText
20520
+ })]
20521
+ });
20522
+ }
20523
+ /**
20524
+ * SwitchInputField component with data binding support
20525
+ * Supports both traditional props and dataSource-driven rendering
20526
+ */
20527
+ function SwitchInputField(props) {
20528
+ const {
20529
+ dataSource,
20530
+ bindingOptions,
20531
+ ...restProps
20532
+ } = props;
20533
+ // If no dataSource, use traditional props
20534
+ if (!dataSource) {
20535
+ return jsxRuntime.jsx(SwitchInputFieldView, {
20536
+ ...restProps
20537
+ });
20538
+ }
20539
+ // Use data binding
20540
+ const bindingResult = useDataBinding(dataSource, restProps, SwitchInputFieldModel$1.getSchema(), {
20541
+ cache: true,
20542
+ cacheTTL: 300000,
20543
+ strict: false,
20544
+ ...bindingOptions
20545
+ });
20546
+ // Check if we're still loading data using the metadata properties
20547
+ const bindingLoading = bindingResult.$loading;
20548
+ // Extract all the actual switch properties (excluding metadata)
20549
+ const {
20550
+ dataSource: _source,
20551
+ $loading,
20552
+ $error,
20553
+ $dataSource,
20554
+ $cached,
20555
+ cached,
20556
+ ...switchInputFieldProps
20557
+ } = bindingResult;
20558
+ const error = bindingResult.$error;
20559
+ // Show loading state while fetching data
20560
+ if (bindingLoading) {
19691
20561
  return jsxRuntime.jsxs(material.Paper, {
19692
20562
  variant: "outlined",
19693
20563
  sx: {
@@ -19696,16 +20566,16 @@ function SelectInputField(props) {
19696
20566
  },
19697
20567
  children: [jsxRuntime.jsx(material.Typography, {
19698
20568
  variant: "body2",
19699
- children: "Loading SelectInputField..."
20569
+ children: "Loading SwitchInputField..."
19700
20570
  }), jsxRuntime.jsx(material.Typography, {
19701
20571
  variant: "caption",
19702
20572
  color: "text.secondary",
19703
- children: "Loading select field configuration from data source..."
20573
+ children: "Loading switch field configuration from data source..."
19704
20574
  })]
19705
20575
  });
19706
20576
  }
19707
20577
  if (error) {
19708
- console.error('Error loading select input field:', error);
20578
+ console.error('Error loading switch input field:', error);
19709
20579
  {
19710
20580
  return jsxRuntime.jsx(material.Paper, {
19711
20581
  variant: "outlined",
@@ -19717,17 +20587,17 @@ function SelectInputField(props) {
19717
20587
  children: jsxRuntime.jsxs(material.Typography, {
19718
20588
  variant: "body2",
19719
20589
  color: "error",
19720
- children: ["Error loading select field: ", error.message]
20590
+ children: ["Error loading switch field: ", error.message]
19721
20591
  })
19722
20592
  });
19723
20593
  }
19724
20594
  }
19725
- return jsxRuntime.jsx(SelectInputFieldView, {
19726
- ...selectInputFieldProps
20595
+ return jsxRuntime.jsx(SwitchInputFieldView, {
20596
+ ...switchInputFieldProps
19727
20597
  });
19728
20598
  }
19729
20599
  // Mark as QwickApp component
19730
- SelectInputField[QWICKAPP_COMPONENT] = true;
20600
+ SwitchInputField[QWICKAPP_COMPONENT] = true;
19731
20601
 
19732
20602
  const TextField = /*#__PURE__*/React.forwardRef((props, ref) => {
19733
20603
  const {
@@ -20225,7 +21095,7 @@ const FormPage = ({
20225
21095
  title: title,
20226
21096
  description: description,
20227
21097
  coverImage: coverImage,
20228
- form: form,
21098
+ children: form,
20229
21099
  footer: footer,
20230
21100
  status: status,
20231
21101
  message: message,
@@ -20581,6 +21451,605 @@ const Scaffold = ({
20581
21451
 
20582
21452
  loggers.menu;
20583
21453
 
21454
+ /**
21455
+ * Generic ErrorBoundary component for catching and handling React errors
21456
+ *
21457
+ * Features:
21458
+ * - Catches JavaScript errors anywhere in child component tree
21459
+ * - Displays fallback UI with retry functionality
21460
+ * - Shows error details in development mode
21461
+ * - Customizable error handling and fallback UI
21462
+ * - Automatic error logging
21463
+ */
21464
+ class ErrorBoundary extends React.Component {
21465
+ constructor(props) {
21466
+ super(props);
21467
+ this.handleRetry = () => {
21468
+ this.setState({
21469
+ hasError: false,
21470
+ error: null,
21471
+ errorInfo: null
21472
+ });
21473
+ };
21474
+ this.handleRefresh = () => {
21475
+ if (typeof window !== 'undefined') {
21476
+ window.location.reload();
21477
+ }
21478
+ };
21479
+ this.state = {
21480
+ hasError: false,
21481
+ error: null,
21482
+ errorInfo: null
21483
+ };
21484
+ }
21485
+ static getDerivedStateFromError(error) {
21486
+ // Update state so the next render will show the fallback UI
21487
+ return {
21488
+ hasError: true,
21489
+ error,
21490
+ errorInfo: null
21491
+ };
21492
+ }
21493
+ componentDidCatch(error, errorInfo) {
21494
+ // Log error details
21495
+ this.setState({
21496
+ error,
21497
+ errorInfo
21498
+ });
21499
+ // Log to console for debugging
21500
+ console.error('ErrorBoundary caught an error:', error, errorInfo);
21501
+ // Custom error handler
21502
+ if (this.props.onError) {
21503
+ this.props.onError(error, errorInfo);
21504
+ }
21505
+ // Send error to logging service if available
21506
+ if (typeof window !== 'undefined') {
21507
+ // @ts-ignore - Global error logging service
21508
+ if (window.qwickapps?.logError) {
21509
+ window.qwickapps.logError(error, errorInfo);
21510
+ }
21511
+ }
21512
+ }
21513
+ render() {
21514
+ if (this.state.hasError) {
21515
+ // Custom fallback UI
21516
+ if (this.props.fallback) {
21517
+ return this.props.fallback;
21518
+ }
21519
+ // Default error UI
21520
+ return jsxRuntime.jsxs("div", {
21521
+ className: "error-boundary",
21522
+ role: "alert",
21523
+ style: {
21524
+ padding: '2rem',
21525
+ textAlign: 'center',
21526
+ backgroundColor: '#fef2f2',
21527
+ border: '1px solid #fecaca',
21528
+ borderRadius: '8px',
21529
+ margin: '1rem',
21530
+ color: '#991b1b'
21531
+ },
21532
+ children: [jsxRuntime.jsxs("div", {
21533
+ style: {
21534
+ marginBottom: '1.5rem'
21535
+ },
21536
+ children: [jsxRuntime.jsx("h2", {
21537
+ style: {
21538
+ fontSize: '1.5rem',
21539
+ fontWeight: 'bold',
21540
+ marginBottom: '0.5rem',
21541
+ color: '#991b1b'
21542
+ },
21543
+ children: "Something went wrong"
21544
+ }), jsxRuntime.jsx("p", {
21545
+ style: {
21546
+ color: '#7f1d1d',
21547
+ marginBottom: '1rem'
21548
+ },
21549
+ children: "An unexpected error occurred in the application. Please try again or refresh the page."
21550
+ })]
21551
+ }), jsxRuntime.jsxs("div", {
21552
+ style: {
21553
+ display: 'flex',
21554
+ gap: '0.75rem',
21555
+ justifyContent: 'center',
21556
+ marginBottom: '1rem'
21557
+ },
21558
+ children: [jsxRuntime.jsx(Button, {
21559
+ variant: "contained",
21560
+ onClick: this.handleRetry,
21561
+ style: {
21562
+ backgroundColor: '#dc2626',
21563
+ color: 'white'
21564
+ },
21565
+ children: "Try Again"
21566
+ }), jsxRuntime.jsx(Button, {
21567
+ variant: "outlined",
21568
+ onClick: this.handleRefresh,
21569
+ style: {
21570
+ borderColor: '#dc2626',
21571
+ color: '#dc2626'
21572
+ },
21573
+ children: "Refresh Page"
21574
+ })]
21575
+ }), this.state.error && jsxRuntime.jsxs("details", {
21576
+ style: {
21577
+ textAlign: 'left',
21578
+ marginTop: '1rem',
21579
+ padding: '1rem',
21580
+ backgroundColor: '#f9fafb',
21581
+ border: '1px solid #d1d5db',
21582
+ borderRadius: '6px'
21583
+ },
21584
+ children: [jsxRuntime.jsx("summary", {
21585
+ style: {
21586
+ cursor: 'pointer',
21587
+ fontWeight: 'bold',
21588
+ marginBottom: '0.5rem',
21589
+ color: '#374151'
21590
+ },
21591
+ children: "Error Details (Development Mode)"
21592
+ }), jsxRuntime.jsxs("pre", {
21593
+ style: {
21594
+ fontSize: '0.75rem',
21595
+ color: '#374151',
21596
+ whiteSpace: 'pre-wrap',
21597
+ overflow: 'auto'
21598
+ },
21599
+ children: [this.state.error.toString(), this.state.errorInfo?.componentStack && jsxRuntime.jsxs(jsxRuntime.Fragment, {
21600
+ children: [jsxRuntime.jsx("br", {}), jsxRuntime.jsx("br", {}), "Component Stack:", this.state.errorInfo.componentStack]
21601
+ })]
21602
+ })]
21603
+ })]
21604
+ });
21605
+ }
21606
+ return this.props.children;
21607
+ }
21608
+ }
21609
+ /**
21610
+ * Higher-order component that wraps a component with ErrorBoundary
21611
+ */
21612
+ function withErrorBoundary(WrappedComponent, errorBoundaryProps) {
21613
+ const WithErrorBoundaryComponent = props => jsxRuntime.jsx(ErrorBoundary, {
21614
+ ...errorBoundaryProps,
21615
+ children: jsxRuntime.jsx(WrappedComponent, {
21616
+ ...props
21617
+ })
21618
+ });
21619
+ WithErrorBoundaryComponent.displayName = `withErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;
21620
+ return WithErrorBoundaryComponent;
21621
+ }
21622
+
21623
+ const AccessibilityContext = /*#__PURE__*/React.createContext(null);
21624
+ // Reducer
21625
+ const accessibilityReducer = (state, action) => {
21626
+ switch (action.type) {
21627
+ case 'SET_HIGH_CONTRAST':
21628
+ return {
21629
+ ...state,
21630
+ highContrast: action.payload
21631
+ };
21632
+ case 'SET_REDUCED_MOTION':
21633
+ return {
21634
+ ...state,
21635
+ reducedMotion: action.payload
21636
+ };
21637
+ case 'SET_LARGE_TEXT':
21638
+ return {
21639
+ ...state,
21640
+ largeText: action.payload
21641
+ };
21642
+ case 'SET_FOCUS_VISIBLE':
21643
+ return {
21644
+ ...state,
21645
+ focusVisible: action.payload
21646
+ };
21647
+ case 'SET_KEYBOARD_USER':
21648
+ return {
21649
+ ...state,
21650
+ isKeyboardUser: action.payload
21651
+ };
21652
+ case 'ADD_ISSUE':
21653
+ return {
21654
+ ...state,
21655
+ issues: [...state.issues, action.payload]
21656
+ };
21657
+ case 'CLEAR_ISSUES':
21658
+ return {
21659
+ ...state,
21660
+ issues: []
21661
+ };
21662
+ case 'SET_ANNOUNCEMENT':
21663
+ return {
21664
+ ...state,
21665
+ lastAnnouncement: action.payload
21666
+ };
21667
+ default:
21668
+ return state;
21669
+ }
21670
+ };
21671
+ // Initial state
21672
+ const initialState = {
21673
+ highContrast: false,
21674
+ reducedMotion: false,
21675
+ largeText: false,
21676
+ focusVisible: true,
21677
+ isKeyboardUser: false,
21678
+ issues: [],
21679
+ lastAnnouncement: null,
21680
+ preferences: {}
21681
+ };
21682
+ // ARIA Live Manager
21683
+ class AriaLiveManager {
21684
+ constructor() {
21685
+ this.politeRegion = null;
21686
+ this.assertiveRegion = null;
21687
+ this.createLiveRegions();
21688
+ }
21689
+ createLiveRegions() {
21690
+ if (typeof document === 'undefined') return;
21691
+ // Polite announcements
21692
+ this.politeRegion = document.createElement('div');
21693
+ this.politeRegion.setAttribute('aria-live', 'polite');
21694
+ this.politeRegion.setAttribute('aria-atomic', 'true');
21695
+ this.politeRegion.setAttribute('id', 'qwickapps-aria-live-polite');
21696
+ this.politeRegion.style.cssText = `
21697
+ position: absolute !important;
21698
+ left: -10000px !important;
21699
+ width: 1px !important;
21700
+ height: 1px !important;
21701
+ overflow: hidden !important;
21702
+ `;
21703
+ document.body.appendChild(this.politeRegion);
21704
+ // Assertive announcements
21705
+ this.assertiveRegion = document.createElement('div');
21706
+ this.assertiveRegion.setAttribute('aria-live', 'assertive');
21707
+ this.assertiveRegion.setAttribute('aria-atomic', 'true');
21708
+ this.assertiveRegion.setAttribute('id', 'qwickapps-aria-live-assertive');
21709
+ this.assertiveRegion.style.cssText = `
21710
+ position: absolute !important;
21711
+ left: -10000px !important;
21712
+ width: 1px !important;
21713
+ height: 1px !important;
21714
+ overflow: hidden !important;
21715
+ `;
21716
+ document.body.appendChild(this.assertiveRegion);
21717
+ }
21718
+ announce(message, level = 'polite') {
21719
+ if (level === 'assertive') {
21720
+ this.announceAssertive(message);
21721
+ } else {
21722
+ this.announcePolite(message);
21723
+ }
21724
+ }
21725
+ announcePolite(message) {
21726
+ if (!this.politeRegion) return;
21727
+ this.politeRegion.textContent = '';
21728
+ // Small delay ensures screen readers detect the change
21729
+ setTimeout(() => {
21730
+ if (this.politeRegion) {
21731
+ this.politeRegion.textContent = message;
21732
+ }
21733
+ }, 100);
21734
+ }
21735
+ announceAssertive(message) {
21736
+ if (!this.assertiveRegion) return;
21737
+ this.assertiveRegion.textContent = '';
21738
+ // Small delay ensures screen readers detect the change
21739
+ setTimeout(() => {
21740
+ if (this.assertiveRegion) {
21741
+ this.assertiveRegion.textContent = message;
21742
+ }
21743
+ }, 100);
21744
+ }
21745
+ }
21746
+ const ariaLiveManager = new AriaLiveManager();
21747
+ /**
21748
+ * Accessibility Provider Component
21749
+ * Provides comprehensive accessibility context and utilities
21750
+ *
21751
+ * Features:
21752
+ * - System preference detection (high contrast, reduced motion)
21753
+ * - Keyboard navigation detection
21754
+ * - ARIA live announcements
21755
+ * - Focus management
21756
+ * - Accessibility auditing
21757
+ * - Settings persistence
21758
+ */
21759
+ const AccessibilityProvider = ({
21760
+ children,
21761
+ enableAudit = "development" === 'development'
21762
+ }) => {
21763
+ const [state, dispatch] = React.useReducer(accessibilityReducer, initialState);
21764
+ React.useEffect(() => {
21765
+ // Detect user preferences from system
21766
+ detectUserPreferences();
21767
+ // Set up keyboard detection
21768
+ const keyboardCleanup = setupKeyboardDetection();
21769
+ // Initialize focus management
21770
+ initializeFocusManagement();
21771
+ // Run initial accessibility audit
21772
+ if (enableAudit) {
21773
+ runAccessibilityAudit();
21774
+ }
21775
+ // Cleanup
21776
+ return () => {
21777
+ if (keyboardCleanup) keyboardCleanup();
21778
+ };
21779
+ }, [enableAudit]);
21780
+ const detectUserPreferences = () => {
21781
+ if (typeof window === 'undefined') return;
21782
+ // High contrast mode
21783
+ if (window.matchMedia && window.matchMedia('(prefers-contrast: high)').matches) {
21784
+ dispatch({
21785
+ type: 'SET_HIGH_CONTRAST',
21786
+ payload: true
21787
+ });
21788
+ }
21789
+ // Reduced motion
21790
+ if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
21791
+ dispatch({
21792
+ type: 'SET_REDUCED_MOTION',
21793
+ payload: true
21794
+ });
21795
+ }
21796
+ // Listen for changes
21797
+ if (window.matchMedia) {
21798
+ const contrastMedia = window.matchMedia('(prefers-contrast: high)');
21799
+ const motionMedia = window.matchMedia('(prefers-reduced-motion: reduce)');
21800
+ const contrastHandler = e => {
21801
+ dispatch({
21802
+ type: 'SET_HIGH_CONTRAST',
21803
+ payload: e.matches
21804
+ });
21805
+ };
21806
+ const motionHandler = e => {
21807
+ dispatch({
21808
+ type: 'SET_REDUCED_MOTION',
21809
+ payload: e.matches
21810
+ });
21811
+ };
21812
+ contrastMedia.addEventListener('change', contrastHandler);
21813
+ motionMedia.addEventListener('change', motionHandler);
21814
+ // Return cleanup function
21815
+ return () => {
21816
+ contrastMedia.removeEventListener('change', contrastHandler);
21817
+ motionMedia.removeEventListener('change', motionHandler);
21818
+ };
21819
+ }
21820
+ };
21821
+ const setupKeyboardDetection = () => {
21822
+ if (typeof document === 'undefined') return;
21823
+ let keyboardUser = false;
21824
+ const handleKeyDown = e => {
21825
+ if (e.key === 'Tab') {
21826
+ keyboardUser = true;
21827
+ dispatch({
21828
+ type: 'SET_KEYBOARD_USER',
21829
+ payload: true
21830
+ });
21831
+ document.body.classList.add('keyboard-user');
21832
+ }
21833
+ };
21834
+ const handleMouseDown = () => {
21835
+ if (keyboardUser) {
21836
+ keyboardUser = false;
21837
+ dispatch({
21838
+ type: 'SET_KEYBOARD_USER',
21839
+ payload: false
21840
+ });
21841
+ document.body.classList.remove('keyboard-user');
21842
+ }
21843
+ };
21844
+ document.addEventListener('keydown', handleKeyDown);
21845
+ document.addEventListener('mousedown', handleMouseDown);
21846
+ return () => {
21847
+ document.removeEventListener('keydown', handleKeyDown);
21848
+ document.removeEventListener('mousedown', handleMouseDown);
21849
+ };
21850
+ };
21851
+ const initializeFocusManagement = () => {
21852
+ if (typeof document === 'undefined') return;
21853
+ // Enhanced focus indicators for keyboard users
21854
+ const style = document.createElement('style');
21855
+ style.textContent = `
21856
+ .keyboard-user *:focus {
21857
+ outline: 3px solid #005cee !important;
21858
+ outline-offset: 2px !important;
21859
+ }
21860
+
21861
+ .high-contrast *:focus {
21862
+ outline: 3px solid #ffffff !important;
21863
+ outline-offset: 2px !important;
21864
+ box-shadow: 0 0 0 1px #000000 !important;
21865
+ }
21866
+
21867
+ .reduced-motion * {
21868
+ animation-duration: 0.01ms !important;
21869
+ animation-iteration-count: 1 !important;
21870
+ transition-duration: 0.01ms !important;
21871
+ }
21872
+
21873
+ .large-text {
21874
+ font-size: 1.2em !important;
21875
+ }
21876
+ `;
21877
+ document.head.appendChild(style);
21878
+ };
21879
+ const runAccessibilityAudit = () => {
21880
+ if (typeof document === 'undefined') return;
21881
+ setTimeout(() => {
21882
+ const issues = [];
21883
+ // Check for images without alt text
21884
+ const images = document.querySelectorAll('img:not([alt])');
21885
+ images.forEach(img => {
21886
+ issues.push({
21887
+ type: 'missing-alt-text',
21888
+ message: 'Image missing alt attribute',
21889
+ level: 'error',
21890
+ element: img
21891
+ });
21892
+ });
21893
+ // Check for buttons without accessible names
21894
+ const buttons = document.querySelectorAll('button:not([aria-label]):not([title])');
21895
+ buttons.forEach(button => {
21896
+ if (!button.textContent?.trim()) {
21897
+ issues.push({
21898
+ type: 'unnamed-button',
21899
+ message: 'Button missing accessible name',
21900
+ level: 'error',
21901
+ element: button
21902
+ });
21903
+ }
21904
+ });
21905
+ // Check for form inputs without labels
21906
+ const inputs = document.querySelectorAll('input:not([aria-label]):not([title])');
21907
+ inputs.forEach(input => {
21908
+ const id = input.getAttribute('id');
21909
+ if (id) {
21910
+ const label = document.querySelector(`label[for="${id}"]`);
21911
+ if (!label) {
21912
+ issues.push({
21913
+ type: 'unlabeled-input',
21914
+ message: 'Form input missing label',
21915
+ level: 'error',
21916
+ element: input
21917
+ });
21918
+ }
21919
+ } else {
21920
+ issues.push({
21921
+ type: 'unlabeled-input',
21922
+ message: 'Form input missing label',
21923
+ level: 'error',
21924
+ element: input
21925
+ });
21926
+ }
21927
+ });
21928
+ dispatch({
21929
+ type: 'CLEAR_ISSUES'
21930
+ });
21931
+ issues.forEach(issue => {
21932
+ dispatch({
21933
+ type: 'ADD_ISSUE',
21934
+ payload: issue
21935
+ });
21936
+ });
21937
+ if (issues.length > 0) {
21938
+ console.group('🔍 Accessibility Issues Found');
21939
+ issues.forEach(issue => {
21940
+ const logMethod = issue.level === 'error' ? console.error : console.warn;
21941
+ logMethod(`${issue.type}: ${issue.message}`);
21942
+ });
21943
+ console.groupEnd();
21944
+ }
21945
+ }, 1000);
21946
+ };
21947
+ // Context value
21948
+ const contextValue = {
21949
+ ...state,
21950
+ // Actions
21951
+ setHighContrast: enabled => dispatch({
21952
+ type: 'SET_HIGH_CONTRAST',
21953
+ payload: enabled
21954
+ }),
21955
+ setReducedMotion: enabled => dispatch({
21956
+ type: 'SET_REDUCED_MOTION',
21957
+ payload: enabled
21958
+ }),
21959
+ setLargeText: enabled => dispatch({
21960
+ type: 'SET_LARGE_TEXT',
21961
+ payload: enabled
21962
+ }),
21963
+ setFocusVisible: enabled => dispatch({
21964
+ type: 'SET_FOCUS_VISIBLE',
21965
+ payload: enabled
21966
+ }),
21967
+ // Utilities
21968
+ announce: (message, level = 'polite') => {
21969
+ ariaLiveManager.announce(message, level);
21970
+ dispatch({
21971
+ type: 'SET_ANNOUNCEMENT',
21972
+ payload: {
21973
+ message,
21974
+ level,
21975
+ timestamp: Date.now()
21976
+ }
21977
+ });
21978
+ },
21979
+ announcePolite: message => {
21980
+ ariaLiveManager.announcePolite(message);
21981
+ dispatch({
21982
+ type: 'SET_ANNOUNCEMENT',
21983
+ payload: {
21984
+ message,
21985
+ level: 'polite',
21986
+ timestamp: Date.now()
21987
+ }
21988
+ });
21989
+ },
21990
+ announceAssertive: message => {
21991
+ ariaLiveManager.announceAssertive(message);
21992
+ dispatch({
21993
+ type: 'SET_ANNOUNCEMENT',
21994
+ payload: {
21995
+ message,
21996
+ level: 'assertive',
21997
+ timestamp: Date.now()
21998
+ }
21999
+ });
22000
+ },
22001
+ addIssue: issue => dispatch({
22002
+ type: 'ADD_ISSUE',
22003
+ payload: issue
22004
+ }),
22005
+ clearIssues: () => dispatch({
22006
+ type: 'CLEAR_ISSUES'
22007
+ }),
22008
+ // Audit function
22009
+ runAudit: runAccessibilityAudit
22010
+ };
22011
+ // Apply CSS classes based on preferences
22012
+ React.useEffect(() => {
22013
+ if (typeof document === 'undefined') return;
22014
+ const {
22015
+ highContrast,
22016
+ reducedMotion,
22017
+ largeText
22018
+ } = state;
22019
+ document.body.classList.toggle('high-contrast', highContrast);
22020
+ document.body.classList.toggle('reduced-motion', reducedMotion);
22021
+ document.body.classList.toggle('large-text', largeText);
22022
+ }, [state.highContrast, state.reducedMotion, state.largeText]);
22023
+ return jsxRuntime.jsx(AccessibilityContext.Provider, {
22024
+ value: contextValue,
22025
+ children: children
22026
+ });
22027
+ };
22028
+ /**
22029
+ * Hook to access accessibility context
22030
+ */
22031
+ const useAccessibility = () => {
22032
+ const context = React.useContext(AccessibilityContext);
22033
+ if (!context) {
22034
+ throw new Error('useAccessibility must be used within an AccessibilityProvider');
22035
+ }
22036
+ return context;
22037
+ };
22038
+ /**
22039
+ * Higher-Order Component for accessibility enhancements
22040
+ */
22041
+ const withAccessibility = WrappedComponent => {
22042
+ const AccessibilityEnhancedComponent = props => {
22043
+ const accessibility = useAccessibility();
22044
+ return jsxRuntime.jsx(WrappedComponent, {
22045
+ ...props,
22046
+ accessibility: accessibility
22047
+ });
22048
+ };
22049
+ AccessibilityEnhancedComponent.displayName = `withAccessibility(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;
22050
+ return AccessibilityEnhancedComponent;
22051
+ };
22052
+
20584
22053
  const QwickApp = ({
20585
22054
  children,
20586
22055
  className,
@@ -20642,16 +22111,20 @@ const QwickApp = ({
20642
22111
  dataSource: dataSource,
20643
22112
  children: content
20644
22113
  }) : content;
20645
- const appContent = jsxRuntime.jsx("div", {
20646
- className: `qwick-app ${className || ''}`,
20647
- style: style,
20648
- children: jsxRuntime.jsx(ThemeProvider, {
20649
- appId: appId,
20650
- defaultTheme: defaultTheme,
20651
- defaultPalette: defaultPalette,
20652
- children: jsxRuntime.jsx(QwickAppContext.Provider, {
20653
- value: contextValue,
20654
- children: wrappedContent
22114
+ const appContent = jsxRuntime.jsx(ErrorBoundary, {
22115
+ children: jsxRuntime.jsx(AccessibilityProvider, {
22116
+ children: jsxRuntime.jsx("div", {
22117
+ className: `qwick-app ${className || ''}`,
22118
+ style: style,
22119
+ children: jsxRuntime.jsx(ThemeProvider, {
22120
+ appId: appId,
22121
+ defaultTheme: defaultTheme,
22122
+ defaultPalette: defaultPalette,
22123
+ children: jsxRuntime.jsx(QwickAppContext.Provider, {
22124
+ value: contextValue,
22125
+ children: wrappedContent
22126
+ })
22127
+ })
20655
22128
  })
20656
22129
  })
20657
22130
  });
@@ -20759,6 +22232,186 @@ const setCSSVariable = (property, value) => {
20759
22232
  document.documentElement.style.setProperty(property, value);
20760
22233
  };
20761
22234
 
22235
+ /**
22236
+ * Generic Breadcrumbs component for navigation hierarchy
22237
+ *
22238
+ * Features:
22239
+ * - Accessible navigation with proper ARIA labels
22240
+ * - Customizable separators and icons
22241
+ * - Responsive design with item truncation
22242
+ * - Support for custom navigation handlers
22243
+ * - Keyboard navigation support
22244
+ * - Screen reader friendly
22245
+ */
22246
+ const Breadcrumbs = ({
22247
+ items,
22248
+ separator = '/',
22249
+ className = '',
22250
+ onNavigate,
22251
+ maxItems,
22252
+ showRoot = true
22253
+ }) => {
22254
+ // Filter and prepare items
22255
+ let displayItems = showRoot ? items : items.slice(1);
22256
+ // Handle max items with ellipsis
22257
+ if (maxItems && displayItems.length > maxItems) {
22258
+ const firstItems = displayItems.slice(0, 1);
22259
+ const lastItems = displayItems.slice(-Math.max(1, maxItems - 2));
22260
+ displayItems = [...firstItems, {
22261
+ label: '...',
22262
+ href: undefined,
22263
+ current: false
22264
+ }, ...lastItems];
22265
+ }
22266
+ const handleItemClick = (e, item, index) => {
22267
+ if (onNavigate) {
22268
+ e.preventDefault();
22269
+ onNavigate(item, index);
22270
+ }
22271
+ };
22272
+ const handleKeyDown = (e, item, index) => {
22273
+ if (e.key === 'Enter' || e.key === ' ') {
22274
+ e.preventDefault();
22275
+ if (onNavigate) {
22276
+ onNavigate(item, index);
22277
+ } else if (item.href) {
22278
+ window.location.href = item.href;
22279
+ }
22280
+ }
22281
+ };
22282
+ if (displayItems.length <= 1) {
22283
+ return null;
22284
+ }
22285
+ return jsxRuntime.jsx("nav", {
22286
+ className: `breadcrumbs ${className}`,
22287
+ role: "navigation",
22288
+ "aria-label": "Breadcrumb navigation",
22289
+ style: {
22290
+ display: 'flex',
22291
+ alignItems: 'center',
22292
+ fontSize: '14px',
22293
+ color: '#6b7280',
22294
+ ...defaultStyles.nav
22295
+ },
22296
+ children: jsxRuntime.jsx("ol", {
22297
+ style: {
22298
+ display: 'flex',
22299
+ alignItems: 'center',
22300
+ listStyle: 'none',
22301
+ margin: 0,
22302
+ padding: 0,
22303
+ gap: '8px'
22304
+ },
22305
+ children: displayItems.map((item, index) => {
22306
+ const isLast = index === displayItems.length - 1;
22307
+ const isClickable = (item.href || onNavigate) && !item.current && item.label !== '...';
22308
+ return jsxRuntime.jsxs("li", {
22309
+ style: {
22310
+ display: 'flex',
22311
+ alignItems: 'center'
22312
+ },
22313
+ children: [isClickable ? jsxRuntime.jsxs("a", {
22314
+ href: item.href,
22315
+ onClick: e => handleItemClick(e, item, index),
22316
+ onKeyDown: e => handleKeyDown(e, item, index),
22317
+ style: {
22318
+ ...defaultStyles.link,
22319
+ color: isLast ? '#374151' : '#6b7280',
22320
+ textDecoration: 'none',
22321
+ display: 'flex',
22322
+ alignItems: 'center',
22323
+ gap: '4px'
22324
+ },
22325
+ tabIndex: 0,
22326
+ "aria-current": item.current ? 'page' : undefined,
22327
+ children: [item.icon && jsxRuntime.jsx("span", {
22328
+ style: {
22329
+ display: 'flex',
22330
+ alignItems: 'center'
22331
+ },
22332
+ "aria-hidden": "true",
22333
+ children: item.icon
22334
+ }), jsxRuntime.jsx("span", {
22335
+ children: item.label
22336
+ })]
22337
+ }) : jsxRuntime.jsxs("span", {
22338
+ style: {
22339
+ ...defaultStyles.current,
22340
+ color: isLast ? '#111827' : '#6b7280',
22341
+ fontWeight: isLast ? 600 : 400,
22342
+ display: 'flex',
22343
+ alignItems: 'center',
22344
+ gap: '4px'
22345
+ },
22346
+ "aria-current": item.current ? 'page' : undefined,
22347
+ children: [item.icon && jsxRuntime.jsx("span", {
22348
+ style: {
22349
+ display: 'flex',
22350
+ alignItems: 'center'
22351
+ },
22352
+ "aria-hidden": "true",
22353
+ children: item.icon
22354
+ }), jsxRuntime.jsx("span", {
22355
+ children: item.label
22356
+ })]
22357
+ }), !isLast && jsxRuntime.jsx("span", {
22358
+ style: {
22359
+ display: 'flex',
22360
+ alignItems: 'center',
22361
+ marginLeft: '8px',
22362
+ color: '#d1d5db',
22363
+ fontSize: '12px'
22364
+ },
22365
+ "aria-hidden": "true",
22366
+ children: separator
22367
+ })]
22368
+ }, `${item.label}-${index}`);
22369
+ })
22370
+ })
22371
+ });
22372
+ };
22373
+ // Default styles
22374
+ const defaultStyles = {
22375
+ nav: {
22376
+ padding: '8px 0'
22377
+ },
22378
+ link: {
22379
+ transition: 'color 0.2s ease',
22380
+ cursor: 'pointer',
22381
+ borderRadius: '4px',
22382
+ padding: '4px',
22383
+ margin: '-4px'
22384
+ },
22385
+ current: {
22386
+ padding: '4px'
22387
+ }
22388
+ };
22389
+ /**
22390
+ * Hook for managing breadcrumb state
22391
+ */
22392
+ const useBreadcrumbs = () => {
22393
+ const [breadcrumbs, setBreadcrumbs] = React.useState([]);
22394
+ const addBreadcrumb = React.useCallback(item => {
22395
+ setBreadcrumbs(prev => [...prev, item]);
22396
+ }, []);
22397
+ const removeBreadcrumb = React.useCallback(index => {
22398
+ setBreadcrumbs(prev => prev.filter((_, i) => i !== index));
22399
+ }, []);
22400
+ const setBreadcrumbsCurrent = React.useCallback(items => {
22401
+ setBreadcrumbs(items);
22402
+ }, []);
22403
+ const clearBreadcrumbs = React.useCallback(() => {
22404
+ setBreadcrumbs([]);
22405
+ }, []);
22406
+ return {
22407
+ breadcrumbs,
22408
+ addBreadcrumb,
22409
+ removeBreadcrumb,
22410
+ setBreadcrumbs: setBreadcrumbsCurrent,
22411
+ clearBreadcrumbs
22412
+ };
22413
+ };
22414
+
20762
22415
  const QwickAppsLogo = props => {
20763
22416
  const {
20764
22417
  styleProps,
@@ -24226,18 +25879,23 @@ exports.ActionType = void 0;
24226
25879
  })(exports.ActionType || (exports.ActionType = {}));
24227
25880
 
24228
25881
  exports.AVAILABLE_PALETTES = AVAILABLE_PALETTES;
25882
+ exports.AccessibilityProvider = AccessibilityProvider;
24229
25883
  exports.AllPalettes = AllPalettes;
24230
25884
  exports.Article = Article;
24231
25885
  exports.BasePage = BasePage;
25886
+ exports.Breadcrumbs = Breadcrumbs;
24232
25887
  exports.Button = Button;
24233
25888
  exports.CardListGrid = CardListGrid;
24234
25889
  exports.ChoiceInputField = ChoiceInputField;
24235
25890
  exports.Code = Code;
25891
+ exports.CollapsibleLayout = CollapsibleLayout;
25892
+ exports.CollapsibleLayoutView = CollapsibleLayoutView;
24236
25893
  exports.Content = Content;
24237
25894
  exports.CoverImageHeader = CoverImageHeader;
24238
25895
  exports.DataProvider = DataProvider;
24239
25896
  exports.DataProxy = DataProxy;
24240
25897
  exports.DimensionsProvider = DimensionsProvider;
25898
+ exports.ErrorBoundary = ErrorBoundary;
24241
25899
  exports.FeatureCard = FeatureCard;
24242
25900
  exports.FeatureGrid = FeatureGrid;
24243
25901
  exports.Footer = Footer;
@@ -24267,16 +25925,19 @@ exports.QwickAppsLogo = QwickAppsLogo;
24267
25925
  exports.SafeSpan = SafeSpan;
24268
25926
  exports.Section = Section;
24269
25927
  exports.SelectInputField = SelectInputField;
25928
+ exports.SwitchInputField = SwitchInputField;
24270
25929
  exports.T = T;
24271
25930
  exports.TextField = TextField;
24272
25931
  exports.TextInputField = TextInputField;
24273
25932
  exports.ThemeProvider = ThemeProvider;
24274
25933
  exports.ThemeSwitcher = ThemeSwitcher;
25934
+ exports.animationConfigs = animationConfigs;
24275
25935
  exports.applyCustomPalette = applyCustomPalette;
24276
25936
  exports.clearUserPalettePreference = clearUserPalettePreference;
24277
25937
  exports.clearUserThemePreference = clearUserThemePreference;
24278
25938
  exports.createLogger = createLogger;
24279
25939
  exports.createPaletteFromCurrentTheme = createPaletteFromCurrentTheme;
25940
+ exports.defaultCollapsibleLayoutProps = defaultCollapsibleLayoutProps;
24280
25941
  exports.deleteCustomPalette = deleteCustomPalette;
24281
25942
  exports.exportPalette = exportPalette;
24282
25943
  exports.getCSSVariable = getCSSVariable;
@@ -24291,6 +25952,7 @@ exports.getThemePerformanceStats = getThemePerformanceStats;
24291
25952
  exports.importPalette = importPalette;
24292
25953
  exports.initializePalette = initializePalette;
24293
25954
  exports.initializeTheme = initializeTheme;
25955
+ exports.isCollapsibleLayoutProps = isCollapsibleLayoutProps;
24294
25956
  exports.loadUserPalettePreference = loadUserPalettePreference;
24295
25957
  exports.loadUserThemePreference = loadUserThemePreference;
24296
25958
  exports.logThemePerformanceStats = logThemePerformanceStats;
@@ -24308,8 +25970,12 @@ exports.saveUserThemePreference = saveUserThemePreference;
24308
25970
  exports.setCSSVariable = setCSSVariable;
24309
25971
  exports.setPalette = setPalette;
24310
25972
  exports.setTheme = setTheme;
25973
+ exports.spacingConfigs = spacingConfigs;
24311
25974
  exports.t = t;
25975
+ exports.useAccessibility = useAccessibility;
24312
25976
  exports.useBaseProps = useBaseProps;
25977
+ exports.useBreadcrumbs = useBreadcrumbs;
25978
+ exports.useCollapsibleState = useCollapsibleState;
24313
25979
  exports.useData = useData;
24314
25980
  exports.useDataBinding = useDataBinding;
24315
25981
  exports.useDataContext = useDataContext;
@@ -24322,3 +25988,5 @@ exports.useSafeLocation = useSafeLocation;
24322
25988
  exports.useSafeNavigate = useSafeNavigate;
24323
25989
  exports.useTemplate = useTemplate;
24324
25990
  exports.useTheme = useTheme;
25991
+ exports.withAccessibility = withAccessibility;
25992
+ exports.withErrorBoundary = withErrorBoundary;