@keboola/design 11.4.0 → 11.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/AGENTS.md +191 -1
- package/CHANGELOG.md +358 -0
- package/COMPONENT-API.md +68 -47
- package/dist/{AIKit-DDg5DBCG.js → AIKit-CNX6aiKm.js} +208 -62
- package/dist/AIKit-CNX6aiKm.js.map +1 -0
- package/dist/{Alert-DHJFrWnS.js → Alert-Ba5b2YPq.js} +2 -2
- package/dist/{Alert-DHJFrWnS.js.map → Alert-Ba5b2YPq.js.map} +1 -1
- package/dist/{Badge-Ch26CXoP.js → Badge-D0pXdekt.js} +2 -2
- package/dist/Badge-D0pXdekt.js.map +1 -0
- package/dist/{BrandEditor-Go7w8Zj2.js → BrandEditor-CSANsxUz.js} +6 -6
- package/dist/{BrandEditor-Go7w8Zj2.js.map → BrandEditor-CSANsxUz.js.map} +1 -1
- package/dist/{BrandLogo-Dmi7jo21.js → BrandLogo-CoKBk4MI.js} +4 -4
- package/dist/BrandLogo-CoKBk4MI.js.map +1 -0
- package/dist/{Breadcrumb-uEkM6adI.js → Breadcrumb-g_xn_-Nf.js} +2 -2
- package/dist/{Breadcrumb-uEkM6adI.js.map → Breadcrumb-g_xn_-Nf.js.map} +1 -1
- package/dist/{Checkbox-fC0BuO2B.js → Checkbox-CUIn2jap.js} +2 -2
- package/dist/{Checkbox-fC0BuO2B.js.map → Checkbox-CUIn2jap.js.map} +1 -1
- package/dist/{Clipboard-ChPdiUy3.js → Clipboard-BTW6C-b_.js} +2 -2
- package/dist/{Clipboard-ChPdiUy3.js.map → Clipboard-BTW6C-b_.js.map} +1 -1
- package/dist/{ClipboardButton-D9pDjgkB.js → ClipboardButton-CwZJdRaz.js} +2 -2
- package/dist/{ClipboardButton-D9pDjgkB.js.map → ClipboardButton-CwZJdRaz.js.map} +1 -1
- package/dist/{CodeEditor-Cxy3HnKH.js → CodeEditor-C9zy7PxK.js} +6 -6
- package/dist/{CodeEditor-Cxy3HnKH.js.map → CodeEditor-C9zy7PxK.js.map} +1 -1
- package/dist/{ColorInput-Bxj-1eLT.js → ColorInput-BZV-u_94.js} +3 -3
- package/dist/{ColorInput-Bxj-1eLT.js.map → ColorInput-BZV-u_94.js.map} +1 -1
- package/dist/{Combobox-Cs_1pj2q.js → Combobox-BfIfaVMA.js} +273 -104
- package/dist/Combobox-BfIfaVMA.js.map +1 -0
- package/dist/{Command-B7ML9YMv.js → Command-Bfa1kpbt.js} +2 -2
- package/dist/{Command-B7ML9YMv.js.map → Command-Bfa1kpbt.js.map} +1 -1
- package/dist/{CopyField-BO_sh-HO.js → CopyField-DpT0Ngz1.js} +2 -2
- package/dist/{CopyField-BO_sh-HO.js.map → CopyField-DpT0Ngz1.js.map} +1 -1
- package/dist/{DateInput-ZdaMQo5i.js → DateInput-DiEd5uCL.js} +3 -3
- package/dist/{DateInput-ZdaMQo5i.js.map → DateInput-DiEd5uCL.js.map} +1 -1
- package/dist/{DateRangeInput-DkvNh_sT.js → DateRangeInput-DPfVYchl.js} +3 -3
- package/dist/{DateRangeInput-DkvNh_sT.js.map → DateRangeInput-DPfVYchl.js.map} +1 -1
- package/dist/{FieldItem-CCd9-xnp.js → FieldItem-B7XMmZSz.js} +3 -3
- package/dist/{FieldItem-CCd9-xnp.js.map → FieldItem-B7XMmZSz.js.map} +1 -1
- package/dist/{Form-k6PH-em3.js → Form-CsttTHn4.js} +7 -7
- package/dist/Form-CsttTHn4.js.map +1 -0
- package/dist/{FormGroup-DbcDtrgU.js → FormGroup-DHvTFdno.js} +3 -3
- package/dist/{FormGroup-DbcDtrgU.js.map → FormGroup-DHvTFdno.js.map} +1 -1
- package/dist/{InputGroup-BnLHY0eq.js → InputGroup-DcZRlVnN.js} +22 -14
- package/dist/InputGroup-DcZRlVnN.js.map +1 -0
- package/dist/{Kbd-CvSM3D3-.js → Kbd-Cvvt91Q8.js} +14 -4
- package/dist/Kbd-Cvvt91Q8.js.map +1 -0
- package/dist/{MermaidDiagram-WkonYErO.js → MermaidDiagram-CXG5tC6J.js} +19 -18
- package/dist/MermaidDiagram-CXG5tC6J.js.map +1 -0
- package/dist/{MultiActionButtonGroup-CxWH7yWK.js → MultiActionButtonGroup-DokHbPgM.js} +2 -2
- package/dist/{MultiActionButtonGroup-CxWH7yWK.js.map → MultiActionButtonGroup-DokHbPgM.js.map} +1 -1
- package/dist/{Navbar-B2UsolVU.js → Navbar-Liy1TPI7.js} +6 -6
- package/dist/{Navbar-B2UsolVU.js.map → Navbar-Liy1TPI7.js.map} +1 -1
- package/dist/PageHeader-Q3IpCnQd.js.map +1 -1
- package/dist/{PageToolbar-DnbFt14Q.js → PageToolbar-DExqEYGl.js} +2 -2
- package/dist/{PageToolbar-DnbFt14Q.js.map → PageToolbar-DExqEYGl.js.map} +1 -1
- package/dist/{Popconfirm-CILjmzKI.js → Popconfirm-5pBzT_HQ.js} +10 -11
- package/dist/{Popconfirm-CILjmzKI.js.map → Popconfirm-5pBzT_HQ.js.map} +1 -1
- package/dist/{RadioGroup-XFzFd1ti.js → RadioGroup-DXPbSj8P.js} +2 -2
- package/dist/{RadioGroup-XFzFd1ti.js.map → RadioGroup-DXPbSj8P.js.map} +1 -1
- package/dist/{Search-4Bxtt8hS.js → Search-5uQAiNIP.js} +2 -2
- package/dist/{Search-4Bxtt8hS.js.map → Search-5uQAiNIP.js.map} +1 -1
- package/dist/{SearchInput-f_oY9T4Z.js → SearchInput-D4UgAXJK.js} +3 -3
- package/dist/{SearchInput-f_oY9T4Z.js.map → SearchInput-D4UgAXJK.js.map} +1 -1
- package/dist/{SectionNav-BpJlisbT.js → SectionNav-OkKCjSA-.js} +3 -3
- package/dist/{SectionNav-BpJlisbT.js.map → SectionNav-OkKCjSA-.js.map} +1 -1
- package/dist/{Select-DpcgKqKB.js → Select-DV3Hak_l.js} +3 -4
- package/dist/Select-DV3Hak_l.js.map +1 -0
- package/dist/{Sidebar-Cm6I4dE1.js → Sidebar-D3cY1kha.js} +44 -20
- package/dist/Sidebar-D3cY1kha.js.map +1 -0
- package/dist/{Slider-pPC_3gz9.js → Slider-CRf-bB4y.js} +2 -2
- package/dist/{Slider-pPC_3gz9.js.map → Slider-CRf-bB4y.js.map} +1 -1
- package/dist/{Switch-ChfPKcTE.js → Switch-B0WdGSjz.js} +7 -7
- package/dist/{Switch-ChfPKcTE.js.map → Switch-B0WdGSjz.js.map} +1 -1
- package/dist/{TextInput-DHM6dHmn.js → TextInput-DH5SkbsE.js} +3 -3
- package/dist/{TextInput-DHM6dHmn.js.map → TextInput-DH5SkbsE.js.map} +1 -1
- package/dist/{ThemeProvider-DrQJtzpd.js → ThemeProvider-2RMdVGxO.js} +17 -12
- package/dist/{ThemeProvider-DrQJtzpd.js.map → ThemeProvider-2RMdVGxO.js.map} +1 -1
- package/dist/{Timeline-6btyJl4D.js → Timeline-BG5Xogxh.js} +11 -11
- package/dist/{Timeline-6btyJl4D.js.map → Timeline-BG5Xogxh.js.map} +1 -1
- package/dist/{Workbench-BzE-Vvd9.js → Workbench-UR2FBC7I.js} +3 -1
- package/dist/Workbench-UR2FBC7I.js.map +1 -0
- package/dist/{ZoomableSvg-BWnDkR61.js → ZoomableSvg-pooPb1Cu.js} +3 -3
- package/dist/{ZoomableSvg-BWnDkR61.js.map → ZoomableSvg-pooPb1Cu.js.map} +1 -1
- package/dist/editors.js +4 -4
- package/dist/flint.js +134 -8
- package/dist/flint.js.map +1 -1
- package/dist/index.d.ts +537 -135
- package/dist/index.js +40 -39
- package/dist/internal/blocks/AIKit.js +2 -2
- package/dist/internal/blocks/AuthLayout.js +118 -0
- package/dist/internal/blocks/AuthLayout.js.map +1 -0
- package/dist/internal/blocks/BrandEditor.js +1 -1
- package/dist/internal/blocks/ClipboardButton.js +1 -1
- package/dist/internal/blocks/ColorInput.js +1 -1
- package/dist/internal/blocks/Command.js +1 -1
- package/dist/internal/blocks/CopyField.js +1 -1
- package/dist/internal/blocks/DateInput.js +1 -1
- package/dist/internal/blocks/DateRangeInput.js +1 -1
- package/dist/internal/blocks/ExportMenu.js +1 -1
- package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
- package/dist/internal/blocks/Form.js +1 -1
- package/dist/internal/blocks/FormGroup.js +1 -1
- package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
- package/dist/internal/blocks/MultiCombobox.js +107 -48
- package/dist/internal/blocks/MultiCombobox.js.map +1 -1
- package/dist/internal/blocks/NumberInput.js +1 -1
- package/dist/internal/blocks/PageToolbar.js +1 -1
- package/dist/internal/blocks/PasswordInput.js +2 -2
- package/dist/internal/blocks/SearchInput.js +1 -1
- package/dist/internal/blocks/SearchInputWithNavigation.js +2 -2
- package/dist/internal/blocks/SectionNav.js +1 -1
- package/dist/internal/blocks/TextInput.js +1 -1
- package/dist/internal/blocks/Textarea.js +1 -1
- package/dist/internal/blocks/TimeInput.js +2 -2
- package/dist/internal/components/Alert.js +1 -1
- package/dist/internal/components/Avatar.js +1 -1
- package/dist/internal/components/Badge.js +1 -1
- package/dist/internal/components/BrandLogo.js +1 -1
- package/dist/internal/components/Breadcrumb.js +1 -1
- package/dist/internal/components/Checkbox.js +1 -1
- package/dist/internal/components/Clipboard.js +1 -1
- package/dist/internal/components/CollapsiblePanel.js +1 -1
- package/dist/internal/components/Combobox.js +2 -2
- package/dist/internal/components/InputGroup.js +1 -1
- package/dist/internal/components/Kbd.js +1 -1
- package/dist/internal/components/Navbar.js +1 -1
- package/dist/internal/components/Popconfirm.js +1 -1
- package/dist/internal/components/RadioGroup.js +1 -1
- package/dist/internal/components/Search.js +1 -1
- package/dist/internal/components/Select.js +1 -1
- package/dist/internal/components/Sidebar.js +1 -1
- package/dist/internal/components/Slider.js +1 -1
- package/dist/internal/components/Switch.js +1 -1
- package/dist/internal/components/ThemeProvider.js +1 -1
- package/dist/internal/components/Timeline.js +1 -1
- package/dist/internal/components/Tooltip.js +1 -1
- package/dist/internal/components/Truncated.js +1 -1
- package/dist/internal/components/Workbench.js +1 -1
- package/dist/internal/components/ZoomableSvg.js +1 -1
- package/dist/internal/utils.js +2 -2
- package/dist/markdown-editor.js +29 -23
- package/dist/markdown-editor.js.map +1 -1
- package/dist/mermaid.js +1 -1
- package/dist/rjsf.js +22 -23
- package/dist/rjsf.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/testing.js +1 -1
- package/dist/{useColorSchemeState-klihG9-i.js → themeScopeContext-D7fSyb06.js} +16 -3
- package/dist/themeScopeContext-D7fSyb06.js.map +1 -0
- package/dist/{themeTokens-D70HeNVF.js → themeTokens-qP1-55O7.js} +37 -10
- package/dist/themeTokens-qP1-55O7.js.map +1 -0
- package/dist/{utils-B5Z52hYs.js → utils-DSvrhU8E.js} +6 -2
- package/dist/{utils-B5Z52hYs.js.map → utils-DSvrhU8E.js.map} +1 -1
- package/dist/vega.d.ts +1 -1
- package/dist/vega.js +3 -3
- package/dist/vega.js.map +1 -1
- package/dist/{vegaTheme-DfoEQhOy.js → vegaTheme-CSvFEMBl.js} +6 -6
- package/dist/vegaTheme-CSvFEMBl.js.map +1 -0
- package/package.json +12 -10
- package/src/styles.css +3 -0
- package/dist/AIKit-DDg5DBCG.js.map +0 -1
- package/dist/Badge-Ch26CXoP.js.map +0 -1
- package/dist/BrandLogo-Dmi7jo21.js.map +0 -1
- package/dist/Combobox-Cs_1pj2q.js.map +0 -1
- package/dist/Form-k6PH-em3.js.map +0 -1
- package/dist/InputGroup-BnLHY0eq.js.map +0 -1
- package/dist/Kbd-CvSM3D3-.js.map +0 -1
- package/dist/MermaidDiagram-WkonYErO.js.map +0 -1
- package/dist/Select-DpcgKqKB.js.map +0 -1
- package/dist/Sidebar-Cm6I4dE1.js.map +0 -1
- package/dist/Workbench-BzE-Vvd9.js.map +0 -1
- package/dist/themeTokens-D70HeNVF.js.map +0 -1
- package/dist/useColorSchemeState-klihG9-i.js.map +0 -1
- package/dist/vegaTheme-DfoEQhOy.js.map +0 -1
|
@@ -1,16 +1,36 @@
|
|
|
1
1
|
import { useArgoDesign } from "../../context-D7X470dy.js";
|
|
2
2
|
import { ChevronDown, Plus, X } from "../../icons-Cek151jC.js";
|
|
3
|
-
import { InputGroup } from "../../InputGroup-
|
|
4
|
-
import { Combobox as Combobox$1, createCreatableItem, defaultGroupToLabel, defaultItemToDisabled, defaultItemToIcon, defaultItemToLabel, defaultQueryToCreateLabel, defaultToCreateValue, isCreatableItem, isGroupItem, isGroupItems,
|
|
5
|
-
import { Fragment, useState } from "react";
|
|
3
|
+
import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
|
|
4
|
+
import { Combobox as Combobox$1, createCreatableItem, defaultGroupToLabel, defaultItemToDisabled, defaultItemToIcon, defaultItemToLabel, defaultQueryToCreateLabel, defaultToCreateValue, isCreatableItem, isGroupItem, isGroupItems, isSelectAllItem, namedLabel, sanitizeTypedInput, selectAllItem, toItemEquality, toLabel, useQueryReporter } from "../../Combobox-BfIfaVMA.js";
|
|
5
|
+
import { Fragment, useMemo, useState } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { Combobox } from "@base-ui/react/combobox";
|
|
8
8
|
//#region src/blocks/MultiCombobox/MultiCombobox.tsx
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
/**
|
|
10
|
+
* The strings one creatable entry stands for.
|
|
11
|
+
*
|
|
12
|
+
* - `id1, id2,` is two values: the blanks a stray separator leaves are dropped.
|
|
13
|
+
* - A repeat collapses to its first occurrence, case-insensitively, as everything the control
|
|
14
|
+
* matches by display string does — one entry cannot add the same value twice.
|
|
15
|
+
* - A `null` separator yields the entry itself.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_CREATE_SEPARATOR = ",";
|
|
18
|
+
/**
|
|
19
|
+
* How the create row lists the values it adds: each separated by the entry's own separator, then
|
|
20
|
+
* a space. A `RegExp` stands for many strings, so the default separator stands in for it.
|
|
21
|
+
*/
|
|
22
|
+
const joinCreateParts = (parts, separator) => parts.join(`${typeof separator === "string" ? separator : DEFAULT_CREATE_SEPARATOR} `);
|
|
23
|
+
const splitCreateEntry = (entry, separator) => {
|
|
24
|
+
if (separator === null) return [entry];
|
|
25
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26
|
+
return entry.split(separator).map((part) => part.trim()).filter((part) => {
|
|
27
|
+
if (part === "") return false;
|
|
28
|
+
const key = part.toLowerCase();
|
|
29
|
+
if (seen.has(key)) return false;
|
|
30
|
+
seen.add(key);
|
|
31
|
+
return true;
|
|
32
|
+
});
|
|
12
33
|
};
|
|
13
|
-
const isSelectAllItem = (item) => isLabeledItem(item) && item.value === "__select_all__";
|
|
14
34
|
/**
|
|
15
35
|
* Multi-selection combobox with chip display and search. Built on Base UI Combobox.
|
|
16
36
|
*
|
|
@@ -18,20 +38,23 @@ const isSelectAllItem = (item) => isLabeledItem(item) && item.value === "__selec
|
|
|
18
38
|
* Items render as chips above the input; `maxVisible` collapses excess into a `+N more` chip.
|
|
19
39
|
* **When NOT to use:** for single selection use `Combobox`; for short enums without search use `Select`.
|
|
20
40
|
* **Composition:** wrap in `FormGroup` for label + help text, or use `useAppForm` for form integration.
|
|
21
|
-
* Pass `allowSelectAll` for a
|
|
22
|
-
*
|
|
41
|
+
* Pass `allowSelectAll` for a "Select All" item when the full enum is small — it covers the whole set
|
|
42
|
+
* and hides itself while a query is active. Pass `allowCreate` to let the user add free-form values
|
|
43
|
+
* that are not in `items` (e.g. entering column names by hand).
|
|
23
44
|
*
|
|
24
45
|
* @see RECIPES.md#creatable-multi-combobox — for free-form-plus-enumerated patterns
|
|
25
46
|
* @see RECIPES.md#filter-toolbar — for combining multi-select with other filter chips
|
|
26
47
|
*/
|
|
27
|
-
const MultiCombobox = ({ items: _itemsProp, value: _valueProp, defaultValue, onValueChange, itemToStringLabel, itemToStringValue, disabled, filter: filterProp, inputRef, variant, sizing, focusVariant, state, placeholder, allowClear, id, name, onBlur, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, className, allowSelectAll = false, empty = "No items", indicator, allowCreate, queryToCreateValue, queryToCreateLabel = defaultQueryToCreateLabel, itemToDisabled = defaultItemToDisabled, itemToLabel
|
|
48
|
+
const MultiCombobox = ({ items: _itemsProp, value: _valueProp, defaultValue, onValueChange, itemToStringLabel, itemToStringValue, disabled, filter: filterProp, isItemEqualToValue: isItemEqualToValueProp, inputRef, variant, sizing, focusVariant, state, placeholder, allowClear = true, id, name, onBlur, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, className, allowSelectAll = false, empty = "No items", indicator, inputValueSanitizer, onQueryChange, allowCreate, canCreate, queryToCreateValue, queryToCreateLabel = defaultQueryToCreateLabel, createSeparator = DEFAULT_CREATE_SEPARATOR, itemToDisabled = defaultItemToDisabled, itemToLabel: itemToLabelProp, itemToIcon = defaultItemToIcon, groupToLabel = defaultGroupToLabel, itemToChipLabel, itemToChipColor, pinnedChipLabels, renderChips, maxVisible = 3 }) => {
|
|
28
49
|
const itemsProp = _itemsProp ?? [];
|
|
29
50
|
const valueProp = _valueProp ?? [];
|
|
51
|
+
const itemToLabel = itemToLabelProp ?? (itemToStringLabel ? (item) => namedLabel(itemToStringLabel(item)) : defaultItemToLabel);
|
|
30
52
|
const chipVariant = useArgoDesign() ? "pill" : "default";
|
|
31
53
|
const [inputValue, setInputValue] = useState("");
|
|
32
54
|
const [createdItems, setCreatedItems] = useState([]);
|
|
33
55
|
const query = inputValue.trim();
|
|
34
|
-
|
|
56
|
+
useQueryReporter(query, onQueryChange);
|
|
57
|
+
const ownsInput = Boolean(allowCreate || inputValueSanitizer || onQueryChange);
|
|
35
58
|
const baseItems = (() => {
|
|
36
59
|
if (createdItems.length === 0) return itemsProp;
|
|
37
60
|
if (isGroupItems(itemsProp)) return [...itemsProp, { items: createdItems }];
|
|
@@ -39,59 +62,101 @@ const MultiCombobox = ({ items: _itemsProp, value: _valueProp, defaultValue, onV
|
|
|
39
62
|
})();
|
|
40
63
|
const allFlatItems = baseItems.flatMap((item) => isGroupItem(item) ? item.items : item);
|
|
41
64
|
const sampleItem = allFlatItems[0];
|
|
42
|
-
const
|
|
65
|
+
const hasSelectAllRow = allowSelectAll && allFlatItems.length > 0;
|
|
66
|
+
const isAllSelected = hasSelectAllRow && allFlatItems.length === (valueProp?.length ?? 0);
|
|
43
67
|
const defaultFilter = Combobox.useFilter({
|
|
44
68
|
multiple: true,
|
|
45
69
|
value: valueProp
|
|
46
70
|
});
|
|
47
|
-
const itemsWithSelectAllItem =
|
|
48
|
-
if (!allowSelectAll) return baseItems;
|
|
49
|
-
return [selectAllItem, ...baseItems];
|
|
50
|
-
})();
|
|
71
|
+
const itemsWithSelectAllItem = hasSelectAllRow ? [selectAllItem, ...baseItems] : baseItems;
|
|
51
72
|
const itemToString = (item) => itemToStringLabel?.(item) ?? toLabel(item);
|
|
73
|
+
const labelKey = (item) => itemToString(item).toLowerCase();
|
|
74
|
+
const createParts = !allowCreate || disabled || !query ? [] : splitCreateEntry(query, createSeparator);
|
|
75
|
+
const selectedKeys = /* @__PURE__ */ new Set();
|
|
76
|
+
if (createParts.length > 0) for (const item of valueProp) selectedKeys.add(labelKey(item));
|
|
77
|
+
const itemKeys = /* @__PURE__ */ new Set();
|
|
78
|
+
if (createParts.length > 0 && canCreate) for (const item of allFlatItems) itemKeys.add(labelKey(item));
|
|
79
|
+
const namesAnItem = (key) => canCreate ? itemKeys.has(key) : allFlatItems.some((item) => labelKey(item) === key);
|
|
80
|
+
/**
|
|
81
|
+
* What the entry adds to the selection: its values the selection does not already hold.
|
|
82
|
+
*
|
|
83
|
+
* - The create row is named from this and committing it adds exactly this, so the row cannot
|
|
84
|
+
* promise something else. A value naming an existing item counts — committing selects it.
|
|
85
|
+
* - `canCreate` drops a value the control would mint and the gate rejects. One naming an item
|
|
86
|
+
* is selected rather than minted, so its format is not that gate's business.
|
|
87
|
+
* - `value` is the whole selection (it is never `undefined`, so the control is always the
|
|
88
|
+
* controlled one), which is why the commit path re-derives nothing.
|
|
89
|
+
*/
|
|
90
|
+
const addedCreateParts = createParts.filter((part) => {
|
|
91
|
+
const key = part.toLowerCase();
|
|
92
|
+
if (selectedKeys.has(key)) return false;
|
|
93
|
+
return !canCreate || namesAnItem(key) || canCreate(part);
|
|
94
|
+
});
|
|
95
|
+
const soleValueKey = createParts.length === 1 ? createParts[0].toLowerCase() : void 0;
|
|
96
|
+
const showCreateRow = addedCreateParts.length > 0 && (soleValueKey === void 0 || !namesAnItem(soleValueKey));
|
|
52
97
|
const items = (() => {
|
|
53
98
|
const base = itemsWithSelectAllItem;
|
|
54
|
-
if (!
|
|
55
|
-
const exactMatch = allFlatItems.some((item) => itemToString(item).toLowerCase() === queryLower);
|
|
56
|
-
const alreadySelected = valueProp.some((item) => itemToString(item).toLowerCase() === queryLower);
|
|
57
|
-
if (exactMatch || alreadySelected) return base;
|
|
99
|
+
if (!showCreateRow) return base;
|
|
58
100
|
const creatable = createCreatableItem(query);
|
|
59
101
|
return isGroupItems(base) ? [...base, { items: [creatable] }] : [...base, creatable];
|
|
60
102
|
})();
|
|
61
103
|
const filter = (item, query, itemToString) => {
|
|
62
|
-
if (isSelectAllItem(item)) return
|
|
104
|
+
if (isSelectAllItem(item)) return query.trim() === "";
|
|
63
105
|
if (isCreatableItem(item)) return true;
|
|
64
106
|
if (filterProp) return filterProp(item, query, itemToString);
|
|
65
107
|
return defaultFilter.contains(item, query, itemToString);
|
|
66
108
|
};
|
|
109
|
+
const isItemEqualToValue = useMemo(() => toItemEquality(isItemEqualToValueProp), [isItemEqualToValueProp]);
|
|
67
110
|
const wrappedItemToStringLabel = !allowCreate ? itemToStringLabel : (item) => isCreatableItem(item) ? item.value : itemToString(item);
|
|
68
111
|
const wrappedItemToStringValue = !allowCreate || !itemToStringValue ? itemToStringValue : (item) => isCreatableItem(item) ? item.value : itemToStringValue(item);
|
|
69
|
-
const value =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
112
|
+
const value = isAllSelected ? [...valueProp, selectAllItem] : valueProp;
|
|
113
|
+
const handleInputValueChange = (next, { reason }) => {
|
|
114
|
+
setInputValue(sanitizeTypedInput(next, reason, inputValueSanitizer));
|
|
115
|
+
};
|
|
73
116
|
const handleValueChange = (next, event) => {
|
|
117
|
+
if (ownsInput) setInputValue((prev) => prev === "" ? prev : "");
|
|
74
118
|
if (!onValueChange) return;
|
|
75
119
|
const created = [];
|
|
76
|
-
const converted =
|
|
77
|
-
if (!isCreatableItem
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
return
|
|
81
|
-
|
|
120
|
+
const converted = (() => {
|
|
121
|
+
if (!allowCreate || !next.some(isCreatableItem)) return next;
|
|
122
|
+
const itemsByLabel = /* @__PURE__ */ new Map();
|
|
123
|
+
for (const item of allFlatItems) itemsByLabel.set(labelKey(item), item);
|
|
124
|
+
return next.flatMap((item) => {
|
|
125
|
+
if (!isCreatableItem(item)) return [item];
|
|
126
|
+
return addedCreateParts.map((part) => {
|
|
127
|
+
const existing = itemsByLabel.get(part.toLowerCase());
|
|
128
|
+
if (existing !== void 0) return existing;
|
|
129
|
+
const value = defaultToCreateValue(part, sampleItem, queryToCreateValue);
|
|
130
|
+
created.push(value);
|
|
131
|
+
return value;
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
})();
|
|
82
135
|
const hasSelectAll = converted.some((item) => isSelectAllItem(item));
|
|
83
136
|
const newValue = (() => {
|
|
84
|
-
if (!
|
|
137
|
+
if (!hasSelectAllRow) return converted;
|
|
85
138
|
if (!hasSelectAll) return isAllSelected ? [] : converted;
|
|
86
139
|
return isAllSelected ? converted.filter((item) => !isSelectAllItem(item)) : allFlatItems;
|
|
87
140
|
})();
|
|
88
141
|
if (allowCreate) {
|
|
89
142
|
const selected = new Set(newValue.map(itemToString));
|
|
90
143
|
setCreatedItems((prev) => [...prev, ...created].filter((item) => selected.has(itemToString(item))));
|
|
91
|
-
setInputValue("");
|
|
92
144
|
}
|
|
93
145
|
onValueChange(newValue, event);
|
|
94
146
|
};
|
|
147
|
+
/**
|
|
148
|
+
* The create row.
|
|
149
|
+
*
|
|
150
|
+
* - `queryToCreateLabel` receives the values committing the row adds, rather than the entry as
|
|
151
|
+
* typed — so the row cannot name a value it drops as a stray separator, a repeat, or one the
|
|
152
|
+
* selection already holds, nor stay silent about one it selects from `items`.
|
|
153
|
+
* - For an entry standing for a single value that string is the entry itself.
|
|
154
|
+
*/
|
|
155
|
+
const renderCreatableItem = (item) => /* @__PURE__ */ jsx(Combobox$1.Item, {
|
|
156
|
+
value: item,
|
|
157
|
+
icon: /* @__PURE__ */ jsx(Plus, {}),
|
|
158
|
+
children: queryToCreateLabel(joinCreateParts(addedCreateParts, createSeparator))
|
|
159
|
+
});
|
|
95
160
|
const renderItem = (item) => {
|
|
96
161
|
return /* @__PURE__ */ jsx(Combobox$1.Item, {
|
|
97
162
|
value: item,
|
|
@@ -108,14 +173,15 @@ const MultiCombobox = ({ items: _itemsProp, value: _valueProp, defaultValue, onV
|
|
|
108
173
|
value,
|
|
109
174
|
defaultValue,
|
|
110
175
|
filter,
|
|
176
|
+
isItemEqualToValue,
|
|
111
177
|
onValueChange: handleValueChange,
|
|
112
178
|
itemToStringLabel: wrappedItemToStringLabel,
|
|
113
179
|
itemToStringValue: wrappedItemToStringValue,
|
|
114
180
|
disabled,
|
|
115
181
|
inputRef,
|
|
116
|
-
...
|
|
182
|
+
...ownsInput ? {
|
|
117
183
|
inputValue,
|
|
118
|
-
onInputValueChange:
|
|
184
|
+
onInputValueChange: handleInputValueChange
|
|
119
185
|
} : {},
|
|
120
186
|
children: [/* @__PURE__ */ jsx(Combobox.Chips, {
|
|
121
187
|
render: /* @__PURE__ */ jsx(Fragment, {}),
|
|
@@ -132,7 +198,8 @@ const MultiCombobox = ({ items: _itemsProp, value: _valueProp, defaultValue, onV
|
|
|
132
198
|
variant: chipVariant,
|
|
133
199
|
itemToChipLabel: itemToChipLabel ?? itemToLabel,
|
|
134
200
|
itemToChipColor,
|
|
135
|
-
pinnedChipLabels
|
|
201
|
+
pinnedChipLabels,
|
|
202
|
+
children: renderChips
|
|
136
203
|
}), /* @__PURE__ */ jsxs("div", {
|
|
137
204
|
className: "tw:flex tw:flex-1 tw:items-center tw:gap-1",
|
|
138
205
|
children: [
|
|
@@ -145,7 +212,7 @@ const MultiCombobox = ({ items: _itemsProp, value: _valueProp, defaultValue, onV
|
|
|
145
212
|
"aria-required": ariaRequired,
|
|
146
213
|
placeholder,
|
|
147
214
|
disabled,
|
|
148
|
-
className: "tw:w-auto tw:min-w-[120px] tw:flex-1"
|
|
215
|
+
className: "tw:w-auto tw:min-w-[120px] tw:flex-1 tw:!px-0 tw:!py-0"
|
|
149
216
|
}),
|
|
150
217
|
allowClear && /* @__PURE__ */ jsx(InputGroup.Button, {
|
|
151
218
|
asChild: true,
|
|
@@ -167,20 +234,12 @@ const MultiCombobox = ({ items: _itemsProp, value: _valueProp, defaultValue, onV
|
|
|
167
234
|
if (isSelectAllItem(itemOrGroup)) return /* @__PURE__ */ jsx(Combobox$1.Item, {
|
|
168
235
|
value: itemOrGroup,
|
|
169
236
|
indicator: "checkbox",
|
|
170
|
-
children:
|
|
171
|
-
});
|
|
172
|
-
if (isCreatableItem(itemOrGroup)) return /* @__PURE__ */ jsx(Combobox$1.Item, {
|
|
173
|
-
value: itemOrGroup,
|
|
174
|
-
icon: /* @__PURE__ */ jsx(Plus, {}),
|
|
175
|
-
children: queryToCreateLabel(itemOrGroup.value)
|
|
237
|
+
children: itemOrGroup.label
|
|
176
238
|
});
|
|
239
|
+
if (isCreatableItem(itemOrGroup)) return renderCreatableItem(itemOrGroup);
|
|
177
240
|
if (isGroupItem(itemOrGroup)) {
|
|
178
241
|
const maybeCreatable = itemOrGroup.items[0];
|
|
179
|
-
if (isCreatableItem(maybeCreatable)) return
|
|
180
|
-
value: maybeCreatable,
|
|
181
|
-
icon: /* @__PURE__ */ jsx(Plus, {}),
|
|
182
|
-
children: queryToCreateLabel(maybeCreatable.value)
|
|
183
|
-
});
|
|
242
|
+
if (isCreatableItem(maybeCreatable)) return renderCreatableItem(maybeCreatable);
|
|
184
243
|
const groupLabel = groupToLabel(itemOrGroup);
|
|
185
244
|
return /* @__PURE__ */ jsxs(Combobox$1.Group, {
|
|
186
245
|
items: itemOrGroup.items,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiCombobox.js","names":["BaseCombobox","Combobox"],"sources":["../../../src/blocks/MultiCombobox/MultiCombobox.tsx"],"sourcesContent":["import { type ComponentProps, Fragment, type ReactNode, useState } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { Combobox } from '../../components/Combobox';\nimport type { Group, LabeledItem } from '../../components/Combobox/types';\nimport {\n createCreatableItem,\n defaultGroupToLabel,\n defaultItemToDisabled,\n defaultItemToIcon,\n defaultItemToLabel,\n defaultQueryToCreateLabel,\n defaultToCreateValue,\n isCreatableItem,\n isGroupItem,\n isGroupItems,\n isLabeledItem,\n toLabel,\n} from '../../components/Combobox/utils';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useArgoDesign } from '../../components/ThemeProvider/context';\nimport { ChevronDown, Plus, X } from '../../icons';\n\ntype ComboboxProps<Value> = BaseCombobox.Root.Props<Value, true>;\ntype ComboboxInputProps = ComponentProps<typeof Combobox.Input>;\ntype ComboboxInputGroupProps = ComponentProps<typeof Combobox.InputGroup>;\ntype ComboboxItemProps = ComponentProps<typeof Combobox.Item>;\ntype ComboboxChipsProps<Value> = ComponentProps<typeof Combobox.Chips<Value>>;\n\ntype Indicator = NonNullable<ComboboxItemProps['indicator']>;\n\ntype CreatableProps<Value> = {\n allowCreate?: boolean;\n queryToCreateLabel?: (query: string) => ReactNode;\n queryToCreateValue?: (query: string) => Value;\n};\n\n/**\n * Props for `MultiCombobox`. Generic over `Value` (the item shape) and `GroupShape` (optional group wrapper).\n * Use `itemToLabel` / `itemToIcon` / `itemToDisabled` to project custom item shapes; use `filter` to override\n * the default substring matcher. Pass `allowCreate` to let the user add free-form values not in `items`.\n */\ntype Props<Value, GroupShape extends Group<Value> = Group<Value>> = Pick<\n ComboboxInputProps,\n // `name`, `onBlur` and the `aria-*` set are forwarded to the input so a form connector can hand\n // over the wiring it derives from the field — without the `aria-*` set the control cannot be linked\n // to its own help and error text, and without `onBlur` the field never registers as blurred, which\n // is the gate `FieldItem` reveals errors on.\n 'placeholder' | 'id' | 'name' | 'onBlur' | 'aria-describedby' | 'aria-invalid' | 'aria-required'\n> &\n Pick<ComboboxInputGroupProps, 'variant' | 'focusVariant' | 'sizing' | 'state' | 'className'> &\n Pick<\n ComboboxProps<Value>,\n | 'disabled'\n | 'inputRef'\n | 'value'\n | 'defaultValue'\n | 'onValueChange'\n | 'itemToStringLabel'\n | 'itemToStringValue'\n | 'filter'\n > &\n Pick<\n ComboboxChipsProps<Value>,\n 'itemToChipLabel' | 'itemToChipColor' | 'pinnedChipLabels' | 'maxVisible'\n > &\n CreatableProps<Value> & {\n items?: readonly (Value | GroupShape)[];\n\n // root specific\n allowClear?: boolean;\n allowSelectAll?: boolean;\n empty?: ReactNode;\n indicator?: Indicator;\n\n // item specific\n itemToLabel?: (item: Value) => ReactNode;\n itemToIcon?: (item: Value) => ReactNode;\n itemToDisabled?: (item: Value) => boolean;\n\n // group specific\n groupToLabel?: (group: GroupShape) => ReactNode;\n };\n\nconst selectAllItem: LabeledItem = {\n value: '__select_all__',\n label: 'Select All',\n};\n\nconst isSelectAllItem = <Value,>(item: Value) =>\n isLabeledItem(item) && item.value === '__select_all__';\n\n/**\n * Multi-selection combobox with chip display and search. Built on Base UI Combobox.\n *\n * **When to use:** picking several items from a searchable enumerated list (filter by tags, assign labels).\n * Items render as chips above the input; `maxVisible` collapses excess into a `+N more` chip.\n * **When NOT to use:** for single selection use `Combobox`; for short enums without search use `Select`.\n * **Composition:** wrap in `FormGroup` for label + help text, or use `useAppForm` for form integration.\n * Pass `allowSelectAll` for a sticky \"Select All\" item when the full enum is small. Pass `allowCreate`\n * to let the user add free-form values that are not in `items` (e.g. entering column names by hand).\n *\n * @see RECIPES.md#creatable-multi-combobox — for free-form-plus-enumerated patterns\n * @see RECIPES.md#filter-toolbar — for combining multi-select with other filter chips\n */\nexport const MultiCombobox = <Value, GroupShape extends Group<Value> = Group<Value>>({\n // root props\n items: _itemsProp,\n value: _valueProp,\n defaultValue,\n onValueChange,\n itemToStringLabel,\n itemToStringValue,\n disabled,\n filter: filterProp,\n inputRef,\n\n // input props\n variant,\n sizing,\n focusVariant,\n state,\n placeholder,\n allowClear,\n id,\n name,\n onBlur,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n className,\n\n // own props\n allowSelectAll = false,\n empty = 'No items',\n indicator,\n\n // creatable\n allowCreate,\n queryToCreateValue,\n queryToCreateLabel = defaultQueryToCreateLabel,\n\n // own item props\n itemToDisabled = defaultItemToDisabled,\n itemToLabel = defaultItemToLabel,\n itemToIcon = defaultItemToIcon,\n groupToLabel = defaultGroupToLabel,\n itemToChipLabel,\n itemToChipColor,\n pinnedChipLabels,\n // Nothing chose 3: value editors override it to `Infinity` (a chip inside `+N` can be neither\n // read nor removed) and single-row filters to `1`. Changing it moves eleven call sites at once,\n // so it waits for a PR that can look at them.\n maxVisible = 3,\n}: Props<Value, GroupShape>) => {\n const itemsProp = _itemsProp ?? [];\n const valueProp = _valueProp ?? [];\n const renderArgo = useArgoDesign();\n const chipVariant = renderArgo ? 'pill' : 'default';\n\n const [inputValue, setInputValue] = useState('');\n const [createdItems, setCreatedItems] = useState<Value[]>([]);\n const query = inputValue.trim();\n const queryLower = query.toLowerCase();\n\n // Created values are appended to `items` so Base UI can keep resolving them (as chips and as\n // list options) once the query clears — otherwise a value that isn't in `items` gets dropped.\n // `handleValueChange` drops the ones the selection no longer holds, so this list tracks the\n // selection rather than every value ever typed.\n const baseItems = (() => {\n if (createdItems.length === 0) return itemsProp;\n if (isGroupItems(itemsProp))\n return [...itemsProp, { items: createdItems } as unknown as GroupShape];\n return [...itemsProp, ...createdItems];\n })();\n\n const allFlatItems = baseItems.flatMap((item) => (isGroupItem(item) ? item.items : item));\n const sampleItem = allFlatItems[0] as Value | undefined;\n const isAllSelected = allFlatItems.length === (valueProp?.length ?? 0);\n\n const defaultFilter = BaseCombobox.useFilter({\n multiple: true,\n value: valueProp,\n });\n\n const itemsWithSelectAllItem = (() => {\n if (!allowSelectAll) return baseItems;\n return [selectAllItem, ...baseItems];\n })();\n\n const itemToString = (item: Value) => itemToStringLabel?.(item) ?? toLabel(item);\n\n const items = (() => {\n const base = itemsWithSelectAllItem;\n if (!allowCreate || disabled || !query) return base;\n\n const exactMatch = allFlatItems.some((item) => itemToString(item).toLowerCase() === queryLower);\n const alreadySelected = valueProp.some(\n (item) => itemToString(item).toLowerCase() === queryLower,\n );\n if (exactMatch || alreadySelected) return base;\n\n const creatable = createCreatableItem(query);\n return isGroupItems(base)\n ? [...base, { items: [creatable] } as unknown as GroupShape]\n : [...base, creatable as unknown as Value];\n })();\n\n const filter = (item: Value, query: string, itemToString?: (value: Value) => string) => {\n // keep select always visible\n if (isSelectAllItem(item)) return true;\n // always offer the transient \"create\" option\n if (isCreatableItem(item)) return true;\n\n if (filterProp) return filterProp(item, query, itemToString);\n return defaultFilter.contains(item, query, itemToString);\n };\n\n const wrappedItemToStringLabel: ComboboxProps<Value>['itemToStringLabel'] = !allowCreate\n ? itemToStringLabel\n : (item) => (isCreatableItem(item) ? item.value : itemToString(item));\n\n const wrappedItemToStringValue: ComboboxProps<Value>['itemToStringValue'] =\n !allowCreate || !itemToStringValue\n ? itemToStringValue\n : (item) => (isCreatableItem(item) ? item.value : itemToStringValue(item));\n\n const value = (() => {\n if (!allowSelectAll) return valueProp;\n return isAllSelected ? [...valueProp, selectAllItem as Value] : valueProp;\n })();\n\n const handleValueChange: ComboboxProps<Value>['onValueChange'] = (next, event) => {\n if (!onValueChange) return;\n\n const created: Value[] = [];\n const converted = allowCreate\n ? next.map((item) => {\n if (!isCreatableItem(item)) return item;\n const value = defaultToCreateValue(item.value, sampleItem, queryToCreateValue) as Value;\n created.push(value);\n return value;\n })\n : next;\n\n const hasSelectAll = converted.some((item) => isSelectAllItem(item));\n const newValue = (() => {\n if (!allowSelectAll) return converted;\n if (!hasSelectAll) return isAllSelected ? [] : converted;\n return isAllSelected ? converted.filter((item) => !isSelectAllItem(item)) : allFlatItems;\n })();\n\n if (allowCreate) {\n // Keep only the created values the selection being emitted still holds — `valueProp` is the\n // selection before this change, so a value created right now is not in it yet.\n const selected = new Set(newValue.map(itemToString));\n setCreatedItems((prev) =>\n [...prev, ...created].filter((item) => selected.has(itemToString(item))),\n );\n setInputValue('');\n }\n\n onValueChange(newValue, event);\n };\n\n const renderItem = (item: Value) => {\n return (\n <Combobox.Item\n value={item}\n indicator={indicator}\n icon={itemToIcon(item)}\n disabled={itemToDisabled(item)}\n >\n {itemToLabel(item)}\n </Combobox.Item>\n );\n };\n\n return (\n <Combobox.Root<Value, true>\n multiple\n // Base UI highlights nothing until ArrowDown, so Enter after typing would drop the query\n // silently — no selection, and the popup closes. Highlighting the first match makes Enter\n // commit it, including the creatable row when `allowCreate` is on.\n autoHighlight\n items={items}\n value={value}\n defaultValue={defaultValue}\n filter={filter}\n onValueChange={handleValueChange}\n itemToStringLabel={wrappedItemToStringLabel}\n itemToStringValue={wrappedItemToStringValue}\n disabled={disabled}\n inputRef={inputRef}\n {...(allowCreate\n ? { inputValue, onInputValueChange: (nextValue: string) => setInputValue(nextValue) }\n : {})}\n >\n <BaseCombobox.Chips render={<Fragment />}>\n <Combobox.InputGroup\n variant={variant}\n sizing={sizing}\n state={state}\n focusVariant={focusVariant}\n className={className}\n >\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-wrap tw:items-center tw:gap-1.5 tw:px-4 tw:py-1.5\">\n <Combobox.Chips<Value>\n maxVisible={maxVisible}\n variant={chipVariant}\n itemToChipLabel={itemToChipLabel ?? itemToLabel}\n itemToChipColor={itemToChipColor}\n pinnedChipLabels={pinnedChipLabels}\n />\n <div className=\"tw:flex tw:flex-1 tw:items-center tw:gap-1\">\n <Combobox.Input\n id={id}\n name={name}\n onBlur={onBlur}\n aria-describedby={ariaDescribedBy}\n aria-invalid={ariaInvalid}\n aria-required={ariaRequired}\n placeholder={placeholder}\n disabled={disabled}\n className=\"tw:w-auto tw:min-w-[120px] tw:flex-1\"\n />\n {allowClear && (\n <InputGroup.Button asChild aria-label=\"Clear\" disabled={disabled}>\n <BaseCombobox.Clear>\n <X className=\"tw:size-4\" />\n </BaseCombobox.Clear>\n </InputGroup.Button>\n )}\n <InputGroup.Button disabled={disabled} asChild aria-label=\"Open combobox\">\n <BaseCombobox.Trigger>\n <ChevronDown className=\"tw:size-4\" />\n </BaseCombobox.Trigger>\n </InputGroup.Button>\n </div>\n </div>\n </Combobox.InputGroup>\n </BaseCombobox.Chips>\n <Combobox.Content>\n <Combobox.Empty>{empty}</Combobox.Empty>\n <Combobox.List>\n {(itemOrGroup: Value | GroupShape) => {\n if (isSelectAllItem(itemOrGroup)) {\n return (\n <Combobox.Item value={itemOrGroup} indicator=\"checkbox\">\n Select All\n </Combobox.Item>\n );\n }\n\n if (isCreatableItem(itemOrGroup)) {\n return (\n <Combobox.Item value={itemOrGroup} icon={<Plus />}>\n {queryToCreateLabel(itemOrGroup.value)}\n </Combobox.Item>\n );\n }\n\n if (isGroupItem(itemOrGroup)) {\n const maybeCreatable = itemOrGroup.items[0];\n\n if (isCreatableItem(maybeCreatable)) {\n return (\n <Combobox.Item value={maybeCreatable} icon={<Plus />}>\n {queryToCreateLabel(maybeCreatable.value)}\n </Combobox.Item>\n );\n }\n\n const groupLabel = groupToLabel(itemOrGroup);\n return (\n <Combobox.Group items={itemOrGroup.items}>\n {groupLabel && <Combobox.GroupLabel>{groupLabel}</Combobox.GroupLabel>}\n <Combobox.GroupList>{renderItem}</Combobox.GroupList>\n </Combobox.Group>\n );\n }\n\n return renderItem(itemOrGroup);\n }}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MultiCombobox.js","names":["BaseCombobox","Combobox"],"sources":["../../../src/blocks/MultiCombobox/MultiCombobox.tsx"],"sourcesContent":["import { type ComponentProps, Fragment, type ReactNode, useMemo, useState } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { Combobox } from '../../components/Combobox';\nimport { namedLabel } from '../../components/Combobox/blankValues';\nimport { sanitizeTypedInput, useQueryReporter } from '../../components/Combobox/query';\nimport type { CreatableItem, Group } from '../../components/Combobox/types';\nimport {\n createCreatableItem,\n defaultGroupToLabel,\n defaultItemToDisabled,\n defaultItemToIcon,\n defaultItemToLabel,\n defaultQueryToCreateLabel,\n defaultToCreateValue,\n isCreatableItem,\n isGroupItem,\n isGroupItems,\n isSelectAllItem,\n selectAllItem,\n toItemEquality,\n toLabel,\n} from '../../components/Combobox/utils';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useArgoDesign } from '../../components/ThemeProvider/context';\nimport { ChevronDown, Plus, X } from '../../icons';\n\ntype ComboboxProps<Value> = BaseCombobox.Root.Props<Value, true>;\ntype ComboboxInputProps = ComponentProps<typeof Combobox.Input>;\ntype ComboboxInputGroupProps = ComponentProps<typeof Combobox.InputGroup>;\ntype ComboboxItemProps = ComponentProps<typeof Combobox.Item>;\ntype ComboboxChipsProps<Value> = ComponentProps<typeof Combobox.Chips<Value>>;\n\ntype Indicator = NonNullable<ComboboxItemProps['indicator']>;\n\n/**\n * The strings one creatable entry stands for.\n *\n * - `id1, id2,` is two values: the blanks a stray separator leaves are dropped.\n * - A repeat collapses to its first occurrence, case-insensitively, as everything the control\n * matches by display string does — one entry cannot add the same value twice.\n * - A `null` separator yields the entry itself.\n */\nconst DEFAULT_CREATE_SEPARATOR = ',';\n\n/**\n * How the create row lists the values it adds: each separated by the entry's own separator, then\n * a space. A `RegExp` stands for many strings, so the default separator stands in for it.\n */\nconst joinCreateParts = (parts: string[], separator: string | RegExp | null) =>\n parts.join(`${typeof separator === 'string' ? separator : DEFAULT_CREATE_SEPARATOR} `);\n\nconst splitCreateEntry = (entry: string, separator: string | RegExp | null): string[] => {\n if (separator === null) return [entry];\n\n const seen = new Set<string>();\n return entry\n .split(separator)\n .map((part) => part.trim())\n .filter((part) => {\n if (part === '') return false;\n const key = part.toLowerCase();\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n};\n\ntype CreatableProps<Value> = {\n allowCreate?: boolean;\n /**\n * Words the create row. Receives the values committing the row will add — an entry standing for\n * several values arrives trimmed and re-joined with its own separator, not as typed.\n */\n queryToCreateLabel?: (query: string) => ReactNode;\n /**\n * Projects one entered string into an item. Called once per value, so a split entry calls it\n * several times, each with an already-trimmed part.\n */\n queryToCreateValue?: (query: string) => Value;\n /**\n * Gate on each value the entry stands for, for `allowCreate`.\n *\n * - Returning `false` drops that value, so an entry left with none hides the create row and the\n * empty state shows instead.\n * - Only called for a value that matches no item and nothing already selected — one naming an\n * item is selected rather than minted, so its format is not this gate's business.\n * - Reach for it when a free-form value has a format (a column name, an email address).\n */\n canCreate?: (query: string) => boolean;\n /**\n * Separator that makes one creatable entry stand for several values. Defaults to **`','`**, so\n * pasting `id1, id2, id3` adds three chips.\n *\n * - Pass a string or a non-capturing `RegExp` for another convention: `';'` for an Outlook\n * address list, `/[\\s,]+/` where a value can never contain a space. A capture group would be\n * handed back as a value of its own — that is `String.prototype.split`'s own behaviour.\n * - Pass `null` where a value legitimately contains the separator — a free-text label, a\n * sentence — and one entry must stay one chip.\n * - Whitespace is deliberately not part of the default: tags and column names contain spaces,\n * and each part is trimmed anyway, so `id1, id2` needs nothing more than the comma.\n */\n createSeparator?: string | RegExp | null;\n};\n\n/**\n * Props for `MultiCombobox`. Generic over `Value` (the item shape) and `GroupShape` (optional group wrapper).\n * Use `itemToLabel` / `itemToIcon` / `itemToDisabled` to project custom item shapes; use `filter` to override\n * the default substring matcher. Pass `isItemEqualToValue` when the items are objects a store recreates —\n * without it Base UI matches `value` against `items` by reference. Pass `allowCreate` to let the user add\n * free-form values not in `items`.\n */\ntype Props<Value, GroupShape extends Group<Value> = Group<Value>> = Pick<\n ComboboxInputProps,\n // `name`, `onBlur` and the `aria-*` set are forwarded to the input so a form connector can hand\n // over the wiring it derives from the field — without the `aria-*` set the control cannot be linked\n // to its own help and error text, and without `onBlur` the field never registers as blurred, which\n // is the gate `FieldItem` reveals errors on.\n 'placeholder' | 'id' | 'name' | 'onBlur' | 'aria-describedby' | 'aria-invalid' | 'aria-required'\n> &\n Pick<ComboboxInputGroupProps, 'variant' | 'focusVariant' | 'sizing' | 'state' | 'className'> &\n Pick<\n ComboboxProps<Value>,\n | 'disabled'\n | 'inputRef'\n | 'value'\n | 'defaultValue'\n | 'onValueChange'\n | 'itemToStringLabel'\n | 'itemToStringValue'\n | 'filter'\n | 'isItemEqualToValue'\n > &\n Pick<\n ComboboxChipsProps<Value>,\n 'itemToChipLabel' | 'itemToChipColor' | 'pinnedChipLabels' | 'maxVisible'\n > &\n CreatableProps<Value> & {\n items?: readonly (Value | GroupShape)[];\n\n // root specific\n /**\n * Offer a clear-all button once something is selected. Defaults to **`true`**.\n *\n * - `BaseCombobox.Clear` only mounts while chips exist, so an empty control renders identically\n * either way. Individual chips stay removable regardless.\n * - Pass `false` where emptying the whole selection must not be one click away.\n */\n allowClear?: boolean;\n /**\n * Adds a \"Select All\" row that selects the whole item set.\n *\n * - The row is hidden while a query narrows the list — it never means \"everything matching\".\n * - Selecting it while everything is already selected clears the selection.\n */\n allowSelectAll?: boolean;\n empty?: ReactNode;\n indicator?: Indicator;\n\n // query specific\n /**\n * Rewrites what the user types before the control adopts it.\n *\n * - The query the list filters by is the rewritten text, and so is every value a created entry\n * is split into — a character the user cannot type is one they cannot create.\n * - Reach for it where a created value has a character set: a column name, a scope, an\n * identifier. `canCreate` is the gate for a format the user must get right themselves.\n * - It has to rewrite rather than drop: it sees the whole text on every keystroke, so one\n * calling `trim()` swallows the space before the next word.\n */\n inputValueSanitizer?: (input: string) => string;\n /**\n * Reports the query the list filters by, `inputValueSanitizer` already applied.\n *\n * - For an owner that needs the query for itself: a server-side search, an option order, the\n * text a synthetic row is offered for. The mount render reports too, so a search driven by\n * this needs no first fetch of its own.\n * - Notification only, and deliberately not Base UI's own `onInputValueChange`: the control\n * keeps ownership of the text — a pick clears it — so there is no controlled `inputValue`\n * to hold in sync.\n */\n onQueryChange?: (query: string) => void;\n\n // item specific\n /**\n * The item's row in the list, and its chip unless `itemToChipLabel` overrides it.\n *\n * - Defaults to `itemToStringLabel`, so a control that projects its items — ids carrying the\n * selection, the label looked up beside them — states the projection once.\n * - Pass it separately only where the row is richer than the input's own text.\n */\n itemToLabel?: (item: Value) => ReactNode;\n itemToIcon?: (item: Value) => ReactNode;\n itemToDisabled?: (item: Value) => boolean;\n\n // chip specific\n /**\n * Renders the chip area from the selected values, in place of the default chips.\n *\n * - For the case no per-value accessor can express: one node standing for the whole selection\n * (\"3 tables selected\"), or a chip count that is not the value count.\n * - A chip that merely holds richer content — a link, an action of its own — needs no slot:\n * `itemToChipLabel` returns a `ReactNode` and the chip lets it take the keyboard.\n * - The chip props above go unused while this is set, `maxVisible` and its `+N` chip included.\n * - `Combobox.Chip` builds a removable chip.\n */\n renderChips?: (values: Value[]) => ReactNode;\n\n // group specific\n groupToLabel?: (group: GroupShape) => ReactNode;\n };\n\n/**\n * Multi-selection combobox with chip display and search. Built on Base UI Combobox.\n *\n * **When to use:** picking several items from a searchable enumerated list (filter by tags, assign labels).\n * Items render as chips above the input; `maxVisible` collapses excess into a `+N more` chip.\n * **When NOT to use:** for single selection use `Combobox`; for short enums without search use `Select`.\n * **Composition:** wrap in `FormGroup` for label + help text, or use `useAppForm` for form integration.\n * Pass `allowSelectAll` for a \"Select All\" item when the full enum is small — it covers the whole set\n * and hides itself while a query is active. Pass `allowCreate` to let the user add free-form values\n * that are not in `items` (e.g. entering column names by hand).\n *\n * @see RECIPES.md#creatable-multi-combobox — for free-form-plus-enumerated patterns\n * @see RECIPES.md#filter-toolbar — for combining multi-select with other filter chips\n */\nexport const MultiCombobox = <Value, GroupShape extends Group<Value> = Group<Value>>({\n // root props\n items: _itemsProp,\n value: _valueProp,\n defaultValue,\n onValueChange,\n itemToStringLabel,\n itemToStringValue,\n disabled,\n filter: filterProp,\n isItemEqualToValue: isItemEqualToValueProp,\n inputRef,\n\n // input props\n variant,\n sizing,\n focusVariant,\n state,\n placeholder,\n allowClear = true,\n id,\n name,\n onBlur,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n className,\n\n // own props\n allowSelectAll = false,\n empty = 'No items',\n indicator,\n\n // query\n inputValueSanitizer,\n onQueryChange,\n\n // creatable\n allowCreate,\n canCreate,\n queryToCreateValue,\n queryToCreateLabel = defaultQueryToCreateLabel,\n createSeparator = DEFAULT_CREATE_SEPARATOR,\n\n // own item props\n itemToDisabled = defaultItemToDisabled,\n itemToLabel: itemToLabelProp,\n itemToIcon = defaultItemToIcon,\n groupToLabel = defaultGroupToLabel,\n itemToChipLabel,\n itemToChipColor,\n pinnedChipLabels,\n renderChips,\n // Nothing chose 3: value editors override it to `Infinity` (a chip inside `+N` can be neither\n // read nor removed) and single-row filters to `1`. Changing it moves eleven call sites at once,\n // so it waits for a PR that can look at them.\n maxVisible = 3,\n}: Props<Value, GroupShape>) => {\n const itemsProp = _itemsProp ?? [];\n const valueProp = _valueProp ?? [];\n // `itemToStringLabel` is a projection, not a display accessor, so a blank it returns still needs\n // naming — rows and chips are where a blank value would otherwise render as nothing.\n const itemToLabel =\n itemToLabelProp ??\n (itemToStringLabel ? (item: Value) => namedLabel(itemToStringLabel(item)) : defaultItemToLabel);\n const renderArgo = useArgoDesign();\n const chipVariant = renderArgo ? 'pill' : 'default';\n\n const [inputValue, setInputValue] = useState('');\n const [createdItems, setCreatedItems] = useState<Value[]>([]);\n const query = inputValue.trim();\n\n useQueryReporter(query, onQueryChange);\n\n // Who holds the input's text. Base UI keeps it unless something here needs to read or rewrite\n // it, because taking it means re-rendering this component on every keystroke — a cost the many\n // controls that only pick from a list should not pay.\n const ownsInput = Boolean(allowCreate || inputValueSanitizer || onQueryChange);\n\n // Created values are appended to `items` so Base UI can keep resolving them (as chips and as\n // list options) once the query clears — otherwise a value that isn't in `items` gets dropped.\n // `handleValueChange` drops the ones the selection no longer holds, so this list tracks the\n // selection rather than every value ever typed.\n const baseItems = (() => {\n if (createdItems.length === 0) return itemsProp;\n if (isGroupItems(itemsProp))\n return [...itemsProp, { items: createdItems } as unknown as GroupShape];\n return [...itemsProp, ...createdItems];\n })();\n\n const allFlatItems = baseItems.flatMap((item) => (isGroupItem(item) ? item.items : item));\n const sampleItem = allFlatItems[0] as Value | undefined;\n // An empty item set has no Select All row: there is nothing to select all of, and reading\n // `0 === 0` as \"everything is selected\" would put the row's own entry into `value`.\n const hasSelectAllRow = allowSelectAll && allFlatItems.length > 0;\n const isAllSelected = hasSelectAllRow && allFlatItems.length === (valueProp?.length ?? 0);\n\n const defaultFilter = BaseCombobox.useFilter({\n multiple: true,\n value: valueProp,\n });\n\n const itemsWithSelectAllItem = hasSelectAllRow ? [selectAllItem, ...baseItems] : baseItems;\n\n const itemToString = (item: Value) => itemToStringLabel?.(item) ?? toLabel(item);\n // An item's display string, case-folded — the key an entered value is matched against.\n const labelKey = (item: Value) => itemToString(item).toLowerCase();\n\n // The values the current entry stands for. Everything the create row is decided from hangs off\n // this, so an empty entry costs a creatable control nothing.\n const createParts =\n !allowCreate || disabled || !query ? [] : splitCreateEntry(query, createSeparator);\n\n const selectedKeys = new Set<string>();\n if (createParts.length > 0) for (const item of valueProp) selectedKeys.add(labelKey(item));\n\n // Does an item carry this display string? `canCreate` asks it per value, so there it earns a\n // set; without the gate only a single-value entry asks, and an early-exiting scan is cheaper.\n const itemKeys = new Set<string>();\n if (createParts.length > 0 && canCreate) {\n for (const item of allFlatItems) itemKeys.add(labelKey(item));\n }\n const namesAnItem = (key: string) =>\n canCreate ? itemKeys.has(key) : allFlatItems.some((item) => labelKey(item) === key);\n\n /**\n * What the entry adds to the selection: its values the selection does not already hold.\n *\n * - The create row is named from this and committing it adds exactly this, so the row cannot\n * promise something else. A value naming an existing item counts — committing selects it.\n * - `canCreate` drops a value the control would mint and the gate rejects. One naming an item\n * is selected rather than minted, so its format is not that gate's business.\n * - `value` is the whole selection (it is never `undefined`, so the control is always the\n * controlled one), which is why the commit path re-derives nothing.\n */\n const addedCreateParts = createParts.filter((part) => {\n const key = part.toLowerCase();\n if (selectedKeys.has(key)) return false;\n return !canCreate || namesAnItem(key) || canCreate(part);\n });\n\n // The one value a single-value entry stands for, keyed — `undefined` for a split entry.\n const soleValueKey = createParts.length === 1 ? createParts[0]!.toLowerCase() : undefined;\n\n // A single value naming an item needs no create row: the list already offers that item's own\n // row, which the default substring filter matches for a single-value entry but not for a split\n // one. The item scan runs only for an entry that would otherwise show the row.\n const showCreateRow =\n addedCreateParts.length > 0 && (soleValueKey === undefined || !namesAnItem(soleValueKey));\n\n const items = (() => {\n const base = itemsWithSelectAllItem;\n if (!showCreateRow) return base;\n\n const creatable = createCreatableItem(query);\n return isGroupItems(base)\n ? [...base, { items: [creatable] } as unknown as GroupShape]\n : [...base, creatable as unknown as Value];\n })();\n\n const filter = (item: Value, query: string, itemToString?: (value: Value) => string) => {\n // Select All covers the whole item set, so it exists only while no query narrows the list.\n if (isSelectAllItem(item)) return query.trim() === '';\n // always offer the transient \"create\" option\n if (isCreatableItem(item)) return true;\n\n if (filterProp) return filterProp(item, query, itemToString);\n return defaultFilter.contains(item, query, itemToString);\n };\n\n // Base UI stores the comparer and lists it in an effect's deps, so a fresh identity per render\n // re-renders every option row and rescans the item list.\n const isItemEqualToValue = useMemo(\n () => toItemEquality(isItemEqualToValueProp),\n [isItemEqualToValueProp],\n );\n\n const wrappedItemToStringLabel: ComboboxProps<Value>['itemToStringLabel'] = !allowCreate\n ? itemToStringLabel\n : (item) => (isCreatableItem(item) ? item.value : itemToString(item));\n\n const wrappedItemToStringValue: ComboboxProps<Value>['itemToStringValue'] =\n !allowCreate || !itemToStringValue\n ? itemToStringValue\n : (item) => (isCreatableItem(item) ? item.value : itemToStringValue(item));\n\n const value = isAllSelected ? [...valueProp, selectAllItem as Value] : valueProp;\n\n const handleInputValueChange: NonNullable<ComboboxProps<Value>['onInputValueChange']> = (\n next,\n { reason },\n ) => {\n setInputValue(sanitizeTypedInput(next, reason, inputValueSanitizer));\n };\n\n const handleValueChange: ComboboxProps<Value>['onValueChange'] = (next, event) => {\n // Emptying the input once the selection changes is this component's job while it holds the\n // text; Base UI does it itself otherwise. React bails out when the text is already empty.\n if (ownsInput) setInputValue((prev) => (prev === '' ? prev : ''));\n if (!onValueChange) return;\n\n const created: Value[] = [];\n const converted = (() => {\n if (!allowCreate || !next.some(isCreatableItem)) return next;\n\n // Items by display string, so a value naming one selects it rather than minting a twin that\n // would be a second chip for one value. Built per commit — the render path only needs to\n // know whether a single value names an item.\n const itemsByLabel = new Map<string, Value>();\n for (const item of allFlatItems) itemsByLabel.set(labelKey(item), item);\n\n return next.flatMap((item) => {\n if (!isCreatableItem(item)) return [item];\n\n return addedCreateParts.map((part) => {\n const existing = itemsByLabel.get(part.toLowerCase());\n if (existing !== undefined) return existing;\n\n const value = defaultToCreateValue(part, sampleItem, queryToCreateValue) as Value;\n created.push(value);\n return value;\n });\n });\n })();\n\n const hasSelectAll = converted.some((item) => isSelectAllItem(item));\n const newValue = (() => {\n if (!hasSelectAllRow) return converted;\n if (!hasSelectAll) return isAllSelected ? [] : converted;\n return isAllSelected ? converted.filter((item) => !isSelectAllItem(item)) : allFlatItems;\n })();\n\n if (allowCreate) {\n // Keep only the created values the selection being emitted still holds — `valueProp` is the\n // selection before this change, so a value created right now is not in it yet.\n const selected = new Set(newValue.map(itemToString));\n setCreatedItems((prev) =>\n [...prev, ...created].filter((item) => selected.has(itemToString(item))),\n );\n }\n\n onValueChange(newValue, event);\n };\n\n /**\n * The create row.\n *\n * - `queryToCreateLabel` receives the values committing the row adds, rather than the entry as\n * typed — so the row cannot name a value it drops as a stray separator, a repeat, or one the\n * selection already holds, nor stay silent about one it selects from `items`.\n * - For an entry standing for a single value that string is the entry itself.\n */\n const renderCreatableItem = (item: CreatableItem) => (\n <Combobox.Item value={item} icon={<Plus />}>\n {queryToCreateLabel(joinCreateParts(addedCreateParts, createSeparator))}\n </Combobox.Item>\n );\n\n const renderItem = (item: Value) => {\n return (\n <Combobox.Item\n value={item}\n indicator={indicator}\n icon={itemToIcon(item)}\n disabled={itemToDisabled(item)}\n >\n {itemToLabel(item)}\n </Combobox.Item>\n );\n };\n\n return (\n <Combobox.Root<Value, true>\n multiple\n // Base UI highlights nothing until ArrowDown, so Enter after typing would drop the query\n // silently — no selection, and the popup closes. Highlighting the first match makes Enter\n // commit it, including the creatable row when `allowCreate` is on.\n autoHighlight\n items={items}\n value={value}\n defaultValue={defaultValue}\n filter={filter}\n isItemEqualToValue={isItemEqualToValue}\n onValueChange={handleValueChange}\n itemToStringLabel={wrappedItemToStringLabel}\n itemToStringValue={wrappedItemToStringValue}\n disabled={disabled}\n inputRef={inputRef}\n {...(ownsInput ? { inputValue, onInputValueChange: handleInputValueChange } : {})}\n >\n <BaseCombobox.Chips render={<Fragment />}>\n <Combobox.InputGroup\n variant={variant}\n sizing={sizing}\n state={state}\n focusVariant={focusVariant}\n className={className}\n >\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-wrap tw:items-center tw:gap-1.5 tw:px-4 tw:py-1.5\">\n <Combobox.Chips<Value>\n maxVisible={maxVisible}\n variant={chipVariant}\n itemToChipLabel={itemToChipLabel ?? itemToLabel}\n itemToChipColor={itemToChipColor}\n pinnedChipLabels={pinnedChipLabels}\n >\n {renderChips}\n </Combobox.Chips>\n <div className=\"tw:flex tw:flex-1 tw:items-center tw:gap-1\">\n <Combobox.Input\n id={id}\n name={name}\n onBlur={onBlur}\n aria-describedby={ariaDescribedBy}\n aria-invalid={ariaInvalid}\n aria-required={ariaRequired}\n placeholder={placeholder}\n disabled={disabled}\n // This row already owns its own edge padding above, and chips share the row with\n // the input rather than sitting outside it — cancel the group's own `&_input`\n // padding so it doesn't double up on top of this row's.\n className=\"tw:w-auto tw:min-w-[120px] tw:flex-1 tw:!px-0 tw:!py-0\"\n />\n {allowClear && (\n <InputGroup.Button asChild aria-label=\"Clear\" disabled={disabled}>\n <BaseCombobox.Clear>\n <X className=\"tw:size-4\" />\n </BaseCombobox.Clear>\n </InputGroup.Button>\n )}\n <InputGroup.Button disabled={disabled} asChild aria-label=\"Open combobox\">\n <BaseCombobox.Trigger>\n <ChevronDown className=\"tw:size-4\" />\n </BaseCombobox.Trigger>\n </InputGroup.Button>\n </div>\n </div>\n </Combobox.InputGroup>\n </BaseCombobox.Chips>\n <Combobox.Content>\n <Combobox.Empty>{empty}</Combobox.Empty>\n <Combobox.List>\n {(itemOrGroup: Value | GroupShape) => {\n if (isSelectAllItem(itemOrGroup)) {\n return (\n <Combobox.Item value={itemOrGroup} indicator=\"checkbox\">\n {itemOrGroup.label}\n </Combobox.Item>\n );\n }\n\n if (isCreatableItem(itemOrGroup)) {\n return renderCreatableItem(itemOrGroup);\n }\n\n if (isGroupItem(itemOrGroup)) {\n const maybeCreatable = itemOrGroup.items[0];\n\n if (isCreatableItem(maybeCreatable)) {\n return renderCreatableItem(maybeCreatable);\n }\n\n const groupLabel = groupToLabel(itemOrGroup);\n return (\n <Combobox.Group items={itemOrGroup.items}>\n {groupLabel && <Combobox.GroupLabel>{groupLabel}</Combobox.GroupLabel>}\n <Combobox.GroupList>{renderItem}</Combobox.GroupList>\n </Combobox.Group>\n );\n }\n\n return renderItem(itemOrGroup);\n }}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InputGroup } from "../../InputGroup-
|
|
1
|
+
import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
//#region src/blocks/NumberInput/NumberInput.tsx
|
|
4
4
|
const toNumberOrNull = (event) => Number.isNaN(event.target.valueAsNumber) ? null : event.target.valueAsNumber;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { PageToolbar } from "../../PageToolbar-
|
|
1
|
+
import { PageToolbar } from "../../PageToolbar-DExqEYGl.js";
|
|
2
2
|
export { PageToolbar };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { createChangeInputEvent } from "../../utils-
|
|
1
|
+
import { createChangeInputEvent } from "../../utils-DSvrhU8E.js";
|
|
2
2
|
import { mergeRefs } from "../utils/mergeRefs.js";
|
|
3
3
|
import { ArrowBigUpDash, Eye, EyeOff, X } from "../../icons-Cek151jC.js";
|
|
4
|
-
import { InputGroup } from "../../InputGroup-
|
|
4
|
+
import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
|
|
5
5
|
import { useControllableState } from "../../useControllableState-M6494mCT.js";
|
|
6
6
|
import { useRef, useState } from "react";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { SearchInput } from "../../SearchInput-
|
|
1
|
+
import { SearchInput } from "../../SearchInput-D4UgAXJK.js";
|
|
2
2
|
export { SearchInput };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { cn } from "../../classNames-BzrkDnOD.js";
|
|
2
|
-
import { keyCodes } from "../../utils-
|
|
2
|
+
import { keyCodes } from "../../utils-DSvrhU8E.js";
|
|
3
3
|
import { ChevronDown, ChevronUp, Search } from "../../icons-Cek151jC.js";
|
|
4
4
|
import { Button } from "../../Button-DsRrU5F1.js";
|
|
5
5
|
import { ButtonGroup } from "../components/ButtonGroup.js";
|
|
6
6
|
import { Separator } from "../components/Separator.js";
|
|
7
|
-
import { TextInput } from "../../TextInput-
|
|
7
|
+
import { TextInput } from "../../TextInput-DH5SkbsE.js";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region src/blocks/SearchInputWithNavigation/SearchInputWithNavigation.tsx
|
|
10
10
|
const SearchInputWithNavigation = ({ ref, value, onValueChange, placeholder = "Search...", variant = "secondary", onClear, focusVariant, currentIndex, totalResults, onNavigateNext, onNavigatePrevious, className }) => {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { SectionNav } from "../../SectionNav-
|
|
1
|
+
import { SectionNav } from "../../SectionNav-OkKCjSA-.js";
|
|
2
2
|
export { SectionNav };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { TextInput } from "../../TextInput-
|
|
1
|
+
import { TextInput } from "../../TextInput-DH5SkbsE.js";
|
|
2
2
|
export { TextInput };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InputGroup } from "../../InputGroup-
|
|
1
|
+
import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
|
|
2
2
|
import { useControllableState } from "../../useControllableState-M6494mCT.js";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
//#region src/blocks/Textarea/Textarea.tsx
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { createChangeInputEvent } from "../../utils-
|
|
1
|
+
import { createChangeInputEvent } from "../../utils-DSvrhU8E.js";
|
|
2
2
|
import { mergeRefs } from "../utils/mergeRefs.js";
|
|
3
3
|
import { Clock, X } from "../../icons-Cek151jC.js";
|
|
4
|
-
import { InputGroup } from "../../InputGroup-
|
|
4
|
+
import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
|
|
5
5
|
import { useControllableState } from "../../useControllableState-M6494mCT.js";
|
|
6
6
|
import { TimePicker } from "../../TimePicker-BGeqc-Ed.js";
|
|
7
7
|
import { useRef, useState } from "react";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Alert } from "../../Alert-
|
|
1
|
+
import { Alert } from "../../Alert-Ba5b2YPq.js";
|
|
2
2
|
export { Alert };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cn } from "../../classNames-BzrkDnOD.js";
|
|
2
|
-
import { useSHA256 } from "../../utils-
|
|
2
|
+
import { useSHA256 } from "../../utils-DSvrhU8E.js";
|
|
3
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import BoringAvatar from "boring-avatars";
|
|
5
5
|
//#region src/components/Avatar.tsx
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Badge } from "../../Badge-
|
|
1
|
+
import { Badge } from "../../Badge-D0pXdekt.js";
|
|
2
2
|
export { Badge };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { BrandLogo } from "../../BrandLogo-
|
|
1
|
+
import { BrandLogo } from "../../BrandLogo-CoKBk4MI.js";
|
|
2
2
|
export { BrandLogo };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Breadcrumb } from "../../Breadcrumb-
|
|
1
|
+
import { Breadcrumb } from "../../Breadcrumb-g_xn_-Nf.js";
|
|
2
2
|
export { Breadcrumb };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Checkbox } from "../../Checkbox-
|
|
1
|
+
import { Checkbox } from "../../Checkbox-CUIn2jap.js";
|
|
2
2
|
export { Checkbox };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Clipboard } from "../../Clipboard-
|
|
1
|
+
import { Clipboard } from "../../Clipboard-BTW6C-b_.js";
|
|
2
2
|
export { Clipboard };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cn } from "../../classNames-BzrkDnOD.js";
|
|
2
|
-
import { keyCodes } from "../../utils-
|
|
2
|
+
import { keyCodes } from "../../utils-DSvrhU8E.js";
|
|
3
3
|
import { ChevronDown } from "../../icons-Cek151jC.js";
|
|
4
4
|
import { Collapsible } from "../../Collapsible-BQXWEOBC.js";
|
|
5
5
|
import { useState } from "react";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Combobox } from "../../Combobox-
|
|
2
|
-
export { Combobox };
|
|
1
|
+
import { Combobox, filterByWords, matchByWords, namedLabel, withBlankValues } from "../../Combobox-BfIfaVMA.js";
|
|
2
|
+
export { Combobox, filterByWords, matchByWords, namedLabel, withBlankValues };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { InputGroup } from "../../InputGroup-
|
|
1
|
+
import { InputGroup } from "../../InputGroup-DcZRlVnN.js";
|
|
2
2
|
export { InputGroup };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Kbd, kbdVariants, keys } from "../../Kbd-
|
|
1
|
+
import { Kbd, kbdVariants, keys } from "../../Kbd-Cvvt91Q8.js";
|
|
2
2
|
export { Kbd, kbdVariants, keys };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Navbar } from "../../Navbar-
|
|
1
|
+
import { Navbar } from "../../Navbar-Liy1TPI7.js";
|
|
2
2
|
export { Navbar };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Popconfirm } from "../../Popconfirm-
|
|
1
|
+
import { Popconfirm } from "../../Popconfirm-5pBzT_HQ.js";
|
|
2
2
|
export { Popconfirm };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RadioGroup } from "../../RadioGroup-
|
|
1
|
+
import { RadioGroup } from "../../RadioGroup-DXPbSj8P.js";
|
|
2
2
|
export { RadioGroup };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Search, SearchForm } from "../../Search-
|
|
1
|
+
import { Search, SearchForm } from "../../Search-5uQAiNIP.js";
|
|
2
2
|
export { Search, SearchForm };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Select } from "../../Select-
|
|
1
|
+
import { Select } from "../../Select-DV3Hak_l.js";
|
|
2
2
|
export { Select };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Sidebar, SidebarProvider, useOptionalSidebar, useSidebar } from "../../Sidebar-
|
|
1
|
+
import { Sidebar, SidebarProvider, useOptionalSidebar, useSidebar } from "../../Sidebar-D3cY1kha.js";
|
|
2
2
|
export { Sidebar, SidebarProvider, useOptionalSidebar, useSidebar };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Slider } from "../../Slider-
|
|
1
|
+
import { Slider } from "../../Slider-CRf-bB4y.js";
|
|
2
2
|
export { Slider };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Switch } from "../../Switch-
|
|
1
|
+
import { Switch } from "../../Switch-B0WdGSjz.js";
|
|
2
2
|
export { Switch };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { DEFAULT_BRAND_ID, DEFAULT_COLOR_SCHEME } from "../../defaults-i_xG2F_1.js";
|
|
2
2
|
import { ArgoDesignContext, useArgoDesign, useTheme } from "../../context-D7X470dy.js";
|
|
3
|
-
import { ThemeProvider, ThemeScope, brandSchema, exampleCustomer, keboola, keboolaLegacySidebar, keboolaLegacyTopnav, useThemeScopeContainer } from "../../ThemeProvider-
|
|
3
|
+
import { ThemeProvider, ThemeScope, brandSchema, exampleCustomer, keboola, keboolaLegacySidebar, keboolaLegacyTopnav, useThemeScopeContainer } from "../../ThemeProvider-2RMdVGxO.js";
|
|
4
4
|
export { ArgoDesignContext, DEFAULT_COLOR_SCHEME, DEFAULT_BRAND_ID as DEFAULT_KEBOOLA_BRAND_ID, ThemeProvider, ThemeScope, brandSchema, exampleCustomer, keboola, keboolaLegacySidebar, keboolaLegacyTopnav, useArgoDesign, useTheme, useThemeScopeContainer };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Timeline } from "../../Timeline-
|
|
1
|
+
import { Timeline } from "../../Timeline-BG5Xogxh.js";
|
|
2
2
|
export { Timeline };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Tooltip, TooltipProvider } from "../../utils-
|
|
1
|
+
import { Tooltip, TooltipProvider } from "../../utils-DSvrhU8E.js";
|
|
2
2
|
export { Tooltip, TooltipProvider };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cn } from "../../classNames-BzrkDnOD.js";
|
|
2
|
-
import { Tooltip } from "../../utils-
|
|
2
|
+
import { Tooltip } from "../../utils-DSvrhU8E.js";
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/Truncated.tsx
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { DEFAULT_WORKBENCH_BAR_HEIGHT_IN_REM, DEFAULT_WORKBENCH_PANEL_HEIGHT_IN_PX, MIN_WORKBENCH_PANEL_HEIGHT_IN_PX, Workbench, useWorkbench } from "../../Workbench-
|
|
1
|
+
import { DEFAULT_WORKBENCH_BAR_HEIGHT_IN_REM, DEFAULT_WORKBENCH_PANEL_HEIGHT_IN_PX, MIN_WORKBENCH_PANEL_HEIGHT_IN_PX, Workbench, useWorkbench } from "../../Workbench-UR2FBC7I.js";
|
|
2
2
|
export { DEFAULT_WORKBENCH_BAR_HEIGHT_IN_REM, DEFAULT_WORKBENCH_PANEL_HEIGHT_IN_PX, MIN_WORKBENCH_PANEL_HEIGHT_IN_PX, Workbench, useWorkbench };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ZoomableSvg, svgToPngBlob, toSvgFileContent } from "../../ZoomableSvg-
|
|
1
|
+
import { ZoomableSvg, svgToPngBlob, toSvgFileContent } from "../../ZoomableSvg-pooPb1Cu.js";
|
|
2
2
|
export { ZoomableSvg, svgToPngBlob, toSvgFileContent };
|