@tidbcloud/uikit 2.2.1 → 2.2.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @tidbcloud/uikit
2
2
 
3
+ ## 2.2.3
4
+
5
+ ### Patch Changes
6
+
7
+ - fix(theme): Enhance Radio and Radio.Indicator styling ([#497](https://github.com/tidbcloud/tidbcloud-uikit/pull/497))
8
+
9
+ ## 2.2.2
10
+
11
+ ### Patch Changes
12
+
13
+ - feat: allow select all for ProMultiSelect component ([#495](https://github.com/tidbcloud/tidbcloud-uikit/pull/495))
14
+
3
15
  ## 2.2.1
4
16
 
5
17
  ### Patch Changes
@@ -19,17 +19,18 @@ const defaultOptionsFilter = require("../../node_modules/.pnpm/@mantine_core@7.1
19
19
  const Pill = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Pill/Pill.cjs");
20
20
  const isOptionsGroup = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Combobox/OptionsDropdown/is-options-group.cjs");
21
21
  const Combobox = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Combobox/Combobox.cjs");
22
+ const Group = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Group/Group.cjs");
23
+ const Checkbox = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Checkbox/Checkbox.cjs");
24
+ const Box = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/core/Box/Box.cjs");
25
+ const Divider = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Divider/Divider.cjs");
22
26
  const InputBase = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/InputBase/InputBase.cjs");
23
27
  const Loader = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Loader/Loader.cjs");
24
28
  const Input = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Input/Input.cjs");
25
29
  const ScrollArea = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/ScrollArea/ScrollArea.cjs");
26
- const Group = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Group/Group.cjs");
27
- const Box = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/core/Box/Box.cjs");
28
- const Checkbox = require("../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Checkbox/Checkbox.cjs");
29
30
  const Option = ({ data, withCheckIcon, value, checkIconPosition, unstyled, renderOption }) => {
30
31
  if (!isOptionsGroup.isOptionsGroup(data)) {
31
32
  const checked = helper.isValueChecked(value, data.value);
32
- const check = withCheckIcon && /* @__PURE__ */ jsxRuntime.jsx(Checkbox.Checkbox, { size: "xs", checked });
33
+ const check = withCheckIcon && /* @__PURE__ */ jsxRuntime.jsx(Checkbox.Checkbox, { size: "xs", checked, "aria-checked": checked, readOnly: true });
33
34
  const defaultContent = /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { children: [
34
35
  checkIconPosition === "left" && check,
35
36
  /* @__PURE__ */ jsxRuntime.jsx(Box.Box, { sx: { flex: 1 }, children: data.label }),
@@ -75,6 +76,104 @@ const defaultProps = {
75
76
  checkIconPosition: "left",
76
77
  hiddenInputValuesDivider: ","
77
78
  };
79
+ const ValuesVisible = ({ moreCount, readOnly, values, disabled, onRemove, optionsLockup }) => {
80
+ const containerRef = React.useRef(null);
81
+ const [valsVisible, setValsVisible] = React.useState(values);
82
+ const [moreVisible, setMoreVisible] = React.useState(moreCount);
83
+ const [isLongFirstOverflow, setIsLongFirstOverflow] = React.useState(false);
84
+ const isCheckOverflowEnd = React.useRef(false);
85
+ React.useLayoutEffect(() => {
86
+ const container = containerRef.current;
87
+ if (!container) {
88
+ return;
89
+ }
90
+ const resizeObserver = new ResizeObserver(() => {
91
+ isCheckOverflowEnd.current = false;
92
+ setValsVisible(values);
93
+ setMoreVisible(moreCount);
94
+ });
95
+ resizeObserver.observe(container);
96
+ return () => resizeObserver.unobserve(container);
97
+ }, [values, moreCount]);
98
+ React.useLayoutEffect(() => {
99
+ const container = containerRef.current;
100
+ if (!container || isCheckOverflowEnd.current) {
101
+ return;
102
+ }
103
+ const isOverflow = container.scrollWidth > container.clientWidth;
104
+ if (isOverflow) {
105
+ if (valsVisible.length === 1) {
106
+ isCheckOverflowEnd.current = true;
107
+ setIsLongFirstOverflow(true);
108
+ return;
109
+ }
110
+ const newValsVisible = valsVisible.slice(0, -1);
111
+ const newMoreVisible = moreVisible + 1;
112
+ setValsVisible(newValsVisible);
113
+ setMoreVisible(newMoreVisible);
114
+ } else if (!isOverflow && isLongFirstOverflow) {
115
+ setIsLongFirstOverflow(false);
116
+ } else {
117
+ isCheckOverflowEnd.current = true;
118
+ }
119
+ }, [valsVisible, moreVisible, isLongFirstOverflow]);
120
+ return /* @__PURE__ */ jsxRuntime.jsxs(
121
+ Pill.Pill.Group,
122
+ {
123
+ mah: 22,
124
+ sx: {
125
+ display: "flex",
126
+ flexWrap: "nowrap",
127
+ overflow: "hidden"
128
+ },
129
+ ref: containerRef,
130
+ children: [
131
+ valsVisible.map((item, index2) => {
132
+ var _a, _b;
133
+ return /* @__PURE__ */ jsxRuntime.jsx(
134
+ Pill.Pill,
135
+ {
136
+ withRemoveButton: !readOnly && !((_a = optionsLockup[item]) == null ? void 0 : _a.disabled),
137
+ onRemove: () => {
138
+ onRemove(item);
139
+ },
140
+ disabled,
141
+ styles: (theme) => ({
142
+ root: {
143
+ backgroundColor: theme.colors.carbon[3],
144
+ borderRadius: theme.radius.sm,
145
+ // if the first item is too long, we need to set flex: 1 and minWidth: 0 to make it shrink
146
+ flex: isLongFirstOverflow ? "1" : void 0,
147
+ minWidth: isLongFirstOverflow ? 0 : void 0
148
+ }
149
+ }),
150
+ children: ((_b = optionsLockup[item]) == null ? void 0 : _b.label) || item
151
+ },
152
+ `${item}-${index2}`
153
+ );
154
+ }),
155
+ /* @__PURE__ */ jsxRuntime.jsxs(
156
+ Pill.Pill,
157
+ {
158
+ styles: (theme) => ({
159
+ root: {
160
+ backgroundColor: theme.colors.carbon[3],
161
+ borderRadius: theme.radius.sm,
162
+ display: moreCount > 0 ? "block" : "none",
163
+ opacity: moreVisible > 0 ? 1 : 0,
164
+ flexShrink: 0
165
+ }
166
+ }),
167
+ children: [
168
+ "+",
169
+ moreVisible
170
+ ]
171
+ }
172
+ )
173
+ ]
174
+ }
175
+ );
176
+ };
78
177
  const ProMultiSelect = (_props) => {
79
178
  const props = useProps.useProps("MultiSelect", defaultProps, _props);
80
179
  const {
@@ -100,6 +199,8 @@ const ProMultiSelect = (_props) => {
100
199
  loading,
101
200
  maxDropdownHeight,
102
201
  error,
202
+ allowSelectAll,
203
+ selectAllText,
103
204
  onOptionSubmit,
104
205
  renderOption,
105
206
  filter,
@@ -140,11 +241,10 @@ const ProMultiSelect = (_props) => {
140
241
  search: searchable ? _searchValue : "",
141
242
  limit: limit ?? Infinity
142
243
  }) : parsedData;
143
- const [targetIndex, setTargetIndex] = React.useState(0);
144
- const hideCount = _value.length - targetIndex - 1;
145
- const values = _value.map((item, index2) => {
244
+ const [targetIndex, setTargetIndex] = React.useState(-1);
245
+ const valuesForCompute = _value.map((item, index2) => {
146
246
  var _a, _b;
147
- return /* @__PURE__ */ jsxRuntime.jsxs(
247
+ return /* @__PURE__ */ jsxRuntime.jsx(
148
248
  Pill.Pill,
149
249
  {
150
250
  withRemoveButton: !readOnly && !((_a = optionsLockup[item]) == null ? void 0 : _a.disabled),
@@ -154,23 +254,7 @@ const ProMultiSelect = (_props) => {
154
254
  },
155
255
  disabled,
156
256
  styles: (theme2) => ({ root: { backgroundColor: theme2.colors.carbon[3], borderRadius: theme2.radius.sm } }),
157
- sx: { position: "relative" },
158
- children: [
159
- ((_b = optionsLockup[item]) == null ? void 0 : _b.label) || item,
160
- targetIndex === index2 && /* @__PURE__ */ jsxRuntime.jsxs(
161
- Pill.Pill,
162
- {
163
- styles: (theme2) => ({
164
- root: { backgroundColor: theme2.colors.carbon[3], borderRadius: theme2.radius.sm, padding: "0 5px" }
165
- }),
166
- sx: { position: "absolute", right: 0, transform: "translateX(calc(100% + 8px))" },
167
- children: [
168
- "+",
169
- hideCount
170
- ]
171
- }
172
- )
173
- ]
257
+ children: ((_b = optionsLockup[item]) == null ? void 0 : _b.label) || item
174
258
  },
175
259
  `${item}-${index2}`
176
260
  );
@@ -179,10 +263,15 @@ const ProMultiSelect = (_props) => {
179
263
  React.useLayoutEffect(() => {
180
264
  var _a;
181
265
  const child = (_a = inputRef.current) == null ? void 0 : _a.children;
182
- if (!child || (child == null ? void 0 : child.length) === 0) return;
183
- const index2 = Array.from(child).findIndex((child2) => child2.offsetTop > 20);
184
- setTargetIndex(index2 - 1);
185
- }, [values]);
266
+ if (!child || (child == null ? void 0 : child.length) <= 1) {
267
+ return;
268
+ }
269
+ const firstOffsetLeft = child[0].offsetLeft;
270
+ const index2 = Array.from(child).findIndex(
271
+ (child2, idx) => child2.offsetLeft === firstOffsetLeft && idx > 0
272
+ );
273
+ setTargetIndex(index2);
274
+ }, [_value]);
186
275
  const options = filteredData == null ? void 0 : filteredData.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
187
276
  Option,
188
277
  {
@@ -195,15 +284,63 @@ const ProMultiSelect = (_props) => {
195
284
  },
196
285
  isOptionsGroup.isOptionsGroup(item) ? item.group : item.value
197
286
  ));
287
+ const allChecked = React.useMemo(() => {
288
+ return parsedData.every((value2) => {
289
+ if (isOptionsGroup.isOptionsGroup(value2)) {
290
+ return value2.items.every((item) => _value.includes(item.value));
291
+ } else {
292
+ return _value.includes(value2.value);
293
+ }
294
+ });
295
+ }, [parsedData, _value]);
296
+ const indeterminate = _value.length > 0 && !allChecked;
297
+ const selectAll = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
298
+ /* @__PURE__ */ jsxRuntime.jsx(
299
+ Combobox.Combobox.Option,
300
+ {
301
+ value: "_select_all",
302
+ "data-checked": allChecked,
303
+ "aria-selected": allChecked,
304
+ active: allChecked,
305
+ styles: (theme2) => ({
306
+ option: {
307
+ "&:hover": {
308
+ backgroundColor: theme2.colors.carbon[3]
309
+ }
310
+ }
311
+ }),
312
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { children: [
313
+ /* @__PURE__ */ jsxRuntime.jsx(Checkbox.Checkbox, { size: "xs", checked: allChecked, indeterminate, "aria-checked": allChecked, readOnly: true }),
314
+ /* @__PURE__ */ jsxRuntime.jsx(Box.Box, { sx: { flex: 1 }, children: selectAllText || "All" })
315
+ ] })
316
+ }
317
+ ),
318
+ /* @__PURE__ */ jsxRuntime.jsx(Divider.Divider, { color: "carbon.3" })
319
+ ] });
198
320
  const handleOptionSubmit = (val) => {
199
- onOptionSubmit == null ? void 0 : onOptionSubmit(val);
200
- setSearchValue("");
201
- combobox.updateSelectedOptionIndex("selected");
202
- if (_value.includes(optionsLockup[val].value)) {
203
- setValue(_value.filter((v) => v !== optionsLockup[val].value));
204
- onRemove == null ? void 0 : onRemove(optionsLockup[val].value);
205
- } else if (_value.length < maxValues) {
206
- setValue([..._value, optionsLockup[val].value]);
321
+ if (val === "_select_all") {
322
+ if (allChecked) {
323
+ setValue([]);
324
+ } else {
325
+ const allValues = parsedData.reduce((acc, value2) => {
326
+ if (isOptionsGroup.isOptionsGroup(value2)) {
327
+ return [...acc, ...value2.items.map((item) => item.value)];
328
+ } else {
329
+ return [...acc, value2.value];
330
+ }
331
+ }, []);
332
+ setValue(allValues);
333
+ }
334
+ } else {
335
+ onOptionSubmit == null ? void 0 : onOptionSubmit(val);
336
+ setSearchValue("");
337
+ combobox.updateSelectedOptionIndex("selected");
338
+ if (_value.includes(optionsLockup[val].value)) {
339
+ setValue(_value.filter((v) => v !== optionsLockup[val].value));
340
+ onRemove == null ? void 0 : onRemove(optionsLockup[val].value);
341
+ } else if (_value.length < maxValues) {
342
+ setValue([..._value, optionsLockup[val].value]);
343
+ }
207
344
  }
208
345
  };
209
346
  const clearButton = /* @__PURE__ */ jsxRuntime.jsx(
@@ -217,6 +354,7 @@ const ProMultiSelect = (_props) => {
217
354
  }
218
355
  );
219
356
  const _clearable = clearable && _value.length > 0 && !disabled && !readOnly;
357
+ const moreCount = targetIndex > 0 ? _value.length - targetIndex : 0;
220
358
  return /* @__PURE__ */ jsxRuntime.jsxs(
221
359
  Combobox.Combobox,
222
360
  {
@@ -260,9 +398,27 @@ const ProMultiSelect = (_props) => {
260
398
  sx: {
261
399
  flexWrap: "wrap",
262
400
  overflowY: "clip",
263
- maxWidth: `calc(100% - ${(hideCount.toString().length + 2) * 8}px)`
401
+ maxWidth: "100%",
402
+ opacity: 0,
403
+ pointerEvents: "none",
404
+ height: 0
264
405
  },
265
- children: values
406
+ children: valuesForCompute
407
+ }
408
+ ),
409
+ // _value.length > 0 is required. Because this component need a render cycle to synchronize props to state. So if we remove '_value.length > 0', when we uncheck the last item, the placeholder will show, but at that moment, the state in this ValuesVisible component keeps previous values
410
+ _value.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
411
+ ValuesVisible,
412
+ {
413
+ disabled,
414
+ readOnly,
415
+ optionsLockup,
416
+ moreCount,
417
+ values: _value.slice(0, targetIndex > 0 ? targetIndex : _value.length),
418
+ onRemove: (item) => {
419
+ setValue(_value.filter((i) => item !== i));
420
+ onRemove == null ? void 0 : onRemove(item);
421
+ }
266
422
  }
267
423
  )
268
424
  ]
@@ -282,7 +438,10 @@ const ProMultiSelect = (_props) => {
282
438
  placeholder: "Find"
283
439
  }
284
440
  ),
285
- /* @__PURE__ */ jsxRuntime.jsx(ScrollArea.ScrollArea.Autosize, { type: "scroll", mah: maxDropdownHeight ?? 200, children: /* @__PURE__ */ jsxRuntime.jsx(Combobox.Combobox.Options, { children: options.length > 0 ? options : /* @__PURE__ */ jsxRuntime.jsx(Combobox.Combobox.Empty, { children: nothingFoundMessage || "Nothing found" }) }) })
441
+ /* @__PURE__ */ jsxRuntime.jsxs(ScrollArea.ScrollArea.Autosize, { type: "scroll", mah: maxDropdownHeight ?? 200, children: [
442
+ allowSelectAll && selectAll,
443
+ /* @__PURE__ */ jsxRuntime.jsx(Combobox.Combobox.Options, { children: options.length > 0 ? options : /* @__PURE__ */ jsxRuntime.jsx(Combobox.Combobox.Empty, { children: nothingFoundMessage || "Nothing found" }) })
444
+ ] })
286
445
  ] })
287
446
  ]
288
447
  }
@@ -2,5 +2,7 @@ import { default as React } from 'react';
2
2
  import { MultiSelectProps } from '../../primitive/index.cjs';
3
3
  export interface ProMultiSelectProps extends Pick<MultiSelectProps, 'data' | 'value' | 'defaultValue' | 'limit' | 'searchable' | 'searchValue' | 'defaultSearchValue' | 'maxValues' | 'readOnly' | 'disabled' | 'size' | 'width' | 'selectFirstOptionOnChange' | 'placeholder' | 'clearable' | 'label' | 'nothingFoundMessage' | 'dropdownOpened' | 'defaultDropdownOpened' | 'maxDropdownHeight' | 'error' | 'onOptionSubmit' | 'renderOption' | 'filter' | 'onChange' | 'onSearchChange' | 'onRemove' | 'onClear'> {
4
4
  loading?: boolean;
5
+ allowSelectAll?: boolean;
6
+ selectAllText?: string;
5
7
  }
6
8
  export declare const ProMultiSelect: React.FC<ProMultiSelectProps>;
@@ -2,5 +2,7 @@ import { default as React } from 'react';
2
2
  import { MultiSelectProps } from '../../primitive/index.mjs';
3
3
  export interface ProMultiSelectProps extends Pick<MultiSelectProps, 'data' | 'value' | 'defaultValue' | 'limit' | 'searchable' | 'searchValue' | 'defaultSearchValue' | 'maxValues' | 'readOnly' | 'disabled' | 'size' | 'width' | 'selectFirstOptionOnChange' | 'placeholder' | 'clearable' | 'label' | 'nothingFoundMessage' | 'dropdownOpened' | 'defaultDropdownOpened' | 'maxDropdownHeight' | 'error' | 'onOptionSubmit' | 'renderOption' | 'filter' | 'onChange' | 'onSearchChange' | 'onRemove' | 'onClear'> {
4
4
  loading?: boolean;
5
+ allowSelectAll?: boolean;
6
+ selectAllText?: string;
5
7
  }
6
8
  export declare const ProMultiSelect: React.FC<ProMultiSelectProps>;
@@ -1,5 +1,5 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
2
- import { useState, useRef, useLayoutEffect } from "react";
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { useState, useRef, useLayoutEffect, useMemo } from "react";
3
3
  import { IconSearchLg } from "../../icons/index.mjs";
4
4
  /* empty css */
5
5
  /* empty css */
@@ -17,17 +17,18 @@ import { defaultOptionsFilter } from "../../node_modules/.pnpm/@mantine_core@7.1
17
17
  import { Pill } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Pill/Pill.mjs";
18
18
  import { isOptionsGroup } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Combobox/OptionsDropdown/is-options-group.mjs";
19
19
  import { Combobox } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Combobox/Combobox.mjs";
20
+ import { Group } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Group/Group.mjs";
21
+ import { Checkbox } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Checkbox/Checkbox.mjs";
22
+ import { Box } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/core/Box/Box.mjs";
23
+ import { Divider } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Divider/Divider.mjs";
20
24
  import { InputBase } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/InputBase/InputBase.mjs";
21
25
  import { Loader } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Loader/Loader.mjs";
22
26
  import { Input } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Input/Input.mjs";
23
27
  import { ScrollArea } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/ScrollArea/ScrollArea.mjs";
24
- import { Group } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Group/Group.mjs";
25
- import { Box } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/core/Box/Box.mjs";
26
- import { Checkbox } from "../../node_modules/.pnpm/@mantine_core@7.15.2_patch_hash_jclkxeaefn6uz54h34k3r3yjsq_@mantine_hooks@7.15.2_react@18.3.1_szqfuioo5damkjdixckhzmwycq/node_modules/@mantine/core/esm/components/Checkbox/Checkbox.mjs";
27
28
  const Option = ({ data, withCheckIcon, value, checkIconPosition, unstyled, renderOption }) => {
28
29
  if (!isOptionsGroup(data)) {
29
30
  const checked = isValueChecked(value, data.value);
30
- const check = withCheckIcon && /* @__PURE__ */ jsx(Checkbox, { size: "xs", checked });
31
+ const check = withCheckIcon && /* @__PURE__ */ jsx(Checkbox, { size: "xs", checked, "aria-checked": checked, readOnly: true });
31
32
  const defaultContent = /* @__PURE__ */ jsxs(Group, { children: [
32
33
  checkIconPosition === "left" && check,
33
34
  /* @__PURE__ */ jsx(Box, { sx: { flex: 1 }, children: data.label }),
@@ -73,6 +74,104 @@ const defaultProps = {
73
74
  checkIconPosition: "left",
74
75
  hiddenInputValuesDivider: ","
75
76
  };
77
+ const ValuesVisible = ({ moreCount, readOnly, values, disabled, onRemove, optionsLockup }) => {
78
+ const containerRef = useRef(null);
79
+ const [valsVisible, setValsVisible] = useState(values);
80
+ const [moreVisible, setMoreVisible] = useState(moreCount);
81
+ const [isLongFirstOverflow, setIsLongFirstOverflow] = useState(false);
82
+ const isCheckOverflowEnd = useRef(false);
83
+ useLayoutEffect(() => {
84
+ const container = containerRef.current;
85
+ if (!container) {
86
+ return;
87
+ }
88
+ const resizeObserver = new ResizeObserver(() => {
89
+ isCheckOverflowEnd.current = false;
90
+ setValsVisible(values);
91
+ setMoreVisible(moreCount);
92
+ });
93
+ resizeObserver.observe(container);
94
+ return () => resizeObserver.unobserve(container);
95
+ }, [values, moreCount]);
96
+ useLayoutEffect(() => {
97
+ const container = containerRef.current;
98
+ if (!container || isCheckOverflowEnd.current) {
99
+ return;
100
+ }
101
+ const isOverflow = container.scrollWidth > container.clientWidth;
102
+ if (isOverflow) {
103
+ if (valsVisible.length === 1) {
104
+ isCheckOverflowEnd.current = true;
105
+ setIsLongFirstOverflow(true);
106
+ return;
107
+ }
108
+ const newValsVisible = valsVisible.slice(0, -1);
109
+ const newMoreVisible = moreVisible + 1;
110
+ setValsVisible(newValsVisible);
111
+ setMoreVisible(newMoreVisible);
112
+ } else if (!isOverflow && isLongFirstOverflow) {
113
+ setIsLongFirstOverflow(false);
114
+ } else {
115
+ isCheckOverflowEnd.current = true;
116
+ }
117
+ }, [valsVisible, moreVisible, isLongFirstOverflow]);
118
+ return /* @__PURE__ */ jsxs(
119
+ Pill.Group,
120
+ {
121
+ mah: 22,
122
+ sx: {
123
+ display: "flex",
124
+ flexWrap: "nowrap",
125
+ overflow: "hidden"
126
+ },
127
+ ref: containerRef,
128
+ children: [
129
+ valsVisible.map((item, index) => {
130
+ var _a, _b;
131
+ return /* @__PURE__ */ jsx(
132
+ Pill,
133
+ {
134
+ withRemoveButton: !readOnly && !((_a = optionsLockup[item]) == null ? void 0 : _a.disabled),
135
+ onRemove: () => {
136
+ onRemove(item);
137
+ },
138
+ disabled,
139
+ styles: (theme) => ({
140
+ root: {
141
+ backgroundColor: theme.colors.carbon[3],
142
+ borderRadius: theme.radius.sm,
143
+ // if the first item is too long, we need to set flex: 1 and minWidth: 0 to make it shrink
144
+ flex: isLongFirstOverflow ? "1" : void 0,
145
+ minWidth: isLongFirstOverflow ? 0 : void 0
146
+ }
147
+ }),
148
+ children: ((_b = optionsLockup[item]) == null ? void 0 : _b.label) || item
149
+ },
150
+ `${item}-${index}`
151
+ );
152
+ }),
153
+ /* @__PURE__ */ jsxs(
154
+ Pill,
155
+ {
156
+ styles: (theme) => ({
157
+ root: {
158
+ backgroundColor: theme.colors.carbon[3],
159
+ borderRadius: theme.radius.sm,
160
+ display: moreCount > 0 ? "block" : "none",
161
+ opacity: moreVisible > 0 ? 1 : 0,
162
+ flexShrink: 0
163
+ }
164
+ }),
165
+ children: [
166
+ "+",
167
+ moreVisible
168
+ ]
169
+ }
170
+ )
171
+ ]
172
+ }
173
+ );
174
+ };
76
175
  const ProMultiSelect = (_props) => {
77
176
  const props = useProps("MultiSelect", defaultProps, _props);
78
177
  const {
@@ -98,6 +197,8 @@ const ProMultiSelect = (_props) => {
98
197
  loading,
99
198
  maxDropdownHeight,
100
199
  error,
200
+ allowSelectAll,
201
+ selectAllText,
101
202
  onOptionSubmit,
102
203
  renderOption,
103
204
  filter,
@@ -138,11 +239,10 @@ const ProMultiSelect = (_props) => {
138
239
  search: searchable ? _searchValue : "",
139
240
  limit: limit ?? Infinity
140
241
  }) : parsedData;
141
- const [targetIndex, setTargetIndex] = useState(0);
142
- const hideCount = _value.length - targetIndex - 1;
143
- const values = _value.map((item, index) => {
242
+ const [targetIndex, setTargetIndex] = useState(-1);
243
+ const valuesForCompute = _value.map((item, index) => {
144
244
  var _a, _b;
145
- return /* @__PURE__ */ jsxs(
245
+ return /* @__PURE__ */ jsx(
146
246
  Pill,
147
247
  {
148
248
  withRemoveButton: !readOnly && !((_a = optionsLockup[item]) == null ? void 0 : _a.disabled),
@@ -152,23 +252,7 @@ const ProMultiSelect = (_props) => {
152
252
  },
153
253
  disabled,
154
254
  styles: (theme2) => ({ root: { backgroundColor: theme2.colors.carbon[3], borderRadius: theme2.radius.sm } }),
155
- sx: { position: "relative" },
156
- children: [
157
- ((_b = optionsLockup[item]) == null ? void 0 : _b.label) || item,
158
- targetIndex === index && /* @__PURE__ */ jsxs(
159
- Pill,
160
- {
161
- styles: (theme2) => ({
162
- root: { backgroundColor: theme2.colors.carbon[3], borderRadius: theme2.radius.sm, padding: "0 5px" }
163
- }),
164
- sx: { position: "absolute", right: 0, transform: "translateX(calc(100% + 8px))" },
165
- children: [
166
- "+",
167
- hideCount
168
- ]
169
- }
170
- )
171
- ]
255
+ children: ((_b = optionsLockup[item]) == null ? void 0 : _b.label) || item
172
256
  },
173
257
  `${item}-${index}`
174
258
  );
@@ -177,10 +261,15 @@ const ProMultiSelect = (_props) => {
177
261
  useLayoutEffect(() => {
178
262
  var _a;
179
263
  const child = (_a = inputRef.current) == null ? void 0 : _a.children;
180
- if (!child || (child == null ? void 0 : child.length) === 0) return;
181
- const index = Array.from(child).findIndex((child2) => child2.offsetTop > 20);
182
- setTargetIndex(index - 1);
183
- }, [values]);
264
+ if (!child || (child == null ? void 0 : child.length) <= 1) {
265
+ return;
266
+ }
267
+ const firstOffsetLeft = child[0].offsetLeft;
268
+ const index = Array.from(child).findIndex(
269
+ (child2, idx) => child2.offsetLeft === firstOffsetLeft && idx > 0
270
+ );
271
+ setTargetIndex(index);
272
+ }, [_value]);
184
273
  const options = filteredData == null ? void 0 : filteredData.map((item) => /* @__PURE__ */ jsx(
185
274
  Option,
186
275
  {
@@ -193,15 +282,63 @@ const ProMultiSelect = (_props) => {
193
282
  },
194
283
  isOptionsGroup(item) ? item.group : item.value
195
284
  ));
285
+ const allChecked = useMemo(() => {
286
+ return parsedData.every((value2) => {
287
+ if (isOptionsGroup(value2)) {
288
+ return value2.items.every((item) => _value.includes(item.value));
289
+ } else {
290
+ return _value.includes(value2.value);
291
+ }
292
+ });
293
+ }, [parsedData, _value]);
294
+ const indeterminate = _value.length > 0 && !allChecked;
295
+ const selectAll = /* @__PURE__ */ jsxs(Fragment, { children: [
296
+ /* @__PURE__ */ jsx(
297
+ Combobox.Option,
298
+ {
299
+ value: "_select_all",
300
+ "data-checked": allChecked,
301
+ "aria-selected": allChecked,
302
+ active: allChecked,
303
+ styles: (theme2) => ({
304
+ option: {
305
+ "&:hover": {
306
+ backgroundColor: theme2.colors.carbon[3]
307
+ }
308
+ }
309
+ }),
310
+ children: /* @__PURE__ */ jsxs(Group, { children: [
311
+ /* @__PURE__ */ jsx(Checkbox, { size: "xs", checked: allChecked, indeterminate, "aria-checked": allChecked, readOnly: true }),
312
+ /* @__PURE__ */ jsx(Box, { sx: { flex: 1 }, children: selectAllText || "All" })
313
+ ] })
314
+ }
315
+ ),
316
+ /* @__PURE__ */ jsx(Divider, { color: "carbon.3" })
317
+ ] });
196
318
  const handleOptionSubmit = (val) => {
197
- onOptionSubmit == null ? void 0 : onOptionSubmit(val);
198
- setSearchValue("");
199
- combobox.updateSelectedOptionIndex("selected");
200
- if (_value.includes(optionsLockup[val].value)) {
201
- setValue(_value.filter((v) => v !== optionsLockup[val].value));
202
- onRemove == null ? void 0 : onRemove(optionsLockup[val].value);
203
- } else if (_value.length < maxValues) {
204
- setValue([..._value, optionsLockup[val].value]);
319
+ if (val === "_select_all") {
320
+ if (allChecked) {
321
+ setValue([]);
322
+ } else {
323
+ const allValues = parsedData.reduce((acc, value2) => {
324
+ if (isOptionsGroup(value2)) {
325
+ return [...acc, ...value2.items.map((item) => item.value)];
326
+ } else {
327
+ return [...acc, value2.value];
328
+ }
329
+ }, []);
330
+ setValue(allValues);
331
+ }
332
+ } else {
333
+ onOptionSubmit == null ? void 0 : onOptionSubmit(val);
334
+ setSearchValue("");
335
+ combobox.updateSelectedOptionIndex("selected");
336
+ if (_value.includes(optionsLockup[val].value)) {
337
+ setValue(_value.filter((v) => v !== optionsLockup[val].value));
338
+ onRemove == null ? void 0 : onRemove(optionsLockup[val].value);
339
+ } else if (_value.length < maxValues) {
340
+ setValue([..._value, optionsLockup[val].value]);
341
+ }
205
342
  }
206
343
  };
207
344
  const clearButton = /* @__PURE__ */ jsx(
@@ -215,6 +352,7 @@ const ProMultiSelect = (_props) => {
215
352
  }
216
353
  );
217
354
  const _clearable = clearable && _value.length > 0 && !disabled && !readOnly;
355
+ const moreCount = targetIndex > 0 ? _value.length - targetIndex : 0;
218
356
  return /* @__PURE__ */ jsxs(
219
357
  Combobox,
220
358
  {
@@ -258,9 +396,27 @@ const ProMultiSelect = (_props) => {
258
396
  sx: {
259
397
  flexWrap: "wrap",
260
398
  overflowY: "clip",
261
- maxWidth: `calc(100% - ${(hideCount.toString().length + 2) * 8}px)`
399
+ maxWidth: "100%",
400
+ opacity: 0,
401
+ pointerEvents: "none",
402
+ height: 0
262
403
  },
263
- children: values
404
+ children: valuesForCompute
405
+ }
406
+ ),
407
+ // _value.length > 0 is required. Because this component need a render cycle to synchronize props to state. So if we remove '_value.length > 0', when we uncheck the last item, the placeholder will show, but at that moment, the state in this ValuesVisible component keeps previous values
408
+ _value.length > 0 && /* @__PURE__ */ jsx(
409
+ ValuesVisible,
410
+ {
411
+ disabled,
412
+ readOnly,
413
+ optionsLockup,
414
+ moreCount,
415
+ values: _value.slice(0, targetIndex > 0 ? targetIndex : _value.length),
416
+ onRemove: (item) => {
417
+ setValue(_value.filter((i) => item !== i));
418
+ onRemove == null ? void 0 : onRemove(item);
419
+ }
264
420
  }
265
421
  )
266
422
  ]
@@ -280,7 +436,10 @@ const ProMultiSelect = (_props) => {
280
436
  placeholder: "Find"
281
437
  }
282
438
  ),
283
- /* @__PURE__ */ jsx(ScrollArea.Autosize, { type: "scroll", mah: maxDropdownHeight ?? 200, children: /* @__PURE__ */ jsx(Combobox.Options, { children: options.length > 0 ? options : /* @__PURE__ */ jsx(Combobox.Empty, { children: nothingFoundMessage || "Nothing found" }) }) })
439
+ /* @__PURE__ */ jsxs(ScrollArea.Autosize, { type: "scroll", mah: maxDropdownHeight ?? 200, children: [
440
+ allowSelectAll && selectAll,
441
+ /* @__PURE__ */ jsx(Combobox.Options, { children: options.length > 0 ? options : /* @__PURE__ */ jsx(Combobox.Empty, { children: nothingFoundMessage || "Nothing found" }) })
442
+ ] })
284
443
  ] })
285
444
  ]
286
445
  }
@@ -918,6 +918,7 @@ const theme = createTheme.createTheme({
918
918
  transform: "var(--radio-icon-transform, scale(0.2))"
919
919
  },
920
920
  radio: {
921
+ borderColor: themeColor(theme2, "carbon", 6),
921
922
  "&:disabled:not(:checked)": {
922
923
  background: themeColor(theme2, "carbon", 4),
923
924
  borderColor: themeColor(theme2, "carbon", 6),
@@ -933,6 +934,31 @@ const theme = createTheme.createTheme({
933
934
  };
934
935
  }
935
936
  },
937
+ RadioIndicator: {
938
+ styles: (theme2, props) => {
939
+ var _a;
940
+ const color = ((_a = props.color) == null ? void 0 : _a.includes(".")) ? props.color.split(".")[0] : props.color ?? "carbon";
941
+ const shade = color.includes("carbon") ? 9 : 7;
942
+ return {
943
+ indicator: {
944
+ "--radio-color": themeColor(theme2, color, shade) + " !important",
945
+ "--radio-icon-color": props.variant === "outline" ? themeColor(theme2, color, shade) : theme2.white + " !important",
946
+ borderColor: themeColor(theme2, "carbon", 6),
947
+ "&[data-disabled]:not([data-checked])": {
948
+ background: themeColor(theme2, "carbon", 4),
949
+ borderColor: themeColor(theme2, "carbon", 6),
950
+ cursor: "not-allowed"
951
+ },
952
+ "&[data-disabled][data-checked]": {
953
+ color: themeColor(theme2, "carbon", 2),
954
+ background: themeColor(theme2, "carbon", 6),
955
+ borderColor: themeColor(theme2, "carbon", 6),
956
+ cursor: "not-allowed"
957
+ }
958
+ }
959
+ };
960
+ }
961
+ },
936
962
  SegmentedControl: {
937
963
  styles: (theme2) => {
938
964
  return {
@@ -916,6 +916,7 @@ const theme = createTheme({
916
916
  transform: "var(--radio-icon-transform, scale(0.2))"
917
917
  },
918
918
  radio: {
919
+ borderColor: themeColor(theme2, "carbon", 6),
919
920
  "&:disabled:not(:checked)": {
920
921
  background: themeColor(theme2, "carbon", 4),
921
922
  borderColor: themeColor(theme2, "carbon", 6),
@@ -931,6 +932,31 @@ const theme = createTheme({
931
932
  };
932
933
  }
933
934
  },
935
+ RadioIndicator: {
936
+ styles: (theme2, props) => {
937
+ var _a;
938
+ const color = ((_a = props.color) == null ? void 0 : _a.includes(".")) ? props.color.split(".")[0] : props.color ?? "carbon";
939
+ const shade = color.includes("carbon") ? 9 : 7;
940
+ return {
941
+ indicator: {
942
+ "--radio-color": themeColor(theme2, color, shade) + " !important",
943
+ "--radio-icon-color": props.variant === "outline" ? themeColor(theme2, color, shade) : theme2.white + " !important",
944
+ borderColor: themeColor(theme2, "carbon", 6),
945
+ "&[data-disabled]:not([data-checked])": {
946
+ background: themeColor(theme2, "carbon", 4),
947
+ borderColor: themeColor(theme2, "carbon", 6),
948
+ cursor: "not-allowed"
949
+ },
950
+ "&[data-disabled][data-checked]": {
951
+ color: themeColor(theme2, "carbon", 2),
952
+ background: themeColor(theme2, "carbon", 6),
953
+ borderColor: themeColor(theme2, "carbon", 6),
954
+ cursor: "not-allowed"
955
+ }
956
+ }
957
+ };
958
+ }
959
+ },
934
960
  SegmentedControl: {
935
961
  styles: (theme2) => {
936
962
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tidbcloud/uikit",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "tidbcloud uikit",
5
5
  "type": "module",
6
6
  "main": "dist/primitive/index.cjs",