@douglasneuroinformatics/libui 6.2.1 → 6.3.1

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 (112) hide show
  1. package/dist/components/ComboBox/ComboBox.d.ts +27 -0
  2. package/dist/components/ComboBox/ComboBox.d.ts.map +1 -0
  3. package/dist/components/ComboBox/ComboBox.js +37 -0
  4. package/dist/components/ComboBox/ComboBox.js.map +1 -0
  5. package/dist/components/ComboBox/ComboBoxChips.d.ts +9 -0
  6. package/dist/components/ComboBox/ComboBoxChips.d.ts.map +1 -0
  7. package/dist/components/ComboBox/ComboBoxChips.js +17 -0
  8. package/dist/components/ComboBox/ComboBoxChips.js.map +1 -0
  9. package/dist/components/ComboBox/ComboBoxClear.d.ts +4 -0
  10. package/dist/components/ComboBox/ComboBoxClear.d.ts.map +1 -0
  11. package/dist/components/ComboBox/ComboBoxClear.js +10 -0
  12. package/dist/components/ComboBox/ComboBoxClear.js.map +1 -0
  13. package/dist/components/ComboBox/ComboBoxCollection.d.ts +4 -0
  14. package/dist/components/ComboBox/ComboBoxCollection.d.ts.map +1 -0
  15. package/dist/components/ComboBox/ComboBoxCollection.js +7 -0
  16. package/dist/components/ComboBox/ComboBoxCollection.js.map +1 -0
  17. package/dist/components/ComboBox/ComboBoxContent.d.ts +4 -0
  18. package/dist/components/ComboBox/ComboBoxContent.d.ts.map +1 -0
  19. package/dist/components/ComboBox/ComboBoxContent.js +8 -0
  20. package/dist/components/ComboBox/ComboBoxContent.js.map +1 -0
  21. package/dist/components/ComboBox/ComboBoxEmpty.d.ts +4 -0
  22. package/dist/components/ComboBox/ComboBoxEmpty.d.ts.map +1 -0
  23. package/dist/components/ComboBox/ComboBoxEmpty.js +8 -0
  24. package/dist/components/ComboBox/ComboBoxEmpty.js.map +1 -0
  25. package/dist/components/ComboBox/ComboBoxGroup.d.ts +4 -0
  26. package/dist/components/ComboBox/ComboBoxGroup.d.ts.map +1 -0
  27. package/dist/components/ComboBox/ComboBoxGroup.js +8 -0
  28. package/dist/components/ComboBox/ComboBoxGroup.js.map +1 -0
  29. package/dist/components/ComboBox/ComboBoxInput.d.ts +7 -0
  30. package/dist/components/ComboBox/ComboBoxInput.d.ts.map +1 -0
  31. package/dist/components/ComboBox/ComboBoxInput.js +17 -0
  32. package/dist/components/ComboBox/ComboBoxInput.js.map +1 -0
  33. package/dist/components/ComboBox/ComboBoxItem.d.ts +4 -0
  34. package/dist/components/ComboBox/ComboBoxItem.d.ts.map +1 -0
  35. package/dist/components/ComboBox/ComboBoxItem.js +9 -0
  36. package/dist/components/ComboBox/ComboBoxItem.js.map +1 -0
  37. package/dist/components/ComboBox/ComboBoxLabel.d.ts +4 -0
  38. package/dist/components/ComboBox/ComboBoxLabel.d.ts.map +1 -0
  39. package/dist/components/ComboBox/ComboBoxLabel.js +8 -0
  40. package/dist/components/ComboBox/ComboBoxLabel.js.map +1 -0
  41. package/dist/components/ComboBox/ComboBoxList.d.ts +4 -0
  42. package/dist/components/ComboBox/ComboBoxList.d.ts.map +1 -0
  43. package/dist/components/ComboBox/ComboBoxList.js +8 -0
  44. package/dist/components/ComboBox/ComboBoxList.js.map +1 -0
  45. package/dist/components/ComboBox/ComboBoxSeparator.d.ts +4 -0
  46. package/dist/components/ComboBox/ComboBoxSeparator.d.ts.map +1 -0
  47. package/dist/components/ComboBox/ComboBoxSeparator.js +8 -0
  48. package/dist/components/ComboBox/ComboBoxSeparator.js.map +1 -0
  49. package/dist/components/ComboBox/ComboBoxTrigger.d.ts +4 -0
  50. package/dist/components/ComboBox/ComboBoxTrigger.d.ts.map +1 -0
  51. package/dist/components/ComboBox/ComboBoxTrigger.js +9 -0
  52. package/dist/components/ComboBox/ComboBoxTrigger.js.map +1 -0
  53. package/dist/components/ComboBox/ComboBoxValue.d.ts +4 -0
  54. package/dist/components/ComboBox/ComboBoxValue.d.ts.map +1 -0
  55. package/dist/components/ComboBox/ComboBoxValue.js +7 -0
  56. package/dist/components/ComboBox/ComboBoxValue.js.map +1 -0
  57. package/dist/components/DataTable/DataTableBody.d.ts.map +1 -1
  58. package/dist/components/DataTable/DataTableBody.js +1 -1
  59. package/dist/components/DataTable/DataTableBody.js.map +1 -1
  60. package/dist/components/DataTable/DataTableHead.d.ts.map +1 -1
  61. package/dist/components/DataTable/DataTableHead.js +3 -3
  62. package/dist/components/DataTable/DataTableHead.js.map +1 -1
  63. package/dist/components/InputGroup/InputGroup.d.ts +4 -0
  64. package/dist/components/InputGroup/InputGroup.d.ts.map +1 -0
  65. package/dist/components/InputGroup/InputGroup.js +8 -0
  66. package/dist/components/InputGroup/InputGroup.js.map +1 -0
  67. package/dist/components/InputGroup/InputGroupAddon.d.ts +8 -0
  68. package/dist/components/InputGroup/InputGroupAddon.d.ts.map +1 -0
  69. package/dist/components/InputGroup/InputGroupAddon.js +23 -0
  70. package/dist/components/InputGroup/InputGroupAddon.js.map +1 -0
  71. package/dist/components/InputGroup/InputGroupButton.d.ts +9 -0
  72. package/dist/components/InputGroup/InputGroupButton.d.ts.map +1 -0
  73. package/dist/components/InputGroup/InputGroupButton.js +29 -0
  74. package/dist/components/InputGroup/InputGroupButton.js.map +1 -0
  75. package/dist/components/InputGroup/InputGroupInput.d.ts +4 -0
  76. package/dist/components/InputGroup/InputGroupInput.d.ts.map +1 -0
  77. package/dist/components/InputGroup/InputGroupInput.js +9 -0
  78. package/dist/components/InputGroup/InputGroupInput.js.map +1 -0
  79. package/dist/components/InputGroup/InputGroupText.d.ts +4 -0
  80. package/dist/components/InputGroup/InputGroupText.d.ts.map +1 -0
  81. package/dist/components/InputGroup/InputGroupText.js +8 -0
  82. package/dist/components/InputGroup/InputGroupText.js.map +1 -0
  83. package/dist/components/InputGroup/InputGroupTextArea.d.ts +4 -0
  84. package/dist/components/InputGroup/InputGroupTextArea.d.ts.map +1 -0
  85. package/dist/components/InputGroup/InputGroupTextArea.js +9 -0
  86. package/dist/components/InputGroup/InputGroupTextArea.js.map +1 -0
  87. package/package.json +2 -1
  88. package/src/components/ComboBox/ComboBox.stories.tsx +31 -0
  89. package/src/components/ComboBox/ComboBox.tsx +41 -0
  90. package/src/components/ComboBox/ComboBoxChips.tsx +69 -0
  91. package/src/components/ComboBox/ComboBoxClear.tsx +23 -0
  92. package/src/components/ComboBox/ComboBoxCollection.tsx +7 -0
  93. package/src/components/ComboBox/ComboBoxContent.tsx +39 -0
  94. package/src/components/ComboBox/ComboBoxEmpty.tsx +18 -0
  95. package/src/components/ComboBox/ComboBoxGroup.tsx +9 -0
  96. package/src/components/ComboBox/ComboBoxInput.tsx +51 -0
  97. package/src/components/ComboBox/ComboBoxItem.tsx +28 -0
  98. package/src/components/ComboBox/ComboBoxLabel.tsx +15 -0
  99. package/src/components/ComboBox/ComboBoxList.tsx +18 -0
  100. package/src/components/ComboBox/ComboBoxSeparator.tsx +15 -0
  101. package/src/components/ComboBox/ComboBoxTrigger.tsx +23 -0
  102. package/src/components/ComboBox/ComboBoxValue.tsx +7 -0
  103. package/src/components/DataTable/DataTable.stories.tsx +19 -1
  104. package/src/components/DataTable/DataTableBody.tsx +5 -1
  105. package/src/components/DataTable/DataTableHead.tsx +5 -3
  106. package/src/components/InputGroup/InputGroup.stories.tsx +27 -0
  107. package/src/components/InputGroup/InputGroup.tsx +19 -0
  108. package/src/components/InputGroup/InputGroupAddon.tsx +42 -0
  109. package/src/components/InputGroup/InputGroupButton.tsx +50 -0
  110. package/src/components/InputGroup/InputGroupInput.tsx +20 -0
  111. package/src/components/InputGroup/InputGroupText.tsx +17 -0
  112. package/src/components/InputGroup/InputGroupTextArea.tsx +20 -0
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ import type { VariantProps } from 'class-variance-authority';
3
+ import { Button } from '../Button/Button.tsx';
4
+ declare const inputGroupButtonVariants: (props?: ({
5
+ size?: "sm" | "xs" | "icon-sm" | "icon-xs" | null | undefined;
6
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
+ declare const InputGroupButton: ({ className, size, type, variant, ...props }: Omit<React.ComponentProps<typeof Button>, "size"> & VariantProps<typeof inputGroupButtonVariants>) => import("react/jsx-runtime").JSX.Element;
8
+ export { InputGroupButton };
9
+ //# sourceMappingURL=InputGroupButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputGroupButton.d.ts","sourceRoot":"","sources":["../../../src/components/InputGroup/InputGroupButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAI7D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,QAAA,MAAM,wBAAwB;;8EAY5B,CAAC;AASH,QAAA,MAAM,gBAAgB,GAAI,8CAMvB,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC,OAAO,wBAAwB,CAAC,4CAWnG,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { cva } from 'class-variance-authority';
4
+ import { cn } from '#utils';
5
+ import { Button } from "../Button/Button.js";
6
+ const inputGroupButtonVariants = cva('gap-2 text-sm flex items-center shadow-none', {
7
+ defaultVariants: {
8
+ size: 'xs'
9
+ },
10
+ variants: {
11
+ size: {
12
+ 'icon-sm': 'size-8 p-0 has-[>svg]:p-0',
13
+ 'icon-xs': 'size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0',
14
+ sm: '',
15
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5"
16
+ }
17
+ }
18
+ });
19
+ const buttonSizeMap = {
20
+ 'icon-sm': 'icon',
21
+ 'icon-xs': 'icon',
22
+ sm: 'sm',
23
+ xs: 'sm'
24
+ };
25
+ const InputGroupButton = ({ className, size = 'xs', type = 'button', variant = 'ghost', ...props }) => {
26
+ return (_jsx(Button, { className: cn(inputGroupButtonVariants({ size }), className), "data-size": size, size: buttonSizeMap[size ?? 'xs'], type: type, variant: variant, ...props }));
27
+ };
28
+ export { InputGroupButton };
29
+ //# sourceMappingURL=InputGroupButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputGroupButton.js","sourceRoot":"","sources":["../../../src/components/InputGroup/InputGroupButton.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAG/C,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAsB,CAAC;AAE9C,MAAM,wBAAwB,GAAG,GAAG,CAAC,6CAA6C,EAAE;IAClF,eAAe,EAAE;QACf,IAAI,EAAE,IAAI;KACX;IACD,QAAQ,EAAE;QACR,IAAI,EAAE;YACJ,SAAS,EAAE,2BAA2B;YACtC,SAAS,EAAE,6DAA6D;YACxE,EAAE,EAAE,EAAE;YACN,EAAE,EAAE,2FAA2F;SAChG;KACF;CACF,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG;IACpB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;IACjB,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;CACA,CAAC;AAEX,MAAM,gBAAgB,GAAG,CAAC,EACxB,SAAS,EACT,IAAI,GAAG,IAAI,EACX,IAAI,GAAG,QAAQ,EACf,OAAO,GAAG,OAAO,EACjB,GAAG,KAAK,EAC0F,EAAE,EAAE;IACtG,OAAO,CACL,KAAC,MAAM,IACL,SAAS,EAAE,EAAE,CAAC,wBAAwB,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,eACjD,IAAI,EACf,IAAI,EAAE,aAAa,CAAC,IAAI,IAAI,IAAI,CAAC,EACjC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,KACZ,KAAK,GACT,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ declare const InputGroupInput: ({ className, ...props }: React.ComponentProps<"input">) => import("react/jsx-runtime").JSX.Element;
3
+ export { InputGroupInput };
4
+ //# sourceMappingURL=InputGroupInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputGroupInput.d.ts","sourceRoot":"","sources":["../../../src/components/InputGroup/InputGroupInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,QAAA,MAAM,eAAe,GAAI,yBAAyB,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,4CAW9E,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { cn } from '#utils';
4
+ import { Input } from "../Input/Input.js";
5
+ const InputGroupInput = ({ className, ...props }) => {
6
+ return (_jsx(Input, { className: cn('flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent', className), "data-slot": "input-group-control", ...props }));
7
+ };
8
+ export { InputGroupInput };
9
+ //# sourceMappingURL=InputGroupInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputGroupInput.js","sourceRoot":"","sources":["../../../src/components/InputGroup/InputGroupInput.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAoB,CAAC;AAE3C,MAAM,eAAe,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAiC,EAAE,EAAE;IACjF,OAAO,CACL,KAAC,KAAK,IACJ,SAAS,EAAE,EAAE,CACX,kLAAkL,EAClL,SAAS,CACV,eACS,qBAAqB,KAC3B,KAAK,GACT,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ declare const InputGroupText: ({ className, ...props }: React.ComponentProps<"span">) => import("react/jsx-runtime").JSX.Element;
3
+ export { InputGroupText };
4
+ //# sourceMappingURL=InputGroupText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputGroupText.d.ts","sourceRoot":"","sources":["../../../src/components/InputGroup/InputGroupText.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,QAAA,MAAM,cAAc,GAAI,yBAAyB,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,4CAU5E,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { cn } from '#utils';
4
+ const InputGroupText = ({ className, ...props }) => {
5
+ return (_jsx("span", { className: cn("text-muted-foreground flex items-center gap-2 text-sm [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", className), ...props }));
6
+ };
7
+ export { InputGroupText };
8
+ //# sourceMappingURL=InputGroupText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputGroupText.js","sourceRoot":"","sources":["../../../src/components/InputGroup/InputGroupText.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE5B,MAAM,cAAc,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAgC,EAAE,EAAE;IAC/E,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,wHAAwH,EACxH,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ declare const InputGroupTextArea: ({ className, ...props }: React.ComponentProps<"textarea">) => import("react/jsx-runtime").JSX.Element;
3
+ export { InputGroupTextArea };
4
+ //# sourceMappingURL=InputGroupTextArea.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputGroupTextArea.d.ts","sourceRoot":"","sources":["../../../src/components/InputGroup/InputGroupTextArea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,QAAA,MAAM,kBAAkB,GAAI,yBAAyB,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,4CAWpF,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { cn } from '#utils';
4
+ import { TextArea } from "../TextArea/TextArea.js";
5
+ const InputGroupTextArea = ({ className, ...props }) => {
6
+ return (_jsx(TextArea, { className: cn('flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent', className), "data-slot": "input-group-control", ...props }));
7
+ };
8
+ export { InputGroupTextArea };
9
+ //# sourceMappingURL=InputGroupTextArea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputGroupTextArea.js","sourceRoot":"","sources":["../../../src/components/InputGroup/InputGroupTextArea.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAA0B,CAAC;AAEpD,MAAM,kBAAkB,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAoC,EAAE,EAAE;IACvF,OAAO,CACL,KAAC,QAAQ,IACP,SAAS,EAAE,EAAE,CACX,mMAAmM,EACnM,SAAS,CACV,eACS,qBAAqB,KAC3B,KAAK,GACT,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@douglasneuroinformatics/libui",
3
3
  "type": "module",
4
- "version": "6.2.1",
4
+ "version": "6.3.1",
5
5
  "packageManager": "pnpm@10.7.1",
6
6
  "description": "Generic UI components for DNP projects, built using React and Tailwind CSS",
7
7
  "author": "Joshua Unrau",
@@ -97,6 +97,7 @@
97
97
  "zod": "^3.25.x"
98
98
  },
99
99
  "dependencies": {
100
+ "@base-ui/react": "^1.2.0",
100
101
  "@douglasneuroinformatics/libjs": "^3.0.2",
101
102
  "@douglasneuroinformatics/libui-form-types": "^0.11.0",
102
103
  "@radix-ui/react-accordion": "^1.2.3",
@@ -0,0 +1,31 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { ComboBox } from './ComboBox.tsx';
4
+
5
+ type Story = StoryObj<typeof ComboBox>;
6
+
7
+ const frameworks: string[] = ['Next.js', 'SvelteKit', 'Nuxt.js', 'Remix', 'Astro'];
8
+
9
+ export default {
10
+ args: {
11
+ children: (
12
+ <ComboBox items={frameworks}>
13
+ <ComboBox.Input placeholder="Select a framework" />
14
+ <ComboBox.Content>
15
+ <ComboBox.Empty>No items found.</ComboBox.Empty>
16
+ <ComboBox.List>
17
+ {(item: string) => (
18
+ <ComboBox.Item key={item} value={item}>
19
+ {item}
20
+ </ComboBox.Item>
21
+ )}
22
+ </ComboBox.List>
23
+ </ComboBox.Content>
24
+ </ComboBox>
25
+ )
26
+ },
27
+ component: ComboBox,
28
+ tags: ['autodocs']
29
+ } as Meta<typeof ComboBox>;
30
+
31
+ export const Default: Story = {};
@@ -0,0 +1,41 @@
1
+ import * as React from 'react';
2
+
3
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
4
+
5
+ import { ComboboxChip, ComboboxChips, ComboboxChipsInput } from './ComboBoxChips.tsx';
6
+ import { ComboboxClear } from './ComboBoxClear.tsx';
7
+ import { ComboboxCollection } from './ComboBoxCollection.tsx';
8
+ import { ComboboxContent } from './ComboBoxContent.tsx';
9
+ import { ComboboxEmpty } from './ComboBoxEmpty.tsx';
10
+ import { ComboboxGroup } from './ComboBoxGroup.tsx';
11
+ import { ComboboxInput } from './ComboBoxInput.tsx';
12
+ import { ComboboxItem } from './ComboBoxItem.tsx';
13
+ import { ComboboxLabel } from './ComboBoxLabel.tsx';
14
+ import { ComboboxList } from './ComboBoxList.tsx';
15
+ import { ComboboxSeparator } from './ComboBoxSeparator.tsx';
16
+ import { ComboboxTrigger } from './ComboBoxTrigger.tsx';
17
+ import { ComboboxValue } from './ComboBoxValue.tsx';
18
+
19
+ function useComboboxAnchor() {
20
+ return React.useRef<HTMLDivElement | null>(null);
21
+ }
22
+
23
+ export { useComboboxAnchor };
24
+
25
+ export const ComboBox = Object.assign(ComboboxPrimitive.Root.bind(null), {
26
+ Chip: ComboboxChip,
27
+ Chips: ComboboxChips,
28
+ ChipsInput: ComboboxChipsInput,
29
+ Clear: ComboboxClear,
30
+ Collection: ComboboxCollection,
31
+ Content: ComboboxContent,
32
+ Empty: ComboboxEmpty,
33
+ Group: ComboboxGroup,
34
+ Input: ComboboxInput,
35
+ Item: ComboboxItem,
36
+ Label: ComboboxLabel,
37
+ List: ComboboxList,
38
+ Separator: ComboboxSeparator,
39
+ Trigger: ComboboxTrigger,
40
+ Value: ComboboxValue
41
+ });
@@ -0,0 +1,69 @@
1
+ import * as React from 'react';
2
+
3
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
4
+ import { XIcon } from 'lucide-react';
5
+
6
+ import { cn } from '#utils';
7
+
8
+ import { Button } from '../Button/Button.tsx';
9
+
10
+ const ComboboxChips = ({
11
+ className,
12
+ ...props
13
+ }: ComboboxPrimitive.Chips.Props & React.ComponentPropsWithRef<typeof ComboboxPrimitive.Chips>) => {
14
+ return (
15
+ <ComboboxPrimitive.Chips
16
+ className={cn(
17
+ 'dark:bg-input/30 border-input focus-within:border-ring focus-within:ring-ring/50 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive dark:has-aria-invalid:border-destructive/50 flex min-h-8 flex-wrap items-center gap-1 rounded-lg border bg-transparent bg-clip-padding px-2.5 py-1 text-sm transition-colors focus-within:ring-3 has-aria-invalid:ring-3 has-data-[slot=combobox-chip]:px-1',
18
+ className
19
+ )}
20
+ data-slot="combobox-chips"
21
+ {...props}
22
+ />
23
+ );
24
+ };
25
+
26
+ const ComboboxChip = ({
27
+ children,
28
+ className,
29
+ showRemove = true,
30
+ ...props
31
+ }: ComboboxPrimitive.Chip.Props & {
32
+ showRemove?: boolean;
33
+ }) => {
34
+ return (
35
+ <ComboboxPrimitive.Chip
36
+ className={cn(
37
+ 'bg-muted text-foreground flex h-[calc(--spacing(5.25))] w-fit items-center justify-center gap-1 rounded-sm px-1.5 text-xs font-medium whitespace-nowrap has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0',
38
+ className
39
+ )}
40
+ data-slot="combobox-chip"
41
+ {...props}
42
+ >
43
+ {children}
44
+ {showRemove && (
45
+ <ComboboxPrimitive.ChipRemove
46
+ className="-ml-1 opacity-50 hover:opacity-100"
47
+ data-slot="combobox-chip-remove"
48
+ render={
49
+ <Button size="sm" variant="ghost">
50
+ <XIcon className="pointer-events-none" />
51
+ </Button>
52
+ }
53
+ />
54
+ )}
55
+ </ComboboxPrimitive.Chip>
56
+ );
57
+ };
58
+
59
+ const ComboboxChipsInput = ({ className, ...props }: ComboboxPrimitive.Input.Props) => {
60
+ return (
61
+ <ComboboxPrimitive.Input
62
+ className={cn('min-w-16 flex-1 outline-none', className)}
63
+ data-slot="combobox-chip-input"
64
+ {...props}
65
+ />
66
+ );
67
+ };
68
+
69
+ export { ComboboxChip, ComboboxChips, ComboboxChipsInput };
@@ -0,0 +1,23 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+ import { XIcon } from 'lucide-react';
3
+
4
+ import { cn } from '#utils';
5
+
6
+ import { InputGroupButton } from '../InputGroup/InputGroupButton.tsx';
7
+
8
+ const ComboboxClear = ({ className, ...props }: ComboboxPrimitive.Clear.Props) => {
9
+ return (
10
+ <ComboboxPrimitive.Clear
11
+ className={cn(className)}
12
+ data-slot="combobox-clear"
13
+ {...props}
14
+ render={
15
+ <InputGroupButton size="icon-xs" variant="ghost">
16
+ <XIcon className="pointer-events-none" />
17
+ </InputGroupButton>
18
+ }
19
+ />
20
+ );
21
+ };
22
+
23
+ export { ComboboxClear };
@@ -0,0 +1,7 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+
3
+ const ComboboxCollection = ({ ...props }: ComboboxPrimitive.Collection.Props) => {
4
+ return <ComboboxPrimitive.Collection data-slot="combobox-collection" {...props} />;
5
+ };
6
+
7
+ export { ComboboxCollection };
@@ -0,0 +1,39 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+
3
+ import { cn } from '#utils';
4
+
5
+ const ComboboxContent = ({
6
+ align = 'start',
7
+ alignOffset = 0,
8
+ anchor,
9
+ className,
10
+ side = 'bottom',
11
+ sideOffset = 6,
12
+ ...props
13
+ }: ComboboxPrimitive.Popup.Props &
14
+ Pick<ComboboxPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'anchor' | 'side' | 'sideOffset'>) => {
15
+ return (
16
+ <ComboboxPrimitive.Portal>
17
+ <ComboboxPrimitive.Positioner
18
+ align={align}
19
+ alignOffset={alignOffset}
20
+ anchor={anchor}
21
+ className="isolate z-50"
22
+ side={side}
23
+ sideOffset={sideOffset}
24
+ >
25
+ <ComboboxPrimitive.Popup
26
+ className={cn(
27
+ 'bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 *:data-[slot=input-group]:bg-input/30 *:data-[slot=input-group]:border-input/30 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg shadow-md ring-1 duration-100 data-[chips=true]:min-w-(--anchor-width) *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-8 *:data-[slot=input-group]:shadow-none',
28
+ className
29
+ )}
30
+ data-chips={!!anchor}
31
+ data-slot="combobox-content"
32
+ {...props}
33
+ />
34
+ </ComboboxPrimitive.Positioner>
35
+ </ComboboxPrimitive.Portal>
36
+ );
37
+ };
38
+
39
+ export { ComboboxContent };
@@ -0,0 +1,18 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+
3
+ import { cn } from '#utils';
4
+
5
+ const ComboboxEmpty = ({ className, ...props }: ComboboxPrimitive.Empty.Props) => {
6
+ return (
7
+ <ComboboxPrimitive.Empty
8
+ className={cn(
9
+ 'text-muted-foreground hidden w-full justify-center py-2 text-center text-sm group-data-empty/combobox-content:flex',
10
+ className
11
+ )}
12
+ data-slot="combobox-empty"
13
+ {...props}
14
+ />
15
+ );
16
+ };
17
+
18
+ export { ComboboxEmpty };
@@ -0,0 +1,9 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+
3
+ import { cn } from '#utils';
4
+
5
+ const ComboboxGroup = ({ className, ...props }: ComboboxPrimitive.Group.Props) => {
6
+ return <ComboboxPrimitive.Group className={cn(className)} data-slot="combobox-group" {...props} />;
7
+ };
8
+
9
+ export { ComboboxGroup };
@@ -0,0 +1,51 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+ import { ChevronDownIcon } from 'lucide-react';
3
+
4
+ import { cn } from '#utils';
5
+
6
+ import { InputGroup } from '../InputGroup/InputGroup.tsx';
7
+ import { InputGroupAddon } from '../InputGroup/InputGroupAddon.tsx';
8
+ import { InputGroupButton } from '../InputGroup/InputGroupButton.tsx';
9
+ import { InputGroupInput } from '../InputGroup/InputGroupInput.tsx';
10
+ import { ComboboxClear } from './ComboBoxClear.tsx';
11
+ import { ComboboxTrigger } from './ComboBoxTrigger.tsx';
12
+
13
+ const ComboboxInput = ({
14
+ children,
15
+ className,
16
+ disabled = false,
17
+ showClear = false,
18
+ showTrigger = true,
19
+ ...props
20
+ }: ComboboxPrimitive.Input.Props & {
21
+ showClear?: boolean;
22
+ showTrigger?: boolean;
23
+ }) => {
24
+ return (
25
+ <InputGroup className={cn('w-auto', className)}>
26
+ <ComboboxPrimitive.Input render={<InputGroupInput disabled={disabled} />} {...props} />
27
+ <InputGroupAddon align="inline-end">
28
+ {showTrigger && (
29
+ <ComboboxTrigger
30
+ disabled={disabled}
31
+ /* Now this works because ComboboxTrigger is expecting 'render' */
32
+ render={
33
+ <InputGroupButton
34
+ className="group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent"
35
+ data-slot="input-group-button"
36
+ size="icon-xs"
37
+ variant="ghost"
38
+ >
39
+ <ChevronDownIcon className="text-muted-foreground pointer-events-none size-4" />
40
+ </InputGroupButton>
41
+ }
42
+ />
43
+ )}
44
+ {showClear && <ComboboxClear disabled={disabled} />}
45
+ </InputGroupAddon>
46
+ {children}
47
+ </InputGroup>
48
+ );
49
+ };
50
+
51
+ export { ComboboxInput };
@@ -0,0 +1,28 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+ import { CheckIcon } from 'lucide-react';
3
+
4
+ import { cn } from '#utils';
5
+
6
+ const ComboboxItem = ({ children, className, ...props }: ComboboxPrimitive.Item.Props) => {
7
+ return (
8
+ <ComboboxPrimitive.Item
9
+ className={cn(
10
+ "data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground relative flex w-full cursor-default items-center gap-2 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
11
+ className
12
+ )}
13
+ data-slot="combobox-item"
14
+ {...props}
15
+ >
16
+ {children}
17
+ <ComboboxPrimitive.ItemIndicator
18
+ render={
19
+ <span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center">
20
+ <CheckIcon className="pointer-events-none" />
21
+ </span>
22
+ }
23
+ />
24
+ </ComboboxPrimitive.Item>
25
+ );
26
+ };
27
+
28
+ export { ComboboxItem };
@@ -0,0 +1,15 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+
3
+ import { cn } from '#utils';
4
+
5
+ const ComboboxLabel = ({ className, ...props }: ComboboxPrimitive.GroupLabel.Props) => {
6
+ return (
7
+ <ComboboxPrimitive.GroupLabel
8
+ className={cn('text-muted-foreground px-2 py-1.5 text-xs', className)}
9
+ data-slot="combobox-label"
10
+ {...props}
11
+ />
12
+ );
13
+ };
14
+
15
+ export { ComboboxLabel };
@@ -0,0 +1,18 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+
3
+ import { cn } from '#utils';
4
+
5
+ const ComboboxList = ({ className, ...props }: ComboboxPrimitive.List.Props) => {
6
+ return (
7
+ <ComboboxPrimitive.List
8
+ className={cn(
9
+ 'no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0',
10
+ className
11
+ )}
12
+ data-slot="combobox-list"
13
+ {...props}
14
+ />
15
+ );
16
+ };
17
+
18
+ export { ComboboxList };
@@ -0,0 +1,15 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+
3
+ import { cn } from '#utils';
4
+
5
+ const ComboboxSeparator = ({ className, ...props }: ComboboxPrimitive.Separator.Props) => {
6
+ return (
7
+ <ComboboxPrimitive.Separator
8
+ className={cn('bg-border -mx-1 my-1 h-px', className)}
9
+ data-slot="combobox-separator"
10
+ {...props}
11
+ />
12
+ );
13
+ };
14
+
15
+ export { ComboboxSeparator };
@@ -0,0 +1,23 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+ import { ChevronDownIcon } from 'lucide-react';
3
+
4
+ import { cn } from '#utils';
5
+
6
+ const ComboboxTrigger = ({ children, className, render, ...props }: ComboboxPrimitive.Trigger.Props) => {
7
+ return (
8
+ <ComboboxPrimitive.Trigger
9
+ className={cn("[&_svg:not([class*='size-'])]:size-4", className)}
10
+ data-slot="combobox-trigger"
11
+ render={render} // This allows it to "become" the InputGroupButton
12
+ {...props}
13
+ >
14
+ {children}
15
+ {/* We move the icon here so it's always included,
16
+ unless you prefer passing it as children manually.
17
+ */}
18
+ {!render && <ChevronDownIcon className="text-muted-foreground pointer-events-none size-4" />}
19
+ </ComboboxPrimitive.Trigger>
20
+ );
21
+ };
22
+
23
+ export { ComboboxTrigger };
@@ -0,0 +1,7 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react';
2
+
3
+ const ComboboxValue = ({ ...props }: ComboboxPrimitive.Value.Props) => {
4
+ return <ComboboxPrimitive.Value data-slot="combobox-value" {...props} />;
5
+ };
6
+
7
+ export { ComboboxValue };
@@ -228,6 +228,7 @@ export const Grouped: Story = {
228
228
  header: 'Status'
229
229
  }
230
230
  ],
231
+ enableResizing: false,
231
232
  header: 'Internal'
232
233
  },
233
234
  {
@@ -241,15 +242,32 @@ export const Grouped: Story = {
241
242
  header: 'Amount'
242
243
  }
243
244
  ],
245
+ enableResizing: false,
244
246
  header: 'Details'
245
247
  }
