@sia.soul/sia-react-ui 0.1.39 → 0.1.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-GLS4WVIZ.js → chunk-6TLANQVX.js} +1 -1
- package/dist/{chunk-WR7XTQRU.js → chunk-CEZ4GW3X.js} +96 -50
- package/dist/{chunk-LRGD2QDA.js → chunk-ZTJUFVJO.js} +820 -820
- package/dist/{core-D4opRFkZ.d.cts → core-BAHoW7_e.d.cts} +2 -2
- package/dist/{core-VNY_7WRq.d.ts → core-fn8h4yRg.d.ts} +2 -2
- package/dist/core.cjs +996 -949
- package/dist/core.css +46 -18
- package/dist/core.d.cts +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +2 -2
- package/dist/index.cjs +534 -487
- package/dist/index.css +46 -18
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/select-date-range.js +2 -2
- package/package.json +1 -1
|
@@ -2,11 +2,10 @@ import {
|
|
|
2
2
|
TextArea
|
|
3
3
|
} from "./chunk-SMCYEPBL.js";
|
|
4
4
|
import {
|
|
5
|
-
FloatingScrollbarProvider,
|
|
6
5
|
Popover,
|
|
7
6
|
Tooltip,
|
|
8
7
|
useOverlayLifecycle
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ZTJUFVJO.js";
|
|
10
9
|
import {
|
|
11
10
|
Dropdown,
|
|
12
11
|
Icon
|
|
@@ -191,6 +190,7 @@ function Tag({
|
|
|
191
190
|
// src/components/Tabs.tsx
|
|
192
191
|
import { useEffect, useId, useLayoutEffect as useLayoutEffect2, useMemo, useRef as useRef2, useState as useState3 } from "react";
|
|
193
192
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
193
|
+
import { createElement } from "react";
|
|
194
194
|
function Tabs({
|
|
195
195
|
items,
|
|
196
196
|
activeKey,
|
|
@@ -225,6 +225,42 @@ function Tabs({
|
|
|
225
225
|
const sliding = ["capsule", "line", "underline", "tech", "tech-line"].includes(type);
|
|
226
226
|
const listRef = useRef2(null);
|
|
227
227
|
const indicatorRef = useRef2(null);
|
|
228
|
+
const moreRef = useRef2(null);
|
|
229
|
+
const [overflow, setOverflow] = useState3({ count: items.length, width: 0 });
|
|
230
|
+
const [moreOpen, setMoreOpen] = useState3(false);
|
|
231
|
+
const visibleCount = resolvedOrientation === "horizontal" ? overflow.count : items.length;
|
|
232
|
+
const hiddenItems = items.slice(visibleCount);
|
|
233
|
+
useLayoutEffect2(() => {
|
|
234
|
+
const list = listRef.current;
|
|
235
|
+
if (!list || resolvedOrientation !== "horizontal") return;
|
|
236
|
+
const entries = Array.from(list.children).filter((node) => node instanceof HTMLElement && node.hasAttribute("data-tab-entry"));
|
|
237
|
+
const measure = () => {
|
|
238
|
+
const css = getComputedStyle(list);
|
|
239
|
+
const gap = parseFloat(css.columnGap) || 0;
|
|
240
|
+
const padding = (parseFloat(css.paddingLeft) || 0) + (parseFloat(css.paddingRight) || 0);
|
|
241
|
+
const widths = entries.map((node) => node.getBoundingClientRect().width);
|
|
242
|
+
const total = widths.reduce((sum, width2) => sum + width2, 0) + gap * Math.max(0, widths.length - 1);
|
|
243
|
+
const available = Math.max(0, list.clientWidth - padding);
|
|
244
|
+
let count = widths.length;
|
|
245
|
+
if (total > available + 0.5) {
|
|
246
|
+
const moreWidth = moreRef.current?.getBoundingClientRect().width ?? 36;
|
|
247
|
+
let used = moreWidth;
|
|
248
|
+
count = 0;
|
|
249
|
+
for (const width2 of widths) {
|
|
250
|
+
if (used + gap + width2 > available + 0.5) break;
|
|
251
|
+
used += gap + width2;
|
|
252
|
+
count++;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const width = Math.ceil(total + padding + (parseFloat(css.borderLeftWidth) || 0) + (parseFloat(css.borderRightWidth) || 0));
|
|
256
|
+
setOverflow((previous) => previous.count === count && previous.width === width ? previous : { count, width });
|
|
257
|
+
};
|
|
258
|
+
measure();
|
|
259
|
+
const observer = new ResizeObserver(measure);
|
|
260
|
+
observer.observe(list);
|
|
261
|
+
entries.forEach((entry) => observer.observe(entry));
|
|
262
|
+
return () => observer.disconnect();
|
|
263
|
+
}, [items, type, size, closable, resolvedOrientation, tabBarTitle, tabBarExtraContent]);
|
|
228
264
|
const [contentState, setContentState] = useState3(() => ({ key: selectedKey, visited: /* @__PURE__ */ new Set([selectedKey]) }));
|
|
229
265
|
const settledKeyRef = useRef2(selectedKey);
|
|
230
266
|
const afterChangeRef = useRef2(onAfterChange);
|
|
@@ -239,16 +275,12 @@ function Tabs({
|
|
|
239
275
|
function updateIndicator() {
|
|
240
276
|
if (!list || !indicator) return;
|
|
241
277
|
const active = list.querySelector('[role="tab"][aria-selected="true"]');
|
|
242
|
-
if (!active) {
|
|
278
|
+
if (!active || active.closest('[data-tab-hidden="true"]')) {
|
|
243
279
|
indicator.style.visibility = "hidden";
|
|
244
280
|
return;
|
|
245
281
|
}
|
|
246
282
|
const listRect = list.getBoundingClientRect();
|
|
247
283
|
const rect = active.getBoundingClientRect();
|
|
248
|
-
if (type === "tech-line" && resolvedOrientation === "horizontal") {
|
|
249
|
-
if (rect.left < listRect.left) list.scrollLeft += rect.left - listRect.left;
|
|
250
|
-
else if (rect.right > listRect.right) list.scrollLeft += rect.right - listRect.right;
|
|
251
|
-
}
|
|
252
284
|
const currentRect = active.getBoundingClientRect();
|
|
253
285
|
indicator.style.transform = `translate(${currentRect.left - listRect.left - list.clientLeft + list.scrollLeft}px, ${currentRect.top - listRect.top - list.clientTop + list.scrollTop}px)`;
|
|
254
286
|
indicator.style.width = `${rect.width}px`;
|
|
@@ -264,7 +296,7 @@ function Tabs({
|
|
|
264
296
|
observer.observe(list);
|
|
265
297
|
list.querySelectorAll('[role="tab"]').forEach((tab) => observer.observe(tab));
|
|
266
298
|
return () => observer.disconnect();
|
|
267
|
-
}, [sliding, type, selectedKey, items, size, resolvedPosition, centered, closable]);
|
|
299
|
+
}, [sliding, type, selectedKey, items, size, resolvedPosition, centered, closable, visibleCount]);
|
|
268
300
|
useEffect(() => {
|
|
269
301
|
let cancelled = false;
|
|
270
302
|
let frame = 0;
|
|
@@ -298,7 +330,8 @@ function Tabs({
|
|
|
298
330
|
}
|
|
299
331
|
function focusAndSelect(key) {
|
|
300
332
|
selectTab(key);
|
|
301
|
-
|
|
333
|
+
if (items.findIndex((item) => item.key === key) >= visibleCount) moreRef.current?.focus();
|
|
334
|
+
else document.getElementById(`${baseId}-tab-${key}`)?.focus();
|
|
302
335
|
}
|
|
303
336
|
function handleKeyDown(event, key) {
|
|
304
337
|
const previousKey = resolvedOrientation === "horizontal" ? "ArrowLeft" : "ArrowUp";
|
|
@@ -320,54 +353,53 @@ function Tabs({
|
|
|
320
353
|
...withTitleTooltip(props),
|
|
321
354
|
children: [
|
|
322
355
|
/* @__PURE__ */ jsxs4("div", { className: "sia-tabs__header", children: [
|
|
323
|
-
/* @__PURE__ */ jsx4(FloatingScrollbarProvider, { targetRef: listRef, disabled: type !== "tech-line" || resolvedOrientation !== "horizontal" }),
|
|
324
356
|
tabBarTitle ? /* @__PURE__ */ jsxs4("div", { className: "sia-tabs__title", children: [
|
|
325
357
|
tabBarTitle,
|
|
326
358
|
type === "tech-line" ? /* @__PURE__ */ jsx4("svg", { className: "sia-tabs__title-connector", viewBox: "0 0 32 40", "aria-hidden": "true", children: /* @__PURE__ */ jsx4("path", { d: "M0 39.25 H5 Q8 39.25 10 35.25 L28 3.75 Q29 1.75 32 1.75", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinejoin: "round" }) }) : null
|
|
327
359
|
] }) : null,
|
|
328
|
-
/* @__PURE__ */ jsxs4("div", { ref: listRef, className: `sia-tabs__list${sliding ? " sia-tabs__list--sliding" : ""}`, role: "tablist", "aria-orientation": resolvedOrientation, children: [
|
|
360
|
+
/* @__PURE__ */ jsxs4("div", { ref: listRef, style: resolvedOrientation === "horizontal" && overflow.width ? { width: overflow.width } : void 0, className: `sia-tabs__list${sliding ? " sia-tabs__list--sliding" : ""}`, role: "tablist", "aria-orientation": resolvedOrientation, children: [
|
|
329
361
|
sliding ? /* @__PURE__ */ jsx4("span", { ref: indicatorRef, className: `sia-tabs__indicator${type === "capsule" ? " sia-tabs__capsule-indicator" : ""}`, "aria-hidden": "true", children: type === "tech-line" ? /* @__PURE__ */ jsx4("span", { className: "sia-tabs__indicator-shape", "aria-hidden": "true" }) : null }, type) : null,
|
|
330
|
-
items.map((item) => {
|
|
362
|
+
items.map((item, index) => {
|
|
331
363
|
const selected = item.key === selectedKey;
|
|
332
364
|
const canClose = item.closable ?? closable;
|
|
333
|
-
const tabNode = /* @__PURE__ */ jsxs4("span", { className: `sia-tabs__tab-wrap${canClose ? " is-closable" : ""}`, children: [
|
|
334
|
-
/* @__PURE__ */ jsxs4(
|
|
335
|
-
"button",
|
|
336
|
-
{
|
|
337
|
-
id: `${baseId}-tab-${item.key}`,
|
|
338
|
-
type: "button",
|
|
339
|
-
className: "sia-tabs__tab",
|
|
340
|
-
role: "tab",
|
|
341
|
-
"aria-selected": selected,
|
|
342
|
-
"aria-controls": hasPanels ? `${baseId}-panel-${item.key}` : void 0,
|
|
343
|
-
tabIndex: selected ? 0 : -1,
|
|
344
|
-
disabled: item.disabled,
|
|
345
|
-
onClick: () => selectTab(item.key),
|
|
346
|
-
onKeyDown: (event) => handleKeyDown(event, item.key),
|
|
347
|
-
children: [
|
|
348
|
-
type === "tech-line" ? /* @__PURE__ */ jsx4("span", { className: "sia-tabs__tab-shape", "aria-hidden": "true" }) : null,
|
|
349
|
-
item.icon ? /* @__PURE__ */ jsx4("span", { className: "sia-tabs__icon", children: item.icon }) : null,
|
|
350
|
-
/* @__PURE__ */ jsx4("span", { children: item.label })
|
|
351
|
-
]
|
|
352
|
-
}
|
|
353
|
-
),
|
|
354
|
-
canClose ? /* @__PURE__ */ jsx4(
|
|
355
|
-
"button",
|
|
356
|
-
{
|
|
357
|
-
type: "button",
|
|
358
|
-
className: "sia-tabs__close",
|
|
359
|
-
"aria-label": `\u5173\u95ED${typeof item.label === "string" ? item.label : "\u6807\u7B7E\u9875"}`,
|
|
360
|
-
disabled: item.disabled,
|
|
361
|
-
onClick: () => onEdit?.(item.key, "remove"),
|
|
362
|
-
children: /* @__PURE__ */ jsx4(Icon, { name: "close", size: 12 })
|
|
363
|
-
}
|
|
364
|
-
) : null
|
|
365
|
-
] }, item.key);
|
|
366
365
|
const contextMenuItems = typeof tabContextMenu === "function" ? tabContextMenu(item) : tabContextMenu;
|
|
366
|
+
const entryProps = { "data-tab-entry": "", "data-tab-hidden": index >= visibleCount, "aria-hidden": index >= visibleCount || void 0 };
|
|
367
|
+
const tabNode = /* @__PURE__ */ createElement("span", { ...!contextMenuItems?.length ? entryProps : {}, className: `sia-tabs__tab-wrap${canClose ? " is-closable" : ""}`, key: item.key }, /* @__PURE__ */ jsxs4(
|
|
368
|
+
"button",
|
|
369
|
+
{
|
|
370
|
+
id: `${baseId}-tab-${item.key}`,
|
|
371
|
+
type: "button",
|
|
372
|
+
className: "sia-tabs__tab",
|
|
373
|
+
role: "tab",
|
|
374
|
+
"aria-selected": selected,
|
|
375
|
+
"aria-controls": hasPanels ? `${baseId}-panel-${item.key}` : void 0,
|
|
376
|
+
tabIndex: selected ? 0 : -1,
|
|
377
|
+
disabled: item.disabled,
|
|
378
|
+
onClick: () => selectTab(item.key),
|
|
379
|
+
onKeyDown: (event) => handleKeyDown(event, item.key),
|
|
380
|
+
children: [
|
|
381
|
+
type === "tech-line" ? /* @__PURE__ */ jsx4("span", { className: "sia-tabs__tab-shape", "aria-hidden": "true" }) : null,
|
|
382
|
+
item.icon ? /* @__PURE__ */ jsx4("span", { className: "sia-tabs__icon", children: item.icon }) : null,
|
|
383
|
+
/* @__PURE__ */ jsx4("span", { children: item.label })
|
|
384
|
+
]
|
|
385
|
+
}
|
|
386
|
+
), canClose ? /* @__PURE__ */ jsx4(
|
|
387
|
+
"button",
|
|
388
|
+
{
|
|
389
|
+
type: "button",
|
|
390
|
+
className: "sia-tabs__close",
|
|
391
|
+
"aria-label": `\u5173\u95ED${typeof item.label === "string" ? item.label : "\u6807\u7B7E\u9875"}`,
|
|
392
|
+
disabled: item.disabled,
|
|
393
|
+
onClick: () => onEdit?.(item.key, "remove"),
|
|
394
|
+
children: /* @__PURE__ */ jsx4(Icon, { name: "close", size: 12 })
|
|
395
|
+
}
|
|
396
|
+
) : null);
|
|
367
397
|
if (!contextMenuItems?.length) return tabNode;
|
|
368
|
-
return /* @__PURE__ */
|
|
398
|
+
return /* @__PURE__ */ createElement(
|
|
369
399
|
Dropdown,
|
|
370
400
|
{
|
|
401
|
+
...entryProps,
|
|
402
|
+
key: item.key,
|
|
371
403
|
className: "sia-tabs__tab-context-trigger",
|
|
372
404
|
popupClassName: "sia-tabs__tab-context-menu",
|
|
373
405
|
trigger: ["contextMenu"],
|
|
@@ -376,12 +408,26 @@ function Tabs({
|
|
|
376
408
|
items: contextMenuItems,
|
|
377
409
|
selectable: false,
|
|
378
410
|
onClick: (info) => onTabContextMenuClick?.({ ...info, tabKey: item.key, tab: item })
|
|
379
|
-
}
|
|
380
|
-
children: tabNode
|
|
411
|
+
}
|
|
381
412
|
},
|
|
382
|
-
|
|
413
|
+
tabNode
|
|
383
414
|
);
|
|
384
|
-
})
|
|
415
|
+
}),
|
|
416
|
+
resolvedOrientation === "horizontal" ? /* @__PURE__ */ jsx4(
|
|
417
|
+
Dropdown,
|
|
418
|
+
{
|
|
419
|
+
className: "sia-tabs__more",
|
|
420
|
+
"data-tab-hidden": !hiddenItems.length,
|
|
421
|
+
trigger: ["hover", "click"],
|
|
422
|
+
placement: "bottomRight",
|
|
423
|
+
showTriggerIcon: false,
|
|
424
|
+
autoFocus: true,
|
|
425
|
+
open: moreOpen && hiddenItems.length > 0,
|
|
426
|
+
onOpenChange: setMoreOpen,
|
|
427
|
+
menu: { items: hiddenItems.map((item) => ({ key: item.key, label: item.label, icon: item.icon, disabled: item.disabled })), selectedKeys: [selectedKey], onClick: (info) => selectTab(info.key) },
|
|
428
|
+
children: /* @__PURE__ */ jsx4(Button, { ref: moreRef, variant: "text", icon: /* @__PURE__ */ jsx4(Icon, { name: "more-horizontal" }), "aria-label": "\u66F4\u591A\u9009\u9879\u5361", onKeyDown: (event) => handleKeyDown(event, selectedKey), className: hiddenItems.some((item) => item.key === selectedKey) ? "is-active" : void 0 })
|
|
429
|
+
}
|
|
430
|
+
) : null
|
|
385
431
|
] }),
|
|
386
432
|
tabBarExtraContent ? /* @__PURE__ */ jsx4("div", { className: "sia-tabs__extra", children: tabBarExtraContent }) : null
|
|
387
433
|
] }),
|