diff --git a/packages/components/src/components/ContenPanel/hooks/useContentPanelContainer/useContentPanelContainer.ts b/packages/components/src/components/ContenPanel/hooks/useContentPanelContainer/useContentPanelContainer.ts index 35816fd1..9c6ced65 100644 --- a/packages/components/src/components/ContenPanel/hooks/useContentPanelContainer/useContentPanelContainer.ts +++ b/packages/components/src/components/ContenPanel/hooks/useContentPanelContainer/useContentPanelContainer.ts @@ -6,7 +6,10 @@ import type { ButtonBaseProps } from '@koobiq/react-primitives'; import type { OverlayTriggerState } from '@react-stately/overlays'; export type UseContentPanelReturnValue = { - triggerProps: ButtonBaseProps; + triggerProps: Omit< + ButtonBaseProps, + 'isLoading' | 'children' | 'className' | 'style' + >; closeButtonProps: ButtonBaseProps; containerProps?: HTMLAttributes; panelProps?: HTMLAttributes; diff --git a/packages/components/src/components/Dialog/Dialog.tsx b/packages/components/src/components/Dialog/Dialog.tsx index a4ef283a..e7557faf 100644 --- a/packages/components/src/components/Dialog/Dialog.tsx +++ b/packages/components/src/components/Dialog/Dialog.tsx @@ -11,10 +11,10 @@ import { useEventListener, } from '@koobiq/react-core'; import { - ButtonContext, Provider, useDialog, DEFAULT_SLOT, + ButtonContext, } from '@koobiq/react-primitives'; import { utilClasses } from '../../styles/utility'; diff --git a/packages/components/src/components/IconButton/IconButton.module.css b/packages/components/src/components/IconButton/IconButton.module.css index 85e1cb3a..8c93e617 100644 --- a/packages/components/src/components/IconButton/IconButton.module.css +++ b/packages/components/src/components/IconButton/IconButton.module.css @@ -34,6 +34,10 @@ color var(--kbq-transition-default); @mixin typography text-normal-medium; + + & > * { + flex-shrink: 0; + } } .l { diff --git a/packages/components/src/components/Input/Input.tsx b/packages/components/src/components/Input/Input.tsx index 193f0390..a4a1e495 100644 --- a/packages/components/src/components/Input/Input.tsx +++ b/packages/components/src/components/Input/Input.tsx @@ -122,6 +122,7 @@ export const Input = forwardRef((props, ref) => { const clearButtonProps = mergeProps( { isClearable, + tabIndex: -1, isHidden: clearButtonIsHidden, }, slotProps?.clearButton diff --git a/packages/components/src/components/Tree/Tree.css b/packages/components/src/components/Tree/Tree.css new file mode 100644 index 00000000..cfcd23c8 --- /dev/null +++ b/packages/components/src/components/Tree/Tree.css @@ -0,0 +1,70 @@ +@import url('../../styles/mixins.css'); + +.kbq-Tree { + --tree-item-level: ; + --tree-item-padding: var(--kbq-size-m); + + outline: none; + overflow: auto; + box-sizing: border-box; + forced-color-adjust: none; + display: flex; + flex-direction: column; + + &[data-empty] { + align-items: center; + justify-content: center; + min-block-size: 100px; + + @mixin typography text-normal; + } +} + +.kbq-TreeItem { + padding-inline-start: calc( + (var(--tree-item-level)) * var(--tree-item-padding) + ); + + &:not([data-disabled], [data-has-child-items], [data-selection-mode]) { + cursor: default; + } + + &:not([data-disabled])[data-has-child-items], + &:not([data-disabled])[data-selection-mode], + &:not([data-disabled])[data-href] { + cursor: pointer; + } + + &[data-disabled]:not([data-has-child-items], [data-selection-mode]) { + cursor: default; + } + + [data-slot='chevron'] { + visibility: hidden; + margin-block: var(--kbq-size-3xs); + } + + &[data-has-child-items] [data-slot='chevron'] { + visibility: visible; + } +} + +.kbq-TreeLoader { + display: flex; + align-items: center; + justify-content: center; +} + +.kbq-TreeLoadMoreItem { + display: flex; + align-items: center; + gap: var(--kbq-size-m); + cursor: default; + padding-inline-start: calc( + (var(--tree-item-level)) * var(--tree-item-padding) + 24px + ); + + & > * { + display: contents; + } +} diff --git a/packages/components/src/components/Tree/Tree.mdx b/packages/components/src/components/Tree/Tree.mdx new file mode 100644 index 00000000..6d79baa5 --- /dev/null +++ b/packages/components/src/components/Tree/Tree.mdx @@ -0,0 +1,94 @@ +import { + Meta, + Story, + Props, + Status, +} from '../../../../../.storybook/components'; + +import * as Stories from './Tree.stories'; + + + +# Tree + + + +A tree provides users with a way to navigate nested hierarchical information, +with support for keyboard navigation and selection. + +```tsx +import { Tree } from '@koobiq/react-components'; +``` + + + +## Props + + + +## Components + +Use these components to build hierarchical navigation, selection, and lazy loading flows. + +- `Tree` — Root container for hierarchical items. +- `Tree.Item` — Defines a node in the tree (leaf or branch). +- `Tree.ItemContent` — Customizes row content (text, icons, slots). +- `Tree.LoadMoreItem` — Triggers and displays async loading state for additional items. + +## Content + +Tree supports both static and dynamic collections. +Use static items when the structure is known in advance, and use the render function with the `items` prop when the data comes from an external source or changes over time. + + + +## Multiple selection + +Use `selectionMode="multiple"` to allow selecting more than one item. +Use `selectionBehavior="toggle"` to render checkbox selection controls. + + + +## Slots + +Use `Tree.ItemContent` to customize item layout. +For example, you can add icons, typography, badges, and slot-specific props for chevron and checkbox controls. + + + +## Empty state + +When no items are available, use `renderEmptyState` to render a clear empty result message. + + + +## Disabled + +Use `disabledKeys` to disable specific items in the tree. + + + +## Links + +Tree items can act as links using `href`. +This is useful for navigation trees and any hierarchical link structure. + + + +## Selection and actions + +Use `selectionMode` and `onSelectionChange` for controlled selection. +Use `onAction` to handle item activation separately from selection. + + + +## Async Loading + +Tree supports progressive loading with `Tree.LoadMoreItem`. +Combine it with `useAsyncList` to fetch nested data on demand. + + + +## Other examples + + diff --git a/packages/components/src/components/Tree/Tree.stories.tsx b/packages/components/src/components/Tree/Tree.stories.tsx new file mode 100644 index 00000000..5f837abc --- /dev/null +++ b/packages/components/src/components/Tree/Tree.stories.tsx @@ -0,0 +1,649 @@ +import { useState } from 'react'; + +import { IconEllipsisVertical16, IconFolder16 } from '@koobiq/react-icons'; +import { Collection } from '@koobiq/react-primitives'; +import type { Meta, StoryObj } from '@storybook/react'; + +import { FlexBox, useAsyncList } from '../../index'; +import type { Selection } from '../../index'; +import { IconButton } from '../IconButton'; +import { spacing } from '../layout'; +import { Menu } from '../Menu'; +import { Typography } from '../Typography'; + +import { Tree } from './Tree'; + +const meta = { + title: 'Components/Tree', + component: Tree, + parameters: { + layout: 'centered', + }, + subcomponents: { + 'Tree.Item': Tree.Item, + 'Tree.ItemContent': Tree.ItemContent, + 'Tree.LoadMoreItem': Tree.LoadMoreItem, + }, + argTypes: {}, + tags: ['status:new', 'date:2026-03-02'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const items = [ + { + id: 1, + title: 'app', + type: 'directory', + children: [ + { + id: 2, + title: 'Http', + type: 'directory', + children: [{ id: 3, title: 'index.html', type: 'file', children: [] }], + }, + { + id: 4, + title: 'Providers', + type: 'directory', + children: [ + { + id: 5, + title: 'EventServiceProvider.js', + type: 'file', + children: [], + }, + ], + }, + ], + }, + { + id: 6, + title: 'config', + type: 'directory', + children: [ + { id: 7, title: 'app.js', type: 'file', children: [] }, + { id: 8, title: 'database.js', type: 'file', children: [] }, + ], + }, + { + id: 9, + title: 'public', + type: 'directory', + children: [{ id: 10, title: 'logo.svg', type: 'file', children: [] }], + }, + { id: 11, title: '.env', type: 'file', children: [] }, + { id: 12, title: '.gitignore', type: 'file', children: [] }, + { id: 13, title: 'README.md', type: 'file', children: [] }, +]; + +export const Base: Story = { + parameters: { + layout: 'padded', + }, + render: (args) => ( + + + app + + Http + + index.html + + + + Providers + + EventServiceProvider.js + + + + + config + + app.js + + + database.js + + + + public + + logo.svg + + + + .env + + + .gitignore + + + README.md + + + ), +}; + +export const MultipleSelection: Story = { + name: 'Multiple selection', + parameters: { + layout: 'padded', + }, + render: function Render() { + const [selectedKeys, setSelectedKeys] = useState( + new Set(['index-html', 'logo-svg', 'readme-file']) + ); + + return ( + <> + + + app + + Http + + index.html + + + + Providers + + EventServiceProvider.js + + + + + config + + app.js + + + database.js + + + + public + + logo.svg + + + + .env + + + .gitignore + + + README.md + + + + Selected keys: {Array.from(selectedKeys).join(', ') || 'none'} + + + ); + }, +}; + +export const Content: Story = { + parameters: { + layout: 'padded', + }, + render: function Render() { + return ( + + {function renderItem(item) { + return ( + + {item.title} + {/* recursively render children */} + {renderItem} + + ); + }} + + ); + }, +}; + +export const Slots: Story = { + parameters: { + layout: 'padded', + }, + render: function Render() { + function MyTreeItemContent({ + title, + type, + }: { + title: string; + type: string; + }) { + const [isMenuOpen, setIsMenuOpen] = useState(false); + + return ( + + {({ isHovered, isFocusVisibleWithin }) => ( + <> + {type === 'directory' && } + {title} + {(isHovered || isFocusVisibleWithin || isMenuOpen) && ( + ( + + + + )} + > + Edit + Copy + Delete + + )} + + )} + + ); + } + + function MyTreeItem({ item }: { item: (typeof items)[number] }) { + return ( + + + + {(child) => } + + + ); + } + + return ( + + {(item) => } + + ); + }, +}; + +export const EmptyState: Story = { + parameters: { + layout: 'padded', + }, + render: function Render() { + return ( + 'No results found.'} + > + {[]} + + ); + }, +}; + +export const Disabled: Story = { + name: 'Disabled items', + parameters: { + layout: 'padded', + }, + render: function Render() { + return ( + + {function renderItem(item) { + return ( + + {item.title} + {renderItem} + + ); + }} + + ); + }, +}; + +interface Product { + id: number; + title: string; + brand: string; +} + +export const Links: Story = { + parameters: { + layout: 'padded', + }, + render: function Render() { + return ( + + + React + + Components + + + Hooks + + + + Storybook + + Essentials + + + + ); + }, +}; + +export const SelectionAndActions: Story = { + name: 'Selection and actions', + parameters: { + layout: 'padded', + }, + render: function Render() { + const [selectedKeys, setSelectedKeys] = useState( + new Set(['index-html']) + ); + + const [lastAction, setLastAction] = useState('none'); + + return ( + <> + setLastAction(String(key))} + defaultExpandedKeys={['app', 'http', 'providers', 'config']} + > + + app + + Http + + index.html + + + + Providers + + EventServiceProvider.js + + + + + config + + app.js + + + database.js + + + + public + + logo.svg + + + + .env + + + .gitignore + + + README.md + + + + Selected keys: {Array.from(selectedKeys).join(', ') || 'none'} + + Last action: {lastAction} + + ); + }, +}; + +export const AsyncLoading: Story = { + parameters: { + layout: 'padded', + }, + render: function Render() { + const ITEMS_PER_PAGE = 5; + + const smartphonesList = useAsyncList({ + async load({ signal, cursor }) { + const skip = Number(cursor ?? 0); + + const response = await fetch( + `https://dummyjson.com/products/category/smartphones?limit=${ITEMS_PER_PAGE}&skip=${skip}`, + { signal } + ); + + const data = await response.json(); + const nextSkip = skip + ITEMS_PER_PAGE; + + return { + items: data.products ?? [], + cursor: nextSkip < data.total ? String(nextSkip) : undefined, + }; + }, + }); + + const mobileAccessoriesList = useAsyncList({ + async load({ signal, cursor }) { + const skip = Number(cursor ?? 0); + + const response = await fetch( + `https://dummyjson.com/products/category/mobile-accessories?limit=${ITEMS_PER_PAGE}&skip=${skip}`, + { signal } + ); + + const data = await response.json(); + const nextSkip = skip + ITEMS_PER_PAGE; + + return { + items: data.products ?? [], + cursor: nextSkip < data.total ? String(nextSkip) : undefined, + }; + }, + }); + + return ( + + + Smartphones + + {(item) => ( + + + {item.brand} {item.title} + + + )} + + + + + Mobile accessories + + {(item) => ( + + + {item.brand} {item.title} + + + )} + + + + + ); + }, +}; + +export const Examples: Story = { + parameters: { + layout: 'padded', + }, + render: (args) => ( + + + app + + Http + + index.html + + + + Providers + + EventServiceProvider.js + + + + + config + + app.js + + + database.js + + + + + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus + asperiores delectus doloremque fugiat illo laudantium nesciunt + omnis. Aliquam, earum, velit? + + + + + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. + Accusamus asperiores delectus doloremque fugiat illo laudantium + nesciunt omnis. Aliquam, earum, velit? + + + + + + .env + + + .gitignore + + + README.md + + + + + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. + Accusamus asperiores delectus doloremque fugiat illo laudantium + nesciunt omnis. Aliquam, earum, velit? + + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. + Accusamus asperiores delectus doloremque fugiat illo laudantium + nesciunt omnis. Aliquam, earum, velit? + + + + + + ), +}; diff --git a/packages/components/src/components/Tree/Tree.test.tsx b/packages/components/src/components/Tree/Tree.test.tsx new file mode 100644 index 00000000..e477751f --- /dev/null +++ b/packages/components/src/components/Tree/Tree.test.tsx @@ -0,0 +1,177 @@ +import { render, screen } from '@testing-library/react'; +import { userEvent } from '@testing-library/user-event'; +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; + +import { Provider } from '../Provider'; + +import { Tree } from './index'; + +describe('Tree', () => { + const originalIntersectionObserver = globalThis.IntersectionObserver; + + beforeAll(() => { + // jsdom doesn't provide IntersectionObserver, but Tree.LoadMoreItem uses it. + globalThis.IntersectionObserver = vi.fn(() => ({ + disconnect: () => {}, + observe: () => {}, + takeRecords: () => [], + unobserve: () => {}, + })) as unknown as typeof IntersectionObserver; + }); + + afterAll(() => { + globalThis.IntersectionObserver = originalIntersectionObserver; + }); + + it('should merge custom className with default root class', () => { + render( + 'tree-custom'} + > + + Documents + + + ); + + expect(screen.getByTestId('tree')).toHaveClass('kbq-Tree', 'tree-custom'); + }); + + it('should merge custom className with default Tree.Item class', () => { + render( + + 'tree-item-custom'} + > + Documents + + + ); + + expect(screen.getByTestId('tree-item')).toHaveClass( + 'kbq-TreeItem', + 'tree-item-custom' + ); + }); + + it('should pass slotProps to chevron and checkbox controls in Tree.ItemContent', () => { + render( + + + + Documents + + + Project + + + + ); + + expect(screen.getByTestId('tree-chevron')).toHaveClass( + 'tree-chevron-custom' + ); + + expect(screen.getByTestId('tree-selection')).toHaveClass( + 'tree-selection-custom' + ); + }); + + it('should mark disabled item via disabledKeys', () => { + render( + + + Documents + + Project + + + + ); + + expect(screen.getByTestId('project-item')).toHaveAttribute( + 'data-disabled', + 'true' + ); + }); + + it('should merge className and style in Tree.LoadMoreItem', () => { + const onLoadMore = vi.fn(); + + render( + + + Documents + 'load-more-custom'} + style={() => ({ padding: 8 })} + /> + + + ); + + expect(screen.getByTestId('load-more')).toHaveClass( + 'kbq-TreeLoadMoreItem', + 'load-more-custom' + ); + + expect(screen.getByTestId('load-more')).toHaveStyle({ padding: '8px' }); + }); + + it('should support client side routing via Provider router', async () => { + const onNavigate = vi.fn(); + + render( + { + onNavigate(); + }, + }} + > + + + React docs + + + + ); + + await userEvent.click(screen.getByText('React docs')); + + expect(onNavigate).toBeCalled(); + }); +}); diff --git a/packages/components/src/components/Tree/Tree.tsx b/packages/components/src/components/Tree/Tree.tsx new file mode 100644 index 00000000..34ad0d61 --- /dev/null +++ b/packages/components/src/components/Tree/Tree.tsx @@ -0,0 +1,42 @@ +'use client'; + +import { clsx } from '@koobiq/react-core'; +import type { TreeProps } from '@koobiq/react-primitives'; +import { Tree as AriaTree, composeRenderProps } from '@koobiq/react-primitives'; + +import './Tree.css'; +import { utilClasses } from '../../styles/utility'; + +import { TreeItem, TreeItemContent, TreeLoadMoreItem } from './components'; + +const { list } = utilClasses; + +export type { TreeProps }; + +export function TreeComponent({ + className, + ...props +}: TreeProps) { + return ( + + clsx('kbq-Tree', list, className) + )} + /> + ); +} + +TreeComponent.displayName = 'Tree'; + +type CompoundedComponent = typeof TreeComponent & { + Item: typeof TreeItem; + ItemContent: typeof TreeItemContent; + LoadMoreItem: typeof TreeLoadMoreItem; +}; + +export const Tree = TreeComponent as CompoundedComponent; + +TreeComponent.Item = TreeItem; +TreeComponent.ItemContent = TreeItemContent; +TreeComponent.LoadMoreItem = TreeLoadMoreItem; diff --git a/packages/components/src/components/Tree/components/TreeItem/TreeItem.tsx b/packages/components/src/components/Tree/components/TreeItem/TreeItem.tsx new file mode 100644 index 00000000..a3aab7be --- /dev/null +++ b/packages/components/src/components/Tree/components/TreeItem/TreeItem.tsx @@ -0,0 +1,33 @@ +'use client'; + +import { clsx } from '@koobiq/react-core'; +import { + TreeItem as AriaTreeItem, + composeRenderProps, +} from '@koobiq/react-primitives'; + +import { utilClasses } from '../../../../styles/utility'; + +import type { TreeItemProps } from './types'; + +const textVariant = utilClasses.typography; +const { listItem } = utilClasses; + +export function TreeItem({ + children, + className, + textValue, + ...props +}: TreeItemProps) { + return ( + + clsx('kbq-TreeItem', listItem, textVariant['text-normal'], className) + )} + > + {children} + + ); +} diff --git a/packages/components/src/components/Tree/components/TreeItem/index.ts b/packages/components/src/components/Tree/components/TreeItem/index.ts new file mode 100644 index 00000000..90ee095e --- /dev/null +++ b/packages/components/src/components/Tree/components/TreeItem/index.ts @@ -0,0 +1,2 @@ +export * from './TreeItem'; +export * from './types'; diff --git a/packages/components/src/components/Tree/components/TreeItem/types.ts b/packages/components/src/components/Tree/components/TreeItem/types.ts new file mode 100644 index 00000000..132ebcc8 --- /dev/null +++ b/packages/components/src/components/Tree/components/TreeItem/types.ts @@ -0,0 +1,4 @@ +import type { DataAttributeProps } from '@koobiq/react-core'; +import type { TreeItemProps as AriaTreeItemProps } from '@koobiq/react-primitives'; + +export type TreeItemProps = Partial & DataAttributeProps; diff --git a/packages/components/src/components/Tree/components/TreeItemContent/TreeItemContent.tsx b/packages/components/src/components/Tree/components/TreeItemContent/TreeItemContent.tsx new file mode 100644 index 00000000..88c5ccd7 --- /dev/null +++ b/packages/components/src/components/Tree/components/TreeItemContent/TreeItemContent.tsx @@ -0,0 +1,50 @@ +'use client'; + +import { mergeProps } from '@koobiq/react-core'; +import { IconChevronRightS16 } from '@koobiq/react-icons'; +import { TreeItemContent as AriaTreeItemContent } from '@koobiq/react-primitives'; + +import { AnimatedIcon } from '../../../AnimatedIcon'; +import { Checkbox } from '../../../Checkbox'; +import { IconButton } from '../../../IconButton'; + +import type { + TreeItemContentProps, + TreeItemContentPropSlotProps, +} from './types'; + +export function TreeItemContent(props: TreeItemContentProps) { + const { children, slotProps, ...other } = props; + + return ( + + {(renderProps) => { + const { selectionBehavior, selectionMode, isDisabled, isExpanded } = + renderProps; + + const chevronProps = mergeProps< + (TreeItemContentPropSlotProps['chevron'] | undefined)[] + >( + { variant: 'fade-contrast', size: 'l', isCompact: true, isDisabled }, + slotProps?.chevron + ); + + return ( + <> + + ]} + directions={[0, 90]} + activeIndex={+isExpanded} + /> + + {selectionBehavior === 'toggle' && selectionMode === 'multiple' && ( + + )} + {typeof children === 'function' ? children(renderProps) : children} + + ); + }} + + ); +} diff --git a/packages/components/src/components/Tree/components/TreeItemContent/index.ts b/packages/components/src/components/Tree/components/TreeItemContent/index.ts new file mode 100644 index 00000000..07627e98 --- /dev/null +++ b/packages/components/src/components/Tree/components/TreeItemContent/index.ts @@ -0,0 +1,2 @@ +export * from './TreeItemContent'; +export * from './types'; diff --git a/packages/components/src/components/Tree/components/TreeItemContent/types.ts b/packages/components/src/components/Tree/components/TreeItemContent/types.ts new file mode 100644 index 00000000..6c3d2b64 --- /dev/null +++ b/packages/components/src/components/Tree/components/TreeItemContent/types.ts @@ -0,0 +1,14 @@ +import type { DataAttributeProps } from '@koobiq/react-core'; +import type { TreeItemContentProps as AriaTreeItemContentProps } from '@koobiq/react-primitives'; + +import type { CheckboxProps } from '../../../Checkbox'; +import type { IconButtonProps } from '../../../IconButton'; + +export type TreeItemContentPropSlotProps = { + chevron?: Omit & DataAttributeProps; + checkbox?: Omit; +}; + +export type TreeItemContentProps = AriaTreeItemContentProps & { + slotProps?: TreeItemContentPropSlotProps; +} & DataAttributeProps; diff --git a/packages/components/src/components/Tree/components/TreeLoadMoreItem/TreeLoadMoreItem.tsx b/packages/components/src/components/Tree/components/TreeLoadMoreItem/TreeLoadMoreItem.tsx new file mode 100644 index 00000000..2c20aaaf --- /dev/null +++ b/packages/components/src/components/Tree/components/TreeLoadMoreItem/TreeLoadMoreItem.tsx @@ -0,0 +1,40 @@ +'use client'; + +import type { CSSProperties } from 'react'; + +import { clsx } from '@koobiq/react-core'; +import { + TreeLoadMoreItem as AriaTreeLoadMoreItem, + composeRenderProps, + type TreeLoadMoreItemProps, +} from '@koobiq/react-primitives'; + +import { utilClasses } from '../../../../styles/utility'; +import { ProgressSpinner } from '../../../ProgressSpinner'; +import { Typography } from '../../../Typography'; + +const { listItem } = utilClasses; + +export function TreeLoadMoreItem(props: TreeLoadMoreItemProps) { + const { className, style, ...other } = props; + + return ( + + clsx('kbq-TreeLoadMoreItem', listItem, className) + )} + style={composeRenderProps( + style, + (style, { level }) => + ({ + '--tree-item-level': level, + ...style, + }) as CSSProperties + )} + > + + Loading more... + + ); +} diff --git a/packages/components/src/components/Tree/components/TreeLoadMoreItem/index.ts b/packages/components/src/components/Tree/components/TreeLoadMoreItem/index.ts new file mode 100644 index 00000000..ceb6c3d5 --- /dev/null +++ b/packages/components/src/components/Tree/components/TreeLoadMoreItem/index.ts @@ -0,0 +1 @@ +export * from './TreeLoadMoreItem'; diff --git a/packages/components/src/components/Tree/components/index.ts b/packages/components/src/components/Tree/components/index.ts new file mode 100644 index 00000000..cc8066ee --- /dev/null +++ b/packages/components/src/components/Tree/components/index.ts @@ -0,0 +1,3 @@ +export * from './TreeLoadMoreItem'; +export * from './TreeItem'; +export * from './TreeItemContent'; diff --git a/packages/components/src/components/Tree/index.ts b/packages/components/src/components/Tree/index.ts new file mode 100644 index 00000000..30433296 --- /dev/null +++ b/packages/components/src/components/Tree/index.ts @@ -0,0 +1,2 @@ +export * from './Tree'; +export * from './components'; diff --git a/packages/components/src/components/index.ts b/packages/components/src/components/index.ts index 648d4fc4..1454c431 100644 --- a/packages/components/src/components/index.ts +++ b/packages/components/src/components/index.ts @@ -47,6 +47,7 @@ export * from './Accordion'; export * from './ContenPanel'; export * from './Navbar'; export * from './ActionsPanel'; +export * from './Tree'; export * from './layout'; export { useListData, diff --git a/packages/primitives/package.json b/packages/primitives/package.json index f407d969..169557f3 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -83,7 +83,8 @@ "@react-stately/toast": "^3.1.3", "@react-stately/toggle": "^3.9.4", "@react-stately/tooltip": "^3.5.10", - "@react-stately/tree": "^3.9.5" + "@react-stately/tree": "^3.9.5", + "react-aria-components": "^1.15.1" }, "peerDependencies": { "react": "18.x || 19.x", diff --git a/packages/primitives/src/components/Button/Button.tsx b/packages/primitives/src/components/Button/Button.tsx index 45353795..fd581b0b 100644 --- a/packages/primitives/src/components/Button/Button.tsx +++ b/packages/primitives/src/components/Button/Button.tsx @@ -8,11 +8,14 @@ import { filterDOMProps, polymorphicForwardRef, } from '@koobiq/react-core'; +import { + useContextProps, + ButtonContext, + useRenderProps, +} from 'react-aria-components'; import { useButton } from '../../behaviors'; -import { useContextProps, useRenderProps } from '../../utils'; -import { ButtonContext } from './ButtonContext'; import type { ButtonBaseProps } from './types'; export const Button = polymorphicForwardRef<'button', ButtonBaseProps>( diff --git a/packages/primitives/src/components/Button/ButtonContext.tsx b/packages/primitives/src/components/Button/ButtonContext.tsx deleted file mode 100644 index c1ba8367..00000000 --- a/packages/primitives/src/components/Button/ButtonContext.tsx +++ /dev/null @@ -1,11 +0,0 @@ -'use client'; - -import { createContext } from 'react'; - -import type { ContextValue } from '../../utils'; - -import type { ButtonProps } from './index'; - -export const ButtonContext = createContext< - ContextValue ->({}); diff --git a/packages/primitives/src/components/Button/index.ts b/packages/primitives/src/components/Button/index.ts index cb1dee87..f3c45c15 100644 --- a/packages/primitives/src/components/Button/index.ts +++ b/packages/primitives/src/components/Button/index.ts @@ -1,3 +1,2 @@ export * from './Button.js'; export * from './types.js'; -export * from './ButtonContext'; diff --git a/packages/primitives/src/components/Checkbox/Checkbox.tsx b/packages/primitives/src/components/Checkbox/Checkbox.tsx index d9f6d816..ff2e056a 100644 --- a/packages/primitives/src/components/Checkbox/Checkbox.tsx +++ b/packages/primitives/src/components/Checkbox/Checkbox.tsx @@ -1,23 +1,27 @@ 'use client'; -import { type ComponentRef, useContext } from 'react'; -import { forwardRef } from 'react'; +import type { ComponentRef } from 'react'; +import { forwardRef, useContext } from 'react'; import { useDOMRef, mergeProps, filterDOMProps } from '@koobiq/react-core'; import { VisuallyHidden } from '@react-aria/visually-hidden'; import { useToggleState } from '@react-stately/toggle'; +import { + useRenderProps, + useContextProps, + CheckboxContext, +} from 'react-aria-components'; import { useCheckbox, useCheckboxGroupItem } from '../../behaviors'; -import { removeDataAttributes, useRenderProps } from '../../utils'; +import { removeDataAttributes } from '../../utils'; -import { - CheckboxGroupContext, - type CheckboxProps, - type CheckboxRenderProps, -} from './index'; +import { CheckboxGroupContext } from './index'; +import type { CheckboxProps, CheckboxRenderProps } from './index'; export const Checkbox = forwardRef, CheckboxProps>( - (props, ref) => { + (inProps, inRef) => { + const [props, ref] = useContextProps(inProps, inRef, CheckboxContext); + const { children, inputRef } = props; const groupState = useContext(CheckboxGroupContext); diff --git a/packages/primitives/src/components/Checkbox/types.ts b/packages/primitives/src/components/Checkbox/types.ts index 0dc4ab3c..c1147d99 100644 --- a/packages/primitives/src/components/Checkbox/types.ts +++ b/packages/primitives/src/components/Checkbox/types.ts @@ -19,6 +19,7 @@ export type CheckboxRenderProps = { type CheckboxBaseProps = RenderProps & { inputRef?: RefObject; + slot?: string; }; export type CheckboxProps = ExtendableProps< diff --git a/packages/primitives/src/components/FieldError/FieldError.tsx b/packages/primitives/src/components/FieldError/FieldError.tsx index ae3f347f..dcd83031 100644 --- a/packages/primitives/src/components/FieldError/FieldError.tsx +++ b/packages/primitives/src/components/FieldError/FieldError.tsx @@ -1,14 +1,11 @@ -import { - type ComponentPropsWithRef, - createContext, - type ElementType, - useContext, -} from 'react'; +import { createContext, useContext } from 'react'; +import type { ComponentPropsWithRef, ElementType } from 'react'; import type { ValidationResult } from '@koobiq/react-core'; import { isNotNil, polymorphicForwardRef } from '@koobiq/react-core'; +import type { RenderProps } from 'react-aria-components'; +import { useRenderProps } from 'react-aria-components'; -import { type RenderProps, useRenderProps } from '../../utils'; import { Text } from '../Text'; export const FieldErrorContext = createContext(null); diff --git a/packages/primitives/src/components/Form/Form.tsx b/packages/primitives/src/components/Form/Form.tsx index 49dd552a..feb07ce8 100644 --- a/packages/primitives/src/components/Form/Form.tsx +++ b/packages/primitives/src/components/Form/Form.tsx @@ -6,9 +6,10 @@ import type { FormProps as SharedFormProps, } from '@koobiq/react-core'; import { FormValidationContext } from '@react-stately/form'; +import type { ContextValue } from 'react-aria-components'; +import { useContextProps } from 'react-aria-components'; -import type { ContextValue, DOMProps } from '../../utils'; -import { useContextProps } from '../../utils'; +import type { DOMProps } from '../../utils'; export interface FormProps extends SharedFormProps, DOMProps, GlobalDOMAttributes { diff --git a/packages/primitives/src/components/Group/Group.tsx b/packages/primitives/src/components/Group/Group.tsx index c6d51e8c..4023bb37 100644 --- a/packages/primitives/src/components/Group/Group.tsx +++ b/packages/primitives/src/components/Group/Group.tsx @@ -8,10 +8,10 @@ import { useHover, useFocusRing, } from '@koobiq/react-core'; +import { useRenderProps } from 'react-aria-components'; -import { useRenderProps } from '../../utils'; - -import { type GroupProps, type GroupRef, useGroupContext } from './index'; +import { useGroupContext } from './index'; +import type { GroupProps, GroupRef } from './index'; export const Group = forwardRef((props, ref) => { const defaultProps = useGroupContext(); diff --git a/packages/primitives/src/components/Label/Label.tsx b/packages/primitives/src/components/Label/Label.tsx index d3d9bbf4..ddbe7dc6 100644 --- a/packages/primitives/src/components/Label/Label.tsx +++ b/packages/primitives/src/components/Label/Label.tsx @@ -3,8 +3,7 @@ import type { ComponentPropsWithRef, ElementType } from 'react'; import { polymorphicForwardRef } from '@koobiq/react-core'; - -import { useContextProps } from '../../utils'; +import { useContextProps } from 'react-aria-components'; import type { LabelBaseProps } from './index'; import { LabelContext } from './index'; diff --git a/packages/primitives/src/components/Link/Link.tsx b/packages/primitives/src/components/Link/Link.tsx index 3f3f536c..21dd0519 100644 --- a/packages/primitives/src/components/Link/Link.tsx +++ b/packages/primitives/src/components/Link/Link.tsx @@ -8,9 +8,9 @@ import { polymorphicForwardRef, filterDOMProps, } from '@koobiq/react-core'; +import { useRenderProps } from 'react-aria-components'; import { useLink } from '../../behaviors'; -import { useRenderProps } from '../../utils'; import type { LinkBaseProps } from './types.js'; diff --git a/packages/primitives/src/components/NumberField/NumberField.tsx b/packages/primitives/src/components/NumberField/NumberField.tsx index 3743e608..f429b213 100644 --- a/packages/primitives/src/components/NumberField/NumberField.tsx +++ b/packages/primitives/src/components/NumberField/NumberField.tsx @@ -6,15 +6,15 @@ import { filterDOMProps } from '@koobiq/react-core'; import { useLocale } from '@react-aria/i18n'; import { useNumberField } from '@react-aria/numberfield'; import { useNumberFieldState } from '@react-stately/numberfield'; - import { + ButtonContext, DEFAULT_SLOT, Provider, - removeDataAttributes, useRenderProps, useSlottedContext, -} from '../../utils'; -import { ButtonContext } from '../Button'; +} from 'react-aria-components'; + +import { removeDataAttributes } from '../../utils'; import { FieldErrorContext } from '../FieldError'; import { FormContext } from '../Form'; import { GroupContext } from '../Group'; diff --git a/packages/primitives/src/components/ProgressBar/ProgressBar.tsx b/packages/primitives/src/components/ProgressBar/ProgressBar.tsx index 81a7127a..89af630c 100644 --- a/packages/primitives/src/components/ProgressBar/ProgressBar.tsx +++ b/packages/primitives/src/components/ProgressBar/ProgressBar.tsx @@ -2,8 +2,8 @@ import { mergeProps, polymorphicForwardRef } from '@koobiq/react-core'; import { useProgressBar } from '@react-aria/progress'; +import { Provider, useRenderProps } from 'react-aria-components'; -import { Provider, useRenderProps } from '../../utils'; import { LabelContext } from '../Label'; import type { ProgressBarBaseProps } from './index'; diff --git a/packages/primitives/src/components/Radio/Radio.tsx b/packages/primitives/src/components/Radio/Radio.tsx index efaf208d..b870df9e 100644 --- a/packages/primitives/src/components/Radio/Radio.tsx +++ b/packages/primitives/src/components/Radio/Radio.tsx @@ -4,9 +4,10 @@ import { type ComponentRef, forwardRef, useContext } from 'react'; import { useDOMRef, mergeProps, filterDOMProps } from '@koobiq/react-core'; import { VisuallyHidden } from '@react-aria/visually-hidden'; +import { useRenderProps } from 'react-aria-components'; import { useRadio } from '../../behaviors'; -import { removeDataAttributes, useRenderProps } from '../../utils'; +import { removeDataAttributes } from '../../utils'; import type { RadioProps, RadioRenderProps } from './index'; import { RadioContext } from './index'; diff --git a/packages/primitives/src/components/Radio/RadioGroup.tsx b/packages/primitives/src/components/Radio/RadioGroup.tsx index 914f6be5..4591b99a 100644 --- a/packages/primitives/src/components/Radio/RadioGroup.tsx +++ b/packages/primitives/src/components/Radio/RadioGroup.tsx @@ -4,15 +4,14 @@ import { forwardRef } from 'react'; import type { ComponentRef } from 'react'; import { filterDOMProps } from '@koobiq/react-core'; - -import { useRadioGroup, useRadioGroupState } from '../../behaviors'; import { + useSlottedContext, useRenderProps, Provider, - removeDataAttributes, - useSlottedContext, - DEFAULT_SLOT, -} from '../../utils'; +} from 'react-aria-components'; + +import { useRadioGroup, useRadioGroupState } from '../../behaviors'; +import { removeDataAttributes, DEFAULT_SLOT } from '../../utils'; import { FieldErrorContext } from '../FieldError'; import { FormContext } from '../Form'; import { LabelContext } from '../Label'; diff --git a/packages/primitives/src/components/Switch/Switch.tsx b/packages/primitives/src/components/Switch/Switch.tsx index 789aeab4..816475f5 100644 --- a/packages/primitives/src/components/Switch/Switch.tsx +++ b/packages/primitives/src/components/Switch/Switch.tsx @@ -5,9 +5,10 @@ import { forwardRef } from 'react'; import { useDOMRef, mergeProps, filterDOMProps } from '@koobiq/react-core'; import { VisuallyHidden } from '@react-aria/visually-hidden'; +import { useRenderProps } from 'react-aria-components'; import { useSwitch } from '../../behaviors'; -import { removeDataAttributes, useRenderProps } from '../../utils'; +import { removeDataAttributes } from '../../utils'; import type { SwitchProps, SwitchRenderProps } from './index'; diff --git a/packages/primitives/src/components/Text/Text.tsx b/packages/primitives/src/components/Text/Text.tsx index 7fff260a..f5d8bba8 100644 --- a/packages/primitives/src/components/Text/Text.tsx +++ b/packages/primitives/src/components/Text/Text.tsx @@ -3,8 +3,7 @@ import type { ComponentPropsWithRef, ComponentRef, ElementType } from 'react'; import { polymorphicForwardRef } from '@koobiq/react-core'; - -import { useContextProps } from '../../utils'; +import { useContextProps } from 'react-aria-components'; import { type TextBaseProps, TextContext } from './index'; diff --git a/packages/primitives/src/components/TextField/TextField.tsx b/packages/primitives/src/components/TextField/TextField.tsx index ce523be9..f6c46024 100644 --- a/packages/primitives/src/components/TextField/TextField.tsx +++ b/packages/primitives/src/components/TextField/TextField.tsx @@ -10,15 +10,15 @@ import { useLocalizedStringFormatter, } from '@koobiq/react-core'; import { useTextField } from '@react-aria/textfield'; - import { Provider, + DEFAULT_SLOT, + ButtonContext, useRenderProps, useSlottedContext, - removeDataAttributes, - DEFAULT_SLOT, -} from '../../utils'; -import { ButtonContext } from '../Button'; +} from 'react-aria-components'; + +import { removeDataAttributes } from '../../utils'; import { FieldErrorContext } from '../FieldError'; import { FormContext } from '../Form'; import { InputContext } from '../Input'; @@ -157,7 +157,6 @@ function TextFieldRender( 'aria-label': stringFormatter.format('clear'), preventFocusOnPress: true, onPress: handleClear, - tabIndex: -1, }, }, }, diff --git a/packages/primitives/src/index.ts b/packages/primitives/src/index.ts index c45cc660..f7551058 100644 --- a/packages/primitives/src/index.ts +++ b/packages/primitives/src/index.ts @@ -114,6 +114,35 @@ export * from '@react-stately/form'; export * from '@react-aria/selection'; +// RAC +export type { + ContextValue, + TreeProps, + TreeRenderProps, + TreeItemProps, + TreeItemRenderProps, + TreeItemContentProps, + TreeItemContentRenderProps, + TreeLoadMoreItemProps, + TreeLoadMoreItemRenderProps, +} from 'react-aria-components'; + +export { + Tree, + Provider, + TreeItem, + TreeContext, + Collection, + TreeItemContent, + ButtonContext, + TreeStateContext, + TreeLoadMoreItem, + useContextProps, + DEFAULT_SLOT, + useSlottedContext, + composeRenderProps, +} from 'react-aria-components'; + export * from './behaviors'; export * from './components'; -export * from './utils'; +export { removeDataAttributes } from './utils'; diff --git a/packages/primitives/src/utils/index.tsx b/packages/primitives/src/utils/index.tsx index 679d716c..e2be2400 100644 --- a/packages/primitives/src/utils/index.tsx +++ b/packages/primitives/src/utils/index.tsx @@ -1,18 +1,6 @@ -import type { - JSX, - CSSProperties, - ReactNode, - Context, - ForwardedRef, -} from 'react'; -import { useMemo, useContext } from 'react'; +import type { CSSProperties, ReactNode, ForwardedRef } from 'react'; -import type { - AriaLabelingProps, - DOMProps as SharedDOMProps, - RefObject, -} from '@koobiq/react-core'; -import { mergeProps, mergeRefs, useObjectRef } from '@koobiq/react-core'; +import type { DOMProps as SharedDOMProps } from '@koobiq/react-core'; export const DEFAULT_SLOT = Symbol('default'); @@ -20,14 +8,6 @@ interface SlottedValue { slots?: Record; } -export interface SlotProps { - /** - * A slot name for the component. Slots allow the component to receive props from a parent component. - * An explicit `null` value indicates that the local props completely override all props received from a parent. - */ - slot?: string | null; -} - export type WithRef = T & { ref?: ForwardedRef }; export type SlottedContextValue = SlottedValue | T | null | undefined; @@ -65,99 +45,6 @@ export interface RenderProps extends StyleRenderProps { | ((values: T & { defaultChildren: ReactNode | undefined }) => ReactNode); } -interface RenderPropsHookOptions - extends RenderProps, SharedDOMProps, AriaLabelingProps { - values: T; - defaultChildren?: ReactNode; - defaultClassName?: string; - defaultStyle?: CSSProperties; -} - -export type UserRenderPropsReturn = { - className: string | undefined; - style: CSSProperties | undefined; - children: ReactNode | undefined; -}; - -export function useRenderProps( - props: RenderPropsHookOptions -): UserRenderPropsReturn { - const { - className, - style, - children, - defaultClassName = undefined, - defaultChildren = undefined, - defaultStyle, - values, - } = props; - - return useMemo(() => { - let computedClassName: string | undefined; - let computedStyle: CSSProperties | undefined; - let computedChildren: ReactNode | undefined; - - if (typeof className === 'function') { - computedClassName = className({ ...values, defaultClassName }); - } else { - computedClassName = className; - } - - if (typeof style === 'function') { - computedStyle = style({ ...values, defaultStyle: defaultStyle || {} }); - } else { - computedStyle = style; - } - - if (typeof children === 'function') { - computedChildren = children({ ...values, defaultChildren }); - } else if (children == null) { - computedChildren = defaultChildren; - } else { - computedChildren = children; - } - - return { - className: computedClassName ?? defaultClassName, - style: - computedStyle || defaultStyle - ? { ...defaultStyle, ...computedStyle } - : undefined, - children: computedChildren ?? defaultChildren, - }; - }, [ - className, - style, - children, - defaultClassName, - defaultChildren, - defaultStyle, - values, - ]); -} - -type ProviderValue = [Context, T]; -type ProviderValues = { - [K in keyof T]: ProviderValue; -}; - -interface ProviderProps { - values: ProviderValues; - children: ReactNode; -} - -export function Provider({ - values, - children, -}: ProviderProps): JSX.Element { - return values.reduceRight( - (acc, [Context, value]) => ( - {acc} - ), - children as JSX.Element - ); -} - export function removeDataAttributes(props: T): T { const prefix = /^(data-.*)$/; const filteredProps = {} as T; @@ -170,90 +57,3 @@ export function removeDataAttributes(props: T): T { return filteredProps; } - -export function useSlottedContext( - context: Context>, - slot?: string | null -): T | null | undefined { - const ctx = useContext(context); - - if (slot === null) { - return null; - } - - if (ctx && typeof ctx === 'object' && 'slots' in ctx && ctx.slots) { - const slotKey = slot || DEFAULT_SLOT; - - if (!ctx.slots[slotKey]) { - const availableSlots = new Intl.ListFormat().format( - Object.keys(ctx.slots).map((p) => `"${p}"`) - ); - - const errorMessage = slot - ? `Invalid slot "${slot}".` - : 'A slot prop is required.'; - - throw new Error( - `${errorMessage} Valid slot names are ${availableSlots}.` - ); - } - - return ctx.slots[slotKey]; - } - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - return ctx; -} - -export function useContextProps( - props: T & SlotProps, - ref: ForwardedRef | undefined, - context: Context> -): [T, RefObject] { - const ctx = useSlottedContext(context, props.slot) || {}; - const { ref: contextRef, ...contextProps } = ctx as any; - - const mergedRef = useObjectRef( - useMemo(() => mergeRefs(ref, contextRef), [ref, contextRef]) - ); - - const mergedProps = mergeProps(contextProps, props) as unknown as T; - - // mergeProps does not merge `style`. Adding this there might be a breaking change. - if ( - 'style' in contextProps && - contextProps.style && - 'style' in props && - props.style - ) { - if ( - typeof contextProps.style === 'function' || - typeof props.style === 'function' - ) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - mergedProps.style = (renderProps) => { - const contextStyle = - typeof contextProps.style === 'function' - ? contextProps.style(renderProps) - : contextProps.style; - - const defaultStyle = { ...renderProps.defaultStyle, ...contextStyle }; - - const style = - typeof props.style === 'function' - ? props.style({ ...renderProps, defaultStyle }) - : props.style; - - return { ...defaultStyle, ...style }; - }; - } else { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - mergedProps.style = { ...contextProps.style, ...props.style }; - } - } - - return [mergedProps, mergedRef]; -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 92ebcf42..8b3f5831 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -469,6 +469,9 @@ importers: react: specifier: ^19.0.0 version: 19.2.3 + react-aria-components: + specifier: ^1.15.1 + version: 1.15.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react-dom: specifier: ^19.0.0 version: 19.2.3(react@19.2.3) @@ -2188,6 +2191,12 @@ packages: react: ^19.0.0 react-dom: ^19.0.0 + '@react-aria/color@3.1.4': + resolution: {integrity: sha512-LNFo0A9EEn2HZ8O/hASschH++M+krfezcp01XPv0/2ZQJ5b5u7VvJlUOEXtPsD4i9+BzvkSAEoVUXdlJie9V2Q==} + peerDependencies: + react: ^19.0.0 + react-dom: ^19.0.0 + '@react-aria/combobox@3.14.2': resolution: {integrity: sha512-qwBeb8cMgK3xwrvXYHPtcphduD/k+oTcU18JHPvEO2kmR32knB33H81C2/Zoh4x86zTDJXaEtPscXBWuQ/M7AQ==} peerDependencies: @@ -2212,6 +2221,12 @@ packages: react: ^19.0.0 react-dom: ^19.0.0 + '@react-aria/dnd@3.11.5': + resolution: {integrity: sha512-3IGrABfK8Cf6/b/uEmGEDGeubWKMUK3umWunF/tdkWBnIaxpdj4gRkWFMw7siWQYnqir6AN567nrWXtHFcLKsA==} + peerDependencies: + react: ^19.0.0 + react-dom: ^19.0.0 + '@react-aria/focus@3.21.4': resolution: {integrity: sha512-6gz+j9ip0/vFRTKJMl3R30MHopn4i19HqqLfSQfElxJD+r9hBnYG1Q6Wd/kl/WRR1+CALn2F+rn06jUnf5sT8Q==} peerDependencies: @@ -2281,6 +2296,12 @@ packages: react: ^19.0.0 react-dom: ^19.0.0 + '@react-aria/meter@3.4.29': + resolution: {integrity: sha512-XAhJf8LlYQl+QQXqtpWvzjlrT8MZKEG6c8N3apC5DONgSKlCwfmDm4laGEJPqtuz3QGiOopsfSfyTFYHjWsfZw==} + peerDependencies: + react: ^19.0.0 + react-dom: ^19.0.0 + '@react-aria/numberfield@3.12.4': resolution: {integrity: sha512-TgKBjKOjyURzbqNR2wF4tSFmQKNK5DqE4QZSlQxpYYo1T6zuztkh+oTOUZ4IWCJymL5qLtuPfGHCZbR7B+DN2w==} peerDependencies: @@ -2329,6 +2350,12 @@ packages: react: ^19.0.0 react-dom: ^19.0.0 + '@react-aria/slider@3.8.4': + resolution: {integrity: sha512-/FYCgK1qVqaz2VCDfR2x4BjyJ8lmWg1v8//+WIwKdIu4cz0KUs+U3yx0w1vp676RoERp3OEvkT3tb+/jHQ1hjA==} + peerDependencies: + react: ^19.0.0 + react-dom: ^19.0.0 + '@react-aria/spinbutton@3.7.1': resolution: {integrity: sha512-Nisah6yzxOC6983u/5ck0w+OQoa3sRKmpDvWpTEX0g2+ZIABOl8ttdSd65XKtxXmXHdK8X1zmrfeGOBfBR3sKA==} peerDependencies: @@ -2401,12 +2428,24 @@ packages: react: ^19.0.0 react-dom: ^19.0.0 + '@react-aria/tree@3.1.6': + resolution: {integrity: sha512-igLX+OQrbXCBLrtPWgUevU0iDrgTSAJh1ncHoPzfD/YDcyTDLqKdy2nZhNbJ/IdHCwTyzIknhFJ700K20Ymw9A==} + peerDependencies: + react: ^19.0.0 + react-dom: ^19.0.0 + '@react-aria/utils@3.33.0': resolution: {integrity: sha512-yvz7CMH8d2VjwbSa5nGXqjU031tYhD8ddax95VzJsHSPyqHDEGfxul8RkhGV6oO7bVqZxVs6xY66NIgae+FHjw==} peerDependencies: react: ^19.0.0 react-dom: ^19.0.0 + '@react-aria/virtualizer@4.1.12': + resolution: {integrity: sha512-va0VAD28nq7rk1vHZvnkq591EbWuDKBwh2NzAEn+zz9JjMtpg4utcihNXECJ1DwMRkpaT6q+KpOE7dSdzTxPBQ==} + peerDependencies: + react: ^19.0.0 + react-dom: ^19.0.0 + '@react-aria/visually-hidden@3.8.30': resolution: {integrity: sha512-iY44USEU8sJy0NOJ/sTDn3YlspbhHuVG3nx2YYrzfmxbS3i+lNwkCfG8kJ77dtmbuDLIdBGKENjGkbcwz3kiJg==} peerDependencies: @@ -2433,6 +2472,11 @@ packages: peerDependencies: react: ^19.0.0 + '@react-stately/color@3.9.4': + resolution: {integrity: sha512-SprAP5STMg6K0jq+A3UoimsvvTCIGItUtWurS/lDRoQJYajFR8IUdz+mekU/GaXzvFhMN32dijOtFcfxnA4cfA==} + peerDependencies: + react: ^19.0.0 + '@react-stately/combobox@3.12.2': resolution: {integrity: sha512-h4YRmzA+s3aMwUrXm6jyWLN0BWWXUNiodArB1wC24xNdeI7S8O3mxz6G2r3Ne8AE02FXmZXs9SD30Mx5vVVuqQ==} peerDependencies: @@ -2453,6 +2497,11 @@ packages: peerDependencies: react: ^19.0.0 + '@react-stately/dnd@3.7.3': + resolution: {integrity: sha512-yBtzAimyYvJWnzP80Scx7l559+43TVSyjaMpUR6/s2IjqD3XoPKgPsv7KaFUmygBTkCBGBFJn404rYgMCOsu3g==} + peerDependencies: + react: ^19.0.0 + '@react-stately/flags@3.1.2': resolution: {integrity: sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==} @@ -2466,6 +2515,12 @@ packages: peerDependencies: react: ^19.0.0 + '@react-stately/layout@4.5.3': + resolution: {integrity: sha512-BDYnvO2AKzvWfxxVM96kif3qCynsA+XcNoQC+T77exH+LLT8zlK9oOdarZXTlok/eZmjs6+5wmjq51PeL6eM5w==} + peerDependencies: + react: ^19.0.0 + react-dom: ^19.0.0 + '@react-stately/list@3.13.3': resolution: {integrity: sha512-xN0v7rzhIKshhcshOzx+ZgVngXnGCtMPRdhoDLGaHzQy5YfxvKBMNLCnr5Lm4T1U/kIvHbyzxmr5uwmH8WxoIg==} peerDependencies: @@ -2506,6 +2561,11 @@ packages: peerDependencies: react: ^19.0.0 + '@react-stately/slider@3.7.4': + resolution: {integrity: sha512-cSOYSx2nsOQejMg6Ql0+GUpqAiPwRA5teYXUghNvuBDtVxnd4l2rnXs54Ww48tU43xf2+L3kkmMofThjABoEPw==} + peerDependencies: + react: ^19.0.0 + '@react-stately/table@3.15.3': resolution: {integrity: sha512-W1wR0O/PmdD8hCUFIAelHICjUX/Ii6ZldPlH6EILr9olyGpoCaY7XmnyG7kii1aANuQGBeskjJdXvS6LX/gyDw==} peerDependencies: @@ -2541,6 +2601,12 @@ packages: peerDependencies: react: ^19.0.0 + '@react-stately/virtualizer@4.4.5': + resolution: {integrity: sha512-MP33zys3nRYTk/+3BPchxlil9GrwbMksc3XuvNACeZqYEA/oEidsHffgPL+LY0iitKCmQE6pg49MI5HvBuOd2w==} + peerDependencies: + react: ^19.0.0 + react-dom: ^19.0.0 + '@react-types/autocomplete@3.0.0-alpha.37': resolution: {integrity: sha512-9KkL/UEUHIqp4OD4PffeZPiRV93ZBKq84sBrzTbTIPN+os+N+Lfz45Mg67NM2RumR/KQSVE0gZp7OA0eOvxPYA==} peerDependencies: @@ -2566,6 +2632,11 @@ packages: peerDependencies: react: ^19.0.0 + '@react-types/color@3.1.3': + resolution: {integrity: sha512-XM0x8iZpAf036w9qceD2RFroehLxKRwkVer7EvdJNs8K8iUN8TuhCagzsomiSJtyYh5MFysEVQ2ir85toiAFyw==} + peerDependencies: + react: ^19.0.0 + '@react-types/combobox@3.13.11': resolution: {integrity: sha512-5/tdmTAvqPpiWzEeaV7uLLSbSTkkoQ1mVz6NfKMPuw4ZBkY3lPc9JDkkQjY/JrquZao+KY4Dx8ZIoS0NqkrFrw==} peerDependencies: @@ -2606,6 +2677,11 @@ packages: peerDependencies: react: ^19.0.0 + '@react-types/meter@3.4.14': + resolution: {integrity: sha512-rNw0Do2AM3zLGZ0pSWweViuddg1uW99PWzE6RQXE8nsTHTeiwDZt9SYGdObEnjd+nJ3YzemqekG0Kqt93iNBcA==} + peerDependencies: + react: ^19.0.0 + '@react-types/numberfield@3.8.17': resolution: {integrity: sha512-Q9n24OaSMXrebMowbtowmHLNclknN3XkcBIaYMwA2BIGIl+fZFnI8MERM0pG87W+wki6FepDExsDW9YxQF4pnw==} peerDependencies: @@ -2641,6 +2717,11 @@ packages: peerDependencies: react: ^19.0.0 + '@react-types/slider@3.8.3': + resolution: {integrity: sha512-HCDegYiUA27CcJKvFwgpR8ktFKf2nAirXqQEgVPV4uxk6JIeiRx41yqM/xPJGfmaqa7BARYARLT41yN2V8Kadg==} + peerDependencies: + react: ^19.0.0 + '@react-types/switch@3.5.16': resolution: {integrity: sha512-6fynclkyg0wGHo3f1bwk4Z+gZZEg0Z63iP5TFhgHWdZ8W+Uq6F3u7V4IgQpuJ2NleL1c2jy2/CKdS9v06ac2Og==} peerDependencies: @@ -7350,6 +7431,18 @@ packages: re2@1.23.3: resolution: {integrity: sha512-5jh686rmj/8dYpBo72XYgwzgG8Y9HNDATYZ1x01gqZ6FvXVUP33VZ0+6GLCeavaNywz3OkXBU8iNX7LjiuisPg==} + react-aria-components@1.15.1: + resolution: {integrity: sha512-irGhZ+vBvoY9xJHf/qzPLLwFZ8cBUrYwPERGhgjE62dy/RXMUiEW+1DeTHz0OvtjbvFbhNp/I7XM9IaBvmLALg==} + peerDependencies: + react: ^19.0.0 + react-dom: ^19.0.0 + + react-aria@3.46.0: + resolution: {integrity: sha512-We0diSsMK35jw53JFjgF9w8obBjehAUI/TRiynnzSrjRd9eoHYQcecHlptke/HEFxvya/Gcm+LA21Im1+qnIeQ==} + peerDependencies: + react: ^19.0.0 + react-dom: ^19.0.0 + react-docgen-typescript@2.2.2: resolution: {integrity: sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==} peerDependencies: @@ -7380,6 +7473,11 @@ packages: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} engines: {node: '>=0.10.0'} + react-stately@3.44.0: + resolution: {integrity: sha512-Il3trIp2Mo1SSa9PhQFraqOpC74zEFmwuMAlu5Fj3qdtihJOKOFqoyDl7ALRrVfnvCkau6rui155d/NMKvd+RQ==} + peerDependencies: + react: ^19.0.0 + react-transition-group@4.4.5: resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} peerDependencies: @@ -10330,6 +10428,24 @@ snapshots: react-dom: 19.2.3(react@19.2.3) use-sync-external-store: 1.6.0(react@19.2.3) + '@react-aria/color@3.1.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@react-aria/i18n': 3.12.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/interactions': 3.27.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/numberfield': 3.12.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/slider': 3.8.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/spinbutton': 3.7.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/textfield': 3.18.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/utils': 3.33.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/visually-hidden': 3.8.30(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-stately/color': 3.9.4(react@19.2.3) + '@react-stately/form': 3.2.3(react@19.2.3) + '@react-types/color': 3.1.3(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@react-aria/combobox@3.14.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@react-aria/focus': 3.21.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -10395,6 +10511,22 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + '@react-aria/dnd@3.11.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@internationalized/string': 3.2.7 + '@react-aria/i18n': 3.12.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/interactions': 3.27.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/live-announcer': 3.4.4 + '@react-aria/overlays': 3.31.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/utils': 3.33.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-stately/collections': 3.12.9(react@19.2.3) + '@react-stately/dnd': 3.7.3(react@19.2.3) + '@react-types/button': 3.15.0(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@react-aria/focus@3.21.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@react-aria/interactions': 3.27.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -10535,6 +10667,15 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + '@react-aria/meter@3.4.29(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@react-aria/progress': 3.4.29(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-types/meter': 3.4.14(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@react-aria/numberfield@3.12.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@react-aria/i18n': 3.12.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -10645,6 +10786,19 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + '@react-aria/slider@3.8.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@react-aria/i18n': 3.12.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/interactions': 3.27.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/label': 3.7.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/utils': 3.33.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-stately/slider': 3.7.4(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@react-types/slider': 3.8.3(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@react-aria/spinbutton@3.7.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@react-aria/i18n': 3.12.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -10658,7 +10812,7 @@ snapshots: '@react-aria/ssr@3.9.10(react@19.2.3)': dependencies: - '@swc/helpers': 0.5.17 + '@swc/helpers': 0.5.19 react: 19.2.3 '@react-aria/switch@3.7.10(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': @@ -10788,6 +10942,19 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + '@react-aria/tree@3.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@react-aria/gridlist': 3.14.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/i18n': 3.12.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/selection': 3.27.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/utils': 3.33.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-stately/tree': 3.9.5(react@19.2.3) + '@react-types/button': 3.15.0(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@react-aria/utils@3.33.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@react-aria/ssr': 3.9.10(react@19.2.3) @@ -10799,6 +10966,17 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + '@react-aria/virtualizer@4.1.12(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@react-aria/i18n': 3.12.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/interactions': 3.27.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/utils': 3.33.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-stately/virtualizer': 4.4.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@react-aria/visually-hidden@3.8.30(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@react-aria/interactions': 3.27.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -10838,6 +11016,19 @@ snapshots: '@swc/helpers': 0.5.19 react: 19.2.3 + '@react-stately/color@3.9.4(react@19.2.3)': + dependencies: + '@internationalized/number': 3.6.5 + '@internationalized/string': 3.2.7 + '@react-stately/form': 3.2.3(react@19.2.3) + '@react-stately/numberfield': 3.10.4(react@19.2.3) + '@react-stately/slider': 3.7.4(react@19.2.3) + '@react-stately/utils': 3.11.0(react@19.2.3) + '@react-types/color': 3.1.3(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + '@react-stately/combobox@3.12.2(react@19.2.3)': dependencies: '@react-stately/collections': 3.12.9(react@19.2.3) @@ -10876,6 +11067,13 @@ snapshots: '@swc/helpers': 0.5.19 react: 19.2.3 + '@react-stately/dnd@3.7.3(react@19.2.3)': + dependencies: + '@react-stately/selection': 3.20.8(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + '@react-stately/flags@3.1.2': dependencies: '@swc/helpers': 0.5.17 @@ -10895,6 +11093,18 @@ snapshots: '@swc/helpers': 0.5.19 react: 19.2.3 + '@react-stately/layout@4.5.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@react-stately/collections': 3.12.9(react@19.2.3) + '@react-stately/table': 3.15.3(react@19.2.3) + '@react-stately/virtualizer': 4.4.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-types/grid': 3.3.7(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@react-types/table': 3.13.5(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@react-stately/list@3.13.3(react@19.2.3)': dependencies: '@react-stately/collections': 3.12.9(react@19.2.3) @@ -10963,6 +11173,14 @@ snapshots: '@swc/helpers': 0.5.19 react: 19.2.3 + '@react-stately/slider@3.7.4(react@19.2.3)': + dependencies: + '@react-stately/utils': 3.11.0(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@react-types/slider': 3.8.3(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + '@react-stately/table@3.15.3(react@19.2.3)': dependencies: '@react-stately/collections': 3.12.9(react@19.2.3) @@ -11019,6 +11237,13 @@ snapshots: '@swc/helpers': 0.5.17 react: 19.2.3 + '@react-stately/virtualizer@4.4.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@react-types/shared': 3.33.0(react@19.2.3) + '@swc/helpers': 0.5.19 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@react-types/autocomplete@3.0.0-alpha.37(react@19.2.3)': dependencies: '@react-types/combobox': 3.13.11(react@19.2.3) @@ -11048,6 +11273,12 @@ snapshots: '@react-types/shared': 3.33.0(react@19.2.3) react: 19.2.3 + '@react-types/color@3.1.3(react@19.2.3)': + dependencies: + '@react-types/shared': 3.33.0(react@19.2.3) + '@react-types/slider': 3.8.3(react@19.2.3) + react: 19.2.3 + '@react-types/combobox@3.13.11(react@19.2.3)': dependencies: '@react-types/shared': 3.33.0(react@19.2.3) @@ -11093,6 +11324,11 @@ snapshots: '@react-types/shared': 3.33.0(react@19.2.3) react: 19.2.3 + '@react-types/meter@3.4.14(react@19.2.3)': + dependencies: + '@react-types/progress': 3.5.17(react@19.2.3) + react: 19.2.3 + '@react-types/numberfield@3.8.17(react@19.2.3)': dependencies: '@react-types/shared': 3.33.0(react@19.2.3) @@ -11128,6 +11364,11 @@ snapshots: dependencies: react: 19.2.3 + '@react-types/slider@3.8.3(react@19.2.3)': + dependencies: + '@react-types/shared': 3.33.0(react@19.2.3) + react: 19.2.3 + '@react-types/switch@3.5.16(react@19.2.3)': dependencies: '@react-types/shared': 3.33.0(react@19.2.3) @@ -16840,6 +17081,87 @@ snapshots: - supports-color optional: true + react-aria-components@1.15.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + '@internationalized/date': 3.11.0 + '@internationalized/string': 3.2.7 + '@react-aria/autocomplete': 3.0.0-rc.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/collections': 3.0.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/dnd': 3.11.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/focus': 3.21.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/interactions': 3.27.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/live-announcer': 3.4.4 + '@react-aria/overlays': 3.31.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/ssr': 3.9.10(react@19.2.3) + '@react-aria/textfield': 3.18.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/toolbar': 3.0.0-beta.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/utils': 3.33.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/virtualizer': 4.1.12(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-stately/autocomplete': 3.0.0-beta.4(react@19.2.3) + '@react-stately/layout': 4.5.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-stately/selection': 3.20.8(react@19.2.3) + '@react-stately/table': 3.15.3(react@19.2.3) + '@react-stately/utils': 3.11.0(react@19.2.3) + '@react-stately/virtualizer': 4.4.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-types/form': 3.7.17(react@19.2.3) + '@react-types/grid': 3.3.7(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + '@react-types/table': 3.13.5(react@19.2.3) + '@swc/helpers': 0.5.19 + client-only: 0.0.1 + react: 19.2.3 + react-aria: 3.46.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react-dom: 19.2.3(react@19.2.3) + react-stately: 3.44.0(react@19.2.3) + use-sync-external-store: 1.6.0(react@19.2.3) + + react-aria@3.46.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + '@internationalized/string': 3.2.7 + '@react-aria/breadcrumbs': 3.5.31(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/button': 3.14.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/calendar': 3.9.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/checkbox': 3.16.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/color': 3.1.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/combobox': 3.14.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/datepicker': 3.16.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/dialog': 3.5.33(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/disclosure': 3.1.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/dnd': 3.11.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/focus': 3.21.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/gridlist': 3.14.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/i18n': 3.12.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/interactions': 3.27.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/label': 3.7.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/landmark': 3.0.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/link': 3.8.8(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/listbox': 3.15.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/menu': 3.20.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/meter': 3.4.29(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/numberfield': 3.12.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/overlays': 3.31.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/progress': 3.4.29(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/radio': 3.12.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/searchfield': 3.8.11(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/select': 3.17.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/selection': 3.27.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/separator': 3.4.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/slider': 3.8.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/ssr': 3.9.10(react@19.2.3) + '@react-aria/switch': 3.7.10(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/table': 3.17.10(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/tabs': 3.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/tag': 3.8.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/textfield': 3.18.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/toast': 3.0.10(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/tooltip': 3.9.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/tree': 3.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/utils': 3.33.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-aria/visually-hidden': 3.8.30(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + react-docgen-typescript@2.2.2(typescript@5.7.3): dependencies: typescript: 5.7.3 @@ -16874,6 +17196,36 @@ snapshots: react-refresh@0.18.0: {} + react-stately@3.44.0(react@19.2.3): + dependencies: + '@react-stately/calendar': 3.9.2(react@19.2.3) + '@react-stately/checkbox': 3.7.4(react@19.2.3) + '@react-stately/collections': 3.12.9(react@19.2.3) + '@react-stately/color': 3.9.4(react@19.2.3) + '@react-stately/combobox': 3.12.2(react@19.2.3) + '@react-stately/data': 3.15.1(react@19.2.3) + '@react-stately/datepicker': 3.16.0(react@19.2.3) + '@react-stately/disclosure': 3.0.10(react@19.2.3) + '@react-stately/dnd': 3.7.3(react@19.2.3) + '@react-stately/form': 3.2.3(react@19.2.3) + '@react-stately/list': 3.13.3(react@19.2.3) + '@react-stately/menu': 3.9.10(react@19.2.3) + '@react-stately/numberfield': 3.10.4(react@19.2.3) + '@react-stately/overlays': 3.6.22(react@19.2.3) + '@react-stately/radio': 3.11.4(react@19.2.3) + '@react-stately/searchfield': 3.5.18(react@19.2.3) + '@react-stately/select': 3.9.1(react@19.2.3) + '@react-stately/selection': 3.20.8(react@19.2.3) + '@react-stately/slider': 3.7.4(react@19.2.3) + '@react-stately/table': 3.15.3(react@19.2.3) + '@react-stately/tabs': 3.8.8(react@19.2.3) + '@react-stately/toast': 3.1.3(react@19.2.3) + '@react-stately/toggle': 3.9.4(react@19.2.3) + '@react-stately/tooltip': 3.5.10(react@19.2.3) + '@react-stately/tree': 3.9.5(react@19.2.3) + '@react-types/shared': 3.33.0(react@19.2.3) + react: 19.2.3 + react-transition-group@4.4.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: '@babel/runtime': 7.26.0