246
248
  ],
249
+
247
250
  data: createData(100),
248
251
  onRowDoubleClick(row) {
249
252
  alert(`row with ID ${row.id} double clicked`);
250
253
  },
251
254
  onSearchChange: () => {
252
255
  return;
253
- }
256
+ },
257
+ rowActions: [
258
+ {
259
+ label: 'Modify',
260
+ onSelect: () => {
261
+ alert('Modify');
262
+ }
263
+ },
264
+ {
265
+ destructive: true,
266
+ label: 'Delete',
267
+ onSelect: () => {
268
+ alert('Delete');
269
+ }
270
+ }
271
+ ]
254
272
  }
255
273
  };
@@ -63,7 +63,11 @@ export const DataTableBody: React.FC<
63
63
  }
64
64
  const content = flexRender(cell.column.columnDef.cell, cell.getContext());
65
65
  return (
66
- <div className="flex items-center border-r px-4 py-2 last:border-r-0" key={cell.id} style={style}>
66
+ <div
67
+ className="flex items-center border-r bg-inherit px-4 py-2 last:border-r-0"
68
+ key={cell.id}
69
+ style={style}
70
+ >
67
71
  {content && typeof content === 'object' ? content : <span className="block truncate">{content}</span>}
68
72
  </div>
69
73
  );
@@ -1,3 +1,4 @@
1
+ import { ACTIONS_COLUMN_ID } from './constants.ts';
1
2
  import { useDataTableHandle } from './hooks.ts';
2
3
  import { flexRender } from './utils.tsx';
3
4
 
@@ -24,11 +25,12 @@ export const DataTableHead = () => {
24
25
  style.position = 'sticky';
25
26
  style.zIndex = 20;
26
27
  }
27
- // no border with actions on right
28
- // TODO - consider resizing toggle in this case
29
- if (header.column.getIsLastColumn('center')) {
28
+
29
+ const nextHeader = headerGroup.headers[header.index + 1];
30
+ if (nextHeader?.column.id === ACTIONS_COLUMN_ID) {
30
31
  style.borderRight = 'none';
31
32
  }
33
+
32
34
  return (
33
35
  <div
34
36
  className="group/cell bg-background relative flex items-center border-r border-b px-4 py-2 last:border-r-0"