@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
@@ -0,0 +1,159 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { ErrorBoundary, withErrorBoundary } from '../components/ErrorBoundary';
3
+ import React from 'react';
4
+
5
+ // Test component that throws an error
6
+ const ThrowError = ({ shouldThrow = false }: { shouldThrow?: boolean }) => {
7
+ if (shouldThrow) {
8
+ throw new Error('Intentional error for testing ErrorBoundary');
9
+ }
10
+ return <div>This component is working fine!</div>;
11
+ };
12
+
13
+ const meta: Meta<typeof ErrorBoundary> = {
14
+ title: 'Framework/ErrorBoundary',
15
+ component: ErrorBoundary,
16
+ parameters: {
17
+ layout: 'centered',
18
+ docs: {
19
+ description: {
20
+ component: 'A React Error Boundary component that catches JavaScript errors and displays a user-friendly fallback UI with recovery options.',
21
+ },
22
+ },
23
+ },
24
+ tags: ['autodocs'],
25
+ argTypes: {
26
+ fallback: {
27
+ description: 'Custom fallback UI to display when an error occurs',
28
+ },
29
+ onError: {
30
+ description: 'Callback function called when an error is caught',
31
+ action: 'onError',
32
+ },
33
+ showErrorDetails: {
34
+ description: 'Whether to show error details (overrides development mode detection)',
35
+ control: 'boolean',
36
+ },
37
+ children: {
38
+ description: 'Child components to wrap with error boundary',
39
+ },
40
+ },
41
+ };
42
+
43
+ export default meta;
44
+ type Story = StoryObj<typeof meta>;
45
+
46
+ // Default story with working component
47
+ export const Default: Story = {
48
+ args: {
49
+ children: <div>This is a working component wrapped in ErrorBoundary</div>,
50
+ },
51
+ };
52
+
53
+ // Story that demonstrates error handling
54
+ export const WithError: Story = {
55
+ args: {
56
+ children: <ThrowError shouldThrow={true} />,
57
+ },
58
+ parameters: {
59
+ docs: {
60
+ description: {
61
+ story: 'Demonstrates ErrorBoundary catching an error and displaying the fallback UI.',
62
+ },
63
+ },
64
+ },
65
+ };
66
+
67
+ // Story with custom fallback UI
68
+ export const CustomFallback: Story = {
69
+ args: {
70
+ children: <ThrowError shouldThrow={true} />,
71
+ fallback: (
72
+ <div style={{
73
+ padding: '2rem',
74
+ textAlign: 'center',
75
+ background: '#ffe6e6',
76
+ border: '2px solid #ff9999',
77
+ borderRadius: '8px',
78
+ color: '#cc0000'
79
+ }}>
80
+ <h3>🚨 Custom Error UI</h3>
81
+ <p>Something went wrong, but we have a custom fallback!</p>
82
+ </div>
83
+ ),
84
+ },
85
+ parameters: {
86
+ docs: {
87
+ description: {
88
+ story: 'Shows how to provide a custom fallback UI instead of the default error message.',
89
+ },
90
+ },
91
+ },
92
+ };
93
+
94
+ // Story showing error details in development mode
95
+ export const WithErrorDetails: Story = {
96
+ args: {
97
+ children: <ThrowError shouldThrow={true} />,
98
+ showErrorDetails: true,
99
+ },
100
+ parameters: {
101
+ docs: {
102
+ description: {
103
+ story: 'Shows error details including stack trace (normally only shown in development mode).',
104
+ },
105
+ },
106
+ },
107
+ };
108
+
109
+ // Story demonstrating the HOC
110
+ const TestComponent = () => <div>Component enhanced with ErrorBoundary HOC</div>;
111
+ const EnhancedComponent = withErrorBoundary(TestComponent);
112
+
113
+ export const HigherOrderComponent: Story = {
114
+ render: () => <EnhancedComponent />,
115
+ parameters: {
116
+ docs: {
117
+ description: {
118
+ story: 'Demonstrates using the withErrorBoundary Higher-Order Component to wrap any component with error handling.',
119
+ },
120
+ },
121
+ },
122
+ };
123
+
124
+ // Interactive story for testing retry functionality
125
+ export const Interactive: Story = {
126
+ render: () => {
127
+ const [shouldThrow, setShouldThrow] = React.useState(false);
128
+
129
+ return (
130
+ <div style={{ padding: '2rem' }}>
131
+ <button
132
+ onClick={() => setShouldThrow(!shouldThrow)}
133
+ style={{
134
+ marginBottom: '1rem',
135
+ padding: '0.5rem 1rem',
136
+ background: shouldThrow ? '#ff4444' : '#44aa44',
137
+ color: 'white',
138
+ border: 'none',
139
+ borderRadius: '4px',
140
+ cursor: 'pointer'
141
+ }}
142
+ >
143
+ {shouldThrow ? 'Fix Component' : 'Break Component'}
144
+ </button>
145
+
146
+ <ErrorBoundary>
147
+ <ThrowError shouldThrow={shouldThrow} />
148
+ </ErrorBoundary>
149
+ </div>
150
+ );
151
+ },
152
+ parameters: {
153
+ docs: {
154
+ description: {
155
+ story: 'Interactive demo where you can break and fix the component to see ErrorBoundary in action.',
156
+ },
157
+ },
158
+ },
159
+ };
@@ -0,0 +1,231 @@
1
+ /**
2
+ * TypeScript type definitions for CollapsibleLayout component
3
+ *
4
+ * Provides TypeScript interfaces that extend the schema model with React-specific types
5
+ * and component-level functionality for the CollapsibleLayout component.
6
+ *
7
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
+ */
9
+
10
+ import React, { ReactNode } from 'react';
11
+ import type { WithDataBinding, ModelProps } from '@qwickapps/schema';
12
+ import type { WithBaseProps } from '../hooks/useBaseProps';
13
+ import CollapsibleLayoutModel from '../schemas/CollapsibleLayoutSchema';
14
+
15
+ /**
16
+ * Core CollapsibleLayout properties extending the schema model
17
+ *
18
+ * This interface combines the schema-defined properties with React-specific types
19
+ * and additional component functionality not captured in the schema.
20
+ */
21
+ export type CollapsibleLayoutViewProps = ModelProps<CollapsibleLayoutModel> &
22
+ WithBaseProps & {
23
+ // ========================================
24
+ // React Event Handlers
25
+ // ========================================
26
+
27
+ /**
28
+ * Callback fired when the collapsed state changes
29
+ * @param collapsed - The new collapsed state
30
+ */
31
+ onToggle?: (collapsed: boolean) => void;
32
+
33
+ // ========================================
34
+ // React Node Overrides
35
+ // ========================================
36
+
37
+ /** Lead icon as React node (overrides string-based leadIcon from schema) */
38
+ leadIcon?: ReactNode;
39
+
40
+ /** Header actions as React node (overrides string-based headerActions from schema) */
41
+ headerActions?: ReactNode;
42
+
43
+ /** Collapsed view content as React node (overrides string-based collapsedView from schema) */
44
+ collapsedView?: ReactNode;
45
+
46
+ /** Main content as React node (overrides string-based children from schema) */
47
+ children?: ReactNode;
48
+
49
+ /** Footer content as React node (overrides string-based footerView from schema) */
50
+ footerView?: ReactNode;
51
+
52
+ /** Collapsed state icon as React node (overrides string-based collapsedIcon from schema) */
53
+ collapsedIcon?: ReactNode;
54
+
55
+ /** Expanded state icon as React node (overrides string-based expandedIcon from schema) */
56
+ expandedIcon?: ReactNode;
57
+
58
+ // ========================================
59
+ // Additional Component Props
60
+ // ========================================
61
+
62
+ /**
63
+ * Unique key for local storage persistence (when persistState is true)
64
+ * Defaults to component id or generates one automatically
65
+ */
66
+ storageKey?: string;
67
+
68
+ /**
69
+ * Animation duration in milliseconds
70
+ * @default 300
71
+ */
72
+ animationDuration?: number;
73
+
74
+ /**
75
+ * Disable all animations (useful for testing or accessibility)
76
+ * @default false
77
+ */
78
+ disableAnimations?: boolean;
79
+
80
+ /**
81
+ * Custom CSS class for the container
82
+ */
83
+ containerClassName?: string;
84
+
85
+ /**
86
+ * Custom CSS class for the header
87
+ */
88
+ headerClassName?: string;
89
+
90
+ /**
91
+ * Custom CSS class for the content area
92
+ */
93
+ contentClassName?: string;
94
+
95
+ /**
96
+ * Custom CSS class for the footer
97
+ */
98
+ footerClassName?: string;
99
+
100
+ // ========================================
101
+ // Accessibility Props
102
+ // ========================================
103
+
104
+ /**
105
+ * ARIA label for the toggle button
106
+ * @default "Toggle content visibility"
107
+ */
108
+ toggleAriaLabel?: string;
109
+
110
+ /**
111
+ * ID of element that describes the collapsible content
112
+ */
113
+ 'aria-describedby'?: string;
114
+
115
+ /**
116
+ * Additional ARIA attributes for the content region
117
+ */
118
+ contentAriaProps?: {
119
+ 'aria-label'?: string;
120
+ 'aria-labelledby'?: string;
121
+ role?: string;
122
+ };
123
+ };
124
+
125
+ /**
126
+ * Complete CollapsibleLayout component props interface
127
+ *
128
+ * This is the interface that should be used by the CollapsibleLayout component.
129
+ * It combines the view props with data binding capabilities.
130
+ */
131
+ export interface CollapsibleLayoutProps extends CollapsibleLayoutViewProps, WithDataBinding {}
132
+
133
+ /**
134
+ * Type guard to check if a component has CollapsibleLayout props
135
+ */
136
+ export function isCollapsibleLayoutProps(props: any): props is CollapsibleLayoutProps {
137
+ return props && typeof props === 'object' && ('collapsed' in props || 'defaultCollapsed' in props);
138
+ }
139
+
140
+ /**
141
+ * Default props for CollapsibleLayout component
142
+ */
143
+ export const defaultCollapsibleLayoutProps: Partial<CollapsibleLayoutProps> = {
144
+ // Note: collapsed is intentionally omitted so components can be uncontrolled
145
+ defaultCollapsed: false,
146
+ triggerArea: 'both',
147
+ animationStyle: 'slide',
148
+ persistState: false,
149
+ showDivider: true,
150
+ variant: 'default',
151
+ headerSpacing: 'comfortable',
152
+ contentSpacing: 'comfortable',
153
+ animationDuration: 300,
154
+ disableAnimations: false,
155
+ toggleAriaLabel: 'Toggle content visibility',
156
+ };
157
+
158
+ /**
159
+ * Animation style configurations
160
+ */
161
+ export interface AnimationConfig {
162
+ duration: number;
163
+ easing: string;
164
+ transform?: string;
165
+ opacity?: [number, number];
166
+ }
167
+
168
+ export const animationConfigs: Record<NonNullable<CollapsibleLayoutProps['animationStyle']>, AnimationConfig> = {
169
+ fade: {
170
+ duration: 300,
171
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
172
+ opacity: [0, 1],
173
+ },
174
+ slide: {
175
+ duration: 300,
176
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
177
+ transform: 'translateY(-10px)',
178
+ },
179
+ scale: {
180
+ duration: 200,
181
+ easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)',
182
+ transform: 'scale(0.95)',
183
+ opacity: [0, 1],
184
+ },
185
+ };
186
+
187
+ /**
188
+ * Spacing configurations
189
+ */
190
+ export interface SpacingConfig {
191
+ padding: string;
192
+ gap?: string;
193
+ }
194
+
195
+ export const spacingConfigs: Record<NonNullable<CollapsibleLayoutProps['headerSpacing'] | CollapsibleLayoutProps['contentSpacing']>, SpacingConfig> = {
196
+ compact: {
197
+ padding: '8px 12px',
198
+ gap: '4px',
199
+ },
200
+ comfortable: {
201
+ padding: '16px 20px',
202
+ gap: '8px',
203
+ },
204
+ spacious: {
205
+ padding: '24px 32px',
206
+ gap: '16px',
207
+ },
208
+ };
209
+
210
+ /**
211
+ * Utility type for extracting controlled vs uncontrolled props
212
+ */
213
+ export type ControlledCollapsibleLayoutProps = CollapsibleLayoutProps & {
214
+ collapsed: boolean;
215
+ onToggle: (collapsed: boolean) => void;
216
+ };
217
+
218
+ export type UncontrolledCollapsibleLayoutProps = CollapsibleLayoutProps & {
219
+ defaultCollapsed?: boolean;
220
+ onToggle?: (collapsed: boolean) => void;
221
+ };
222
+
223
+ /**
224
+ * Hook return type for managing collapsed state
225
+ */
226
+ export interface UseCollapsibleLayoutState {
227
+ collapsed: boolean;
228
+ toggle: () => void;
229
+ setCollapsed: (collapsed: boolean) => void;
230
+ isControlled: boolean;
231
+ }
@@ -93,6 +93,7 @@ export type LoadingState = 'idle' | 'loading' | 'success' | 'error';
93
93
 
