@health-samurai/react-components 0.0.0-alpha.7 → 0.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/bundle.css +10 -10
  2. package/dist/src/components/data-table.d.ts +2 -2
  3. package/dist/src/components/data-table.d.ts.map +1 -1
  4. package/dist/src/components/data-table.js.map +1 -1
  5. package/dist/src/components/fhir-structure-view.d.ts +8 -8
  6. package/dist/src/components/fhir-structure-view.d.ts.map +1 -1
  7. package/dist/src/components/fhir-structure-view.js +9 -7
  8. package/dist/src/components/fhir-structure-view.js.map +1 -1
  9. package/dist/src/components/segment-control.d.ts +3 -3
  10. package/dist/src/components/segment-control.d.ts.map +1 -1
  11. package/dist/src/components/segment-control.js +4 -4
  12. package/dist/src/components/segment-control.js.map +1 -1
  13. package/dist/src/components/segment-control.stories.d.ts +2 -3
  14. package/dist/src/components/segment-control.stories.d.ts.map +1 -1
  15. package/dist/src/components/split-button.d.ts +2 -2
  16. package/dist/src/components/split-button.d.ts.map +1 -1
  17. package/dist/src/components/split-button.js +2 -2
  18. package/dist/src/components/split-button.js.map +1 -1
  19. package/dist/src/components/tree-view.d.ts +25 -5
  20. package/dist/src/components/tree-view.d.ts.map +1 -1
  21. package/dist/src/components/tree-view.js +44 -51
  22. package/dist/src/components/tree-view.js.map +1 -1
  23. package/dist/src/components/tree-view.stories.js +8 -8
  24. package/dist/src/components/tree-view.stories.js.map +1 -1
  25. package/dist/src/icons.d.ts +8 -8
  26. package/dist/src/icons.d.ts.map +1 -1
  27. package/dist/src/icons.js +16 -16
  28. package/dist/src/icons.js.map +1 -1
  29. package/dist/src/index.d.ts +1 -1
  30. package/dist/src/index.d.ts.map +1 -1
  31. package/dist/src/index.js.map +1 -1
  32. package/dist/src/shadcn/components/ui/chart.d.ts +2 -2
  33. package/dist/src/shadcn/components/ui/chart.d.ts.map +1 -1
  34. package/dist/src/shadcn/components/ui/chart.js +2 -2
  35. package/dist/src/shadcn/components/ui/chart.js.map +1 -1
  36. package/dist/src/shadcn/components/ui/combobox.d.ts.map +1 -1
  37. package/dist/src/shadcn/components/ui/combobox.js +13 -22
  38. package/dist/src/shadcn/components/ui/combobox.js.map +1 -1
  39. package/dist/src/shadcn/components/ui/form.d.ts +2 -2
  40. package/dist/src/shadcn/components/ui/form.d.ts.map +1 -1
  41. package/dist/src/shadcn/components/ui/form.js +4 -4
  42. package/dist/src/shadcn/components/ui/form.js.map +1 -1
  43. package/dist/src/shadcn/components/ui/sonner.d.ts +3 -3
  44. package/dist/src/shadcn/components/ui/sonner.d.ts.map +1 -1
  45. package/dist/src/shadcn/components/ui/sonner.js +4 -4
  46. package/dist/src/shadcn/components/ui/sonner.js.map +1 -1
  47. package/dist/src/shadcn/components/ui/tabs.d.ts +6 -1
  48. package/dist/src/shadcn/components/ui/tabs.d.ts.map +1 -1
  49. package/dist/src/shadcn/components/ui/tabs.js +12 -8
  50. package/dist/src/shadcn/components/ui/tabs.js.map +1 -1
  51. package/dist/src/shadcn/components/ui/tree.d.ts.map +1 -1
  52. package/dist/src/shadcn/components/ui/tree.js +2 -2
  53. package/dist/src/shadcn/components/ui/tree.js.map +1 -1
  54. package/package.json +1 -1
  55. package/src/components/data-table.tsx +2 -1
  56. package/src/components/fhir-structure-view.tsx +16 -14
  57. package/src/components/segment-control.tsx +5 -5
  58. package/src/components/split-button.tsx +2 -2
  59. package/src/components/tree-view.stories.tsx +8 -8
  60. package/src/components/tree-view.tsx +100 -66
  61. package/src/icons.tsx +16 -16
  62. package/src/index.tsx +1 -1
  63. package/src/shadcn/components/ui/chart.tsx +2 -2
  64. package/src/shadcn/components/ui/combobox.tsx +13 -18
  65. package/src/shadcn/components/ui/form.tsx +5 -7
  66. package/src/shadcn/components/ui/sonner.tsx +5 -5
  67. package/src/shadcn/components/ui/tabs.tsx +26 -17
  68. package/src/shadcn/components/ui/tree.tsx +2 -4
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/shadcn/components/ui/tree.tsx"],"sourcesContent":["import type { ItemInstance } from \"@headless-tree/core\";\nimport { ChevronDownIcon } from \"lucide-react\";\nimport { Slot } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { cn } from \"#shadcn/lib/utils\";\n\ntype WithMeta = {\n\tmeta?: {\n\t\tlastNode?: boolean;\n\t};\n};\n\n// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\ninterface TreeContextValue<T = any> {\n\tindent: number;\n\tcurrentItem?: ItemInstance<T>;\n\t// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\n\ttree?: any;\n}\n\nconst TreeContext = React.createContext<TreeContextValue>({\n\tindent: 20,\n});\n\n// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\nfunction useTreeContext<T = any>() {\n\treturn React.useContext(TreeContext) as TreeContextValue<T>;\n}\n\ninterface TreeProps extends React.HTMLAttributes<HTMLDivElement> {\n\tindent?: number;\n\t// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\n\ttree?: any;\n}\n\nfunction Tree({ indent = 20, tree, className, ...props }: TreeProps) {\n\tconst containerProps =\n\t\ttree && typeof tree.getContainerProps === \"function\"\n\t\t\t? tree.getContainerProps()\n\t\t\t: {};\n\tconst mergedProps = { ...props, ...containerProps };\n\n\t// Extract style from mergedProps to merge with our custom styles\n\tconst { style: propStyle, ...otherProps } = mergedProps;\n\n\t// Merge styles\n\tconst mergedStyle = {\n\t\t...propStyle,\n\t\t\"--tree-indent\": `${indent}px`,\n\t\t\"--border\": `var(--color-border-separator)`,\n\t} as React.CSSProperties;\n\n\treturn (\n\t\t<TreeContext.Provider value={{ indent, tree }}>\n\t\t\t<div\n\t\t\t\tdata-slot=\"tree\"\n\t\t\t\tstyle={mergedStyle}\n\t\t\t\tclassName={cn(\"flex flex-col\", className)}\n\t\t\t\t{...otherProps}\n\t\t\t/>\n\t\t</TreeContext.Provider>\n\t);\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\ninterface TreeItemProps<T = any>\n\textends React.HTMLAttributes<HTMLButtonElement> {\n\titem: ItemInstance<T>;\n\tindent?: number;\n\tasChild?: boolean;\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\nfunction TreeItem<T = any>({\n\titem,\n\tclassName,\n\tasChild,\n\tchildren,\n\t...props\n}: Omit<TreeItemProps<T>, \"indent\">) {\n\tconst { indent } = useTreeContext<T>();\n\n\tconst itemProps = typeof item.getProps === \"function\" ? item.getProps() : {};\n\tconst mergedProps = { ...props, ...itemProps };\n\n\t// Extract style from mergedProps to merge with our custom styles\n\tconst { style: propStyle, ...otherProps } = mergedProps;\n\n\t// Merge styles\n\tconst mergedStyle = {\n\t\t...propStyle,\n\t\t\"--tree-padding\": `${item.getItemMeta().level * indent}px`,\n\t} as React.CSSProperties;\n\n\tconst Comp = asChild ? Slot.Root : \"span\";\n\n\treturn (\n\t\t<TreeContext.Provider value={{ indent, currentItem: item }}>\n\t\t\t<Comp\n\t\t\t\tdata-slot=\"tree-item\"\n\t\t\t\tstyle={mergedStyle}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"z-10 ps-(--tree-padding) outline-hidden select-none focus:z-20 data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-focus={\n\t\t\t\t\ttypeof item.isFocused === \"function\"\n\t\t\t\t\t\t? item.isFocused() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-folder={\n\t\t\t\t\ttypeof item.isFolder === \"function\"\n\t\t\t\t\t\t? item.isFolder() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-selected={\n\t\t\t\t\ttypeof item.isSelected === \"function\"\n\t\t\t\t\t\t? item.isSelected() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-drag-target={\n\t\t\t\t\ttypeof item.isDragTarget === \"function\"\n\t\t\t\t\t\t? item.isDragTarget() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-search-match={\n\t\t\t\t\ttypeof item.isMatchingSearch === \"function\"\n\t\t\t\t\t\t? item.isMatchingSearch() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\taria-expanded={item.isExpanded()}\n\t\t\t\t{...Object.fromEntries(\n\t\t\t\t\tObject.entries(otherProps).filter(\n\t\t\t\t\t\t([key]) => key !== \"onClick\" && key !== \"onDragStart\",\n\t\t\t\t\t),\n\t\t\t\t)}\n\t\t\t\tonDragStart={(e) => {\n\t\t\t\t\tif ((e.target as HTMLElement).dataset.slot === \"drag-handle\") {\n\t\t\t\t\t\titem.getProps().onDragStart(e);\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Comp>\n\t\t</TreeContext.Provider>\n\t);\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\ninterface TreeItemLabelProps<T = any>\n\textends React.HTMLAttributes<HTMLSpanElement> {\n\thideChevron?: boolean;\n\tdisableHover?: boolean;\n\titem?: ItemInstance<T>;\n\thorizontalLines?: boolean;\n}\n\nfunction TreeItemLabel<T>({\n\titem: propItem,\n\tchildren,\n\tclassName,\n\tdisableHover,\n\thorizontalLines,\n\thideChevron,\n\t...props\n}: TreeItemLabelProps<T & WithMeta>) {\n\tconst { currentItem } = useTreeContext<T & WithMeta>();\n\tconst item = propItem || currentItem;\n\n\tif (!item) {\n\t\tconsole.warn(\"TreeItemLabel: No item provided via props or context\");\n\t\treturn null;\n\t}\n\n\tconst data = item.getItemData?.();\n\tconst isLastNode = data?.meta?.lastNode;\n\tconst itemMeta = item.getItemMeta();\n\n\treturn (\n\t\t<span\n\t\t\tdata-slot=\"tree-item-label\"\n\t\t\tclassName={cn(\n\t\t\t\t\"group/tree-item-label relative select-text in-focus-visible:ring-ring/50 bg-background text-text-secondary in-data-[drag-target=true]:bg-accent flex items-center gap-2 pr-2 pl-2.5 py-1.5 text-sm transition-colors not-in-data-[folder=true]:ps-2.5 in-focus-visible:ring-[3px] in-data-[search-match=true]:bg-blue-400/20! [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n\t\t\t\t!disableHover &&\n\t\t\t\t\t\"in-data-[selected=true]:bg-bg-secondary in-data-[selected=true]:text-text-primary\",\n\t\t\t\t!disableHover &&\n\t\t\t\t\titem.isFolder() &&\n\t\t\t\t\t\"hover:bg-bg-secondary hover:text-text-primary cursor-pointer\",\n\t\t\t\tdisableHover && \"text-text-primary\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{item.isFolder() && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"self-start mt-0.5 cursor-pointer\"\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\titem.isExpanded() ? item.collapse() : item.expand();\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<ChevronDownIcon className=\"text-muted-foreground size-4 in-aria-[expanded=false]:-rotate-90\" />\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{!item.isFolder() && horizontalLines && (\n\t\t\t\t<div\n\t\t\t\t\tclassName={`w-5 min-w-5 h-px border-t mt-2 -ml-1 self-start`}\n\t\t\t\t></div>\n\t\t\t)}\n\t\t\t{item.isFolder() && item.isExpanded() && horizontalLines && (\n\t\t\t\t<div\n\t\t\t\t\tclassName={`absolute left-4.25 top-8 w-px min-h-full h-full border-l mt-2.25 self-start `}\n\t\t\t\t></div>\n\t\t\t)}\n\t\t\t{horizontalLines && (\n\t\t\t\t<div\n\t\t\t\t\tclassName={`absolute left-0 top-4.75 -m-[5px] border-t w-4 ${isLastNode ? \"h-full bg-inherit \" : \"\"} ${itemMeta.level === 0 ? \"hidden\" : \"\"}`}\n\t\t\t\t></div>\n\t\t\t)}\n\t\t\t{children ||\n\t\t\t\t(typeof item.getItemName === \"function\" ? item.getItemName() : null)}\n\t\t</span>\n\t);\n}\n\nfunction TreeDragLine({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n\tconst { tree } = useTreeContext();\n\n\tif (!tree || typeof tree.getDragLineStyle !== \"function\") {\n\t\tconsole.warn(\n\t\t\t\"TreeDragLine: No tree provided via context or tree does not have getDragLineStyle method\",\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst dragLine = tree.getDragLineStyle();\n\treturn (\n\t\t<div\n\t\t\tstyle={dragLine}\n\t\t\tclassName={cn(\n\t\t\t\t\"bg-primary before:bg-background before:border-primary absolute z-30 -mt-px h-0.5 w-[unset] before:absolute before:-top-[3px] before:left-0 before:size-2 before:rounded-full before:border-2\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport { Tree, TreeItem, TreeItemLabel, TreeDragLine, type ItemInstance };\n"],"names":["ChevronDownIcon","Slot","React","cn","TreeContext","createContext","indent","useTreeContext","useContext","Tree","tree","className","props","containerProps","getContainerProps","mergedProps","style","propStyle","otherProps","mergedStyle","Provider","value","div","data-slot","TreeItem","item","asChild","children","itemProps","getProps","getItemMeta","level","Comp","Root","currentItem","data-focus","isFocused","undefined","data-folder","isFolder","data-selected","isSelected","data-drag-target","isDragTarget","data-search-match","isMatchingSearch","aria-expanded","isExpanded","Object","fromEntries","entries","filter","key","onDragStart","e","target","dataset","slot","TreeItemLabel","propItem","disableHover","horizontalLines","hideChevron","console","warn","data","getItemData","isLastNode","meta","lastNode","itemMeta","span","button","type","onClick","collapse","expand","getItemName","TreeDragLine","getDragLineStyle","dragLine"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/shadcn/components/ui/tree.tsx"],"sourcesContent":["import type { ItemInstance } from \"@headless-tree/core\";\nimport { ChevronDownIcon } from \"lucide-react\";\nimport { Slot } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { cn } from \"#shadcn/lib/utils\";\n\ntype WithMeta = {\n\tmeta?: {\n\t\tlastNode?: boolean;\n\t};\n};\n\n// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\ninterface TreeContextValue<T = any> {\n\tindent: number;\n\tcurrentItem?: ItemInstance<T>;\n\t// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\n\ttree?: any;\n}\n\nconst TreeContext = React.createContext<TreeContextValue>({\n\tindent: 20,\n});\n\n// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\nfunction useTreeContext<T = any>() {\n\treturn React.useContext(TreeContext) as TreeContextValue<T>;\n}\n\ninterface TreeProps extends React.HTMLAttributes<HTMLDivElement> {\n\tindent?: number;\n\t// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\n\ttree?: any;\n}\n\nfunction Tree({ indent = 20, tree, className, ...props }: TreeProps) {\n\tconst containerProps =\n\t\ttree && typeof tree.getContainerProps === \"function\"\n\t\t\t? tree.getContainerProps()\n\t\t\t: {};\n\tconst mergedProps = { ...props, ...containerProps };\n\n\t// Extract style from mergedProps to merge with our custom styles\n\tconst { style: propStyle, ...otherProps } = mergedProps;\n\n\t// Merge styles\n\tconst mergedStyle = {\n\t\t...propStyle,\n\t\t\"--tree-indent\": `${indent}px`,\n\t\t\"--border\": `var(--color-border-separator)`,\n\t} as React.CSSProperties;\n\n\treturn (\n\t\t<TreeContext.Provider value={{ indent, tree }}>\n\t\t\t<div\n\t\t\t\tdata-slot=\"tree\"\n\t\t\t\tstyle={mergedStyle}\n\t\t\t\tclassName={cn(\"flex flex-col\", className)}\n\t\t\t\t{...otherProps}\n\t\t\t/>\n\t\t</TreeContext.Provider>\n\t);\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\ninterface TreeItemProps<T = any>\n\textends React.HTMLAttributes<HTMLButtonElement> {\n\titem: ItemInstance<T>;\n\tindent?: number;\n\tasChild?: boolean;\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\nfunction TreeItem<T = any>({\n\titem,\n\tclassName,\n\tasChild,\n\tchildren,\n\t...props\n}: Omit<TreeItemProps<T>, \"indent\">) {\n\tconst { indent } = useTreeContext<T>();\n\n\tconst itemProps = typeof item.getProps === \"function\" ? item.getProps() : {};\n\tconst mergedProps = { ...props, ...itemProps };\n\n\t// Extract style from mergedProps to merge with our custom styles\n\tconst { style: propStyle, ...otherProps } = mergedProps;\n\n\t// Merge styles\n\tconst mergedStyle = {\n\t\t...propStyle,\n\t\t\"--tree-padding\": `${item.getItemMeta().level * indent}px`,\n\t} as React.CSSProperties;\n\n\tconst Comp = asChild ? Slot.Root : \"span\";\n\n\treturn (\n\t\t<TreeContext.Provider value={{ indent, currentItem: item }}>\n\t\t\t<Comp\n\t\t\t\tdata-slot=\"tree-item\"\n\t\t\t\tstyle={mergedStyle}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"z-10 ps-(--tree-padding) outline-hidden select-none focus:z-20 data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-focus={\n\t\t\t\t\ttypeof item.isFocused === \"function\"\n\t\t\t\t\t\t? item.isFocused() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-folder={\n\t\t\t\t\ttypeof item.isFolder === \"function\"\n\t\t\t\t\t\t? item.isFolder() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-selected={\n\t\t\t\t\ttypeof item.isSelected === \"function\"\n\t\t\t\t\t\t? item.isSelected() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-drag-target={\n\t\t\t\t\ttypeof item.isDragTarget === \"function\"\n\t\t\t\t\t\t? item.isDragTarget() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-search-match={\n\t\t\t\t\ttypeof item.isMatchingSearch === \"function\"\n\t\t\t\t\t\t? item.isMatchingSearch() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\taria-expanded={item.isExpanded()}\n\t\t\t\t{...Object.fromEntries(\n\t\t\t\t\tObject.entries(otherProps).filter(([key]) => key !== \"onDragStart\"),\n\t\t\t\t)}\n\t\t\t\tonDragStart={(e) => {\n\t\t\t\t\tif ((e.target as HTMLElement).dataset.slot === \"drag-handle\") {\n\t\t\t\t\t\titem.getProps().onDragStart(e);\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Comp>\n\t\t</TreeContext.Provider>\n\t);\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: FIXME Origin UI as-is\ninterface TreeItemLabelProps<T = any>\n\textends React.HTMLAttributes<HTMLSpanElement> {\n\thideChevron?: boolean;\n\tdisableHover?: boolean;\n\titem?: ItemInstance<T>;\n\thorizontalLines?: boolean;\n}\n\nfunction TreeItemLabel<T>({\n\titem: propItem,\n\tchildren,\n\tclassName,\n\tdisableHover,\n\thorizontalLines,\n\thideChevron,\n\t...props\n}: TreeItemLabelProps<T & WithMeta>) {\n\tconst { currentItem } = useTreeContext<T & WithMeta>();\n\tconst item = propItem || currentItem;\n\n\tif (!item) {\n\t\tconsole.warn(\"TreeItemLabel: No item provided via props or context\");\n\t\treturn null;\n\t}\n\n\tconst data = item.getItemData?.();\n\tconst isLastNode = data?.meta?.lastNode;\n\tconst itemMeta = item.getItemMeta();\n\n\treturn (\n\t\t<span\n\t\t\tdata-slot=\"tree-item-label\"\n\t\t\tclassName={cn(\n\t\t\t\t\"group/tree-item-label relative select-text in-focus-visible:ring-ring/50 bg-background text-text-secondary in-data-[drag-target=true]:bg-accent flex items-center gap-2 pr-2 pl-2.5 py-1.5 text-sm transition-colors not-in-data-[folder=true]:ps-2.5 in-focus-visible:ring-[3px] in-data-[search-match=true]:bg-blue-400/20! [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n\t\t\t\t!disableHover &&\n\t\t\t\t\t\"in-data-[focus=true]:bg-bg-secondary in-data-[focus=true]:text-text-primary\",\n\t\t\t\t!disableHover &&\n\t\t\t\t\titem.isFolder() &&\n\t\t\t\t\t\"hover:bg-bg-secondary hover:text-text-primary cursor-pointer\",\n\t\t\t\tdisableHover && \"text-text-primary\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{item.isFolder() && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"self-start mt-0.5 cursor-pointer\"\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\titem.isExpanded() ? item.collapse() : item.expand();\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<ChevronDownIcon className=\"text-muted-foreground size-4 in-aria-[expanded=false]:-rotate-90\" />\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{!item.isFolder() && horizontalLines && (\n\t\t\t\t<div\n\t\t\t\t\tclassName={`w-5 min-w-5 h-px border-t mt-2 -ml-1 self-start`}\n\t\t\t\t></div>\n\t\t\t)}\n\t\t\t{item.isFolder() && item.isExpanded() && horizontalLines && (\n\t\t\t\t<div\n\t\t\t\t\tclassName={`absolute left-4.25 top-8 w-px min-h-full h-full border-l mt-2.25 self-start `}\n\t\t\t\t></div>\n\t\t\t)}\n\t\t\t{horizontalLines && (\n\t\t\t\t<div\n\t\t\t\t\tclassName={`absolute left-0 top-4.75 -m-[5px] border-t w-4 ${isLastNode ? \"h-full bg-inherit \" : \"\"} ${itemMeta.level === 0 ? \"hidden\" : \"\"}`}\n\t\t\t\t></div>\n\t\t\t)}\n\t\t\t{children ||\n\t\t\t\t(typeof item.getItemName === \"function\" ? item.getItemName() : null)}\n\t\t</span>\n\t);\n}\n\nfunction TreeDragLine({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n\tconst { tree } = useTreeContext();\n\n\tif (!tree || typeof tree.getDragLineStyle !== \"function\") {\n\t\tconsole.warn(\n\t\t\t\"TreeDragLine: No tree provided via context or tree does not have getDragLineStyle method\",\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst dragLine = tree.getDragLineStyle();\n\treturn (\n\t\t<div\n\t\t\tstyle={dragLine}\n\t\t\tclassName={cn(\n\t\t\t\t\"bg-primary before:bg-background before:border-primary absolute z-30 -mt-px h-0.5 w-[unset] before:absolute before:-top-[3px] before:left-0 before:size-2 before:rounded-full before:border-2\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport { Tree, TreeItem, TreeItemLabel, TreeDragLine, type ItemInstance };\n"],"names":["ChevronDownIcon","Slot","React","cn","TreeContext","createContext","indent","useTreeContext","useContext","Tree","tree","className","props","containerProps","getContainerProps","mergedProps","style","propStyle","otherProps","mergedStyle","Provider","value","div","data-slot","TreeItem","item","asChild","children","itemProps","getProps","getItemMeta","level","Comp","Root","currentItem","data-focus","isFocused","undefined","data-folder","isFolder","data-selected","isSelected","data-drag-target","isDragTarget","data-search-match","isMatchingSearch","aria-expanded","isExpanded","Object","fromEntries","entries","filter","key","onDragStart","e","target","dataset","slot","TreeItemLabel","propItem","disableHover","horizontalLines","hideChevron","console","warn","data","getItemData","isLastNode","meta","lastNode","itemMeta","span","button","type","onClick","collapse","expand","getItemName","TreeDragLine","getDragLineStyle","dragLine"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@health-samurai/react-components",
3
- "version": "0.0.0-alpha.7",
3
+ "version": "0.0.0-alpha.8",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import {
4
+ type AccessorKeyColumnDef,
4
5
  type ColumnDef,
5
6
  flexRender,
6
7
  getCoreRowModel,
@@ -117,4 +118,4 @@ export function DataTable<TData, TValue>({
117
118
  );
118
119
  }
119
120
 
120
- export type { ColumnDef };
121
+ export type { ColumnDef, AccessorKeyColumnDef };
@@ -15,16 +15,16 @@ type PackageSpec = {
15
15
  };
16
16
 
17
17
  type Coordinate = {
18
- id: string;
19
- packageSpec: PackageSpec;
20
- "package-spec": PackageSpec;
21
- label: string;
18
+ id?: string;
19
+ packageSpec?: PackageSpec;
20
+ "package-spec"?: PackageSpec;
21
+ label?: string;
22
22
  };
23
23
 
24
24
  type FhirStructure = {
25
25
  type?: string;
26
- min?: string;
27
- max?: string;
26
+ min?: string | number;
27
+ max?: string | number;
28
28
  lastNode?: boolean;
29
29
  isSummary?: boolean;
30
30
  isModifier?: boolean;
@@ -40,7 +40,7 @@ type FhirStructure = {
40
40
  vsCoordinate?: Coordinate;
41
41
  };
42
42
 
43
- const FiledIcon = (item: ItemInstance<TreeViewItem<FhirStructure>>) => {
43
+ function FiledIcon(item: ItemInstance<TreeViewItem<FhirStructure>>) {
44
44
  const filedType = item.getItemData()?.meta?.type;
45
45
 
46
46
  switch (filedType) {
@@ -76,7 +76,7 @@ const FiledIcon = (item: ItemInstance<TreeViewItem<FhirStructure>>) => {
76
76
  default:
77
77
  return <CustomIcon.ComplexTypeIcon />;
78
78
  }
79
- };
79
+ }
80
80
 
81
81
  const customItemFieldNameClass = cn(
82
82
  "flex",
@@ -89,7 +89,7 @@ const customItemFieldNameClass = cn(
89
89
  "in-data-[folder=true]:min-w-[calc(260px-var(--tree-padding))]",
90
90
  );
91
91
 
92
- const customItemView = (item: ItemInstance<TreeViewItem<FhirStructure>>) => {
92
+ function customItemView(item: ItemInstance<TreeViewItem<FhirStructure>>) {
93
93
  const fieldName = item.getItemData()?.name;
94
94
  const cardinalityMin = item.getItemData()?.meta?.min;
95
95
  const cardinalityMax = item.getItemData()?.meta?.max;
@@ -192,13 +192,13 @@ const customItemView = (item: ItemInstance<TreeViewItem<FhirStructure>>) => {
192
192
  </div>
193
193
  </div>
194
194
  );
195
- };
195
+ }
196
196
 
197
- const FhirStructureView = ({
197
+ function FhirStructureView({
198
198
  tree,
199
199
  }: {
200
200
  tree: Record<string, TreeViewItem<FhirStructure>>;
201
- }) => {
201
+ }) {
202
202
  const expandedItemIds = React.useMemo(() => {
203
203
  return Object.keys(tree ?? {});
204
204
  }, [tree]);
@@ -213,6 +213,8 @@ const FhirStructureView = ({
213
213
  <div className="min-w-[200px] w-[200px]">Description</div>
214
214
  </div>
215
215
  <TreeView
216
+ focusedItem={null}
217
+ onFocusedItemChange={() => {}}
216
218
  hideChevron={true}
217
219
  horizontalLines={true}
218
220
  disableHover={true}
@@ -220,10 +222,10 @@ const FhirStructureView = ({
220
222
  rootItemId="root"
221
223
  items={tree}
222
224
  customItemView={customItemView}
223
- expandedItemIds={expandedItemIds}
225
+ defaultExpandedItems={expandedItemIds}
224
226
  />
225
227
  </div>
226
228
  );
227
- };
229
+ }
228
230
 
229
231
  export { FhirStructureView, type FhirStructure };
@@ -34,7 +34,7 @@ const segmentControlItemClass = cn(
34
34
  "select-none",
35
35
  );
36
36
 
37
- const SegmentControlItem = ({ children, value }: SegmentControlItemProps) => {
37
+ function SegmentControlItem({ children, value }: SegmentControlItemProps) {
38
38
  const { defaultValue, onValueChange, name } = useContext(
39
39
  SegmentControlContext,
40
40
  );
@@ -55,14 +55,14 @@ const SegmentControlItem = ({ children, value }: SegmentControlItemProps) => {
55
55
  </label>
56
56
  </div>
57
57
  );
58
- };
58
+ }
59
59
 
60
- const SegmentControl = ({
60
+ function SegmentControl({
61
61
  children,
62
62
  defaultValue,
63
63
  onValueChange,
64
64
  name,
65
- }: SegmentControlProps & { children?: ReactNode }) => {
65
+ }: SegmentControlProps & { children?: ReactNode }) {
66
66
  const contextValue: SegmentControlContextType = {
67
67
  ...(defaultValue !== undefined && { defaultValue }),
68
68
  ...(onValueChange !== undefined && { onValueChange }),
@@ -76,6 +76,6 @@ const SegmentControl = ({
76
76
  </div>
77
77
  </SegmentControlContext.Provider>
78
78
  );
79
- };
79
+ }
80
80
 
81
81
  export { SegmentControl, SegmentControlItem };
@@ -10,8 +10,8 @@ const splitButtonStyles = cn(
10
10
  "*:data-[slot=dropdown-menu-trigger]:border-l-0",
11
11
  );
12
12
 
13
- const SplitButton = ({ children }: { children: React.ReactNode }) => {
13
+ function SplitButton({ children }: { children: React.ReactNode }) {
14
14
  return <div className={splitButtonStyles}>{children}</div>;
15
- };
15
+ }
16
16
 
17
17
  export { SplitButton };
@@ -160,14 +160,14 @@ export const Default: Story = {
160
160
  args: {
161
161
  items: items,
162
162
  rootItemId: "root",
163
- selectedItemId: "request9",
164
- expandedItemIds: ["collection3"],
165
- onSelectItem: (a) => action("onSelectItem")(a),
163
+ focusedItem: "request9",
164
+ defaultExpandedItems: ["collection3"],
165
+ onFocusedItemChange: (a) => action("onSelectItem")(a),
166
166
  },
167
167
  render: (args) => <TreeView {...args} />,
168
168
  };
169
169
 
170
- const customItemView = (item: ItemInstance<TreeViewItem<ItemMeta>>) => {
170
+ function customItemView(item: ItemInstance<TreeViewItem<ItemMeta>>) {
171
171
  const isRootLevel = item.getItemMeta().level === 0;
172
172
  const hasChildren = item.getItemData()?.children !== undefined;
173
173
  const requestMethhod = item.getItemData()?.meta?.method;
@@ -250,15 +250,15 @@ const customItemView = (item: ItemInstance<TreeViewItem<ItemMeta>>) => {
250
250
  </div>
251
251
  </div>
252
252
  );
253
- };
253
+ }
254
254
 
255
255
  export const CustomItemView: Story = {
256
256
  args: {
257
257
  items: items,
258
258
  rootItemId: "root",
259
- selectedItemId: "request11",
260
- expandedItemIds: ["collection3", "collection4"],
261
- onSelectItem: (a) => action("onSelectItem")(a.getItemData()?.name),
259
+ focusedItem: "request11",
260
+ defaultExpandedItems: ["collection3", "collection4"],
261
+ onFocusedItemChange: (a) => action("onSelectItem")(a ? items[a]?.name : a),
262
262
  customItemView: customItemView,
263
263
  },
264
264
  render: (args) => <TreeView {...args} />,
@@ -3,7 +3,7 @@ import type {
3
3
  ItemInstance,
4
4
  TreeConfig,
5
5
  TreeInstance,
6
- TreeState,
6
+ Updater,
7
7
  } from "@headless-tree/core";
8
8
  import {
9
9
  createOnDropHandler,
@@ -14,7 +14,7 @@ import {
14
14
  syncDataLoaderFeature,
15
15
  } from "@headless-tree/core";
16
16
  import { useTree } from "@headless-tree/react";
17
- import React, { useEffect } from "react";
17
+ import React from "react";
18
18
  import { Tree, TreeItem, TreeItemLabel } from "#shadcn/components/ui/tree";
19
19
  import { cn } from "#shadcn/lib/utils.js";
20
20
 
@@ -45,45 +45,46 @@ interface TreeViewItem<T> {
45
45
 
46
46
  const customClickBehavior: FeatureImplementation = {
47
47
  itemInstance: {
48
- getProps: ({ tree, item, prev }) => ({
49
- ...prev?.(),
50
- onClick: () => {
51
- item.primaryAction();
52
- if (item.isExpanded()) {
53
- item.collapse();
54
- } else {
55
- item.expand();
56
- }
57
- if (!item.isFolder()) {
58
- tree.setSelectedItems([item.getItemMeta().itemId]);
59
- }
60
- },
61
- }),
48
+ getProps: ({ item, prev }) => {
49
+ return {
50
+ ...prev?.(),
51
+ onClick: () => {
52
+ item.setFocused();
53
+ item.primaryAction();
54
+ },
55
+ };
56
+ },
62
57
  },
63
58
  };
64
59
 
65
60
  const indent = 22;
66
61
 
67
- function TreeView<T>({
68
- rootItemId,
69
- items,
70
- selectedItemId,
71
- expandedItemIds,
72
- onSelectItem,
73
- customItemView,
74
- onRename,
75
- disableHover,
76
- zebra,
77
- horizontalLines,
78
- hideChevron,
79
- itemLabelClassFn,
80
- canReorder,
81
- onDropFn,
82
- }: {
62
+ type ExpansionPropsUncontrolled = {
63
+ defaultExpandedItems?: string[];
64
+ expandedItems?: never;
65
+ onExpandedItemsChange?: never;
66
+ };
67
+ type ExpansionPropsControlled = {
68
+ defaultExpandedItems?: never;
69
+ expandedItems: string[];
70
+ onExpandedItemsChange: (items: string[]) => void;
71
+ };
72
+ type ExpansionProps = ExpansionPropsUncontrolled | ExpansionPropsControlled;
73
+
74
+ type FocusPropsUncontrolled = {
75
+ defaultFocusedItem?: string;
76
+ focusedItem?: never;
77
+ onFocusedItemChange?: never;
78
+ };
79
+ type FocusPropsControlled = {
80
+ defaultFocusedItem?: never;
81
+ focusedItem: string | null;
82
+ onFocusedItemChange: (item: string | null) => void;
83
+ };
84
+ type FocusProps = FocusPropsUncontrolled | FocusPropsControlled;
85
+
86
+ type TreeViewProps<T> = {
83
87
  rootItemId: string;
84
- selectedItemId?: string;
85
- expandedItemIds?: string[];
86
- onSelectItem?: (item: ItemInstance<TreeViewItem<T>>) => void;
87
88
  items: Record<string, TreeViewItem<T>>;
88
89
  customItemView?: (
89
90
  item: ItemInstance<TreeViewItem<T>>,
@@ -103,18 +104,68 @@ function TreeView<T>({
103
104
  item: ItemInstance<TreeViewItem<T>>,
104
105
  newChildren: string[],
105
106
  ) => void;
106
- }) {
107
+ } & ExpansionProps &
108
+ FocusProps;
109
+
110
+ function TreeView<T>({
111
+ rootItemId,
112
+ items,
113
+ defaultFocusedItem,
114
+ focusedItem,
115
+ onFocusedItemChange,
116
+ defaultExpandedItems,
117
+ expandedItems,
118
+ onExpandedItemsChange,
119
+ customItemView,
120
+ onRename,
121
+ disableHover,
122
+ zebra,
123
+ horizontalLines,
124
+ hideChevron,
125
+ itemLabelClassFn,
126
+ canReorder,
127
+ onDropFn,
128
+ }: TreeViewProps<T>) {
107
129
  "use no memo";
108
- const [state, setState] = React.useState<Partial<TreeState<TreeViewItem<T>>>>(
109
- {},
110
- );
130
+
131
+ const initialExpandedItems = defaultExpandedItems ?? expandedItems;
132
+ const initialFocusedItem = defaultFocusedItem ?? focusedItem;
133
+
134
+ const setExpandedItems =
135
+ expandedItems !== undefined && onExpandedItemsChange !== undefined
136
+ ? (updater: Updater<string[]>) => {
137
+ const newVal =
138
+ updater instanceof Function ? updater(expandedItems) : updater;
139
+
140
+ onExpandedItemsChange(newVal);
141
+ }
142
+ : undefined;
143
+
144
+ const setFocusedItem =
145
+ focusedItem !== undefined && onFocusedItemChange !== undefined
146
+ ? (updater: Updater<string | null>) => {
147
+ const newVal =
148
+ updater instanceof Function ? updater(focusedItem) : updater;
149
+
150
+ onFocusedItemChange(newVal);
151
+ }
152
+ : undefined;
153
+
111
154
  const treeConfig: TreeConfig<TreeViewItem<T>> = {
112
155
  initialState: {
113
- selectedItems: selectedItemId ? [selectedItemId] : [],
114
- expandedItems: expandedItemIds ?? [],
156
+ ...(initialExpandedItems !== undefined
157
+ ? { expandedItems: initialExpandedItems }
158
+ : {}),
159
+ ...(initialFocusedItem !== undefined
160
+ ? { focusedItem: initialFocusedItem }
161
+ : {}),
115
162
  },
116
- state,
117
- setState,
163
+ state: {
164
+ ...(expandedItems !== undefined ? { expandedItems } : {}),
165
+ ...(focusedItem !== undefined ? { focusedItem } : {}),
166
+ },
167
+ ...(setExpandedItems !== undefined ? { setExpandedItems } : {}),
168
+ ...(setFocusedItem !== undefined ? { setFocusedItem } : {}),
118
169
  indent,
119
170
  rootItemId: rootItemId,
120
171
  isItemFolder: (item: ItemInstance<TreeViewItem<T>>) =>
@@ -130,9 +181,9 @@ function TreeView<T>({
130
181
  syncDataLoaderFeature,
131
182
  hotkeysCoreFeature,
132
183
  selectionFeature,
133
- customClickBehavior,
134
184
  renamingFeature,
135
185
  dragAndDropFeature,
186
+ customClickBehavior,
136
187
  ],
137
188
  canReorder: canReorder ?? false,
138
189
  onDrop: createOnDropHandler((item, newChildren) => {
@@ -142,28 +193,11 @@ function TreeView<T>({
142
193
 
143
194
  const tree = useTree<TreeViewItem<T>>(treeConfig);
144
195
 
145
- // biome-ignore lint/correctness/useExhaustiveDependencies: We must have explicit sync here
146
- useEffect(() => {
196
+ const [prevItems, setPrevItems] = React.useState<null | typeof items>(null);
197
+ if (prevItems !== items) {
147
198
  tree.rebuildTree();
148
- }, [items]);
149
-
150
- useEffect(() => {
151
- setState((currentState) => {
152
- return {
153
- ...currentState,
154
- selectedItems: selectedItemId ? [selectedItemId] : [],
155
- };
156
- });
157
- }, [selectedItemId]);
158
-
159
- useEffect(() => {
160
- setState((currentState) => {
161
- return {
162
- ...currentState,
163
- expandedItems: expandedItemIds ?? [],
164
- };
165
- });
166
- }, [expandedItemIds]);
199
+ setPrevItems(items);
200
+ }
167
201
 
168
202
  return (
169
203
  <Tree tree={tree} indent={indent}>
@@ -183,7 +217,7 @@ function TreeView<T>({
183
217
  hideChevron={hideChevron ?? false}
184
218
  disableHover={disableHover ?? false}
185
219
  className={cn(treeItemLabelStyle, itemLabelClassFn?.(item))}
186
- onClick={() => onSelectItem?.(item)}
220
+ // onClick={() => onSelectItem?.(item)}
187
221
  horizontalLines={horizontalLines ?? false}
188
222
  >
189
223
  {customItemView
package/src/icons.tsx CHANGED
@@ -1,4 +1,4 @@
1
- export const PlayIcon = () => {
1
+ export function PlayIcon() {
2
2
  return (
3
3
  <svg
4
4
  width="16"
@@ -16,9 +16,9 @@ export const PlayIcon = () => {
16
16
  />
17
17
  </svg>
18
18
  );
19
- };
19
+ }
20
20
 
21
- export const PinIcon = () => {
21
+ export function PinIcon() {
22
22
  return (
23
23
  <svg
24
24
  width="16"
@@ -42,9 +42,9 @@ export const PinIcon = () => {
42
42
  />
43
43
  </svg>
44
44
  );
45
- };
45
+ }
46
46
 
47
- export const ResourceIcon = () => {
47
+ export function ResourceIcon() {
48
48
  return (
49
49
  <svg
50
50
  width="16"
@@ -92,9 +92,9 @@ export const ResourceIcon = () => {
92
92
  />
93
93
  </svg>
94
94
  );
95
- };
95
+ }
96
96
 
97
- export const BackoneElementIcon = () => {
97
+ export function BackoneElementIcon() {
98
98
  return (
99
99
  <svg
100
100
  width="16"
@@ -114,9 +114,9 @@ export const BackoneElementIcon = () => {
114
114
  />
115
115
  </svg>
116
116
  );
117
- };
117
+ }
118
118
 
119
- export const TypCodeIcon = () => {
119
+ export function TypCodeIcon() {
120
120
  return (
121
121
  <svg
122
122
  width="16"
@@ -164,9 +164,9 @@ export const TypCodeIcon = () => {
164
164
  />
165
165
  </svg>
166
166
  );
167
- };
167
+ }
168
168
 
169
- export const ReferenceIcon = () => {
169
+ export function ReferenceIcon() {
170
170
  return (
171
171
  <svg
172
172
  width="16"
@@ -200,9 +200,9 @@ export const ReferenceIcon = () => {
200
200
  />
201
201
  </svg>
202
202
  );
203
- };
203
+ }
204
204
 
205
- export const ComplexTypeIcon = () => {
205
+ export function ComplexTypeIcon() {
206
206
  return (
207
207
  <svg
208
208
  width="16"
@@ -248,9 +248,9 @@ export const ComplexTypeIcon = () => {
248
248
  </defs>
249
249
  </svg>
250
250
  );
251
- };
251
+ }
252
252
 
253
- export const UnionIcon = () => {
253
+ export function UnionIcon() {
254
254
  return (
255
255
  <svg
256
256
  width="16"
@@ -284,4 +284,4 @@ export const UnionIcon = () => {
284
284
  </g>
285
285
  </svg>
286
286
  );
287
- };
287
+ }
package/src/index.tsx CHANGED
@@ -1,5 +1,5 @@
1
1
  // Shadcn Components
2
- export { toast } from "sonner";
2
+ export { type ExternalToast, toast } from "sonner";
3
3
  export * from "./components/button-dropdown";
4
4
  export * from "./components/code-editor";
5
5
  export * from "./components/copy-icon";
@@ -68,7 +68,7 @@ function ChartContainer({
68
68
  );
69
69
  }
70
70
 
71
- const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
71
+ function ChartStyle({ id, config }: { id: string; config: ChartConfig }) {
72
72
  const colorConfig = Object.entries(config).filter(
73
73
  ([, config]) => config.theme || config.color,
74
74
  );
@@ -100,7 +100,7 @@ ${colorConfig
100
100
  }}
101
101
  />
102
102
  );
103
- };
103
+ }
104
104
 
105
105
  const ChartTooltip = RechartsPrimitive.Tooltip;
106
106
 
@@ -56,17 +56,14 @@ export function Combobox({
56
56
 
57
57
  const selectedOption = options.find((option) => option.value === value);
58
58
 
59
- // Reset search when closing and auto-focus when opening
60
- React.useEffect(() => {
61
- if (!open) {
59
+ const changeOpen = (newOpen: boolean) => {
60
+ if (!newOpen) {
62
61
  setSearchValue("");
63
62
  } else {
64
- // Auto-focus on search input when opening
65
- setTimeout(() => {
66
- inputRef.current?.focus();
67
- }, 0);
63
+ inputRef.current?.focus();
68
64
  }
69
- }, [open]);
65
+ setOpen(newOpen);
66
+ };
70
67
 
71
68
  return (
72
69
  <Select
@@ -74,7 +71,7 @@ export function Combobox({
74
71
  {...(onValueChange && { onValueChange })}
75
72
  disabled={disabled}
76
73
  open={open}
77
- onOpenChange={setOpen}
74
+ onOpenChange={changeOpen}
78
75
  >
79
76
  <SelectTrigger className={className}>
80
77
  <SelectValue placeholder={placeholder}>
@@ -99,7 +96,7 @@ export function Combobox({
99
96
  data-state={value === option.value ? "checked" : undefined}
100
97
  onSelect={(currentValue) => {
101
98
  onValueChange?.(currentValue);
102
- setOpen(false);
99
+ changeOpen(false);
103
100
  }}
104
101
  >
105
102
  {option.label}
@@ -176,19 +173,17 @@ export function MultiCombobox({
176
173
  };
177
174
 
178
175
  // Reset search when closing and auto-focus when opening
179
- React.useEffect(() => {
180
- if (!open) {
176
+ const changeOpen = (newOpen: boolean) => {
177
+ if (!newOpen) {
181
178
  setSearchValue("");
182
179
  } else {
183
- // Auto-focus on search input when opening
184
- setTimeout(() => {
185
- inputRef.current?.focus();
186
- }, 0);
180
+ inputRef.current?.focus();
187
181
  }
188
- }, [open]);
182
+ setOpen(newOpen);
183
+ };
189
184
 
190
185
  return (
191
- <Select open={open} onOpenChange={setOpen}>
186
+ <Select open={open} onOpenChange={changeOpen}>
192
187
  <SelectTrigger
193
188
  className={`${className} ${displayText ? "!text-text-primary" : undefined}`}
194
189
  disabled={disabled}