@fangxinyan/lumina 0.9.0 → 0.9.2

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 (136) hide show
  1. package/dist/Alert.d.cts +1 -1
  2. package/dist/Alert.d.ts +1 -1
  3. package/dist/AppShell.d.cts +1 -1
  4. package/dist/AppShell.d.ts +1 -1
  5. package/dist/AutoComplete.d.cts +1 -1
  6. package/dist/AutoComplete.d.ts +1 -1
  7. package/dist/Avatar.d.cts +1 -1
  8. package/dist/Avatar.d.ts +1 -1
  9. package/dist/Badge.d.cts +1 -1
  10. package/dist/Badge.d.ts +1 -1
  11. package/dist/Button.d.cts +1 -1
  12. package/dist/Button.d.ts +1 -1
  13. package/dist/Calendar.d.cts +1 -1
  14. package/dist/Calendar.d.ts +1 -1
  15. package/dist/Card.d.cts +1 -1
  16. package/dist/Card.d.ts +1 -1
  17. package/dist/Cascader.d.cts +1 -1
  18. package/dist/Cascader.d.ts +1 -1
  19. package/dist/Checkbox.d.cts +1 -1
  20. package/dist/Checkbox.d.ts +1 -1
  21. package/dist/Collapse.d.cts +1 -1
  22. package/dist/Collapse.d.ts +1 -1
  23. package/dist/ColorPicker.d.cts +1 -1
  24. package/dist/ColorPicker.d.ts +1 -1
  25. package/dist/CommandPalette.d.cts +1 -1
  26. package/dist/CommandPalette.d.ts +1 -1
  27. package/dist/ContextMenu.d.cts +1 -1
  28. package/dist/ContextMenu.d.ts +1 -1
  29. package/dist/DatePicker.d.cts +1 -1
  30. package/dist/DatePicker.d.ts +1 -1
  31. package/dist/DateTimePicker.d.cts +1 -1
  32. package/dist/DateTimePicker.d.ts +1 -1
  33. package/dist/Divider.d.cts +1 -1
  34. package/dist/Divider.d.ts +1 -1
  35. package/dist/Drawer.d.cts +1 -1
  36. package/dist/Drawer.d.ts +1 -1
  37. package/dist/Empty.d.cts +1 -1
  38. package/dist/Empty.d.ts +1 -1
  39. package/dist/Form.d.cts +1 -1
  40. package/dist/Form.d.ts +1 -1
  41. package/dist/Icon.d.cts +1 -1
  42. package/dist/Icon.d.ts +1 -1
  43. package/dist/Image.d.cts +1 -1
  44. package/dist/Image.d.ts +1 -1
  45. package/dist/Input.d.cts +1 -1
  46. package/dist/Input.d.ts +1 -1
  47. package/dist/InputNumber.d.cts +1 -1
  48. package/dist/InputNumber.d.ts +1 -1
  49. package/dist/List.d.cts +1 -1
  50. package/dist/List.d.ts +1 -1
  51. package/dist/Message.d.cts +1 -1
  52. package/dist/Message.d.ts +1 -1
  53. package/dist/{Modal-UI2FXNDR.css → Modal-KLLX3Z2M.css} +23 -6
  54. package/dist/Modal.cjs +2 -2
  55. package/dist/Modal.d.cts +1 -1
  56. package/dist/Modal.d.ts +1 -1
  57. package/dist/Modal.js +1 -1
  58. package/dist/Pagination.cjs +3 -3
  59. package/dist/Pagination.d.cts +1 -1
  60. package/dist/Pagination.d.ts +1 -1
  61. package/dist/Pagination.js +2 -2
  62. package/dist/Popover.d.cts +1 -1
  63. package/dist/Popover.d.ts +1 -1
  64. package/dist/Progress.d.cts +1 -1
  65. package/dist/Progress.d.ts +1 -1
  66. package/dist/Radio.d.cts +1 -1
  67. package/dist/Radio.d.ts +1 -1
  68. package/dist/{Select-QPBB73KA.css → Select-Y3X3ZJTC.css} +54 -11
  69. package/dist/Select.cjs +2 -4
  70. package/dist/Select.d.cts +8 -2
  71. package/dist/Select.d.ts +8 -2
  72. package/dist/Select.js +1 -3
  73. package/dist/Skeleton.d.cts +1 -1
  74. package/dist/Skeleton.d.ts +1 -1
  75. package/dist/Slider.d.cts +1 -1
  76. package/dist/Slider.d.ts +1 -1
  77. package/dist/Spin.d.cts +1 -1
  78. package/dist/Spin.d.ts +1 -1
  79. package/dist/Splitter.d.cts +1 -1
  80. package/dist/Splitter.d.ts +1 -1
  81. package/dist/StatusBar.d.cts +1 -1
  82. package/dist/StatusBar.d.ts +1 -1
  83. package/dist/Surface.d.cts +2 -2
  84. package/dist/Surface.d.ts +2 -2
  85. package/dist/Switch.d.cts +1 -1
  86. package/dist/Switch.d.ts +1 -1
  87. package/dist/Table.cjs +4 -4
  88. package/dist/Table.d.cts +1 -1
  89. package/dist/Table.d.ts +1 -1
  90. package/dist/Table.js +3 -3
  91. package/dist/TablePro.cjs +5 -5
  92. package/dist/TablePro.d.cts +1 -1
  93. package/dist/TablePro.d.ts +1 -1
  94. package/dist/TablePro.js +4 -4
  95. package/dist/Tabs.d.cts +1 -1
  96. package/dist/Tabs.d.ts +1 -1
  97. package/dist/Tag.d.cts +1 -1
  98. package/dist/Tag.d.ts +1 -1
  99. package/dist/Textarea.d.cts +1 -1
  100. package/dist/Textarea.d.ts +1 -1
  101. package/dist/{Theme-uQq2B0Yk.d.cts → Theme-BJa0Nb3w.d.cts} +1 -1
  102. package/dist/{Theme-CLedeJ_C.d.ts → Theme-DTtq_WWg.d.ts} +1 -1
  103. package/dist/Theme.d.cts +4 -4
  104. package/dist/Theme.d.ts +4 -4
  105. package/dist/ThemePanel.d.cts +2 -2
  106. package/dist/ThemePanel.d.ts +2 -2
  107. package/dist/TimePicker.d.cts +1 -1
  108. package/dist/TimePicker.d.ts +1 -1
  109. package/dist/Timeline.d.cts +1 -1
  110. package/dist/Timeline.d.ts +1 -1
  111. package/dist/Tooltip.d.cts +1 -1
  112. package/dist/Tooltip.d.ts +1 -1
  113. package/dist/Typography.d.cts +1 -1
  114. package/dist/Typography.d.ts +1 -1
  115. package/dist/{chunk-K3KHQ77L.cjs → chunk-CDT2QCBL.cjs} +177 -85
  116. package/dist/{chunk-HMN65CDW.cjs → chunk-IDEE7PP5.cjs} +2 -2
  117. package/dist/{chunk-UCE53RYR.js → chunk-LZXJN3XA.js} +1 -1
  118. package/dist/{chunk-7KA5D37Z.cjs → chunk-MJYMPK5K.cjs} +2 -2
  119. package/dist/{chunk-AL2PYVVP.js → chunk-MSWWABXP.js} +177 -85
  120. package/dist/{chunk-VTN6YLRJ.cjs → chunk-QZ2AAQBX.cjs} +2 -2
  121. package/dist/{chunk-GMFOY7RD.js → chunk-RJCPXAZ3.js} +10 -4
  122. package/dist/{chunk-JMYUO7V7.js → chunk-RM6JIM6O.js} +1 -1
  123. package/dist/{chunk-I2YL5XE4.cjs → chunk-SOAGRYM3.cjs} +10 -4
  124. package/dist/{chunk-2NECDEAJ.js → chunk-U3T6RC6U.js} +1 -1
  125. package/dist/{componentThemeTypes-Jt4B5aU8.d.ts → componentThemeTypes-C7lS3Hi8.d.cts} +6 -2
  126. package/dist/{componentThemeTypes-Jt4B5aU8.d.cts → componentThemeTypes-C7lS3Hi8.d.ts} +6 -2
  127. package/dist/index.cjs +11 -11
  128. package/dist/index.d.cts +3 -3
  129. package/dist/index.d.ts +3 -3
  130. package/dist/index.js +6 -6
  131. package/dist/styles.css +77 -16
  132. package/docs/llms/modal.md +24 -2
  133. package/docs/llms/select.md +40 -1
  134. package/docs/llms/theme.md +1 -1
  135. package/docs/llms.md +1 -1
  136. package/package.json +1 -1