94
94
  // Export all content-related types
95
95
  export * from './CacheProvider';
96
+ export * from './CollapsibleLayout';
96
97
  export * from './ContentProxy';
97
98
  export * from './DataTypes';
98
99
  export * from './TemplateProvider';
@@ -1,7 +0,0 @@
1
- /**
2
- * Schema builders - Re-exported from @qwickapps/schema
3
- *
4
- * @deprecated Import directly from '@qwickapps/schema' instead
5
- */
6
- export { FieldBuilder, SchemaBuilder, ModelBuilder, createSchema, field, model, Fields } from '@qwickapps/schema';
7
- //# sourceMappingURL=Builders.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Builders.d.ts","sourceRoot":"","sources":["../../src/schemas/Builders.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,KAAK,EACL,KAAK,EACL,MAAM,EACP,MAAM,mBAAmB,CAAC"}
@@ -1,7 +0,0 @@
1
- /**
2
- * Schema types - Re-exported from @qwickapps/schema
3
- *
4
- * @deprecated Import directly from '@qwickapps/schema' instead
5
- */
6
- export { Schema, Model, FieldDefinition, DataType, FieldType, ValidationRules, EditorConfig } from '@qwickapps/schema';
7
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schemas/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,MAAM,EACN,KAAK,EACL,eAAe,EACf,QAAQ,EACR,SAAS,EACT,eAAe,EACf,YAAY,EACb,MAAM,mBAAmB,CAAC"}
@@ -1,7 +0,0 @@
1
- /**
2
- * Data binding types - Re-exported from @qwickapps/schema
3
- *
4
- * @deprecated Import directly from '@qwickapps/schema' instead
5
- */
6
- export { DataBindingProps, DataBindingMeta, DataBindingOptions, WithDataBinding, DataBindingResult } from '@qwickapps/schema';
7
- //# sourceMappingURL=DataBinding.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DataBinding.d.ts","sourceRoot":"","sources":["../../src/types/DataBinding.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EAClB,MAAM,mBAAmB,CAAC"}
@@ -1,7 +0,0 @@
1
- /**
2
- * Data provider interface - Re-exported from @qwickapps/schema
3
- *
4
- * @deprecated Import directly from '@qwickapps/schema' instead
5
- */
6
- export { IDataProvider, DataResponse, ModelInstance, SelectOptions } from '@qwickapps/schema';
7
- //# sourceMappingURL=DataProvider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DataProvider.d.ts","sourceRoot":"","sources":["../../src/types/DataProvider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}