@keboola/design 9.0.0 → 9.1.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/dist/rjsf.cjs CHANGED
@@ -25,7 +25,7 @@ var r = require('@codemirror/legacy-modes/mode/r');
25
25
  var shell = require('@codemirror/legacy-modes/mode/shell');
26
26
  var toml = require('@codemirror/legacy-modes/mode/toml');
27
27
  var codemirrorThemeGithub = require('@uiw/codemirror-theme-github');
28
- var codemirrorLangSfsql = require('@keboola/codemirror-lang-sfsql');
28
+ var codemirrorLangSql = require('@keboola/codemirror-lang-sql');
29
29
  var colors = require('@keboola/tailwind-config/colors');
30
30
  var simpleMode = require('@codemirror/legacy-modes/mode/simple-mode');
31
31
  var state = require('@codemirror/state');
@@ -38,6 +38,7 @@ var TextareaAutosize = require('react-textarea-autosize');
38
38
  var reactCheckbox = require('@radix-ui/react-checkbox');
39
39
  var reactPopover = require('@radix-ui/react-popover');
40
40
  var combobox = require('@base-ui/react/combobox');
41
+ var reactVirtual = require('@tanstack/react-virtual');
41
42
  var RRadioGroup = require('@radix-ui/react-radio-group');
42
43
  var RSeparator = require('@radix-ui/react-separator');
43
44
 
