@maxio-com/react-ui-components 9.17.1 → 9.19.0

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.
@@ -31,10 +31,11 @@ Choose the visual treatment that fits the surrounding surface.
31
31
  ### Behavior
32
32
 
33
33
  - **Mouse and touch**: selecting a tab updates the active tab and renders the matching panel.
34
- - **Keyboard**: Tab moves focus into the tab list. ArrowRight and ArrowLeft move selection across enabled tabs.
34
+ - **Keyboard**: Tab moves focus into the tab list. ArrowRight and ArrowLeft move selection across enabled tabs, and Home/End jump to the first/last enabled tab.
35
35
  - **Focus management**: the selected tab receives focus after keyboard selection.
36
36
  - **Controlled state**: use `index` with `onChange` when the active tab needs to be driven by route state, saved preferences, or another component.
37
37
  - **Uncontrolled state**: use `defaultIndex` when Tabs can manage its own selection after the initial render.
38
+ - **Overflow**: set `overflow="auto"` on `TabList` when a tab set can grow past the available width. Tabs that don't fit collapse into a "More" menu; the active tab is always kept visible, even if it would otherwise be the one to collapse.
38
39
 
39
40
  ### Accessibility
40
41
 
@@ -43,6 +44,7 @@ Choose the visual treatment that fits the surrounding surface.
43
44
  - Give icon-only tabs an accessible name with `aria-label`.
44
45
  - Do not put disabled tabs in the selected state.
45
46
  - Keep focus indicators visible and preserve the built-in arrow-key behavior.
47
+ - The "More" overflow menu is fully keyboard-operable: `Enter`/`Space`/`ArrowDown` on the trigger opens it and focuses the first item, `ArrowUp`/`ArrowDown` move between items, and `Escape` closes it and returns focus to the trigger.
46
48
 
47
49
  ### Content
48
50
 
