@sia.soul/sia-react-ui 0.1.24 → 0.1.26

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.
Files changed (37) hide show
  1. package/dist/{Select-O_yY51vc.d.ts → Select-CCrPqULn.d.ts} +1 -1
  2. package/dist/{Select-W_xpkpOW.d.cts → Select-YJbT-MF1.d.cts} +1 -1
  3. package/dist/chart.cjs +1 -1
  4. package/dist/chart.js +4 -4
  5. package/dist/{chunk-6R7JY7IY.js → chunk-5MW3NE2V.js} +227 -202
  6. package/dist/{chunk-T2QIW4OO.js → chunk-IQU4GGLM.js} +11 -5
  7. package/dist/{chunk-6WBABNAX.js → chunk-IYNS423D.js} +1 -1
  8. package/dist/{chunk-RGXVPS37.js → chunk-LK56NX5F.js} +3 -3
  9. package/dist/{chunk-LIYCU2GU.js → chunk-NAOV53NK.js} +5 -5
  10. package/dist/{chunk-LA7O3PN4.js → chunk-PXHBIRQW.js} +1 -1
  11. package/dist/{chunk-NSSPGXNM.js → chunk-RAO3JHDL.js} +1 -1
  12. package/dist/{chunk-GUXAWU63.js → chunk-TZROBD65.js} +3 -3
  13. package/dist/{chunk-LRPQ5FGE.js → chunk-YF2I6SDB.js} +3 -3
  14. package/dist/{chunk-OH6YILJW.js → chunk-YQDHCORW.js} +1 -1
  15. package/dist/{core-tbb9ZiBY.d.cts → core-BM-wnJRa.d.cts} +3 -3
  16. package/dist/{core-BOzLwiXG.d.ts → core-CLqv6btD.d.ts} +3 -3
  17. package/dist/core.cjs +270 -243
  18. package/dist/core.css +10 -5
  19. package/dist/core.d.cts +2 -2
  20. package/dist/core.d.ts +2 -2
  21. package/dist/core.js +6 -6
  22. package/dist/index.cjs +296 -252
  23. package/dist/index.css +10 -5
  24. package/dist/index.d.cts +20 -14
  25. package/dist/index.d.ts +20 -14
  26. package/dist/index.js +29 -15
  27. package/dist/markdown-editor.cjs +1 -1
  28. package/dist/markdown-editor.js +2 -2
  29. package/dist/rich-text-editor.cjs +2 -2
  30. package/dist/rich-text-editor.js +4 -4
  31. package/dist/{select-date-range-C9w8z3G8.d.cts → select-date-range-CtA-B8DB.d.cts} +1 -1
  32. package/dist/{select-date-range-BjqFUeU6.d.ts → select-date-range-D9W_mmMq.d.ts} +1 -1
  33. package/dist/select-date-range.cjs +706 -674
  34. package/dist/select-date-range.d.cts +2 -2
  35. package/dist/select-date-range.d.ts +2 -2
  36. package/dist/select-date-range.js +5 -5
  37. package/package.json +1 -1
@@ -301,7 +301,7 @@ interface SelectProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "def
301
301
  */
302
302
  notFoundContent?: ReactNode;
303
303
  }
304
- /** 选择器组件。 */
304
+ /** 选择器组件。下拉面板每次展开自动定位到列表顺序中的第一个已选项,支持普通和虚拟列表;未选中时从顶部显示。 */
305
305
  declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLButtonElement>>;
306
306
 
307
307
  export { type ButtonProps as B, type ModalOpenConfig as M, type OverlayContainer as O, type SelectOption as S, type OverlayApiHandle as a, type SelectChangeValue as b, type SelectProps as c, type ModalActionResult as d, type ButtonSize as e, Button as f, type ButtonVariant as g, Modal as h, type ModalProps as i, type ModalType as j, Select as k, type SelectMode as l, type SelectValue as m };
@@ -301,7 +301,7 @@ interface SelectProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "def
301
301
  */
302
302
  notFoundContent?: ReactNode;
303
303
  }
304
- /** 选择器组件。 */
304
+ /** 选择器组件。下拉面板每次展开自动定位到列表顺序中的第一个已选项,支持普通和虚拟列表;未选中时从顶部显示。 */
305
305
  declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLButtonElement>>;
306
306
 
307
307
  export { type ButtonProps as B, type ModalOpenConfig as M, type OverlayContainer as O, type SelectOption as S, type OverlayApiHandle as a, type SelectChangeValue as b, type SelectProps as c, type ModalActionResult as d, type ButtonSize as e, Button as f, type ButtonVariant as g, Modal as h, type ModalProps as i, type ModalType as j, Select as k, type SelectMode as l, type SelectValue as m };
package/dist/chart.cjs CHANGED
@@ -317,7 +317,7 @@ function installTitleTooltips(doc) {
317
317
  else if (active.getAttribute("data-sia-title") !== doc.getElementById(tooltipId)?.textContent) render();
318
318
  });
319
319
  observer.observe(doc.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["data-sia-title"] });
320
- }, 250);
320
+ }, 600);
321
321
  };