@@ -1,13 +1,12 @@
1
1
  import { Tag } from './chunk-OGMI3TO5.js';
2
2
  import { useFloating } from './chunk-3QXP2ZNP.js';
3
- import { Input } from './chunk-TUXF2G2O.js';
4
3
  import { useOverlayLayer } from './chunk-2A4GYSN4.js';
5
4
  import { Icon, renderIconSlot } from './chunk-2BM65ITV.js';
6
5
  import { withComponentTheme, useComponentPortalTheme, InternalComponentThemePart } from './chunk-5HLNFDV4.js';
7
6
  import { usePortalContainer } from './chunk-CPVUDSIY.js';
8
7
  import './tokens-223RYVVS.css';
9
8
  import './shared-NJHRNLRH.css';
10
- import './Select-QPBB73KA.css';
9
+ import './Select-Y3X3ZJTC.css';
11
10
  import * as React from 'react';
12
11
  import { createPortal } from 'react-dom';
13
12
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -29,6 +28,10 @@ var defaultFilter = (input, opt, optionFilterProp) => {
29
28
  const txt = propValue != null ? String(propValue) : opt.text ?? (typeof opt.label === "string" ? opt.label : String(opt.value));
30
29
  return txt.toLowerCase().includes(q);
31
30
  };
31
+ var getSearchInputDisplayWidth = (value) => Array.from(value).reduce(
32
+ (width, character) => width + ((character.codePointAt(0) ?? 0) > 255 ? 2 : 1),
33
+ 0
34
+ );
32
35
  var getOptionAriaLabel = (option) => {
33
36
  if (option.ariaLabel) return option.ariaLabel;
34
37
  if (typeof option.label === "string" || typeof option.label === "number") {
@@ -47,6 +50,9 @@ var SelectInner = (props, forwardedRef) => {
47
50
  allowClear,
48
51
  searchable,
49
52
  showSearch,
53
+ searchValue: searchValueProp,
54
+ defaultSearchValue,
55
+ onSearch,
50
56
  filterOption,
51
57
  optionFilterProp,
52
58
  loading,
@@ -95,7 +101,7 @@ var SelectInner = (props, forwardedRef) => {
95
101
  isMulti && Array.isArray(props.defaultValue) ? props.defaultValue : []
96
102
  );
97
103
  const [innerOpen, setInnerOpen] = React.useState(defaultOpen ?? false);
98
- const [query, setQuery] = React.useState("");
104
+ const [innerSearchValue, setInnerSearchValue] = React.useState(defaultSearchValue ?? "");
99
105
  const [activeIdx, setActiveIdx] = React.useState(-1);
100
106
  const searchRef = React.useRef(null);
101
107
  const portalContainer = usePortalContainer();
@@ -114,12 +120,29 @@ var SelectInner = (props, forwardedRef) => {
114
120
  const openControlled = openProp !== void 0;
115
121
  const requestedOpen = openControlled ? openProp : innerOpen;
116
122
  const open = !disabled && requestedOpen;
117
- const setOpen = (v) => {
118
- if (disabled && v) return;
119
- if (!openControlled) setInnerOpen(v);
120
- onOpenChange?.(v);
121
- if (!v) setQuery("");
122
- };
123
+ const requestedOpenRef = React.useRef(requestedOpen);
124
+ requestedOpenRef.current = requestedOpen;
125
+ const searchControlled = searchValueProp !== void 0;
126
+ const searchValue = searchControlled ? searchValueProp : innerSearchValue;
127
+ const hasInlineSearch = mergedSearchable;
128
+ const showsInlineSearchInput = hasInlineSearch && (isMulti || open);
129
+ const updateSearchValue = React.useCallback((nextValue) => {
130
+ if (!searchControlled) setInnerSearchValue(nextValue);
131
+ onSearch?.(nextValue);
132
+ }, [onSearch, searchControlled]);
133
+ const resetSearchValue = React.useCallback(() => {
134
+ if (!searchValue) return;
135
+ if (!searchControlled) setInnerSearchValue("");
136
+ onSearch?.("");
137
+ }, [onSearch, searchControlled, searchValue]);
138
+ const setOpen = React.useCallback((nextOpen) => {
139
+ if (disabled && nextOpen) return;
140
+ if (nextOpen === requestedOpenRef.current) return;
141
+ requestedOpenRef.current = nextOpen;
142
+ if (!openControlled) setInnerOpen(nextOpen);
143
+ onOpenChange?.(nextOpen);
144
+ if (!nextOpen) resetSearchValue();
145
+ }, [disabled, onOpenChange, openControlled, resetSearchValue]);
123
146
  React.useEffect(() => {
124
147
  if (!disabled || openControlled || !innerOpen) return;
125
148
  setInnerOpen(false);
@@ -130,7 +153,7 @@ var SelectInner = (props, forwardedRef) => {
130
153
  placement: "bottom",
131
154
  matchTriggerWidth: !hasCustomPopupWidth,
132
155
  panelWidth: typeof resolvedPopupWidth === "number" ? resolvedPopupWidth : 360,
133
- panelHeight: mergedListHeight + (mergedSearchable ? 58 : 12)
156
+ panelHeight: mergedListHeight + 12
134
157
  });
135
158
  useOverlayLayer({
136
159
  open: open && portalContainer != null,
@@ -172,7 +195,7 @@ var SelectInner = (props, forwardedRef) => {
172
195
  };
173
196
  document.addEventListener("mousedown", h);
174
197
  return () => document.removeEventListener("mousedown", h);
175
- }, [open]);
198
+ }, [menuRef, open, setOpen, triggerRef]);
176
199
  React.useEffect(() => {
177
200
  if (open && mergedSearchable) {
178
201
  requestAnimationFrame(() => searchRef.current?.focus());
@@ -184,14 +207,32 @@ var SelectInner = (props, forwardedRef) => {
184
207
  [options]
185
208
  );
186
209
  const allFlat = React.useMemo(() => flatten(orderedItems), [orderedItems]);
210
+ const optionByValue = React.useMemo(() => {
211
+ const index = /* @__PURE__ */ new Map();
212
+ allFlat.forEach((option) => index.set(option.value, option));
213
+ return index;
214
+ }, [allFlat]);
215
+ const selectedOptionCacheRef = React.useRef(/* @__PURE__ */ new Map());
216
+ React.useEffect(() => {
217
+ selectedValues.forEach((selectedValue) => {
218
+ const option = optionByValue.get(selectedValue);
219
+ if (option) selectedOptionCacheRef.current.set(selectedValue, option);
220
+ });
221
+ }, [optionByValue, selectedValues]);
222
+ const selectedOptions = React.useMemo(
223
+ () => selectedValues.map(
224
+ (selectedValue) => optionByValue.get(selectedValue) ?? selectedOptionCacheRef.current.get(selectedValue)
225
+ ).filter((option) => option !== void 0),
226
+ [optionByValue, selectedValues]
227
+ );
187
228
  const filteredFlat = React.useMemo(() => {
188
- if (!query.trim()) return allFlat;
229
+ if (!searchValue.trim()) return allFlat;
189
230
  if (filterOption === false) return allFlat;
190
231
  const f = typeof filterOption === "function" ? filterOption : (input, option) => defaultFilter(input, option, optionFilterProp);
191
- return allFlat.filter((o) => f(query, o));
192
- }, [allFlat, query, filterOption, optionFilterProp]);
232
+ return allFlat.filter((o) => f(searchValue, o));
233
+ }, [allFlat, filterOption, optionFilterProp, searchValue]);
193
234
  const filteredItems = React.useMemo(() => {
194
- if (!query.trim()) {
235
+ if (!searchValue.trim()) {
195
236
  return orderedItems.filter((item) => !isGroup(item) || item.options.length > 0);
196
237
  }
197
238
  return orderedItems.map((it) => {
@@ -201,7 +242,7 @@ var SelectInner = (props, forwardedRef) => {
201
242
  const kept = it.options.filter((o) => filteredFlat.includes(o));
202
243
  return kept.length ? { ...it, options: kept } : null;
203
244
  }).filter((x) => x !== null);
204
- }, [orderedItems, filteredFlat, query]);
245
+ }, [orderedItems, filteredFlat, searchValue]);
205
246
  React.useEffect(() => {
206
247
  setActiveIdx((current) => {
207
248
  if (current >= 0 && current < filteredFlat.length && !isOptionDisabled(filteredFlat[current])) {
@@ -212,6 +253,7 @@ var SelectInner = (props, forwardedRef) => {
212
253
  }, [filteredFlat, isOptionDisabled]);
213
254
  const pickSingle = (opt) => {
214
255
  if (disabled || isOptionDisabled(opt)) return;
256
+ selectedOptionCacheRef.current.set(opt.value, opt);
215
257
  if (!singleControlled) setInnerSingle(opt.value);
216
258
  props.onChange?.(opt.value);
217
259
  setOpen(false);
@@ -220,8 +262,17 @@ var SelectInner = (props, forwardedRef) => {
220
262
  if (disabled || isOptionDisabled(opt)) return;
221
263
  const cur = multiValue ?? [];
222
264
  const next = cur.includes(opt.value) ? cur.filter((v) => v !== opt.value) : [...cur, opt.value];
265
+ selectedOptionCacheRef.current.set(opt.value, opt);
266
+ if (!multiControlled) setInnerMulti(next);
267
+ props.onChange?.(next);
268
+ if (hasInlineSearch) requestAnimationFrame(() => searchRef.current?.focus());
269
+ };
270
+ const removeMultiValue = (removedValue) => {
271
+ if (disabled) return;
272
+ const next = (multiValue ?? []).filter((value) => value !== removedValue);
223
273
  if (!multiControlled) setInnerMulti(next);
224
274
  props.onChange?.(next);
275
+ if (hasInlineSearch) requestAnimationFrame(() => searchRef.current?.focus());
225
276
  };
226
277
  const clearAll = () => {
227
278
  if (disabled) return;
@@ -237,13 +288,20 @@ var SelectInner = (props, forwardedRef) => {
237
288
  };
238
289
  const isSelected = (val) => isMulti ? (multiValue ?? []).includes(val) : singleValue === val;
239
290
  const onKeyDown = (e) => {
240
- if ((e.key === "Backspace" || e.key === "Delete") && showClear) {
291
+ const fromSearchInput = e.target === searchRef.current;
292
+ if (e.nativeEvent.isComposing || e.keyCode === 229) return;
293
+ if (fromSearchInput && e.key === "Backspace" && !searchValue && isMulti && multiValue.length > 0) {
294
+ e.preventDefault();
295
+ removeMultiValue(multiValue[multiValue.length - 1]);
296
+ return;
297
+ }
298
+ if (!fromSearchInput && (e.key === "Backspace" || e.key === "Delete") && showClear) {
241
299
  e.preventDefault();
242
300
  clearAll();
243
301
  return;
244
302
  }
245
303
  if (!open) {
246
- if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
304
+ if (e.key === "Enter" || !fromSearchInput && e.key === " " || e.key === "ArrowDown") {
247
305
  e.preventDefault();
248
306
  setOpen(true);
249
307
  }
@@ -286,13 +344,47 @@ var SelectInner = (props, forwardedRef) => {
286
344
  return;
287
345
  }
288
346
  };
347
+ const renderInlineSearchInput = () => {
348
+ if (!showsInlineSearchInput) return null;
349
+ const multiHasSelection = isMulti && multiValue.length > 0;
350
+ const searchDisplayWidth = getSearchInputDisplayWidth(searchValue);
351
+ return /* @__PURE__ */ jsx(
352
+ "input",
353
+ {
354
+ ref: searchRef,
355
+ id: fieldId,
356
+ className: `select-search-input ${multiHasSelection ? "with-selection" : "empty"}`,
357
+ type: "search",
358
+ value: searchValue,
359
+ style: multiHasSelection ? { width: `${Math.min(Math.max(searchDisplayWidth + 1, 2), 32)}ch` } : void 0,
360
+ placeholder: isMulti ? multiValue.length === 0 ? placeholder : void 0 : "\u641C\u7D22...",
361
+ disabled,
362
+ autoComplete: "off",
363
+ role: "combobox",
364
+ "aria-autocomplete": "list",
365
+ "aria-label": ariaLabel,
366
+ "aria-labelledby": ariaLabelledBy,
367
+ "aria-invalid": ariaInvalid,
368
+ "aria-required": ariaRequired,
369
+ "aria-describedby": ariaDescribedBy,
370
+ "aria-haspopup": "listbox",
371
+ "aria-expanded": open,
372
+ "aria-controls": open ? listboxId : void 0,
373
+ "aria-activedescendant": open && activeIdx >= 0 ? `${listboxId}-option-${activeIdx}` : void 0,
374
+ onChange: (event) => {
375
+ updateSearchValue(event.target.value);
376
+ if (!open) setOpen(true);
377
+ }
378
+ }
379
+ );
380
+ };
289
381
  const renderTrigger = () => {
290
382
  if (isMulti) {
291
- const selected = (multiValue ?? []).map((v) => allFlat.find((o) => o.value === v)).filter((o) => !!o);
383
+ const selected = selectedOptions;
292
384
  const max = maxTagCount;
293
385
  const shown = max != null ? selected.slice(0, max) : selected;
294
386
  const overflow = selected.length - shown.length;
295
- if (selected.length === 0) {
387
+ if (selected.length === 0 && !hasInlineSearch) {
296
388
  return /* @__PURE__ */ jsx("span", { className: "placeholder", children: placeholder });
297
389
  }
298
390
  return /* @__PURE__ */ jsx(InternalComponentThemePart, { components: "Tag", children: /* @__PURE__ */ jsxs("span", { className: "select-tags", children: [
@@ -301,24 +393,25 @@ var SelectInner = (props, forwardedRef) => {
301
393
  {
302
394
  tone: "accent",
303
395
  removable: !disabled,
304
- onRemove: () => {
305
- const cur = multiValue ?? [];
306
- const next = cur.filter((v) => v !== o.value);
307
- if (!multiControlled) setInnerMulti(next);
308
- props.onChange?.(next);
396
+ onRemove: () => removeMultiValue(o.value),
397
+ onMouseDown: (event) => {
398
+ event.preventDefault();
399
+ event.stopPropagation();
309
400
  },
310
401
  onClick: (e) => e.stopPropagation(),
311
- children: selectedRender?.(o, { value: o.value, multiple: true }) ?? o.label
402
+ children: /* @__PURE__ */ jsx("span", { className: "select-tag-label", children: selectedRender?.(o, { value: o.value, multiple: true }) ?? o.label })
312
403
  },
313
404
  String(o.value)
314
405
  )),
315
- overflow > 0 && /* @__PURE__ */ jsxs(Tag, { tone: "neutral", children: [
406
+ overflow > 0 && /* @__PURE__ */ jsxs(Tag, { className: "select-tag-overflow", tone: "neutral", children: [
316
407
  "+",
317
408
  overflow
318
- ] })
409
+ ] }),
410
+ renderInlineSearchInput()
319
411
  ] }) });
320
412
  }
321
- const current = allFlat.find((o) => o.value === singleValue);
413
+ if (showsInlineSearchInput) return renderInlineSearchInput();
414
+ const current = selectedOptions[0];
322
415
  if (!current) return /* @__PURE__ */ jsx("span", { className: "placeholder", children: placeholder });
323
416
  if (selectedRender) {
324
417
  return /* @__PURE__ */ jsx("span", { className: "select-value select-value-custom", children: selectedRender(current, { value: current.value, multiple: false }) });
@@ -365,6 +458,9 @@ var SelectInner = (props, forwardedRef) => {
365
458
  "aria-label": getOptionAriaLabel(o),
366
459
  disabled: optionDisabled,
367
460
  className: `menu-item ${sel ? "active" : ""} ${active ? "highlight" : ""}`,
461
+ onMouseDown: (event) => {
462
+ if (hasInlineSearch) event.preventDefault();
463
+ },
368
464
  onClick: () => isMulti ? toggleMulti(o) : pickSingle(o),
369
465
  children: [
370
466
  isMulti && /* @__PURE__ */ jsx("span", { className: `menu-check ${sel ? "on" : ""}`, "aria-hidden": true, children: sel && /* @__PURE__ */ jsx(Icon, { name: "check", size: 11, stroke: 3 }) }),
@@ -391,15 +487,32 @@ var SelectInner = (props, forwardedRef) => {
391
487
  item.options.map((option) => renderOption(option, !!item.pinned))
392
488
  ] }, `g-${groupIndex}-${item.pinned ? "pinned" : "regular"}`) : renderOption(item)
393
489
  );
490
+ const handleTriggerClick = (event) => {
491
+ if (disabled) return;
492
+ if (!hasInlineSearch) {
493
+ setOpen(!open);
494
+ return;
495
+ }
496
+ const target = event.target;
497
+ if (target.closest(".select-caret")) {
498
+ setOpen(!open);
499
+ return;
500
+ }
501
+ setOpen(true);
502
+ searchRef.current?.focus();
503
+ };
394
504
  return /* @__PURE__ */ jsxs(
395
505
  "div",
396
506
  {
397
507
  ref: setTriggerRef,
398
508
  ...rest,
399
- className: `select ${size} ${isMulti ? "multi" : ""} ${open ? "open" : ""} ${disabled ? "disabled" : ""} ${invalid ? "invalid" : ""} ${className}`,
509
+ className: `select ${size} ${isMulti ? "multi" : ""} ${hasInlineSearch ? "searchable" : ""} ${open ? "open" : ""} ${disabled ? "disabled" : ""} ${invalid ? "invalid" : ""} ${className}`,
400
510
  onKeyDown: (e) => {
401
511
  onRootKeyDown?.(e);
402
- if (!e.defaultPrevented && e.target.classList.contains("select-trigger")) onKeyDown(e);
512
+ const target = e.target;
513
+ if (!e.defaultPrevented && (target.classList.contains("select-trigger") || target === searchRef.current)) {
514
+ onKeyDown(e);
515
+ }
403
516
  },
404
517
  onBlur: (event) => {
405
518
  onRootBlur?.(event);
@@ -424,20 +537,20 @@ var SelectInner = (props, forwardedRef) => {
424
537
  "div",
425
538
  {
426
539
  className: "select-trigger",
427
- onClick: () => !disabled && setOpen(!open),
428
- tabIndex: disabled ? -1 : triggerTabIndex ?? 0,
429
- id: fieldId,
430
- role: "combobox",
431
- "aria-disabled": disabled || void 0,
432
- "aria-label": ariaLabel,
433
- "aria-labelledby": ariaLabelledBy,
434
- "aria-invalid": ariaInvalid,
435
- "aria-required": ariaRequired,
436
- "aria-describedby": ariaDescribedBy,
437
- "aria-haspopup": "listbox",
438
- "aria-expanded": open,
439
- "aria-controls": open ? listboxId : void 0,
440
- "aria-activedescendant": open && activeIdx >= 0 ? `${listboxId}-option-${activeIdx}` : void 0,
540
+ onClick: handleTriggerClick,
541
+ tabIndex: showsInlineSearchInput || disabled ? -1 : triggerTabIndex ?? 0,
542
+ id: showsInlineSearchInput ? void 0 : fieldId,
543
+ role: showsInlineSearchInput ? void 0 : "combobox",
544
+ "aria-disabled": showsInlineSearchInput ? void 0 : disabled || void 0,
545
+ "aria-label": showsInlineSearchInput ? void 0 : ariaLabel,
546
+ "aria-labelledby": showsInlineSearchInput ? void 0 : ariaLabelledBy,
547
+ "aria-invalid": showsInlineSearchInput ? void 0 : ariaInvalid,
548
+ "aria-required": showsInlineSearchInput ? void 0 : ariaRequired,
549
+ "aria-describedby": showsInlineSearchInput ? void 0 : ariaDescribedBy,
550
+ "aria-haspopup": showsInlineSearchInput ? void 0 : "listbox",
551
+ "aria-expanded": showsInlineSearchInput ? void 0 : open,
552
+ "aria-controls": showsInlineSearchInput ? void 0 : open ? listboxId : void 0,
553
+ "aria-activedescendant": showsInlineSearchInput ? void 0 : open && activeIdx >= 0 ? `${listboxId}-option-${activeIdx}` : void 0,
441
554
  children: [
442
555
  renderTrigger(),
443
556
  /* @__PURE__ */ jsx(Icon, { name: "chevDown", size: 14, className: "select-caret" })
@@ -451,7 +564,10 @@ var SelectInner = (props, forwardedRef) => {
451
564
  className: "select-clear",
452
565
  "aria-label": "Clear",
453
566
  onPointerDown: (event) => event.stopPropagation(),
454
- onMouseDown: (event) => event.stopPropagation(),
567
+ onMouseDown: (event) => {
568
+ if (hasInlineSearch) event.preventDefault();
569
+ event.stopPropagation();
570
+ },
455
571
  onClick: (event) => {
456
572
  event.stopPropagation();
457
573
  clearAll();
@@ -460,7 +576,7 @@ var SelectInner = (props, forwardedRef) => {
460
576
  }
461
577
  ),
462
578
  open && portalContainer && createPortal(
463
- /* @__PURE__ */ jsxs(
579
+ /* @__PURE__ */ jsx(
464
580
  "div",
465
581
  {
466
582
  ref: menuRef,
@@ -475,44 +591,20 @@ var SelectInner = (props, forwardedRef) => {
475
591
  ...portalTheme.styles.popup,
476
592
  ...popupStyle
477
593
  },
478
- children: [
479
- mergedSearchable && /* @__PURE__ */ jsx("div", { className: "menu-search", children: /* @__PURE__ */ jsx(InternalComponentThemePart, { components: "Input", children: /* @__PURE__ */ jsx(
480
- Input,
481
- {
482
- ref: searchRef,
483
- size: "sm",
484
- leadingIcon: "search",
485
- value: query,
486
- placeholder: "\u641C\u7D22...",
487
- role: "combobox",
488
- "aria-autocomplete": "list",
489
- "aria-expanded": open,
490
- "aria-controls": listboxId,
491
- "aria-activedescendant": activeIdx >= 0 ? `${listboxId}-option-${activeIdx}` : void 0,
492
- onValueChange: setQuery,
493
- onKeyDown: (e) => {
494
- if (e.key === "Escape" || e.key === "ArrowDown" || e.key === "ArrowUp" || e.key === "Enter") {
495
- e.preventDefault();
496
- onKeyDown(e);
497
- }
498
- }
499
- }
500
- ) }) }),
501
- /* @__PURE__ */ jsx(
502
- "div",
503
- {
504
- className: "menu-options",
505
- style: { maxHeight: mergedListHeight },
506
- children: loading ? /* @__PURE__ */ jsxs("div", { className: "menu-state", children: [
507
- /* @__PURE__ */ jsx("span", { className: "menu-state-ico", children: /* @__PURE__ */ jsx("span", { className: "spinner" }) }),
508
- /* @__PURE__ */ jsx("span", { children: "\u52A0\u8F7D\u4E2D..." })
509
- ] }) : filteredFlat.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "menu-state", children: [
510
- /* @__PURE__ */ jsx("span", { className: "menu-state-ico", children: /* @__PURE__ */ jsx(Icon, { name: "search", size: 16 }) }),
511
- /* @__PURE__ */ jsx("span", { children: emptyContent ?? "\u6682\u65E0\u5339\u914D\u9879" })
512
- ] }) : renderMenuItems(filteredItems)
513
- }
514
- )
515
- ]
594
+ children: /* @__PURE__ */ jsx(
595
+ "div",
596
+ {
597
+ className: "menu-options",
598
+ style: { maxHeight: mergedListHeight },
599
+ children: loading ? /* @__PURE__ */ jsxs("div", { className: "menu-state", children: [
600
+ /* @__PURE__ */ jsx("span", { className: "menu-state-ico", children: /* @__PURE__ */ jsx("span", { className: "spinner" }) }),
601
+ /* @__PURE__ */ jsx("span", { children: "\u52A0\u8F7D\u4E2D..." })
602
+ ] }) : filteredFlat.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "menu-state", children: [
603
+ /* @__PURE__ */ jsx("span", { className: "menu-state-ico", children: /* @__PURE__ */ jsx(Icon, { name: "search", size: 16 }) }),
604
+ /* @__PURE__ */ jsx("span", { children: emptyContent ?? "\u6682\u65E0\u5339\u914D\u9879" })
605
+ ] }) : renderMenuItems(filteredItems)
606
+ }
607
+ )
516
608
  }
517
609
  ),
518
610
  portalContainer
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkK3KHQ77L_cjs = require('./chunk-K3KHQ77L.cjs');
3
+ var chunkCDT2QCBL_cjs = require('./chunk-CDT2QCBL.cjs');
4
4
  var chunkGFGMGJ5A_cjs = require('./chunk-GFGMGJ5A.cjs');
5
5
  var chunkVDVKY2IX_cjs = require('./chunk-VDVKY2IX.cjs');
6
6
  var chunkV6BLBIY6_cjs = require('./chunk-V6BLBIY6.cjs');
@@ -137,7 +137,7 @@ var PaginationBase = React__namespace.forwardRef(({
137
137
  }
138
138
  ),
139
139
  showSizeChanger && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pg-size-changer", children: /* @__PURE__ */ jsxRuntime.jsx(
140
- chunkK3KHQ77L_cjs.Select,
140
+ chunkCDT2QCBL_cjs.Select,
141
141
  {
142
142
  value: normalizedPageSize,
143
143
  size: "sm",
@@ -5,7 +5,7 @@ import { useComponentPortalTheme, InternalComponentThemePart, withComponentTheme
5
5
  import { usePortalContainer } from './chunk-CPVUDSIY.js';
6
6
  import './tokens-223RYVVS.css';
7
7
  import './shared-NJHRNLRH.css';
8
- import './Modal-UI2FXNDR.css';
8
+ import './Modal-KLLX3Z2M.css';
9
9
  import * as React from 'react';
10
10
  import ReactDOM from 'react-dom';
11
11
  import { createRoot } from 'react-dom/client';
@@ -118,6 +118,7 @@ var ModalBase = React.forwardRef((props, ref) => {
118
118
  )
119
119
  ] });
120
120
  const modalBodyStyle = bodyOverflow == null ? { ...portalTheme.styles.body, ...bodyStyle } : { ...portalTheme.styles.body, overflow: bodyOverflow, ...bodyStyle };
121
+ const usesDefaultBodyOverflow = bodyOverflow == null && bodyStyle?.overflow == null && portalTheme.styles.body?.overflow == null;
121
122
  return ReactDOM.createPortal(
122
123
  /* @__PURE__ */ jsx(OverlayZIndexProvider, { zIndex: overlayZIndex, children: /* @__PURE__ */ jsx(
123
124
  "div",
@@ -145,7 +146,7 @@ var ModalBase = React.forwardRef((props, ref) => {
145
146
  ...portalTheme.dataAttributes,
146
147
  ...rest,
147
148
  children: [
148
- (title || description || closable) && /* @__PURE__ */ jsxs("div", { className: "modal-head", children: [
149
+ (title || description || closable) && /* @__PURE__ */ jsxs("div", { className: "modal-head", style: portalTheme.styles.header, children: [
149
150
  /* @__PURE__ */ jsxs("div", { className: "modal-titles", children: [
150
151
  title && /* @__PURE__ */ jsx("div", { id: titleId, className: "modal-title", children: title }),
151
152
  description && /* @__PURE__ */ jsx("div", { id: descriptionId, className: "modal-desc", children: description })
@@ -165,12 +166,17 @@ var ModalBase = React.forwardRef((props, ref) => {
165
166
  "div",
166
167
  {
167
168
  ...bodyProps,
168
- className: ["modal-body", `inset-${bodyInset}`, bodyClassName].filter(Boolean).join(" "),
169
+ className: [
170
+ "modal-body",
171
+ `inset-${bodyInset}`,
172
+ usesDefaultBodyOverflow ? "default-overflow" : "",
173
+ bodyClassName
174
+ ].filter(Boolean).join(" "),
169
175
  style: modalBodyStyle,
170
176
  children
171
177
  }
172
178
  ),
173
- footer === null ? null : /* @__PURE__ */ jsx("div", { className: "modal-foot", children: footer ?? defaultFooter })
179
+ footer === null ? null : /* @__PURE__ */ jsx("div", { className: "modal-foot", style: portalTheme.styles.footer, children: footer ?? defaultFooter })
174
180
  ]
175
181
  }
176
182
  )
@@ -1,4 +1,4 @@
1
- import { Pagination } from './chunk-UCE53RYR.js';
1
+ import { Pagination } from './chunk-LZXJN3XA.js';
2
2
  import { Checkbox } from './chunk-QSLXUNLM.js';
3
3
  import { useFloating } from './chunk-3QXP2ZNP.js';
4
4
  import { useOverlayLayer } from './chunk-2A4GYSN4.js';
@@ -7,7 +7,7 @@ var chunkV6BLBIY6_cjs = require('./chunk-V6BLBIY6.cjs');
7
7
  var chunkI4GJZLJU_cjs = require('./chunk-I4GJZLJU.cjs');
8
8
  require('./tokens-223RYVVS.css');
9
9
  require('./shared-NJHRNLRH.css');
10
- require('./Modal-UI2FXNDR.css');
10
+ require('./Modal-KLLX3Z2M.css');
11
11
  var React = require('react');
12
12
  var ReactDOM = require('react-dom');
13
13
  var client = require('react-dom/client');
@@ -143,6 +143,7 @@ var ModalBase = React__namespace.forwardRef((props, ref) => {
143
143
  )
144
144
  ] });
145
145
  const modalBodyStyle = bodyOverflow == null ? { ...portalTheme.styles.body, ...bodyStyle } : { ...portalTheme.styles.body, overflow: bodyOverflow, ...bodyStyle };
146
+ const usesDefaultBodyOverflow = bodyOverflow == null && bodyStyle?.overflow == null && portalTheme.styles.body?.overflow == null;
146
147
  return ReactDOM__default.default.createPortal(
147
148
  /* @__PURE__ */ jsxRuntime.jsx(chunkHSDMJUB6_cjs.OverlayZIndexProvider, { zIndex: overlayZIndex, children: /* @__PURE__ */ jsxRuntime.jsx(
148
149
  "div",
@@ -170,7 +171,7 @@ var ModalBase = React__namespace.forwardRef((props, ref) => {
170
171
  ...portalTheme.dataAttributes,
171
172
  ...rest,
172
173
  children: [
173
- (title || description || closable) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "modal-head", children: [
174
+ (title || description || closable) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "modal-head", style: portalTheme.styles.header, children: [
174
175
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "modal-titles", children: [
175
176
  title && /* @__PURE__ */ jsxRuntime.jsx("div", { id: titleId, className: "modal-title", children: title }),
176
177
  description && /* @__PURE__ */ jsxRuntime.jsx("div", { id: descriptionId, className: "modal-desc", children: description })
@@ -190,12 +191,17 @@ var ModalBase = React__namespace.forwardRef((props, ref) => {
190
191
  "div",
191
192
  {
192
193
  ...bodyProps,
193
- className: ["modal-body", `inset-${bodyInset}`, bodyClassName].filter(Boolean).join(" "),
194
+ className: [
195
+ "modal-body",
196
+ `inset-${bodyInset}`,
197
+ usesDefaultBodyOverflow ? "default-overflow" : "",
198
+ bodyClassName
199
+ ].filter(Boolean).join(" "),
194
200
  style: modalBodyStyle,
195
201
  children
196
202
  }
197
203
  ),
198
- footer === null ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "modal-foot", children: footer ?? defaultFooter })
204
+ footer === null ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "modal-foot", style: portalTheme.styles.footer, children: footer ?? defaultFooter })
199
205
  ]
200
206
  }
201
207
  )
@@ -1,4 +1,4 @@
1
- import { Table } from './chunk-JMYUO7V7.js';
1
+ import { Table } from './chunk-RM6JIM6O.js';
2
2
  import { withComponentTheme, InternalComponentThemePart } from './chunk-5HLNFDV4.js';
3
3
  import './tokens-223RYVVS.css';
4
4
  import './shared-NJHRNLRH.css';
@@ -60,8 +60,12 @@ interface ComponentThemeOverride<TSlot extends string = string> {
60
60
  tokens?: ThemeTokens;
61
61
  styles?: Partial<Record<TSlot, React.CSSProperties>>;
62
62
  }
63
+ /** Modal 对外提供的稳定结构样式插槽。 */
64
+ type ModalThemeSlot = "root" | "popup" | "overlay" | "header" | "body" | "footer";
63
65
  /** 按公共组件名称配置的主题覆盖。 */
64
- type ComponentThemeOverrides = Partial<Record<ComponentThemeName, ComponentThemeOverride>>;
66
+ type ComponentThemeOverrides = Partial<{
67
+ [TName in ComponentThemeName]: TName extends "Modal" ? ComponentThemeOverride<ModalThemeSlot> : ComponentThemeOverride;
68
+ }>;
65
69
  /** 单个组件或组件子树使用的视觉主题。 */
66
70
  interface ComponentThemeOptions extends Omit<ComponentThemeOverride, "styles"> {
67
71
  scope?: ComponentThemeScope;
@@ -74,4 +78,4 @@ interface ComponentThemeProps {
74
78
  theme?: ComponentTheme;
75
79
  }
76
80
 
77
- export type { AccentKey as A, ComponentTheme as C, ResolvedThemeColors as R, ThemeBaseMode as T, AccentPalette as a, ComponentThemeName as b, ComponentThemeOptions as c, ComponentThemeOverride as d, ComponentThemeOverrides as e, ComponentThemeProps as f, ComponentThemeScope as g, CustomAccentInput as h, ThemeColorOverrides as i, ThemeSemanticColors as j, ThemeSurfacePalette as k, ThemeTokens as l };
81
+ export type { AccentKey as A, ComponentTheme as C, ModalThemeSlot as M, ResolvedThemeColors as R, ThemeBaseMode as T, AccentPalette as a, ComponentThemeName as b, ComponentThemeOptions as c, ComponentThemeOverride as d, ComponentThemeOverrides as e, ComponentThemeProps as f, ComponentThemeScope as g, CustomAccentInput as h, ThemeColorOverrides as i, ThemeSemanticColors as j, ThemeSurfacePalette as k, ThemeTokens as l };
@@ -60,8 +60,12 @@ interface ComponentThemeOverride<TSlot extends string = string> {
60
60
  tokens?: ThemeTokens;
61
61
  styles?: Partial<Record<TSlot, React.CSSProperties>>;
62
62
  }
63
+ /** Modal 对外提供的稳定结构样式插槽。 */
64
+ type ModalThemeSlot = "root" | "popup" | "overlay" | "header" | "body" | "footer";
63
65
  /** 按公共组件名称配置的主题覆盖。 */
64
- type ComponentThemeOverrides = Partial<Record<ComponentThemeName, ComponentThemeOverride>>;
66
+ type ComponentThemeOverrides = Partial<{
67
+ [TName in ComponentThemeName]: TName extends "Modal" ? ComponentThemeOverride<ModalThemeSlot> : ComponentThemeOverride;
68
+ }>;
65
69
  /** 单个组件或组件子树使用的视觉主题。 */
66
70
  interface ComponentThemeOptions extends Omit<ComponentThemeOverride, "styles"> {
67
71
  scope?: ComponentThemeScope;
@@ -74,4 +78,4 @@ interface ComponentThemeProps {
74
78
  theme?: ComponentTheme;
75
79
  }
76
80
 
77
- export type { AccentKey as A, ComponentTheme as C, ResolvedThemeColors as R, ThemeBaseMode as T, AccentPalette as a, ComponentThemeName as b, ComponentThemeOptions as c, ComponentThemeOverride as d, ComponentThemeOverrides as e, ComponentThemeProps as f, ComponentThemeScope as g, CustomAccentInput as h, ThemeColorOverrides as i, ThemeSemanticColors as j, ThemeSurfacePalette as k, ThemeTokens as l };
81
+ export type { AccentKey as A, ComponentTheme as C, ModalThemeSlot as M, ResolvedThemeColors as R, ThemeBaseMode as T, AccentPalette as a, ComponentThemeName as b, ComponentThemeOptions as c, ComponentThemeOverride as d, ComponentThemeOverrides as e, ComponentThemeProps as f, ComponentThemeScope as g, CustomAccentInput as h, ThemeColorOverrides as i, ThemeSemanticColors as j, ThemeSurfacePalette as k, ThemeTokens as l };