@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.
- package/README.md +326 -0
- package/dist/components/AccessibilityProvider.d.ts +64 -0
- package/dist/components/AccessibilityProvider.d.ts.map +1 -0
- package/dist/components/Breadcrumbs.d.ts +39 -0
- package/dist/components/Breadcrumbs.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.d.ts +39 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/components/QwickApp.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/index.d.ts +3 -0
- package/dist/components/index.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/index.bundled.css +12 -0
- package/dist/index.esm.js +1678 -25
- package/dist/index.js +1689 -21
- 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/AccessibilityProvider.tsx +466 -0
- package/src/components/Breadcrumbs.tsx +223 -0
- package/src/components/ErrorBoundary.tsx +216 -0
- package/src/components/QwickApp.tsx +17 -11
- package/src/components/__tests__/AccessibilityProvider.test.tsx +330 -0
- package/src/components/__tests__/Breadcrumbs.test.tsx +268 -0
- package/src/components/__tests__/ErrorBoundary.test.tsx +163 -0
- package/src/components/forms/FormBlock.tsx +2 -2
- package/src/components/index.ts +3 -0
- 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/schemas/CollapsibleLayoutSchema.ts +276 -0
- package/src/schemas/SwitchInputFieldSchema.ts +99 -0
- package/src/stories/AccessibilityProvider.stories.tsx +284 -0
- package/src/stories/Breadcrumbs.stories.tsx +304 -0
- package/src/stories/CollapsibleLayout.stories.tsx +1566 -0
- package/src/stories/ErrorBoundary.stories.tsx +159 -0
- package/src/types/CollapsibleLayout.ts +231 -0
- package/src/types/index.ts +1 -0
- package/dist/schemas/Builders.d.ts +0 -7
- package/dist/schemas/Builders.d.ts.map +0 -1
- package/dist/schemas/types.d.ts +0 -7
- package/dist/schemas/types.d.ts.map +0 -1
- package/dist/types/DataBinding.d.ts +0 -7
- package/dist/types/DataBinding.d.ts.map +0 -1
- package/dist/types/DataProvider.d.ts +0 -7
- package/dist/types/DataProvider.d.ts.map +0 -1
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Breadcrumbs, useBreadcrumbs, type BreadcrumbItem } from '../components/Breadcrumbs';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
// Icons for demo
|
|
6
|
+
const HomeIcon = () => (
|
|
7
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
8
|
+
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
|
|
9
|
+
</svg>
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
const FolderIcon = () => (
|
|
13
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
14
|
+
<path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/>
|
|
15
|
+
</svg>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const FileIcon = () => (
|
|
19
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
20
|
+
<path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z"/>
|
|
21
|
+
</svg>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Demo component with navigation simulation
|
|
25
|
+
const BreadcrumbDemo = () => {
|
|
26
|
+
const { breadcrumbs, setBreadcrumbs, addBreadcrumb, removeBreadcrumb, clearBreadcrumbs } = useBreadcrumbs();
|
|
27
|
+
const [currentPath, setCurrentPath] = React.useState('Home > Documents > Projects');
|
|
28
|
+
|
|
29
|
+
const samplePaths = [
|
|
30
|
+
'Home',
|
|
31
|
+
'Home > Documents',
|
|
32
|
+
'Home > Documents > Projects',
|
|
33
|
+
'Home > Documents > Projects > QwickApps',
|
|
34
|
+
'Home > Documents > Projects > QwickApps > Framework',
|
|
35
|
+
'Home > Store > Products',
|
|
36
|
+
'Home > Store > Products > Electronics > Computers',
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const pathToBreadcrumbs = (path: string): BreadcrumbItem[] => {
|
|
40
|
+
const parts = path.split(' > ');
|
|
41
|
+
return parts.map((part, index) => ({
|
|
42
|
+
label: part,
|
|
43
|
+
href: `/${part.toLowerCase().replace(/\s+/g, '-')}`,
|
|
44
|
+
icon: index === 0 ? <HomeIcon /> :
|
|
45
|
+
index === parts.length - 1 ? <FileIcon /> :
|
|
46
|
+
<FolderIcon />,
|
|
47
|
+
current: index === parts.length - 1
|
|
48
|
+
}));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
React.useEffect(() => {
|
|
52
|
+
setBreadcrumbs(pathToBreadcrumbs(currentPath));
|
|
53
|
+
}, [currentPath, setBreadcrumbs]);
|
|
54
|
+
|
|
55
|
+
const handleNavigate = (item: BreadcrumbItem, index: number) => {
|
|
56
|
+
const newPath = breadcrumbs.slice(0, index + 1).map(b => b.label).join(' > ');
|
|
57
|
+
setCurrentPath(newPath);
|
|
58
|
+
alert(`Navigated to: ${item.label}`);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div style={{ padding: '2rem' }}>
|
|
63
|
+
<h2>Interactive Breadcrumbs Demo</h2>
|
|
64
|
+
|
|
65
|
+
<div style={{ marginBottom: '2rem' }}>
|
|
66
|
+
<h3>Current Navigation:</h3>
|
|
67
|
+
<Breadcrumbs items={breadcrumbs} onNavigate={handleNavigate} />
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div style={{ marginBottom: '2rem' }}>
|
|
71
|
+
<h3>Navigate to Different Paths:</h3>
|
|
72
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
|
|
73
|
+
{samplePaths.map((path) => (
|
|
74
|
+
<button
|
|
75
|
+
key={path}
|
|
76
|
+
onClick={() => setCurrentPath(path)}
|
|
77
|
+
style={{
|
|
78
|
+
padding: '0.5rem 1rem',
|
|
79
|
+
background: path === currentPath ? '#007cba' : '#f0f0f0',
|
|
80
|
+
color: path === currentPath ? 'white' : 'black',
|
|
81
|
+
border: '1px solid #ddd',
|
|
82
|
+
borderRadius: '4px',
|
|
83
|
+
textAlign: 'left',
|
|
84
|
+
cursor: 'pointer'
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
{path}
|
|
88
|
+
</button>
|
|
89
|
+
))}
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<div>
|
|
94
|
+
<h3>Breadcrumb Controls:</h3>
|
|
95
|
+
<div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
|
|
96
|
+
<button
|
|
97
|
+
onClick={() => addBreadcrumb({ label: 'New Item', href: '/new' })}
|
|
98
|
+
style={{ padding: '0.5rem 1rem', background: '#28a745', color: 'white', border: 'none', borderRadius: '4px' }}
|
|
99
|
+
>
|
|
100
|
+
Add Item
|
|
101
|
+
</button>
|
|
102
|
+
<button
|
|
103
|
+
onClick={() => removeBreadcrumb(breadcrumbs.length - 1)}
|
|
104
|
+
style={{ padding: '0.5rem 1rem', background: '#dc3545', color: 'white', border: 'none', borderRadius: '4px' }}
|
|
105
|
+
>
|
|
106
|
+
Remove Last
|
|
107
|
+
</button>
|
|
108
|
+
<button
|
|
109
|
+
onClick={clearBreadcrumbs}
|
|
110
|
+
style={{ padding: '0.5rem 1rem', background: '#6c757d', color: 'white', border: 'none', borderRadius: '4px' }}
|
|
111
|
+
>
|
|
112
|
+
Clear All
|
|
113
|
+
</button>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const meta: Meta<typeof Breadcrumbs> = {
|
|
121
|
+
title: 'Components/Breadcrumbs',
|
|
122
|
+
component: Breadcrumbs,
|
|
123
|
+
parameters: {
|
|
124
|
+
layout: 'centered',
|
|
125
|
+
docs: {
|
|
126
|
+
description: {
|
|
127
|
+
component: 'A navigation breadcrumb component that shows the current page location within the application hierarchy. Supports accessibility, keyboard navigation, and customization.',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
tags: ['autodocs'],
|
|
132
|
+
argTypes: {
|
|
133
|
+
items: {
|
|
134
|
+
description: 'Array of breadcrumb items to display',
|
|
135
|
+
},
|
|
136
|
+
separator: {
|
|
137
|
+
description: 'Custom separator between breadcrumb items',
|
|
138
|
+
control: 'text',
|
|
139
|
+
},
|
|
140
|
+
className: {
|
|
141
|
+
description: 'Additional CSS classes to apply',
|
|
142
|
+
control: 'text',
|
|
143
|
+
},
|
|
144
|
+
onNavigate: {
|
|
145
|
+
description: 'Callback function when a breadcrumb is clicked',
|
|
146
|
+
action: 'navigate',
|
|
147
|
+
},
|
|
148
|
+
maxItems: {
|
|
149
|
+
description: 'Maximum number of items to show (truncates with ellipsis)',
|
|
150
|
+
control: { type: 'number', min: 1, max: 10 },
|
|
151
|
+
},
|
|
152
|
+
showRoot: {
|
|
153
|
+
description: 'Whether to show the root (first) item',
|
|
154
|
+
control: 'boolean',
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export default meta;
|
|
160
|
+
type Story = StoryObj<typeof meta>;
|
|
161
|
+
|
|
162
|
+
// Sample breadcrumb data
|
|
163
|
+
const sampleBreadcrumbs: BreadcrumbItem[] = [
|
|
164
|
+
{ label: 'Home', href: '/', icon: <HomeIcon /> },
|
|
165
|
+
{ label: 'Products', href: '/products', icon: <FolderIcon /> },
|
|
166
|
+
{ label: 'Electronics', href: '/products/electronics', icon: <FolderIcon /> },
|
|
167
|
+
{ label: 'Laptop', href: '/products/electronics/laptop', icon: <FileIcon />, current: true },
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
// Default story
|
|
171
|
+
export const Default: Story = {
|
|
172
|
+
args: {
|
|
173
|
+
items: sampleBreadcrumbs,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Story with custom separator
|
|
178
|
+
export const CustomSeparator: Story = {
|
|
179
|
+
args: {
|
|
180
|
+
items: sampleBreadcrumbs,
|
|
181
|
+
separator: '→',
|
|
182
|
+
},
|
|
183
|
+
parameters: {
|
|
184
|
+
docs: {
|
|
185
|
+
description: {
|
|
186
|
+
story: 'Breadcrumbs with a custom arrow separator instead of the default slash.',
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Story with emoji separator
|
|
193
|
+
export const EmojiSeparator: Story = {
|
|
194
|
+
args: {
|
|
195
|
+
items: sampleBreadcrumbs,
|
|
196
|
+
separator: '🏠',
|
|
197
|
+
},
|
|
198
|
+
parameters: {
|
|
199
|
+
docs: {
|
|
200
|
+
description: {
|
|
201
|
+
story: 'Breadcrumbs with an emoji separator for a more playful look.',
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// Story with max items (truncation)
|
|
208
|
+
export const TruncatedItems: Story = {
|
|
209
|
+
args: {
|
|
210
|
+
items: [
|
|
211
|
+
{ label: 'Home', href: '/' },
|
|
212
|
+
{ label: 'Level 1', href: '/level1' },
|
|
213
|
+
{ label: 'Level 2', href: '/level1/level2' },
|
|
214
|
+
{ label: 'Level 3', href: '/level1/level2/level3' },
|
|
215
|
+
{ label: 'Level 4', href: '/level1/level2/level3/level4' },
|
|
216
|
+
{ label: 'Current Page', href: '/level1/level2/level3/level4/current', current: true },
|
|
217
|
+
],
|
|
218
|
+
maxItems: 4,
|
|
219
|
+
},
|
|
220
|
+
parameters: {
|
|
221
|
+
docs: {
|
|
222
|
+
description: {
|
|
223
|
+
story: 'When there are too many items, middle items are replaced with ellipsis.',
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// Story without root item
|
|
230
|
+
export const WithoutRoot: Story = {
|
|
231
|
+
args: {
|
|
232
|
+
items: sampleBreadcrumbs,
|
|
233
|
+
showRoot: false,
|
|
234
|
+
},
|
|
235
|
+
parameters: {
|
|
236
|
+
docs: {
|
|
237
|
+
description: {
|
|
238
|
+
story: 'Breadcrumbs without showing the root (first) item.',
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
// Story without icons
|
|
245
|
+
export const WithoutIcons: Story = {
|
|
246
|
+
args: {
|
|
247
|
+
items: [
|
|
248
|
+
{ label: 'Home', href: '/' },
|
|
249
|
+
{ label: 'Products', href: '/products' },
|
|
250
|
+
{ label: 'Electronics', href: '/products/electronics' },
|
|
251
|
+
{ label: 'Laptop', href: '/products/electronics/laptop', current: true },
|
|
252
|
+
],
|
|
253
|
+
},
|
|
254
|
+
parameters: {
|
|
255
|
+
docs: {
|
|
256
|
+
description: {
|
|
257
|
+
story: 'Simple breadcrumbs without icons, just text navigation.',
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// Story with navigation handler
|
|
264
|
+
export const WithNavigation: Story = {
|
|
265
|
+
args: {
|
|
266
|
+
items: sampleBreadcrumbs,
|
|
267
|
+
onNavigate: (item, index) => {
|
|
268
|
+
alert(`Clicked on "${item.label}" at index ${index}`);
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
parameters: {
|
|
272
|
+
docs: {
|
|
273
|
+
description: {
|
|
274
|
+
story: 'Breadcrumbs with a navigation handler that prevents default link behavior.',
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// Interactive demo story
|
|
281
|
+
export const InteractiveDemo: Story = {
|
|
282
|
+
render: () => <BreadcrumbDemo />,
|
|
283
|
+
parameters: {
|
|
284
|
+
docs: {
|
|
285
|
+
description: {
|
|
286
|
+
story: 'Interactive demo showing breadcrumb navigation with the useBreadcrumbs hook.',
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// Accessibility showcase
|
|
293
|
+
export const AccessibilityShowcase: Story = {
|
|
294
|
+
args: {
|
|
295
|
+
items: sampleBreadcrumbs,
|
|
296
|
+
},
|
|
297
|
+
parameters: {
|
|
298
|
+
docs: {
|
|
299
|
+
description: {
|
|
300
|
+
story: 'This breadcrumb component includes proper ARIA labels, keyboard navigation, and screen reader support. Try using Tab and Enter keys to navigate.',
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
};
|