322
322
  doc.addEventListener("pointerover", (event) => {
323
323
  if (event.pointerType === "touch") return;
package/dist/chart.js CHANGED
@@ -56,10 +56,10 @@ import {
56
56
  smoothSvgPath,
57
57
  svgArcPath,
58
58
  transferCompositeValue
59
- } from "./chunk-GUXAWU63.js";
60
- import "./chunk-OH6YILJW.js";
61
- import "./chunk-6WBABNAX.js";
62
- import "./chunk-NSSPGXNM.js";
59
+ } from "./chunk-TZROBD65.js";
60
+ import "./chunk-YQDHCORW.js";
61
+ import "./chunk-IYNS423D.js";
62
+ import "./chunk-RAO3JHDL.js";
63
63
  export {
64
64
  BarChart,
65
65
  CHART_VIEWBOX_HEIGHT,
@@ -2,10 +2,10 @@ import {
2
2
  Dropdown,
3
3
  Icon,
4
4
  Input
5
- } from "./chunk-LRPQ5FGE.js";
5
+ } from "./chunk-YF2I6SDB.js";
6
6
  import {
7
7
  Button
8
- } from "./chunk-6WBABNAX.js";
8
+ } from "./chunk-IYNS423D.js";
9
9
  import {
10
10
  ControlSizeContext,
11
11
  PopupPortal,
@@ -13,7 +13,7 @@ import {
13
13
  useControllableState,
14
14
  useFloatingPlaceholder,
15
15
  withTitleTooltip
16
- } from "./chunk-NSSPGXNM.js";
16
+ } from "./chunk-RAO3JHDL.js";
17
17
 
18
18
  // src/components/Checkbox.tsx
19
19
  import { createContext, forwardRef, useContext, useEffect, useId, useMemo, useRef } from "react";
@@ -852,206 +852,15 @@ var Modal2 = Object.assign(ModalRoot, {
852
852
  }
853
853
  });
854
854
 
