@ttoss/components 2.12.3 → 2.12.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md 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
- **📖 [View all components in Storybook](https://storybook.ttoss.dev/?path=/docs/components-accordion--docs)**
11
+ [View all components in Storybook](https://storybook.ttoss.dev/?path=/docs/components-accordion--docs)
12
12
 
13
- ## Components Overview
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
- Collapsible content sections. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-accordion--docs)
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
- Accordion,
24
- AccordionItem,
25
- AccordionItemButton,
26
- AccordionItemHeading,
27
- AccordionItemPanel,
28
- } from '@ttoss/components/Accordion';
29
-
30
- <Accordion allowMultipleExpanded>
31
- <AccordionItem>
32
- <AccordionItemHeading>
33
- <AccordionItemButton>Section Title</AccordionItemButton>
34
- </AccordionItemHeading>
35
- <AccordionItemPanel>Section content</AccordionItemPanel>
36
- </AccordionItem>
37
- </Accordion>;
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-drawer--docs)
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 support. Displays uploaded files with previews, clickable links, and remove functionality. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-fileuploader--docs)
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
- // Callbacks
85
- onUploadComplete={(file, result) => {
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} // 10MB
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-installpwa--docs)
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/). [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-jsoneditor--docs)
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). [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-jsonview--docs)
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-list--docs)
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-lockedoverlay--docs)
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-markdown--docs)
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-menu--docs)
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-navlist--docs)
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
- onItemClick={(item) => console.log('Clicked:', item)}
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-modal--docs)
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-notificationcard--docs)
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-notificationsmenu--docs)
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-search--docs)
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). [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-table--docs)
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-tabs--docs)
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. [📖 Docs](https://storybook.ttoss.dev/?path=/docs/components-toast--docs)
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
- export { AccordionItem, AccordionItemButton, AccordionItemHeading, AccordionItemPanel } from 'react-accessible-accordion';
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
- * Callback which is invoked when items are expanded or collapsed. Gets passed uuids of the currently expanded AccordionItems.
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
- onChange?: (args: string[]) => void;
83
+ renderItem?: (props: AccordionRenderItemProps) => React.ReactNode;
13
84
  };
14
- declare const Accordion: ({ children, allowMultipleExpanded, allowZeroExpanded, preExpanded, onChange, ...boxProps }: AccordionProps) => react_jsx_runtime.JSX.Element;
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
- children,
12
- allowMultipleExpanded,
13
- allowZeroExpanded,
14
- preExpanded,
15
- onChange,
8
+ items,
9
+ multiple = false,
10
+ defaultExpanded,
11
+ onAccordionChange,
12
+ renderItem,
13
+ sx,
16
14
  ...boxProps
17
15
  }) => {
18
- const {
19
- theme
20
- } = useTheme();
21
- const className = React.useMemo(() => {
22
- const styles = transformStyleObject({
23
- ".accordion__item": {
24
- marginBottom: 3
25
- },
26
- ".accordion__heading": {
27
- padding: "md",
28
- border: "1px solid",
29
- borderColor: "black"
30
- },
31
- ".accordion__button": {},
32
- ".accordion__panel": {
33
- padding: 2
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
- })(theme);
36
- return createClassName(styles);
37
- }, [theme]);
33
+ onAccordionChange?.(newExpanded);
34
+ return newExpanded;
35
+ });
36
+ }, [multiple, onAccordionChange]);
38
37
  return /* @__PURE__ */React.createElement(Box, {
39
- variant: "accordion",
40
- className,
38
+ sx: {
39
+ display: "flex",
40
+ flexDirection: "column",
41
+ gap: 2,
42
+ ...sx
43
+ },
41
44
  ...boxProps
42
- }, /* @__PURE__ */React.createElement(ReactAccessibleAccordion, {
43
- allowMultipleExpanded,
44
- allowZeroExpanded,
45
- preExpanded,
46
- onChange
47
- }, children));
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, AccordionItem, AccordionItemButton, AccordionItemHeading, AccordionItemPanel };
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";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/components",
3
- "version": "2.12.3",
3
+ "version": "2.12.5",
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.20.6",
113
- "@theme-ui/css": "^0.17.1",
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.19.2",
116
- "react-accessible-accordion": "^5.0.0",
117
- "react-day-picker": "^9.11.3",
118
- "react-grid-layout": "^1.5.2",
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.2",
122
+ "react-toastify": "^11.0.5",
125
123
  "rehype-raw": "^7.0.0",
126
- "remark-gfm": "^4.0.0"
124
+ "remark-gfm": "^4.0.1"
127
125
  },
128
126
  "peerDependencies": {
129
127
  "react": ">=16.8.0",
130
- "@ttoss/react-hooks": "^2.1.11",
131
- "@ttoss/react-icons": "^0.5.6",
132
- "@ttoss/react-i18n": "^2.0.25",
133
- "@ttoss/ui": "^6.4.3"
128
+ "@ttoss/ui": "^6.5.1",
129
+ "@ttoss/react-hooks": "^2.1.12",
130
+ "@ttoss/react-i18n": "^2.0.26",
131
+ "@ttoss/react-icons": "^0.5.7"
134
132
  },
135
133
  "devDependencies": {
136
134
  "@types/jest": "^30.0.0",
137
- "@types/react": "^19.2.7",
138
- "@types/react-grid-layout": "^1.3.6",
135
+ "@types/react": "^19.2.8",
139
136
  "jest": "^30.2.0",
140
- "react": "^19.2.1",
137
+ "react": "^19.2.3",
141
138
  "tsup": "^8.5.1",
142
- "tsx": "^4.19.2",
139
+ "tsx": "^4.21.0",
143
140
  "@ttoss/config": "^1.35.12",
144
- "@ttoss/react-hooks": "^2.1.11",
141
+ "@ttoss/react-hooks": "^2.1.12",
142
+ "@ttoss/react-icons": "^0.5.7",
143
+ "@ttoss/react-i18n": "^2.0.26",
145
144
  "@ttoss/i18n-cli": "^0.7.38",
146
- "@ttoss/react-i18n": "^2.0.25",
147
- "@ttoss/react-icons": "^0.5.6",
148
- "@ttoss/test-utils": "^4.0.2",
149
- "@ttoss/ui": "^6.4.3"
145
+ "@ttoss/test-utils": "^4.0.3",
146
+ "@ttoss/ui": "^6.5.1"
150
147
  },
151
148
  "keywords": [
152
149
  "React",