@rebasepro/ui 0.3.0 → 0.5.0

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.
package/README.md CHANGED
@@ -1,84 +1,142 @@
1
- ## Rebase UI
2
-
3
-
4
- **Rebase UI** is a high quality set of components that you can use to build your own custom views. You can
5
- use these components to build your own Rebase views, or in any other React application. You just need to install
6
- `tailwindcss` and the `@rebasepro/ui` package.
7
-
8
- ### Why build this UI kit?
9
- Rebase was using MUI until version 3.0. MUI provides ready to use components with intuitive APIs, but it also
10
- comes with a lot of complexity and overhead. We wanted to build a simpler and more flexible UI kit that could be used
11
- in any React project, not just in Rebase.
12
- We also wanted to make it easy to transition from MUI to our new UI kit, so we kept the API as similar as possible.
13
- The result it a set of components that are easy to use, easy to customize, **much more performant** and with a smaller bundle size.
14
-
15
- The components are primarily built using **Radix UI** primitives and **tailwindcss**. This means that you can easily customize them
16
- using tailwindcss classes or override the styles using CSS.
17
-
18
- See the full list of components in https://rebase.pro/docs/components
19
-
20
-
21
- > All the components are exported from the `@rebasepro/ui` package. These are the same components used internally in **Rebase**.
1
+ # @rebasepro/ui
22
2
 
3
+ React component library and design system for the Rebase ecosystem. Built on Radix UI primitives, Tailwind CSS, and lucide-react icons.
23
4
 
24
5
  ## Installation
25
6
 
26
- If you are using Rebase, you don't need to install this package, as it is already included, and
27
- configured for you.
28
-
29
- To use the components in your own project, you need to install the `@rebasepro/ui` package:
30
-
31
- ```bash
32
- yarn add @rebasepro/ui
33
- ```
34
- or
35
7
  ```bash
36
- npm install @rebasepro/ui
8
+ pnpm add @rebasepro/ui
37
9
  ```
38
10
 
39
- You also need to install `tailwindcss`:
11
+ ### Peer Dependencies
40
12
 
41
- ```bash
42
- yarn add tailwindcss @tailwindcss/typography
43
- ```
44
-
45
- And initialize it in your project:
13
+ - `react` >= 19.0.0
14
+ - `react-dom` >= 19.0.0
46
15
 
47
- ```bash
48
- npx tailwindcss init
49
- ```
16
+ ## What This Package Does
50
17
 
51
- And add then add the rebase preset in your `tailwind.config.js`:
18
+ `@rebasepro/ui` provides all the shared UI primitives used across Rebase packages (`@rebasepro/studio`, `@rebasepro/admin`, etc.). It wraps Radix UI components with Rebase's design tokens and Tailwind styling, and re-exports lucide-react icons so other packages don't need direct icon dependencies.
52
19
 