855
- // src/components/SelectionPanel.tsx
856
- import { useEffect as useEffect5, useId as useId4, useMemo as useMemo3, useRef as useRef5, useState as useState3 } from "react";
857
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
858
- function SelectionPanel({
859
- options,
860
- value,
861
- onChange,
862
- multiple = false,
863
- allowDeselect = false,
864
- disabled = false,
865
- loading = false,
866
- showSearch = true,
867
- showActions = true,
868
- includeUnknownValues = true,
869
- searchValue,
870
- onSearch,
871
- selectedOnly = false,
872
- showValue = false,
873
- displayField = "label",
874
- columns = 1,
875
- maxHeight = 250,
876
- autoFocusSearch = false
877
- }) {
878
- const [localSearch, setLocalSearch] = useState3("");
879
- const search = searchValue ?? localSearch;
880
- const [scrollTop, setScrollTop] = useState3(0);
881
- const [active, setActive] = useState3();
882
- const [keyboardActive, setKeyboardActive] = useState3(false);
883
- const [deselectedHover, setDeselectedHover] = useState3();
884
- const listRef = useRef5(null);
885
- const id = useId4();
886
- const selected = useMemo3(() => new Set(value), [value]);
887
- const count = Math.max(1, Math.floor(columns));
888
- const allOptions = useMemo3(() => {
889
- if (!includeUnknownValues) return [...options];
890
- const known = new Set(options.filter((option) => option.optionType !== "divider").map((option) => option.value));
891
- return [...value.filter((item) => !known.has(item)).map((item) => ({ value: item, label: String(item), group: "\u81EA\u5B9A\u4E49\u503C" })), ...options];
892
- }, [options, value, includeUnknownValues]);
893
- const filtered = useMemo3(
894
- () => allOptions.filter((option) => (!selectedOnly || selected.has(option.value)) && (!search || option.optionType !== "divider" && [option.label, option.value].some((text) => String(text ?? "").toLowerCase().includes(search.toLowerCase())))),
895
- [allOptions, selectedOnly, selected, search]
896
- );
897
- const rows = useMemo3(() => {
898
- const groups = /* @__PURE__ */ new Map();
899
- filtered.forEach((option) => {
900
- const items = groups.get(option.group) ?? [];
901
- items.push(option);
902
- groups.set(option.group, items);
903
- });
904
- const rows2 = [];
905
- let top = 0;
906
- for (const [group, items] of groups) {
907
- if (group) {
908
- rows2.push({ key: `group-${rows2.length}`, title: group, top, height: 30 });
909
- top += 30;
910
- }
911
- for (let index = 0; index < items.length; index += count) {
912
- const height = showValue ? 48 : 34;
913
- rows2.push({ key: `row-${rows2.length}`, items: items.slice(index, index + count), top, height });
914
- top += height;
915
- }
916
- }
917
- return rows2;
918
- }, [filtered, count, showValue]);
919
- const totalHeight = rows.length ? rows[rows.length - 1].top + rows[rows.length - 1].height : 0;
920
- const virtual = filtered.length > 100;
921
- const renderedRows = virtual ? rows.filter((row) => row.top + row.height >= scrollTop - 100 && row.top <= scrollTop + maxHeight + 100) : rows;
922
- const enabled = filtered.filter((option) => !option.disabled && option.optionType !== "divider");
923
- useEffect5(() => {
924
- setScrollTop(0);
925
- if (listRef.current) listRef.current.scrollTop = 0;
926
- setActive(void 0);
927
- }, [search, selectedOnly, count]);
928
- function toggle(option, keyboard = false) {
929
- if (disabled || loading || option.disabled || option.optionType === "divider") return;
930
- setActive(option.value);
931
- setKeyboardActive(keyboard);
932
- setDeselectedHover(!keyboard && !multiple && allowDeselect && selected.has(option.value) ? option.value : void 0);
933
- onChange(multiple ? selected.has(option.value) ? value.filter((item) => item !== option.value) : [...value, option.value] : allowDeselect && selected.has(option.value) ? [] : [option.value]);
934
- }
935
- function batch(operation) {
936
- if (disabled || loading) return;
937
- if (operation === "clear") {
938
- onChange([]);
939
- return;
940
- }
941
- const editable = new Set(enabled.map((option) => option.value));
942
- const retained = value.filter((item) => !editable.has(item));
943
- const add = enabled.filter((option) => operation === "all" || !selected.has(option.value)).map((option) => option.value);
944
- onChange([...retained, ...add]);
945
- }
946
- return /* @__PURE__ */ jsxs4("div", { className: "sia-selection-panel", children: [
947
- showSearch && /* @__PURE__ */ jsx4(
948
- Input,
949
- {
950
- "aria-label": "\u641C\u7D22\u9009\u9879",
951
- placeholder: "\u641C\u7D22",
952
- autoFocus: autoFocusSearch,
953
- value: search,
954
- allowClear: true,
955
- onChange: (event) => {
956
- setLocalSearch(event.target.value);
957
- onSearch?.(event.target.value);
958
- }
959
- }
960
- ),
961
- multiple && showActions && /* @__PURE__ */ jsxs4("div", { className: "sia-selection-panel__actions", children: [
962
- /* @__PURE__ */ jsx4(Button, { variant: "link", size: "small", disabled: disabled || loading || !enabled.length, onClick: () => batch("all"), children: "\u5168\u9009" }),
963
- /* @__PURE__ */ jsx4(Button, { variant: "link", size: "small", disabled: disabled || loading || !enabled.length, onClick: () => batch("invert"), children: "\u53CD\u9009" }),
964
- /* @__PURE__ */ jsx4(Button, { variant: "link", size: "small", disabled: disabled || loading || !value.length, onClick: () => batch("clear"), children: "\u6E05\u7A7A" }),
965
- /* @__PURE__ */ jsxs4("span", { children: [
966
- "\u5DF2\u9009 ",
967
- value.length,
968
- " \u9879"
969
- ] })
970
- ] }),
971
- /* @__PURE__ */ jsx4(
972
- "div",
973
- {
974
- ref: listRef,
975
- role: "listbox",
976
- "aria-label": "\u9009\u9879\u5217\u8868",
977
- "aria-multiselectable": multiple || void 0,
978
- tabIndex: disabled ? -1 : 0,
979
- className: "sia-selection-panel__list",
980
- style: { maxHeight },
981
- onScroll: (event) => setScrollTop(event.currentTarget.scrollTop),
982
- onPointerDown: () => setKeyboardActive(false),
983
- onBlur: (event) => {
984
- if (!event.currentTarget.contains(event.relatedTarget)) setKeyboardActive(false);
985
- },
986
- "aria-activedescendant": active !== void 0 ? `${id}-${typeof active}-${active}` : void 0,
987
- onKeyDown: (event) => {
988
- if (event.target instanceof HTMLInputElement) return;
989
- if (disabled || loading || !enabled.length) return;
990
- const index = enabled.findIndex((option) => option.value === active);
991
- if (["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
992
- event.preventDefault();
993
- setKeyboardActive(true);
994
- setDeselectedHover(void 0);
995
- const next = event.key === "Home" ? 0 : event.key === "End" ? enabled.length - 1 : Math.max(0, Math.min(enabled.length - 1, index + (event.key === "ArrowDown" ? 1 : -1)));
996
- const option = enabled[next];
997
- setActive(option.value);
998
- const row = rows.find((row2) => row2.items?.includes(option));
999
- if (row && listRef.current) {
1000
- listRef.current.scrollTop = Math.max(0, row.top - maxHeight / 2);
1001
- setScrollTop(listRef.current.scrollTop);
1002
- }
1003
- } else if ((event.key === "Enter" || event.key === " ") && index >= 0) {
1004
- event.preventDefault();
1005
- toggle(enabled[index], true);
1006
- }
1007
- },
1008
- children: loading ? /* @__PURE__ */ jsx4("div", { role: "status", children: "\u52A0\u8F7D\u4E2D\u2026" }) : !rows.length ? /* @__PURE__ */ jsx4("div", { className: "sia-selection-panel__empty", children: "\u6682\u65E0\u5339\u914D\u9009\u9879" }) : /* @__PURE__ */ jsx4("div", { style: { height: totalHeight, position: "relative" }, children: renderedRows.map((row) => /* @__PURE__ */ jsx4(
1009
- "div",
1010
- {
1011
- className: row.title !== void 0 ? "sia-selection-panel__group" : "sia-selection-panel__row",
1012
- style: { position: "absolute", top: row.top, height: row.height, width: "100%", gridTemplateColumns: `repeat(${count}, minmax(0, 1fr))` },
1013
- children: row.title ?? row.items?.map((option, index) => option.optionType === "divider" ? /* @__PURE__ */ jsx4("div", { role: "separator", className: "sia-selection-panel__divider" }, `divider-${index}`) : /* @__PURE__ */ jsx4(Tooltip, { title: option.disabled ? option.disabledTip : void 0, placement: "right", children: /* @__PURE__ */ jsx4(
1014
- "div",
1015
- {
1016
- role: "option",
1017
- id: `${id}-${typeof option.value}-${option.value}`,
1018
- tabIndex: -1,
1019
- "aria-selected": selected.has(option.value),
1020
- "aria-disabled": disabled || option.disabled || void 0,
1021
- className: `sia-selection-panel__option${keyboardActive && active === option.value ? " is-active" : ""}`,
1022
- "data-deselected-hover": deselectedHover === option.value || void 0,
1023
- onPointerLeave: () => {
1024
- if (deselectedHover === option.value) setDeselectedHover(void 0);
1025
- },
1026
- onClick: (event) => {
1027
- if (!event.target.closest(".sia-checkbox")) toggle(option);
1028
- },
1029
- children: multiple ? /* @__PURE__ */ jsx4(Checkbox2, { checked: selected.has(option.value), disabled: disabled || loading || option.disabled, tabIndex: -1, onChange: () => toggle(option), children: /* @__PURE__ */ jsxs4("span", { className: "sia-selection-panel__text", children: [
1030
- /* @__PURE__ */ jsx4("span", { className: "sia-selection-panel__label", children: showValue || displayField === "label" ? option.label : String(option.value) }),
1031
- showValue && /* @__PURE__ */ jsx4("small", { children: String(option.value) })
1032
- ] }) }) : /* @__PURE__ */ jsxs4("span", { className: "sia-selection-panel__text", children: [
1033
- /* @__PURE__ */ jsx4("span", { className: "sia-selection-panel__label", children: showValue || displayField === "label" ? option.label : String(option.value) }),
1034
- showValue && /* @__PURE__ */ jsx4("small", { children: String(option.value) })
1035
- ] })
1036
- }
1037
- ) }, `${typeof option.value}-${option.value}`))
1038
- },
1039
- row.key
1040
- )) })
1041
- }
1042
- )
1043
- ] });
1044
- }
1045
-
1046
855
  // src/components/FloatingScrollbarProvider.tsx
1047
- import { useEffect as useEffect7 } from "react";
856
+ import { useEffect as useEffect6 } from "react";
1048
857
 
1049
858
  // src/components/useScrollbarProximity.ts
1050
- import { useEffect as useEffect6 } from "react";
859
+ import { useEffect as useEffect5 } from "react";
1051
860
  var users = 0;
1052
861
  var cleanup;
1053
862
  function useScrollbarProximity() {
1054
- useEffect6(() => {
863
+ useEffect5(() => {
1055
864
  if (users++ === 0) {
1056
865
  let frame = 0;
1057
866
  let x = -Infinity;
@@ -1172,7 +981,7 @@ function createTrack(axis) {
1172
981
  }
1173
982
  function FloatingScrollbarProvider({ disabled = false, targetRef }) {
1174
983
  useScrollbarProximity();
1175
- useEffect7(() => {
984
+ useEffect6(() => {
1176
985
  if (disabled) return;
1177
986
  const layer = document.createElement("div");
1178
987
  layer.className = "sia-floating-scrollbar-layer";
@@ -1418,8 +1227,200 @@ function FloatingScrollbarProvider({ disabled = false, targetRef }) {
1418
1227
  return null;
1419
1228
  }
1420
1229
 
1230
+ // src/components/SelectionPanel.tsx
1231
+ import { useEffect as useEffect7, useId as useId4, useMemo as useMemo3, useRef as useRef5, useState as useState3 } from "react";
1232
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1233
+ function SelectionPanel({
1234
+ options,
1235
+ value,
1236
+ onChange,
1237
+ multiple = false,
1238
+ allowDeselect = false,
1239
+ disabled = false,
1240
+ loading = false,
1241
+ showSearch = true,
1242
+ showActions = true,
1243
+ includeUnknownValues = true,
1244
+ searchValue,
1245
+ onSearch,
1246
+ selectedOnly = false,
1247
+ showValue = false,
1248
+ displayField = "label",
1249
+ columns = 1,
1250
+ maxHeight = 250,
1251
+ autoFocusSearch = false
1252
+ }) {
1253
+ const [localSearch, setLocalSearch] = useState3("");
1254
+ const search = searchValue ?? localSearch;
1255
+ const [scrollTop, setScrollTop] = useState3(0);
1256
+ const [active, setActive] = useState3();
1257
+ const [keyboardActive, setKeyboardActive] = useState3(false);
1258
+ const [deselectedHover, setDeselectedHover] = useState3();
1259
+ const listRef = useRef5(null);
1260
+ const id = useId4();
1261
+ const selected = useMemo3(() => new Set(value), [value]);
1262
+ const count = Math.max(1, Math.floor(columns));
1263
+ const allOptions = useMemo3(() => {
1264
+ if (!includeUnknownValues) return [...options];
1265
+ const known = new Set(options.filter((option) => option.optionType !== "divider").map((option) => option.value));
1266
+ return [...value.filter((item) => !known.has(item)).map((item) => ({ value: item, label: String(item), group: "\u81EA\u5B9A\u4E49\u503C" })), ...options];
1267
+ }, [options, value, includeUnknownValues]);
1268
+ const filtered = useMemo3(
1269
+ () => allOptions.filter((option) => (!selectedOnly || selected.has(option.value)) && (!search || option.optionType !== "divider" && [option.label, option.value].some((text) => String(text ?? "").toLowerCase().includes(search.toLowerCase())))),
1270
+ [allOptions, selectedOnly, selected, search]
1271
+ );
1272
+ const rows = useMemo3(() => {
1273
+ const groups = /* @__PURE__ */ new Map();
1274
+ filtered.forEach((option) => {
1275
+ const items = groups.get(option.group) ?? [];
1276
+ items.push(option);
1277
+ groups.set(option.group, items);
1278
+ });
1279
+ const rows2 = [];
1280
+ let top = 0;
1281
+ for (const [group, items] of groups) {
1282
+ if (group) {
1283
+ rows2.push({ key: `group-${rows2.length}`, title: group, top, height: 30 });
1284
+ top += 30;
1285
+ }
1286
+ for (let index = 0; index < items.length; index += count) {
1287
+ const height = showValue ? 48 : 34;
1288
+ rows2.push({ key: `row-${rows2.length}`, items: items.slice(index, index + count), top, height });
1289
+ top += height;
1290
+ }
1291
+ }
1292
+ return rows2;
1293
+ }, [filtered, count, showValue]);
1294
+ const totalHeight = rows.length ? rows[rows.length - 1].top + rows[rows.length - 1].height : 0;
1295
+ const virtual = filtered.length > 100;
1296
+ const renderedRows = virtual ? rows.filter((row) => row.top + row.height >= scrollTop - 100 && row.top <= scrollTop + maxHeight + 100) : rows;
1297
+ const enabled = filtered.filter((option) => !option.disabled && option.optionType !== "divider");
1298
+ useEffect7(() => {
1299
+ setScrollTop(0);
1300
+ if (listRef.current) listRef.current.scrollTop = 0;
1301
+ setActive(void 0);
1302
+ }, [search, selectedOnly, count]);
1303
+ function toggle(option, keyboard = false) {
1304
+ if (disabled || loading || option.disabled || option.optionType === "divider") return;
1305
+ setActive(option.value);
1306
+ setKeyboardActive(keyboard);
1307
+ setDeselectedHover(!keyboard && !multiple && allowDeselect && selected.has(option.value) ? option.value : void 0);
1308
+ onChange(multiple ? selected.has(option.value) ? value.filter((item) => item !== option.value) : [...value, option.value] : allowDeselect && selected.has(option.value) ? [] : [option.value]);
1309
+ }
1310
+ function batch(operation) {
1311
+ if (disabled || loading) return;
1312
+ if (operation === "clear") {
1313
+ onChange([]);
1314
+ return;
1315
+ }
1316
+ const editable = new Set(enabled.map((option) => option.value));
1317
+ const retained = value.filter((item) => !editable.has(item));
1318
+ const add = enabled.filter((option) => operation === "all" || !selected.has(option.value)).map((option) => option.value);
1319
+ onChange([...retained, ...add]);
1320
+ }
1321
+ return /* @__PURE__ */ jsxs4("div", { className: "sia-selection-panel", children: [
1322
+ /* @__PURE__ */ jsx4(FloatingScrollbarProvider, { targetRef: listRef }),
1323
+ showSearch && /* @__PURE__ */ jsx4(
1324
+ Input,
1325
+ {
1326
+ "aria-label": "\u641C\u7D22\u9009\u9879",
1327
+ placeholder: "\u641C\u7D22",
1328
+ autoFocus: autoFocusSearch,
1329
+ value: search,
1330
+ allowClear: true,
1331
+ onChange: (event) => {
1332
+ setLocalSearch(event.target.value);
1333
+ onSearch?.(event.target.value);
1334
+ }
1335
+ }
1336
+ ),
1337
+ multiple && showActions && /* @__PURE__ */ jsxs4("div", { className: "sia-selection-panel__actions", children: [
1338
+ /* @__PURE__ */ jsx4(Button, { variant: "link", size: "small", disabled: disabled || loading || !enabled.length, onClick: () => batch("all"), children: "\u5168\u9009" }),
1339
+ /* @__PURE__ */ jsx4(Button, { variant: "link", size: "small", disabled: disabled || loading || !enabled.length, onClick: () => batch("invert"), children: "\u53CD\u9009" }),
1340
+ /* @__PURE__ */ jsx4(Button, { variant: "link", size: "small", disabled: disabled || loading || !value.length, onClick: () => batch("clear"), children: "\u6E05\u7A7A" }),
1341
+ /* @__PURE__ */ jsxs4("span", { children: [
1342
+ "\u5DF2\u9009 ",
1343
+ value.length,
1344
+ " \u9879"
1345
+ ] })
1346
+ ] }),
1347
+ /* @__PURE__ */ jsx4(
1348
+ "div",
1349
+ {
1350
+ ref: listRef,
1351
+ role: "listbox",
1352
+ "aria-label": "\u9009\u9879\u5217\u8868",
1353
+ "aria-multiselectable": multiple || void 0,
1354
+ tabIndex: disabled ? -1 : 0,
1355
+ className: "sia-selection-panel__list",
1356
+ style: { maxHeight },
1357
+ onScroll: (event) => setScrollTop(event.currentTarget.scrollTop),
1358
+ onPointerDown: () => setKeyboardActive(false),
1359
+ onBlur: (event) => {
1360
+ if (!event.currentTarget.contains(event.relatedTarget)) setKeyboardActive(false);
1361
+ },
1362
+ "aria-activedescendant": active !== void 0 ? `${id}-${typeof active}-${active}` : void 0,
1363
+ onKeyDown: (event) => {
1364
+ if (event.target instanceof HTMLInputElement) return;
1365
+ if (disabled || loading || !enabled.length) return;
1366
+ const index = enabled.findIndex((option) => option.value === active);
1367
+ if (["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
1368
+ event.preventDefault();
1369
+ setKeyboardActive(true);
1370
+ setDeselectedHover(void 0);
1371
+ const next = event.key === "Home" ? 0 : event.key === "End" ? enabled.length - 1 : Math.max(0, Math.min(enabled.length - 1, index + (event.key === "ArrowDown" ? 1 : -1)));
1372
+ const option = enabled[next];
1373
+ setActive(option.value);
1374
+ const row = rows.find((row2) => row2.items?.includes(option));
1375
+ if (row && listRef.current) {
1376
+ listRef.current.scrollTop = Math.max(0, row.top - maxHeight / 2);
1377
+ setScrollTop(listRef.current.scrollTop);
1378
+ }
1379
+ } else if ((event.key === "Enter" || event.key === " ") && index >= 0) {
1380
+ event.preventDefault();
1381
+ toggle(enabled[index], true);
1382
+ }
1383
+ },
1384
+ children: loading ? /* @__PURE__ */ jsx4("div", { role: "status", children: "\u52A0\u8F7D\u4E2D\u2026" }) : !rows.length ? /* @__PURE__ */ jsx4("div", { className: "sia-selection-panel__empty", children: "\u6682\u65E0\u5339\u914D\u9009\u9879" }) : /* @__PURE__ */ jsx4("div", { style: { height: totalHeight, position: "relative" }, children: renderedRows.map((row) => /* @__PURE__ */ jsx4(
1385
+ "div",
1386
+ {
1387
+ className: row.title !== void 0 ? "sia-selection-panel__group" : "sia-selection-panel__row",
1388
+ style: { position: "absolute", top: row.top, height: row.height, width: "100%", gridTemplateColumns: `repeat(${count}, minmax(0, 1fr))` },
1389
+ children: row.title ?? row.items?.map((option, index) => option.optionType === "divider" ? /* @__PURE__ */ jsx4("div", { role: "separator", className: "sia-selection-panel__divider" }, `divider-${index}`) : /* @__PURE__ */ jsx4(Tooltip, { title: option.disabled ? option.disabledTip : void 0, placement: "right", children: /* @__PURE__ */ jsx4(
1390
+ "div",
1391
+ {
1392
+ role: "option",
1393
+ id: `${id}-${typeof option.value}-${option.value}`,
1394
+ tabIndex: -1,
1395
+ "aria-selected": selected.has(option.value),
1396
+ "aria-disabled": disabled || option.disabled || void 0,
1397
+ className: `sia-selection-panel__option${keyboardActive && active === option.value ? " is-active" : ""}`,
1398
+ "data-deselected-hover": deselectedHover === option.value || void 0,
1399
+ onPointerLeave: () => {
1400
+ if (deselectedHover === option.value) setDeselectedHover(void 0);
1401
+ },
1402
+ onClick: (event) => {
1403
+ if (!event.target.closest(".sia-checkbox")) toggle(option);
1404
+ },
1405
+ children: multiple ? /* @__PURE__ */ jsx4(Checkbox2, { checked: selected.has(option.value), disabled: disabled || loading || option.disabled, tabIndex: -1, onChange: () => toggle(option), children: /* @__PURE__ */ jsxs4("span", { className: "sia-selection-panel__text", children: [
1406
+ /* @__PURE__ */ jsx4("span", { className: "sia-selection-panel__label", children: showValue || displayField === "label" ? option.label : String(option.value) }),
1407
+ showValue && /* @__PURE__ */ jsx4("small", { children: String(option.value) })
1408
+ ] }) }) : /* @__PURE__ */ jsxs4("span", { className: "sia-selection-panel__text", children: [
1409
+ /* @__PURE__ */ jsx4("span", { className: "sia-selection-panel__label", children: showValue || displayField === "label" ? option.label : String(option.value) }),
1410
+ showValue && /* @__PURE__ */ jsx4("small", { children: String(option.value) })
1411
+ ] })
1412
+ }
1413
+ ) }, `${typeof option.value}-${option.value}`))
1414
+ },
1415
+ row.key
1416
+ )) })
1417
+ }
1418
+ )
1419
+ ] });
1420
+ }
1421
+
1421
1422
  // src/components/Select.tsx
1422
- import { forwardRef as forwardRef3, useDeferredValue, useEffect as useEffect8, useId as useId5, useMemo as useMemo4, useRef as useRef7, useState as useState5 } from "react";
1423
+ import { forwardRef as forwardRef3, useDeferredValue, useEffect as useEffect8, useId as useId5, useLayoutEffect as useLayoutEffect3, useMemo as useMemo4, useRef as useRef7, useState as useState5 } from "react";
1423
1424
 
1424
1425
  // src/components/OverflowTags.tsx
1425
1426
  import { useLayoutEffect as useLayoutEffect2, useRef as useRef6, useState as useState4 } from "react";
@@ -1530,6 +1531,8 @@ var Select = forwardRef3(function Select2({
1530
1531
  const [query, setQuery] = useState5("");
1531
1532
  const [activeIndex, setActiveIndex] = useState5(-1);
1532
1533
  const [scrollTop, setScrollTop] = useState5(0);
1534
+ const [dropdownFontSize, setDropdownFontSize] = useState5();
1535
+ const pendingSelectedScroll = useRef7(false);
1533
1536
  const deferredQuery = useDeferredValue(query.trim());
1534
1537
  const initialValue = defaultValue === void 0 ? mode === "multiple" ? [] : null : defaultValue;
1535
1538
  const [currentValue, setCurrentValue] = useControllableState({
@@ -1587,10 +1590,31 @@ var Select = forwardRef3(function Select2({
1587
1590
  useEffect8(() => {
1588
1591
  if (disabled || loading) closeDropdown();
1589
1592
  }, [disabled, loading]);
1593
+ useEffect8(() => {
1594
+ if (!open || popupMode !== "dropdown" || !pendingSelectedScroll.current || query) return;
1595
+ const index = filteredOptions.findIndex((option) => selectedValueSet.has(option.value));
1596
+ if (index < 0) return;
1597
+ const frame = requestAnimationFrame(() => {
1598
+ const list = listRef.current;
1599
+ if (!list) return;
1600
+ const item = virtualEnabled ? null : list.querySelectorAll('[role="option"]')[index];
1601
+ const top = virtualEnabled ? index * optionHeight : item ? item.getBoundingClientRect().top - list.getBoundingClientRect().top + list.scrollTop : 0;
1602
+ list.scrollTop = Math.max(0, top - (list.clientHeight - (item?.offsetHeight ?? optionHeight)) / 2);
1603
+ setScrollTop(list.scrollTop);
1604
+ pendingSelectedScroll.current = false;
1605
+ });
1606
+ return () => cancelAnimationFrame(frame);
1607
+ }, [open, popupMode, filteredOptions, selectedValueSet, virtualEnabled, optionHeight, query]);
1608
+ useLayoutEffect3(() => {
1609
+ if (!open || popupMode !== "dropdown") return;
1610
+ const trigger = rootRef.current?.querySelector(".sia-select__trigger");
1611
+ if (trigger) setDropdownFontSize(getComputedStyle(trigger).fontSize);
1612
+ }, [open, popupMode, size]);
1590
1613
  function firstEnabledIndex() {
1591
1614
  return filteredOptions.findIndex((option) => !option.disabled);
1592
1615
  }
1593
1616
  function closeDropdown() {
1617
+ pendingSelectedScroll.current = false;
1594
1618
  setOpen(false);
1595
1619
  setQuery("");
1596
1620
  setScrollTop(0);
@@ -1615,6 +1639,7 @@ var Select = forwardRef3(function Select2({
1615
1639
  }
1616
1640
  function openDropdown() {
1617
1641
  if (disabled || loading) return;
1642
+ pendingSelectedScroll.current = true;
1618
1643
  setOpenedMode(automaticMode);
1619
1644
  const selectedIndex = filteredOptions.findIndex((option) => selectedValueSet.has(option.value) && !option.disabled);
1620
1645
  setActiveIndex(selectedIndex >= 0 ? selectedIndex : firstEnabledIndex());
@@ -1789,7 +1814,7 @@ var Select = forwardRef3(function Select2({
1789
1814
  }
1790
1815
  ),
1791
1816
  allowClear && hasValue && !disabled && !loading ? /* @__PURE__ */ jsx6("button", { className: "sia-select__clear", type: "button", "aria-label": "\u6E05\u7A7A\u9009\u62E9", onClick: clearValue, children: /* @__PURE__ */ jsx6(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null,
1792
- /* @__PURE__ */ jsxs6(PopupPortal, { ref: popupRef, anchorRef: rootRef, open: open && popupMode === "dropdown", className: `sia-select__dropdown${filteredOptions.length === 0 && !canSubmitInput ? " sia-select__dropdown--empty" : ""}`, children: [
1817
+ /* @__PURE__ */ jsxs6(PopupPortal, { ref: popupRef, anchorRef: rootRef, open: open && popupMode === "dropdown", style: { fontSize: dropdownFontSize }, className: `sia-select__dropdown${filteredOptions.length === 0 && !canSubmitInput ? " sia-select__dropdown--empty" : ""}`, children: [
1793
1818
  /* @__PURE__ */ jsx6(FloatingScrollbarProvider, { targetRef: listRef }),
1794
1819
  showSearch || allowInput ? /* @__PURE__ */ jsxs6("label", { className: "sia-select__search", children: [
1795
1820
  /* @__PURE__ */ jsx6(Icon, { name: "search", size: 15 }),
@@ -1929,9 +1954,9 @@ export {
1929
1954
  useOverlayLifecycle,
1930
1955
  OverlayPortal,
1931
1956
  Modal2 as Modal,
1932
- SelectionPanel,
1933
- OverflowTags,
1934
1957
  useScrollbarProximity,
1935
1958
  FloatingScrollbarProvider,
1959
+ SelectionPanel,
1960
+ OverflowTags,
1936
1961
  Select
1937
1962
  };
@@ -1,16 +1,17 @@
1
1
  import {
2
+ FloatingScrollbarProvider,
2
3
  Select
3
- } from "./chunk-6R7JY7IY.js";
4
+ } from "./chunk-5MW3NE2V.js";
4
5
  import {
5
6
  Icon
6
- } from "./chunk-LRPQ5FGE.js";
7
+ } from "./chunk-YF2I6SDB.js";
7
8
  import {
8
9
  PopupPortal,
9
10
  useControlSize,
10
11
  useControllableState,
11
12
  useFloatingPlaceholder,
12
13
  withTitleTooltip
13
- } from "./chunk-NSSPGXNM.js";
14
+ } from "./chunk-RAO3JHDL.js";
14
15
 
15
16
  // src/components/DatePicker.tsx
16
17
  import { useEffect, useId, useMemo, useRef as useRef2, useState } from "react";
@@ -161,6 +162,10 @@ function TimePanel({
161
162
  }) {
162
163
  const [hour = "00", minute = "00", second = "00"] = value.split(":");
163
164
  const columnsRef = useRef(null);
165
+ const hourRef = useRef(null);
166
+ const minuteRef = useRef(null);
167
+ const secondRef = useRef(null);
168
+ const columnRefs = [hourRef, minuteRef, secondRef];
164
169
  useLayoutEffect(() => {
165
170
  for (const column of columnsRef.current?.children ?? []) {
166
171
  const selected = column.querySelector('[aria-selected="true"]');
@@ -191,7 +196,7 @@ function TimePanel({
191
196
  showSecond ? `:${second}` : "",
192
197
  use12Hours ? Number(hour) < 12 ? " AM" : " PM" : ""
193
198
  ] }),
194
- /* @__PURE__ */ jsx("div", { ref: columnsRef, className: "sia-date-panel__time-columns", children: columns.map((column) => /* @__PURE__ */ jsx("div", { role: "listbox", "aria-label": `${ariaLabel}${column.label}`, children: Array.from({ length: column.count }, (_, index) => {
199
+ /* @__PURE__ */ jsx("div", { ref: columnsRef, className: "sia-date-panel__time-columns", children: columns.map((column) => /* @__PURE__ */ jsx("div", { ref: columnRefs[column.index], role: "listbox", "aria-label": `${ariaLabel}${column.label}`, children: Array.from({ length: column.count }, (_, index) => {
195
200
  const next = pad(index);
196
201
  const candidate = [hour, minute, second];
197
202
  candidate[column.index] = next;
@@ -203,7 +208,8 @@ function TimePanel({
203
208
  const target = event.key === "Home" ? 0 : event.key === "End" ? buttons.length - 1 : Math.max(0, Math.min(buttons.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)));
204
209
  buttons[target]?.focus();
205
210
  }, onClick: () => update(column.index, next), children: use12Hours && column.index === 0 ? `${pad(index % 12 || 12)} ${index < 12 ? "AM" : "PM"}` : next }, next);
206
- }) }, column.label)) })
211
+ }) }, column.label)) }),
212
+ columns.map((column) => /* @__PURE__ */ jsx(FloatingScrollbarProvider, { targetRef: columnRefs[column.index] }, column.index))
207
213
  ] });
208
214
  }
209
215
  function DatePanelFooter({
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  useControlSize,
3
3
  withTitleTooltip
4
- } from "./chunk-NSSPGXNM.js";
4
+ } from "./chunk-RAO3JHDL.js";
5
5
 
6
6
  // src/components/Button.tsx
7
7
  import { forwardRef, useRef } from "react";
@@ -2,14 +2,14 @@ import {
2
2
  Dropdown,
3
3
  Icon,
4
4
  Input
5
- } from "./chunk-LRPQ5FGE.js";
5
+ } from "./chunk-YF2I6SDB.js";
6
6
  import {
7
7
  Button
8
- } from "./chunk-6WBABNAX.js";
8
+ } from "./chunk-IYNS423D.js";
9
9
  import {
10
10
  useFloatingPlaceholder,
11
11
  withTitleTooltip
12
- } from "./chunk-NSSPGXNM.js";
12
+ } from "./chunk-RAO3JHDL.js";
13
13
 
14
14
  // src/components/RichTextEditor.tsx
15
15
  import { useEffect, useMemo, useRef, useState } from "react";