@@ -119,10 +121,31 @@ const Example = () => {
119
121
  </Tabs>
120
122
  ```
121
123
 
124
+ ### Handling overflow
125
+
126
+ Set `overflow="auto"` on `TabList` when a tab set can grow past the
127
+ available width (many tabs, narrow containers). Tabs that don't fit
128
+ collapse into a "More" menu, and the currently active tab is always
129
+ promoted to the visible row even if it would otherwise overflow.
130
+ `moreLabel` customizes the accessible label of the "More" trigger
131
+ (defaults to `"More"`).
132
+
133
+ The menu is built with
134
+ [react-aria-components](https://react-spectrum.adobe.com/react-aria/) and
135
+ is fully keyboard-operable out of the box:
136
+
137
+ - `Enter`, `Space`, or `ArrowDown` on the trigger opens the menu and
138
+ focuses its first item.
139
+ - `ArrowUp`/`ArrowDown` move focus between items.
140
+ - `Enter`/`Space` on a focused item selects it, closes the menu, and
141
+ returns focus to the trigger.
142
+ - `Escape` closes the menu without selecting anything and also returns
143
+ focus to the trigger.
144
+
122
145
  ## Imports
123
146
 
124
147
  ```tsx
125
- import { Body, Icon, Tab, TabList, TabPanel, TabPanels, Tabs } from "@maxio-com/react-ui-components";
148
+ import { Body, Card, Icon, Tab, TabList, TabPanel, TabPanels, Tabs } from "@maxio-com/react-ui-components";
126
149
  ```
127
150
 
128
151
  ## Prop Types
@@ -133,7 +156,7 @@ import { Body, Icon, Tab, TabList, TabPanel, TabPanels, Tabs } from "@maxio-com/
133
156
  | --- | --- | --- | --- | --- | --- |
134
157
  | `defaultIndex` | `number` | no | `0` | Indicates which tab should be active by default | TypeLiteral |
135
158
  | `index` | `number` | no | - | Indicates which tab should be active in controlled mode. | TypeLiteral |
136
- | `onChange` | `((idx: number \| ((prevIdx: number) => number)) => void)` | no | - | Callback function that is fired when the tab is changed | TabsContext |
159
+ | `onChange` | `TabsOnChange` | no | - | Callback function that is fired when the tab is changed | TypeLiteral |
137
160
  | `variant` | `"line" \| "contained"` | no | `line` | The variant of the tabs. | TabsContext |
138
161
  | `withDivider` | `boolean` | no | `false` | Add divider between tabs | TabsContext |
139
162
 
@@ -191,3 +214,53 @@ const BareIcon = () => <Tabs>
191
214
  </TabPanels>
192
215
  </Tabs>;
193
216
  ```
217
+
218
+ ### Overflow
219
+
220
+ Use `overflow="auto"` when a tab set can grow past the available width (many tabs, narrow containers). Tabs that don't fit collapse into a "More" menu; the active tab is always kept visible.
221
+
222
+ ```tsx
223
+ const Overflow = () => <div style={{ width: '400px' }}>
224
+ <Tabs defaultIndex={0}>
225
+ <TabList ariaLabel="Account sections" overflow="auto">
226
+ {OVERFLOW_TABS.map((tab) => (
227
+ <Tab key={tab}>{tab}</Tab>
228
+ ))}
229
+ </TabList>
230
+ <TabPanels>
231
+ {OVERFLOW_TABS.map((tab) => (
232
+ <TabPanel key={`${tab}-content`} style={{ height: '150px' }}>
233
+ <Body>{`${tab} content for Acme Billing.`}</Body>
234
+ </TabPanel>
235
+ ))}
236
+ </TabPanels>
237
+ </Tabs>
238
+ </div>;
239
+ ```
240
+
241
+ ### In Card
242
+
243
+ Use Tabs to drive a Card's own navigation when the card represents a sectioned view: put TabList in Card.Header so the tabs read as the card's title, and put each TabPanel's content in Card.Body so the panel reads as the card's body. Tabs still wraps both sections since it's the context provider connecting TabList's selection to TabPanels, regardless of where each one sits in the DOM.
244
+
245
+ ```tsx
246
+ const InCard = () => <Tabs defaultIndex={0}>
247
+ <Card>
248
+ <Card.Header style={{ padding: 0 }}>
249
+ <TabList ariaLabel="Customer account sections">
250
+ {TABS.map((tab) => (
251
+ <Tab key={tab}>{tab}</Tab>
252
+ ))}
253
+ </TabList>
254
+ </Card.Header>
255
+ <Card.Body style={{ borderTopLeftRadius: 0, borderTopRightRadius: 0 }}>
256
+ <TabPanels>
257
+ {TABS.map((tab) => (
258
+ <TabPanel key={`${tab}-content`}>
259
+ <Body>{`${tab} content for Acme Billing.`}</Body>
260
+ </TabPanel>
261
+ ))}
262
+ </TabPanels>
263
+ </Card.Body>
264
+ </Card>
265
+ </Tabs>;
266
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maxio-com/react-ui-components",
3
- "version": "9.17.1",
3
+ "version": "9.19.0",
4
4
  "description": "React UI components",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -45,10 +45,13 @@
45
45
  "react-dom": "^19.1.1"
46
46
  },
47
47
  "dependencies": {
48
+ "@atlaskit/pragmatic-drag-and-drop": "^2.0.1",
49
+ "@atlaskit/pragmatic-drag-and-drop-hitbox": "^2.0.0",
48
50
  "@floating-ui/react-dom": "^2.1.6",
49
51
  "@floating-ui/react-dom-interactions": "^0.13.3",
50
52
  "@maxio-com/design-tokens": "^4.2.2",
51
53
  "@react-aria/toast": "3.0.7",
54
+ "@react-aria/utils": "^3.33.1",
52
55
  "@react-stately/checkbox": "^3.7.1",
53
56
  "@react-stately/radio": "^3.11.1",
54
57
  "@react-stately/toast": "3.1.2",
@@ -56,11 +59,11 @@
56
59
  "@tanstack/react-table": "^8.21.3",
57
60
  "classnames": "^2.5.1",
58
61
  "framer-motion": "^12.23.19",
59
- "react-aria": "^3.47.0",
60
- "react-aria-components": "^1.14.0"
62
+ "react-aria": "^3.50.0",
63
+ "react-aria-components": "^1.19.0"
61
64
  },
62
65
  "publishConfig": {
63
66
  "access": "public"
64
67
  },
65
- "gitHead": "6e541e8259760555ada7b510dc1cd419f39dcfa3"
68
+ "gitHead": "550dc2c6524537ca3808d6b69a07c16f98c9848d"
66
69
  }
@@ -149,7 +149,7 @@ declare const Breadcrumbs: React$1.FC<BreadcrumbsProps>;
149
149
  declare const BreadcrumbsItem: React$1.FC<BreadcrumbsItemProps>;
150
150
  //# sourceMappingURL=BreadcrumbsItem.d.ts.map
151
151
 
152
- declare const Button: (props: ButtonProps) => React$1.JSX.Element;
152
+ declare const Button: React$1.ForwardRefExoticComponent<ButtonProps & React$1.RefAttributes<HTMLAnchorElement | HTMLButtonElement>>;
153
153
  //# sourceMappingURL=Button.d.ts.map
154
154
 
155
155
  type ButtonSize = 'sm' | 'md' | 'lg';
@@ -163,9 +163,41 @@ declare const IconButton: ({ "aria-label": ariaLabel, className, ...props }: Ico
163
163
 
164
164
  type TableSize = 'sm' | 'md' | 'lg';
165
165
  type ColumnAlign = 'left' | 'right';
166
+ type RowReorderMode = 'siblings' | 'same-level' | 'all';
167
+ type RowReorderPosition = 'before' | 'after' | 'inside';
168
+ type RowReorderLocation = {
169
+ parentRowId: string | null;
170
+ index: number;
171
+ };
172
+ type RowReorderEvent<TData extends RowData> = {
173
+ data: TData[];
174
+ row: Row<TData>;
175
+ rowId: string;
176
+ targetRow: Row<TData>;
177
+ targetRowId: string;
178
+ position: RowReorderPosition;
179
+ source: RowReorderLocation;
180
+ destination: RowReorderLocation;
181
+ };
166
182
  type RequiredTableOptions<TData extends RowData> = Pick<TableOptions<TData>, 'data' | 'columns'>;
167
- type OptionalTableOptions<TData extends RowData> = Partial<Omit<TableOptions<TData>, 'getCoreRowModel' | 'enableExpanding'>>;
168
- type DataTableProps<TData extends RowData = unknown> = {
183
+ type OptionalTableOptions<TData extends RowData> = Partial<Omit<TableOptions<TData>, 'getCoreRowModel' | 'enableExpanding' | 'enableSorting' | 'getSubRows'>>;
184
+ type RowReorderingOptions<TData extends RowData> = {
185
+ enableSorting?: TableOptions<TData>['enableSorting'];
186
+ enableRowReordering?: false;
187
+ getSubRows?: TableOptions<TData>['getSubRows'];
188
+ getRowReorderLabel?: never;
189
+ onRowReorder?: never;
190
+ rowReorderMode?: never;
191
+ } | {
192
+ enableSorting?: TableOptions<TData>['enableSorting'];
193
+ enableRowReordering: true;
194
+ getSubRows?: never;
195
+ getRowId: NonNullable<TableOptions<TData>['getRowId']>;
196
+ getRowReorderLabel?: (row: Row<TData>) => string;
197
+ onRowReorder: (event: RowReorderEvent<TData>) => void;
198
+ rowReorderMode?: RowReorderMode;
199
+ };
200
+ type DataTableBaseProps<TData extends RowData> = {
169
201
  size?: TableSize;
170
202
  pattern?: boolean;
171
203
  align?: ColumnAlign;
@@ -179,6 +211,7 @@ type DataTableProps<TData extends RowData = unknown> = {
179
211
  onSelect?: (selected: RowSelectionState) => void;
180
212
  onSort?: (selected: SortingState) => void;
181
213
  } & RequiredTableOptions<TData> & OptionalTableOptions<TData>;
214
+ type DataTableProps<TData extends RowData = unknown> = DataTableBaseProps<TData> & RowReorderingOptions<TData>;
182
215
  declare module '@tanstack/react-table' {
183
216
  interface ColumnMeta<TData extends RowData, TValue> {
184
217
  align?: ColumnAlign;
@@ -188,7 +221,7 @@ declare module '@tanstack/react-table' {
188
221
  }
189
222
  }
190
223
 
191
- declare const DataTable: <TData extends RowData>({ pattern, size, SubRowComponent, onExpand, onSelect, onSort, enableSorting, enableRowSelection, enableExpanding, columns: originalColumns, actions, actionsColumnSize, onRowAction, state: userState, ...props }: DataTableProps<TData>) => React$1.JSX.Element;
224
+ declare const DataTable: <TData extends RowData>({ pattern, size, SubRowComponent, onExpand, onSelect, onSort, enableSorting, enableRowSelection, enableExpanding, columns: originalColumns, actions, actionsColumnSize, onRowAction, enableRowReordering, getRowReorderLabel, onRowReorder, rowReorderMode, getRowId, getSubRows, state: userState, ...props }: DataTableProps<TData>) => React$1.JSX.Element;
192
225
  //# sourceMappingURL=DataTable.d.ts.map
193
226
 
194
227
  type DrawerPlacement = 'left' | 'right' | 'top' | 'bottom';
@@ -275,6 +308,8 @@ declare function useWindowSize(debounce?: number): {
275
308
  windowHeight: number;
276
309
  };
277
310
 
311
+ declare function useElementResizeObserver<T extends HTMLElement = HTMLElement>(ref: RefObject<T | null>): number;
312
+
278
313
  type OverlayTriggerProps = {
279
314
  children: React$1.ReactNode;
280
315
  placement?: Placement;
@@ -396,9 +431,10 @@ interface SideNavTopDropdownItem extends AnchorHTMLAttributes<HTMLAnchorElement>
396
431
  type SideNavWrapperProps = Omit<SideNavProviderProps, 'children'>;
397
432
  declare const SideNavWrapper: ({ withIcons, shouldToggleSidebar, topDropdownItems, sections, collapseBreakpoint, isOpen, onChange, }: SideNavWrapperProps) => React$1.JSX.Element;
398
433
 
399
- type CommonTabProps = React.HTMLAttributes<HTMLDivElement> & {
434
+ type CommonTabProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'id'> & {
400
435
  disabled?: boolean;
401
436
  value?: number;
437
+ id?: string;
402
438
  isCurrent?: boolean;
403
439
  };
404
440
  type IconTab = {
@@ -412,31 +448,32 @@ type DefaultTab = {
412
448
  };
413
449
  type TabProps = CommonTabProps & (DefaultTab | IconTab);
414
450
 
415
- declare const Tab: ({ disabled, value, isCurrent, ...props }: TabProps) => React$1.JSX.Element;
451
+ declare const Tab: ({ disabled, value, className, id: legacyId, isCurrent, ...props }: TabProps) => React$1.JSX.Element;
416
452
  //# sourceMappingURL=Tab.d.ts.map
417
453
 
418
454
  type TabsVariant = 'line' | 'contained';
455
+ type TabsOnChange = ((idx: number) => void) | ((idx: number | ((prevIdx: number) => number)) => void);
419
456
  interface TabsContext {
420
457
  variant: TabsVariant;
421
458
  withDivider: boolean;
422
- onChange: (idx: number | ((prevIdx: number) => number)) => void;
423
- currentIndex: number;
424
459
  }
425
- type TabsProviderProps = Omit<Partial<TabsContext>, 'currentIndex'> & {
460
+ type TabsProviderProps = Partial<TabsContext> & {
426
461
  children: ReactNode;
427
462
  defaultIndex?: number;
428
463
  index?: number;
464
+ onChange?: TabsOnChange;
429
465
  };
430
466
 
431
467
  type TabsProps = TabsProviderProps;
432
468
  declare const Tabs: ({ children, variant, withDivider, defaultIndex, index, onChange, }: TabsProps) => React$1.JSX.Element;
433
469
  //# sourceMappingURL=Tabs.d.ts.map
434
470
 
435
- interface TabPanelProps extends React$1.HtmlHTMLAttributes<HTMLDivElement> {
471
+ interface TabPanelProps extends Omit<React$1.HtmlHTMLAttributes<HTMLDivElement>, 'children' | 'id'> {
436
472
  children: ReactNode;
437
473
  value?: number;
474
+ id?: string;
438
475
  }
439
- declare const TabPanel: ({ children, value, ...props }: TabPanelProps) => React$1.JSX.Element;
476
+ declare const TabPanel: ({ children, value, className, id: legacyId, ...props }: TabPanelProps) => React$1.JSX.Element;
440
477
 
441
478
  interface TabPanelsProps {
442
479
  children: React$1.ReactNode;
@@ -447,8 +484,10 @@ declare const TabPanels: ({ children }: TabPanelsProps) => React$1.JSX.Element;
447
484
  interface TabListProps extends React$1.HtmlHTMLAttributes<HTMLDivElement> {
448
485
  ariaLabel: string;
449
486
  children: ReactNode;
487
+ overflow?: 'auto' | 'none';
488
+ moreLabel?: string;
450
489
  }
451
- declare const TabList: ({ children, className, ariaLabel, ...props }: TabListProps) => React$1.JSX.Element;
490
+ declare const TabList: ({ children, className, ariaLabel, overflow, moreLabel, ...props }: TabListProps) => React$1.JSX.Element;
452
491
  //# sourceMappingURL=TabList.d.ts.map
453
492
 
454
493
  type TagSize = 'sm';
@@ -879,5 +918,5 @@ type AuthLayoutProps = {
879
918
  declare const AuthLayout: ({ children, heading, description, sentiment, leadingElement, alert, topAddon, footer, }: AuthLayoutProps) => React$1.JSX.Element;
880
919
  //# sourceMappingURL=AuthLayout.d.ts.map
881
920
 
882
- export { ActionList, Alert, AuthLayout, Avatar, Banner, Body, Breadcrumbs, BreadcrumbsItem, Button, Card, Checkbox, CheckboxGroup, Chip, Code, ComboBox, DataTable, Display, Drawer, Flex, FormErrorMessage, FormHelperText, GlobalToastProvider, Grid, Heading, Icon, IconButton, Label, Link, ListBox, LoadingSpinner, Logo, Menu, MenuButton, MenuList, OverlayTrigger, Pagination, Popover, ProgressBar, Radio, RadioGroup, SegmentedControl, Select, SideNavWrapper as SideNav, Tab, TabList, TabPanel, TabPanels, Tabs, Tag, TextArea, TextField, TextInput, Tile, ToastProvider, ToastQueue, Toggle, Tooltip, TooltipTrigger, TopBar, useHover, useOverlayTrigger, useToast, useWindowSize };
921
+ export { ActionList, Alert, AuthLayout, Avatar, Banner, Body, Breadcrumbs, BreadcrumbsItem, Button, Card, Checkbox, CheckboxGroup, Chip, Code, ComboBox, DataTable, Display, Drawer, Flex, FormErrorMessage, FormHelperText, GlobalToastProvider, Grid, Heading, Icon, IconButton, Label, Link, ListBox, LoadingSpinner, Logo, Menu, MenuButton, MenuList, OverlayTrigger, Pagination, Popover, ProgressBar, Radio, RadioGroup, SegmentedControl, Select, SideNavWrapper as SideNav, Tab, TabList, TabPanel, TabPanels, Tabs, Tag, TextArea, TextField, TextInput, Tile, ToastProvider, ToastQueue, Toggle, Tooltip, TooltipTrigger, TopBar, useElementResizeObserver, useHover, useOverlayTrigger, useToast, useWindowSize };
883
922
  export type { ComboBoxProps, DrawerProps, Interactions, OverlayAriaRole, Placement, PopoverProps, SegmentedControlItemProps, SegmentedControlProps, SegmentedControlSize, TextAreaProps, TextFieldProps, TextInputProps };