@@ -1141,6 +1142,7 @@ var LANGUAGE_MODES = [
1141
1142
  "text/x-mysql",
1142
1143
  "text/x-pgsql",
1143
1144
  "text/x-mssql",
1145
+ // Snowflake, under a historical name — these strings are a published prop contract.
1144
1146
  "text/x-sfsql",
1145
1147
  "text/x-plsql",
1146
1148
  "text/x-rsrc",
@@ -1202,8 +1204,6 @@ var ALWAYS_OFF = {
1202
1204
  var buildBasicSetup = (readOnly) => ({
1203
1205
  ...ALWAYS_OFF,
1204
1206
  ...readOnly ? {
1205
- history: false,
1206
- historyKeymap: false,
1207
1207
  closeBrackets: false,
1208
1208
  closeBracketsKeymap: false,
1209
1209
  lintKeymap: false,
@@ -1225,20 +1225,6 @@ var buildCustomTheme = () => codemirrorThemeGithub.githubLightInit({
1225
1225
  selection: resolveToken("primary", "31 143 255")
1226
1226
  }
1227
1227
  });
1228
- var sfsqlWithLanguageData = {
1229
- ...codemirrorLangSfsql.sfsql,
1230
- languageData: {
1231
- ...codemirrorLangSfsql.sfsql.languageData,
1232
- // `toggleComment` is a no-op without these, so Mod-/ silently does nothing.
1233
- commentTokens: { line: "--", block: { open: "/*", close: "*/" } },
1234
- autocomplete: autocomplete.completeFromList(
1235
- Object.keys(codemirrorLangSfsql.modeSpec.keywords).map((label) => ({
1236
- label: label.toUpperCase(),
1237
- type: "keyword"
1238
- }))
1239
- )
1240
- }
1241
- };
1242
1228
  var getLanguageMode = (mode) => {
1243
1229
  switch (mode) {
1244
1230
  case void 0:
@@ -1255,7 +1241,7 @@ var getLanguageMode = (mode) => {
1255
1241
  case "text/x-mssql":
1256
1242
  return langSql.sql({ upperCaseKeywords: true, dialect: langSql.MSSQL });
1257
1243
  case "text/x-sfsql":
1258
- return language.StreamLanguage.define(sfsqlWithLanguageData);
1244
+ return langSql.sql({ upperCaseKeywords: true, dialect: codemirrorLangSql.getSqlDialect("snowflake") });
1259
1245
  case "text/x-plsql":
1260
1246
  return langSql.sql({ upperCaseKeywords: true, dialect: langSql.PLSQL });
1261
1247
  case "text/x-rsrc":
@@ -1517,7 +1503,7 @@ var completeVariables = (variables = []) => {
1517
1503
  return { from: match2.to - name.length, options };
1518
1504
  };
1519
1505
  };
1520
- var emptyArray = [];
1506
+ var useVariableCompletion = (variables = []) => useStableCallback(completeVariables(variables));
1521
1507
  var emptyObject = {};
1522
1508
  var CodeEditor = ({
1523
1509
  value,
@@ -1529,7 +1515,8 @@ var CodeEditor = ({
1529
1515
  searchQuery,
1530
1516
  searchMatchIndex,
1531
1517
  readOnly = false,
1532
- autocompletions = emptyArray,
1518
+ inputLocked = false,
1519
+ autocompletions,
1533
1520
  completionSource,
1534
1521
  variables,
1535
1522
  extraKeys = emptyObject,
@@ -1565,21 +1552,23 @@ var CodeEditor = ({
1565
1552
  [boundKeysSignature]
1566
1553
  );
1567
1554
  const tooltipLayer = useTooltipsExtension();
1568
- const variableCompletion = React26.useMemo(() => completeVariables(variables), [variables]);
1555
+ const variableCompletion = useVariableCompletion(variables);
1569
1556
  const customTheme = useThemedExtension("editor:syntax", buildCustomTheme);
1570
1557
  const baseTheme = useThemedExtension(
1571
1558
  "code-editor:chrome",
1572
1559
  () => view.EditorView.theme(buildBaseThemeStyles())
1573
1560
  );
1574
1561
  const commonExtensions = React26.useMemo(() => {
1562
+ const callerCompletions = completionSource ?? (completeAny ? autocomplete.completeAnyWord : autocompletions?.length ? autocompletions : null);
1563
+ const completionEntries = [
1564
+ ...callerCompletions ? [{ autocomplete: callerCompletions }] : [],
1565
+ { autocomplete: variableCompletion }
1566
+ ];
1575
1567
  return [
1576
1568
  getLanguageMode(mode),
1577
1569
  shouldLintJson(mode, readOnly) ? lint.linter(langJson.jsonParseLinter()) : [],
1578
1570
  withLineWrapping ? view.EditorView.lineWrapping : [],
1579
- CodeMirror.EditorState.languageData.of(() => [
1580
- { autocomplete: completionSource ?? (completeAny ? autocomplete.completeAnyWord : autocompletions) }
1581
- ]),
1582
- CodeMirror.EditorState.languageData.of(() => [{ autocomplete: variableCompletion }]),
1571
+ CodeMirror.EditorState.languageData.of(() => completionEntries),
1583
1572
  view.keymap.of(
1584
1573
  boundKeys.map((key) => ({
1585
1574
  key,
@@ -1620,7 +1609,10 @@ var CodeEditor = ({
1620
1609
  ...commonExtensions,
1621
1610
  view.placeholder(placeholder),
1622
1611
  view.EditorView.editable.of(!readOnly),
1623
- CodeMirror.EditorState.readOnly.of(readOnly),
1612
+ // The lock is this facet and nothing else. `contenteditable` is what the
1613
+ // read-only wash keys off, and `basicSetup` is what holds the undo history,
1614
+ // so leaving both alone is what makes the lock invisible.
1615
+ CodeMirror.EditorState.readOnly.of(readOnly || inputLocked),
1624
1616
  previousValue ? merge.unifiedMergeView({
1625
1617
  original: previousValue,
1626
1618
  mergeControls: false,
@@ -1628,7 +1620,7 @@ var CodeEditor = ({
1628
1620
  collapseUnchanged: withCollapseUnchanged ? {} : void 0
1629
1621
  }) : []
1630
1622
  ];
1631
- }, [commonExtensions, placeholder, readOnly, previousValue, withCollapseUnchanged]);
1623
+ }, [commonExtensions, placeholder, readOnly, inputLocked, previousValue, withCollapseUnchanged]);
1632
1624
  const config = React26.useMemo(() => {
1633
1625
  return {
1634
1626
  ...buildBasicSetup(readOnly),
@@ -9245,9 +9237,9 @@ var ComboboxItemIndicator = ({ ref, className, variant = "check", ...props }) =>
9245
9237
  "tw:absolute",
9246
9238
  "tw:right-2",
9247
9239
  "tw:group-data-[variant=default]/combobox-content:right-4",
9248
- // Lucide SVGs default to 24×24 — constrain the rendered child so the
9249
- // 16px indicator slot owns the actual size.
9250
- 'tw:[&_svg:not([class*="tw:size-"])]:size-4',
9240
+ // `render={<Check />}` makes the icon the indicator element itself (not a descendant), so a
9241
+ // `[&_svg]` rule never matches it — size it directly or Lucide renders at its 24px default.
9242
+ "tw:size-4",
9251
9243
  "tw:group-data-[highlighted]/combobox-item:text-accent-foreground",
9252
9244
  "tw:group-data-[variant=default]/combobox-content:group-data-[highlighted]/combobox-item:text-foreground",
9253
9245
  className
@@ -9372,6 +9364,9 @@ var ComboboxGroupLabel = ({ ref, className, ...props }) => /* @__PURE__ */ jsxRu
9372
9364
  }
9373
9365
  );
9374
9366
  var ComboboxCollection = ({ ...props }) => /* @__PURE__ */ jsxRuntime.jsx(combobox.Combobox.Collection, { "data-slot": "combobox-collection", ...props });
9367
+ var VIRTUALIZE_THRESHOLD = 30;
9368
+ var ESTIMATED_ROW_HEIGHT = 40;
9369
+ var ESTIMATED_LIST_HEIGHT = 320;
9375
9370
  var Combobox = ({
9376
9371
  // root props
9377
9372
  items: _itemsProp,
@@ -9398,6 +9393,7 @@ var Combobox = ({
9398
9393
  empty = "No items",
9399
9394
  indicator,
9400
9395
  prefix: prefix2,
9396
+ virtualized = false,
9401
9397
  // creatable
9402
9398
  allowCreate,
9403
9399
  queryToCreateValue,
@@ -9421,7 +9417,9 @@ var Combobox = ({
9421
9417
  const label = value === null ? "" : itemToStringLabelProp?.(value) ?? toLabel(value);
9422
9418
  setInputValue((prev) => prev === label ? prev : label);
9423
9419
  }, [value]);
9424
- const query = inputValue.trim();
9420
+ const selectedLabel = value == null ? void 0 : itemToStringLabelProp?.(value) ?? toLabel(value);
9421
+ const isShowingSelection = selectedLabel !== void 0 && inputValue === selectedLabel;
9422
+ const query = (isShowingSelection ? "" : inputValue).trim();
9425
9423
  const queryLower = query.toLowerCase();
9426
9424
  const itemsProp = _itemsProp ?? [];
9427
9425
  const sampleItem = itemsProp.flatMap((item) => isGroupItem(item) ? item.items : [item])[0];
@@ -9446,7 +9444,7 @@ var Combobox = ({
9446
9444
  if (isCreatableItem(value2)) return value2.value;
9447
9445
  return itemToStringLabelProp?.(value2) ?? toLabel(value2);
9448
9446
  };
9449
- const wrappedFilter = !allowCreate || !filter ? filter : (item, ...args) => isCreatableItem(item) || filter(item, ...args);
9447
+ const wrappedFilter = isShowingSelection ? () => true : !allowCreate || !filter ? filter : (item, ...args) => isCreatableItem(item) || filter(item, ...args);
9450
9448
  const wrappedItemToStringValue = !allowCreate || !itemToStringValue ? itemToStringValue : (item) => isCreatableItem(item) ? item.value : itemToStringValue(item);
9451
9449
  const isItemEqualToValue = (a, b) => {
9452
9450
  if (isCreatableItem(a) || isCreatableItem(b)) return toValueKey(a) === toValueKey(b);
@@ -9481,10 +9479,34 @@ var Combobox = ({
9481
9479
  closeReasonRef.current = "item-press";
9482
9480
  onValueChange?.(next, event);
9483
9481
  };
9484
- const renderItem = (item) => {
9482
+ const [listElement, setListElement] = React26.useState(null);
9483
+ const isGrouped = isGroupItems(allItems);
9484
+ const shouldVirtualize = !isGrouped && (virtualized === true || virtualized === "auto" && allItems.length > VIRTUALIZE_THRESHOLD);
9485
+ const matchesQuery = (item) => {
9486
+ if (isCreatableItem(item)) return true;
9487
+ if (!query) return true;
9488
+ if (filter) return !!filter(item, query, (value2) => itemToStringLabel(value2) ?? toLabel(value2));
9489
+ return (itemToStringLabel(item) ?? toLabel(item)).toLowerCase().includes(queryLower);
9490
+ };
9491
+ const virtualItems = shouldVirtualize ? items.filter(matchesQuery) : [];
9492
+ const virtualizer = reactVirtual.useVirtualizer({
9493
+ count: virtualItems.length,
9494
+ getScrollElement: () => listElement,
9495
+ estimateSize: () => ESTIMATED_ROW_HEIGHT,
9496
+ overscan: 12,
9497
+ enabled: shouldVirtualize,
9498
+ // Seed a viewport height so rows paint on the first frame. Without it the list measures 0 until
9499
+ // the ResizeObserver fires (a frame later), which renders an empty popup on open.
9500
+ initialRect: { width: 0, height: ESTIMATED_LIST_HEIGHT }
9501
+ });
9502
+ const renderItem = (item, index) => {
9503
+ if (isCreatableItem(item)) {
9504
+ return /* @__PURE__ */ jsxRuntime.jsx(Combobox.Item, { index, value: item, icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}), children: queryToCreateLabel(item.value) });
9505
+ }
9485
9506
  return /* @__PURE__ */ jsxRuntime.jsx(
9486
9507
  Combobox.Item,
9487
9508
  {
9509
+ index,
9488
9510
  value: item,
9489
9511
  indicator,
9490
9512
  icon: itemToIcon(item),
@@ -9493,13 +9515,20 @@ var Combobox = ({
9493
9515
  }
9494
9516
  );
9495
9517
  };
9518
+ const rowStyle = (offset) => ({
9519
+ position: "absolute",
9520
+ top: 0,
9521
+ left: 0,
9522
+ width: "100%",
9523
+ transform: `translateY(${offset}px)`
9524
+ });
9496
9525
  return /* @__PURE__ */ jsxRuntime.jsxs(
9497
9526
  combobox.Combobox.Root,
9498
9527
  {
9499
- items,
9528
+ items: shouldVirtualize ? virtualItems : items,
9500
9529
  value,
9501
9530
  defaultValue,
9502
- filter: wrappedFilter,
9531
+ filter: shouldVirtualize ? null : wrappedFilter,
9503
9532
  onValueChange: handleOnValueChange,
9504
9533
  itemToStringLabel,
9505
9534
  isItemEqualToValue,
@@ -9509,6 +9538,12 @@ var Combobox = ({
9509
9538
  inputRef,
9510
9539
  inputValue,
9511
9540
  onInputValueChange: handleInputValueChange,
9541
+ virtualized: shouldVirtualize,
9542
+ onItemHighlighted: (_, details) => {
9543
+ if (shouldVirtualize && details.reason === "keyboard") {
9544
+ virtualizer.scrollToIndex(details.index);
9545
+ }
9546
+ },
9512
9547
  children: [
9513
9548
  /* @__PURE__ */ jsxRuntime.jsxs(
9514
9549
  ComboboxInputGroup,
@@ -9530,7 +9565,30 @@ var Combobox = ({
9530
9565
  ),
9531
9566
  /* @__PURE__ */ jsxRuntime.jsxs(ComboboxContent, { children: [
9532
9567
  /* @__PURE__ */ jsxRuntime.jsx(ComboboxEmpty, { children: empty }),
9533
- /* @__PURE__ */ jsxRuntime.jsx(ComboboxList, { children: (itemOrGroup) => {
9568
+ shouldVirtualize ? /* @__PURE__ */ jsxRuntime.jsx(ComboboxList, { ref: setListElement, children: /* @__PURE__ */ jsxRuntime.jsx(
9569
+ "div",
9570
+ {
9571
+ style: {
9572
+ position: "relative",
9573
+ width: "100%",
9574
+ height: `${virtualizer.getTotalSize()}px`
9575
+ },
9576
+ children: virtualizer.getVirtualItems().map((row) => {
9577
+ const item = virtualItems[row.index];
9578
+ if (item === void 0) return null;
9579
+ return /* @__PURE__ */ jsxRuntime.jsx(
9580
+ "div",
9581
+ {
9582
+ "data-index": row.index,
9583
+ ref: virtualizer.measureElement,
9584
+ style: rowStyle(row.start),
9585
+ children: renderItem(item, row.index)
9586
+ },
9587
+ row.key
9588
+ );
9589
+ })
9590
+ }
9591
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(ComboboxList, { children: (itemOrGroup) => {
9534
9592
  if (isCreatableItem(itemOrGroup))
9535
9593
  return /* @__PURE__ */ jsxRuntime.jsx(Combobox.Item, { value: itemOrGroup, icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}), children: queryToCreateLabel(itemOrGroup.value) });
9536
9594
  if (isGroupItem(itemOrGroup)) {
@@ -9541,7 +9599,7 @@ var Combobox = ({
9541
9599
  const groupLabel = groupToLabel(itemOrGroup);
9542
9600
  return /* @__PURE__ */ jsxRuntime.jsxs(Combobox.Group, { items: itemOrGroup.items, children: [
9543
9601
  groupLabel && /* @__PURE__ */ jsxRuntime.jsx(Combobox.GroupLabel, { children: groupLabel }),
9544
- /* @__PURE__ */ jsxRuntime.jsx(Combobox.GroupList, { children: renderItem })
9602
+ /* @__PURE__ */ jsxRuntime.jsx(Combobox.GroupList, { children: (item) => renderItem(item) })
9545
9603
  ] });
9546
9604
  }
9547
9605
  return renderItem(itemOrGroup);