From 919c1942ce53caf0ca83ee464b65e6a86d60196c Mon Sep 17 00:00:00 2001 From: Rohan Chakraborty Date: Wed, 7 May 2025 23:43:28 +0530 Subject: [PATCH 01/14] feat: Dropdown 2.0 (#367) * wip: dropdown changes * feat: migrate to ariakit dropdown menu * fix: update dropdown doc * feat: dropdown autocomplete support * fix: dropdown focus loop * feat: dropdown examples * fix: remove redundant prop * feat: update dropdown docs * feat: update dropdown docs * feat: update linear demo * chore: update pnpm lock * chore: update lockfile --- apps/www/package.json | 2 +- apps/www/src/components/demo/demo-preview.tsx | 27 +- apps/www/src/components/demo/demo.tsx | 12 +- .../www/src/components/demo/styles.module.css | 15 + apps/www/src/components/demo/types.ts | 5 + .../src/components/linear-dropdown-demo.tsx | 285 +++++++ .../content/docs/components/dropdown/demo.ts | 362 +++++++- .../docs/components/dropdown/index.mdx | 54 +- .../content/docs/components/dropdown/props.ts | 78 +- apps/www/src/lib/prettier.ts | 24 +- .../components/dropdown-menu/cell.module.css | 10 +- .../v1/components/dropdown-menu/cell.tsx | 7 +- .../dropdown-menu/dropdown-menu-content.tsx | 83 +- .../dropdown-menu/dropdown-menu-item.tsx | 100 ++- .../dropdown-menu/dropdown-menu-misc.tsx | 78 +- .../dropdown-menu/dropdown-menu-root.tsx | 181 ++-- .../dropdown-menu/dropdown-menu-trigger.tsx | 82 +- .../dropdown-menu/dropdown-menu.module.css | 14 +- .../dropdown-menu/dropdown-menu.tsx | 24 +- .../v1/components/dropdown-menu/types.ts | 3 + .../v1/components/dropdown-menu/utils.ts | 22 +- pnpm-lock.yaml | 784 ++++++++---------- 22 files changed, 1522 insertions(+), 730 deletions(-) create mode 100644 apps/www/src/components/linear-dropdown-demo.tsx create mode 100644 packages/raystack/v1/components/dropdown-menu/types.ts diff --git a/apps/www/package.json b/apps/www/package.json index 5d21cea64..2e7668304 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -21,7 +21,7 @@ "lucide-react": "^0.477.0", "next": "14.2.5", "next-themes": "^0.4.4", - "prettier": "^2.5.1", + "prettier": "^2.8.8", "react": "^18.3.1", "react-dom": "^18.3.1", "react-live": "^4.1.8", diff --git a/apps/www/src/components/demo/demo-preview.tsx b/apps/www/src/components/demo/demo-preview.tsx index f44203325..f00a7a098 100644 --- a/apps/www/src/components/demo/demo-preview.tsx +++ b/apps/www/src/components/demo/demo-preview.tsx @@ -2,15 +2,24 @@ import { useState } from "react"; import { LiveProvider } from "react-live"; +import { cx } from "class-variance-authority"; +import { Tab, Tabs } from "fumadocs-ui/components/tabs"; import Preview from "../preview"; import Editor from "../editor"; import styles from "./styles.module.css"; import { DemoPreviewProps } from "./types"; -import { cx } from "class-variance-authority"; -export default function DemoPreview({ code, tabs, scope }: DemoPreviewProps) { +export default function DemoPreview({ + code, + tabs, + scope, + codePreview, +}: DemoPreviewProps) { const [activeTab, setActiveTab] = useState(0); const activeCode = ((tabs ? tabs[activeTab].code : code) ?? "").trim(); + + const previewCode = + typeof codePreview === "string" ? codePreview : activeCode; return (
@@ -32,7 +41,19 @@ export default function DemoPreview({ code, tabs, scope }: DemoPreviewProps) {
- + {Array.isArray(codePreview) ? ( + tab.label)} + className={styles.codeTabGroup}> + {codePreview.map(tab => ( + + + + ))} + + ) : ( + + )}
); diff --git a/apps/www/src/components/demo/demo.tsx b/apps/www/src/components/demo/demo.tsx index 76ec75e71..1178cce39 100644 --- a/apps/www/src/components/demo/demo.tsx +++ b/apps/www/src/components/demo/demo.tsx @@ -8,11 +8,21 @@ import DemoPlayground from "./demo-playground"; import { Suspense } from "react"; import { Info, X, Home, Laugh } from "lucide-react"; import DataTableDemo from "../datatable-demo"; +import LinearDropdownDemo from "../linear-dropdown-demo"; export default function Demo(props: DemoProps) { const { data, - scope = { ...Apsara, ...ApsaraV1, DataTableDemo, Info, X, Home, Laugh }, + scope = { + ...Apsara, + ...ApsaraV1, + DataTableDemo, + LinearDropdownDemo, + Info, + X, + Home, + Laugh, + }, } = props; if (data.type === "code") { diff --git a/apps/www/src/components/demo/styles.module.css b/apps/www/src/components/demo/styles.module.css index a4125fa21..68ca6e276 100644 --- a/apps/www/src/components/demo/styles.module.css +++ b/apps/www/src/components/demo/styles.module.css @@ -99,6 +99,21 @@ .iconButton.active { border-color: var(--rs-color-background-accent-emphasis); } + +.codeTabGroup { + border-radius: 0; + margin: 0; + border-bottom: none; + border-right: none; + border-left: none; + padding: 0; +} + +.codeTab { + border-radius: 0; + padding: 0; +} + @media (max-width: 920px) { .previewContainer { flex-direction: column; diff --git a/apps/www/src/components/demo/types.ts b/apps/www/src/components/demo/types.ts index 4ad990e8d..12b74c76c 100644 --- a/apps/www/src/components/demo/types.ts +++ b/apps/www/src/components/demo/types.ts @@ -1,10 +1,15 @@ export type ScopeType = Record; +type TabProps = { + label: string; + code: string; +}; export type DemoPreviewProps = { type: "code"; code?: string; tabs?: { name: string; code: string }[]; scope?: ScopeType; + codePreview?: string | TabProps[]; }; export type DemoPlaygroundProps = { diff --git a/apps/www/src/components/linear-dropdown-demo.tsx b/apps/www/src/components/linear-dropdown-demo.tsx new file mode 100644 index 000000000..aeac1d418 --- /dev/null +++ b/apps/www/src/components/linear-dropdown-demo.tsx @@ -0,0 +1,285 @@ +import { Avatar, Button, DropdownMenu, Flex, Text } from "@raystack/apsara/v1"; +import { Calendar, ChevronRight, Download } from "lucide-react"; +import { Fragment, ReactNode, useState } from "react"; + +type DropdownMenuItem = + | { + type: "item"; + label: string | string[]; + disabled?: boolean; + trailingIcon?: ReactNode; + leadingIcon?: ReactNode; + } + | { type: "separator" } + | { type: "group"; label: string; items: DropdownMenuItem[] } + | { + type: "submenu"; + label: string; + items: DropdownMenuItem[]; + trailingIcon?: ReactNode; + leadingIcon?: ReactNode; + }; + +const dropdownMenuData: DropdownMenuItem[] = [ + { + type: "group", + label: "Actions", + items: [ + { + type: "submenu", + label: "Assign member...", + items: [ + { + type: "item", + label: "Rohan", + leadingIcon: ( + + ), + }, + { + type: "item", + label: "Rohil", + leadingIcon: ( + + ), + }, + { + type: "item", + label: "Gaurav", + leadingIcon: ( + + ), + }, + { + type: "item", + label: "Abhishek", + leadingIcon: ( + + ), + }, + { + type: "item", + label: "Aman", + leadingIcon: ( + + ), + }, + { + type: "item", + label: "Risabh", + leadingIcon: ( + + ), + }, + { + type: "item", + label: "Ajinkya", + leadingIcon: ( + + ), + }, + ], + }, + { type: "item", label: "Subscribe..." }, + { type: "item", label: "Rename..." }, + ], + }, + { type: "separator" }, + { + type: "group", + label: "More", + items: [ + { + type: "submenu", + label: "Export", + items: [ + { + type: "item", + label: "All (.zip)", + leadingIcon: , + }, + { + type: "submenu", + label: "CSV", + leadingIcon: , + items: [ + { + type: "item", + label: "All", + leadingIcon: , + }, + { + type: "item", + label: "3 Months", + leadingIcon: , + }, + { + type: "item", + label: "6 Months", + leadingIcon: , + }, + ], + }, + { + type: "submenu", + label: "PDF", + leadingIcon: , + items: [ + { + type: "item", + label: "All", + leadingIcon: , + }, + { + type: "item", + label: "3 Months", + leadingIcon: , + }, + { + type: "item", + label: "6 Months", + leadingIcon: , + }, + ], + }, + ], + }, + { type: "item", label: "Copy", disabled: true }, + { + type: "item", + label: "Delete...", + trailingIcon: ( + + ⌘⇧D + + ), + }, + ], + }, +]; + +function filterDropdownMenuItems( + items: DropdownMenuItem[], + query: string, + path: string[] = [], + isInsideSubmenu = false, +): DropdownMenuItem[] { + if (!query?.length) return items; + const normalizedQuery = query.trim().toLowerCase(); + const results: DropdownMenuItem[] = []; + + for (const item of items) { + if (item.type === "separator") continue; + + if (item.type === "item") { + const fullPath = isInsideSubmenu ? [...path, item.label] : [item.label]; + const flatLabel = fullPath.join(" ").toLowerCase(); + if (flatLabel.includes(normalizedQuery)) { + results.push({ + ...item, + label: fullPath, + } as DropdownMenuItem); + } + } + + if (item.type === "submenu") { + const nested = filterDropdownMenuItems( + item.items, + query, + [...path, item.label], + true, + ); + results.push(...nested); + } + + if (item.type === "group") { + const nested = filterDropdownMenuItems( + item.items, + query, + path, + isInsideSubmenu, + ); + results.push(...nested); + } + } + + return results.slice(0, 8); +} + +export default function LinearDropdownDemo() { + const [searchQuery, setSearchQuery] = useState(""); + + const renderDropdownMenu = (items: DropdownMenuItem[], query: string) => { + const filteredItems = filterDropdownMenuItems(items, query); + + if (searchQuery && filteredItems.length === 0) { + return ( +
+ No results +
+ ); + } + + return filteredItems.map((item, index) => { + switch (item.type) { + case "group": + return ( + + {item.label} + {item.items && renderDropdownMenu(item.items, query)} + + ); + case "separator": + return ; + case "submenu": + return ( + + + {item.label} + + + {item.items && renderDropdownMenu(item.items, query)} + + + ); + case "item": + return ( + + {Array.isArray(item.label) + ? item.label.map((part, i) => ( + + {i > 0 && } + {part} + + )) + : item.label} + + ); + default: + return null; + } + }); + }; + + return ( + + setSearchQuery(value)}> + + + + + {renderDropdownMenu(dropdownMenuData, searchQuery)} + + + + ); +} diff --git a/apps/www/src/content/docs/components/dropdown/demo.ts b/apps/www/src/content/docs/components/dropdown/demo.ts index ea755f13d..d113096e1 100644 --- a/apps/www/src/content/docs/components/dropdown/demo.ts +++ b/apps/www/src/content/docs/components/dropdown/demo.ts @@ -6,7 +6,7 @@ export const getCode = (props: any) => { return ` - + @@ -16,34 +16,34 @@ export const getCode = (props: any) => { Actions - - + + Export - - - + + + All (.zip) - + CSV - - + + All 3 Months 6 Months - - - - + + + + PDF - - + + All 3 Months 6 Months - - - - + + + + Copy `, }; + +export const autocompleteDemo = { + type: "code", + tabs: [ + { + name: "Default Autocomplete", + code: ` + + + + + + + Heading + Assign member... + Subscribe... + Rename... + + + Actions + + Export + + All (.zip) + + CSV + + All + 3 Months + 6 Months + + + + PDF + + All + 3 Months + 6 Months + + + + + Copy + + ⌘⇧D + + }> + Delete... + + + `, + }, + { + name: "Manual Autocomplete", + code: ` + function ManualDemo(){ + const items = [ + "Assign member...", + "Subscribe...", + "Rename...", + "Copy", + "Delete...", + ]; + + const [simpleSearchQuery, setSimpleSearchQuery] = React.useState(""); + return setSimpleSearchQuery(value)}> + + + + + {items + .filter(item => item.toLowerCase().includes(simpleSearchQuery)) + .map((item, index) => ( + {item} + ))} + + + }`, + }, + ], +}; + +export const linearDemo = { + type: "code", + previewCode: false, + code: ``, + codePreview: [ + { + label: "index.tsx", + code: `function LinearDropdownDemo() { + const [searchQuery, setSearchQuery] = useState(""); + + const renderDropdownMenu = (items: DropdownMenuItem[], query: string) => { + const filteredItems = filterDropdownMenuItems(items, query); + + if (searchQuery && filteredItems.length === 0) { + return
No results
; + } + + return filteredItems.map((item, index) => { + switch (item.type) { + case "group": + return ( + + {item.label} + {item.items && renderDropdownMenu(item.items, query)} + + ); + case "separator": + return ; + case "submenu": + return ( + + + {item.label} + + + {item.items && renderDropdownMenu(item.items, query)} + + + ); + case "item": + return ( + + {Array.isArray(item.label) + ? item.label.map((part, i) => ( + + {i > 0 && } + {part} + + )) + : item.label} + + ); + default: + return null; + } + }); + }; + + return ( + setSearchQuery(value)}> + + + + + {renderDropdownMenu(dropdownMenuData, searchQuery)} + + + ); +} +`, + }, + { + label: "utils.ts", + code: `function filterDropdownMenuItems( + items: DropdownMenuItem[], + query: string, + path: string[] = [], + isInsideSubmenu = false, +): DropdownMenuItem[] { + if (!query?.length) return items; + const normalizedQuery = query.trim().toLowerCase(); + const results: DropdownMenuItem[] = []; + + for (const item of items) { + if (item.type === "separator") continue; + + if (item.type === "item") { + const fullPath = isInsideSubmenu ? [...path, item.label] : [item.label]; + const flatLabel = fullPath.join(" ").toLowerCase(); + if (flatLabel.includes(normalizedQuery)) { + results.push({ + ...item, + label: fullPath, + } as DropdownMenuItem); + } + } + + if (item.type === "submenu") { + const nested = filterDropdownMenuItems( + item.items, + query, + [...path, item.label], + true, + ); + results.push(...nested); + } + + if (item.type === "group") { + const nested = filterDropdownMenuItems( + item.items, + query, + path, + isInsideSubmenu, + ); + results.push(...nested); + } + } + + return results.slice(0, 8); +}`, + }, + { + label: "data.ts", + code: `type DropdownMenuItem = + | { + type: "item"; + label: string | string[]; + disabled?: boolean; + trailingIcon?: ReactNode; + leadingIcon?: ReactNode; + } + | { type: "separator" } + | { type: "group"; label: string; items: DropdownMenuItem[] } + | { + type: "submenu"; + label: string; + items: DropdownMenuItem[]; + trailingIcon?: ReactNode; + leadingIcon?: ReactNode; + }; + +const dropdownMenuData: DropdownMenuItem[] = [ + { + type: "group", + label: "Heading", + items: [ + { type: "item", label: "Assign member..." }, + { type: "item", label: "Subscribe..." }, + { type: "item", label: "Rename..." }, + ], + }, + { type: "separator" }, + { + type: "group", + label: "Actions", + items: [ + { + type: "submenu", + label: "Export", + items: [ + { + type: "item", + label: "All (.zip)", + leadingIcon: , + }, + { + type: "submenu", + label: "CSV", + leadingIcon: , + items: [ + { + type: "item", + label: "All", + leadingIcon: , + }, + { + type: "item", + label: "3 Months", + leadingIcon: , + }, + { + type: "item", + label: "6 Months", + leadingIcon: , + }, + ], + }, + { + type: "submenu", + label: "PDF", + leadingIcon: , + items: [ + { + type: "item", + label: "All", + leadingIcon: , + }, + { + type: "item", + label: "3 Months", + leadingIcon: , + }, + { + type: "item", + label: "6 Months", + leadingIcon: , + }, + ], + }, + ], + }, + { type: "item", label: "Copy", disabled: true }, + { + type: "item", + label: "Delete...", + trailingIcon: ( + + ⌘⇧D + + ), + }, + ], + }, +];`, + }, + ], +}; diff --git a/apps/www/src/content/docs/components/dropdown/index.mdx b/apps/www/src/content/docs/components/dropdown/index.mdx index fd6165038..6a9cbb1d7 100644 --- a/apps/www/src/content/docs/components/dropdown/index.mdx +++ b/apps/www/src/content/docs/components/dropdown/index.mdx @@ -1,51 +1,69 @@ --- title: Dropdown Menu -description: Displays a menu to the user — such as a set of actions or functions — triggered by a button. +description: Displays a menu to the user, such as a set of actions or functions, triggered by a button. tag: update --- -import { playground, iconsDemo, customDemo, basicDemo } from "./demo.ts"; +import { + playground, + iconsDemo, + customDemo, + basicDemo, + autocompleteDemo, + linearDemo, +} from "./demo.ts"; ## Dropdown Props -Customize the dropdown menu's behavior and appearance with these configuration options. -The DropdownMenu component is composed of several parts, each with their own props +The DropdownMenu component is composed of several parts, each with their own props. + +The root element is the parent component that holds the dropdown menu. Using the `autocomplete` prop, you can enable autocomplete functionality. Built on top of [Ariakit MenuProvider](https://ariakit.org/reference/menu-provider) + + ### DropdownMenu.Trigger -The button that opens the dropdown menu. +The button that triggers the dropdown menu. Built on top of [Ariakit MenuButton](https://ariakit.org/reference/menu-button) +### DropdownMenu.TriggerItem + +`TriggerItem` is a helper component that renders a `DropdownMenu.Trigger` as a `DropdownMenu.MenuItem`. + +Accepts all `DropdownMenu.Item` props. The component is helpful to match styles for sub menu trigger. Use DropdownMenu.Trigger if you want more control. + ### DropdownMenu.Content -The container that holds the dropdown menu items. +The container that holds the dropdown menu items. Built on top of [Ariakit Menu](https://ariakit.org/reference/menu) ### DropdownMenu.Item -Individual clickable options within the dropdown menu. +Individual clickable options within the dropdown menu. Built on top of [Ariakit MenuItem](https://ariakit.org/reference/menu-item). + +Renders as an [Ariakit ComboboxItem](https://ariakit.org/reference/combobox-item) when used in an autocomplete dropdown. By default, the item's `children` is used for matching and selection, which can be overriden by passing a `value` prop. ### DropdownMenu.Group -A way to group related menu items together. +A way to group related menu items together. Built on top of [Ariakit MenuGroup](https://ariakit.org/reference/menu-group) ### DropdownMenu.Label -Text labels to describe groups of menu items. +Renders a label in a menu group. This component should be wrapped with DropdownMenu.Group so the `aria-labelledby` is correctly set on the group element. Built on top of [Ariakit MenuGroupLabel](https://ariakit.org/reference/menu-group-label) ### DropdownMenu.Separator -Visual divider between menu items or groups. +Visual divider between menu items or groups. Built on top of [Ariakit MenuSeparator](https://ariakit.org/reference/menu-separator) @@ -74,3 +92,19 @@ You can add icons to the dropdown items. Supports both leading and trailing icon Organize related menu items into sections with descriptive headers. + +### Autocomplete + +To enable autocomplete, pass the `autocomplete` prop to the Dropdown root element. Each menu instance will manage its own autocomplete behavior. + +By default, only the top-level menu items are filtered. For more advanced control, set `autocompleteMode="manual"` and implement your own custom filtering logic. + + + +### Linear inspired Dropdown + +This is a Linear-inspired dropdown component that supports custom filtering and displays nested options. Users can search through all nested items using a single input field. + +To closely replicate Linear-style filtering, the filtering logic should include result ranking. Using a utility like [match-sorter](https://www.npmjs.com/package/match-sorter) can help achieve this by sorting filtered results based on relevance. + + diff --git a/apps/www/src/content/docs/components/dropdown/props.ts b/apps/www/src/content/docs/components/dropdown/props.ts index 5d9c9f6f5..eb9723ed5 100644 --- a/apps/www/src/content/docs/components/dropdown/props.ts +++ b/apps/www/src/content/docs/components/dropdown/props.ts @@ -1,20 +1,71 @@ +export interface DropdownMenuRootProps { + /** Enables search functionality within the dropdown menu */ + autocomplete?: boolean; + + /** Controls the autocomplete behavior mode + * - "auto": Automatically filters items as user types + * - "manual": Requires explicit filtering through onSearch callback + * @default "auto" + */ + autocompleteMode?: "auto" | "manual"; + + /** Current search value for autocomplete */ + searchValue?: string; + + /** Initial search value for autocomplete */ + defaultSearchValue?: string; + + /** Callback fired when the search value changes */ + onSearch?: (value: string) => void; + + /** Placement of the dropdown relative to the trigger + * @default "bottom-start"" + */ + placement?: + | "top" + | "top-start" + | "top-end" + | "bottom" + | "bottom-start" + | "bottom-end" + | "left" + | "left-start" + | "left-end" + | "right" + | "right-start" + | "right-end"; + + /** Whether the dropdown should loop focus when navigating with keyboard + * @default true + */ + focusLoop?: boolean; +} + export interface DropdownMenuTriggerProps { /** Boolean to merge props onto child element */ asChild?: boolean; } export interface DropdownMenuContentProps { - /** Alignment of the dropdown */ - align?: "start" | "center" | "end"; + /** Placeholder text for the autocomplete search input + * @default "Search..." + */ + searchPlaceholder?: string; /** - * Offset from the trigger + * The distance between the popover and the anchor element. * @default 4 */ - sideOffset?: number; + gutter?: number; - /** Additional CSS class names */ - className?: string; + /** + * The skidding of the popover along the anchor element. Can be set to negative values to make the popover shift to the opposite side. + * @default 0 + */ + shift?: number; + + /** Boolean to merge props onto child element */ + asChild?: boolean; } export interface DropdownMenuItemProps { @@ -27,23 +78,38 @@ export interface DropdownMenuItemProps { /** Whether the item is disabled */ disabled?: boolean; + /** Value of the item to be used for autocomplete */ + value?: string; + /** Additional CSS class names */ className?: string; + + /** Boolean to merge props onto child element */ + asChild?: boolean; } export interface DropdownMenuGroupProps { /** Additional CSS class names */ className?: string; + + /** Boolean to merge props onto child element */ + asChild?: boolean; } export interface DropdownMenuLabelProps { /** Additional CSS class names */ className?: string; + + /** Boolean to merge props onto child element */ + asChild?: boolean; } export interface DropdownMenuSeparatorProps { /** Additional CSS class names */ className?: string; + + /** Boolean to merge props onto child element */ + asChild?: boolean; } export interface DropdownMenuEmptyStateProps { diff --git a/apps/www/src/lib/prettier.ts b/apps/www/src/lib/prettier.ts index 97534c6a6..5e0dc7cc5 100644 --- a/apps/www/src/lib/prettier.ts +++ b/apps/www/src/lib/prettier.ts @@ -3,13 +3,21 @@ import prettier from "prettier/standalone"; // @ts-ignore import tsParser from "prettier/parser-typescript"; +const prettierOptions = { + parser: "typescript", + plugins: [tsParser], + printWidth: 80, +}; export const getFormattedCode = (code: string) => { - return prettier - .format(`(${code})`, { - parser: "typescript", - plugins: [tsParser], - printWidth: 80, - }) - .trim() - .replace(/;\s*$/, ""); //remove trailing semicolon + try { + return prettier + .format(`(${code})`, prettierOptions) + .trim() + .replace(/;\s*$/, ""); //remove trailing semicolon + } catch (e) { + return prettier + .format(`${code}`, prettierOptions) + .trim() + .replace(/;\s*$/, ""); //remove trailing semicolon + } }; diff --git a/packages/raystack/v1/components/dropdown-menu/cell.module.css b/packages/raystack/v1/components/dropdown-menu/cell.module.css index ef0c14aa1..bce9bde8b 100644 --- a/packages/raystack/v1/components/dropdown-menu/cell.module.css +++ b/packages/raystack/v1/components/dropdown-menu/cell.module.css @@ -3,7 +3,7 @@ padding: var(--rs-space-3); display: flex; align-items: center; - gap: var(--rs-space-2); + gap: var(--rs-space-3); font-family: var(--rs-font-body); font-weight: var(--rs-font-weight-regular); font-size: var(--rs-font-size-small); @@ -11,10 +11,7 @@ letter-spacing: var(--rs-letter-spacing-small); } -.cell:hover, -.cell:focus, -.cell[data-highlighted]:not(.comboboxcell), -.cell.comboboxcell[data-active-item] { +.cell[data-active-item] { outline: none; cursor: pointer; font-family: var(--rs-font-body); @@ -25,7 +22,8 @@ border-radius: var(--rs-radius-2); background: var(--rs-color-background-base-primary-hover); } -.cell[data-disabled] { + +.cell[aria-disabled] { opacity: 0.6; pointer-events: none; } diff --git a/packages/raystack/v1/components/dropdown-menu/cell.tsx b/packages/raystack/v1/components/dropdown-menu/cell.tsx index 0a08392b4..b6fc3a7cc 100644 --- a/packages/raystack/v1/components/dropdown-menu/cell.tsx +++ b/packages/raystack/v1/components/dropdown-menu/cell.tsx @@ -4,12 +4,13 @@ import styles from "./cell.module.css"; import { Checkbox } from "../checkbox"; export type CellBaseProps = { - type?: "select" | "item"; - isComboboxCell?: boolean; leadingIcon?: ReactNode; trailingIcon?: ReactNode; }; -export type CellProps = HTMLAttributes & CellBaseProps; +export type CellProps = HTMLAttributes & + CellBaseProps & { + type?: "select" | "item"; + }; export const Cell = forwardRef( ( diff --git a/packages/raystack/v1/components/dropdown-menu/dropdown-menu-content.tsx b/packages/raystack/v1/components/dropdown-menu/dropdown-menu-content.tsx index 6eec46163..1d5bdcbde 100644 --- a/packages/raystack/v1/components/dropdown-menu/dropdown-menu-content.tsx +++ b/packages/raystack/v1/components/dropdown-menu/dropdown-menu-content.tsx @@ -1,40 +1,57 @@ -import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"; -import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; +import { ElementRef, forwardRef, useRef } from "react"; +import { Menu, MenuProps, useMenuContext } from "@ariakit/react"; import { Combobox, ComboboxList } from "@ariakit/react"; import { cx } from "class-variance-authority"; -import { useDropdownContext } from "./dropdown-menu-root"; import styles from "./dropdown-menu.module.css"; +import { WithAsChild } from "./types"; +import { Slot } from "@radix-ui/react-slot"; +import { useDropdownContext } from "./dropdown-menu-root"; + +export interface MenuContentProps + extends Omit, "portal"> { + searchPlaceholder?: string; +} export const DropdownMenuContent = forwardRef< - ElementRef, - ComponentPropsWithoutRef ->(({ className, children, sideOffset = 4, ...props }, ref) => { - const { autocomplete } = useDropdownContext(); - return ( - - , + MenuContentProps +>( + ( + { className, children, asChild, searchPlaceholder = "Search...", ...props }, + ref, + ) => { + const menu = useMenuContext(); + const { autocomplete } = useDropdownContext(); + const isSubMenu = !!menu?.parent; + const comboboxRef = useRef(null); + + return ( + : undefined} {...props}> {autocomplete ? ( <> { - event.preventDefault(); - event.stopPropagation(); - }} - onMouseOver={event => { - event.preventDefault(); - event.stopPropagation(); + autoSelect + onPointerEnter={e => { + if (document && document.activeElement !== comboboxRef.current) + comboboxRef.current?.focus(); }} /> @@ -44,23 +61,7 @@ export const DropdownMenuContent = forwardRef< ) : ( children )} - - - ); -}); -DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; - -export const DropdownMenuSubMenuContent = forwardRef< - ElementRef, - ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)); -DropdownMenuSubMenuContent.displayName = - DropdownMenuPrimitive.SubContent.displayName; + + ); + }, +); diff --git a/packages/raystack/v1/components/dropdown-menu/dropdown-menu-item.tsx b/packages/raystack/v1/components/dropdown-menu/dropdown-menu-item.tsx index e6d3f6bd6..5b7077f6a 100644 --- a/packages/raystack/v1/components/dropdown-menu/dropdown-menu-item.tsx +++ b/packages/raystack/v1/components/dropdown-menu/dropdown-menu-item.tsx @@ -1,46 +1,62 @@ -import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"; -import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; +import { forwardRef } from "react"; +import { MenuItem, MenuItemProps, useMenuContext } from "@ariakit/react"; +import { ComboboxItem, ComboboxItemProps } from "@ariakit/react"; import { Cell, CellBaseProps } from "./cell"; -import { useDropdownContext, useMenuLevel } from "./dropdown-menu-root"; -import { ComboboxItem } from "@ariakit/react"; -import { getMatch, getValue } from "./utils"; +import { WithAsChild } from "./types"; +import { Slot } from "@radix-ui/react-slot"; +import { useDropdownContext } from "./dropdown-menu-root"; +import { getMatch } from "./utils"; + +export interface DropdownMenuItemProps + extends WithAsChild, + CellBaseProps { + forceRender?: "combobox" | "auto"; + value?: string; +} export const DropdownMenuItem = forwardRef< - ElementRef, - ComponentPropsWithoutRef & - Omit & { - value?: string; - } ->(({ children, value, ...props }, ref) => { - const { autocomplete, searchValue } = useDropdownContext(); - const menuLevel = useMenuLevel(); - - const item = ( - - {children} - - ); - - if (menuLevel >= 2) return item; - - const computedValue = getValue(value, children); - - if (autocomplete && !getMatch(computedValue, searchValue)) return null; - - if (autocomplete) return ; - - return item; + HTMLDivElement, + DropdownMenuItemProps +>(({ children, asChild, forceRender, value, ...props }, ref) => { + const { autocomplete, searchValue, shouldFilter } = useDropdownContext(); + const menu = useMenuContext(); + + const defaultProps: MenuItemProps = { + ref, + focusOnHover: true, + blurOnHoverEnd: false, + render: asChild ? : , + ...props, + }; + + // In auto mode, hide items that don't match the search value + if (!forceRender && shouldFilter && !getMatch(value, children, searchValue)) { + return null; + } + + if (forceRender === "combobox" || autocomplete) { + const comboboxProps = defaultProps as ComboboxItemProps; + return ( + { + // Make sure that clicking on a combobox item that opens a nested + // menu/dialog does not close the menu. + const expandable = event.currentTarget.hasAttribute("aria-expanded"); + if (expandable) return false; + // By default, clicking on a ComboboxItem only closes its own popover. + // However, since we're in a menu context, we also close all parent + // menus. + menu?.hideAll(); + return true; + }}> + {children} + + ); + } + + return {children}; }); - -export const DropdownMenuRadioItem = forwardRef< - ElementRef, - ComponentPropsWithoutRef & - Omit ->(({ children, ...props }, ref) => ( - - {children} - -)); -DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; - -export const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; diff --git a/packages/raystack/v1/components/dropdown-menu/dropdown-menu-misc.tsx b/packages/raystack/v1/components/dropdown-menu/dropdown-menu-misc.tsx index 48474a948..e77fa197d 100644 --- a/packages/raystack/v1/components/dropdown-menu/dropdown-menu-misc.tsx +++ b/packages/raystack/v1/components/dropdown-menu/dropdown-menu-misc.tsx @@ -1,64 +1,79 @@ import { - ComponentPropsWithoutRef, ElementRef, forwardRef, + Fragment, HTMLAttributes, ReactNode, } from "react"; +import { + MenuGroup, + MenuGroupLabel, + MenuGroupLabelProps, + MenuGroupProps, + MenuSeparator, + MenuSeparatorProps, +} from "@ariakit/react"; +import { Slot } from "@radix-ui/react-slot"; import { cx } from "class-variance-authority"; -import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; +import { WithAsChild } from "./types"; import styles from "./dropdown-menu.module.css"; -import { useDropdownContext, useMenuLevel } from "./dropdown-menu-root"; +import { useDropdownContext } from "./dropdown-menu-root"; + +export const DropdownMenuGroup = forwardRef< + ElementRef, + WithAsChild +>(({ className, asChild, ...props }, ref) => { + const { shouldFilter } = useDropdownContext(); + + return ( + : asChild ? : undefined} + {...props} + /> + ); +}); export const DropdownMenuLabel = forwardRef< - ElementRef, - ComponentPropsWithoutRef ->(({ className, ...props }, ref) => { - const { autocomplete, searchValue } = useDropdownContext(); - const menuLevel = useMenuLevel(); + ElementRef, + WithAsChild +>(({ className, asChild, ...props }, ref) => { + const { shouldFilter } = useDropdownContext(); - if (autocomplete && menuLevel === 1 && searchValue?.length) return null; + if (shouldFilter) { + return null; + } return ( - : undefined} {...props} /> ); }); -DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; export const DropdownMenuSeparator = forwardRef< - ElementRef, - ComponentPropsWithoutRef ->(({ className, ...props }, ref) => { - const { autocomplete, searchValue } = useDropdownContext(); - const menuLevel = useMenuLevel(); + ElementRef, + WithAsChild +>(({ className, asChild, ...props }, ref) => { + const { shouldFilter } = useDropdownContext(); - if (autocomplete && menuLevel === 1 && searchValue?.length) return null; + if (shouldFilter) { + return null; + } return ( - : undefined} {...props} /> ); }); -DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; - -export const DropdownMenuGroup = forwardRef< - ElementRef, - ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DropdownMenuGroup.displayName = DropdownMenuPrimitive.Group.displayName; export const DropdownMenuEmptyState = forwardRef< HTMLDivElement, @@ -70,4 +85,3 @@ export const DropdownMenuEmptyState = forwardRef< {children} )); -DropdownMenuEmptyState.displayName = "DropdownMenuEmptyState"; diff --git a/packages/raystack/v1/components/dropdown-menu/dropdown-menu-root.tsx b/packages/raystack/v1/components/dropdown-menu/dropdown-menu-root.tsx index 9eae3e03a..11f5c40a8 100644 --- a/packages/raystack/v1/components/dropdown-menu/dropdown-menu-root.tsx +++ b/packages/raystack/v1/components/dropdown-menu/dropdown-menu-root.tsx @@ -1,101 +1,124 @@ import { - ComponentProps, - createContext, - forwardRef, - useContext, - useState, -} from "react"; -import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; -import { ComboboxProvider } from "@ariakit/react"; - -interface DropdownContextValue { + ComboboxProvider, + MenuProvider, + MenuProviderProps, +} from "@ariakit/react"; +import { createContext, useContext, useState } from "react"; + +interface CommonProps { autocomplete?: boolean; + autocompleteMode?: "auto" | "manual"; searchValue?: string; } -/* -Root context to manage the Dropdown control -@remarks Only for internal usage. -*/ + +interface DropdownContextValue extends CommonProps { + parent?: CommonProps; +} + +interface UseDropdownContext extends DropdownContextValue { + shouldFilter?: boolean; + parent?: CommonProps & { + shouldFilter?: boolean; + }; +} + +/** + Root context to manage the Dropdown control + @remarks Only for internal usage. + */ + export const DropdownContext = createContext( undefined, ); -export const useDropdownContext = () => { +export const useDropdownContext = (): UseDropdownContext => { const context = useContext(DropdownContext); - if (!context) { - throw new Error( - "useDropdownContext must be used within a DropdownMenuProvider", - ); - } - return context; -}; + if (!context) return {}; -/* -Context to determine the level of Menu -@remarks Only for internal usage. -*/ -export const MenuLevelContext = createContext(1); + const shouldFilter = !!( + context?.autocomplete && + context?.autocompleteMode === "auto" && + context?.searchValue?.length + ); -export const useMenuLevel = () => useContext(MenuLevelContext); + const shouldFilterParent = !!( + context?.parent?.autocomplete && + context?.parent?.autocompleteMode === "auto" && + context?.parent?.searchValue?.length + ); -type DropdownMenuProps = ComponentProps & { - autocomplete?: boolean; + return { + ...context, + shouldFilter, + parent: context?.parent && { + ...context.parent, + shouldFilter: shouldFilterParent, + }, + }; }; -export function DropdownMenuRoot({ - children, - autocomplete = false, - defaultOpen = false, - open, - onOpenChange, +export interface NormalDropdownMenuRootProps extends MenuProviderProps { + autocomplete?: false; + autocompleteMode?: never; + searchValue?: never; + onSearch?: never; + defaultSearchValue?: never; +} + +export interface AutocompleteDropdownMenuRootProps + extends MenuProviderProps, + CommonProps { + autocomplete: true; + onSearch?: (value: string) => void; + defaultSearchValue?: string; +} + +export type DropdownMenuRootProps = + | NormalDropdownMenuRootProps + | AutocompleteDropdownMenuRootProps; + +export const DropdownMenuRoot = ({ + autocomplete, + autocompleteMode = "auto", + searchValue: providedSearchValue, + onSearch, + focusLoop = true, + defaultSearchValue = "", ...props -}: DropdownMenuProps) { - const [searchValue, setSearchValue] = useState(""); - const [internalOpen, setInternalOpen] = useState(defaultOpen); +}: DropdownMenuRootProps) => { + const [internalSearchValue, setInternalSearchValue] = + useState(defaultSearchValue); + const dropdownContext = useDropdownContext(); - const computedOpen = open ?? internalOpen; + const searchValue = providedSearchValue ?? internalSearchValue; - const setOpen = (value: boolean) => { - if (typeof onOpenChange === "function") onOpenChange(value); - else setInternalOpen(value); + const setValue = (value: string) => { + setInternalSearchValue(value); + onSearch?.(value); }; - return ( - - - - {autocomplete ? ( - - {children} - - ) : ( - children - )} - - - - ); -} + const element = ; -export const DropdownMenuSubMenu = forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ children, ...props }, ref) => { - const menuLevel = useMenuLevel(); return ( - - - {children} - - + + {autocomplete ? ( + + {element} + + ) : ( + element + )} + ); -}); -DropdownMenuSubMenu.displayName = DropdownMenuPrimitive.Sub.displayName; +}; diff --git a/packages/raystack/v1/components/dropdown-menu/dropdown-menu-trigger.tsx b/packages/raystack/v1/components/dropdown-menu/dropdown-menu-trigger.tsx index 60b47ea17..b5cc929bc 100644 --- a/packages/raystack/v1/components/dropdown-menu/dropdown-menu-trigger.tsx +++ b/packages/raystack/v1/components/dropdown-menu/dropdown-menu-trigger.tsx @@ -1,43 +1,61 @@ -import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"; -import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; -import { ComboboxItem } from "@ariakit/react"; -import { useDropdownContext, useMenuLevel } from "./dropdown-menu-root"; -import { TriangleRightIcon } from "~/v1/icons"; -import { Cell, CellBaseProps } from "./cell"; -import { getMatch, getValue } from "./utils"; +import { forwardRef } from "react"; +import { MenuButton, MenuButtonProps } from "@ariakit/react"; +import { Slot } from "@radix-ui/react-slot"; +import { DropdownMenuItem, DropdownMenuItemProps } from "./dropdown-menu-item"; +import { WithAsChild } from "./types"; +import { TriangleRightIcon } from "@raystack/apsara/icons"; +import { useDropdownContext } from "./dropdown-menu-root"; +import { getMatch } from "./utils"; -export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; +export interface DropdownMenuTriggerProps + extends WithAsChild {} -export const DropdownMenuSubMenuTrigger = forwardRef< - ElementRef, - ComponentPropsWithoutRef & - Omit & { - value?: string; - } +export const DropdownMenuTrigger = forwardRef< + HTMLButtonElement, + DropdownMenuTriggerProps +>(({ children, asChild, ...props }, ref) => { + return ( + : undefined} {...props}> + {children} + + ); +}); + +export interface DropdownMenuTriggerItemProps extends DropdownMenuItemProps {} + +/** + * `TriggerItem` is a helper component that renders a `Trigger` as a `MenuItem`. + */ +export const DropdownMenuTriggerItem = forwardRef< + HTMLButtonElement, + DropdownMenuTriggerItemProps >( ( { children, value, trailingIcon = , ...props }, ref, ) => { - const { autocomplete, searchValue } = useDropdownContext(); - const menuLevel = useMenuLevel(); + const { parent } = useDropdownContext(); - const item = ( - - - {children} - - - ); - if ((autocomplete && menuLevel >= 3) || (!autocomplete && menuLevel >= 2)) - return item; - - const computedValue = getValue(value, children); + if ( + parent?.shouldFilter && + !getMatch(value, children, parent?.searchValue) + ) { + return null; + } - if (autocomplete && !getMatch(computedValue, searchValue)) return null; - if (autocomplete) return ; - return item; + return ( + + }> + {children} + + ); }, ); -DropdownMenuSubMenuTrigger.displayName = - DropdownMenuPrimitive.SubTrigger.displayName; diff --git a/packages/raystack/v1/components/dropdown-menu/dropdown-menu.module.css b/packages/raystack/v1/components/dropdown-menu/dropdown-menu.module.css index 32182ba57..5db0e6f23 100644 --- a/packages/raystack/v1/components/dropdown-menu/dropdown-menu.module.css +++ b/packages/raystack/v1/components/dropdown-menu/dropdown-menu.module.css @@ -15,7 +15,11 @@ box-shadow: var(--rs-shadow-lifted); border: 1px solid var(--rs-color-border-base-primary); color: var(--rs-color-foreground-base-primary); - min-width: var(--radix-dropdown-menu-trigger-width); + min-width: var(--popover-anchor-width); +} +.content:focus, +.content:focus-visible { + outline: none; } .comboboxContainer { @@ -26,6 +30,10 @@ padding: var(--rs-space-2); } +.comboboxContent:empty { + padding: 0; +} + .comboboxInput { width: 100%; background: transparent; @@ -39,6 +47,10 @@ border-bottom: 0.5px solid var(--rs-color-border-base-primary); } +.comboboxContainer:has(.comboboxContent:empty) .comboboxInput { + border-bottom: none; +} + .comboboxInput:focus { outline: none; } diff --git a/packages/raystack/v1/components/dropdown-menu/dropdown-menu.tsx b/packages/raystack/v1/components/dropdown-menu/dropdown-menu.tsx index 631e12668..3c3dc3d8f 100644 --- a/packages/raystack/v1/components/dropdown-menu/dropdown-menu.tsx +++ b/packages/raystack/v1/components/dropdown-menu/dropdown-menu.tsx @@ -1,17 +1,10 @@ -import { DropdownMenuRoot, DropdownMenuSubMenu } from "./dropdown-menu-root"; +import { DropdownMenuRoot } from "./dropdown-menu-root"; +import { DropdownMenuContent } from "./dropdown-menu-content"; +import { DropdownMenuItem } from "./dropdown-menu-item"; import { - DropdownMenuContent, - DropdownMenuSubMenuContent, -} from "./dropdown-menu-content"; -import { - DropdownMenuSubMenuTrigger, DropdownMenuTrigger, + DropdownMenuTriggerItem, } from "./dropdown-menu-trigger"; -import { - DropdownMenuItem, - DropdownMenuRadioGroup, - DropdownMenuRadioItem, -} from "./dropdown-menu-item"; import { DropdownMenuEmptyState, DropdownMenuGroup, @@ -21,15 +14,14 @@ import { export const DropdownMenu = Object.assign(DropdownMenuRoot, { Trigger: DropdownMenuTrigger, + /** + * `TriggerItem` is a helper component that renders a `Trigger` as a `MenuItem`. + */ + TriggerItem: DropdownMenuTriggerItem, Content: DropdownMenuContent, Item: DropdownMenuItem, Group: DropdownMenuGroup, Label: DropdownMenuLabel, Separator: DropdownMenuSeparator, EmptyState: DropdownMenuEmptyState, - SubMenu: DropdownMenuSubMenu, - SubMenuContent: DropdownMenuSubMenuContent, - SubMenuTrigger: DropdownMenuSubMenuTrigger, - RadioItem: DropdownMenuRadioItem, - RadioGroup: DropdownMenuRadioGroup, }); diff --git a/packages/raystack/v1/components/dropdown-menu/types.ts b/packages/raystack/v1/components/dropdown-menu/types.ts new file mode 100644 index 000000000..99ac57a5a --- /dev/null +++ b/packages/raystack/v1/components/dropdown-menu/types.ts @@ -0,0 +1,3 @@ +export type WithAsChild = Omit & { + asChild?: boolean; +}; diff --git a/packages/raystack/v1/components/dropdown-menu/utils.ts b/packages/raystack/v1/components/dropdown-menu/utils.ts index 8ab68702c..9cdddf6bc 100644 --- a/packages/raystack/v1/components/dropdown-menu/utils.ts +++ b/packages/raystack/v1/components/dropdown-menu/utils.ts @@ -1,9 +1,23 @@ import { ReactNode } from "react"; -export const getMatch = (value: string, search?: string) => { +export const getMatch = ( + value?: string, + children?: ReactNode, + search?: string, +) => { if (!search?.length) return true; - return value.toLowerCase().includes(search.toLowerCase()); + const childrenValue = getChildrenValue(children)?.toLowerCase(); + + return ( + value?.toLowerCase().includes(search.toLowerCase()) || + childrenValue?.includes(search.toLowerCase()) + ); }; -export const getValue = (value?: string, children?: ReactNode) => - String(value ?? typeof children === "string" ? children : "") ?? ""; +export const getChildrenValue = (children?: ReactNode) => { + if (typeof children === "string") return children; + if (typeof children === "object" && children !== null) { + return children.toString(); + } + return null; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d2af52582..912c9f6e2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: version: 2.9.2(@parcel/core@2.12.0)(typescript@4.7.2) '@turbo/gen': specifier: ^1.9.7 - version: 1.9.7(@swc/core@1.11.24)(@types/node@22.13.4)(typescript@4.7.2) + version: 1.9.7(@swc/core@1.11.21)(@types/node@22.13.4)(typescript@4.7.2) concurrently: specifier: ^9.1.2 version: 9.1.2 @@ -75,8 +75,8 @@ importers: specifier: ^0.4.4 version: 0.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) prettier: - specifier: ^2.5.1 - version: 2.5.1 + specifier: ^2.8.8 + version: 2.8.8 react: specifier: ^18.3.1 version: 18.3.1 @@ -244,7 +244,7 @@ importers: version: 15.1.0(rollup@3.25.1) '@rollup/plugin-typescript': specifier: ^11.1.1 - version: 11.1.1(rollup@3.25.1)(tslib@2.8.1)(typescript@5.4.3) + version: 11.1.1(rollup@3.25.1)(tslib@2.6.3)(typescript@5.4.3) '@svgr/rollup': specifier: ^8.1.0 version: 8.1.0(rollup@3.25.1)(typescript@5.4.3) @@ -274,7 +274,7 @@ importers: version: 3.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + version: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -304,7 +304,7 @@ importers: version: 3.25.1 rollup-plugin-postcss: specifier: ^4.0.2 - version: 4.0.2(postcss@8.4.24)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + version: 4.0.2(postcss@8.4.24)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) rollup-plugin-tsconfig-paths: specifier: ^1.5.2 version: 1.5.2(rollup@3.25.1)(typescript@5.4.3) @@ -313,7 +313,7 @@ importers: version: 7.6.0 ts-jest: specifier: ^29.2.5 - version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)))(typescript@5.4.3) + version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)))(typescript@5.4.3) tsconfig: specifier: workspace:* version: link:../tsconfig @@ -358,10 +358,6 @@ packages: resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} - '@babel/code-frame@7.27.1': - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} - engines: {node: '>=6.9.0'} - '@babel/compat-data@7.26.3': resolution: {integrity: sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==} engines: {node: '>=6.9.0'} @@ -493,10 +489,6 @@ packages: resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.9': resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} @@ -1038,8 +1030,8 @@ packages: resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==} engines: {node: '>=6.9.0'} - '@babel/runtime@7.27.1': - resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==} + '@babel/runtime@7.27.0': + resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==} engines: {node: '>=6.9.0'} '@babel/template@7.24.7': @@ -1307,33 +1299,18 @@ packages: '@floating-ui/core@1.6.4': resolution: {integrity: sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==} - '@floating-ui/core@1.7.0': - resolution: {integrity: sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==} - '@floating-ui/dom@1.6.7': resolution: {integrity: sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==} - '@floating-ui/dom@1.7.0': - resolution: {integrity: sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==} - '@floating-ui/react-dom@2.1.1': resolution: {integrity: sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' - '@floating-ui/react-dom@2.1.2': - resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - '@floating-ui/utils@0.2.4': resolution: {integrity: sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==} - '@floating-ui/utils@0.2.9': - resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} - '@formatjs/intl-localematcher@0.5.10': resolution: {integrity: sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q==} @@ -2302,6 +2279,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-arrow@1.1.2': + resolution: {integrity: sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-arrow@1.1.6': resolution: {integrity: sha512-2JMfHJf/eVnwq+2dewT3C0acmCWD3XiVA1Da+jTDqo342UlU13WvXtqHhG+yJw5JeQmu4ue2eMy6gcEArLBlcw==} peerDependencies: @@ -2533,6 +2523,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-dialog@1.1.6': + resolution: {integrity: sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-direction@1.0.1': resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} peerDependencies: @@ -2623,6 +2626,15 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 + '@radix-ui/react-focus-guards@1.1.1': + resolution: {integrity: sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-focus-guards@1.1.2': resolution: {integrity: sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==} peerDependencies: @@ -2638,6 +2650,19 @@ packages: react: ^16.8 || ^17.0 || ^18.0 react-dom: ^16.8 || ^17.0 || ^18.0 + '@radix-ui/react-focus-scope@1.1.2': + resolution: {integrity: sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-focus-scope@1.1.6': resolution: {integrity: sha512-r9zpYNUQY+2jWHWZGyddQLL9YHkM/XvSFHVcWs7bdVuxMAnCwTAuy6Pf47Z4nw7dYcUou1vg/VgjjrrH03VeBw==} peerDependencies: @@ -2727,6 +2752,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-popover@1.1.6': + resolution: {integrity: sha512-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-popper@1.1.3': resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==} peerDependencies: @@ -2740,6 +2778,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-popper@1.2.2': + resolution: {integrity: sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-popper@1.2.6': resolution: {integrity: sha512-7iqXaOWIjDBfIG7aq8CUEeCSsQMLFdn7VEE8TaFz704DtEzpPHR7w/uuzRflvKgltqSAImgcmxQ7fFX3X7wasg==} peerDependencies: @@ -2772,6 +2823,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-portal@1.1.4': + resolution: {integrity: sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-portal@1.1.8': resolution: {integrity: sha512-hQsTUIn7p7fxCPvao/q6wpbxmCwgLrlz+nOrJgC+RwfZqWY/WN+UMqkXzrtKbPrF82P43eCTl3ekeKuyAQbFeg==} peerDependencies: @@ -3332,6 +3396,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-rect@1.1.0': + resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-rect@1.1.1': resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} peerDependencies: @@ -3410,6 +3483,9 @@ packages: '@radix-ui/rect@1.0.1': resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==} + '@radix-ui/rect@1.1.0': + resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==} + '@radix-ui/rect@1.1.1': resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} @@ -3620,8 +3696,8 @@ packages: resolution: {integrity: sha512-0XR1poYvPQoPpmfDYLEqUGu5ePAQ4pdgN3VFsZBNAeze7qubVpsIY1o1R6PZpKep/DKu33GSm2NhwpCLkMs2Cw==} engines: {node: '>=14'} - '@swc/core-darwin-arm64@1.11.24': - resolution: {integrity: sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA==} + '@swc/core-darwin-arm64@1.11.21': + resolution: {integrity: sha512-v6gjw9YFWvKulCw3ZA1dY+LGMafYzJksm1mD4UZFZ9b36CyHFowYVYug1ajYRIRqEvvfIhHUNV660zTLoVFR8g==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] @@ -3632,8 +3708,8 @@ packages: cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.11.24': - resolution: {integrity: sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==} + '@swc/core-darwin-x64@1.11.21': + resolution: {integrity: sha512-CUiTiqKlzskwswrx9Ve5NhNoab30L1/ScOfQwr1duvNlFvarC8fvQSgdtpw2Zh3MfnfNPpyLZnYg7ah4kbT9JQ==} engines: {node: '>=10'} cpu: [x64] os: [darwin] @@ -3644,8 +3720,8 @@ packages: cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.11.24': - resolution: {integrity: sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==} + '@swc/core-linux-arm-gnueabihf@1.11.21': + resolution: {integrity: sha512-YyBTAFM/QPqt1PscD8hDmCLnqPGKmUZpqeE25HXY8OLjl2MUs8+O4KjwPZZ+OGxpdTbwuWFyMoxjcLy80JODvg==} engines: {node: '>=10'} cpu: [arm] os: [linux] @@ -3656,8 +3732,8 @@ packages: cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.11.24': - resolution: {integrity: sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==} + '@swc/core-linux-arm64-gnu@1.11.21': + resolution: {integrity: sha512-DQD+ooJmwpNsh4acrftdkuwl5LNxxg8U4+C/RJNDd7m5FP9Wo4c0URi5U0a9Vk/6sQNh9aSGcYChDpqCDWEcBw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] @@ -3668,8 +3744,8 @@ packages: cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.11.24': - resolution: {integrity: sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==} + '@swc/core-linux-arm64-musl@1.11.21': + resolution: {integrity: sha512-y1L49+snt1a1gLTYPY641slqy55QotPdtRK9Y6jMi4JBQyZwxC8swWYlQWb+MyILwxA614fi62SCNZNznB3XSA==} engines: {node: '>=10'} cpu: [arm64] os: [linux] @@ -3680,8 +3756,8 @@ packages: cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.11.24': - resolution: {integrity: sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==} + '@swc/core-linux-x64-gnu@1.11.21': + resolution: {integrity: sha512-NesdBXv4CvVEaFUlqKj+GA4jJMNUzK2NtKOrUNEtTbXaVyNiXjFCSaDajMTedEB0jTAd9ybB0aBvwhgkJUWkWA==} engines: {node: '>=10'} cpu: [x64] os: [linux] @@ -3692,8 +3768,8 @@ packages: cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.11.24': - resolution: {integrity: sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==} + '@swc/core-linux-x64-musl@1.11.21': + resolution: {integrity: sha512-qFV60pwpKVOdmX67wqQzgtSrUGWX9Cibnp1CXyqZ9Mmt8UyYGvmGu7p6PMbTyX7vdpVUvWVRf8DzrW2//wmVHg==} engines: {node: '>=10'} cpu: [x64] os: [linux] @@ -3704,8 +3780,8 @@ packages: cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.11.24': - resolution: {integrity: sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==} + '@swc/core-win32-arm64-msvc@1.11.21': + resolution: {integrity: sha512-DJJe9k6gXR/15ZZVLv1SKhXkFst8lYCeZRNHH99SlBodvu4slhh/MKQ6YCixINRhCwliHrpXPym8/5fOq8b7Ig==} engines: {node: '>=10'} cpu: [arm64] os: [win32] @@ -3716,8 +3792,8 @@ packages: cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.11.24': - resolution: {integrity: sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==} + '@swc/core-win32-ia32-msvc@1.11.21': + resolution: {integrity: sha512-TqEXuy6wedId7bMwLIr9byds+mKsaXVHctTN88R1UIBPwJA92Pdk0uxDgip0pEFzHB/ugU27g6d8cwUH3h2eIw==} engines: {node: '>=10'} cpu: [ia32] os: [win32] @@ -3728,8 +3804,8 @@ packages: cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.11.24': - resolution: {integrity: sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==} + '@swc/core-win32-x64-msvc@1.11.21': + resolution: {integrity: sha512-BT9BNNbMxdpUM1PPAkYtviaV0A8QcXttjs2MDtOeSqqvSJaPtyM+Fof2/+xSwQDmDEFzbGCcn75M5+xy3lGqpA==} engines: {node: '>=10'} cpu: [x64] os: [win32] @@ -3740,8 +3816,8 @@ packages: cpu: [x64] os: [win32] - '@swc/core@1.11.24': - resolution: {integrity: sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==} + '@swc/core@1.11.21': + resolution: {integrity: sha512-/Y3BJLcwd40pExmdar8MH2UGGvCBrqNN7hauOMckrEX2Ivcbv3IMhrbGX4od1dnF880Ed8y/E9aStZCIQi0EGw==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -4417,11 +4493,6 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - browserslist@4.24.5: - resolution: {integrity: sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - bs-logger@0.2.6: resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} engines: {node: '>= 6'} @@ -4505,9 +4576,6 @@ packages: caniuse-lite@1.0.30001701: resolution: {integrity: sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw==} - caniuse-lite@1.0.30001717: - resolution: {integrity: sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==} - ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -5011,10 +5079,6 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} - detect-libc@2.0.4: - resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} - engines: {node: '>=8'} - detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -5117,9 +5181,6 @@ packages: electron-to-chromium@1.5.109: resolution: {integrity: sha512-AidaH9JETVRr9DIPGfp1kAarm/W6hRJTPuCnkF+2MqhF4KaAgRIcBc8nvjk+YMXZhwfISof/7WG29eS4iGxQLQ==} - electron-to-chromium@1.5.150: - resolution: {integrity: sha512-rOOkP2ZUMx1yL4fCxXQKDHQ8ZXwisb2OycOQVKHgvB3ZI4CvehOd4y2tfnnLDieJ3Zs1RL1Dlp3cMkyIn7nnXA==} - elegant-spinner@1.0.1: resolution: {integrity: sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==} engines: {node: '>=0.10.0'} @@ -7979,6 +8040,11 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9008,9 +9074,6 @@ packages: tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsutils@3.21.0: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -9548,12 +9611,6 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/code-frame@7.27.1': - dependencies: - '@babel/helper-validator-identifier': 7.27.1 - js-tokens: 4.0.0 - picocolors: 1.1.1 - '@babel/compat-data@7.26.3': {} '@babel/compat-data@7.26.8': {} @@ -9740,8 +9797,6 @@ snapshots: '@babel/helper-validator-identifier@7.25.9': {} - '@babel/helper-validator-identifier@7.27.1': {} - '@babel/helper-validator-option@7.25.9': {} '@babel/helper-wrap-function@7.25.9': @@ -10393,7 +10448,9 @@ snapshots: dependencies: regenerator-runtime: 0.14.1 - '@babel/runtime@7.27.1': {} + '@babel/runtime@7.27.0': + dependencies: + regenerator-runtime: 0.14.1 '@babel/template@7.24.7': dependencies: @@ -10485,7 +10542,7 @@ snapshots: '@emotion/babel-plugin@11.11.0': dependencies: '@babel/helper-module-imports': 7.24.7 - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@emotion/hash': 0.9.1 '@emotion/memoize': 0.8.1 '@emotion/serialize': 1.1.4 @@ -10512,7 +10569,7 @@ snapshots: '@emotion/react@11.11.4(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.4 @@ -10662,42 +10719,25 @@ snapshots: dependencies: '@floating-ui/utils': 0.2.4 - '@floating-ui/core@1.7.0': - dependencies: - '@floating-ui/utils': 0.2.9 - '@floating-ui/dom@1.6.7': dependencies: '@floating-ui/core': 1.6.4 '@floating-ui/utils': 0.2.4 - '@floating-ui/dom@1.7.0': - dependencies: - '@floating-ui/core': 1.7.0 - '@floating-ui/utils': 0.2.9 - '@floating-ui/react-dom@2.1.1(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: '@floating-ui/dom': 1.6.7 react: 18.2.0 react-dom: 18.3.1(react@18.2.0) - '@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': + '@floating-ui/react-dom@2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/dom': 1.7.0 - react: 18.2.0 - react-dom: 18.3.1(react@18.2.0) - - '@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@floating-ui/dom': 1.7.0 + '@floating-ui/dom': 1.6.7 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) '@floating-ui/utils@0.2.4': {} - '@floating-ui/utils@0.2.9': {} - '@formatjs/intl-localematcher@0.5.10': dependencies: tslib: 2.6.3 @@ -10756,7 +10796,7 @@ snapshots: jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3))': + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -10770,7 +10810,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + jest-config: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -11217,6 +11257,8 @@ snapshots: '@parcel/logger': 2.12.0 '@parcel/utils': 2.12.0 lmdb: 2.8.5 + transitivePeerDependencies: + - '@swc/helpers' '@parcel/cache@2.9.2(@parcel/core@2.12.0)': dependencies: @@ -11311,7 +11353,7 @@ snapshots: '@parcel/workers': 2.12.0(@parcel/core@2.12.0) abortcontroller-polyfill: 1.7.8 base-x: 3.0.11 - browserslist: 4.24.5 + browserslist: 4.24.4 clone: 2.1.2 dotenv: 7.0.0 dotenv-expand: 5.1.0 @@ -11536,7 +11578,7 @@ snapshots: '@parcel/types': 2.12.0(@parcel/core@2.12.0) '@parcel/utils': 2.12.0 '@parcel/workers': 2.12.0(@parcel/core@2.12.0) - '@swc/core': 1.11.24 + '@swc/core': 1.11.21 semver: 7.7.1 transitivePeerDependencies: - '@swc/helpers' @@ -12083,11 +12125,11 @@ snapshots: '@radix-ui/primitive@1.0.0': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/primitive@1.0.1': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/primitive@1.1.0': {} @@ -12132,7 +12174,7 @@ snapshots: '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) react: 18.2.0 react-dom: 18.3.1(react@18.2.0) @@ -12140,20 +12182,20 @@ snapshots: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-arrow@1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-arrow@1.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) - react: 18.2.0 - react-dom: 18.3.1(react@18.2.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-arrow@1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-arrow@1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.3.1(react@18.2.0) optionalDependencies: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 @@ -12190,7 +12232,7 @@ snapshots: '@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0) '@radix-ui/react-context': 1.0.1(@types/react@18.2.12)(react@18.2.0) @@ -12239,7 +12281,7 @@ snapshots: '@radix-ui/react-collection@1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0) '@radix-ui/react-context': 1.0.1(@types/react@18.2.12)(react@18.2.0) '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) @@ -12288,12 +12330,12 @@ snapshots: '@radix-ui/react-compose-refs@1.0.0(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 '@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 optionalDependencies: '@types/react': 18.2.12 @@ -12322,20 +12364,14 @@ snapshots: optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-compose-refs@1.1.2(@types/react@18.2.12)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.2.12 - '@radix-ui/react-context@1.0.0(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 '@radix-ui/react-context@1.0.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 optionalDependencies: '@types/react': 18.2.12 @@ -12364,15 +12400,9 @@ snapshots: optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-context@1.1.2(@types/react@18.2.12)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.2.12 - '@radix-ui/react-dialog@1.0.0(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/primitive': 1.0.0 '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0) '@radix-ui/react-context': 1.0.0(react@18.2.0) @@ -12414,20 +12444,20 @@ snapshots: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-dialog@1.1.13(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dialog@1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-portal': 1.1.8(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.2(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.2.12)(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -12438,7 +12468,7 @@ snapshots: '@radix-ui/react-direction@1.0.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 optionalDependencies: '@types/react': 18.2.12 @@ -12463,7 +12493,7 @@ snapshots: '@radix-ui/react-dismissable-layer@1.0.0(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/primitive': 1.0.0 '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0) '@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1(react@18.2.0))(react@18.2.0) @@ -12474,7 +12504,7 @@ snapshots: '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0) '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) @@ -12512,19 +12542,6 @@ snapshots: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-dismissable-layer@1.1.9(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.2.12 - '@types/react-dom': 18.0.11 - '@radix-ui/react-dropdown-menu@2.1.14(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -12542,30 +12559,41 @@ snapshots: '@radix-ui/react-focus-guards@1.0.0(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 - '@radix-ui/react-focus-guards@1.1.2(@types/react@18.2.12)(react@18.2.0)': + '@radix-ui/react-focus-guards@1.1.1(@types/react@18.2.12)(react@18.3.1)': dependencies: - react: 18.2.0 + react: 18.3.1 optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-focus-guards@1.1.2(@types/react@18.2.12)(react@18.3.1)': + '@radix-ui/react-focus-guards@1.1.2(@types/react@18.2.12)(react@18.2.0)': dependencies: - react: 18.3.1 + react: 18.2.0 optionalDependencies: '@types/react': 18.2.12 '@radix-ui/react-focus-scope@1.0.0(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0) '@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1(react@18.2.0))(react@18.2.0) '@radix-ui/react-use-callback-ref': 1.0.0(react@18.2.0) react: 18.2.0 react-dom: 18.3.1(react@18.2.0) + '@radix-ui/react-focus-scope@1.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.2.12 + '@types/react-dom': 18.0.11 + '@radix-ui/react-focus-scope@1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.12)(react@18.2.0) @@ -12577,30 +12605,19 @@ snapshots: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-focus-scope@1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.2.12 - '@types/react-dom': 18.0.11 - '@radix-ui/react-icons@1.3.0(react@18.2.0)': dependencies: react: 18.2.0 '@radix-ui/react-id@1.0.0(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-use-layout-effect': 1.0.0(react@18.2.0) react: 18.2.0 '@radix-ui/react-id@1.0.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.12)(react@18.2.0) react: 18.2.0 optionalDependencies: @@ -12627,13 +12644,6 @@ snapshots: optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-id@1.1.1(@types/react@18.2.12)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.2.12 - '@radix-ui/react-menu@2.1.14(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -12705,21 +12715,21 @@ snapshots: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-popover@1.1.13(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-popover@1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-popper': 1.2.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.8(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.2(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.2.12)(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -12730,7 +12740,7 @@ snapshots: '@radix-ui/react-popper@1.1.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@floating-ui/react-dom': 2.1.1(react-dom@18.3.1(react@18.2.0))(react@18.2.0) '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0) @@ -12747,9 +12757,27 @@ snapshots: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 + '@radix-ui/react-popper@1.2.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/react-dom': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.0(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@18.2.12)(react@18.3.1) + '@radix-ui/rect': 1.1.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.2.12 + '@types/react-dom': 18.0.11 + '@radix-ui/react-popper@1.2.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.2.0))(react@18.2.0) + '@floating-ui/react-dom': 2.1.1(react-dom@18.3.1(react@18.2.0))(react@18.2.0) '@radix-ui/react-arrow': 1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.12)(react@18.2.0) '@radix-ui/react-context': 1.1.2(@types/react@18.2.12)(react@18.2.0) @@ -12765,34 +12793,16 @@ snapshots: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-popper@1.2.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-arrow': 1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-use-rect': 1.1.1(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/rect': 1.1.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.2.12 - '@types/react-dom': 18.0.11 - '@radix-ui/react-portal@1.0.0(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1(react@18.2.0))(react@18.2.0) react: 18.2.0 react-dom: 18.3.1(react@18.2.0) '@radix-ui/react-portal@1.0.4(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) react: 18.2.0 react-dom: 18.3.1(react@18.2.0) @@ -12800,29 +12810,29 @@ snapshots: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-portal@1.1.8(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-portal@1.1.4(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.2.0) - react: 18.2.0 - react-dom: 18.3.1(react@18.2.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-portal@1.1.8(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-portal@1.1.8(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.2.0) + react: 18.2.0 + react-dom: 18.3.1(react@18.2.0) optionalDependencies: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 '@radix-ui/react-presence@1.0.0(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0) '@radix-ui/react-use-layout-effect': 1.0.0(react@18.2.0) react: 18.2.0 @@ -12830,7 +12840,7 @@ snapshots: '@radix-ui/react-presence@1.0.1(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0) '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.12)(react@18.2.0) react: 18.2.0 @@ -12879,26 +12889,16 @@ snapshots: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-presence@1.1.4(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.2.12 - '@types/react-dom': 18.0.11 - '@radix-ui/react-primitive@1.0.0(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-slot': 1.0.0(react@18.2.0) react: 18.2.0 react-dom: 18.3.1(react@18.2.0) '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-slot': 1.0.2(@types/react@18.2.12)(react@18.2.0) react: 18.2.0 react-dom: 18.3.1(react@18.2.0) @@ -12942,15 +12942,6 @@ snapshots: '@types/react': 18.2.12 '@types/react-dom': 18.0.11 - '@radix-ui/react-primitive@2.1.2(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-slot': 1.2.2(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.2.12 - '@types/react-dom': 18.0.11 - '@radix-ui/react-radio-group@1.1.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.8 @@ -12972,7 +12963,7 @@ snapshots: '@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0) @@ -13116,7 +13107,7 @@ snapshots: '@radix-ui/react-slot@1.0.0(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0) react: 18.2.0 @@ -13156,13 +13147,6 @@ snapshots: optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-slot@1.2.2(@types/react@18.2.12)(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.2.12 - '@radix-ui/react-switch@1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.8 @@ -13230,7 +13214,7 @@ snapshots: '@radix-ui/react-toggle@1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.12)(react@18.2.0) @@ -13263,12 +13247,12 @@ snapshots: '@radix-ui/react-use-callback-ref@1.0.0(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 optionalDependencies: '@types/react': 18.2.12 @@ -13291,21 +13275,15 @@ snapshots: optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.2.12)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.2.12 - '@radix-ui/react-use-controllable-state@1.0.0(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-use-callback-ref': 1.0.0(react@18.2.0) react: 18.2.0 '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.12)(react@18.2.0) react: 18.2.0 optionalDependencies: @@ -13333,14 +13311,6 @@ snapshots: optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.2.12)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.2.12)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.2.12 - '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.2.12)(react@18.2.0)': dependencies: '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.2.0) @@ -13348,22 +13318,15 @@ snapshots: optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.2.12)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.2.12 - '@radix-ui/react-use-escape-keydown@1.0.0(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-use-callback-ref': 1.0.0(react@18.2.0) react: 18.2.0 '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.12)(react@18.2.0) react: 18.2.0 optionalDependencies: @@ -13383,21 +13346,14 @@ snapshots: optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.2.12)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.2.12 - '@radix-ui/react-use-layout-effect@1.0.0(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 optionalDependencies: '@types/react': 18.2.12 @@ -13420,15 +13376,9 @@ snapshots: optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.2.12)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.2.12 - '@radix-ui/react-use-previous@1.0.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 react: 18.2.0 optionalDependencies: '@types/react': 18.2.12 @@ -13453,29 +13403,29 @@ snapshots: '@radix-ui/react-use-rect@1.0.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/rect': 1.0.1 react: 18.2.0 optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-use-rect@1.1.1(@types/react@18.2.12)(react@18.2.0)': + '@radix-ui/react-use-rect@1.1.0(@types/react@18.2.12)(react@18.3.1)': dependencies: - '@radix-ui/rect': 1.1.1 - react: 18.2.0 + '@radix-ui/rect': 1.1.0 + react: 18.3.1 optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-use-rect@1.1.1(@types/react@18.2.12)(react@18.3.1)': + '@radix-ui/react-use-rect@1.1.1(@types/react@18.2.12)(react@18.2.0)': dependencies: '@radix-ui/rect': 1.1.1 - react: 18.3.1 + react: 18.2.0 optionalDependencies: '@types/react': 18.2.12 '@radix-ui/react-use-size@1.0.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.12)(react@18.2.0) react: 18.2.0 optionalDependencies: @@ -13488,23 +13438,23 @@ snapshots: optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-use-size@1.1.1(@types/react@18.2.12)(react@18.2.0)': + '@radix-ui/react-use-size@1.1.0(@types/react@18.2.12)(react@18.3.1)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.2.0) - react: 18.2.0 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.12)(react@18.3.1) + react: 18.3.1 optionalDependencies: '@types/react': 18.2.12 - '@radix-ui/react-use-size@1.1.1(@types/react@18.2.12)(react@18.3.1)': + '@radix-ui/react-use-size@1.1.1(@types/react@18.2.12)(react@18.2.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.3.1) - react: 18.3.1 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.2.12)(react@18.2.0) + react: 18.2.0 optionalDependencies: '@types/react': 18.2.12 '@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0)': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.2.0))(react@18.2.0) react: 18.2.0 react-dom: 18.3.1(react@18.2.0) @@ -13532,7 +13482,9 @@ snapshots: '@radix-ui/rect@1.0.1': dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 + + '@radix-ui/rect@1.1.0': {} '@radix-ui/rect@1.1.1': {} @@ -13565,14 +13517,14 @@ snapshots: optionalDependencies: rollup: 3.25.1 - '@rollup/plugin-typescript@11.1.1(rollup@3.25.1)(tslib@2.8.1)(typescript@5.4.3)': + '@rollup/plugin-typescript@11.1.1(rollup@3.25.1)(tslib@2.6.3)(typescript@5.4.3)': dependencies: '@rollup/pluginutils': 5.1.0(rollup@3.25.1) resolve: 1.22.8 typescript: 5.4.3 optionalDependencies: rollup: 3.25.1 - tslib: 2.8.1 + tslib: 2.6.3 '@rollup/pluginutils@5.1.0(rollup@3.25.1)': dependencies: @@ -13783,81 +13735,81 @@ snapshots: - supports-color - typescript - '@swc/core-darwin-arm64@1.11.24': + '@swc/core-darwin-arm64@1.11.21': optional: true '@swc/core-darwin-arm64@1.6.13': optional: true - '@swc/core-darwin-x64@1.11.24': + '@swc/core-darwin-x64@1.11.21': optional: true '@swc/core-darwin-x64@1.6.13': optional: true - '@swc/core-linux-arm-gnueabihf@1.11.24': + '@swc/core-linux-arm-gnueabihf@1.11.21': optional: true '@swc/core-linux-arm-gnueabihf@1.6.13': optional: true - '@swc/core-linux-arm64-gnu@1.11.24': + '@swc/core-linux-arm64-gnu@1.11.21': optional: true '@swc/core-linux-arm64-gnu@1.6.13': optional: true - '@swc/core-linux-arm64-musl@1.11.24': + '@swc/core-linux-arm64-musl@1.11.21': optional: true '@swc/core-linux-arm64-musl@1.6.13': optional: true - '@swc/core-linux-x64-gnu@1.11.24': + '@swc/core-linux-x64-gnu@1.11.21': optional: true '@swc/core-linux-x64-gnu@1.6.13': optional: true - '@swc/core-linux-x64-musl@1.11.24': + '@swc/core-linux-x64-musl@1.11.21': optional: true '@swc/core-linux-x64-musl@1.6.13': optional: true - '@swc/core-win32-arm64-msvc@1.11.24': + '@swc/core-win32-arm64-msvc@1.11.21': optional: true '@swc/core-win32-arm64-msvc@1.6.13': optional: true - '@swc/core-win32-ia32-msvc@1.11.24': + '@swc/core-win32-ia32-msvc@1.11.21': optional: true '@swc/core-win32-ia32-msvc@1.6.13': optional: true - '@swc/core-win32-x64-msvc@1.11.24': + '@swc/core-win32-x64-msvc@1.11.21': optional: true '@swc/core-win32-x64-msvc@1.6.13': optional: true - '@swc/core@1.11.24': + '@swc/core@1.11.21': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.21 optionalDependencies: - '@swc/core-darwin-arm64': 1.11.24 - '@swc/core-darwin-x64': 1.11.24 - '@swc/core-linux-arm-gnueabihf': 1.11.24 - '@swc/core-linux-arm64-gnu': 1.11.24 - '@swc/core-linux-arm64-musl': 1.11.24 - '@swc/core-linux-x64-gnu': 1.11.24 - '@swc/core-linux-x64-musl': 1.11.24 - '@swc/core-win32-arm64-msvc': 1.11.24 - '@swc/core-win32-ia32-msvc': 1.11.24 - '@swc/core-win32-x64-msvc': 1.11.24 + '@swc/core-darwin-arm64': 1.11.21 + '@swc/core-darwin-x64': 1.11.21 + '@swc/core-linux-arm-gnueabihf': 1.11.21 + '@swc/core-linux-arm64-gnu': 1.11.21 + '@swc/core-linux-arm64-musl': 1.11.21 + '@swc/core-linux-x64-gnu': 1.11.21 + '@swc/core-linux-x64-musl': 1.11.21 + '@swc/core-win32-arm64-msvc': 1.11.21 + '@swc/core-win32-ia32-msvc': 1.11.21 + '@swc/core-win32-x64-msvc': 1.11.21 '@swc/core@1.6.13(@swc/helpers@0.5.12)': dependencies: @@ -13880,7 +13832,7 @@ snapshots: '@swc/helpers@0.5.12': dependencies: - tslib: 2.8.1 + tslib: 2.6.3 '@swc/helpers@0.5.5': dependencies: @@ -13917,8 +13869,8 @@ snapshots: '@testing-library/dom@10.4.0': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/runtime': 7.27.1 + '@babel/code-frame': 7.26.2 + '@babel/runtime': 7.27.0 '@types/aria-query': 5.0.4 aria-query: 5.3.0 chalk: 4.1.2 @@ -13970,7 +13922,7 @@ snapshots: '@tsconfig/node16@1.0.4': {} - '@turbo/gen@1.9.7(@swc/core@1.11.24)(@types/node@22.13.4)(typescript@4.7.2)': + '@turbo/gen@1.9.7(@swc/core@1.11.21)(@types/node@22.13.4)(typescript@4.7.2)': dependencies: chalk: 2.4.2 commander: 10.0.1 @@ -13979,7 +13931,7 @@ snapshots: minimatch: 9.0.5 node-plop: 0.26.3 semver: 7.6.2 - ts-node: 10.9.2(@swc/core@1.11.24)(@types/node@22.13.4)(typescript@4.7.2) + ts-node: 10.9.2(@swc/core@1.11.21)(@types/node@22.13.4)(typescript@4.7.2) update-check: 1.5.4 validate-npm-package-name: 5.0.1 transitivePeerDependencies: @@ -14103,7 +14055,7 @@ snapshots: '@types/prettier@3.0.0': dependencies: - prettier: 2.5.1 + prettier: 2.8.8 '@types/prismjs@1.26.4': {} @@ -14398,7 +14350,7 @@ snapshots: aria-hidden@1.2.4: dependencies: - tslib: 2.8.1 + tslib: 2.6.3 aria-query@5.1.3: dependencies: @@ -14495,7 +14447,7 @@ snapshots: ast-types@0.13.4: dependencies: - tslib: 2.8.1 + tslib: 2.6.3 astral-regex@2.0.0: {} @@ -14551,7 +14503,7 @@ snapshots: babel-plugin-macros@3.1.0: dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 cosmiconfig: 7.1.0 resolve: 1.22.8 @@ -14680,13 +14632,6 @@ snapshots: node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.4) - browserslist@4.24.5: - dependencies: - caniuse-lite: 1.0.30001717 - electron-to-chromium: 1.5.150 - node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.24.5) - bs-logger@0.2.6: dependencies: fast-json-stable-stringify: 2.1.0 @@ -14777,8 +14722,6 @@ snapshots: caniuse-lite@1.0.30001701: {} - caniuse-lite@1.0.30001717: {} - ccount@2.0.1: {} chalk@1.1.3: @@ -15036,13 +14979,13 @@ snapshots: optionalDependencies: typescript: 5.4.3 - create-jest@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)): + create-jest@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + jest-config: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -15327,10 +15270,7 @@ snapshots: detect-libc@1.0.3: {} - detect-libc@2.0.3: - optional: true - - detect-libc@2.0.4: {} + detect-libc@2.0.3: {} detect-newline@3.1.0: {} @@ -15362,7 +15302,7 @@ snapshots: dom-helpers@5.2.1: dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 csstype: 3.1.3 dom-serializer@1.4.1: @@ -15410,7 +15350,7 @@ snapshots: dot-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.8.1 + tslib: 2.6.3 dot-prop@6.0.1: dependencies: @@ -15434,8 +15374,6 @@ snapshots: electron-to-chromium@1.5.109: {} - electron-to-chromium@1.5.150: {} - elegant-spinner@1.0.1: {} emittery@0.13.1: {} @@ -16261,10 +16199,10 @@ snapshots: dependencies: '@radix-ui/react-accordion': 1.2.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-collapsible': 1.1.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-dialog': 1.1.13(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dialog': 1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-direction': 1.1.0(@types/react@18.2.12)(react@18.3.1) '@radix-ui/react-navigation-menu': 1.2.5(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-popover': 1.1.13(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-popover': 1.1.6(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-scroll-area': 1.2.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.1.2(@types/react@18.2.12)(react@18.3.1) '@radix-ui/react-tabs': 1.1.3(@types/react-dom@18.0.11)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17221,16 +17159,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)): + jest-cli@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + create-jest: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + jest-config: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -17240,7 +17178,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)): + jest-config@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)): dependencies: '@babel/core': 7.26.0 '@jest/test-sequencer': 29.7.0 @@ -17266,7 +17204,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 18.19.39 - ts-node: 10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3) + ts-node: 10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -17501,12 +17439,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)): + jest@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + jest-cli: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -17815,7 +17753,7 @@ snapshots: lower-case@2.0.2: dependencies: - tslib: 2.8.1 + tslib: 2.6.3 lowercase-keys@2.0.0: {} @@ -18449,7 +18387,7 @@ snapshots: no-case@3.0.4: dependencies: lower-case: 2.0.2 - tslib: 2.8.1 + tslib: 2.6.3 node-addon-api@4.3.0: {} @@ -18473,7 +18411,7 @@ snapshots: node-gyp-build-optional-packages@5.1.1: dependencies: - detect-libc: 2.0.4 + detect-libc: 2.0.3 node-gyp-build-optional-packages@5.2.2: dependencies: @@ -18991,13 +18929,13 @@ snapshots: read-cache: 1.0.0 resolve: 1.22.8 - postcss-load-config@3.1.4(postcss@8.4.24)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)): + postcss-load-config@3.1.4(postcss@8.4.24)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: postcss: 8.4.24 - ts-node: 10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3) + ts-node: 10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3) postcss-merge-longhand@5.1.7(postcss@8.4.24): dependencies: @@ -19201,6 +19139,8 @@ snapshots: prettier@2.5.1: {} + prettier@2.8.8: {} + pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1 @@ -19350,7 +19290,7 @@ snapshots: dependencies: react: 18.2.0 react-style-singleton: 2.2.1(@types/react@18.2.12)(react@18.2.0) - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 @@ -19358,7 +19298,7 @@ snapshots: dependencies: react: 18.2.0 react-style-singleton: 2.2.3(@types/react@18.2.12)(react@18.2.0) - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 @@ -19366,7 +19306,7 @@ snapshots: dependencies: react: 18.3.1 react-style-singleton: 2.2.3(@types/react@18.2.12)(react@18.3.1) - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 @@ -19386,7 +19326,7 @@ snapshots: react: 18.2.0 react-remove-scroll-bar: 2.3.8(@types/react@18.2.12)(react@18.2.0) react-style-singleton: 2.2.3(@types/react@18.2.12)(react@18.2.0) - tslib: 2.8.1 + tslib: 2.6.3 use-callback-ref: 1.3.3(@types/react@18.2.12)(react@18.2.0) use-sidecar: 1.1.3(@types/react@18.2.12)(react@18.2.0) optionalDependencies: @@ -19397,7 +19337,7 @@ snapshots: react: 18.3.1 react-remove-scroll-bar: 2.3.8(@types/react@18.2.12)(react@18.3.1) react-style-singleton: 2.2.3(@types/react@18.2.12)(react@18.3.1) - tslib: 2.8.1 + tslib: 2.6.3 use-callback-ref: 1.3.3(@types/react@18.2.12)(react@18.3.1) use-sidecar: 1.1.3(@types/react@18.2.12)(react@18.3.1) optionalDependencies: @@ -19425,7 +19365,7 @@ snapshots: get-nonce: 1.0.1 invariant: 2.2.4 react: 18.2.0 - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 @@ -19433,7 +19373,7 @@ snapshots: dependencies: get-nonce: 1.0.1 react: 18.2.0 - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 @@ -19441,13 +19381,13 @@ snapshots: dependencies: get-nonce: 1.0.1 react: 18.3.1 - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 react-transition-group@4.4.5(react-dom@18.3.1(react@18.2.0))(react@18.2.0): dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.26.9 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -19769,7 +19709,7 @@ snapshots: dependencies: glob: 7.2.3 - rollup-plugin-postcss@4.0.2(postcss@8.4.24)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)): + rollup-plugin-postcss@4.0.2(postcss@8.4.24)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)): dependencies: chalk: 4.1.2 concat-with-sourcemaps: 1.1.0 @@ -19778,7 +19718,7 @@ snapshots: p-queue: 6.6.2 pify: 5.0.0 postcss: 8.4.24 - postcss-load-config: 3.1.4(postcss@8.4.24)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + postcss-load-config: 3.1.4(postcss@8.4.24)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) postcss-modules: 4.3.1(postcss@8.4.24) promise.series: 0.2.0 resolve: 1.22.8 @@ -20352,12 +20292,12 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)))(typescript@5.4.3): + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)))(typescript@5.4.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3)) + jest: 29.7.0(@types/node@18.19.39)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -20376,7 +20316,7 @@ snapshots: '@ts-morph/common': 0.26.1 code-block-writer: 13.0.3 - ts-node@10.9.2(@swc/core@1.11.24)(@types/node@18.19.39)(typescript@5.4.3): + ts-node@10.9.2(@swc/core@1.11.21)(@types/node@18.19.39)(typescript@5.4.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -20394,10 +20334,10 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.11.24 + '@swc/core': 1.11.21 optional: true - ts-node@10.9.2(@swc/core@1.11.24)(@types/node@22.13.4)(typescript@4.7.2): + ts-node@10.9.2(@swc/core@1.11.21)(@types/node@22.13.4)(typescript@4.7.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -20415,7 +20355,7 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.11.24 + '@swc/core': 1.11.21 tsconfig-paths@3.15.0: dependencies: @@ -20428,8 +20368,6 @@ snapshots: tslib@2.6.3: {} - tslib@2.8.1: {} - tsutils@3.21.0(typescript@5.7.3): dependencies: tslib: 1.14.1 @@ -20621,12 +20559,6 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - update-browserslist-db@1.1.3(browserslist@4.24.5): - dependencies: - browserslist: 4.24.5 - escalade: 3.2.0 - picocolors: 1.1.1 - update-check@1.5.4: dependencies: registry-auth-token: 3.3.2 @@ -20669,21 +20601,21 @@ snapshots: use-callback-ref@1.3.2(@types/react@18.2.12)(react@18.2.0): dependencies: react: 18.2.0 - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 use-callback-ref@1.3.3(@types/react@18.2.12)(react@18.2.0): dependencies: react: 18.2.0 - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 use-callback-ref@1.3.3(@types/react@18.2.12)(react@18.3.1): dependencies: react: 18.3.1 - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 @@ -20701,7 +20633,7 @@ snapshots: dependencies: detect-node-es: 1.1.0 react: 18.2.0 - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 @@ -20709,7 +20641,7 @@ snapshots: dependencies: detect-node-es: 1.1.0 react: 18.2.0 - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 @@ -20717,7 +20649,7 @@ snapshots: dependencies: detect-node-es: 1.1.0 react: 18.3.1 - tslib: 2.8.1 + tslib: 2.6.3 optionalDependencies: '@types/react': 18.2.12 From 3e771fe9be2caad57a0d113d0947db45bf06ebe0 Mon Sep 17 00:00:00 2001 From: Rishabh Mishra Date: Tue, 13 May 2025 14:38:44 +0530 Subject: [PATCH 02/14] fix: ci breaking as checkout position incorrect (#391) (#400) * fix: ci breaking as checkout position incorrect (#391) * fix: update version in package.json (#394) * fix: update version in package.json * fix: add ref --------- Co-authored-by: Gaurav Singh --- .github/workflows/release.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 75fac61b6..8859aa2e1 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -12,6 +12,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: + - name: Checkout 🛎️ + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.ref }} + - name: Check Branch and Tag run: | BRANCH=$(git branch -r --contains ${{ github.ref }}) @@ -32,11 +38,6 @@ jobs: exit 1 fi - - name: Checkout 🛎️ - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Setup pnpm 9 uses: pnpm/action-setup@v4 with: From 9634c3f62ccca72de4d436b783ec479c5367fa36 Mon Sep 17 00:00:00 2001 From: Rishabh Mishra Date: Tue, 13 May 2025 15:12:29 +0530 Subject: [PATCH 03/14] ci: create release file for rc tags (#401) --- .github/workflows/release-rc.yaml | 57 +++++++++++++++++++++++++++++++ .github/workflows/release.yaml | 25 ++------------ 2 files changed, 59 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/release-rc.yaml diff --git a/.github/workflows/release-rc.yaml b/.github/workflows/release-rc.yaml new file mode 100644 index 000000000..ba291c851 --- /dev/null +++ b/.github/workflows/release-rc.yaml @@ -0,0 +1,57 @@ +name: Release to NPM when a tag is pushed + +on: + push: + tags: + - "v*.*.*-rc.*" + +jobs: + release: + name: Release + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: develop + + - name: Setup pnpm 9 + uses: pnpm/action-setup@v4 + with: + version: 9.3.0 + + - name: Setup Node.js 18.x + uses: actions/setup-node@v2 + with: + node-version: 18.x + + - name: Install Dependencies 🔧 + run: pnpm install + + - name: Build Step 🔧 + env: + CI: "" + run: pnpm run ci:build + + - name: Create .npmrc + run: | + cat << EOF > "$HOME/.npmrc" + //registry.npmjs.org/:_authToken=$NPM_TOKEN + EOF + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Bump Package Version + run: pnpm run bump-version + working-directory: ./packages/raystack + env: + GIT_REFNAME: ${{ github.ref_name }} + + - name: Run Release 🚀 + run: pnpm run release:ci + working-directory: ./packages/raystack + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8859aa2e1..c84d002d4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -3,8 +3,7 @@ name: Release to NPM when a tag is pushed on: push: tags: - - 'v*.*.*' - - 'v*.*.*-rc.*' + - "v*.*.*" jobs: release: @@ -16,27 +15,7 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 0 - ref: ${{ github.ref }} - - - name: Check Branch and Tag - run: | - BRANCH=$(git branch -r --contains ${{ github.ref }}) - TAG=${{ github.ref_name }} - - if [[ $BRANCH =~ origin/main$ ]]; then - if [[ $TAG =~ -rc\. ]]; then - echo "[SKIPPED] Release candidate tags (v*.*.*-rc.*) are only allowed on develop branch" - exit 0 - fi - elif [[ $BRANCH =~ origin/develop$ ]]; then - if [[ ! $TAG =~ -rc\. ]]; then - echo "[SKIPPED] Release tags (v*.*.*) are only allowed on main branch. Use release candidate tags (v*.*.*-rc.*)" - exit 1 - fi - else - echo "[SKIPPED] Tags can only be pushed from main or develop branches" - exit 1 - fi + ref: main - name: Setup pnpm 9 uses: pnpm/action-setup@v4 From 73525c91578df82612e8e6e75c250a2a44fd3462 Mon Sep 17 00:00:00 2001 From: Rishabh Mishra Date: Tue, 13 May 2025 15:27:15 +0530 Subject: [PATCH 04/14] fix: update tag regex in github action (#403) --- .github/workflows/release-rc.yaml | 4 ++-- .github/workflows/release.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-rc.yaml b/.github/workflows/release-rc.yaml index ba291c851..1a4b612c7 100644 --- a/.github/workflows/release-rc.yaml +++ b/.github/workflows/release-rc.yaml @@ -1,9 +1,9 @@ -name: Release to NPM when a tag is pushed +name: Publishing Release Candidate on: push: tags: - - "v*.*.*-rc.*" + - "v[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+" jobs: release: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c84d002d4..01dc2fb19 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -3,7 +3,7 @@ name: Release to NPM when a tag is pushed on: push: tags: - - "v*.*.*" + - "v[0-9]+.[0-9]+.[0-9]+" jobs: release: From e76bdc1bd43b03a139829670c26a55ae3999acc1 Mon Sep 17 00:00:00 2001 From: Rishabh Mishra Date: Wed, 14 May 2025 11:44:15 +0530 Subject: [PATCH 05/14] ci: add npm dist tags to the package (#405) --- .github/workflows/release-rc.yaml | 2 +- .github/workflows/release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-rc.yaml b/.github/workflows/release-rc.yaml index 1a4b612c7..6c622b42a 100644 --- a/.github/workflows/release-rc.yaml +++ b/.github/workflows/release-rc.yaml @@ -50,7 +50,7 @@ jobs: GIT_REFNAME: ${{ github.ref_name }} - name: Run Release 🚀 - run: pnpm run release:ci + run: pnpm run release:ci --npm.tag=next working-directory: ./packages/raystack env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 01dc2fb19..9a660599f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -50,7 +50,7 @@ jobs: GIT_REFNAME: ${{ github.ref_name }} - name: Run Release 🚀 - run: pnpm run release:ci + run: pnpm run release:ci --npm.tag=latest working-directory: ./packages/raystack env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 9fc22f89c784d77a5eb6fa57aa6f48c170502490 Mon Sep 17 00:00:00 2001 From: Rohan Chakraborty Date: Tue, 20 May 2025 08:41:52 +0530 Subject: [PATCH 06/14] feat: add `autocomplete` support for Select (#395) * feat: autocomplete functionality in select * feat: select autocomplete qol changes * feat: update select docs * feat: update select doc tag * feat: add support for htmlAutocomplete --- apps/www/src/app/examples/page.tsx | 429 +++++++++++------- .../content/docs/components/select/demo.ts | 61 ++- .../content/docs/components/select/index.mdx | 16 + .../content/docs/components/select/props.ts | 26 ++ .../v1/components/select/select-content.tsx | 74 ++- .../v1/components/select/select-item.tsx | 73 ++- .../v1/components/select/select-root.tsx | 101 ++++- .../v1/components/select/select-trigger.tsx | 21 +- .../v1/components/select/select.module.css | 58 ++- 9 files changed, 633 insertions(+), 226 deletions(-) diff --git a/apps/www/src/app/examples/page.tsx b/apps/www/src/app/examples/page.tsx index 5b020f657..679a6ad17 100644 --- a/apps/www/src/app/examples/page.tsx +++ b/apps/www/src/app/examples/page.tsx @@ -52,6 +52,12 @@ const Page = () => { { value: "analytics", label: "Analytics", icon: }, { value: "settings", label: "Settings", icon: }, { value: "profile", label: "Profile", icon: }, + { value: "reports", label: "Reports", icon: }, + { value: "activities", label: "Activities", icon: }, + { value: "help", label: "Help", icon: }, + { value: "preferences", label: "Preferences", icon: }, + { value: "notifications", label: "Notifications", icon: }, + { value: "logout", label: "Logout", icon: }, ]; const filterOptions = [ @@ -161,82 +167,88 @@ const Page = () => { onClear={() => setSearch1("")} /> console.log(value)} calendarProps={{ - captionLayout: 'dropdown', - startMonth: dayjs().add(3, 'month').toDate(), - endMonth: dayjs().add(4, 'year').toDate(), - disabled: { before: dayjs().add(3, 'month').toDate(), after: dayjs().add(3, 'year').toDate() }, - mode: 'single', + captionLayout: "dropdown", + startMonth: dayjs().add(3, "month").toDate(), + endMonth: dayjs().add(4, "year").toDate(), + disabled: { + before: dayjs().add(3, "month").toDate(), + after: dayjs().add(3, "year").toDate(), + }, + mode: "single", required: true, - selected: new Date() + selected: new Date(), }} textFieldProps={{ state: "valid", - size: 'medium', + size: "medium", }} /> - console.log(range)} + onSelect={range => console.log(range)} calendarProps={{ - captionLayout: 'dropdown', - mode: 'range', + captionLayout: "dropdown", + mode: "range", required: true, selected: { - from: dayjs('2027-11-15').toDate(), - to: dayjs('2027-12-10').toDate() + from: dayjs("2027-11-15").toDate(), + to: dayjs("2027-12-10").toDate(), }, numberOfMonths: 2, fromYear: 2024, toYear: 2027, - startMonth: dayjs('2024-01-01').toDate(), - endMonth: dayjs('2027-12-01').toDate(), - defaultMonth: dayjs('2027-11-01').toDate() + startMonth: dayjs("2024-01-01").toDate(), + endMonth: dayjs("2027-12-01").toDate(), + defaultMonth: dayjs("2027-11-01").toDate(), }} inputFieldsProps={{ startDate: { - size: 'small' + size: "small", }, endDate: { - size: 'small' - } + size: "small", + }, }} /> - Some important message in the footer} /> + + Some important message in the footer + + } + /> { + onSelect={date => { console.log(date); - }} - > + }}> - { icon={} heading="KYC required for image orders" subHeading="Please contact your organization owner to complete the KYC process for the image orders. You can also contact support@raystack.io for assistance." - primaryAction={} + primaryAction={ + + } variant="empty1" /> @@ -579,34 +595,23 @@ const Page = () => { This is the dialog content. - + Team Members: - - - - + + + + Quick Actions: - + @@ -614,10 +619,15 @@ const Page = () => { - + Team Role: - @@ -639,13 +649,26 @@ const Page = () => { - - Filter Team Members - You can filter team members by: + + + Filter Team Members + + + You can filter team members by: +
    -
  • Name
  • -
  • Role
  • -
  • Department
  • +
  • + Name +
  • +
  • + Role +
  • +
  • + Department +
@@ -660,16 +683,18 @@ const Page = () => { Actions: - - - - - + + - @@ -677,8 +702,12 @@ const Page = () => { - Team Actions - + + Team Actions + + Add Member Edit Team @@ -686,10 +715,14 @@ const Page = () => { Settings Permissions - Notifications + + Notifications + - Delete Team + + Delete Team + @@ -700,7 +733,7 @@ const Page = () => { label="Example Text Area" placeholder="Type something..." value={inputValue} - onChange={(e) => setInputValue(e.target.value)} + onChange={e => setInputValue(e.target.value)} />
@@ -719,31 +752,17 @@ const Page = () => { Team Members: - - - - + + + + Quick Actions: - + @@ -776,13 +795,26 @@ const Page = () => { - - Filter Team Members - You can filter team members by: + + + Filter Team Members + + + You can filter team members by: +
    -
  • Name
  • -
  • Role
  • -
  • Department
  • +
  • + Name +
  • +
  • + Role +
  • +
  • + Department +
@@ -799,9 +831,7 @@ const Page = () => { Actions: - + @@ -809,7 +839,9 @@ const Page = () => { Team Actions - + Add Member Edit Team @@ -820,7 +852,9 @@ const Page = () => { Notifications - Delete Team + + Delete Team + @@ -831,7 +865,7 @@ const Page = () => { label="Example Text Area" placeholder="Type something..." value={inputValue} - onChange={(e) => setInputValue(e.target.value)} + onChange={e => setInputValue(e.target.value)} /> @@ -840,34 +874,23 @@ const Page = () => { This is the nested dialog content. - + Team Members: - - - - + + + + Quick Actions: - + @@ -875,10 +898,15 @@ const Page = () => { - + Team Role: - @@ -900,13 +928,26 @@ const Page = () => { - - Filter Team Members - You can filter team members by: + + + Filter Team Members + + + You can filter team members by: +
    -
  • Name
  • -
  • Role
  • -
  • Department
  • +
  • + Name +
  • +
  • + Role +
  • +
  • + Department +
@@ -922,18 +963,20 @@ const Page = () => { Actions: - - - + + + - Team Actions - + + Team Actions + + Add Member Edit Team @@ -941,10 +984,14 @@ const Page = () => { Settings Permissions - Notifications + + Notifications + - Delete Team + + Delete Team + @@ -1056,26 +1103,70 @@ const Page = () => { - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + + + + + diff --git a/apps/www/src/content/docs/components/select/demo.ts b/apps/www/src/content/docs/components/select/demo.ts index 1bd6e1144..a06b030f0 100644 --- a/apps/www/src/content/docs/components/select/demo.ts +++ b/apps/www/src/content/docs/components/select/demo.ts @@ -3,9 +3,10 @@ import { getPropsString } from "@/lib/utils"; export const getCode = (props: any) => { + const { autocomplete, ...rest } = props; return ` - `, }; + +export const autocompleteDemo = { + type: "code", + tabs: [ + { + name: "Default Autocomplete", + code: ` + `, + }, + { + name: "Manual Autocomplete", + code: ` + function ManualDemo(){ + const items = [ + "Apple", + "Banana", + "Grape", + "Orange", + "Pineapple", + ]; + + const [simpleSearchQuery, setSimpleSearchQuery] = React.useState(""); + return + }`, + }, + ], +}; diff --git a/apps/www/src/content/docs/components/select/index.mdx b/apps/www/src/content/docs/components/select/index.mdx index 721e5bf1c..cc73c50ca 100644 --- a/apps/www/src/content/docs/components/select/index.mdx +++ b/apps/www/src/content/docs/components/select/index.mdx @@ -1,6 +1,7 @@ --- title: Select description: Displays a list of options for the user to pick from—triggered by a button. +tag: update --- import { @@ -10,6 +11,7 @@ import { variantDemo, separatorDemo, iconDemo, + autocompleteDemo, } from "./demo.ts"; @@ -34,6 +36,12 @@ import { Select } from "@raystack/apsara/v1"; ## Select Props +The Select component is composed of several parts, each with their own props. + +The root element is the parent component that holds the select. Using the `autocomplete` prop, you can enable autocomplete functionality. Autcomplet is built using [Ariakit ComboboxProvider](https://ariakit.org/reference/combobox-provider) + + + ### Select.Trigger Props @@ -70,6 +78,14 @@ You can pass `leadingIcon` prop to Select.Item to include items +### Autocomplete + +To enable autocomplete, pass the `autocomplete` prop to the Select root element. + +By default, only select items are filtered using a simple match. For more advanced control, set `autocompleteMode="manual"` and implement your own custom filtering logic. + + + ## Accessibility The Select component follows WAI-ARIA guidelines: diff --git a/apps/www/src/content/docs/components/select/props.ts b/apps/www/src/content/docs/components/select/props.ts index 9293661dc..36e6e3591 100644 --- a/apps/www/src/content/docs/components/select/props.ts +++ b/apps/www/src/content/docs/components/select/props.ts @@ -1,3 +1,24 @@ +export interface SelectRootProps { + /** Enables search functionality within the select */ + autocomplete?: boolean; + + /** Controls the autocomplete behavior mode + * - "auto": Automatically filters items as user types + * - "manual": Requires explicit filtering through onSearch callback + * @default "auto" + */ + autocompleteMode?: "auto" | "manual"; + + /** Current search value for autocomplete */ + searchValue?: string; + + /** Initial search value for autocomplete */ + defaultSearchValue?: string; + + /** Callback fired when the search value changes */ + onSearch?: (value: string) => void; +} + export interface SelectTriggerProps { /** Defines the size of the trigger. */ size?: "small" | "medium"; @@ -22,6 +43,11 @@ export interface SelectTriggerProps { } export interface SelectContentProps { + /** Placeholder text for the autocomplete search input + * @default "Search..." + */ + searchPlaceholder?: string; + /** * Position of the content * @default "popper" diff --git a/packages/raystack/v1/components/select/select-content.tsx b/packages/raystack/v1/components/select/select-content.tsx index bc5acc459..4931454ca 100644 --- a/packages/raystack/v1/components/select/select-content.tsx +++ b/packages/raystack/v1/components/select/select-content.tsx @@ -1,23 +1,65 @@ -import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"; +import { ElementRef, forwardRef } from "react"; import * as SelectPrimitive from "@radix-ui/react-select"; +import { Combobox, ComboboxList } from "@ariakit/react"; import { cx } from "class-variance-authority"; import styles from "./select.module.css"; +import { useSelectContext } from "./select-root"; + +export interface SelectContentProps extends SelectPrimitive.SelectContentProps { + searchPlaceholder?: string; +} export const SelectContent = forwardRef< ElementRef, - ComponentPropsWithoutRef ->(({ className, children, position = "popper", ...props }, ref) => ( - - { - e.stopPropagation(); - }} - {...props}> - {children} - - -)); + SelectContentProps +>( + ( + { + className, + children, + position = "popper", + searchPlaceholder = "Search...", + ...props + }, + ref, + ) => { + const { autocomplete } = useSelectContext(); + + return ( + + + + {autocomplete ? ( + <> + { + event.preventDefault(); + event.stopPropagation(); + }} + /> + + {children} + + + ) : ( + children + )} + + + + ); + }, +); SelectContent.displayName = SelectPrimitive.Content.displayName; diff --git a/packages/raystack/v1/components/select/select-item.tsx b/packages/raystack/v1/components/select/select-item.tsx index 12ca6b08c..6141206d4 100644 --- a/packages/raystack/v1/components/select/select-item.tsx +++ b/packages/raystack/v1/components/select/select-item.tsx @@ -1,27 +1,39 @@ -import { - ComponentPropsWithoutRef, - ElementRef, - forwardRef, - useEffect, -} from "react"; +import { ElementRef, forwardRef, useEffect } from "react"; import * as SelectPrimitive from "@radix-ui/react-select"; +import { ComboboxItem } from "@ariakit/react"; import { cx } from "class-variance-authority"; import styles from "./select.module.css"; import { Text, TextProps } from "../text"; import { useSelectContext } from "./select-root"; +import { getMatch } from "../dropdown-menu/utils"; export const SelectItem = forwardRef< ElementRef, - ComponentPropsWithoutRef & { + Omit & { textProps?: TextProps; leadingIcon?: React.ReactNode; } >( ( - { className, textProps = {}, children, value, leadingIcon, ...props }, + { + className, + textProps = {}, + children, + value, + leadingIcon, + disabled, + ...props + }, ref, ) => { - const { registerIcon, unregisterIcon } = useSelectContext(); + const { + registerIcon, + unregisterIcon, + autocomplete, + autocompleteMode, + searchValue, + value: selectValue, + } = useSelectContext(); useEffect(() => { if (!leadingIcon) return; @@ -32,16 +44,49 @@ export const SelectItem = forwardRef< }; }, [value, leadingIcon]); + const shouldFilter = !!( + autocomplete && + autocompleteMode === "auto" && + searchValue?.length + ); + + const isSelected = value === selectValue.value; + const isMatched = getMatch(value, children, searchValue); + const isHidden = shouldFilter && isSelected && !isMatched; + + if (shouldFilter && !isMatched && !isSelected) { + // Not selected and doesn't match search, so don't render at all + return null; + } + + const element = ( + <> + {leadingIcon &&
{leadingIcon}
} + + {children} + + + ); + return ( - {leadingIcon &&
{leadingIcon}
} - - {children} - + {autocomplete ? ( + { + event.preventDefault(); + }}> + {element} + + ) : ( + element + )}
); }, diff --git a/packages/raystack/v1/components/select/select-root.tsx b/packages/raystack/v1/components/select/select-root.tsx index 513736781..447b2410a 100644 --- a/packages/raystack/v1/components/select/select-root.tsx +++ b/packages/raystack/v1/components/select/select-root.tsx @@ -6,7 +6,7 @@ import { useRef, useState, } from "react"; - +import { ComboboxProvider } from "@ariakit/react"; import * as SelectPrimitive from "@radix-ui/react-select"; type IconType = Record; @@ -14,11 +14,20 @@ type ValueType = { value?: string; icon?: ReactNode; }; -type SelectContextValue = { + +interface CommonProps { + autocomplete?: boolean; + autocompleteMode?: "auto" | "manual"; + searchValue?: string; + onSearch?: (value: string) => void; + defaultSearchValue?: string; +} + +interface SelectContextValue extends CommonProps { value: ValueType; registerIcon: (value: string, icon: ReactNode) => void; unregisterIcon: (value: string) => void; -}; +} /* Root context to manage the Select control @@ -34,25 +43,80 @@ export const useSelectContext = () => { return context; }; +export interface NormalSelectRootProps extends SelectPrimitive.SelectProps { + autocomplete?: false; + autocompleteMode?: never; + searchValue?: never; + onSearch?: never; + defaultSearchValue?: never; +} + +export interface AutocompleteSelectRootProps + extends SelectPrimitive.SelectProps, + CommonProps { + autocomplete: true; +} + +export type BaseSelectRootProps = + | NormalSelectRootProps + | AutocompleteSelectRootProps; + +export type SelectRootProps = Omit & { + htmlAutoComplete?: string; +}; + export const SelectRoot = ({ children, value, onValueChange, defaultValue, + autocomplete, + autocompleteMode = "auto", + searchValue: providedSearchValue, + onSearch, + defaultSearchValue = "", + open: controlledOpen, + defaultOpen = false, + onOpenChange, + htmlAutoComplete, ...props -}: SelectPrimitive.SelectProps) => { +}: SelectRootProps) => { const [internalValue, setInternalValue] = useState( defaultValue, ); + const [internalSearchValue, setInternalSearchValue] = + useState(defaultSearchValue); + const [internalOpen, setInternalOpen] = useState(defaultOpen); const icons = useRef({}); const computedValue = value ?? internalValue; const icon = computedValue && icons.current?.[computedValue]; + const searchValue = providedSearchValue ?? internalSearchValue; + const open = controlledOpen ?? internalOpen; - const setValue = (_value: string) => { - onValueChange?.(_value); - setInternalValue(_value); - }; + const setValue = useCallback( + (_value: string) => { + onValueChange?.(_value); + setInternalValue(_value); + }, + [onValueChange], + ); + + const setSearchValue = useCallback( + (value: string) => { + setInternalSearchValue(value); + onSearch?.(value); + }, + [onSearch], + ); + + const handleOpenChange = useCallback( + (value: boolean) => { + setInternalOpen(value); + onOpenChange?.(value); + }, + [onOpenChange], + ); const registerIcon = useCallback( (value, icon) => { @@ -68,18 +132,37 @@ export const SelectRoot = ({ [], ); + const element = ( + + {children} + + ); + return ( - {children} + {autocomplete ? element : children} ); diff --git a/packages/raystack/v1/components/select/select-trigger.tsx b/packages/raystack/v1/components/select/select-trigger.tsx index 6322163ce..294a39e73 100644 --- a/packages/raystack/v1/components/select/select-trigger.tsx +++ b/packages/raystack/v1/components/select/select-trigger.tsx @@ -1,9 +1,4 @@ -import { - ComponentPropsWithoutRef, - ElementRef, - forwardRef, - PropsWithChildren, -} from "react"; +import { ElementRef, forwardRef, SVGAttributes } from "react"; import { ChevronDownIcon } from "@radix-ui/react-icons"; import * as SelectPrimitive from "@radix-ui/react-select"; import { cva, VariantProps } from "class-variance-authority"; @@ -22,7 +17,7 @@ export interface TriggerStyleProps { stopPropagation?: boolean; } -export interface IconProps extends React.SVGAttributes { +export interface IconProps extends SVGAttributes { children?: never; color?: string; } @@ -44,13 +39,15 @@ const trigger = cva(styles.trigger, { }, }); +type SelectTriggerProps = SelectPrimitive.SelectTriggerProps & + VariantProps & { + iconProps?: IconProps; + } & AriaProps & + TriggerStyleProps; + export const SelectTrigger = forwardRef< ElementRef, - ComponentPropsWithoutRef & - PropsWithChildren> & { - iconProps?: IconProps; - } & AriaProps & - TriggerStyleProps + SelectTriggerProps >( ( { diff --git a/packages/raystack/v1/components/select/select.module.css b/packages/raystack/v1/components/select/select.module.css index 915241d86..4ce392741 100644 --- a/packages/raystack/v1/components/select/select.module.css +++ b/packages/raystack/v1/components/select/select.module.css @@ -27,16 +27,18 @@ color: var(--rs-color-foreground-base-primary); white-space: normal; word-break: break-word; + border-radius: var(--rs-radius-2); } -.menuitem:hover, -.menuitem:focus, -.menuitem[data-highlighted] { +.menuitem[data-highlighted], +.menuitem[data-active-item="true"] { outline: none; cursor: pointer; - border-radius: var(--rs-radius-2); background: var(--rs-color-background-base-primary-hover); } +.menuitem[data-state="checked"] { + background: var(--rs-color-background-neutral-secondary); +} .menuitem[data-disabled] { opacity: 0.6; @@ -263,3 +265,51 @@ cursor: not-allowed; pointer-events: none; } + +.comboboxContainer { + padding: 0; + position: relative; +} + +.comboboxContent { + padding: var(--rs-space-2); +} + +/* + Empty state matches: + 1. Completely empty container + 2. Container where all .item children have data-hidden="true" +*/ +.comboboxContent:empty, +.comboboxContent:not(:has(.menuitem:not([data-hidden="true"]))) { + padding: 0; +} +.comboboxContainer:has(.comboboxContent:empty) .comboboxInput, +.comboboxContainer:has(.comboboxContent:not(:has(.menuitem:not([data-hidden="true"])))) + .comboboxInput { + border-bottom: none; +} + +.comboboxInput { + width: 100%; + color: var(--rs-color-foreground-base-primary); + padding: var(--rs-space-3) var(--rs-space-4); + font-family: var(--rs-font-body); + font-weight: var(--rs-font-weight-regular); + font-size: var(--rs-font-size-small); + line-height: var(--rs-line-height-small); + letter-spacing: var(--rs-letter-spacing-small); + border-bottom: 0.5px solid var(--rs-color-border-base-primary); + position: sticky; + top: 0; + z-index: 2; + background-color: var(--rs-color-background-base-primary); +} + +.comboboxInput:focus { + outline: none; +} + +.hidden { + display: none; +} From ab1d669af8a98795b781cba02c4e92a579c2327c Mon Sep 17 00:00:00 2001 From: Rohan Chakraborty Date: Tue, 20 May 2025 11:36:11 +0530 Subject: [PATCH 07/14] feat: select improvements (#397) * feat: autocomplete functionality in select * feat: select autocomplete qol changes * feat: update select docs * feat: update select doc tag * feat: add support for htmlAutocomplete * feat: select updates * feat: update docs * fix: use rs space tokens --- .../content/docs/components/select/index.mdx | 24 ++++++++ .../content/docs/components/select/props.ts | 24 ++++++++ .../dropdown-menu/dropdown-menu.module.css | 2 +- .../v1/components/select/select-content.tsx | 14 +++-- .../v1/components/select/select-item.tsx | 8 +-- .../v1/components/select/select-misc.tsx | 59 +++++++++++++++++++ .../v1/components/select/select-root.tsx | 37 +++++++++++- .../v1/components/select/select.module.css | 30 +++++----- .../raystack/v1/components/select/select.tsx | 6 +- 9 files changed, 172 insertions(+), 32 deletions(-) create mode 100644 packages/raystack/v1/components/select/select-misc.tsx diff --git a/apps/www/src/content/docs/components/select/index.mdx b/apps/www/src/content/docs/components/select/index.mdx index cc73c50ca..19911f1fa 100644 --- a/apps/www/src/content/docs/components/select/index.mdx +++ b/apps/www/src/content/docs/components/select/index.mdx @@ -44,16 +44,40 @@ The root element is the parent component that holds the select. Using the `autoc ### Select.Trigger Props +The button that triggers the Select. + ### Select.Content Props +The container that holds the Select items. + ### Select.Item Props +Individual clickable options within the Select. + +### Select.Group + +A way to group related Select items together. + + + +### Select.Label + +Renders a label in a Select group. This component can only be used inside Select.Group + + + +### Select.Separator + +Visual divider between Select items or groups. + + + ## Examples ### Basic Select diff --git a/apps/www/src/content/docs/components/select/props.ts b/apps/www/src/content/docs/components/select/props.ts index 36e6e3591..ad8666439 100644 --- a/apps/www/src/content/docs/components/select/props.ts +++ b/apps/www/src/content/docs/components/select/props.ts @@ -68,3 +68,27 @@ export interface SelectItemProps { /** Additional CSS class names. */ className?: string; } + +export interface SelectGroupProps { + /** Additional CSS class names */ + className?: string; + + /** Boolean to merge props onto child element */ + asChild?: boolean; +} + +export interface SelectLabelProps { + /** Additional CSS class names */ + className?: string; + + /** Boolean to merge props onto child element */ + asChild?: boolean; +} + +export interface SelectSeparatorProps { + /** Additional CSS class names */ + className?: string; + + /** Boolean to merge props onto child element */ + asChild?: boolean; +} diff --git a/packages/raystack/v1/components/dropdown-menu/dropdown-menu.module.css b/packages/raystack/v1/components/dropdown-menu/dropdown-menu.module.css index 5db0e6f23..842834ae6 100644 --- a/packages/raystack/v1/components/dropdown-menu/dropdown-menu.module.css +++ b/packages/raystack/v1/components/dropdown-menu/dropdown-menu.module.css @@ -56,7 +56,7 @@ } .label { - padding: 6px var(--rs-space-3); + padding: var(--rs-space-2) var(--rs-space-3); font-weight: var(--rs-font-weight-medium); font-size: var(--rs-font-size-mini); } diff --git a/packages/raystack/v1/components/select/select-content.tsx b/packages/raystack/v1/components/select/select-content.tsx index 4931454ca..73b6e1b80 100644 --- a/packages/raystack/v1/components/select/select-content.tsx +++ b/packages/raystack/v1/components/select/select-content.tsx @@ -19,6 +19,7 @@ export const SelectContent = forwardRef< children, position = "popper", searchPlaceholder = "Search...", + sideOffset = 4, ...props }, ref, @@ -30,14 +31,15 @@ export const SelectContent = forwardRef< - + {autocomplete ? ( <> { @@ -44,12 +44,6 @@ export const SelectItem = forwardRef< }; }, [value, leadingIcon]); - const shouldFilter = !!( - autocomplete && - autocompleteMode === "auto" && - searchValue?.length - ); - const isSelected = value === selectValue.value; const isMatched = getMatch(value, children, searchValue); const isHidden = shouldFilter && isSelected && !isMatched; diff --git a/packages/raystack/v1/components/select/select-misc.tsx b/packages/raystack/v1/components/select/select-misc.tsx new file mode 100644 index 000000000..0dd3603fc --- /dev/null +++ b/packages/raystack/v1/components/select/select-misc.tsx @@ -0,0 +1,59 @@ +import { ElementRef, forwardRef, Fragment } from "react"; +import * as SelectPrimitive from "@radix-ui/react-select"; +import { cx } from "class-variance-authority"; +import { useSelectContext } from "./select-root"; +import styles from "./select.module.css"; + +export const SelectGroup = forwardRef< + ElementRef, + SelectPrimitive.SelectGroupProps +>(({ className, children, ...props }, ref) => { + const { shouldFilter } = useSelectContext(); + + if (shouldFilter) return {children}; + + return ( + + {children} + + ); +}); +SelectGroup.displayName = SelectPrimitive.Group.displayName; + +export const SelectLabel = forwardRef< + ElementRef, + SelectPrimitive.SelectLabelProps +>(({ className, ...props }, ref) => { + const { shouldFilter } = useSelectContext(); + + if (shouldFilter) return null; + + return ( + + ); +}); +SelectLabel.displayName = SelectPrimitive.Label.displayName; + +export const SelectSeparator = forwardRef< + ElementRef, + SelectPrimitive.SelectSeparatorProps +>(({ className, ...props }, ref) => { + const { shouldFilter } = useSelectContext(); + + if (shouldFilter) return null; + return ( + + ); +}); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; diff --git a/packages/raystack/v1/components/select/select-root.tsx b/packages/raystack/v1/components/select/select-root.tsx index 447b2410a..87653bc8b 100644 --- a/packages/raystack/v1/components/select/select-root.tsx +++ b/packages/raystack/v1/components/select/select-root.tsx @@ -29,18 +29,51 @@ interface SelectContextValue extends CommonProps { unregisterIcon: (value: string) => void; } +interface UseSelectContext extends SelectContextValue { + shouldFilter?: boolean; +} + /* Root context to manage the Select control @remarks Only for internal usage. */ const SelectContext = createContext(undefined); -export const useSelectContext = () => { +export const useSelectContext = (): UseSelectContext => { const context = useContext(SelectContext); if (!context) { throw new Error("useSelectContext must be used within a SelectProvider"); } - return context; + const shouldFilter = !!( + context?.autocomplete && + context?.autocompleteMode === "auto" && + context?.searchValue?.length + ); + return { + ...context, + shouldFilter, + }; +}; + +export interface NormalSelectRootProps extends SelectPrimitive.SelectProps { + autocomplete?: false; + autocompleteMode?: never; + searchValue?: never; + onSearch?: never; + defaultSearchValue?: never; +} + +export interface AutocompleteSelectRootProps + extends SelectPrimitive.SelectProps, + CommonProps { + autocomplete: true; +} + +export type SelectRootProps = Omit< + NormalSelectRootProps | AutocompleteSelectRootProps, + "autoComplete" +> & { + htmlAutoComplete?: string; }; export interface NormalSelectRootProps extends SelectPrimitive.SelectProps { diff --git a/packages/raystack/v1/components/select/select.module.css b/packages/raystack/v1/components/select/select.module.css index 4ce392741..81207ddbe 100644 --- a/packages/raystack/v1/components/select/select.module.css +++ b/packages/raystack/v1/components/select/select.module.css @@ -1,21 +1,19 @@ .content { + --apsara-select-padding: var(--rs-space-2); z-index: var(--rs-z-index-portal); font-family: var(--rs-font-body); font-size: var(--rs-font-size-small); line-height: var(--rs-line-height-small); letter-spacing: var(--rs-letter-spacing-small); box-sizing: border-box; - padding: var(--rs-space-2); background-color: var(--rs-color-background-base-primary); border-radius: var(--rs-radius-2); box-shadow: var(--rs-shadow-soft); border: 1px solid var(--rs-color-border-base-primary); min-width: var(--radix-select-trigger-width); - margin-top: var(--rs-space-2); transition: all 0.2s ease; - overflow-y: auto; max-height: 320px; - max-width: 300px; + position: relative; } .menuitem { @@ -45,14 +43,16 @@ pointer-events: none; } +.label { + padding: var(--rs-space-2) var(--rs-space-3); + font-weight: var(--rs-font-weight-medium); + font-size: var(--rs-font-size-mini); +} + .separator { height: 1px; margin: var(--rs-space-2) calc(var(--rs-space-3) * -1); - background: var(--rs-color-background-neutral-secondary); -} - -.menugroup { - padding: var(--rs-space-3); + background: var(--rs-color-border-base-primary); } .trigger { @@ -266,13 +266,13 @@ pointer-events: none; } -.comboboxContainer { - padding: 0; - position: relative; +.comboboxContent, +.viewport { + padding: var(--apsara-select-padding); } -.comboboxContent { - padding: var(--rs-space-2); +.comboboxViewport { + padding: 0; } /* @@ -304,6 +304,8 @@ top: 0; z-index: 2; background-color: var(--rs-color-background-base-primary); + border-top-left-radius: var(--rs-radius-2); + border-top-right-radius: var(--rs-radius-2); } .comboboxInput:focus { diff --git a/packages/raystack/v1/components/select/select.tsx b/packages/raystack/v1/components/select/select.tsx index fbe1ac1d8..264c54ac0 100644 --- a/packages/raystack/v1/components/select/select.tsx +++ b/packages/raystack/v1/components/select/select.tsx @@ -4,9 +4,10 @@ import { SelectContent } from "./select-content"; import { SelectItem } from "./select-item"; import { SelectValue } from "./select-value"; import { SelectRoot } from "./select-root"; +import { SelectGroup, SelectLabel, SelectSeparator } from "./select-misc"; export const Select = Object.assign(SelectRoot, { - Group: SelectPrimitive.Group, + Group: SelectGroup, Value: SelectValue, ScrollUpButton: SelectPrimitive.ScrollDownButton, ScrollDownButton: SelectPrimitive.ScrollDownButton, @@ -14,5 +15,6 @@ export const Select = Object.assign(SelectRoot, { Trigger: SelectTrigger, Content: SelectContent, Item: SelectItem, - Separator: SelectPrimitive.Separator, + Separator: SelectSeparator, + Label: SelectLabel, }); From 02b6412f2952089faa2fdb8220a28f8e629b3b13 Mon Sep 17 00:00:00 2001 From: Rohan Chakraborty Date: Thu, 22 May 2025 10:54:33 +0530 Subject: [PATCH 08/14] chore: merge main into develop (#408) * Feat: Add Skeleton component (#381) * feat(calendar): handle loading state (#382) * feat(calendar): handle loading state * chore: minor refactor * fix: ci breaking as checkout position incorrect (#391) * Revert/workflow 4573 (#392) * fix (CI): Workflow breaking (#393) fix: update release workflow to enforce branch and tag rules * fix: update version in package.json (#394) * fix: update version in package.json * fix: add ref * feat: Support for `as` in Sidebar.Item (#386) * feat: as support for sidebar item * feat: update props in doc * Feat: Setup Code formatting, linting and import sorter (#384) * feat: grid component (#383) * feat: grid component * feat: grid doc * fix: Error prop not overriding for date-picker (#398) * Fix release files tag main (#404) * ci: create release file for rc tags * fix: update tag regex in github action * fix: Error prop not overriding for date-picker (#402) * fix: Error prop not overriding for date-picker * fix: Error prop not overriding for date-picker --------- Co-authored-by: Gaurav Singh * chore (Box): Deprecate old Box component (#406) * fix: update version in package.json * chore: deprecate old box * chore: update package version * chore: update comment --------- Co-authored-by: Gaurav Singh Co-authored-by: Pratik Kumar Singh <56654568+singh-pk@users.noreply.github.com> Co-authored-by: Rishabh Mishra --- .editorconfig | 32 +++ .eslintrc.js | 11 +- .eslintrs.js | 7 + .github/workflows/release.yaml | 2 +- .prettierignore | 3 + .vscode/settings.json | 36 +++- .zed/settings.json | 37 ++++ README.md | 2 +- apps/www/src/app/playground/page.tsx | 1 + apps/www/src/components/playground/index.ts | 1 + .../playground/skeleton-examples.tsx | 39 ++++ .../src/content/docs/components/grid/demo.ts | 50 +++++ .../content/docs/components/grid/index.mdx | 31 +++ .../src/content/docs/components/grid/props.ts | 156 ++++++++++++++ .../content/docs/components/sidebar/props.ts | 11 + .../content/docs/components/skeleton/demo.ts | 106 ++++++++++ .../docs/components/skeleton/index.mdx | 100 +++++++++ .../content/docs/components/skeleton/props.ts | 75 +++++++ biome.json | 155 ++++++++++++++ lefthook.yml | 6 + package.json | 8 +- packages/raystack/box/box.tsx | 3 + packages/raystack/package.json | 2 +- .../raystack/v1/components/avatar/avatar.tsx | 178 +++++++++------- .../v1/components/calendar/calendar.tsx | 47 +++-- .../v1/components/calendar/date-picker.tsx | 6 +- .../v1/components/calendar/range-picker.tsx | 8 +- .../v1/components/filter-chip/filter-chip.tsx | 2 +- .../raystack/v1/components/grid/grid-item.tsx | 59 ++++++ packages/raystack/v1/components/grid/grid.tsx | 126 ++++++++++++ packages/raystack/v1/components/grid/index.ts | 6 + packages/raystack/v1/components/grid/types.ts | 6 + .../v1/components/sidebar/sidebar.tsx | 108 +++++----- .../raystack/v1/components/skeleton/index.ts | 1 + .../components/skeleton/skeleton.module.css | 38 ++++ .../v1/components/skeleton/skeleton.tsx | 96 +++++++++ packages/raystack/v1/index.tsx | 2 + pnpm-lock.yaml | 191 ++++++++++++++++++ 38 files changed, 1599 insertions(+), 149 deletions(-) create mode 100644 .editorconfig create mode 100644 .eslintrs.js create mode 100644 .prettierignore create mode 100644 .zed/settings.json create mode 100644 apps/www/src/components/playground/skeleton-examples.tsx create mode 100644 apps/www/src/content/docs/components/grid/demo.ts create mode 100644 apps/www/src/content/docs/components/grid/index.mdx create mode 100644 apps/www/src/content/docs/components/grid/props.ts create mode 100644 apps/www/src/content/docs/components/skeleton/demo.ts create mode 100644 apps/www/src/content/docs/components/skeleton/index.mdx create mode 100644 apps/www/src/content/docs/components/skeleton/props.ts create mode 100644 biome.json create mode 100644 lefthook.yml create mode 100644 packages/raystack/v1/components/grid/grid-item.tsx create mode 100644 packages/raystack/v1/components/grid/grid.tsx create mode 100644 packages/raystack/v1/components/grid/index.ts create mode 100644 packages/raystack/v1/components/grid/types.ts create mode 100644 packages/raystack/v1/components/skeleton/index.ts create mode 100644 packages/raystack/v1/components/skeleton/skeleton.module.css create mode 100644 packages/raystack/v1/components/skeleton/skeleton.tsx diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..a78a52795 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,32 @@ +# https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true + +# TypeScript, JavaScript, JSX, TSX, JSON files +[*.{ts,tsx,js,jsx,json,jsonc}] +indent_style = space +indent_size = 2 + +# CSS files +[*.css] +indent_style = space +indent_size = 2 + +# Markdown files +[*.md] +trim_trailing_whitespace = false +indent_style = space +indent_size = 2 + +# Configuration files +[*.{yml,yaml}] +indent_style = space +indent_size = 2 \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 5b999efa4..ece3287ea 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,10 +1,7 @@ module.exports = { + // This project uses Biome instead of ESLint + // Keep this file for backwards compatibility only root: true, - // This tells ESLint to load the config from the package `eslint-config-custom` - extends: ["custom"], - settings: { - next: { - rootDir: ["apps/*/"], - }, - }, + extends: [], + rules: {} }; diff --git a/.eslintrs.js b/.eslintrs.js new file mode 100644 index 000000000..bace80cca --- /dev/null +++ b/.eslintrs.js @@ -0,0 +1,7 @@ +module.exports = { + // This project uses Biome instead of ESLint + // Keep this file for backwards compatibility and to avoid eslint conflicts + root: true, + extends: [], + rules: {}, +}; diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9a660599f..484cf796f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -63,4 +63,4 @@ jobs: gh release create "$GITHUB_REF_NAME" \ --repo "$GITHUB_REPOSITORY" \ --generate-notes \ - --verify-tag + --verify-tag \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..076c4d797 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +# This project uses Biome as a formatting, linting and import sorter toolchain. +# Ignore everything +* \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 25fa6215f..e1838a78b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,37 @@ { - "typescript.tsdk": "node_modules/typescript/lib" + "typescript.tsdk": "node_modules/typescript/lib", + + "biome.enabled": true, + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.biome": "explicit", + "source.organizeImports.biome": "explicit" + }, + + "eslint.enable": false, + + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[jsonc]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[css]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[markdown]": { + "editor.defaultFormatter": "biomejs.biome" + } } diff --git a/.zed/settings.json b/.zed/settings.json new file mode 100644 index 000000000..3d8fb5a10 --- /dev/null +++ b/.zed/settings.json @@ -0,0 +1,37 @@ +{ + "formatter": { + "language_server": { + "name": "biome" + } + }, + "code_actions_on_format": { + "source.fixAll.biome": true, + "source.organizeImports.biome": true + }, + "languages": { + "JavaScript": { + "formatter": { "name": "biome" } + }, + "JSX": { + "formatter": { "name": "biome" } + }, + "TypeScript": { + "formatter": { "name": "biome" } + }, + "TSX": { + "formatter": { "name": "biome" } + }, + "JSON": { + "formatter": { "name": "biome" } + }, + "JSON with Comments": { + "formatter": { "name": "biome" } + }, + "CSS": { + "formatter": { "name": "biome" } + }, + "Markdown": { + "formatter": { "name": "biome" } + } + } +} diff --git a/README.md b/README.md index 42e029db3..ffbebde3f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Apsara -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg?logo=apache)](LICENSE) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg?logo=apache)](LICENSE) [![Formatted with Biome](https://img.shields.io/badge/Formatted_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev/) [![Linted with Biome](https://img.shields.io/badge/Linted_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) [![Checked with Biome](https://img.shields.io/badge/Checked_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) Apsara 🧚‍♀️ is an open-source React UI component library built on Radix UI primitives and vanilla CSS. It provides enterprise-grade, accessible components designed for building complex data interfaces. diff --git a/apps/www/src/app/playground/page.tsx b/apps/www/src/app/playground/page.tsx index 48f31a63e..6edba1003 100644 --- a/apps/www/src/app/playground/page.tsx +++ b/apps/www/src/app/playground/page.tsx @@ -40,6 +40,7 @@ export default function Page() { + diff --git a/apps/www/src/components/playground/index.ts b/apps/www/src/components/playground/index.ts index 39ee24524..9d46b0492 100644 --- a/apps/www/src/components/playground/index.ts +++ b/apps/www/src/components/playground/index.ts @@ -39,3 +39,4 @@ export * from "./text-examples"; export * from "./text-area-examples"; export * from "./toast-examples"; export * from "./tooltip-examples"; +export * from './skeleton-examples'; diff --git a/apps/www/src/components/playground/skeleton-examples.tsx b/apps/www/src/components/playground/skeleton-examples.tsx new file mode 100644 index 000000000..08b26f8da --- /dev/null +++ b/apps/www/src/components/playground/skeleton-examples.tsx @@ -0,0 +1,39 @@ +"use client"; + +import { Skeleton, Flex } from "@raystack/apsara/v1"; +import PlaygroundLayout from "./playground-layout"; + +export function SkeletonExamples() { + return ( + + + {/* Basic Usage */} + + + {/* Multiple Lines */} + + + {/* Custom Colors */} + + + {/* Animation Control */} + + + + + + {/* Card Layout Example */} + + {/* Image placeholder */} + {/* Title placeholder */} + {/* Text lines placeholder */} + + + + ); +} \ No newline at end of file diff --git a/apps/www/src/content/docs/components/grid/demo.ts b/apps/www/src/content/docs/components/grid/demo.ts new file mode 100644 index 000000000..ac36a69ae --- /dev/null +++ b/apps/www/src/content/docs/components/grid/demo.ts @@ -0,0 +1,50 @@ +"use client"; + +import { getPropsString } from "@/lib/utils"; + +export const getCode = (props: any) => { + return ` + + + + + + + + + + `; +}; +export const playground = { + type: "playground", + controls: { + gap: { + type: "select", + options: ["extra-small", "small", "medium", "large", "extra-large"], + initialValue: "small", + }, + rows: { + type: "number", + min: 1, + max: 10, + initialValue: 4, + }, + columns: { + type: "number", + min: 1, + max: 10, + initialValue: 2, + }, + justifyItems: { + type: "select", + options: ["start", "end", "center", "stretch"], + initialValue: "center", + }, + alignItems: { + type: "select", + options: ["start", "end", "center", "stretch"], + initialValue: "center", + }, + }, + getCode, +}; diff --git a/apps/www/src/content/docs/components/grid/index.mdx b/apps/www/src/content/docs/components/grid/index.mdx new file mode 100644 index 000000000..5f792e0d3 --- /dev/null +++ b/apps/www/src/content/docs/components/grid/index.mdx @@ -0,0 +1,31 @@ +--- +title: Grid +description: A flexible and powerful component for grid layout +tag: new +--- + +import { playground, iconsDemo, customDemo, basicDemo } from "./demo.ts"; + + + +## Usage + +```tsx +import { Grid } from "@raystack/apsara/v1"; + + + 1 + 2 + 3 +; +``` + +## Grid Props + + + +### Grid.Item Props + +Grid.Item is a wrapper component that must be a direct child of Grid. Use it when you need to customize the positioning or styling of individual grid items. + + diff --git a/apps/www/src/content/docs/components/grid/props.ts b/apps/www/src/content/docs/components/grid/props.ts new file mode 100644 index 000000000..a120b171b --- /dev/null +++ b/apps/www/src/content/docs/components/grid/props.ts @@ -0,0 +1,156 @@ +export interface GridProps { + /** + * Defines named grid areas using CSS Grid template areas syntax. + */ + templateAreas?: string | string[]; + + /** + * Controls how auto-placed items flow into the grid. + * - "row": Items flow by row + * - "column": Items flow by column + * - "dense": Attempts to fill in holes in the grid + */ + autoFlow?: "row" | "column" | "dense" | "row dense" | "column dense"; + + /** + * Sets the size of auto-generated columns. + * Accepts any valid CSS size value. + */ + autoColumns?: string; + + /** + * Sets the size of auto-generated rows. + * Accepts any valid CSS size value. + */ + autoRows?: string; + + /** + * Defines the columns of the grid. Supports CSS Grid template columns syntax. + * + * If you pass a number, columns will be created using repeat(n, 1fr). + */ + columns?: string | number; + + /** + * Defines the rows of the grid. Supports CSS Grid template rows syntax. + * + * If you pass a number, rows will be created using repeat(n, 1fr). + */ + rows?: string | number; + + /** + * Sets the gap between grid items. + */ + gap?: "extra-small" | "small" | "medium" | "large" | "extra-large"; + + /** + * Sets the gap between grid columns. + */ + columnGap?: "extra-small" | "small" | "medium" | "large" | "extra-large"; + + /** + * Sets the gap between grid rows. + */ + rowGap?: "extra-small" | "small" | "medium" | "large" | "extra-large"; + + /** + * Aligns grid items along the inline (row) axis. + */ + justifyItems?: "start" | "end" | "center" | "stretch"; + + /** + * Aligns grid items along the block (column) axis. + */ + alignItems?: "start" | "end" | "center" | "stretch"; + + /** + * Aligns the entire grid along the inline (row) axis. + */ + justifyContent?: + | "start" + | "end" + | "center" + | "stretch" + | "space-around" + | "space-between" + | "space-evenly"; + + /** + * Aligns the entire grid along the block (column) axis. + */ + alignContent?: + | "start" + | "end" + | "center" + | "stretch" + | "space-around" + | "space-between" + | "space-evenly"; + + /** + * Renders the grid as an inline element instead of a block element. + * + * @default false + */ + inline?: boolean; + + /** + * Merges the grid's props with its child component. + * Useful for composition with other components. + */ + asChild?: boolean; +} + +export interface GridItemProps { + /** + * Specifies the named grid area where the item should be placed. + * Must match a named area defined in the parent Grid's templateAreas. + */ + area?: string; + + /** + * Defines the starting column line where the item should be placed. + */ + colStart?: number | string; + + /** + * Defines the ending column line where the item should be placed. + */ + colEnd?: number | string; + + /** + * Defines the starting row line where the item should be placed. + */ + rowStart?: number | string; + + /** + * Defines the ending row line where the item should be placed. + */ + rowEnd?: number | string; + + /** + * Specifies how many columns the item should span. + */ + colSpan?: number | string; + + /** + * Specifies how many rows the item should span. + */ + rowSpan?: number | string; + + /** + * Aligns the item along the inline (row) axis within its grid area. + */ + justifySelf?: "start" | "end" | "center" | "stretch"; + + /** + * Aligns the item along the block (column) axis within its grid area. + */ + alignSelf?: "start" | "end" | "center" | "stretch"; + + /** + * Merges the grid item's props with its child component. + * Useful for composition with other components. + */ + asChild?: boolean; +} diff --git a/apps/www/src/content/docs/components/sidebar/props.ts b/apps/www/src/content/docs/components/sidebar/props.ts index aeeb1a046..e7b6c71d7 100644 --- a/apps/www/src/content/docs/components/sidebar/props.ts +++ b/apps/www/src/content/docs/components/sidebar/props.ts @@ -1,3 +1,5 @@ +import { ReactElement } from "react"; + export interface SidebarRootProps { /** Controls the expanded/collapsed state. */ open?: boolean; @@ -68,4 +70,13 @@ export interface SidebarItemProps { /** ReactNode for the item's label. */ children?: React.ReactNode; + + /** + * Custom element used to render the SidebarItem. + * + * All props are forwarded to the specified element. + * + * @default "" + */ + as?: ReactElement; } diff --git a/apps/www/src/content/docs/components/skeleton/demo.ts b/apps/www/src/content/docs/components/skeleton/demo.ts new file mode 100644 index 000000000..6a518bc09 --- /dev/null +++ b/apps/www/src/content/docs/components/skeleton/demo.ts @@ -0,0 +1,106 @@ +"use client"; + +import { getPropsString } from "@/lib/utils"; + +export const getCode = (props: any) => { + return ``; +}; + +export const playground = { + type: "playground", + controls: { + width: { + type: "text", + initialValue: "200px", + }, + height: { + type: "text", + initialValue: "15px", + }, + count: { + type: "number", + initialValue: 3, + }, + enableAnimation: { + type: "checkbox", + initialValue: true, + }, + duration: { + type: "number", + initialValue: 1.5, + }, + inline: { + type: "checkbox", + initialValue: false, + } + }, + getCode, +}; + +export const basicDemo = { + type: "code", + code: ` + + + `, +}; + +export const multipleDemo = { + type: "code", + code: ` + + + `, +}; + +export const customStylesDemo = { + type: "code", + code: ` + + + `, +}; + +export const animationDemo = { + type: "code", + code: ` + + + + `, +}; + +export const cardDemo = { + type: "code", + code: ` + + {/* Image placeholder */} + {/* Title placeholder */} + {/* Text lines placeholder */} + `, +}; + +export const providerDemo = { + type: "code", + code: ` + + + + + + + + + + + `, +}; + diff --git a/apps/www/src/content/docs/components/skeleton/index.mdx b/apps/www/src/content/docs/components/skeleton/index.mdx new file mode 100644 index 000000000..027fdc76b --- /dev/null +++ b/apps/www/src/content/docs/components/skeleton/index.mdx @@ -0,0 +1,100 @@ +--- +title: Skeleton +description: A placeholder loading state that mimics the layout of content while it's being loaded. +tag: new +--- + +import { + playground, + basicDemo, + multipleDemo, + customStylesDemo, + animationDemo, + cardDemo, + providerDemo, +} from "./demo.ts"; + + + +## Usage + +The Skeleton component is used to create placeholder loading states that represent the layout of content while it's being loaded. It provides a visual indication that content is loading and helps maintain layout stability. + +```tsx +import { Skeleton } from "@raystack/apsara/v1"; + +; +``` + +## Skeleton Props + + + +## Examples + +### Basic Usage + +A simple skeleton loader with fixed dimensions. + + + +### Multiple Lines + +Create multiple skeleton lines using the count prop. + + + +### Using Provider + +Group multiple skeletons and share common props using Skeleton.Provider. + + + +### Custom Styles + +Customize the appearance using baseColor and highlightColor. + + + +### Animation Control + +Control the animation duration or disable it entirely. + + + +### Complex Layout + +Create a card-like loading state by combining multiple skeletons. + + + +## Provider Pattern + +The Skeleton component supports a Provider pattern that allows you to share common props across multiple skeleton instances: + +```tsx + + {/* Inherits provider props */} + {/* Inherits provider props, overrides width */} + {/* Overrides specific props */} + +``` + +All props available on the Skeleton component can be passed to the Provider and will be inherited by child Skeleton components. Individual Skeleton components can override any provider props with their own values. + +## Accessibility + +The Skeleton component follows accessibility best practices: + +- Uses semantic HTML elements +- Provides appropriate ARIA attributes +- Maintains sufficient color contrast +- Animation can be disabled for users who prefer reduced motion +- Supports both block and inline layouts \ No newline at end of file diff --git a/apps/www/src/content/docs/components/skeleton/props.ts b/apps/www/src/content/docs/components/skeleton/props.ts new file mode 100644 index 000000000..6f7b513cf --- /dev/null +++ b/apps/www/src/content/docs/components/skeleton/props.ts @@ -0,0 +1,75 @@ +export interface SkeletonProps { + /** + * Width of the skeleton + * @defaultValue "50px for inline, 100% otherwise" + */ + width?: string | number; + + /** + * Height of the skeleton + * @defaultValue "var(--rs-space-4)" + */ + height?: string | number; + + /** + * Base color of the skeleton + * @defaultValue "var(--rs-color-background-base-primary-hover)" + */ + baseColor?: string; + + /** + * Color of the shimmer effect + * @defaultValue "var(--rs-color-background-base-primary)" + */ + highlightColor?: string; + + /** + * Border radius of the skeleton + * @defaultValue "var(--rs-radius-2)" + */ + borderRadius?: string | number; + + /** + * Whether to display as inline-block + * @defaultValue false + */ + inline?: boolean; + + /** + * Duration of the animation in seconds + * @defaultValue 1.5 + */ + duration?: number; + + /** + * Whether to enable the shimmer animation + * @defaultValue true + */ + enableAnimation?: boolean; + + /** + * Number of skeleton elements to render + * @defaultValue 1 + */ + count?: number; + + /** + * Additional CSS class names for the skeleton element + */ + className?: string; + + /** + * Additional inline styles for the skeleton element + */ + style?: React.CSSProperties; + + /** + * Additional CSS class names for the container element (div for block and span for inline) + */ + containerClassName?: string; + + /** + * Additional inline styles for the container element (div for block and span for inline) + */ + containerStyle?: React.CSSProperties; +} \ No newline at end of file diff --git a/biome.json b/biome.json new file mode 100644 index 000000000..22e7e7b08 --- /dev/null +++ b/biome.json @@ -0,0 +1,155 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true, + "defaultBranch": "main" + }, + "files": { "ignoreUnknown": false, "ignore": [] }, + "formatter": { + "enabled": true, + "useEditorconfig": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 80, + "attributePosition": "auto", + "bracketSpacing": true + }, + "organizeImports": { "enabled": true }, + "linter": { + "enabled": true, + "rules": { + "recommended": false, + "a11y": { "noBlankTarget": "error" }, + "complexity": { + "noExtraBooleanCast": "error", + "noMultipleSpacesInRegularExpressionLiterals": "error", + "noUselessCatch": "error", + "noUselessTypeConstraint": "error", + "noWith": "error" + }, + "correctness": { + "noChildrenProp": "error", + "noConstAssign": "error", + "noConstantCondition": "error", + "noEmptyCharacterClassInRegex": "error", + "noEmptyPattern": "warn", + "noGlobalObjectCalls": "error", + "noInnerDeclarations": "error", + "noInvalidConstructorSuper": "error", + "noInvalidUseBeforeDeclaration": "error", + "noNewSymbol": "error", + "noNonoctalDecimalEscape": "error", + "noPrecisionLoss": "error", + "noSelfAssign": "error", + "noSetterReturn": "error", + "noSwitchDeclarations": "error", + "noUndeclaredVariables": "error", + "noUnreachable": "error", + "noUnreachableSuper": "error", + "noUnsafeFinally": "error", + "noUnsafeOptionalChaining": "error", + "noUnusedLabels": "error", + "noUnusedVariables": "warn", + "useArrayLiterals": "off", + "useExhaustiveDependencies": "warn", + "useHookAtTopLevel": "error", + "useIsNan": "error", + "useJsxKeyInIterable": "error", + "useValidForDirection": "error", + "useYield": "error", + "noUnusedImports": "warn" + }, + "security": { "noDangerouslySetInnerHtmlWithChildren": "error" }, + "style": { "noNamespace": "error", "useAsConstAssertion": "warn" }, + "suspicious": { + "noAsyncPromiseExecutor": "error", + "noCatchAssign": "error", + "noClassAssign": "error", + "noCommentText": "warn", + "noCompareNegZero": "error", + "noControlCharactersInRegex": "error", + "noDebugger": "error", + "noDuplicateCase": "error", + "noDuplicateClassMembers": "error", + "noDuplicateJsxProps": "error", + "noDuplicateObjectKeys": "error", + "noDuplicateParameters": "error", + "noEmptyBlockStatements": "warn", + "noExplicitAny": "warn", + "noExtraNonNullAssertion": "warn", + "noFallthroughSwitchClause": "error", + "noFunctionAssign": "error", + "noGlobalAssign": "error", + "noImportAssign": "error", + "noMisleadingCharacterClass": "error", + "noMisleadingInstantiator": "error", + "noPrototypeBuiltins": "error", + "noRedeclare": "error", + "noShadowRestrictedNames": "error", + "noSparseArray": "error", + "noUnsafeDeclarationMerging": "error", + "noUnsafeNegation": "error", + "useGetterReturn": "error", + "useNamespaceKeyword": "error", + "useValidTypeof": "error" + }, + "nursery": { + "useConsistentCurlyBraces": "error" + } + } + }, + "javascript": { + "formatter": { + "jsxQuoteStyle": "single", + "quoteProperties": "asNeeded", + "trailingCommas": "none", + "semicolons": "always", + "arrowParentheses": "asNeeded", + "bracketSameLine": false, + "quoteStyle": "single", + "attributePosition": "auto", + "bracketSpacing": true + } + }, + "overrides": [ + { "include": [".eslintrc.{js,cjs}"] }, + { + "include": ["*.ts", "*.tsx", "*.mts", "*.cts"], + "linter": { + "rules": { + "correctness": { + "noConstAssign": "off", + "noGlobalObjectCalls": "off", + "noInvalidBuiltinInstantiation": "off", + "noInvalidConstructorSuper": "off", + "noNewSymbol": "off", + "noSetterReturn": "off", + "noUndeclaredVariables": "off", + "noUnreachable": "off", + "noUnreachableSuper": "off" + }, + "style": { + "noArguments": "error", + "noVar": "error", + "useConst": "error" + }, + "suspicious": { + "noClassAssign": "off", + "noDuplicateClassMembers": "off", + "noDuplicateObjectKeys": "off", + "noDuplicateParameters": "off", + "noFunctionAssign": "off", + "noImportAssign": "off", + "noRedeclare": "off", + "noUnsafeNegation": "off", + "useGetterReturn": "off" + } + } + } + } + ] +} diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 000000000..f7f723070 --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,6 @@ +pre-commit: + commands: + check: + glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}" + run: pnpm format + stage_fixed: true \ No newline at end of file diff --git a/package.json b/package.json index 9359de7c8..81ceab265 100644 --- a/package.json +++ b/package.json @@ -7,21 +7,23 @@ "dev": "turbo dev --filter=@raystack/apsara", "lint": "turbo lint --filter=@raystack/apsara", "clean": "turbo clean --filter=@raystack/apsara", - "format": "prettier --write \"**/*.{ts,tsx,md}\"", + "format": "pnpm exec biome check --staged --write .", "ci:build": "turbo build --filter=@raystack/apsara", "ci:release": "turbo release --filter=@raystack/apsara -- --ci --no-increment" }, "devDependencies": { + "@biomejs/biome": "1.9.4", "@parcel/packager-ts": "2.9.2", "@parcel/transformer-typescript-types": "2.9.2", "@turbo/gen": "^1.9.7", + "concurrently": "^9.1.2", "eslint": "^7.32.0", "eslint-config-custom": "workspace:*", + "lefthook": "^1.11.12", "prettier": "^2.5.1", "process": "^0.11.10", "turbo": "2.3.1", - "typescript": "4.7", - "concurrently": "^9.1.2" + "typescript": "4.7" }, "packageManager": "pnpm@9.3.0", "name": "apsara" diff --git a/packages/raystack/box/box.tsx b/packages/raystack/box/box.tsx index ef12b2cea..bb727c210 100644 --- a/packages/raystack/box/box.tsx +++ b/packages/raystack/box/box.tsx @@ -7,6 +7,9 @@ const box = cva(styles.box); type BoxProps = PropsWithChildren> & HTMLAttributes; +/** + * @deprecated Use Box from '@raystack/apsara/v1' instead. + */ export function Box({ children, className, ...props }: BoxProps) { return (
diff --git a/packages/raystack/package.json b/packages/raystack/package.json index 27b72c1b6..cff8e5b6d 100644 --- a/packages/raystack/package.json +++ b/packages/raystack/package.json @@ -1,6 +1,6 @@ { "name": "@raystack/apsara", - "version": "0.19.0", + "version": "0.45.7", "types": "dist/index.d.ts", "sideEffects": false, "engines": { diff --git a/packages/raystack/v1/components/avatar/avatar.tsx b/packages/raystack/v1/components/avatar/avatar.tsx index dcafc288a..6e0033eeb 100644 --- a/packages/raystack/v1/components/avatar/avatar.tsx +++ b/packages/raystack/v1/components/avatar/avatar.tsx @@ -1,93 +1,129 @@ +import * as AvatarPrimitive from '@radix-ui/react-avatar'; +import { VariantProps, cva } from 'class-variance-authority'; +import { clsx } from 'clsx'; import { ComponentPropsWithoutRef, ElementRef, - forwardRef, - ReactNode -} from "react"; -import * as AvatarPrimitive from "@radix-ui/react-avatar"; -import { cva, VariantProps } from "class-variance-authority"; -import { clsx } from 'clsx'; - -import {AVATAR_COLORS, getAvatarProps} from './utils' -import { Box } from "../box"; -import styles from "./avatar.module.css"; + ReactNode, + forwardRef +} from 'react'; +import { Box } from '../box'; +import styles from './avatar.module.css'; +import { AVATAR_COLORS, getAvatarProps } from './utils'; const avatar = cva(styles.avatar, { variants: { radius: { - small: styles["avatar-small"], - full: styles["avatar-full"], + small: styles['avatar-small'], + full: styles['avatar-full'] }, size: { - 1: styles["avatar-size-1"], - 2: styles["avatar-size-2"], - 3: styles["avatar-size-3"], - 4: styles["avatar-size-4"], - 5: styles["avatar-size-5"], - 6: styles["avatar-size-6"], - 7: styles["avatar-size-7"], - 8: styles["avatar-size-8"], - 9: styles["avatar-size-9"], - 10: styles["avatar-size-10"], - 11: styles["avatar-size-11"], - 12: styles["avatar-size-12"], - 13: styles["avatar-size-13"], + 1: styles['avatar-size-1'], + 2: styles['avatar-size-2'], + 3: styles['avatar-size-3'], + 4: styles['avatar-size-4'], + 5: styles['avatar-size-5'], + 6: styles['avatar-size-6'], + 7: styles['avatar-size-7'], + 8: styles['avatar-size-8'], + 9: styles['avatar-size-9'], + 10: styles['avatar-size-10'], + 11: styles['avatar-size-11'], + 12: styles['avatar-size-12'], + 13: styles['avatar-size-13'] }, variant: { - solid: styles["avatar-solid"], - soft: styles["avatar-soft"], + solid: styles['avatar-solid'], + soft: styles['avatar-soft'] }, disabled: { - true: styles["avatar-disabled"], + true: styles['avatar-disabled'] }, color: { - indigo: styles["avatar-color-indigo"], - orange: styles["avatar-color-orange"], - mint: styles["avatar-color-mint"], - neutral: styles["avatar-color-neutral"], - sky: styles["avatar-color-sky"], - lime: styles["avatar-color-lime"], - grass: styles["avatar-color-grass"], - cyan: styles["avatar-color-cyan"], - iris: styles["avatar-color-iris"], - purple: styles["avatar-color-purple"], - pink: styles["avatar-color-pink"], - crimson: styles["avatar-color-crimson"], - gold: styles["avatar-color-gold"], - }, + indigo: styles['avatar-color-indigo'], + orange: styles['avatar-color-orange'], + mint: styles['avatar-color-mint'], + neutral: styles['avatar-color-neutral'], + sky: styles['avatar-color-sky'], + lime: styles['avatar-color-lime'], + grass: styles['avatar-color-grass'], + cyan: styles['avatar-color-cyan'], + iris: styles['avatar-color-iris'], + purple: styles['avatar-color-purple'], + pink: styles['avatar-color-pink'], + crimson: styles['avatar-color-crimson'], + gold: styles['avatar-color-gold'] + } }, compoundVariants: [ - { variant: 'solid', color: 'indigo', className: styles['avatar-solid-indigo'] }, - { variant: 'solid', color: 'orange', className: styles['avatar-solid-orange'] }, + { + variant: 'solid', + color: 'indigo', + className: styles['avatar-solid-indigo'] + }, + { + variant: 'solid', + color: 'orange', + className: styles['avatar-solid-orange'] + }, { variant: 'solid', color: 'mint', className: styles['avatar-solid-mint'] }, { variant: 'solid', color: 'sky', className: styles['avatar-solid-sky'] }, { variant: 'solid', color: 'lime', className: styles['avatar-solid-lime'] }, - { variant: 'solid', color: 'grass', className: styles['avatar-solid-grass'] }, + { + variant: 'solid', + color: 'grass', + className: styles['avatar-solid-grass'] + }, { variant: 'solid', color: 'cyan', className: styles['avatar-solid-cyan'] }, { variant: 'solid', color: 'iris', className: styles['avatar-solid-iris'] }, - { variant: 'solid', color: 'purple', className: styles['avatar-solid-purple'] }, + { + variant: 'solid', + color: 'purple', + className: styles['avatar-solid-purple'] + }, { variant: 'solid', color: 'pink', className: styles['avatar-solid-pink'] }, - { variant: 'solid', color: 'crimson', className: styles['avatar-solid-crimson'] }, + { + variant: 'solid', + color: 'crimson', + className: styles['avatar-solid-crimson'] + }, { variant: 'solid', color: 'gold', className: styles['avatar-solid-gold'] }, - { variant: 'soft', color: 'indigo', className: styles['avatar-soft-indigo'] }, - { variant: 'soft', color: 'orange', className: styles['avatar-soft-orange'] }, + { + variant: 'soft', + color: 'indigo', + className: styles['avatar-soft-indigo'] + }, + + { + variant: 'soft', + color: 'orange', + className: styles['avatar-soft-orange'] + }, { variant: 'soft', color: 'mint', className: styles['avatar-soft-mint'] }, { variant: 'soft', color: 'sky', className: styles['avatar-soft-sky'] }, { variant: 'soft', color: 'lime', className: styles['avatar-soft-lime'] }, { variant: 'soft', color: 'grass', className: styles['avatar-soft-grass'] }, { variant: 'soft', color: 'cyan', className: styles['avatar-soft-cyan'] }, { variant: 'soft', color: 'iris', className: styles['avatar-soft-iris'] }, - { variant: 'soft', color: 'purple', className: styles['avatar-soft-purple'] }, + { + variant: 'soft', + color: 'purple', + className: styles['avatar-soft-purple'] + }, { variant: 'soft', color: 'pink', className: styles['avatar-soft-pink'] }, - { variant: 'soft', color: 'crimson', className: styles['avatar-soft-crimson'] }, - { variant: 'soft', color: 'gold', className: styles['avatar-soft-gold'] }, + { + variant: 'soft', + color: 'crimson', + className: styles['avatar-soft-crimson'] + }, + { variant: 'soft', color: 'gold', className: styles['avatar-soft-gold'] } ], defaultVariants: { size: 3, - radius: "small", - variant: "soft", - color: "indigo", - }, + radius: 'small', + variant: 'soft', + color: 'indigo' + } }); const image = cva(styles.image); @@ -99,7 +135,7 @@ export interface AvatarProps src?: string; alt?: string; fallback?: ReactNode; - variant?: "solid" | "soft"; + variant?: 'solid' | 'soft'; color?: AVATAR_COLORS; asChild?: boolean; className?: string; @@ -110,7 +146,19 @@ const AvatarRoot = forwardRef< AvatarProps >( ( - { className, alt, src, fallback, size, radius, variant, color, style, asChild, ...props }, + { + className, + alt, + src, + fallback, + size, + radius, + variant, + color, + style, + asChild, + ...props + }, ref ) => ( @@ -120,11 +168,7 @@ const AvatarRoot = forwardRef< asChild={asChild} {...props} > - + {fallback} @@ -151,11 +195,7 @@ export const AvatarGroup = forwardRef( const firstAvatarProps = getAvatarProps(avatars[0]); return ( -
+
{avatars.map((avatar, index) => (
{avatar} @@ -176,5 +216,3 @@ export const AvatarGroup = forwardRef( ); } ); - -AvatarGroup.displayName = 'AvatarGroup'; diff --git a/packages/raystack/v1/components/calendar/calendar.tsx b/packages/raystack/v1/components/calendar/calendar.tsx index 1e9102658..d740fe2bd 100644 --- a/packages/raystack/v1/components/calendar/calendar.tsx +++ b/packages/raystack/v1/components/calendar/calendar.tsx @@ -12,12 +12,14 @@ import { DayPickerProps, DropdownProps, } from 'react-day-picker'; -import Skeleton from 'react-loading-skeleton'; +import { clsx } from 'clsx'; import { Flex } from '../flex/flex'; import { Select } from '../select'; import { Tooltip } from '../tooltip'; +import { Skeleton } from '../skeleton'; import styles from './calendar.module.css'; +import { IconButton } from '../icon-button'; interface OnDropdownOpen { onDropdownOpen?: VoidFunction; @@ -36,12 +38,17 @@ export type CalendarProps = DayPickerProps & const root = cva(styles.calendarRoot); +interface DropDownComponentProps extends DropdownProps, OnDropdownOpen { + disabled?: boolean; +} + function DropDown({ options = [], value, onChange, onDropdownOpen, -}: DropdownProps & OnDropdownOpen) { + disabled, +}: DropDownComponentProps) { const [open, setOpen] = useState(false); useEffect(() => { @@ -69,6 +76,7 @@ function DropDown({ stopPropagation={true} size="small" variant="text" + disabled={disabled} > @@ -119,13 +127,30 @@ export const Calendar = function ({ timeZone={timeZone} components={{ Chevron: (props) => { - if (props.orientation === 'left') { - return ; - } - return ; + const icon = props.orientation === 'left' ? ( + + ) : ( + + ); + + return ( + + {icon} + + ); }, Dropdown: (props: DropdownProps) => ( - + ), DayButton: (props) => { const { day, ...buttonProps } = props; @@ -144,12 +169,10 @@ export const Calendar = function ({ MonthGrid: (props) => loadingData ? ( ) : ( diff --git a/packages/raystack/v1/components/calendar/date-picker.tsx b/packages/raystack/v1/components/calendar/date-picker.tsx index 9bbbc85a9..a1c63e94c 100644 --- a/packages/raystack/v1/components/calendar/date-picker.tsx +++ b/packages/raystack/v1/components/calendar/date-picker.tsx @@ -161,18 +161,18 @@ export function DatePicker({ const defaultTrigger = ( : undefined} {...inputFieldProps} + ref={inputFieldRef} defaultValue={formattedDate} onChange={handleInputChange} onFocus={handleInputFocus} onBlur={handleInputBlur} - error={error} onKeyUp={handleKeyUp} - className={styles.datePickerInput} /> ); diff --git a/packages/raystack/v1/components/calendar/range-picker.tsx b/packages/raystack/v1/components/calendar/range-picker.tsx index ee99232f6..178a070a8 100644 --- a/packages/raystack/v1/components/calendar/range-picker.tsx +++ b/packages/raystack/v1/components/calendar/range-picker.tsx @@ -59,14 +59,14 @@ export function RangePicker({ ? dayjs(selectedRange.to).format(dateFormat) : ""; - // Ensures two months are visible even when + // Ensures two months are visible even when // current month is the last allowed month (endMonth). const computedDefaultMonth = useMemo(() => { let month = currentMonth; if (calendarProps?.endMonth) { const endMonth = dayjs(calendarProps.endMonth); const fromMonth = dayjs(currentMonth); - + if (fromMonth.isSame(endMonth, 'month')) { month = endMonth.subtract(1, 'month').toDate(); } @@ -127,9 +127,9 @@ export function RangePicker({ size='small' placeholder="Select start date" trailingIcon={showCalendarIcon ? : undefined} + className={styles.datePickerInput} {...(inputFieldsProps.startDate ?? {})} value={startDate} - className={styles.datePickerInput} readOnly /> @@ -137,9 +137,9 @@ export function RangePicker({ size='small' placeholder="Select end date" trailingIcon={showCalendarIcon ? : undefined} + className={styles.datePickerInput} {...(inputFieldsProps.endDate ?? {})} value={endDate} - className={styles.datePickerInput} readOnly /> diff --git a/packages/raystack/v1/components/filter-chip/filter-chip.tsx b/packages/raystack/v1/components/filter-chip/filter-chip.tsx index b12c6f059..2f23638d2 100644 --- a/packages/raystack/v1/components/filter-chip/filter-chip.tsx +++ b/packages/raystack/v1/components/filter-chip/filter-chip.tsx @@ -154,7 +154,7 @@ export const FilterChip = ({ value={filterValue} onSelect={date => setFilterValue(date)} showCalendarIcon={false} - textFieldProps={{ className: styles.dateField }} + inputFieldProps={{ className: styles.dateField }} /> ); diff --git a/packages/raystack/v1/components/grid/grid-item.tsx b/packages/raystack/v1/components/grid/grid-item.tsx new file mode 100644 index 000000000..8d1cb9749 --- /dev/null +++ b/packages/raystack/v1/components/grid/grid-item.tsx @@ -0,0 +1,59 @@ +import { forwardRef, HTMLAttributes } from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { AlignType } from "./types"; + +type GridItemProps = HTMLAttributes & { + area?: string; + colStart?: number | string; + colEnd?: number | string; + rowStart?: number | string; + rowEnd?: number | string; + colSpan?: number | string; + rowSpan?: number | string; + justifySelf?: AlignType; + alignSelf?: AlignType; + asChild?: boolean; +}; + +export const GridItem = forwardRef( + ( + { + area, + colStart, + colEnd, + rowStart, + rowEnd, + colSpan, + rowSpan, + justifySelf, + alignSelf, + style, + asChild, + ...props + }, + ref, + ) => { + const Comp = asChild ? Slot : "div"; + + return ( + + ); + }, +); + +GridItem.displayName = "GridItem"; diff --git a/packages/raystack/v1/components/grid/grid.tsx b/packages/raystack/v1/components/grid/grid.tsx new file mode 100644 index 000000000..bbfcf785d --- /dev/null +++ b/packages/raystack/v1/components/grid/grid.tsx @@ -0,0 +1,126 @@ +import { forwardRef, HTMLAttributes, useMemo } from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { AlignExtendedType, AlignType } from "./types"; + +const GAPS = { + "extra-small": "var(--rs-space-2)", + small: "var(--rs-space-3)", + medium: "var(--rs-space-5)", + large: "var(--rs-space-9)", + "extra-large": "var(--rs-space-11)", +} as const; + +type GapType = keyof typeof GAPS; + +type GridProps = HTMLAttributes & { + /** + * Supports CSS Grid template areas syntax. + * + * @example + * + * + */ + templateAreas?: string | string[]; + autoFlow?: "row" | "column" | "dense" | "row dense" | "column dense"; + autoColumns?: string; + autoRows?: string; + + /** + * Supports CSS Grid template columns syntax. + * + * If you pass a number, columns will be created using repeat(n, 1fr). + * + * @example + * + * + */ + columns?: string | number; + + /** + * Supports CSS Grid template rows syntax. + * + * If you pass a number, rows will be created using repeat(n, 1fr). + * + * @example + * + * + */ + rows?: string | number; + gap?: GapType; + columnGap?: GapType; + rowGap?: GapType; + justifyItems?: AlignType; + alignItems?: AlignType; + justifyContent?: AlignExtendedType; + alignContent?: AlignExtendedType; + inline?: boolean; + asChild?: boolean; +}; + +export const Grid = forwardRef( + ( + { + templateAreas, + autoFlow, + autoColumns, + autoRows, + columns, + rows, + gap, + columnGap, + rowGap, + justifyItems, + alignItems, + justifyContent, + alignContent, + inline = false, + style = {}, + asChild, + ...props + }, + ref, + ) => { + const gridTemplateColumns = + typeof columns === "number" ? `repeat(${columns}, 1fr)` : columns; + const gridTemplateRows = + typeof rows === "number" ? `repeat(${rows}, 1fr)` : rows; + + const gridTemplateAreas = useMemo(() => { + if (Array.isArray(templateAreas)) { + return templateAreas + .map(area => `"${area}"`) + .join(" ") + .trim(); + } + return templateAreas; + }, [templateAreas]); + + const Comp = asChild ? Slot : "div"; + + return ( + + ); + }, +); + +Grid.displayName = "Grid"; diff --git a/packages/raystack/v1/components/grid/index.ts b/packages/raystack/v1/components/grid/index.ts new file mode 100644 index 000000000..0c8236c9d --- /dev/null +++ b/packages/raystack/v1/components/grid/index.ts @@ -0,0 +1,6 @@ +import { Grid as GridPrimitive } from "./grid"; +import { GridItem } from "./grid-item"; + +export const Grid = Object.assign(GridPrimitive, { + Item: GridItem, +}); diff --git a/packages/raystack/v1/components/grid/types.ts b/packages/raystack/v1/components/grid/types.ts new file mode 100644 index 000000000..afde3fd3e --- /dev/null +++ b/packages/raystack/v1/components/grid/types.ts @@ -0,0 +1,6 @@ +export type AlignType = "start" | "end" | "center" | "stretch"; +export type AlignExtendedType = + | AlignType + | "space-around" + | "space-between" + | "space-evenly"; diff --git a/packages/raystack/v1/components/sidebar/sidebar.tsx b/packages/raystack/v1/components/sidebar/sidebar.tsx index 9e4d2c30a..320a96079 100644 --- a/packages/raystack/v1/components/sidebar/sidebar.tsx +++ b/packages/raystack/v1/components/sidebar/sidebar.tsx @@ -6,7 +6,9 @@ import { forwardRef, ReactNode, createContext, - useContext + useContext, + ReactElement, + cloneElement, } from "react"; import { Tooltip, TooltipProvider } from "../tooltip"; @@ -18,7 +20,9 @@ interface SidebarContextValue { hideCollapsedItemTooltip?: boolean; } -const SidebarContext = createContext({ isCollapsed: false }); +const SidebarContext = createContext({ + isCollapsed: false, +}); const root = cva(styles.root); @@ -38,6 +42,7 @@ interface SidebarItemProps extends ComponentPropsWithoutRef<"a"> { icon: ReactNode; active?: boolean; disabled?: boolean; + as?: ReactElement; classNames?: { root?: string; icon?: string; @@ -57,10 +62,19 @@ const SidebarRoot = forwardRef< SidebarProps >( ( - { className, position = "left", open, onOpenChange, hideCollapsedItemTooltip, children, ...props }, - ref + { + className, + position = "left", + open, + onOpenChange, + hideCollapsedItemTooltip, + children, + ...props + }, + ref, ) => ( - + + asChild>