53
- ```javascript
54
- import rebaseConfig from "@rebasepro/ui/tailwind.config.js";
20
+ Import the stylesheet in your app:
55
21
 
56
- export default {
57
- presets: [rebaseConfig],
58
- content: [
59
- "./index.html",
60
- "./src/**/*.{js,ts,jsx,tsx}",
61
- "./node_modules/@rebasepro/**/src/**/*.{js,ts,jsx,tsx}"
62
- ]
63
- };
22
+ ```typescript
23
+ import "@rebasepro/ui/index.css";
64
24
  ```
65
- (You might need to adjust the paths in the `content` array to match your project structure)
66
25
 
67
- Finally, you need to define your primary and secondary colors in your `index.css` file:
68
-
69
- ```css
70
- @import 'tailwindcss';
71
- @import "@rebasepro/ui/index.css" layer(base);
72
-
73
- @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
74
-
75
- @source "../index.html";
76
- @source "./**/*.{js,ts,jsx,tsx}";
77
- @source "../node_modules/@rebasepro/**/*.{js,ts,jsx,tsx}";
26
+ ## Key Exports
27
+
28
+ ### Components
29
+
30
+ | Component | Description |
31
+ |---|---|
32
+ | `Alert` | Status messages and notifications |
33
+ | `Autocomplete` | Text input with suggestions |
34
+ | `Avatar` | User avatar display |
35
+ | `Badge` | Small status indicator |
36
+ | `BooleanSwitch` / `BooleanSwitchWithLabel` | Toggle switch |
37
+ | `Button` / `IconButton` / `LoadingButton` | Action buttons |
38
+ | `Card` | Content container card |
39
+ | `CenteredView` | Horizontally/vertically centered layout |
40
+ | `Checkbox` | Checkbox input (Radix) |
41
+ | `Chip` / `FilterChip` | Tag-like chips |
42
+ | `CircularProgress` / `CircularProgressCenter` | Loading spinners |
43
+ | `Collapse` | Collapsible content (Radix) |
44
+ | `ColorPicker` | Color selection input |
45
+ | `Container` | Max-width content wrapper |
46
+ | `DateTimeField` | Date/time picker input |
47
+ | `DebouncedTextField` | Text field with debounced onChange |
48
+ | `Dialog` / `DialogTitle` / `DialogContent` / `DialogActions` | Modal dialogs (Radix) |
49
+ | `ErrorBoundary` | React error boundary |
50
+ | `ExpandablePanel` | Expandable/collapsible panel |
51
+ | `FileUpload` | Drag-and-drop file upload (react-dropzone) |
52
+ | `InputLabel` / `InfoLabel` / `Label` | Form labels |
53
+ | `Markdown` | Markdown renderer (markdown-it) |
54
+ | `Menu` / `Menubar` | Dropdown and menu bar (Radix) |
55
+ | `MultiSelect` | Multi-value select input |
56
+ | `Paper` | Elevated surface |
57
+ | `Popover` | Popover overlay (Radix) |
58
+ | `RadioGroup` | Radio button group (Radix) |
59
+ | `ResizablePanels` | Resizable split panes |
60
+ | `SearchBar` | Search input with icon |
61
+ | `Select` | Single-value select (Radix) |
62
+ | `Separator` | Visual divider (Radix) |
63
+ | `Sheet` | Slide-out panel |
64
+ | `Skeleton` | Loading placeholder |
65
+ | `Slider` | Range slider (Radix) |
66
+ | `Table` / `VirtualTable` | Data tables (VirtualTable uses react-window) |
67
+ | `Tabs` | Tab navigation (Radix) |
68
+ | `TextareaAutosize` | Auto-resizing textarea |
69
+ | `TextField` | Text input field |
70
+ | `ToggleButtonGroup` | Segmented toggle buttons |
71
+ | `Tooltip` | Hover tooltip (Radix) |
72
+ | `Typography` | Text with variant styling |
73
+
74
+ ### Re-exported Radix Primitives
75
+
76
+ ```typescript
77
+ import { Portal, PopoverPrimitive, Slot } from "@rebasepro/ui";
78
+ ```
78
79
 
