diff --git a/apps/ui/content/docs/components/avatar.mdx b/apps/ui/content/docs/components/avatar.mdx index 6ab5a0613..4c584671e 100644 --- a/apps/ui/content/docs/components/avatar.mdx +++ b/apps/ui/content/docs/components/avatar.mdx @@ -60,6 +60,20 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" ``` +Use `keepMounted` when the image relies on native lazy loading or an optimized image component. The fallback remains visible while the image loads or if it fails: + +```tsx + + + JD + +``` + ## API Reference ### Avatar @@ -68,7 +82,7 @@ Root component. Styled wrapper for `Avatar.Root` from Base UI with default size ### AvatarImage -Image element for the avatar. Styled wrapper for `Avatar.Image` from Base UI. +Image element for the avatar. Styled wrapper for `Avatar.Image` from Base UI with support for `keepMounted` images. ### AvatarFallback diff --git a/apps/ui/content/docs/components/combobox.mdx b/apps/ui/content/docs/components/combobox.mdx index f8c9f1076..fc7d8c875 100644 --- a/apps/ui/content/docs/components/combobox.mdx +++ b/apps/ui/content/docs/components/combobox.mdx @@ -59,6 +59,7 @@ import { ComboboxItem, ComboboxList, ComboboxPopup, + createComboboxItems, } from "@/components/ui/combobox" ``` @@ -81,6 +82,33 @@ const items = [ ``` +When your source items are objects but selection should use a stable primitive value, create a typed collection with `createComboboxItems`: + +```tsx +const users = [ + { id: "ada", name: "Ada Lovelace" }, + { id: "grace", name: "Grace Hopper" }, +] + +const userItems = createComboboxItems(users, { + getLabel: (user) => user.name, + getValue: (user) => user.id, +}) + + + + + + {(user) => ( + + {user.name} + + )} + + + +``` + ### Multiple Selection ```tsx @@ -145,6 +173,10 @@ The root combobox component. Manages the combobox state and provides context to | `open` | `boolean` | Controls whether the popup is open | | `...props` | `React.ComponentProps` | All Base UI Combobox props are supported | +### createComboboxItems + +Creates a typed item collection that derives primitive selection values and labels from object items. Define static collections outside components and memoize dynamic collections. + ### ComboboxInput The input field component for single selection mode with extended features for size variants and addon support. @@ -328,4 +360,3 @@ Use `SelectButton` as a `render` prop on `ComboboxTrigger` to make the combobox ### Form Integration - Multiple - diff --git a/apps/ui/package.json b/apps/ui/package.json index 9f5723b5a..798076907 100644 --- a/apps/ui/package.json +++ b/apps/ui/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@base-ui/react": "1.6.0", + "@base-ui/react": "1.8.0", "@coss/ui": "workspace:*", "@daypicker/react": "10.0.1", "@hugeicons/core-free-icons": "^2.0.0", diff --git a/apps/ui/public/r/avatar.json b/apps/ui/public/r/avatar.json index d54a36f0f..677171f31 100644 --- a/apps/ui/public/r/avatar.json +++ b/apps/ui/public/r/avatar.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/default/ui/avatar.tsx", - "content": "\"use client\";\n\nimport { Avatar as AvatarPrimitive } from \"@base-ui/react/avatar\";\nimport type React from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\n\nexport function Avatar({\n className,\n ...props\n}: AvatarPrimitive.Root.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function AvatarImage({\n className,\n ...props\n}: AvatarPrimitive.Image.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function AvatarFallback({\n className,\n ...props\n}: AvatarPrimitive.Fallback.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport { AvatarPrimitive };\n", + "content": "\"use client\";\n\nimport { Avatar as AvatarPrimitive } from \"@base-ui/react/avatar\";\nimport type React from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\n\nexport function Avatar({\n className,\n ...props\n}: AvatarPrimitive.Root.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function AvatarImage({\n className,\n ...props\n}: AvatarPrimitive.Image.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function AvatarFallback({\n className,\n ...props\n}: AvatarPrimitive.Fallback.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport { AvatarPrimitive };\n", "type": "registry:ui" } ], diff --git a/apps/ui/public/r/combobox.json b/apps/ui/public/r/combobox.json index bb26dd71e..24f5c04bb 100644 --- a/apps/ui/public/r/combobox.json +++ b/apps/ui/public/r/combobox.json @@ -11,7 +11,7 @@ "files": [ { "path": "registry/default/ui/combobox.tsx", - "content": "\"use client\";\n\nimport { Combobox as ComboboxPrimitive } from \"@base-ui/react/combobox\";\nimport { ChevronsUpDownIcon, XIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { ScrollArea } from \"@/registry/default/ui/scroll-area\";\n\nexport const ComboboxContext: React.Context<{\n chipsRef: React.RefObject | null;\n multiple: boolean;\n}> = React.createContext<{\n chipsRef: React.RefObject | null;\n multiple: boolean;\n}>({\n chipsRef: null,\n multiple: false,\n});\n\nexport function Combobox(\n props: ComboboxPrimitive.Root.Props,\n): React.ReactElement {\n const chipsRef = React.useRef(null);\n return (\n \n \n \n );\n}\n\nexport function ComboboxChipsInput({\n className,\n size,\n ...props\n}: Omit & {\n size?: \"sm\" | \"default\" | \"lg\" | number;\n ref?: React.Ref;\n}): React.ReactElement {\n const sizeValue = (size ?? \"default\") as \"sm\" | \"default\" | \"lg\" | number;\n\n return (\n \n );\n}\n\nexport function ComboboxInput({\n className,\n showTrigger = true,\n showClear = false,\n startAddon,\n size,\n triggerProps,\n clearProps,\n ...props\n}: Omit & {\n showTrigger?: boolean;\n showClear?: boolean;\n startAddon?: React.ReactNode;\n size?: \"sm\" | \"default\" | \"lg\" | number;\n ref?: React.Ref;\n triggerProps?: ComboboxPrimitive.Trigger.Props;\n clearProps?: ComboboxPrimitive.Clear.Props;\n}): React.ReactElement {\n const sizeValue = (size ?? \"default\") as \"sm\" | \"default\" | \"lg\" | number;\n\n return (\n *.w-full]:w-fit w-full text-foreground has-disabled:opacity-64\"\n data-slot=\"combobox-input-group\"\n >\n {startAddon && (\n \n {startAddon}\n \n )}\n \n }\n {...props}\n />\n {showTrigger && (\n \n \n \n \n \n )}\n {showClear && (\n \n \n \n )}\n \n );\n}\n\nexport function ComboboxTrigger({\n className,\n children,\n ...props\n}: ComboboxPrimitive.Trigger.Props): React.ReactElement {\n return (\n \n {children}\n \n );\n}\n\nexport function ComboboxPopup({\n className,\n children,\n side = \"bottom\",\n sideOffset = 4,\n alignOffset,\n align = \"start\",\n anchor: anchorProp,\n portalProps,\n ...props\n}: ComboboxPrimitive.Popup.Props & {\n align?: ComboboxPrimitive.Positioner.Props[\"align\"];\n sideOffset?: ComboboxPrimitive.Positioner.Props[\"sideOffset\"];\n alignOffset?: ComboboxPrimitive.Positioner.Props[\"alignOffset\"];\n side?: ComboboxPrimitive.Positioner.Props[\"side\"];\n anchor?: ComboboxPrimitive.Positioner.Props[\"anchor\"];\n portalProps?: ComboboxPrimitive.Portal.Props;\n}): React.ReactElement {\n const { chipsRef } = React.useContext(ComboboxContext);\n const anchor = anchorProp ?? chipsRef;\n\n return (\n \n \n \n \n {children}\n \n \n \n \n );\n}\n\nexport function ComboboxItem({\n className,\n children,\n ...props\n}: ComboboxPrimitive.Item.Props): React.ReactElement {\n return (\n \n \n \n \n \n \n
{children}
\n \n );\n}\n\nexport function ComboboxSeparator({\n className,\n ...props\n}: ComboboxPrimitive.Separator.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function ComboboxGroup({\n className,\n ...props\n}: ComboboxPrimitive.Group.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function ComboboxGroupLabel({\n className,\n ...props\n}: ComboboxPrimitive.GroupLabel.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function ComboboxEmpty({\n className,\n ...props\n}: ComboboxPrimitive.Empty.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function ComboboxRow({\n className,\n ...props\n}: ComboboxPrimitive.Row.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport const ComboboxValue: typeof ComboboxPrimitive.Value =\n ComboboxPrimitive.Value;\n\nexport function ComboboxList({\n className,\n ...props\n}: ComboboxPrimitive.List.Props): React.ReactElement {\n return (\n \n \n \n );\n}\n\nexport function ComboboxClear({\n className,\n ...props\n}: ComboboxPrimitive.Clear.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function ComboboxStatus({\n className,\n ...props\n}: ComboboxPrimitive.Status.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport const ComboboxCollection: typeof ComboboxPrimitive.Collection =\n ComboboxPrimitive.Collection;\n\nexport function ComboboxChips({\n className,\n children,\n startAddon,\n ...props\n}: ComboboxPrimitive.Chips.Props & {\n startAddon?: React.ReactNode;\n}): React.ReactElement {\n const { chipsRef } = React.useContext(ComboboxContext);\n\n return (\n | null}\n {...props}\n >\n {startAddon && (\n \n {startAddon}\n \n )}\n {children}\n \n );\n}\n\nexport function ComboboxChip({\n children,\n removeProps,\n ...props\n}: ComboboxPrimitive.Chip.Props & {\n removeProps?: ComboboxPrimitive.ChipRemove.Props;\n}): React.ReactElement {\n return (\n \n {children}\n \n \n );\n}\n\nexport function ComboboxChipRemove(\n props: ComboboxPrimitive.ChipRemove.Props,\n): React.ReactElement {\n return (\n \n \n \n );\n}\n\nexport const useComboboxFilter: typeof ComboboxPrimitive.useFilter =\n ComboboxPrimitive.useFilter;\n\nexport { ComboboxPrimitive };\n", + "content": "\"use client\";\n\nimport { Combobox as ComboboxPrimitive } from \"@base-ui/react/combobox\";\nimport { ChevronsUpDownIcon, XIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { ScrollArea } from \"@/registry/default/ui/scroll-area\";\n\nexport const ComboboxContext: React.Context<{\n chipsRef: React.RefObject | null;\n multiple: boolean;\n}> = React.createContext<{\n chipsRef: React.RefObject | null;\n multiple: boolean;\n}>({\n chipsRef: null,\n multiple: false,\n});\n\nexport function Combobox<\n Value,\n Multiple extends boolean | undefined = false,\n Item = Value,\n>(\n props: ComboboxPrimitive.Root.Props,\n): React.ReactElement {\n const chipsRef = React.useRef(null);\n return (\n \n \n \n );\n}\n\nexport function ComboboxChipsInput({\n className,\n size,\n ...props\n}: Omit & {\n size?: \"sm\" | \"default\" | \"lg\" | number;\n ref?: React.Ref;\n}): React.ReactElement {\n const sizeValue = (size ?? \"default\") as \"sm\" | \"default\" | \"lg\" | number;\n\n return (\n \n );\n}\n\nexport function ComboboxInput({\n className,\n showTrigger = true,\n showClear = false,\n startAddon,\n size,\n triggerProps,\n clearProps,\n ...props\n}: Omit & {\n showTrigger?: boolean;\n showClear?: boolean;\n startAddon?: React.ReactNode;\n size?: \"sm\" | \"default\" | \"lg\" | number;\n ref?: React.Ref;\n triggerProps?: ComboboxPrimitive.Trigger.Props;\n clearProps?: ComboboxPrimitive.Clear.Props;\n}): React.ReactElement {\n const sizeValue = (size ?? \"default\") as \"sm\" | \"default\" | \"lg\" | number;\n\n return (\n *.w-full]:w-fit w-full text-foreground has-disabled:opacity-64\"\n data-slot=\"combobox-input-group\"\n >\n {startAddon && (\n \n {startAddon}\n \n )}\n \n }\n {...props}\n />\n {showTrigger && (\n \n \n \n \n \n )}\n {showClear && (\n \n \n \n )}\n \n );\n}\n\nexport function ComboboxTrigger({\n className,\n children,\n ...props\n}: ComboboxPrimitive.Trigger.Props): React.ReactElement {\n return (\n \n {children}\n \n );\n}\n\nexport function ComboboxPopup({\n className,\n children,\n side = \"bottom\",\n sideOffset = 4,\n alignOffset,\n align = \"start\",\n anchor: anchorProp,\n portalProps,\n ...props\n}: ComboboxPrimitive.Popup.Props & {\n align?: ComboboxPrimitive.Positioner.Props[\"align\"];\n sideOffset?: ComboboxPrimitive.Positioner.Props[\"sideOffset\"];\n alignOffset?: ComboboxPrimitive.Positioner.Props[\"alignOffset\"];\n side?: ComboboxPrimitive.Positioner.Props[\"side\"];\n anchor?: ComboboxPrimitive.Positioner.Props[\"anchor\"];\n portalProps?: ComboboxPrimitive.Portal.Props;\n}): React.ReactElement {\n const { chipsRef } = React.useContext(ComboboxContext);\n const anchor = anchorProp ?? chipsRef;\n\n return (\n \n \n \n \n {children}\n \n \n \n \n );\n}\n\nexport function ComboboxItem({\n className,\n children,\n ...props\n}: ComboboxPrimitive.Item.Props): React.ReactElement {\n return (\n \n \n \n \n \n \n
{children}
\n \n );\n}\n\nexport function ComboboxSeparator({\n className,\n ...props\n}: ComboboxPrimitive.Separator.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function ComboboxGroup({\n className,\n ...props\n}: ComboboxPrimitive.Group.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function ComboboxGroupLabel({\n className,\n ...props\n}: ComboboxPrimitive.GroupLabel.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function ComboboxEmpty({\n className,\n ...props\n}: ComboboxPrimitive.Empty.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function ComboboxRow({\n className,\n ...props\n}: ComboboxPrimitive.Row.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport const ComboboxValue: typeof ComboboxPrimitive.Value =\n ComboboxPrimitive.Value;\n\nexport function ComboboxList({\n className,\n ...props\n}: ComboboxPrimitive.List.Props): React.ReactElement {\n return (\n \n \n \n );\n}\n\nexport function ComboboxClear({\n className,\n ...props\n}: ComboboxPrimitive.Clear.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport function ComboboxStatus({\n className,\n ...props\n}: ComboboxPrimitive.Status.Props): React.ReactElement {\n return (\n \n );\n}\n\nexport const ComboboxCollection: typeof ComboboxPrimitive.Collection =\n ComboboxPrimitive.Collection;\n\nexport function ComboboxChips({\n className,\n children,\n startAddon,\n ...props\n}: ComboboxPrimitive.Chips.Props & {\n startAddon?: React.ReactNode;\n}): React.ReactElement {\n const { chipsRef } = React.useContext(ComboboxContext);\n\n return (\n | null}\n {...props}\n >\n {startAddon && (\n \n {startAddon}\n \n )}\n {children}\n \n );\n}\n\nexport function ComboboxChip({\n children,\n removeProps,\n ...props\n}: ComboboxPrimitive.Chip.Props & {\n removeProps?: ComboboxPrimitive.ChipRemove.Props;\n}): React.ReactElement {\n return (\n \n {children}\n \n \n );\n}\n\nexport function ComboboxChipRemove(\n props: ComboboxPrimitive.ChipRemove.Props,\n): React.ReactElement {\n return (\n \n \n \n );\n}\n\nexport const createComboboxItems: typeof ComboboxPrimitive.createItems =\n ComboboxPrimitive.createItems;\n\nexport const useComboboxFilter: typeof ComboboxPrimitive.useFilter =\n ComboboxPrimitive.useFilter;\n\nexport { ComboboxPrimitive };\n", "type": "registry:ui" } ], diff --git a/apps/ui/registry/default/ui/avatar.tsx b/apps/ui/registry/default/ui/avatar.tsx index 6aaa0b80d..1e9c551e0 100644 --- a/apps/ui/registry/default/ui/avatar.tsx +++ b/apps/ui/registry/default/ui/avatar.tsx @@ -11,7 +11,7 @@ export function Avatar({ return ( @@ -40,7 +43,7 @@ export function AvatarFallback({ return ( ( - props: ComboboxPrimitive.Root.Props, +export function Combobox< + Value, + Multiple extends boolean | undefined = false, + Item = Value, +>( + props: ComboboxPrimitive.Root.Props, ): React.ReactElement { const chipsRef = React.useRef(null); return ( @@ -429,6 +433,9 @@ export function ComboboxChipRemove( ); } +export const createComboboxItems: typeof ComboboxPrimitive.createItems = + ComboboxPrimitive.createItems; + export const useComboboxFilter: typeof ComboboxPrimitive.useFilter = ComboboxPrimitive.useFilter; diff --git a/apps/ui/skills/coss/references/primitives/avatar.md b/apps/ui/skills/coss/references/primitives/avatar.md index 96b24a676..5e98f1c6e 100644 --- a/apps/ui/skills/coss/references/primitives/avatar.md +++ b/apps/ui/skills/coss/references/primitives/avatar.md @@ -32,6 +32,8 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" ``` +Use `keepMounted` on `AvatarImage` when the image relies on native lazy loading or an optimized image component. The image and fallback are layered so the fallback remains visible while the image loads or if it fails. + ## Patterns from coss particles ### Key patterns diff --git a/apps/ui/skills/coss/references/primitives/combobox.md b/apps/ui/skills/coss/references/primitives/combobox.md index e72dcfd2c..176617f31 100644 --- a/apps/ui/skills/coss/references/primitives/combobox.md +++ b/apps/ui/skills/coss/references/primitives/combobox.md @@ -39,6 +39,7 @@ import { ComboboxPopup, ComboboxSeparator, ComboboxValue, + createComboboxItems, useComboboxFilter, } from "@/components/ui/combobox" ``` @@ -66,6 +67,8 @@ const items = [ For form-bound comboboxes, prefer `Field` composition (`Field` + `FieldLabel` + `FieldError`) instead of standalone controls. +Use `createComboboxItems` when object items should derive stable primitive selection values and labels. Define static collections at module scope and memoize dynamic collections. + ## Patterns from coss particles - **Portal forwarding**: optional `portalProps` on `ComboboxPopup` → Base UI `Combobox.Portal` (`keepMounted`, `container`, …). See [portal-props.md](../portal-props.md). diff --git a/bun.lock b/bun.lock index 4812e6546..0cd54374d 100644 --- a/bun.lock +++ b/bun.lock @@ -104,7 +104,7 @@ "name": "ui", "version": "0.1.0", "dependencies": { - "@base-ui/react": "1.6.0", + "@base-ui/react": "1.8.0", "@coss/ui": "workspace:*", "@daypicker/react": "10.0.1", "@hugeicons/core-free-icons": "^2.0.0", @@ -172,7 +172,7 @@ "name": "@coss/ui", "version": "0.0.0", "dependencies": { - "@base-ui/react": "1.6.0", + "@base-ui/react": "1.8.0", "@daypicker/react": "^10.0.1", "@hugeicons/core-free-icons": "^2.0.0", "@hugeicons/react": "^1.1.1", @@ -258,7 +258,7 @@ "@babel/preset-typescript": ["@babel/preset-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "7.27.1", "@babel/helper-validator-option": "7.27.1", "@babel/plugin-syntax-jsx": "7.27.1", "@babel/plugin-transform-modules-commonjs": "7.27.1", "@babel/plugin-transform-typescript": "7.28.0" }, "peerDependencies": { "@babel/core": "7.28.4" } }, "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ=="], - "@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="], + "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="], "@babel/runtime-corejs3": ["@babel/runtime-corejs3@7.28.2", "", { "dependencies": { "core-js-pure": "3.45.0" } }, "sha512-FVFaVs2/dZgD3Y9ZD+AKNKjyGKzwu0C54laAXWUXgLcVXcCX6YZ6GhK2cp7FogSN2OA0Fu+QT8dP3FUdo9ShSQ=="], @@ -268,9 +268,9 @@ "@babel/types": ["@babel/types@7.28.4", "", { "dependencies": { "@babel/helper-string-parser": "7.27.1", "@babel/helper-validator-identifier": "7.27.1" } }, "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q=="], - "@base-ui/react": ["@base-ui/react@1.6.0", "", { "dependencies": { "@babel/runtime": "^7.29.2", "@base-ui/utils": "0.3.1", "@floating-ui/react-dom": "^2.1.8", "@floating-ui/utils": "^0.2.11", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@date-fns/tz": "^1.2.0", "@types/react": "^17 || ^18 || ^19", "date-fns": "^4.0.0", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@date-fns/tz", "@types/react", "date-fns"] }, "sha512-/jzjTWJYXhRFO45Bev9lc3cHbmjzCMpUqbMZ2AgKy/z25mY9B6shGSNcXcjQar9n5doM0KYW1W8fcFv2jZBuMw=="], + "@base-ui/react": ["@base-ui/react@1.8.0", "", { "dependencies": { "@babel/runtime": "^7.29.7", "@base-ui/utils": "0.4.0", "@floating-ui/react-dom": "^2.1.9", "@floating-ui/utils": "^0.2.12", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@date-fns/tz": "^1.2.0", "@types/react": "^17 || ^18 || ^19", "date-fns": "^4.0.0", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@date-fns/tz", "@types/react", "date-fns"] }, "sha512-P0/1sxo6SBVZOklKMIedvTWqw2s2IQzi9x5bIVsXu980cuSOD4NeuRSs+/L7LZQfDkZP/uRZyGPyfFl/B1oH+Q=="], - "@base-ui/utils": ["@base-ui/utils@0.3.1", "", { "dependencies": { "@babel/runtime": "^7.29.2", "@floating-ui/utils": "^0.2.11", "reselect": "^5.2.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-gFFiltORVmW/N6IILTGxizP3PBpVpysqML1ALY5Vk0mH+7faVkCknOU31goYHN5Aoek2dkjxva1XOD2Ce9WuIg=="], + "@base-ui/utils": ["@base-ui/utils@0.4.0", "", { "dependencies": { "@babel/runtime": "^7.29.7", "@floating-ui/utils": "^0.2.12", "reselect": "^5.2.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-bO9fz25kKtPf+aZVyfQrC0PDmJdmVni31W2hCS5/Owb+inwdIL3XU26pCPRPlt4LSxZrBgLwubXQXQlKaFEZzw=="], "@biomejs/biome": ["@biomejs/biome@2.3.10", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.10", "@biomejs/cli-darwin-x64": "2.3.10", "@biomejs/cli-linux-arm64": "2.3.10", "@biomejs/cli-linux-arm64-musl": "2.3.10", "@biomejs/cli-linux-x64": "2.3.10", "@biomejs/cli-linux-x64-musl": "2.3.10", "@biomejs/cli-win32-arm64": "2.3.10", "@biomejs/cli-win32-x64": "2.3.10" }, "bin": { "biome": "bin/biome" } }, "sha512-/uWSUd1MHX2fjqNLHNL6zLYWBbrJeG412/8H7ESuK8ewoRoMPUgHDebqKrPTx/5n6f17Xzqc9hdg3MEqA5hXnQ=="], @@ -380,13 +380,13 @@ "@examples/calcom": ["@examples/calcom@workspace:apps/examples/calcom"], - "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="], + "@floating-ui/core": ["@floating-ui/core@1.8.0", "", { "dependencies": { "@floating-ui/utils": "^0.2.12" } }, "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ=="], - "@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="], + "@floating-ui/dom": ["@floating-ui/dom@1.8.0", "", { "dependencies": { "@floating-ui/core": "^1.8.0", "@floating-ui/utils": "^0.2.12" } }, "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg=="], - "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.8", "", { "dependencies": { "@floating-ui/dom": "^1.7.6" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A=="], + "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.9", "", { "dependencies": { "@floating-ui/dom": "^1.8.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg=="], - "@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="], + "@floating-ui/utils": ["@floating-ui/utils@0.2.12", "", {}, "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww=="], "@formatjs/ecma402-abstract": ["@formatjs/ecma402-abstract@2.3.4", "", { "dependencies": { "@formatjs/fast-memoize": "2.2.7", "@formatjs/intl-localematcher": "0.6.1", "decimal.js": "10.6.0", "tslib": "2.8.1" } }, "sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA=="], diff --git a/packages/ui/package.json b/packages/ui/package.json index 51c6d3951..7dae7c22e 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@base-ui/react": "1.6.0", + "@base-ui/react": "1.8.0", "@daypicker/react": "^10.0.1", "@hugeicons/core-free-icons": "^2.0.0", "@hugeicons/react": "^1.1.1", diff --git a/packages/ui/src/components/avatar.tsx b/packages/ui/src/components/avatar.tsx index 9a3cf1a92..6f658c559 100644 --- a/packages/ui/src/components/avatar.tsx +++ b/packages/ui/src/components/avatar.tsx @@ -11,7 +11,7 @@ export function Avatar({ return ( @@ -40,7 +43,7 @@ export function AvatarFallback({ return ( ( - props: ComboboxPrimitive.Root.Props, +export function Combobox< + Value, + Multiple extends boolean | undefined = false, + Item = Value, +>( + props: ComboboxPrimitive.Root.Props, ): React.ReactElement { const chipsRef = React.useRef(null); return ( @@ -429,6 +433,9 @@ export function ComboboxChipRemove( ); } +export const createComboboxItems: typeof ComboboxPrimitive.createItems = + ComboboxPrimitive.createItems; + export const useComboboxFilter: typeof ComboboxPrimitive.useFilter = ComboboxPrimitive.useFilter;