@fangxinyan/lumina 0.9.2 → 0.9.4

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.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkQZ2AAQBX_cjs = require('./chunk-QZ2AAQBX.cjs');
3
+ var chunkA5MLLFKT_cjs = require('./chunk-A5MLLFKT.cjs');
4
4
  var chunkKPBZKHCS_cjs = require('./chunk-KPBZKHCS.cjs');
5
5
  var chunkFJB3243S_cjs = require('./chunk-FJB3243S.cjs');
6
6
  var chunkHSDMJUB6_cjs = require('./chunk-HSDMJUB6.cjs');
@@ -503,7 +503,7 @@ var TableInner = ({
503
503
  }
504
504
  ),
505
505
  pagEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-pagination", children: /* @__PURE__ */ jsxRuntime.jsx(chunkV6BLBIY6_cjs.InternalComponentThemePart, { components: "Pagination", children: /* @__PURE__ */ jsxRuntime.jsx(
506
- chunkQZ2AAQBX_cjs.Pagination,
506
+ chunkA5MLLFKT_cjs.Pagination,
507
507
  {
508
508
  total: totalCount,
509
509
  pageSize: curPageSize,
@@ -6,11 +6,67 @@ import { withComponentTheme, useComponentPortalTheme, InternalComponentThemePart
6
6
  import { usePortalContainer } from './chunk-CPVUDSIY.js';
7
7
  import './tokens-223RYVVS.css';
8
8
  import './shared-NJHRNLRH.css';
9
- import './Select-Y3X3ZJTC.css';
10
- import * as React from 'react';
9
+ import './Select-M3HCB3PW.css';
10
+ import * as React2 from 'react';
11
11
  import { createPortal } from 'react-dom';
12
12
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
13
13
 
14
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React2.useLayoutEffect : React2.useEffect;
15
+ function measureResponsiveTags(container) {
16
+ const availableWidth = container.getBoundingClientRect().width;
17
+ if (availableWidth <= 0) return void 0;
18
+ const tags = Array.from(container.querySelectorAll("[data-select-tag]"));
19
+ const overflows = Array.from(container.querySelectorAll("[data-select-overflow]"));
20
+ const search = container.querySelector(".select-search-measure");
21
+ const gap = parseFloat(getComputedStyle(container).columnGap) || 0;
22
+ const tagWidths = tags.map((tag) => tag.getBoundingClientRect().width);
23
+ const overflowWidths = [0, ...overflows.map((tag) => tag.getBoundingClientRect().width)];
24
+ const inputWidth = search ? Math.min(search.getBoundingClientRect().width, Math.max(
25
+ 0,
26
+ availableWidth - (overflowWidths[tags.length] ?? 0) - (tags.length > 0 ? gap : 0)
27
+ )) : 0;
28
+ let count = 0;
29
+ let prefixWidth = 0;
30
+ for (let index = 0; index <= tags.length; index += 1) {
31
+ const remaining = tags.length - index;
32
+ const itemCount = index + (remaining > 0 ? 1 : 0) + (search ? 1 : 0);
33
+ const width = prefixWidth + (overflowWidths[remaining] ?? 0) + inputWidth + Math.max(0, itemCount - 1) * gap;
34
+ if (width <= availableWidth) count = index;
35
+ prefixWidth += tagWidths[index] ?? 0;
36
+ }
37
+ return { count, inputWidth };
38
+ }
39
+ function useResponsiveTags(enabled, items, searchable) {
40
+ const tagsRef = React2.useRef(null);
41
+ const [layout, setLayout] = React2.useState({ count: 0, inputWidth: 0 });
42
+ const measure = React2.useCallback(() => {
43
+ if (!tagsRef.current) return;
44
+ const next = measureResponsiveTags(tagsRef.current);
45
+ if (next) setLayout((previous) => previous.count === next.count && previous.inputWidth === next.inputWidth ? previous : next);
46
+ }, []);
47
+ useIsomorphicLayoutEffect(() => {
48
+ if (enabled) measure();
49
+ });
50
+ useIsomorphicLayoutEffect(() => {
51
+ const container = tagsRef.current;
52
+ if (!enabled || !container) return;
53
+ let frame = 0;
54
+ const scheduleMeasure = () => {
55
+ cancelAnimationFrame(frame);
56
+ frame = requestAnimationFrame(measure);
57
+ };
58
+ const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(scheduleMeasure) : void 0;
59
+ observer?.observe(container);
60
+ container.querySelectorAll("[data-select-tag], [data-select-overflow], .select-search-measure").forEach((element) => observer?.observe(element));
61
+ window.addEventListener("resize", scheduleMeasure);
62
+ return () => {
63
+ observer?.disconnect();
64
+ window.removeEventListener("resize", scheduleMeasure);
65
+ cancelAnimationFrame(frame);
66
+ };
67
+ }, [enabled, items, searchable, measure]);
68
+ return { tagsRef, count: Math.min(layout.count, items.length), inputWidth: layout.inputWidth };
69
+ }
14
70
  var isGroup = (it) => Array.isArray(it.options);
15
71
  var flatten = (items) => items.flatMap((it) => isGroup(it) ? it.options : [it]);
16
72
  var prioritizePinnedGroups = (items) => {
@@ -89,21 +145,22 @@ var SelectInner = (props, forwardedRef) => {
89
145
  ...rest
90
146
  } = props;
91
147
  const isMulti = multiple === true;
148
+ const responsiveTags = isMulti && maxTagCount === "responsive";
92
149
  const mergedClearable = clearable ?? !!allowClear;
93
150
  const mergedClearIcon = typeof allowClear === "object" ? allowClear.clearIcon : void 0;
94
151
  const mergedSearchable = searchable ?? !!showSearch;
95
152
  const mergedListHeight = Number.isFinite(listHeight) && listHeight > 0 ? listHeight : 260;
96
153
  const mergedMenuClassName = [menuClassName, popupClassName, dropdownClassName].filter(Boolean).join(" ");
97
- const [innerSingle, setInnerSingle] = React.useState(
154
+ const [innerSingle, setInnerSingle] = React2.useState(
98
155
  !isMulti ? props.defaultValue : void 0
99
156
  );
100
- const [innerMulti, setInnerMulti] = React.useState(
157
+ const [innerMulti, setInnerMulti] = React2.useState(
101
158
  isMulti && Array.isArray(props.defaultValue) ? props.defaultValue : []
102
159
  );
103
- const [innerOpen, setInnerOpen] = React.useState(defaultOpen ?? false);
104
- const [innerSearchValue, setInnerSearchValue] = React.useState(defaultSearchValue ?? "");
105
- const [activeIdx, setActiveIdx] = React.useState(-1);
106
- const searchRef = React.useRef(null);
160
+ const [innerOpen, setInnerOpen] = React2.useState(defaultOpen ?? false);
161
+ const [innerSearchValue, setInnerSearchValue] = React2.useState(defaultSearchValue ?? "");
162
+ const [activeIdx, setActiveIdx] = React2.useState(-1);
163
+ const searchRef = React2.useRef(null);
107
164
  const portalContainer = usePortalContainer();
108
165
  const portalTheme = useComponentPortalTheme([
109
166
  "Select",
@@ -116,26 +173,26 @@ var SelectInner = (props, forwardedRef) => {
116
173
  (styleValue) => styleValue?.width != null || styleValue?.minWidth != null || styleValue?.maxWidth != null
117
174
  );
118
175
  const resolvedPopupWidth = popupStyle?.width ?? themedPopupStyle?.width;
119
- const listboxId = React.useId();
176
+ const listboxId = React2.useId();
120
177
  const openControlled = openProp !== void 0;
121
178
  const requestedOpen = openControlled ? openProp : innerOpen;
122
179
  const open = !disabled && requestedOpen;
123
- const requestedOpenRef = React.useRef(requestedOpen);
180
+ const requestedOpenRef = React2.useRef(requestedOpen);
124
181
  requestedOpenRef.current = requestedOpen;
125
182
  const searchControlled = searchValueProp !== void 0;
126
183
  const searchValue = searchControlled ? searchValueProp : innerSearchValue;
127
184
  const hasInlineSearch = mergedSearchable;
128
185
  const showsInlineSearchInput = hasInlineSearch && (isMulti || open);
129
- const updateSearchValue = React.useCallback((nextValue) => {
186
+ const updateSearchValue = React2.useCallback((nextValue) => {
130
187
  if (!searchControlled) setInnerSearchValue(nextValue);
131
188
  onSearch?.(nextValue);
132
189
  }, [onSearch, searchControlled]);
133
- const resetSearchValue = React.useCallback(() => {
190
+ const resetSearchValue = React2.useCallback(() => {
134
191
  if (!searchValue) return;
135
192
  if (!searchControlled) setInnerSearchValue("");
136
193
  onSearch?.("");
137
194
  }, [onSearch, searchControlled, searchValue]);
138
- const setOpen = React.useCallback((nextOpen) => {
195
+ const setOpen = React2.useCallback((nextOpen) => {
139
196
  if (disabled && nextOpen) return;
140
197
  if (nextOpen === requestedOpenRef.current) return;
141
198
  requestedOpenRef.current = nextOpen;
@@ -143,7 +200,7 @@ var SelectInner = (props, forwardedRef) => {
143
200
  onOpenChange?.(nextOpen);
144
201
  if (!nextOpen) resetSearchValue();
145
202
  }, [disabled, onOpenChange, openControlled, resetSearchValue]);
146
- React.useEffect(() => {
203
+ React2.useEffect(() => {
147
204
  if (!disabled || openControlled || !innerOpen) return;
148
205
  setInnerOpen(false);
149
206
  onOpenChange?.(false);
@@ -163,7 +220,7 @@ var SelectInner = (props, forwardedRef) => {
163
220
  onEscape: () => setOpen(false),
164
221
  restoreFocus: true
165
222
  });
166
- const setTriggerRef = React.useCallback(
223
+ const setTriggerRef = React2.useCallback(
167
224
  (node) => {
168
225
  triggerRef.current = node;
169
226
  if (typeof forwardedRef === "function") forwardedRef(node);
@@ -176,16 +233,16 @@ var SelectInner = (props, forwardedRef) => {
176
233
  const singleValue = singleControlled ? props.value : innerSingle;
177
234
  const controlledMultiValue = props.value;
178
235
  const multiValue = multiControlled ? Array.isArray(controlledMultiValue) ? controlledMultiValue : [] : innerMulti;
179
- const selectedValues = React.useMemo(
236
+ const selectedValues = React2.useMemo(
180
237
  () => isMulti ? multiValue : singleValue !== void 0 ? [singleValue] : [],
181
238
  [isMulti, multiValue, singleValue]
182
239
  );
183
240
  const selectionLimit = maxCount !== void 0 && Number.isFinite(maxCount) ? Math.max(0, Math.floor(maxCount)) : void 0;
184
- const isOptionDisabled = React.useCallback((option) => {
241
+ const isOptionDisabled = React2.useCallback((option) => {
185
242
  const selected = selectedValues.includes(option.value);
186
243
  return !!option.disabled || !!getOptionDisabled?.(option, selectedValues) || isMulti && !selected && selectionLimit !== void 0 && selectedValues.length >= selectionLimit;
187
244
  }, [getOptionDisabled, isMulti, selectedValues, selectionLimit]);
188
- React.useEffect(() => {
245
+ React2.useEffect(() => {
189
246
  if (!open) return;
190
247
  const h = (e) => {
191
248
  const t = e.target;
@@ -196,42 +253,43 @@ var SelectInner = (props, forwardedRef) => {
196
253
  document.addEventListener("mousedown", h);
197
254
  return () => document.removeEventListener("mousedown", h);
198
255
  }, [menuRef, open, setOpen, triggerRef]);
199
- React.useEffect(() => {
256
+ React2.useEffect(() => {
200
257
  if (open && mergedSearchable) {
201
258
  requestAnimationFrame(() => searchRef.current?.focus());
202
259
  }
203
260
  if (!open) setActiveIdx(-1);
204
261
  }, [open, mergedSearchable]);
205
- const orderedItems = React.useMemo(
262
+ const orderedItems = React2.useMemo(
206
263
  () => prioritizePinnedGroups(options),
207
264
  [options]
208
265
  );
209
- const allFlat = React.useMemo(() => flatten(orderedItems), [orderedItems]);
210
- const optionByValue = React.useMemo(() => {
266
+ const allFlat = React2.useMemo(() => flatten(orderedItems), [orderedItems]);
267
+ const optionByValue = React2.useMemo(() => {
211
268
  const index = /* @__PURE__ */ new Map();
212
269
  allFlat.forEach((option) => index.set(option.value, option));
213
270
  return index;
214
271
  }, [allFlat]);
215
- const selectedOptionCacheRef = React.useRef(/* @__PURE__ */ new Map());
216
- React.useEffect(() => {
272
+ const selectedOptionCacheRef = React2.useRef(/* @__PURE__ */ new Map());
273
+ React2.useEffect(() => {
217
274
  selectedValues.forEach((selectedValue) => {
218
275
  const option = optionByValue.get(selectedValue);
219
276
  if (option) selectedOptionCacheRef.current.set(selectedValue, option);
220
277
  });
221
278
  }, [optionByValue, selectedValues]);
222
- const selectedOptions = React.useMemo(
279
+ const selectedOptions = React2.useMemo(
223
280
  () => selectedValues.map(
224
281
  (selectedValue) => optionByValue.get(selectedValue) ?? selectedOptionCacheRef.current.get(selectedValue)
225
282
  ).filter((option) => option !== void 0),
226
283
  [optionByValue, selectedValues]
227
284
  );
228
- const filteredFlat = React.useMemo(() => {
285
+ const responsiveLayout = useResponsiveTags(responsiveTags, selectedOptions, hasInlineSearch);
286
+ const filteredFlat = React2.useMemo(() => {
229
287
  if (!searchValue.trim()) return allFlat;
230
288
  if (filterOption === false) return allFlat;
231
289
  const f = typeof filterOption === "function" ? filterOption : (input, option) => defaultFilter(input, option, optionFilterProp);
232
290
  return allFlat.filter((o) => f(searchValue, o));
233
291
  }, [allFlat, filterOption, optionFilterProp, searchValue]);
234
- const filteredItems = React.useMemo(() => {
292
+ const filteredItems = React2.useMemo(() => {
235
293
  if (!searchValue.trim()) {
236
294
  return orderedItems.filter((item) => !isGroup(item) || item.options.length > 0);
237
295
  }
@@ -243,7 +301,7 @@ var SelectInner = (props, forwardedRef) => {
243
301
  return kept.length ? { ...it, options: kept } : null;
244
302
  }).filter((x) => x !== null);
245
303
  }, [orderedItems, filteredFlat, searchValue]);
246
- React.useEffect(() => {
304
+ React2.useEffect(() => {
247
305
  setActiveIdx((current) => {
248
306
  if (current >= 0 && current < filteredFlat.length && !isOptionDisabled(filteredFlat[current])) {
249
307
  return current;
@@ -353,10 +411,11 @@ var SelectInner = (props, forwardedRef) => {
353
411
  {
354
412
  ref: searchRef,
355
413
  id: fieldId,
356
- className: `select-search-input ${multiHasSelection ? "with-selection" : "empty"}`,
414
+ className: "select-search-input",
415
+ "data-inline-size": multiHasSelection ? "content" : "fill",
357
416
  type: "search",
358
417
  value: searchValue,
359
- style: multiHasSelection ? { width: `${Math.min(Math.max(searchDisplayWidth + 1, 2), 32)}ch` } : void 0,
418
+ style: responsiveTags ? { width: responsiveLayout.inputWidth } : multiHasSelection ? { width: `${Math.min(Math.max(searchDisplayWidth + 1, 2), 32)}ch` } : void 0,
360
419
  placeholder: isMulti ? multiValue.length === 0 ? placeholder : void 0 : "\u641C\u7D22...",
361
420
  disabled,
362
421
  autoComplete: "off",
@@ -381,16 +440,21 @@ var SelectInner = (props, forwardedRef) => {
381
440
  const renderTrigger = () => {
382
441
  if (isMulti) {
383
442
  const selected = selectedOptions;
384
- const max = maxTagCount;
443
+ const max = typeof maxTagCount === "number" ? maxTagCount : void 0;
385
444
  const shown = max != null ? selected.slice(0, max) : selected;
386
- const overflow = selected.length - shown.length;
387
- if (selected.length === 0 && !hasInlineSearch) {
445
+ const overflow = selected.length - (responsiveTags ? responsiveLayout.count : shown.length);
446
+ if (selected.length === 0 && !hasInlineSearch && !responsiveTags) {
388
447
  return /* @__PURE__ */ jsx("span", { className: "placeholder", children: placeholder });
389
448
  }
390
- return /* @__PURE__ */ jsx(InternalComponentThemePart, { components: "Tag", children: /* @__PURE__ */ jsxs("span", { className: "select-tags", children: [
391
- shown.map((o) => /* @__PURE__ */ jsx(
449
+ return /* @__PURE__ */ jsx(InternalComponentThemePart, { components: "Tag", children: /* @__PURE__ */ jsxs("span", { className: "select-tags", ref: responsiveLayout.tagsRef, children: [
450
+ selected.length === 0 && !hasInlineSearch && /* @__PURE__ */ jsx("span", { className: "placeholder", children: placeholder }),
451
+ shown.map((o, index) => /* @__PURE__ */ jsx(
392
452
  Tag,
393
453
  {
454
+ "data-select-tag": responsiveTags ? "" : void 0,
455
+ "data-collapsed": responsiveTags && index >= responsiveLayout.count ? "true" : void 0,
456
+ "aria-hidden": responsiveTags && index >= responsiveLayout.count ? true : void 0,
457
+ ...responsiveTags && index >= responsiveLayout.count ? { inert: "" } : {},
394
458
  tone: "accent",
395
459
  removable: !disabled,
396
460
  onRemove: () => removeMultiValue(o.value),
@@ -407,7 +471,14 @@ var SelectInner = (props, forwardedRef) => {
407
471
  "+",
408
472
  overflow
409
473
  ] }),
410
- renderInlineSearchInput()
474
+ renderInlineSearchInput(),
475
+ responsiveTags && /* @__PURE__ */ jsxs("span", { className: "select-tag-measurements", "aria-hidden": "true", ...{ inert: "" }, children: [
476
+ selected.map((option, index) => /* @__PURE__ */ jsxs(Tag, { tone: "neutral", "data-select-overflow": "", children: [
477
+ "+",
478
+ index + 1
479
+ ] }, String(option.value))),
480
+ hasInlineSearch && /* @__PURE__ */ jsx("span", { className: "select-search-measure", children: searchValue || "\u200B" })
481
+ ] })
411
482
  ] }) });
412
483
  }
413
484
  if (showsInlineSearchInput) return renderInlineSearchInput();
@@ -423,6 +494,24 @@ var SelectInner = (props, forwardedRef) => {
423
494
  };
424
495
  const hasSelection = isMulti ? multiValue.length > 0 : singleValue != null;
425
496
  const showClear = mergedClearable && hasSelection && !disabled;
497
+ const renderClearButton = () => showClear && /* @__PURE__ */ jsx(
498
+ "button",
499
+ {
500
+ type: "button",
501
+ className: "select-clear",
502
+ "aria-label": "Clear",
503
+ onPointerDown: (event) => event.stopPropagation(),
504
+ onMouseDown: (event) => {
505
+ if (hasInlineSearch) event.preventDefault();
506
+ event.stopPropagation();
507
+ },
508
+ onClick: (event) => {
509
+ event.stopPropagation();
510
+ clearAll();
511
+ },
512
+ children: mergedClearIcon ?? /* @__PURE__ */ jsx(Icon, { name: "x", size: 12 })
513
+ }
514
+ );
426
515
  let renderIdx = -1;
427
516
  const renderOption = (o, groupPinned = false) => {
428
517
  renderIdx += 1;
@@ -482,7 +571,7 @@ var SelectInner = (props, forwardedRef) => {
482
571
  );
483
572
  };
484
573
  const renderMenuItems = (items) => items.map(
485
- (item, groupIndex) => isGroup(item) ? /* @__PURE__ */ jsxs(React.Fragment, { children: [
574
+ (item, groupIndex) => isGroup(item) ? /* @__PURE__ */ jsxs(React2.Fragment, { children: [
486
575
  /* @__PURE__ */ jsx("div", { className: "menu-group-label", children: item.label }),
487
576
  item.options.map((option) => renderOption(option, !!item.pinned))
488
577
  ] }, `g-${groupIndex}-${item.pinned ? "pinned" : "regular"}`) : renderOption(item)
@@ -506,7 +595,7 @@ var SelectInner = (props, forwardedRef) => {
506
595
  {
507
596
  ref: setTriggerRef,
508
597
  ...rest,
509
- className: `select ${size} ${isMulti ? "multi" : ""} ${hasInlineSearch ? "searchable" : ""} ${open ? "open" : ""} ${disabled ? "disabled" : ""} ${invalid ? "invalid" : ""} ${className}`,
598
+ className: `select ${size} ${isMulti ? "multi" : ""} ${responsiveTags ? "responsive" : ""} ${hasInlineSearch ? "searchable" : ""} ${open ? "open" : ""} ${disabled ? "disabled" : ""} ${invalid ? "invalid" : ""} ${className}`,
510
599
  onKeyDown: (e) => {
511
600
  onRootKeyDown?.(e);
512
601
  const target = e.target;
@@ -553,28 +642,12 @@ var SelectInner = (props, forwardedRef) => {
553
642
  "aria-activedescendant": showsInlineSearchInput ? void 0 : open && activeIdx >= 0 ? `${listboxId}-option-${activeIdx}` : void 0,
554
643
  children: [
555
644
  renderTrigger(),
645
+ responsiveTags && renderClearButton(),
556
646
  /* @__PURE__ */ jsx(Icon, { name: "chevDown", size: 14, className: "select-caret" })
557
647
  ]
558
648
  }
559
649
  ),
560
- showClear && /* @__PURE__ */ jsx(
561
- "button",
562
- {
563
- type: "button",
564
- className: "select-clear",
565
- "aria-label": "Clear",
566
- onPointerDown: (event) => event.stopPropagation(),
567
- onMouseDown: (event) => {
568
- if (hasInlineSearch) event.preventDefault();
569
- event.stopPropagation();
570
- },
571
- onClick: (event) => {
572
- event.stopPropagation();
573
- clearAll();
574
- },
575
- children: mergedClearIcon ?? /* @__PURE__ */ jsx(Icon, { name: "x", size: 12 })
576
- }
577
- ),
650
+ !responsiveTags && renderClearButton(),
578
651
  open && portalContainer && createPortal(
579
652
  /* @__PURE__ */ jsx(
580
653
  "div",
@@ -613,7 +686,7 @@ var SelectInner = (props, forwardedRef) => {
613
686
  }
614
687
  );
615
688
  };
616
- var SelectBase = React.forwardRef(SelectInner);
689
+ var SelectBase = React2.forwardRef(SelectInner);
617
690
  SelectBase.displayName = "Select";
618
691
  var Select = withComponentTheme(
619
692
  SelectBase,
@@ -1,4 +1,4 @@
1
- import { Pagination } from './chunk-LZXJN3XA.js';
1
+ import { Pagination } from './chunk-3SUMCW2F.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';
@@ -1,4 +1,4 @@
1
- import { Table } from './chunk-RM6JIM6O.js';
1
+ import { Table } from './chunk-QITKDNCX.js';
2
2
  import { withComponentTheme, InternalComponentThemePart } from './chunk-5HLNFDV4.js';
3
3
  import './tokens-223RYVVS.css';
4
4
  import './shared-NJHRNLRH.css';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkMJYMPK5K_cjs = require('./chunk-MJYMPK5K.cjs');
3
+ var chunkG5ENSJBS_cjs = require('./chunk-G5ENSJBS.cjs');
4
4
  var chunkV6BLBIY6_cjs = require('./chunk-V6BLBIY6.cjs');
5
5
  require('./tokens-223RYVVS.css');
6
6
  require('./shared-NJHRNLRH.css');
@@ -77,7 +77,7 @@ var TableProInner = ({
77
77
  actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-toolbar-actions", children: actions })
78
78
  ] }),
79
79
  /* @__PURE__ */ jsxRuntime.jsx(chunkV6BLBIY6_cjs.InternalComponentThemePart, { components: "Table", children: /* @__PURE__ */ jsxRuntime.jsx(
80
- chunkMJYMPK5K_cjs.Table,
80
+ chunkG5ENSJBS_cjs.Table,
81
81
  {
82
82
  columns,
83
83
  data,
package/dist/index.cjs CHANGED
@@ -3,8 +3,8 @@
3
3
  var chunkRXITGNPX_cjs = require('./chunk-RXITGNPX.cjs');
4
4
  var chunkXHKSUKKL_cjs = require('./chunk-XHKSUKKL.cjs');
5
5
  var chunk3D5RJA7R_cjs = require('./chunk-3D5RJA7R.cjs');
6
- var chunkIDEE7PP5_cjs = require('./chunk-IDEE7PP5.cjs');
7
- var chunkMJYMPK5K_cjs = require('./chunk-MJYMPK5K.cjs');
6
+ var chunkV6DY7J2Z_cjs = require('./chunk-V6DY7J2Z.cjs');
7
+ var chunkG5ENSJBS_cjs = require('./chunk-G5ENSJBS.cjs');
8
8
  var chunkAEY76EAH_cjs = require('./chunk-AEY76EAH.cjs');
9
9
  require('./chunk-HYJSMFZA.cjs');
10
10
  var chunkAQN3PD24_cjs = require('./chunk-AQN3PD24.cjs');
@@ -20,8 +20,8 @@ var chunk6WEXRX7K_cjs = require('./chunk-6WEXRX7K.cjs');
20
20
  var chunkZ6AG7O4B_cjs = require('./chunk-Z6AG7O4B.cjs');
21
21
  var chunkTPFY5SKB_cjs = require('./chunk-TPFY5SKB.cjs');
22
22
  var chunkSOAGRYM3_cjs = require('./chunk-SOAGRYM3.cjs');
23
- var chunkQZ2AAQBX_cjs = require('./chunk-QZ2AAQBX.cjs');
24
- var chunkCDT2QCBL_cjs = require('./chunk-CDT2QCBL.cjs');
23
+ var chunkA5MLLFKT_cjs = require('./chunk-A5MLLFKT.cjs');
24
+ var chunk562P5YMO_cjs = require('./chunk-562P5YMO.cjs');
25
25
  var chunkVNP5WB6M_cjs = require('./chunk-VNP5WB6M.cjs');
26
26
  var chunk3J7HOTD6_cjs = require('./chunk-3J7HOTD6.cjs');
27
27
  var chunkPYCAGTO7_cjs = require('./chunk-PYCAGTO7.cjs');
@@ -58,7 +58,7 @@ require('./chunk-V6BLBIY6.cjs');
58
58
  var chunkI4GJZLJU_cjs = require('./chunk-I4GJZLJU.cjs');
59
59
 
60
60
  // src/index.ts
61
- var VERSION = "0.9.2";
61
+ var VERSION = "0.9.4";
62
62
 
63
63
  Object.defineProperty(exports, "Timeline", {
64
64
  enumerable: true,
@@ -90,11 +90,11 @@ Object.defineProperty(exports, "Typography", {
90
90
  });
91
91
  Object.defineProperty(exports, "TablePro", {
92
92
  enumerable: true,
93
- get: function () { return chunkIDEE7PP5_cjs.TablePro; }
93
+ get: function () { return chunkV6DY7J2Z_cjs.TablePro; }
94
94
  });
95
95
  Object.defineProperty(exports, "Table", {
96
96
  enumerable: true,
97
- get: function () { return chunkMJYMPK5K_cjs.Table; }
97
+ get: function () { return chunkG5ENSJBS_cjs.Table; }
98
98
  });
99
99
  Object.defineProperty(exports, "Tabs", {
100
100
  enumerable: true,
@@ -190,11 +190,11 @@ Object.defineProperty(exports, "Modal", {
190
190
  });
191
191
  Object.defineProperty(exports, "Pagination", {
192
192
  enumerable: true,
193
- get: function () { return chunkQZ2AAQBX_cjs.Pagination; }
193
+ get: function () { return chunkA5MLLFKT_cjs.Pagination; }
194
194
  });
195
195
  Object.defineProperty(exports, "Select", {
196
196
  enumerable: true,
197
- get: function () { return chunkCDT2QCBL_cjs.Select; }
197
+ get: function () { return chunk562P5YMO_cjs.Select; }
198
198
  });
199
199
  Object.defineProperty(exports, "Tag", {
200
200
  enumerable: true,
package/dist/index.d.cts CHANGED
@@ -54,6 +54,6 @@ import 'react/jsx-runtime';
54
54
  import 'react';
55
55
 
56
56
  /** Package version — bumped by release scripts. */
57
- declare const VERSION = "0.9.2";
57
+ declare const VERSION = "0.9.4";
58
58
 
59
59
  export { VERSION };
package/dist/index.d.ts CHANGED
@@ -54,6 +54,6 @@ import 'react/jsx-runtime';
54
54
  import 'react';
55
55
 
56
56
  /** Package version — bumped by release scripts. */
57
- declare const VERSION = "0.9.2";
57
+ declare const VERSION = "0.9.4";
58
58
 
59
59
  export { VERSION };
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  export { Timeline } from './chunk-U7V2FOIM.js';
2
2
  export { Tooltip } from './chunk-TALNKJQ2.js';
3
3
  export { Link, Paragraph, Text, Title, Typography } from './chunk-2COQYOVG.js';
4
- export { TablePro } from './chunk-U3T6RC6U.js';
5
- export { Table } from './chunk-RM6JIM6O.js';
4
+ export { TablePro } from './chunk-T422LYTL.js';
5
+ export { Table } from './chunk-QITKDNCX.js';
6
6
  export { Tabs } from './chunk-4JANYBXO.js';
7
7
  import './chunk-EE7IJ3MB.js';
8
8
  export { THEME_PANEL_DEFAULT_PRESET_OPTIONS, THEME_PANEL_DEFAULT_THEME_PRESETS, ThemePanel } from './chunk-IU6PLLEL.js';
@@ -18,8 +18,8 @@ export { InputNumber } from './chunk-RYF5ADJW.js';
18
18
  export { List } from './chunk-LACXN5CI.js';
19
19
  export { MessageContainer, ToastContainer, message, toast } from './chunk-2V6RQQRI.js';
20
20
  export { Modal } from './chunk-RJCPXAZ3.js';
21
- export { Pagination } from './chunk-LZXJN3XA.js';
22
- export { Select } from './chunk-MSWWABXP.js';
21
+ export { Pagination } from './chunk-3SUMCW2F.js';
22
+ export { Select } from './chunk-OKGODC5A.js';
23
23
  export { Tag } from './chunk-OGMI3TO5.js';
24
24
  export { Popover } from './chunk-A34P5CU7.js';
25
25
  export { Progress } from './chunk-BOBT7JUB.js';
@@ -56,6 +56,6 @@ import './chunk-5HLNFDV4.js';
56
56
  export { ACCENT_PRESETS, ACCENT_PRESETS_DARK, DEFAULT_THEME_COLORS, FONT_STACKS, ThemeProvider, applyTheme, componentTokensToStyle, deriveThemeColors, normalizeAccentInput, resolveThemeColorScheme, resolveThemeColors, resolveThemeMode, resolveVisualThemeSnapshot, themeColorsToStyle, themeTokenToKebabCase, useTheme, useThemeOptional, visualThemeToStyle } from './chunk-CPVUDSIY.js';
57
57
 
58
58
  // src/index.ts
59
- var VERSION = "0.9.2";
59
+ var VERSION = "0.9.4";
60
60
 
61
61
  export { VERSION };
package/dist/styles.css CHANGED
@@ -1729,11 +1729,11 @@ button.collapse-chev {
1729
1729
  font: inherit;
1730
1730
  line-height: 24px;
1731
1731
  }
1732
- .select-search-input.empty {
1732
+ .select-search-input[data-inline-size="fill"] {
1733
1733
  flex: 1 1 auto;
1734
1734
  width: 100%;
1735
1735
  }
1736
- .select-search-input.with-selection {
1736
+ .select-search-input[data-inline-size="content"] {
1737
1737
  flex: 0 1 auto;
1738
1738
  min-width: 2ch;
1739
1739
  max-width: 100%;
@@ -1777,6 +1777,71 @@ button.collapse-chev {
1777
1777
  }
1778
1778
  .select:hover .select-clear { opacity: 1; }
1779
1779
  .select-clear:hover { color: var(--lmn-select-accent-ink, var(--accent-ink)); box-shadow: var(--lmn-select-neu-shadow-inset, var(--neu-shadow-inset)); }
1780
+ /* 自适应模式:控件按真实宽度参与布局,标签区只展示测量后能完整容纳的前缀。 */
1781
+ .select.multi.responsive .select-trigger {
1782
+ flex-wrap: nowrap;
1783
+ padding: var(--lmn-select-tag-gap, var(--gap-1)) var(--lmn-select-trigger-padding, var(--gap-2));
1784
+ gap: var(--lmn-select-control-gap, var(--gap-2));
1785
+ }
1786
+ .select.multi.responsive .select-tags {
1787
+ flex-wrap: nowrap;
1788
+ flex: 1 1 0%;
1789
+ gap: var(--lmn-select-tag-gap, var(--gap-1));
1790
+ position: relative;
1791
+ }
1792
+ .select.multi.responsive .select-tags > .tag,
1793
+ .select-tag-measurements > .tag {
1794
+ flex: none;
1795
+ width: max-content;
1796
+ max-width: var(--lmn-select-tag-max-width, 160px);
1797
+ }
1798
+ .select.multi.responsive .select-tags > .select-tag-overflow {
1799
+ max-width: none;
1800
+ }
1801
+ .select.multi.responsive [data-collapsed="true"],
1802
+ .select-tag-measurements {
1803
+ position: absolute;
1804
+ top: 0;
1805
+ left: 0;
1806
+ visibility: hidden;
1807
+ pointer-events: none;
1808
+ }
1809
+ .select-tag-measurements {
1810
+ width: 100%;
1811
+ height: 100%;
1812
+ overflow: hidden;
1813
+ }
1814
+ .select-tag-measurements > .tag {
1815
+ position: absolute;
1816
+ max-width: none;
1817
+ }
1818
+ .select-search-measure {
1819
+ display: block;
1820
+ width: max-content;
1821
+ min-width: 2ch;
1822
+ padding-inline: calc(var(--gap-1) / 2);
1823
+ padding-inline-end: calc(var(--gap-1) / 2 + 1ch);
1824
+ white-space: pre;
1825
+ font: inherit;
1826
+ }
1827
+ .select.multi.responsive .select-search-input {
1828
+ flex: 1 1 auto;
1829
+ min-width: 0;
1830
+ max-width: 100%;
1831
+ field-sizing: fixed;
1832
+ }
1833
+ .select.multi.responsive .select-caret,
1834
+ .select.multi.responsive .select-clear {
1835
+ position: static;
1836
+ transform: none;
1837
+ flex-shrink: 0;
1838
+ }
1839
+ .select.multi.responsive.open .select-caret { transform: rotate(180deg); }
1840
+ .select.multi.responsive .select-tags > .placeholder {
1841
+ overflow: hidden;
1842
+ text-overflow: ellipsis;
1843
+ white-space: nowrap;
1844
+ }
1780
1845
  /* Multi-select menu: leading checkbox per item */
1781
1846
  .menu-check {
1782
1847
  width: 16px;
@@ -27,6 +27,20 @@ multiple + Tag 形式呈现已选项。
27
27
  <Select multiple clearable value={tags} onChange={setTags} options={...} />
28
28
  ```
29
29
 
30
+ ### 单行自适应标签折叠
31
+
32
+ maxTagCount="responsive" 按标签、+N、输入框和按钮的实际占位自动增减展示数量,始终单行。长搜索词在原输入框内横向编辑;折叠不改变完整选值。仅多选启用,数字值与未设置时仍保留原来的数量折叠和换行行为。
33
+
34
+ ```tsx
35
+ <Select
36
+ multiple searchable allowClear
37
+ maxTagCount="responsive"
38
+ style={{ width: 218 }}
39
+ value={values} onChange={setValues}
40
+ options={options}
41
+ />
42
+ ```
43
+
30
44
  ### 远程搜索多选
31
45
 
32
46
  searchable 在单选和多选中都复用选择框本体作为输入;多选 Tag 后的空输入会收缩,不单独占行。选中后保持展开和关键词,业务层负责防抖与迟到结果保护。
@@ -181,7 +195,7 @@ loading 时显示 spinner,emptyContent 自定义空态。
181
195
  | onChange | `(value) => void` | — | 变更 |
182
196
  | placeholder | `string` | `"请选择…"` | 空选择时的提示文本 |
183
197
  | multiple | `boolean` | `false` | 多选 |
184
- | maxTagCount | `number` | — | 多选时显示的标签数(超出折叠 +N) |
198
+ | maxTagCount | `number | "responsive"` | — | 多选标签展示上限;responsive 按可用宽度动态折叠为 +N 并保持单行,搜索词可横向编辑;不改变选值。数字和未设置时保留既有换行行为 |
185
199
  | maxCount | `number` | — | 多选允许的最大选择数;达到上限后禁用未选项 |
186
200
  | getOptionDisabled | `(option, selectedValues) => boolean` | — | 基于候选项和当前选择动态判断禁用状态 |
187
201
  | searchable | `boolean` | `false` | 在选择框本体内启用搜索,单选和多选共用同一交互形态 |
package/docs/llms.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > 拟态风格的 React 18 组件库,目标是 Electron 桌面应用。**写给 AI 编程助手**的按需文档 —— 每个组件单独一个 `.md`,避免一次性读取全部。示例源自 playground 的 demo,可直接复制运行。
4
4
 
5
5
  - **包名**: `@fangxinyan/lumina`
6
- - **版本**: `0.9.2`
6
+ - **版本**: `0.9.4`
7
7
  - **React 最低版本**: 18
8
8
  - **环境**: 带打包器的 React 工程(Vite / Next.js / Webpack / Remix / Electron + Vite 等)
9
9
  - **零运行时依赖**: 只依赖 `react` / `react-dom` (peer deps)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fangxinyan/lumina",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "description": "Lumina — Neumorphic component library for Electron & React apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",