@alpic-ai/ui 1.163.0 → 1.164.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.
@@ -102,6 +102,7 @@ function Combobox(props) {
102
102
  function ComboboxTrigger({ className, size, placeholder, children, ...props }) {
103
103
  const { multiple, value, values, open, onDeselect } = useComboboxContext();
104
104
  const isEmpty = multiple ? values.length === 0 : value === null || value === void 0;
105
+ const hasCustomMultipleValue = multiple && children !== void 0;
105
106
  return /* @__PURE__ */ jsx(PopoverTrigger, {
106
107
  asChild: true,
107
108
  children: /* @__PURE__ */ jsxs("button", {
@@ -112,8 +113,8 @@ function ComboboxTrigger({ className, size, placeholder, children, ...props }) {
112
113
  className: cn(selectTriggerVariants({ size }), className),
113
114
  ...props,
114
115
  children: [/* @__PURE__ */ jsx("span", {
115
- className: cn("flex flex-1 items-center gap-1.5 text-left", multiple && "flex-wrap", isEmpty && "text-placeholder"),
116
- children: isEmpty ? placeholder : multiple ? /* @__PURE__ */ jsx(ComboboxTags, {
116
+ className: cn("flex flex-1 items-center gap-1.5 text-left", multiple && !hasCustomMultipleValue && "flex-wrap", isEmpty && !hasCustomMultipleValue && "text-placeholder"),
117
+ children: hasCustomMultipleValue ? children : isEmpty ? placeholder : multiple ? /* @__PURE__ */ jsx(ComboboxTags, {
117
118
  values,
118
119
  onDeselect
119
120
  }) : children
@@ -12,7 +12,7 @@ declare const useFormField: () => {
12
12
  isDirty: boolean;
13
13
  isTouched: boolean;
14
14
  isValidating: boolean;
15
- error?: import("react-hook-form").FieldError;
15
+ error?: import("react-hook-form").FieldError | undefined;
16
16
  id: string;
17
17
  name: string;
18
18
  formItemId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alpic-ai/ui",
3
- "version": "1.163.0",
3
+ "version": "1.164.0",
4
4
  "description": "Alpic design system — shared UI components",
5
5
  "type": "module",
6
6
  "exports": {
@@ -64,8 +64,8 @@
64
64
  "@tailwindcss/postcss": "^4.3.3",
65
65
  "@types/react": "19.2.18",
66
66
  "@types/react-dom": "19.2.4",
67
- "lucide-react": "^1.28.0",
68
- "react-hook-form": "^7.84.0",
67
+ "lucide-react": "^1.30.0",
68
+ "react-hook-form": "^7.85.0",
69
69
  "shx": "^0.4.0",
70
70
  "sonner": "^2.0.7",
71
71
  "tailwindcss": "^4.3.3",
@@ -133,7 +133,10 @@ function AreaChart({
133
133
  ) : (
134
134
  <ResponsiveContainer width="100%" height="100%" initialDimension={{ width: 0, height }}>
135
135
  <RechartsAreaChart
136
- data={data as Record<string, string | number>[]}
136
+ data={
137
+ // biome-ignore lint/plugin/no-type-assertion: Recharts expects a string-indexed data shape.
138
+ data as Record<string, string | number>[]
139
+ }
137
140
  stackOffset={variant === "expand" ? "expand" : "none"}
138
141
  margin={margin}
139
142
  >
@@ -176,7 +176,10 @@ function BarChart({
176
176
  ) : (
177
177
  <ResponsiveContainer width="100%" height="100%" initialDimension={{ width: 0, height }}>
178
178
  <RechartsBarChart
179
- data={data as Record<string, string | number>[]}
179
+ data={
180
+ // biome-ignore lint/plugin/no-type-assertion: Recharts expects a string-indexed data shape.
181
+ data as Record<string, string | number>[]
182
+ }
180
183
  stackOffset={variant === "expand" ? "expand" : "none"}
181
184
  margin={margin}
182
185
  barCategoryGap={barCategoryGap ?? (stacked ? "20%" : "16%")}
@@ -262,6 +265,7 @@ function BarChart({
262
265
  data.map((row, rowIndex) => {
263
266
  const roundedTop = stacked ? topSlotByRow[rowIndex] === slot : true;
264
267
  const isPartial = partialLastBar && rowIndex === data.length - 1;
268
+ // biome-ignore lint/plugin/no-type-assertion: Recharts' Cell radius type does not model its tuple input.
265
269
  const cellRadius = (roundedTop
266
270
  ? [BAR_RADIUS, BAR_RADIUS, 0, 0]
267
271
  : [0, 0, 0, 0]) as unknown as number;
@@ -69,10 +69,12 @@ function Combobox(props: ComboboxProps) {
69
69
  } = props;
70
70
 
71
71
  const [uncontrolledSingleValue, setUncontrolledSingleValue] = useState<string | null>(
72
+ // biome-ignore lint/plugin/no-type-assertion: discriminated props cannot narrow through the separate multiple flag.
72
73
  !multiple ? ((props as ComboboxSingleProps).defaultValue ?? null) : null,
73
74
  );
74
75
 
75
76
  const [uncontrolledMultiValue, setUncontrolledMultiValue] = useState<string[]>(
77
+ // biome-ignore lint/plugin/no-type-assertion: discriminated props cannot narrow through the separate multiple flag.
76
78
  multiple ? ((props as ComboboxMultipleProps).defaultValue ?? []) : [],
77
79
  );
78
80
 
@@ -93,13 +95,17 @@ function Combobox(props: ComboboxProps) {
93
95
 
94
96
  const singleValue = multiple
95
97
  ? null
96
- : (((props as ComboboxSingleProps).value !== undefined
97
- ? (props as ComboboxSingleProps).value
98
+ : // biome-ignore lint/plugin/no-type-assertion: discriminated props cannot narrow through the separate multiple flag.
99
+ (((props as ComboboxSingleProps).value !== undefined
100
+ ? // biome-ignore lint/plugin/no-type-assertion: discriminated props cannot narrow through the separate multiple flag.
101
+ (props as ComboboxSingleProps).value
98
102
  : uncontrolledSingleValue) ?? null);
99
103
 
100
104
  const multiValues = multiple
101
- ? (props as ComboboxMultipleProps).value !== undefined
102
- ? ((props as ComboboxMultipleProps).value as string[])
105
+ ? // biome-ignore lint/plugin/no-type-assertion: discriminated props cannot narrow through the separate multiple flag.
106
+ (props as ComboboxMultipleProps).value !== undefined
107
+ ? // biome-ignore lint/plugin/no-type-assertion: discriminated props cannot narrow through the separate multiple flag.
108
+ ((props as ComboboxMultipleProps).value as string[])
103
109
  : uncontrolledMultiValue
104
110
  : [];
105
111
 
@@ -114,9 +120,13 @@ function Combobox(props: ComboboxProps) {
114
120
  );
115
121
 
116
122
  // Extract specific callbacks to avoid depending on the entire props object
123
+ // biome-ignore lint/plugin/no-type-assertion: discriminated props cannot narrow through the separate multiple flag.
117
124
  const onValueChangeSingle = !multiple ? (props as ComboboxSingleProps).onValueChange : undefined;
125
+ // biome-ignore lint/plugin/no-type-assertion: discriminated props cannot narrow through the separate multiple flag.
118
126
  const onValueChangeMulti = multiple ? (props as ComboboxMultipleProps).onValueChange : undefined;
127
+ // biome-ignore lint/plugin/no-type-assertion: discriminated props cannot narrow through the separate multiple flag.
119
128
  const isControlledSingle = !multiple && (props as ComboboxSingleProps).value !== undefined;
129
+ // biome-ignore lint/plugin/no-type-assertion: discriminated props cannot narrow through the separate multiple flag.
120
130
  const isControlledMulti = multiple && (props as ComboboxMultipleProps).value !== undefined;
121
131
 
122
132
  const onSelect = useCallback(
@@ -197,6 +207,7 @@ function ComboboxTrigger({ className, size, placeholder, children, ...props }: C
197
207
  const { multiple, value, values, open, onDeselect } = useComboboxContext();
198
208
 
199
209
  const isEmpty = multiple ? values.length === 0 : value === null || value === undefined;
210
+ const hasCustomMultipleValue = multiple && children !== undefined;
200
211
 
201
212
  return (
202
213
  <PopoverTrigger asChild>
@@ -211,11 +222,19 @@ function ComboboxTrigger({ className, size, placeholder, children, ...props }: C
211
222
  <span
212
223
  className={cn(
213
224
  "flex flex-1 items-center gap-1.5 text-left",
214
- multiple && "flex-wrap",
215
- isEmpty && "text-placeholder",
225
+ multiple && !hasCustomMultipleValue && "flex-wrap",
226
+ isEmpty && !hasCustomMultipleValue && "text-placeholder",
216
227
  )}
217
228
  >
218
- {isEmpty ? placeholder : multiple ? <ComboboxTags values={values} onDeselect={onDeselect} /> : children}
229
+ {hasCustomMultipleValue ? (
230
+ children
231
+ ) : isEmpty ? (
232
+ placeholder
233
+ ) : multiple ? (
234
+ <ComboboxTags values={values} onDeselect={onDeselect} />
235
+ ) : (
236
+ children
237
+ )}
219
238
  </span>
220
239
  <ChevronDownIcon className="size-5 shrink-0 text-muted-foreground" />
221
240
  </button>
@@ -31,6 +31,7 @@ type FormFieldContextValue<
31
31
  name: TName;
32
32
  };
33
33
 
34
+ // biome-ignore lint/plugin/no-type-assertion: consumers require a non-null context default before a provider is mounted.
34
35
  const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);
35
36
 
36
37
  const FormField = <
@@ -74,6 +75,7 @@ type FormItemContextValue = {
74
75
  id: string;
75
76
  };
76
77
 
78
+ // biome-ignore lint/plugin/no-type-assertion: consumers require a non-null context default before a provider is mounted.
77
79
  const FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);
78
80
 
79
81
  function FormItem({ className, ...props }: React.ComponentProps<"div">) {
@@ -68,6 +68,7 @@ function InputGroupAddon({
68
68
  data-align={align}
69
69
  className={cn(inputGroupAddonVariants({ align }), className)}
70
70
  onClick={(event) => {
71
+ // biome-ignore lint/plugin/no-type-assertion: click targets are DOM elements for this handler.
71
72
  if ((event.target as HTMLElement).closest("button")) {
72
73
  return;
73
74
  }
@@ -111,6 +111,7 @@ function LineChart({
111
111
  </div>
112
112
  ) : (
113
113
  <ResponsiveContainer width="100%" height="100%" initialDimension={{ width: 0, height }}>
114
+ {/* biome-ignore lint/plugin/no-type-assertion: Recharts expects a string-indexed data shape. */}
114
115
  <RechartsLineChart data={data as Record<string, string | number>[]} margin={margin}>
115
116
  <CartesianGrid vertical={false} stroke={theme.grid} strokeDasharray="2 4" />
116
117
  <XAxis
@@ -127,6 +127,7 @@ function SidebarProvider({
127
127
  <div
128
128
  data-slot="sidebar-wrapper"
129
129
  style={
130
+ // biome-ignore lint/plugin/no-type-assertion: CSS custom properties are not included in React's style type.
130
131
  {
131
132
  "--sidebar-width": SIDEBAR_WIDTH,
132
133
  "--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
@@ -195,6 +196,7 @@ function Sidebar({
195
196
  data-mobile="true"
196
197
  className="bg-sidebar-surface text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
197
198
  style={
199
+ // biome-ignore lint/plugin/no-type-assertion: CSS custom properties are not included in React's style type.
198
200
  {
199
201
  "--sidebar-width": SIDEBAR_WIDTH_MOBILE,
200
202
  } as React.CSSProperties
@@ -54,8 +54,10 @@ const readTheme = (): ChartTheme => {
54
54
  const styles = window.getComputedStyle(document.documentElement);
55
55
  const entries = Object.entries(TOKEN_MAP).map(([key, token]) => {
56
56
  const value = styles.getPropertyValue(token).trim();
57
+ // biome-ignore lint/plugin/no-type-assertion: token keys correspond to the chart theme's required color keys.
57
58
  return [key, value || FALLBACK[key as keyof ChartTheme]] as const;
58
59
  });
60
+ // biome-ignore lint/plugin/no-type-assertion: Object.fromEntries cannot preserve the statically known chart-theme keys.
59
61
  const colors = Object.fromEntries(entries) as unknown as Omit<ChartTheme, "isDark">;
60
62
  return { ...colors, isDark: document.documentElement.classList.contains("dark") };
61
63
  };
@@ -82,9 +82,11 @@ const fmtK = (value: number) => (value >= 1000 ? `${(value / 1000).toFixed(value
82
82
  const ms = (value: number) => `${value}ms`;
83
83
 
84
84
  const sessionsTotal = stacked.reduce(
85
+ // biome-ignore lint/plugin/no-type-assertion: each client key is populated with a numeric sample in this fixture.
85
86
  (sum, row) => sum + CLIENTS.reduce((acc, client) => acc + (row[client] as number), 0),
86
87
  0,
87
88
  );
89
+ // biome-ignore lint/plugin/no-type-assertion: each client key is populated with a numeric sample in this fixture.
88
90
  const sessionsSpark = stacked.map((row) => CLIENTS.reduce((acc, client) => acc + (row[client] as number), 0));
89
91
 
90
92
  const latencyPeak = latency.reduce((best, row) => (row.p95 > best.p95 ? row : best));
@@ -70,9 +70,11 @@ const fmtK = (value: number) => (value >= 1000 ? `${(value / 1000).toFixed(value
70
70
  const ms = (value: number) => `${value}ms`;
71
71
 
72
72
  const sessionsTotal = stacked.reduce(
73
+ // biome-ignore lint/plugin/no-type-assertion: each client key is populated with a numeric sample in this fixture.
73
74
  (sum, row) => sum + CLIENTS.reduce((acc, client) => acc + (row[client] as number), 0),
74
75
  0,
75
76
  );
77
+ // biome-ignore lint/plugin/no-type-assertion: each client key is populated with a numeric sample in this fixture.
76
78
  const sessionsSpark = stacked.map((row) => CLIENTS.reduce((acc, client) => acc + (row[client] as number), 0));
77
79
 
78
80
  const errorsPeak = errors.reduce((best, row) => (row.mcp + row.tool > best.mcp + best.tool ? row : best));