@ttoss/components 2.12.4 → 2.12.6
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 +125 -155
- package/dist/Accordion/index.d.ts +140 -8
- package/dist/esm/Accordion/index.js +107 -37
- package/dist/esm/DatePicker/index.js +8 -5
- package/package.json +22 -25
package/README.md
CHANGED
|
@@ -8,38 +8,59 @@ React components for the ttoss ecosystem. **ESM only** package.
|
|
|
8
8
|
pnpm add @ttoss/components @ttoss/ui @emotion/react @ttoss/react-hooks
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
[View all components in Storybook](https://storybook.ttoss.dev/?path=/docs/components-accordion--docs)
|
|
12
12
|
|
|
13
|
-
## Components
|
|
13
|
+
## Components
|
|
14
14
|
|
|
15
15
|
All components are theme-aware and integrate seamlessly with `@ttoss/ui`.
|
|
16
16
|
|
|
17
17
|
### Accordion
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Accessible accordion component with collapsible content sections. [Docs](https://storybook.ttoss.dev/?path=/docs/components-accordion--docs)
|
|
20
20
|
|
|
21
21
|
```tsx
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
22
|
+
import { Accordion } from '@ttoss/components/Accordion';
|
|
23
|
+
|
|
24
|
+
<Accordion
|
|
25
|
+
items={[
|
|
26
|
+
{
|
|
27
|
+
title: 'Section 1',
|
|
28
|
+
content: 'Content for section 1',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
title: 'Section 2',
|
|
32
|
+
content: 'Content for section 2',
|
|
33
|
+
},
|
|
34
|
+
]}
|
|
35
|
+
/>;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### DatePicker
|
|
39
|
+
|
|
40
|
+
Date range picker with presets and mobile support. [Docs](https://storybook.ttoss.dev/?path=/docs/components-datepicker--docs)
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { DatePicker } from '@ttoss/components/DatePicker';
|
|
44
|
+
|
|
45
|
+
<DatePicker
|
|
46
|
+
label="Select period"
|
|
47
|
+
value={dateRange}
|
|
48
|
+
onChange={setDateRange}
|
|
49
|
+
presets={[
|
|
50
|
+
{
|
|
51
|
+
label: 'Last 7 days',
|
|
52
|
+
getValue: () => ({
|
|
53
|
+
from: subDays(new Date(), 7),
|
|
54
|
+
to: new Date(),
|
|
55
|
+
}),
|
|
56
|
+
},
|
|
57
|
+
]}
|
|
58
|
+
/>;
|
|
38
59
|
```
|
|
39
60
|
|
|
40
61
|
### Drawer
|
|
41
62
|
|
|
42
|
-
Slide-out panels from screen edges. [
|
|
63
|
+
Slide-out panels from screen edges. [Docs](https://storybook.ttoss.dev/?path=/docs/components-drawer--docs)
|
|
43
64
|
|
|
44
65
|
```tsx
|
|
45
66
|
import { Drawer } from '@ttoss/components/Drawer';
|
|
@@ -49,65 +70,56 @@ import { Drawer } from '@ttoss/components/Drawer';
|
|
|
49
70
|
</Drawer>;
|
|
50
71
|
```
|
|
51
72
|
|
|
73
|
+
### EnhancedTitle
|
|
74
|
+
|
|
75
|
+
Structured title section with icon, badges, and metadata. [Docs](https://storybook.ttoss.dev/?path=/docs/components-enhancedtitle--docs)
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { EnhancedTitle } from '@ttoss/components/EnhancedTitle';
|
|
79
|
+
|
|
80
|
+
<EnhancedTitle
|
|
81
|
+
icon="fluent:shield-24-filled"
|
|
82
|
+
title="Starter Plan"
|
|
83
|
+
frontTitle="$49.90/mo"
|
|
84
|
+
description="Perfect for small teams"
|
|
85
|
+
variant="primary"
|
|
86
|
+
topBadges={[
|
|
87
|
+
{
|
|
88
|
+
label: 'Active',
|
|
89
|
+
variant: 'positive',
|
|
90
|
+
icon: 'fluent:checkmark-circle-24-filled',
|
|
91
|
+
},
|
|
92
|
+
]}
|
|
93
|
+
bottomBadges={[
|
|
94
|
+
{ label: 'OneClick Tracking', icon: 'fluent:checkmark-24-filled' },
|
|
95
|
+
]}
|
|
96
|
+
/>;
|
|
97
|
+
```
|
|
98
|
+
|
|
52
99
|
### FileUploader
|
|
53
100
|
|
|
54
|
-
Controlled file uploader with drag-and-drop
|
|
101
|
+
Controlled file uploader with drag-and-drop, previews, and validation. [Docs](https://storybook.ttoss.dev/?path=/docs/components-fileuploader--docs)
|
|
55
102
|
|
|
56
103
|
```tsx
|
|
57
104
|
import { FileUploader } from '@ttoss/components/FileUploader';
|
|
58
|
-
import { useState } from 'react';
|
|
59
|
-
|
|
60
|
-
const [files, setFiles] = useState([
|
|
61
|
-
{
|
|
62
|
-
id: 'file-1',
|
|
63
|
-
name: 'document.pdf',
|
|
64
|
-
url: 'https://example.com/files/document.pdf',
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
id: 'file-2',
|
|
68
|
-
name: 'image.jpg',
|
|
69
|
-
imageUrl: 'https://example.com/images/thumb.jpg', // Optional preview
|
|
70
|
-
url: 'https://example.com/files/image.jpg',
|
|
71
|
-
},
|
|
72
|
-
]);
|
|
73
105
|
|
|
74
106
|
<FileUploader
|
|
75
|
-
// Required: Upload handler
|
|
76
107
|
onUpload={async (file, onProgress) => {
|
|
77
|
-
// Your upload logic here
|
|
78
|
-
onProgress?.(50); // Report progress
|
|
79
108
|
const result = await uploadToServer(file);
|
|
80
109
|
return { url: result.url, id: result.id, name: result.name };
|
|
81
110
|
}}
|
|
82
|
-
// Controlled files list
|
|
83
111
|
files={files}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
setFiles([...files, { id: result.id, name: file.name, url: result.url }]);
|
|
87
|
-
}}
|
|
88
|
-
onRemove={(file, index) => {
|
|
89
|
-
setFiles(files.filter((_, i) => i !== index));
|
|
90
|
-
}}
|
|
91
|
-
// Optional: Validation
|
|
112
|
+
onUploadComplete={(file, result) => setFiles([...files, result])}
|
|
113
|
+
onRemove={(file, index) => setFiles(files.filter((_, i) => i !== index))}
|
|
92
114
|
accept="image/*,.pdf"
|
|
93
|
-
maxSize={10 * 1024 * 1024}
|
|
115
|
+
maxSize={10 * 1024 * 1024}
|
|
94
116
|
maxFiles={5}
|
|
95
117
|
/>;
|
|
96
118
|
```
|
|
97
119
|
|
|
98
|
-
**Key Features:**
|
|
99
|
-
|
|
100
|
-
- **Controlled component**: Pass `files` prop to display uploaded files
|
|
101
|
-
- **Clickable file names**: Names are links that open the file URL
|
|
102
|
-
- **Image previews**: Show thumbnails when `imageUrl` is provided
|
|
103
|
-
- **Remove functionality**: Each file has a remove button
|
|
104
|
-
- **Upload callbacks**: `onUploadStart`, `onUploadProgress`, `onUploadComplete`, `onUploadError`
|
|
105
|
-
- **Validation**: File type, size, and quantity limits
|
|
106
|
-
- **Drag-and-drop**: Native drag-and-drop support
|
|
107
|
-
|
|
108
120
|
### InstallPwa
|
|
109
121
|
|
|
110
|
-
PWA installation prompt component.
|
|
122
|
+
PWA installation prompt component.
|
|
111
123
|
|
|
112
124
|
```tsx
|
|
113
125
|
import { InstallPwa } from '@ttoss/components/InstallPwa';
|
|
@@ -117,7 +129,7 @@ import { InstallPwa } from '@ttoss/components/InstallPwa';
|
|
|
117
129
|
|
|
118
130
|
### JsonEditor
|
|
119
131
|
|
|
120
|
-
JSON editor component. Re-exports from [json-edit-react](https://carlosdevpereira.github.io/json-edit-react/). [
|
|
132
|
+
JSON editor component. Re-exports from [json-edit-react](https://carlosdevpereira.github.io/json-edit-react/). [Docs](https://storybook.ttoss.dev/?path=/docs/components-jsoneditor--docs)
|
|
121
133
|
|
|
122
134
|
```tsx
|
|
123
135
|
import { JsonEditor } from '@ttoss/components/JsonEditor';
|
|
@@ -127,7 +139,7 @@ import { JsonEditor } from '@ttoss/components/JsonEditor';
|
|
|
127
139
|
|
|
128
140
|
### JsonView
|
|
129
141
|
|
|
130
|
-
JSON viewer component. Re-exports from [react-json-view-lite](https://github.com/AnyRoad/react-json-view-lite).
|
|
142
|
+
JSON viewer component. Re-exports from [react-json-view-lite](https://github.com/AnyRoad/react-json-view-lite).
|
|
131
143
|
|
|
132
144
|
```tsx
|
|
133
145
|
import { JsonView } from '@ttoss/components/JsonView';
|
|
@@ -137,7 +149,7 @@ import { JsonView } from '@ttoss/components/JsonView';
|
|
|
137
149
|
|
|
138
150
|
### List
|
|
139
151
|
|
|
140
|
-
Unordered lists with customizable items. [
|
|
152
|
+
Unordered lists with customizable items. [Docs](https://storybook.ttoss.dev/?path=/docs/components-list--docs)
|
|
141
153
|
|
|
142
154
|
```tsx
|
|
143
155
|
import { List, ListItem } from '@ttoss/components/List';
|
|
@@ -150,12 +162,11 @@ import { List, ListItem } from '@ttoss/components/List';
|
|
|
150
162
|
|
|
151
163
|
### LockedOverlay
|
|
152
164
|
|
|
153
|
-
Block and display locked features or restricted content within a container. Unlike modals, overlays block only their parent container. [
|
|
165
|
+
Block and display locked features or restricted content within a container. Unlike modals, overlays block only their parent container. [Docs](https://storybook.ttoss.dev/?path=/docs/components-lockedoverlay--docs)
|
|
154
166
|
|
|
155
167
|
```tsx
|
|
156
168
|
import { LockedOverlay } from '@ttoss/components/LockedOverlay';
|
|
157
169
|
|
|
158
|
-
// Parent must have position: relative
|
|
159
170
|
<Box sx={{ position: 'relative' }}>
|
|
160
171
|
<LockedOverlay
|
|
161
172
|
isOpen={isOpen}
|
|
@@ -182,7 +193,7 @@ import { LockedOverlay } from '@ttoss/components/LockedOverlay';
|
|
|
182
193
|
|
|
183
194
|
### Markdown
|
|
184
195
|
|
|
185
|
-
Render markdown content with theme integration. [
|
|
196
|
+
Render markdown content with theme integration. [Docs](https://storybook.ttoss.dev/?path=/docs/components-markdown--docs)
|
|
186
197
|
|
|
187
198
|
```tsx
|
|
188
199
|
import { Markdown } from '@ttoss/components/Markdown';
|
|
@@ -198,7 +209,7 @@ import { Markdown } from '@ttoss/components/Markdown';
|
|
|
198
209
|
|
|
199
210
|
### Menu
|
|
200
211
|
|
|
201
|
-
Dropdown menus with customizable triggers. [
|
|
212
|
+
Dropdown menus with customizable triggers. [Docs](https://storybook.ttoss.dev/?path=/docs/components-menu--docs)
|
|
202
213
|
|
|
203
214
|
```tsx
|
|
204
215
|
import { Menu } from '@ttoss/components/Menu';
|
|
@@ -209,95 +220,44 @@ import { Menu } from '@ttoss/components/Menu';
|
|
|
209
220
|
</Menu>;
|
|
210
221
|
```
|
|
211
222
|
|
|
223
|
+
### MetricCard
|
|
224
|
+
|
|
225
|
+
Display metrics with progress visualization, status indicators, and contextual information. [Docs](https://storybook.ttoss.dev/?path=/docs/components-metriccard--docs)
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
import { MetricCard } from '@ttoss/components/MetricCard';
|
|
229
|
+
|
|
230
|
+
<MetricCard
|
|
231
|
+
metric={{
|
|
232
|
+
type: 'number',
|
|
233
|
+
value: 8,
|
|
234
|
+
max: 10,
|
|
235
|
+
label: 'Active Users',
|
|
236
|
+
icon: 'mdi:account-group',
|
|
237
|
+
}}
|
|
238
|
+
/>;
|
|
239
|
+
```
|
|
240
|
+
|
|
212
241
|
### NavList
|
|
213
242
|
|
|
214
|
-
Navigation lists for sidebars, menus, and dropdowns with icons, grouping, and routing integration. [
|
|
243
|
+
Navigation lists for sidebars, menus, and dropdowns with icons, grouping, and routing integration. [Docs](https://storybook.ttoss.dev/?path=/docs/components-navlist--docs)
|
|
215
244
|
|
|
216
245
|
```tsx
|
|
217
246
|
import { NavList } from '@ttoss/components/NavList';
|
|
218
247
|
|
|
219
|
-
// Simple navigation
|
|
220
248
|
<NavList
|
|
221
249
|
items={[
|
|
222
250
|
{ id: '1', label: 'Home', href: '/', icon: 'mdi:home' },
|
|
223
251
|
{ id: '2', label: 'Profile', href: '/profile', icon: 'mdi:account' },
|
|
224
|
-
{ id: '3', label: 'Settings', href: '/settings', icon: 'mdi:cog' },
|
|
225
252
|
]}
|
|
226
253
|
variant="sidebar"
|
|
227
|
-
/>
|
|
228
|
-
|
|
229
|
-
// With groups
|
|
230
|
-
<NavList
|
|
231
|
-
groups={[
|
|
232
|
-
{
|
|
233
|
-
id: 'main',
|
|
234
|
-
label: 'Main Menu',
|
|
235
|
-
items: [
|
|
236
|
-
{ id: '1', label: 'Dashboard', href: '/dashboard', icon: 'mdi:view-dashboard' },
|
|
237
|
-
{ id: '2', label: 'Analytics', href: '/analytics', icon: 'mdi:chart-line' },
|
|
238
|
-
],
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
id: 'settings',
|
|
242
|
-
label: 'Settings',
|
|
243
|
-
items: [
|
|
244
|
-
{ id: '3', label: 'Account', href: '/account', icon: 'mdi:account-cog' },
|
|
245
|
-
],
|
|
246
|
-
divider: true, // Divider after group
|
|
247
|
-
},
|
|
248
|
-
]}
|
|
249
|
-
/>
|
|
250
|
-
|
|
251
|
-
// With Next.js routing
|
|
252
|
-
import NextLink from 'next/link';
|
|
253
|
-
|
|
254
|
-
<NavList
|
|
255
|
-
items={items}
|
|
256
254
|
LinkComponent={NextLink}
|
|
257
|
-
|
|
258
|
-
/>
|
|
259
|
-
|
|
260
|
-
// Custom Link Component
|
|
261
|
-
// IMPORTANT: Always spread {...props} to preserve styling
|
|
262
|
-
// React Router example (uses 'to' instead of 'href')
|
|
263
|
-
import { Link as RouterLink } from 'react-router-dom';
|
|
264
|
-
|
|
265
|
-
const ReactRouterLink = ({
|
|
266
|
-
href,
|
|
267
|
-
children,
|
|
268
|
-
...props
|
|
269
|
-
}: React.PropsWithChildren<LinkComponentProps>) => {
|
|
270
|
-
return (
|
|
271
|
-
<RouterLink
|
|
272
|
-
to={href}
|
|
273
|
-
{...props} // Required to preserve NavList styles
|
|
274
|
-
>
|
|
275
|
-
{children}
|
|
276
|
-
</RouterLink>
|
|
277
|
-
);
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
<NavList items={items} LinkComponent={ReactRouterLink} />
|
|
255
|
+
/>;
|
|
281
256
|
```
|
|
282
257
|
|
|
283
|
-
**Variants:**
|
|
284
|
-
|
|
285
|
-
- `sidebar` - Sidebar navigation with larger icons (20px) and generous spacing
|
|
286
|
-
- `menu` - Card-based menu with hover animations (18px icons)
|
|
287
|
-
- `dropdown` - Compact dropdown with subtle borders (16px icons)
|
|
288
|
-
|
|
289
|
-
**Features:**
|
|
290
|
-
|
|
291
|
-
- **Auto-grouping** - Items automatically group by `group` property
|
|
292
|
-
- **Active states** - Highlight active items with `active` prop
|
|
293
|
-
- **Disabled items** - Prevent interaction with `disabled` prop
|
|
294
|
-
- **Dividers** - Visual separators with `divider` prop on items or groups
|
|
295
|
-
- **Icon support** - 200k+ icons via `@ttoss/react-icons`
|
|
296
|
-
- **Custom routing** - Compatible with Next.js, React Router via `LinkComponent`
|
|
297
|
-
|
|
298
258
|
### Modal
|
|
299
259
|
|
|
300
|
-
Theme-aware modals with accessibility features. [
|
|
260
|
+
Theme-aware modals with accessibility features. [Docs](https://storybook.ttoss.dev/?path=/docs/components-modal--docs)
|
|
301
261
|
|
|
302
262
|
```tsx
|
|
303
263
|
import { Modal } from '@ttoss/components/Modal';
|
|
@@ -313,7 +273,7 @@ import { Modal } from '@ttoss/components/Modal';
|
|
|
313
273
|
|
|
314
274
|
### NotificationCard
|
|
315
275
|
|
|
316
|
-
Display notification messages with actions. [
|
|
276
|
+
Display notification messages with actions. [Docs](https://storybook.ttoss.dev/?path=/docs/components-notificationcard--docs)
|
|
317
277
|
|
|
318
278
|
```tsx
|
|
319
279
|
import { NotificationCard } from '@ttoss/components/NotificationCard';
|
|
@@ -327,7 +287,7 @@ import { NotificationCard } from '@ttoss/components/NotificationCard';
|
|
|
327
287
|
|
|
328
288
|
### NotificationsMenu
|
|
329
289
|
|
|
330
|
-
Menu component for displaying notifications. [
|
|
290
|
+
Menu component for displaying notifications. [Docs](https://storybook.ttoss.dev/?path=/docs/components-notificationsmenu--docs)
|
|
331
291
|
|
|
332
292
|
```tsx
|
|
333
293
|
import { NotificationsMenu } from '@ttoss/components/NotificationsMenu';
|
|
@@ -340,7 +300,7 @@ import { NotificationsMenu } from '@ttoss/components/NotificationsMenu';
|
|
|
340
300
|
|
|
341
301
|
### Search
|
|
342
302
|
|
|
343
|
-
Debounced search input with loading states. [
|
|
303
|
+
Debounced search input with loading states. [Docs](https://storybook.ttoss.dev/?path=/docs/components-search--docs)
|
|
344
304
|
|
|
345
305
|
```tsx
|
|
346
306
|
import { Search } from '@ttoss/components/Search';
|
|
@@ -353,9 +313,25 @@ import { Search } from '@ttoss/components/Search';
|
|
|
353
313
|
/>;
|
|
354
314
|
```
|
|
355
315
|
|
|
316
|
+
### SpotlightCard
|
|
317
|
+
|
|
318
|
+
Interactive card with spotlight effect, icon, and action buttons. [Docs](https://storybook.ttoss.dev/?path=/docs/components-spotlightcard--docs)
|
|
319
|
+
|
|
320
|
+
```tsx
|
|
321
|
+
import { SpotlightCard } from '@ttoss/components/SpotlightCard';
|
|
322
|
+
|
|
323
|
+
<SpotlightCard
|
|
324
|
+
icon="mdi:rocket-launch"
|
|
325
|
+
title="Launch Product"
|
|
326
|
+
description="Deploy your product to production"
|
|
327
|
+
primaryButton={{ label: 'Deploy', onClick: handleDeploy }}
|
|
328
|
+
secondaryButton={{ label: 'Preview', onClick: handlePreview }}
|
|
329
|
+
/>;
|
|
330
|
+
```
|
|
331
|
+
|
|
356
332
|
### Table
|
|
357
333
|
|
|
358
|
-
Flexible tables with sorting and pagination. Uses [TanStack Table](https://tanstack.com/table/latest). [
|
|
334
|
+
Flexible tables with sorting and pagination. Uses [TanStack Table](https://tanstack.com/table/latest). [Docs](https://storybook.ttoss.dev/?path=/docs/components-table--docs)
|
|
359
335
|
|
|
360
336
|
```tsx
|
|
361
337
|
import {
|
|
@@ -364,14 +340,12 @@ import {
|
|
|
364
340
|
createColumnHelper,
|
|
365
341
|
} from '@ttoss/components/Table';
|
|
366
342
|
|
|
367
|
-
const columns = [
|
|
368
|
-
columnHelper.accessor('name', { header: 'Name' }),
|
|
369
|
-
columnHelper.accessor('email', { header: 'Email' }),
|
|
370
|
-
];
|
|
371
|
-
|
|
372
343
|
const table = useReactTable({
|
|
373
344
|
data,
|
|
374
|
-
columns
|
|
345
|
+
columns: [
|
|
346
|
+
columnHelper.accessor('name', { header: 'Name' }),
|
|
347
|
+
columnHelper.accessor('email', { header: 'Email' }),
|
|
348
|
+
],
|
|
375
349
|
getCoreRowModel: getCoreRowModel(),
|
|
376
350
|
});
|
|
377
351
|
|
|
@@ -403,7 +377,7 @@ const table = useReactTable({
|
|
|
403
377
|
|
|
404
378
|
### Tabs
|
|
405
379
|
|
|
406
|
-
Tab navigation with content panels. [
|
|
380
|
+
Tab navigation with content panels. [Docs](https://storybook.ttoss.dev/?path=/docs/components-tabs--docs)
|
|
407
381
|
|
|
408
382
|
```tsx
|
|
409
383
|
import { Tabs } from '@ttoss/components/Tabs';
|
|
@@ -422,7 +396,7 @@ import { Tabs } from '@ttoss/components/Tabs';
|
|
|
422
396
|
|
|
423
397
|
### Toast
|
|
424
398
|
|
|
425
|
-
Toast notification system. [
|
|
399
|
+
Toast notification system. [Docs](https://storybook.ttoss.dev/?path=/docs/components-toast--docs)
|
|
426
400
|
|
|
427
401
|
```tsx
|
|
428
402
|
import { Toast } from '@ttoss/components/Toast';
|
|
@@ -434,7 +408,3 @@ import { Toast } from '@ttoss/components/Toast';
|
|
|
434
408
|
onClose={() => setIsOpen(false)}
|
|
435
409
|
/>;
|
|
436
410
|
```
|
|
437
|
-
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
```
|
|
@@ -1,16 +1,148 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { BoxProps } from '@ttoss/ui';
|
|
3
|
-
|
|
3
|
+
import * as React from 'react';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Individual item for the Accordion component.
|
|
7
|
+
*/
|
|
8
|
+
type AccordionItem = {
|
|
9
|
+
/**
|
|
10
|
+
* Unique identifier for the accordion item.
|
|
11
|
+
* If not provided, will use the index as the key.
|
|
12
|
+
*/
|
|
13
|
+
id?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Title displayed in the accordion header.
|
|
16
|
+
*/
|
|
17
|
+
title: React.ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* Content displayed when the accordion item is expanded.
|
|
20
|
+
*/
|
|
21
|
+
content: React.ReactNode;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the item is disabled.
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Render props for custom accordion item rendering.
|
|
30
|
+
*/
|
|
31
|
+
type AccordionRenderItemProps = {
|
|
32
|
+
/**
|
|
33
|
+
* The accordion item data.
|
|
34
|
+
*/
|
|
35
|
+
item: AccordionItem;
|
|
36
|
+
/**
|
|
37
|
+
* Index of the item in the items array.
|
|
38
|
+
*/
|
|
39
|
+
index: number;
|
|
40
|
+
/**
|
|
41
|
+
* Whether the item is currently expanded.
|
|
42
|
+
*/
|
|
43
|
+
isExpanded: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Function to toggle the item's expanded state.
|
|
46
|
+
*/
|
|
47
|
+
toggle: () => void;
|
|
48
|
+
/**
|
|
49
|
+
* Generated IDs for accessibility.
|
|
50
|
+
*/
|
|
51
|
+
ids: {
|
|
52
|
+
itemId: string;
|
|
53
|
+
headingId: string;
|
|
54
|
+
panelId: string;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Props for the Accordion component.
|
|
59
|
+
*/
|
|
5
60
|
type AccordionProps = BoxProps & {
|
|
6
|
-
allowMultipleExpanded?: boolean;
|
|
7
|
-
allowZeroExpanded?: boolean;
|
|
8
|
-
preExpanded?: string[];
|
|
9
61
|
/**
|
|
10
|
-
*
|
|
62
|
+
* Array of accordion items to render.
|
|
63
|
+
*/
|
|
64
|
+
items: AccordionItem[];
|
|
65
|
+
/**
|
|
66
|
+
* Whether multiple items can be expanded at once.
|
|
67
|
+
* @default false
|
|
68
|
+
*/
|
|
69
|
+
multiple?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Index or array of indices for initially expanded items.
|
|
72
|
+
*/
|
|
73
|
+
defaultExpanded?: number | number[];
|
|
74
|
+
/**
|
|
75
|
+
* Callback invoked when items are expanded or collapsed.
|
|
76
|
+
* Receives array of currently expanded indices.
|
|
77
|
+
*/
|
|
78
|
+
onAccordionChange?: (expandedIndices: number[]) => void;
|
|
79
|
+
/**
|
|
80
|
+
* Custom render function for accordion items.
|
|
81
|
+
* Provides full control over item rendering while maintaining accessibility.
|
|
11
82
|
*/
|
|
12
|
-
|
|
83
|
+
renderItem?: (props: AccordionRenderItemProps) => React.ReactNode;
|
|
13
84
|
};
|
|
14
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Accessible accordion component with collapsible content sections.
|
|
87
|
+
*
|
|
88
|
+
* This component provides a simplified API for creating expandable/collapsible
|
|
89
|
+
* content sections. It uses design tokens from @ttoss/theme for consistent styling
|
|
90
|
+
* and follows WAI-ARIA accordion pattern for accessibility.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```tsx
|
|
94
|
+
* <Accordion
|
|
95
|
+
* items={[
|
|
96
|
+
* {
|
|
97
|
+
* title: 'Section 1',
|
|
98
|
+
* content: 'Content for section 1',
|
|
99
|
+
* },
|
|
100
|
+
* {
|
|
101
|
+
* title: 'Section 2',
|
|
102
|
+
* content: 'Content for section 2',
|
|
103
|
+
* },
|
|
104
|
+
* ]}
|
|
105
|
+
* />
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```tsx
|
|
110
|
+
* <Accordion
|
|
111
|
+
* multiple
|
|
112
|
+
* defaultExpanded={[0, 1]}
|
|
113
|
+
* items={[
|
|
114
|
+
* {
|
|
115
|
+
* id: 'item-1',
|
|
116
|
+
* title: 'Pre-expanded Section 1',
|
|
117
|
+
* content: <div>Rich content</div>,
|
|
118
|
+
* },
|
|
119
|
+
* {
|
|
120
|
+
* id: 'item-2',
|
|
121
|
+
* title: 'Pre-expanded Section 2',
|
|
122
|
+
* content: <p>More content</p>,
|
|
123
|
+
* },
|
|
124
|
+
* ]}
|
|
125
|
+
* onAccordionChange={(expanded) => console.log('Expanded items:', expanded)}
|
|
126
|
+
* />
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```tsx
|
|
131
|
+
* // Custom rendering with renderItem
|
|
132
|
+
* <Accordion
|
|
133
|
+
* items={items}
|
|
134
|
+
* renderItem={({ item, isExpanded, toggle, ids }) => (
|
|
135
|
+
* <CustomAccordionItem
|
|
136
|
+
* item={item}
|
|
137
|
+
* isExpanded={isExpanded}
|
|
138
|
+
* onToggle={toggle}
|
|
139
|
+
* headingId={ids.headingId}
|
|
140
|
+
* panelId={ids.panelId}
|
|
141
|
+
* />
|
|
142
|
+
* )}
|
|
143
|
+
* />
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
declare const Accordion: ({ items, multiple, defaultExpanded, onAccordionChange, renderItem, sx, ...boxProps }: AccordionProps) => react_jsx_runtime.JSX.Element;
|
|
15
147
|
|
|
16
|
-
export { Accordion, type AccordionProps };
|
|
148
|
+
export { Accordion, type AccordionItem, type AccordionProps, type AccordionRenderItemProps };
|
|
@@ -2,48 +2,118 @@
|
|
|
2
2
|
import { __name } from "../chunk-V4MHYKRI.js";
|
|
3
3
|
|
|
4
4
|
// src/components/Accordion/Accordion.tsx
|
|
5
|
+
import { Box, Button } from "@ttoss/ui";
|
|
5
6
|
import * as React from "react";
|
|
6
|
-
import { AccordionItem, AccordionItemButton, AccordionItemHeading, AccordionItemPanel, Accordion as ReactAccessibleAccordion } from "react-accessible-accordion";
|
|
7
|
-
import { Box, useTheme } from "@ttoss/ui";
|
|
8
|
-
import { css as createClassName } from "@emotion/css";
|
|
9
|
-
import { css as transformStyleObject } from "@theme-ui/css";
|
|
10
7
|
var Accordion = /* @__PURE__ */__name(({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
items,
|
|
9
|
+
multiple = false,
|
|
10
|
+
defaultExpanded,
|
|
11
|
+
onAccordionChange,
|
|
12
|
+
renderItem,
|
|
13
|
+
sx,
|
|
16
14
|
...boxProps
|
|
17
15
|
}) => {
|
|
18
|
-
const {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
16
|
+
const [expandedIndices, setExpandedIndices] = React.useState(() => {
|
|
17
|
+
if (defaultExpanded === void 0) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
return Array.isArray(defaultExpanded) ? defaultExpanded : [defaultExpanded];
|
|
21
|
+
});
|
|
22
|
+
const toggleItem = React.useCallback(index => {
|
|
23
|
+
setExpandedIndices(prev => {
|
|
24
|
+
const isExpanded = prev.includes(index);
|
|
25
|
+
let newExpanded;
|
|
26
|
+
if (isExpanded) {
|
|
27
|
+
newExpanded = prev.filter(i => {
|
|
28
|
+
return i !== index;
|
|
29
|
+
});
|
|
30
|
+
} else {
|
|
31
|
+
newExpanded = multiple ? [...prev, index] : [index];
|
|
34
32
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
onAccordionChange?.(newExpanded);
|
|
34
|
+
return newExpanded;
|
|
35
|
+
});
|
|
36
|
+
}, [multiple, onAccordionChange]);
|
|
38
37
|
return /* @__PURE__ */React.createElement(Box, {
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
sx: {
|
|
39
|
+
display: "flex",
|
|
40
|
+
flexDirection: "column",
|
|
41
|
+
gap: 2,
|
|
42
|
+
...sx
|
|
43
|
+
},
|
|
41
44
|
...boxProps
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
}, items.map((item, index) => {
|
|
46
|
+
const isExpanded = expandedIndices.includes(index);
|
|
47
|
+
const itemId = item.id || `accordion-item-${index}`;
|
|
48
|
+
const headingId = `${itemId}-heading`;
|
|
49
|
+
const panelId = `${itemId}-panel`;
|
|
50
|
+
if (renderItem) {
|
|
51
|
+
return /* @__PURE__ */React.createElement(React.Fragment, {
|
|
52
|
+
key: itemId
|
|
53
|
+
}, renderItem({
|
|
54
|
+
item,
|
|
55
|
+
index,
|
|
56
|
+
isExpanded,
|
|
57
|
+
toggle: /* @__PURE__ */__name(() => {
|
|
58
|
+
return toggleItem(index);
|
|
59
|
+
}, "toggle"),
|
|
60
|
+
ids: {
|
|
61
|
+
itemId,
|
|
62
|
+
headingId,
|
|
63
|
+
panelId
|
|
64
|
+
}
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
return /* @__PURE__ */React.createElement(Box, {
|
|
68
|
+
key: itemId,
|
|
69
|
+
sx: {
|
|
70
|
+
border: "sm",
|
|
71
|
+
borderColor: "display.border.muted.default",
|
|
72
|
+
borderRadius: "md",
|
|
73
|
+
overflow: "hidden"
|
|
74
|
+
}
|
|
75
|
+
}, /* @__PURE__ */React.createElement(Button, {
|
|
76
|
+
id: headingId,
|
|
77
|
+
type: "button",
|
|
78
|
+
disabled: item.disabled,
|
|
79
|
+
onClick: /* @__PURE__ */__name(() => {
|
|
80
|
+
toggleItem(index);
|
|
81
|
+
}, "onClick"),
|
|
82
|
+
"aria-expanded": isExpanded,
|
|
83
|
+
"aria-controls": panelId,
|
|
84
|
+
rightIcon: isExpanded ? "chevron-up" : "chevron-down",
|
|
85
|
+
sx: {
|
|
86
|
+
width: "100%",
|
|
87
|
+
justifyContent: "space-between",
|
|
88
|
+
backgroundColor: isExpanded ? "display.background.muted.default" : "display.background.primary.default",
|
|
89
|
+
color: item.disabled ? "display.text.muted.default" : "display.text.primary.default",
|
|
90
|
+
fontWeight: 500,
|
|
91
|
+
border: "none",
|
|
92
|
+
borderRadius: 0,
|
|
93
|
+
transition: "background-color 0.2s ease",
|
|
94
|
+
"&:hover:not(:disabled)": {
|
|
95
|
+
backgroundColor: "display.background.muted.default"
|
|
96
|
+
},
|
|
97
|
+
"&:focus": {
|
|
98
|
+
outline: "none",
|
|
99
|
+
boxShadow: /* @__PURE__ */__name(theme => {
|
|
100
|
+
return `inset 0 0 0 1px ${
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
102
|
+
theme.colors?.input?.border?.accent?.default || "currentColor"}`;
|
|
103
|
+
}, "boxShadow")
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}, item.title), isExpanded && /* @__PURE__ */React.createElement(Box, {
|
|
107
|
+
id: panelId,
|
|
108
|
+
role: "region",
|
|
109
|
+
"aria-labelledby": headingId,
|
|
110
|
+
sx: {
|
|
111
|
+
padding: 4,
|
|
112
|
+
borderTop: "sm",
|
|
113
|
+
borderColor: "display.border.muted.default",
|
|
114
|
+
backgroundColor: "display.background.primary.default"
|
|
115
|
+
}
|
|
116
|
+
}, item.content));
|
|
117
|
+
}));
|
|
48
118
|
}, "Accordion");
|
|
49
|
-
export { Accordion
|
|
119
|
+
export { Accordion };
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { __name } from "../chunk-V4MHYKRI.js";
|
|
3
3
|
|
|
4
4
|
// src/components/DatePicker/DatePicker.tsx
|
|
5
|
-
import "react-day-picker/style.css";
|
|
6
5
|
import { Icon } from "@ttoss/react-icons";
|
|
7
6
|
import { Box, Button, Flex, Label, Text } from "@ttoss/ui";
|
|
8
7
|
import * as React from "react";
|
|
@@ -243,16 +242,20 @@ var DatePicker = /* @__PURE__ */__name(({
|
|
|
243
242
|
border: "none",
|
|
244
243
|
fontSize: ["12px", "14px"],
|
|
245
244
|
width: ["32px", "36px"],
|
|
246
|
-
height: ["32px", "36px"]
|
|
245
|
+
height: ["32px", "36px"],
|
|
246
|
+
cursor: "pointer"
|
|
247
247
|
},
|
|
248
248
|
"& .rdp-range_start .rdp-day_button": {
|
|
249
|
-
backgroundColor: "action.background.
|
|
249
|
+
backgroundColor: "action.background.accent.default",
|
|
250
|
+
color: "black"
|
|
250
251
|
},
|
|
251
252
|
"& .rdp-range_end .rdp-day_button": {
|
|
252
|
-
backgroundColor: "action.background.
|
|
253
|
+
backgroundColor: "action.background.accent.default",
|
|
254
|
+
color: "black"
|
|
253
255
|
},
|
|
254
256
|
"& .rdp-day_button:hover": {
|
|
255
|
-
backgroundColor: "action.background.
|
|
257
|
+
backgroundColor: "action.background.primary.default",
|
|
258
|
+
color: "action.text.primary.default"
|
|
256
259
|
},
|
|
257
260
|
"& .rdp-day_selected": {
|
|
258
261
|
backgroundColor: "action.background.accent.default",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/components",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.6",
|
|
4
4
|
"description": "React components for ttoss ecosystem.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ttoss",
|
|
@@ -109,44 +109,41 @@
|
|
|
109
109
|
"sideEffects": false,
|
|
110
110
|
"dependencies": {
|
|
111
111
|
"@emotion/css": "^11.13.5",
|
|
112
|
-
"@tanstack/react-table": "^8.
|
|
113
|
-
"@theme-ui/css": "^0.17.
|
|
112
|
+
"@tanstack/react-table": "^8.21.3",
|
|
113
|
+
"@theme-ui/css": "^0.17.4",
|
|
114
114
|
"@types/react-modal": "^3.16.3",
|
|
115
|
-
"json-edit-react": "^1.
|
|
116
|
-
"react-
|
|
117
|
-
"react-
|
|
118
|
-
"react-
|
|
119
|
-
"react-json-view-lite": "^2.3.0",
|
|
120
|
-
"react-markdown": "^9.0.3",
|
|
115
|
+
"json-edit-react": "^1.29.0",
|
|
116
|
+
"react-day-picker": "^9.13.0",
|
|
117
|
+
"react-json-view-lite": "^2.5.0",
|
|
118
|
+
"react-markdown": "^10.1.0",
|
|
121
119
|
"react-modal": "^3.16.3",
|
|
122
120
|
"react-modern-drawer": "^1.4.0",
|
|
123
121
|
"react-tabs": "^6.1.0",
|
|
124
|
-
"react-toastify": "^11.0.
|
|
122
|
+
"react-toastify": "^11.0.5",
|
|
125
123
|
"rehype-raw": "^7.0.0",
|
|
126
|
-
"remark-gfm": "^4.0.
|
|
124
|
+
"remark-gfm": "^4.0.1"
|
|
127
125
|
},
|
|
128
126
|
"peerDependencies": {
|
|
129
127
|
"react": ">=16.8.0",
|
|
130
|
-
"@ttoss/react-hooks": "^2.1.
|
|
131
|
-
"@ttoss/react-
|
|
132
|
-
"@ttoss/
|
|
133
|
-
"@ttoss/
|
|
128
|
+
"@ttoss/react-hooks": "^2.1.12",
|
|
129
|
+
"@ttoss/react-i18n": "^2.0.26",
|
|
130
|
+
"@ttoss/react-icons": "^0.5.7",
|
|
131
|
+
"@ttoss/ui": "^6.5.1"
|
|
134
132
|
},
|
|
135
133
|
"devDependencies": {
|
|
136
134
|
"@types/jest": "^30.0.0",
|
|
137
|
-
"@types/react": "^19.2.
|
|
138
|
-
"@types/react-grid-layout": "^1.3.6",
|
|
135
|
+
"@types/react": "^19.2.8",
|
|
139
136
|
"jest": "^30.2.0",
|
|
140
|
-
"react": "^19.2.
|
|
137
|
+
"react": "^19.2.3",
|
|
141
138
|
"tsup": "^8.5.1",
|
|
142
|
-
"tsx": "^4.
|
|
143
|
-
"@ttoss/react-i18n": "^2.0.25",
|
|
139
|
+
"tsx": "^4.21.0",
|
|
144
140
|
"@ttoss/config": "^1.35.12",
|
|
145
|
-
"@ttoss/
|
|
146
|
-
"@ttoss/react-
|
|
147
|
-
"@ttoss/
|
|
148
|
-
"@ttoss/
|
|
149
|
-
"@ttoss/
|
|
141
|
+
"@ttoss/i18n-cli": "^0.7.38",
|
|
142
|
+
"@ttoss/react-hooks": "^2.1.12",
|
|
143
|
+
"@ttoss/react-i18n": "^2.0.26",
|
|
144
|
+
"@ttoss/react-icons": "^0.5.7",
|
|
145
|
+
"@ttoss/ui": "^6.5.1",
|
|
146
|
+
"@ttoss/test-utils": "^4.0.3"
|
|
150
147
|
},
|
|
151
148
|
"keywords": [
|
|
152
149
|
"React",
|