79
- :root {
80
- --color-primary: #0070F4;
81
- --color-secondary: #FF5B79;
80
+ ### Style Mixins
81
+
82
+ Tailwind class-string constants for consistent styling:
83
+
84
+ | Export | Description |
85
+ |---|---|
86
+ | `focusedClasses` | Ring styles for focused elements |
87
+ | `fieldBackgroundMixin` | Standard field background |
88
+ | `fieldBackgroundHoverMixin` | Hover state for fields |
89
+ | `defaultBorderMixin` | Default border color |
90
+ | `paperMixin` | Paper/card surface style |
91
+ | `cardMixin` / `cardClickableMixin` / `cardSelectedMixin` | Card variants |
92
+
93
+ ### Utilities
94
+
95
+ | Export | Description |
96
+ |---|---|
97
+ | `cls(...)` | Class name merge utility (wraps `clsx`) |
98
+ | `debounce` | Debounce function |
99
+ | `chipColors` | Color palette for chips |
100
+ | `keyToIconComponent` | Map icon string key to lucide component |
101
+
102
+ ### Hooks
103
+
104
+ | Hook | Description |
105
+ |---|---|
106
+ | `useInjectStyles` | Inject CSS into the document head |
107
+ | `useOutsideAlerter` | Detect clicks outside a ref |
108
+ | `useDebouncedCallback` | Debounced callback hook |
109
+ | `useDebounceCallback` | Callback debounce variant |
110
+ | `useDebounceValue` | Debounced value hook |
111
+ | `PortalContainerContext` | Context for portal target container |
112
+
113
+ ### Icons
114
+
115
+ Re-exports ~100 individual lucide-react icon components (e.g. `ArrowRightIcon`, `SearchIcon`, `PlusIcon`), the full `lucideIcons` map, the `Icon` component, `GitHubIcon`, `HandleIcon`, `iconKeys`, and `coolIconKeys`.
116
+
117
+ ## Quick Start
118
+
119
+ ```tsx
120
+ import { Button, TextField, Typography, cls } from "@rebasepro/ui";
121
+ import { SearchIcon } from "@rebasepro/ui";
122
+ import "@rebasepro/ui/index.css";
123
+
124
+ function MyForm() {
125
+ return (
126
+ <div className={cls("flex flex-col gap-4 p-4")}>
127
+ <Typography variant="h6">Search</Typography>
128
+ <TextField placeholder="Type to search..." />
129
+ <Button variant="filled">
130
+ <SearchIcon size={16} />
131
+ Search
132
+ </Button>
133
+ </div>
134
+ );
82
135
  }
83
136
  ```
84
137
 
138
+ ## Related Packages
139
+
140
+ - `@rebasepro/studio` — Dev tools layer (depends on this package)
141
+ - `@rebasepro/admin` — CMS layer (depends on this package)
142
+ - `@rebasepro/core` — Core framework (uses this for shared UI)
@@ -1,9 +1,8 @@
1
1
  import React from "react";
2
- type CardProps = {
2
+ declare const Card: React.ForwardRefExoticComponent<{
3
3
  children: React.ReactNode;
4
4
  style?: React.CSSProperties;
5
5
  onClick?: (e?: React.MouseEvent) => void;
6
6
  className?: string;
7
- };
8
- declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
7
+ } & React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
9
8
  export { Card };
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- export interface FilterChipProps {
2
+ export interface FilterChipProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
3
3
  /**
4
4
  * The text label displayed on the chip.
5
5
  */
@@ -8,10 +8,6 @@ export interface FilterChipProps {
8
8
  * Whether the chip is currently in an active/selected state.
9
9
  */
10
10
  active?: boolean;
11
- /**
12
- * Callback when the chip is clicked.
13
- */
14
- onClick?: () => void;
15
11
  /**
16
12
  * Optional icon rendered before the label.
17
13
  */
@@ -21,10 +17,6 @@ export interface FilterChipProps {
21
17
  * @default "medium"
22
18
  */
23
19
  size?: "small" | "medium";
24
- /**
25
- * Additional class names.
26
- */
27
- className?: string;
28
20
  /**
29
21
  * Whether the chip is disabled.
30
22
  */
@@ -39,4 +31,4 @@ export interface FilterChipProps {
39
31
  *
40
32
  * @group Interactive components
41
33
  */
42
- export declare function FilterChip({ children, active, onClick, icon, size, className, disabled }: FilterChipProps): import("react/jsx-runtime").JSX.Element;
34
+ export declare const FilterChip: React.ForwardRefExoticComponent<FilterChipProps & React.RefAttributes<HTMLButtonElement>>;
@@ -224,6 +224,12 @@ export type OnVirtualTableColumnResizeParams = {
224
224
  key: string;
225
225
  column: VirtualTableColumn;
226
226
  };
227
+ /**
228
+ * @see Table
229
+ * @group Components
230
+ */
231
+ export type WhereFilterOp = "<" | "<=" | "==" | "!=" | ">=" | ">" | "array-contains" | "in" | "not-in" | "array-contains-any";
232
+ export type FilterValues<Key extends string> = Partial<Record<Key, [WhereFilterOp, unknown] | [WhereFilterOp, unknown][]>>;
227
233
  /**
228
234
  * @see Table
229
235
  * @group Components
@@ -233,11 +239,11 @@ export type VirtualTableSort = "asc" | "desc" | undefined;
233
239
  * @see Table
234
240
  * @group Components
235
241
  */
236
- export type VirtualTableFilterValues<Key extends string> = Partial<Record<Key, [VirtualTableWhereFilterOp, unknown]>>;
242
+ export type VirtualTableFilterValues<Key extends string> = FilterValues<Key>;
237
243
  /**
238
244
  * Filter conditions in a `Query.where()` clause are specified using the
239
245
  * strings `<`, `<=`, `==`, `>=`, `>`, `array-contains`, `in`, and `array-contains-any`.
240
246
  * @see Table
241
247
  * @group Models
242
248
  */
243
- export type VirtualTableWhereFilterOp = "<" | "<=" | "==" | "!=" | ">=" | ">" | "array-contains" | "in" | "not-in" | "array-contains-any";
249
+ export type VirtualTableWhereFilterOp = WhereFilterOp;
package/dist/index.css CHANGED
@@ -117,7 +117,7 @@
117
117
  }
118
118
 
119
119
  .typography-button {
120
- @apply text-[13px] font-semibold;
120
+ @apply text-sm font-semibold;
121
121
  }
122
122
 
123
123
  :focus-visible {
package/dist/index.es.js CHANGED
@@ -4,7 +4,7 @@ import { c } from "react-compiler-runtime";
4
4
  import { clsx } from "clsx";
5
5
  import { twMerge } from "tailwind-merge";
6
6
  import * as React from "react";
7
- import React__default, { createContext, useContext, useEffect, useRef, useState, Children, forwardRef, useLayoutEffect, useId, useDeferredValue, useMemo, createRef, useCallback } from "react";
7
+ import React__default, { createContext, useContext, useEffect, useRef, useState, Children, forwardRef, useLayoutEffect, useId, useCallback, useMemo, createRef } from "react";
8
8
  import * as Collapsible from "@radix-ui/react-collapsible";
9
9
  import { AlertCircleIcon, ShieldAlertIcon, ArrowLeftIcon, RefreshCwIcon, ChevronUpIcon, ChevronDownIcon, MinusIcon, CheckIcon, CalendarIcon, XIcon, ChevronRightIcon, SearchIcon, ChevronLeftIcon, ArrowUpIcon, FilterIcon } from "lucide-react";
10
10
  import { AlertCircleIcon as AlertCircleIcon2, AlertTriangleIcon, AlignLeftIcon, AppWindow, ArrowDownToLineIcon, ArrowLeftIcon as ArrowLeftIcon2, ArrowRightFromLineIcon, ArrowRightIcon, ArrowRightToLineIcon, ArrowUpToLineIcon, BoldIcon, BookOpenIcon, CalendarIcon as CalendarIcon2, CheckCircleIcon, CheckIcon as CheckIcon2, CheckSquareIcon, ChevronDownIcon as ChevronDownIcon2, ChevronLeftIcon as ChevronLeftIcon2, ChevronRightIcon as ChevronRightIcon2, ChevronUpIcon as ChevronUpIcon2, ChevronsLeftIcon, ChevronsRightIcon, ChevronsUpDownIcon, CircleIcon, CircleUserIcon, CodeIcon, ColumnsIcon, CopyIcon, DatabaseIcon, DownloadIcon, ExternalLinkIcon, EyeIcon, EyeOffIcon, FileIcon, FileSearchIcon, FileTextIcon, FilterIcon as FilterIcon2, FilterXIcon, FlagIcon, FolderIcon, FolderPlusIcon, FolderUpIcon, FunctionSquareIcon, GitBranchIcon, GlobeIcon, HashIcon, Heading1Icon, Heading2Icon, Heading3Icon, HelpCircleIcon, HistoryIcon, HomeIcon, ImageIcon, ImageOffIcon, InfoIcon, ItalicIcon, KanbanIcon, KeyIcon, KeyRoundIcon, LanguagesIcon, LayoutGridIcon, LinkIcon, ListIcon, ListOrderedIcon, LoaderIcon, LogOutIcon, MailIcon, Maximize2Icon, MenuIcon, MinusCircleIcon, MinusIcon as MinusIcon2, MoonIcon, MoreVerticalIcon, Music2Icon, PanelLeftIcon, PauseIcon, PencilIcon, PhoneIcon, PlayIcon, PlusIcon, QuoteIcon, RefreshCcwIcon, RefreshCwIcon as RefreshCwIcon2, RepeatIcon, Rows3Icon, SaveIcon, SearchIcon as SearchIcon2, SendIcon, SettingsIcon, ShieldIcon, ShoppingCartIcon, SlidersHorizontalIcon, SquareIcon, StarIcon, StrikethroughIcon, SunIcon, SunMoonIcon, TableIcon, TagIcon, TerminalIcon, TextIcon, Trash2Icon, TypeIcon, UnderlineIcon, UndoIcon, UploadCloudIcon, UploadIcon, UserCheckIcon, UserIcon, VideoIcon, VoteIcon, Wand2Icon, XCircleIcon, XIcon as XIcon2, icons } from "lucide-react";
@@ -869,9 +869,10 @@ const BooleanSwitchWithLabel = function BooleanSwitchWithLabel2({
869
869
  "min-h-[64px]": size === "large"
870
870
  }, size === "small" || size === "smallest" ? "pl-2" : "pl-4", size === "small" || size === "smallest" ? "pr-4" : "pr-6", position === "end" ? "flex-row-reverse" : "flex-row", fullWidth ? "w-full" : "", className), onClick: disabled ? void 0 : (e) => {
871
871
  if (props.allowIndeterminate) {
872
- if (value === null || value === void 0) onValueChange?.(true);
873
- else if (value) onValueChange?.(false);
874
- else onValueChange?.(null);
872
+ const onChange = onValueChange;
873
+ if (value === null || value === void 0) onChange?.(true);
874
+ else if (value) onChange?.(false);
875
+ else onChange?.(null);
875
876
  } else {
876
877
  onValueChange?.(!value);
877
878
  }
@@ -985,15 +986,15 @@ const ButtonInner = React__default.memo(React__default.forwardRef((t0, ref) => {
985
986
  "border border-transparent bg-surface-300 dark:bg-surface-500 opacity-40 bg-surface-300/40 dark:bg-surface-500/40": t25
986
987
  });
987
988
  const sizeClasses2 = cls({
988
- "py-0.5 px-1.5": size === "small",
989
- "py-1.5 px-3": size === "medium",
990
- "py-2 px-4": size === "large",
991
- "py-2.5 px-5": size === "xl",
992
- "py-3 px-6": size === "2xl"
989
+ "py-1 px-2": size === "small",
990
+ "py-2 px-4": size === "medium",
991
+ "py-2.5 px-5": size === "large",
992
+ "py-3 px-6": size === "xl",
993
+ "py-4 px-10": size === "2xl"
993
994
  });
994
995
  const iconColorClass = (color === "neutral" || color === "text") && !disabled ? "[&>svg]:text-surface-accent-500 dark:[&>svg]:text-surface-accent-300" : "";
995
996
  if (Component) {
996
- t30 = /* @__PURE__ */ jsxs(Component, { ref, onClick: props.onClick, className: cls(startIcon ? "pl-3" : "", "typography-button h-fit rounded-md whitespace-nowrap inline-flex items-center justify-center p-1.5 px-3 focus:outline-none transition-all ease-in-out duration-150 gap-1.5 active:scale-[0.98]", buttonClasses2, sizeClasses2, iconColorClass, className), ...props, children: [
997
+ t30 = /* @__PURE__ */ jsxs(Component, { ref, onClick: props.onClick, className: cls(startIcon ? "pl-3" : "", "typography-button h-fit rounded-md whitespace-nowrap inline-flex items-center justify-center p-2 px-4 focus:outline-none transition-all ease-in-out duration-150 gap-2 active:scale-[0.98]", buttonClasses2, sizeClasses2, iconColorClass, className), ...props, children: [
997
998
  startIcon,
998
999
  children
999
1000
  ] });
@@ -1002,7 +1003,7 @@ const ButtonInner = React__default.memo(React__default.forwardRef((t0, ref) => {
1002
1003
  t26 = ref;
1003
1004
  t27 = props.type ?? "button";
1004
1005
  t28 = props.onClick;
1005
- t29 = cls(startIcon ? "pl-3" : "", "typography-button h-fit rounded-md whitespace-nowrap inline-flex items-center justify-center p-1.5 px-3 focus:outline-none transition-all ease-in-out duration-150 gap-1.5 active:scale-[0.98]", buttonClasses2, sizeClasses2, iconColorClass, className);
1006
+ t29 = cls(startIcon ? "pl-3" : "", "typography-button h-fit rounded-md whitespace-nowrap inline-flex items-center justify-center p-2 px-4 focus:outline-none transition-all ease-in-out duration-150 gap-2 active:scale-[0.98]", buttonClasses2, sizeClasses2, iconColorClass, className);
1006
1007
  }
1007
1008
  $[11] = Component;
1008
1009
  $[12] = children;
@@ -2147,10 +2148,10 @@ const buttonClasses = "hover:bg-surface-accent-200 hover:bg-opacity-75 hover:bg-
2147
2148
  const baseClasses = "inline-flex items-center justify-center p-2 text-sm font-medium focus:outline-none transition-colors ease-in-out duration-150";
2148
2149
  const colorClasses$1 = "text-surface-accent-500 visited:text-surface-accent-500 dark:text-surface-accent-300 dark:visited:text-surface-300";
2149
2150
  const sizeClasses$1 = {
2150
- medium: "w-9 !h-9 min-w-9 min-h-9",
2151
- small: "w-7 !h-7 min-w-7 min-h-7",
2152
- smallest: "w-5 !h-5 min-w-5 min-h-5",
2153
- large: "w-10 !h-10 min-w-10 min-h-10"
2151
+ medium: "w-10 !h-10 min-w-10 min-h-10",
2152
+ small: "w-8 !h-8 min-w-8 min-h-8",
2153
+ smallest: "w-6 !h-6 min-w-6 min-h-6",
2154
+ large: "w-12 !h-12 min-w-12 min-h-12"
2154
2155
  };
2155
2156
  const shapeClasses = {
2156
2157
  circular: "rounded-full",
@@ -3178,49 +3179,80 @@ const sizeClasses = {
3178
3179
  small: "px-2 py-0.5 text-xs",
3179
3180
  medium: "px-2.5 py-1 text-xs"
3180
3181
  };
3181
- function FilterChip(t0) {
3182
- const $ = c(11);
3183
- const {
3184
- children,
3185
- active: t1,
3186
- onClick,
3187
- icon,
3188
- size: t2,
3189
- className,
3190
- disabled: t3
3191
- } = t0;
3182
+ const FilterChip = React__default.forwardRef(function FilterChip2(t0, ref) {
3183
+ const $ = c(22);
3184
+ let children;
3185
+ let className;
3186
+ let icon;
3187
+ let onClick;
3188
+ let rest;
3189
+ let t1;
3190
+ let t2;
3191
+ let t3;
3192
+ if ($[0] !== t0) {
3193
+ ({
3194
+ children,
3195
+ active: t1,
3196
+ onClick,
3197
+ icon,
3198
+ size: t2,
3199
+ className,
3200
+ disabled: t3,
3201
+ ...rest
3202
+ } = t0);
3203
+ $[0] = t0;
3204
+ $[1] = children;
3205
+ $[2] = className;
3206
+ $[3] = icon;
3207
+ $[4] = onClick;
3208
+ $[5] = rest;
3209
+ $[6] = t1;
3210
+ $[7] = t2;
3211
+ $[8] = t3;
3212
+ } else {
3213
+ children = $[1];
3214
+ className = $[2];
3215
+ icon = $[3];
3216
+ onClick = $[4];
3217
+ rest = $[5];
3218
+ t1 = $[6];
3219
+ t2 = $[7];
3220
+ t3 = $[8];
3221
+ }
3192
3222
  const active = t1 === void 0 ? false : t1;
3193
3223
  const size = t2 === void 0 ? "medium" : t2;
3194
3224
  const disabled = t3 === void 0 ? false : t3;
3195
3225
  const t4 = sizeClasses[size];
3196
3226
  let t5;
3197
- if ($[0] !== active || $[1] !== className || $[2] !== disabled || $[3] !== t4) {
3227
+ if ($[9] !== active || $[10] !== className || $[11] !== disabled || $[12] !== t4) {
3198
3228
  t5 = cls("inline-flex items-center gap-1 rounded-full", "font-medium whitespace-nowrap select-none shrink-0", "transition-all duration-150", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50", t4, active ? "bg-primary/12 text-primary dark:bg-primary/20 dark:text-primary shadow-[inset_0_0_0_1.5px_var(--color-primary)]" : cls("bg-surface-accent-100 text-text-secondary dark:bg-surface-accent-800 dark:text-text-secondary-dark", !disabled && "cursor-pointer hover:bg-surface-accent-200 dark:hover:bg-surface-accent-700"), disabled && "opacity-50 cursor-not-allowed", className);
3199
- $[0] = active;
3200
- $[1] = className;
3201
- $[2] = disabled;
3202
- $[3] = t4;
3203
- $[4] = t5;
3229
+ $[9] = active;
3230
+ $[10] = className;
3231
+ $[11] = disabled;
3232
+ $[12] = t4;
3233
+ $[13] = t5;
3204
3234
  } else {
3205
- t5 = $[4];
3235
+ t5 = $[13];
3206
3236
  }
3207
3237
  let t6;
3208
- if ($[5] !== children || $[6] !== disabled || $[7] !== icon || $[8] !== onClick || $[9] !== t5) {
3209
- t6 = /* @__PURE__ */ jsxs("button", { type: "button", onClick, disabled, className: t5, children: [
3238
+ if ($[14] !== children || $[15] !== disabled || $[16] !== icon || $[17] !== onClick || $[18] !== ref || $[19] !== rest || $[20] !== t5) {
3239
+ t6 = /* @__PURE__ */ jsxs("button", { ref, type: "button", onClick, disabled, className: t5, ...rest, children: [
3210
3240
  icon,
3211
3241
  children
3212
3242
  ] });
3213
- $[5] = children;
3214
- $[6] = disabled;
3215
- $[7] = icon;
3216
- $[8] = onClick;
3217
- $[9] = t5;
3218
- $[10] = t6;
3243
+ $[14] = children;
3244
+ $[15] = disabled;
3245
+ $[16] = icon;
3246
+ $[17] = onClick;
3247
+ $[18] = ref;
3248
+ $[19] = rest;
3249
+ $[20] = t5;
3250
+ $[21] = t6;
3219
3251
  } else {
3220
- t6 = $[10];
3252
+ t6 = $[21];
3221
3253
  }
3222
3254
  return t6;
3223
- }
3255
+ });
3224
3256
  const colorClasses = {
3225
3257
  info: "bg-sky-200 dark:bg-teal-900",
3226
3258
  warn: "bg-orange-200 dark:bg-yellow-950"
@@ -7001,7 +7033,7 @@ function Tabs(t0) {
7001
7033
  } else {
7002
7034
  t10 = $[12];
7003
7035
  }
7004
- const t11 = variant === "standard" && "inline-flex h-10 items-center justify-start rounded-md bg-surface-50 p-1 text-surface-600 dark:bg-surface-900 dark:text-surface-400 gap-2 border";
7036
+ const t11 = variant === "standard" && "inline-flex h-9 items-center justify-start rounded-md bg-surface-50 p-1 text-surface-600 dark:bg-surface-900 dark:text-surface-400 gap-2 border";
7005
7037
  const t12 = variant === "standard" && defaultBorderMixin;
7006
7038
  const t13 = variant === "boxy" && "flex items-center h-full";
7007
7039
  const t14 = variant === "pill" && "flex items-center gap-0.5";
@@ -7075,7 +7107,7 @@ function Tab(t0) {
7075
7107
  const {
7076
7108
  variant
7077
7109
  } = useContext(TabsContext);
7078
- const t1 = variant === "standard" && "rounded-sm px-3 py-1.5 data-[state=active]:bg-white data-[state=active]:text-surface-900 data-[state=active]:shadow-sm dark:data-[state=active]:bg-surface-900 dark:data-[state=active]:text-surface-50";
7110
+ const t1 = variant === "standard" && "rounded-sm px-3 py-1 data-[state=active]:bg-white data-[state=active]:text-surface-900 data-[state=active]:shadow-sm dark:data-[state=active]:bg-surface-900 dark:data-[state=active]:text-surface-50";
7079
7111
  let t2;
7080
7112
  if ($[0] !== className || $[1] !== innerClassName || $[2] !== t1 || $[3] !== variant) {
7081
7113
  t2 = cls("inline-flex items-center justify-center whitespace-nowrap text-sm font-medium ring-offset-white transition-all", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-surface-400 focus-visible:ring-offset-2", "disabled:pointer-events-none disabled:opacity-50", t1, variant === "boxy" && cls("flex-shrink-0 flex items-center gap-1.5 px-3.5 h-9 border-r border-surface-200 dark:border-surface-800 cursor-pointer text-[12px] font-medium transition-colors group relative box-border overflow-hidden", "border-b-2 border-b-transparent", "data-[state=active]:bg-surface-50 dark:data-[state=active]:bg-surface-900", "data-[state=active]:text-text-primary dark:data-[state=active]:text-text-primary-dark", "data-[state=active]:border-b-primary", "text-text-secondary dark:text-text-secondary-dark hover:bg-surface-100 dark:hover:bg-surface-800"), variant === "pill" && cls("px-2 py-0.5 rounded text-[10px] font-medium transition-colors", "data-[state=active]:bg-primary/10 data-[state=active]:text-primary dark:data-[state=active]:bg-primary/20 dark:data-[state=active]:text-blue-400", "text-text-disabled dark:text-text-disabled-dark hover:text-text-secondary dark:hover:text-text-secondary-dark"), className, variant === "standard" && innerClassName);
@@ -7549,73 +7581,59 @@ const Badge = React__default.forwardRef((t0, ref) => {
7549
7581
  });
7550
7582
  Badge.displayName = "Badge";
7551
7583
  function DebouncedTextField(props) {
7552
- const $ = c(13);
7553
- const previousEventRef = React__default.useRef(void 0);
7554
- const [internalValue, setInternalValue] = React__default.useState(props.value);
7555
- const deferredValue = useDeferredValue(internalValue);
7556
- let t0;
7557
- let t1;
7558
- if ($[0] !== props.value) {
7559
- t0 = () => {
7560
- setInternalValue(props.value);
7584
+ const [internalValue, setInternalValue] = useState(props.value ?? "");
7585
+ const lastSentValueRef = useRef(props.value ?? "");
7586
+ const timerRef = useRef(void 0);
7587
+ useEffect(() => {
7588
+ const externalValue = props.value ?? "";
7589
+ if (externalValue !== lastSentValueRef.current) {
7590
+ setInternalValue(externalValue);
7591
+ lastSentValueRef.current = externalValue;
7592
+ }
7593
+ }, [props.value]);
7594
+ useEffect(() => {
7595
+ return () => {
7596
+ if (timerRef.current) clearTimeout(timerRef.current);
7561
7597
  };
7562
- t1 = [props.value];
7563
- $[0] = props.value;
7564
- $[1] = t0;
7565
- $[2] = t1;
7566
- } else {
7567
- t0 = $[1];
7568
- t1 = $[2];
7569
- }
7570
- useEffect(t0, t1);
7571
- let t2;
7572
- if ($[3] !== deferredValue || $[4] !== props) {
7573
- t2 = () => {
7574
- const emptyInitialValue = !props.value;
7575
- if (emptyInitialValue && !deferredValue) {
7576
- return;
7577
- }
7578
- if (deferredValue !== props.value && previousEventRef.current && props.onChange) {
7579
- props.onChange(previousEventRef.current);
7598
+ }, []);
7599
+ const flushChange = useCallback((value, event) => {
7600
+ if (timerRef.current) {
7601
+ clearTimeout(timerRef.current);
7602
+ timerRef.current = void 0;
7603
+ }
7604
+ if (value !== props.value && props.onChange) {
7605
+ lastSentValueRef.current = value;
7606
+ const e = {
7607
+ ...event,
7608
+ target: {
7609
+ ...event?.target,
7610
+ value,
7611
+ name: props.name
7612
+ }
7613
+ };
7614
+ props.onChange(e);
7615
+ }
7616
+ }, [props.value, props.onChange, props.name]);
7617
+ const internalOnChange = useCallback((event_0) => {
7618
+ const newValue = event_0.target.value;
7619
+ setInternalValue(newValue);
7620
+ if (timerRef.current) clearTimeout(timerRef.current);
7621
+ const eventCopy = {
7622
+ ...event_0,
7623
+ target: {
7624
+ ...event_0?.target,
7625
+ name: event_0?.target?.name
7580
7626
  }
7581
7627
  };
7582
- $[3] = deferredValue;
7583
- $[4] = props;
7584
- $[5] = t2;
7585
- } else {
7586
- t2 = $[5];
7587
- }
7588
- let t3;
7589
- if ($[6] !== deferredValue || $[7] !== props.value) {
7590
- t3 = [deferredValue, props.value];
7591
- $[6] = deferredValue;
7592
- $[7] = props.value;
7593
- $[8] = t3;
7594
- } else {
7595
- t3 = $[8];
7596
- }
7597
- useEffect(t2, t3);
7598
- let t4;
7599
- if ($[9] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
7600
- t4 = (event) => {
7601
- previousEventRef.current = event;
7602
- setInternalValue(event.target.value);
7603
- };
7604
- $[9] = t4;
7605
- } else {
7606
- t4 = $[9];
7607
- }
7608
- const internalOnChange = t4;
7609
- let t5;
7610
- if ($[10] !== internalValue || $[11] !== props) {
7611
- t5 = /* @__PURE__ */ jsx(TextField, { ...props, onChange: internalOnChange, value: internalValue });
7612
- $[10] = internalValue;
7613
- $[11] = props;
7614
- $[12] = t5;
7615
- } else {
7616
- t5 = $[12];
7617
- }
7618
- return t5;
7628
+ timerRef.current = setTimeout(() => {
7629
+ flushChange(newValue, eventCopy);
7630
+ }, 150);
7631
+ }, [flushChange]);
7632
+ const internalOnBlur = useCallback((event_1) => {
7633
+ flushChange(internalValue, event_1);
7634
+ props.onBlur?.(event_1);
7635
+ }, [internalValue, flushChange, props.onBlur]);
7636
+ return /* @__PURE__ */ jsx(TextField, { ...props, onChange: internalOnChange, onBlur: internalOnBlur, value: internalValue });
7619
7637
  }
7620
7638
  const styles = `
7621
7639
  @keyframes shimmer {
@@ -8335,7 +8353,8 @@ const VirtualTableHeaderRow = ({
8335
8353
  height: headerHeight
8336
8354
  }, children: [
8337
8355
  columns.map((column_0, columnIndex) => {
8338
- const filterForThisProperty = column_0 && filter && filter[column_0.key] ? filter[column_0.key] : void 0;
8356
+ const columnFilter = column_0 && filter && filter[column_0.key] ? filter[column_0.key] : void 0;
8357
+ const filterForThisProperty = columnFilter ? Array.isArray(columnFilter[0]) ? columnFilter[0] : columnFilter : void 0;
8339
8358
  const isDraggable = !column_0.frozen && !!onColumnsOrderChange;
8340
8359
  const isDragging = draggingColumnId === column_0.key;
8341
8360
  return /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(SortableColumnHeader, { column: column_0, columnIndex, columnRefs, isResizing, onFilterUpdate, filter: filterForThisProperty, sortByProperty, currentSort, onColumnSort, onClickResizeColumn, createFilterField, isDragging, isDraggable }) }, "header_" + column_0.key);