@mshafiqyajid/react-tabs 0.2.0 → 0.3.1
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/README.md +8 -0
- package/dist/styled.cjs +169 -30
- package/dist/styled.cjs.map +1 -1
- package/dist/styled.d.cts +11 -0
- package/dist/styled.d.ts +11 -0
- package/dist/styled.js +170 -31
- package/dist/styled.js.map +1 -1
- package/dist/styles.css +88 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -112,3 +112,11 @@ Add `data-theme="dark"` to a parent element (or `data-rtab-theme="dark"` for com
|
|
|
112
112
|
## License
|
|
113
113
|
|
|
114
114
|
MIT
|
|
115
|
+
|
|
116
|
+
## What's new in 0.3.0
|
|
117
|
+
|
|
118
|
+
- **Closeable tabs** — `tab.closable?: boolean` renders a × button; pair with `onTabClose(value)`.
|
|
119
|
+
- **Scrollable overflow** — `scrollable: true` keeps tabs on one line and renders chevron scroll buttons at the edges instead of wrapping.
|
|
120
|
+
- **Drag-to-reorder** — `sortable: true` + `onReorder(values: string[])`. HTML5 DnD, no external dep.
|
|
121
|
+
- **Keyboard typeahead** — letters jump to the first matching tab whose label starts with the buffer (600 ms reset).
|
|
122
|
+
- **`scrollActiveIntoView`** — default `true` when `scrollable`. Keeps the active tab in the viewport on activation.
|
package/dist/styled.cjs
CHANGED
|
@@ -183,10 +183,23 @@ var TabsStyled = react.forwardRef(
|
|
|
183
183
|
orientation = "horizontal",
|
|
184
184
|
lazyMount = false,
|
|
185
185
|
forceMount = false,
|
|
186
|
+
onTabClose,
|
|
187
|
+
scrollable = false,
|
|
188
|
+
sortable = false,
|
|
189
|
+
onReorder,
|
|
190
|
+
scrollActiveIntoView,
|
|
186
191
|
renderTab,
|
|
187
192
|
renderPanel,
|
|
188
193
|
className
|
|
189
194
|
}, ref) {
|
|
195
|
+
const autoScrollActive = scrollActiveIntoView ?? scrollable;
|
|
196
|
+
const [scrollState, setScrollState] = react.useState({
|
|
197
|
+
left: false,
|
|
198
|
+
right: false
|
|
199
|
+
});
|
|
200
|
+
const typeaheadBufferRef = react.useRef("");
|
|
201
|
+
const typeaheadTimerRef = react.useRef(null);
|
|
202
|
+
const dragValueRef = react.useRef(null);
|
|
190
203
|
const tabDefs = tabs.map((t) => ({ value: t.value, disabled: t.disabled }));
|
|
191
204
|
const resolvedDefault = defaultValue ?? tabs.find((t) => !t.disabled)?.value;
|
|
192
205
|
const { activeValue, getTabProps, getPanelProps } = useTabs({
|
|
@@ -202,43 +215,169 @@ var TabsStyled = react.forwardRef(
|
|
|
202
215
|
const activatedRef = react.useRef(/* @__PURE__ */ new Set());
|
|
203
216
|
if (activeValue !== void 0) activatedRef.current.add(activeValue);
|
|
204
217
|
const rootClass = ["rtab-root", className].filter(Boolean).join(" ");
|
|
218
|
+
react.useEffect(() => {
|
|
219
|
+
if (!scrollable) return;
|
|
220
|
+
const list = tabListRef.current;
|
|
221
|
+
if (!list) return;
|
|
222
|
+
const update = () => {
|
|
223
|
+
setScrollState({
|
|
224
|
+
left: list.scrollLeft > 4,
|
|
225
|
+
right: list.scrollLeft + list.clientWidth < list.scrollWidth - 4
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
update();
|
|
229
|
+
list.addEventListener("scroll", update, { passive: true });
|
|
230
|
+
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(update) : null;
|
|
231
|
+
ro?.observe(list);
|
|
232
|
+
return () => {
|
|
233
|
+
list.removeEventListener("scroll", update);
|
|
234
|
+
ro?.disconnect();
|
|
235
|
+
};
|
|
236
|
+
}, [scrollable, tabs.length]);
|
|
237
|
+
react.useEffect(() => {
|
|
238
|
+
if (!autoScrollActive || !activeValue) return;
|
|
239
|
+
const list = tabListRef.current;
|
|
240
|
+
if (!list) return;
|
|
241
|
+
const activeEl = list.querySelector(`[aria-selected="true"]`);
|
|
242
|
+
if (!activeEl) return;
|
|
243
|
+
activeEl.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
|
|
244
|
+
}, [autoScrollActive, activeValue]);
|
|
245
|
+
const scrollByAmount = (delta) => {
|
|
246
|
+
tabListRef.current?.scrollBy({ left: delta, behavior: "smooth" });
|
|
247
|
+
};
|
|
248
|
+
const handleTypeahead = (e) => {
|
|
249
|
+
if (e.key.length !== 1 || e.altKey || e.ctrlKey || e.metaKey) return;
|
|
250
|
+
typeaheadBufferRef.current = (typeaheadBufferRef.current + e.key).toLowerCase();
|
|
251
|
+
if (typeaheadTimerRef.current) clearTimeout(typeaheadTimerRef.current);
|
|
252
|
+
typeaheadTimerRef.current = setTimeout(() => {
|
|
253
|
+
typeaheadBufferRef.current = "";
|
|
254
|
+
}, 600);
|
|
255
|
+
const buffer = typeaheadBufferRef.current;
|
|
256
|
+
const startIdx = Math.max(0, tabs.findIndex((t) => t.value === activeValue));
|
|
257
|
+
for (let i = 1; i <= tabs.length; i++) {
|
|
258
|
+
const idx = (startIdx + i) % tabs.length;
|
|
259
|
+
const tab = tabs[idx];
|
|
260
|
+
if (!tab || tab.disabled) continue;
|
|
261
|
+
const labelStr = typeof tab.label === "string" ? tab.label : "";
|
|
262
|
+
if (labelStr.toLowerCase().startsWith(buffer)) {
|
|
263
|
+
const list = tabListRef.current;
|
|
264
|
+
const btn = list?.querySelector(`[data-value="${tab.value}"]`);
|
|
265
|
+
btn?.click();
|
|
266
|
+
btn?.focus();
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
const handleDragStart = (val) => (e) => {
|
|
272
|
+
if (!sortable) return;
|
|
273
|
+
dragValueRef.current = val;
|
|
274
|
+
e.dataTransfer.effectAllowed = "move";
|
|
275
|
+
};
|
|
276
|
+
const handleDragOver = (val) => (e) => {
|
|
277
|
+
if (!sortable || !dragValueRef.current || dragValueRef.current === val) return;
|
|
278
|
+
e.preventDefault();
|
|
279
|
+
e.dataTransfer.dropEffect = "move";
|
|
280
|
+
};
|
|
281
|
+
const handleDrop = (val) => (e) => {
|
|
282
|
+
if (!sortable) return;
|
|
283
|
+
e.preventDefault();
|
|
284
|
+
const from = dragValueRef.current;
|
|
285
|
+
dragValueRef.current = null;
|
|
286
|
+
if (!from || from === val || !onReorder) return;
|
|
287
|
+
const order = tabs.map((t) => t.value);
|
|
288
|
+
const fromIdx = order.indexOf(from);
|
|
289
|
+
const toIdx = order.indexOf(val);
|
|
290
|
+
if (fromIdx === -1 || toIdx === -1) return;
|
|
291
|
+
const next = [...order];
|
|
292
|
+
next.splice(fromIdx, 1);
|
|
293
|
+
next.splice(toIdx, 0, from);
|
|
294
|
+
onReorder(next);
|
|
295
|
+
};
|
|
205
296
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
206
297
|
"div",
|
|
207
298
|
{
|
|
208
299
|
ref,
|
|
209
300
|
className: rootClass,
|
|
210
301
|
"data-orientation": orientation,
|
|
302
|
+
"data-scrollable": scrollable || void 0,
|
|
303
|
+
onKeyDown: handleTypeahead,
|
|
211
304
|
children: [
|
|
212
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
305
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rtab-list-wrap", children: [
|
|
306
|
+
scrollable && scrollState.left && /* @__PURE__ */ jsxRuntime.jsx(
|
|
307
|
+
"button",
|
|
308
|
+
{
|
|
309
|
+
type: "button",
|
|
310
|
+
className: "rtab-scroll-btn rtab-scroll-btn--left",
|
|
311
|
+
"aria-label": "Scroll left",
|
|
312
|
+
onClick: () => scrollByAmount(-200),
|
|
313
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7.5 3l-3 3 3 3" }) })
|
|
314
|
+
}
|
|
315
|
+
),
|
|
316
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
317
|
+
"div",
|
|
318
|
+
{
|
|
319
|
+
ref: tabListRef,
|
|
320
|
+
role: "tablist",
|
|
321
|
+
"aria-orientation": orientation,
|
|
322
|
+
className: "rtab-list",
|
|
323
|
+
"data-variant": variant,
|
|
324
|
+
"data-size": size,
|
|
325
|
+
"data-tone": tone,
|
|
326
|
+
"data-orientation": orientation,
|
|
327
|
+
"data-scrollable": scrollable || void 0,
|
|
328
|
+
style: indicatorStyle,
|
|
329
|
+
children: [
|
|
330
|
+
tabs.map((tab, index) => {
|
|
331
|
+
const isActive = activeValue === tab.value;
|
|
332
|
+
const isDisabled = !!tab.disabled;
|
|
333
|
+
const tabProps = getTabProps(tab.value, { disabled: tab.disabled });
|
|
334
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
335
|
+
"button",
|
|
336
|
+
{
|
|
337
|
+
"data-value": tab.value,
|
|
338
|
+
"data-closable": tab.closable || void 0,
|
|
339
|
+
className: "rtab-tab",
|
|
340
|
+
...tabProps,
|
|
341
|
+
draggable: sortable && !isDisabled ? true : void 0,
|
|
342
|
+
onDragStart: sortable ? handleDragStart(tab.value) : void 0,
|
|
343
|
+
onDragOver: sortable ? handleDragOver(tab.value) : void 0,
|
|
344
|
+
onDrop: sortable ? handleDrop(tab.value) : void 0,
|
|
345
|
+
children: [
|
|
346
|
+
renderTab ? renderTab({ tab, index, isActive, isDisabled }) : tab.label,
|
|
347
|
+
tab.closable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
348
|
+
"span",
|
|
349
|
+
{
|
|
350
|
+
className: "rtab-close",
|
|
351
|
+
role: "button",
|
|
352
|
+
tabIndex: -1,
|
|
353
|
+
"aria-label": `Close ${typeof tab.label === "string" ? tab.label : "tab"}`,
|
|
354
|
+
onClick: (e) => {
|
|
355
|
+
e.stopPropagation();
|
|
356
|
+
onTabClose?.(tab.value);
|
|
357
|
+
},
|
|
358
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", width: "10", height: "10", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 3l6 6M9 3l-6 6" }) })
|
|
359
|
+
}
|
|
360
|
+
)
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
tab.value
|
|
364
|
+
);
|
|
365
|
+
}),
|
|
366
|
+
(variant === "line" || variant === "solid" || variant === "pill") && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rtab-indicator", "aria-hidden": "true" })
|
|
367
|
+
]
|
|
368
|
+
}
|
|
369
|
+
),
|
|
370
|
+
scrollable && scrollState.right && /* @__PURE__ */ jsxRuntime.jsx(
|
|
371
|
+
"button",
|
|
372
|
+
{
|
|
373
|
+
type: "button",
|
|
374
|
+
className: "rtab-scroll-btn rtab-scroll-btn--right",
|
|
375
|
+
"aria-label": "Scroll right",
|
|
376
|
+
onClick: () => scrollByAmount(200),
|
|
377
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4.5 3l3 3-3 3" }) })
|
|
378
|
+
}
|
|
379
|
+
)
|
|
380
|
+
] }),
|
|
242
381
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rtab-panels", children: tabs.map((tab) => {
|
|
243
382
|
const isActive = activeValue === tab.value;
|
|
244
383
|
const shouldRender = forceMount || !lazyMount || activatedRef.current.has(tab.value);
|
package/dist/styled.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/useTabs.ts","../src/styled/TabsStyled.tsx"],"names":["useRef","useState","useCallback","useMemo","useLayoutEffect","useEffect","forwardRef","TabsStyled","jsxs","jsx"],"mappings":"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","file":"styled.cjs","sourcesContent":["import {\n type HTMLAttributes,\n type KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport type TabsActivation = \"automatic\" | \"manual\";\nexport type TabsOrientation = \"horizontal\" | \"vertical\";\nexport type TabsChangeReason = \"click\" | \"keyboard\" | \"programmatic\";\n\nexport interface UseTabsTab {\n value: string;\n disabled?: boolean;\n}\n\nexport interface UseTabsOptions {\n /** Tab definitions — needed for keyboard navigation between tabs. */\n tabs?: UseTabsTab[];\n /** Controlled active value. */\n value?: string;\n /** Initial active value when uncontrolled. */\n defaultValue?: string;\n /** Called when the active tab changes. Optional second arg reports the trigger reason. */\n onChange?: (value: string, reason: TabsChangeReason) => void;\n /** \"automatic\" (default) — arrow keys move focus AND activate. \"manual\" — arrows move focus only; Enter/Space activates. */\n activation?: TabsActivation;\n /** Affects keyboard nav. Default \"horizontal\". */\n orientation?: TabsOrientation;\n}\n\nexport interface TabProps extends HTMLAttributes<HTMLButtonElement> {\n id: string;\n role: \"tab\";\n \"aria-selected\": boolean;\n \"aria-controls\": string;\n \"aria-disabled\"?: boolean;\n \"data-state\": \"active\" | \"inactive\";\n tabIndex: number;\n}\n\nexport interface PanelProps extends HTMLAttributes<HTMLDivElement> {\n id: string;\n role: \"tabpanel\";\n \"aria-labelledby\": string;\n \"data-state\": \"active\" | \"inactive\";\n hidden: boolean;\n}\n\nexport interface UseTabsResult {\n /** Currently active tab value. */\n activeValue: string | undefined;\n /** Returns props to spread onto a tab trigger `<button>`. */\n getTabProps: (value: string, options?: { disabled?: boolean }) => TabProps;\n /** Returns props to spread onto a tab panel. */\n getPanelProps: (value: string) => PanelProps;\n /** Programmatically set the active tab. */\n setActiveValue: (value: string) => void;\n}\n\nconst tabId = (listId: string, value: string) => `${listId}-tab-${value}`;\nconst panelId = (listId: string, value: string) => `${listId}-panel-${value}`;\n\nlet counter = 0;\nfunction useStableId() {\n const ref = useRef<string | null>(null);\n if (ref.current === null) {\n ref.current = `rtabs-${++counter}`;\n }\n return ref.current;\n}\n\nexport function useTabs(opts: UseTabsOptions = {}): UseTabsResult {\n const {\n tabs = [],\n value: controlledValue,\n defaultValue,\n onChange,\n activation = \"automatic\",\n orientation = \"horizontal\",\n } = opts;\n\n const listId = useStableId();\n const isControlled = controlledValue !== undefined;\n\n const [internalValue, setInternalValue] = useState<string | undefined>(\n defaultValue,\n );\n\n const activeValue = isControlled ? controlledValue : internalValue;\n\n const tabRefs = useRef<Map<string, HTMLButtonElement>>(new Map());\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n const setActiveValue = useCallback(\n (next: string, reason: TabsChangeReason = \"programmatic\") => {\n const tab = tabs.find((t) => t.value === next);\n if (tab?.disabled) return;\n if (isControlled) {\n if (next !== controlledValue) onChangeRef.current?.(next, reason);\n } else {\n if (next === internalValue) return;\n setInternalValue(next);\n onChangeRef.current?.(next, reason);\n }\n },\n [tabs, isControlled, controlledValue, internalValue],\n );\n\n const focusTab = useCallback((value: string) => {\n tabRefs.current.get(value)?.focus();\n }, []);\n\n const handleKeyDown = useCallback(\n (currentValue: string) =>\n (event: KeyboardEvent<HTMLButtonElement>) => {\n const enabled = tabs.filter((t) => !t.disabled);\n if (enabled.length === 0) return;\n\n const currentIndex = enabled.findIndex((t) => t.value === currentValue);\n\n const isForward =\n orientation === \"vertical\"\n ? event.key === \"ArrowDown\"\n : event.key === \"ArrowRight\";\n const isBackward =\n orientation === \"vertical\"\n ? event.key === \"ArrowUp\"\n : event.key === \"ArrowLeft\";\n\n let nextValue: string | undefined;\n\n if (isForward) {\n const nextIndex = (currentIndex + 1) % enabled.length;\n nextValue = enabled[nextIndex]?.value;\n } else if (isBackward) {\n const prevIndex = (currentIndex - 1 + enabled.length) % enabled.length;\n nextValue = enabled[prevIndex]?.value;\n } else if (event.key === \"Home\") {\n nextValue = enabled[0]?.value;\n } else if (event.key === \"End\") {\n nextValue = enabled[enabled.length - 1]?.value;\n } else if (\n activation === \"manual\" &&\n (event.key === \"Enter\" || event.key === \" \")\n ) {\n event.preventDefault();\n setActiveValue(currentValue, \"keyboard\");\n return;\n } else {\n return;\n }\n\n if (nextValue === undefined || nextValue === currentValue) return;\n event.preventDefault();\n focusTab(nextValue);\n if (activation === \"automatic\") {\n setActiveValue(nextValue, \"keyboard\");\n }\n },\n [tabs, orientation, activation, setActiveValue, focusTab],\n );\n\n const getTabProps = useCallback(\n (value: string, options?: { disabled?: boolean }): TabProps => {\n const isDisabled =\n options?.disabled ?? tabs.find((t) => t.value === value)?.disabled;\n const isSelected = activeValue === value;\n return {\n id: tabId(listId, value),\n role: \"tab\",\n \"aria-selected\": isSelected,\n \"aria-controls\": panelId(listId, value),\n \"aria-disabled\": isDisabled || undefined,\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n tabIndex: isSelected ? 0 : -1,\n disabled: isDisabled,\n ref: (node: HTMLButtonElement | null) => {\n if (node) {\n tabRefs.current.set(value, node);\n } else {\n tabRefs.current.delete(value);\n }\n },\n onClick: () => {\n if (!isDisabled) setActiveValue(value, \"click\");\n },\n onKeyDown: handleKeyDown(value),\n } as TabProps & {\n disabled: boolean | undefined;\n ref: (node: HTMLButtonElement | null) => void;\n };\n },\n [activeValue, listId, tabs, setActiveValue, handleKeyDown],\n );\n\n const getPanelProps = useCallback(\n (value: string): PanelProps => {\n const isActive = activeValue === value;\n return {\n id: panelId(listId, value),\n role: \"tabpanel\",\n \"aria-labelledby\": tabId(listId, value),\n \"data-state\": isActive ? \"active\" : \"inactive\",\n hidden: !isActive,\n tabIndex: 0,\n };\n },\n [activeValue, listId],\n );\n\n return useMemo(\n () => ({ activeValue, getTabProps, getPanelProps, setActiveValue }),\n [activeValue, getTabProps, getPanelProps, setActiveValue],\n );\n}\n","import {\n type CSSProperties,\n type ReactNode,\n forwardRef,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n useTabs,\n type TabsActivation,\n type TabsChangeReason,\n type TabsOrientation,\n} from \"../useTabs\";\n\nexport type TabsVariant = \"line\" | \"solid\" | \"pill\";\nexport type TabsSize = \"sm\" | \"md\" | \"lg\";\nexport type TabsTone = \"neutral\" | \"primary\" | \"success\" | \"danger\";\n\nexport interface TabItem {\n value: string;\n label: ReactNode;\n content: ReactNode;\n disabled?: boolean;\n}\n\nexport interface TabsRenderTabContext {\n tab: TabItem;\n index: number;\n isActive: boolean;\n isDisabled: boolean;\n}\n\nexport interface TabsRenderPanelContext {\n tab: TabItem;\n isActive: boolean;\n}\n\nexport interface TabsStyledProps {\n tabs: TabItem[];\n variant?: TabsVariant;\n size?: TabsSize;\n tone?: TabsTone;\n defaultValue?: string;\n value?: string;\n /** Optional second arg reports the trigger reason (\"click\" | \"keyboard\" | \"programmatic\"). */\n onChange?: (value: string, reason: TabsChangeReason) => void;\n /** \"automatic\" (default) — arrow keys move focus AND activate. \"manual\" — arrows move focus only. */\n activation?: TabsActivation;\n /** Affects keyboard nav direction. Default \"horizontal\". */\n orientation?: TabsOrientation;\n /** Only mount panels after they've been activated at least once. Default: false (all panels mount eagerly). */\n lazyMount?: boolean;\n /** Keep all panels mounted regardless of activation (useful with `lazyMount` overrides). Default: false. */\n forceMount?: boolean;\n /** Replace the default tab button content. The button shell (a11y, ref, key) stays owned by the component. */\n renderTab?: (ctx: TabsRenderTabContext) => ReactNode;\n /** Replace the default panel rendering. */\n renderPanel?: (ctx: TabsRenderPanelContext) => ReactNode;\n className?: string;\n}\n\n// Run layout effects on the client; fall back to a no-op effect on the server.\nconst useIsoLayoutEffect =\n typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\nfunction useIndicator(\n tabListRef: React.RefObject<HTMLDivElement | null>,\n activeValue: string | undefined,\n orientation: TabsOrientation,\n) {\n const [style, setStyle] = useState<CSSProperties>({});\n\n useIsoLayoutEffect(() => {\n if (!tabListRef.current || activeValue === undefined) return;\n\n const measure = () => {\n const list = tabListRef.current;\n if (!list) return;\n const activeTab = list.querySelector<HTMLElement>(\n `[aria-selected=\"true\"]`,\n );\n if (!activeTab) return;\n\n const listRect = list.getBoundingClientRect();\n const tabRect = activeTab.getBoundingClientRect();\n\n if (orientation === \"vertical\") {\n const y = tabRect.top - listRect.top;\n const h = tabRect.height;\n setStyle({\n [\"--rtab-indicator-y\" as string]: `${y}px`,\n [\"--rtab-indicator-height\" as string]: `${h}px`,\n [\"--rtab-indicator-ready\" as string]: \"1\",\n });\n } else {\n const x = tabRect.left - listRect.left;\n const w = tabRect.width;\n setStyle({\n [\"--rtab-indicator-x\" as string]: `${x}px`,\n [\"--rtab-indicator-width\" as string]: `${w}px`,\n [\"--rtab-indicator-ready\" as string]: \"1\",\n });\n }\n };\n\n measure();\n\n if (typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(measure);\n ro.observe(tabListRef.current);\n return () => ro.disconnect();\n }, [activeValue, tabListRef, orientation]);\n\n return style;\n}\n\nexport const TabsStyled = forwardRef<HTMLDivElement, TabsStyledProps>(\n function TabsStyled(\n {\n tabs,\n variant = \"line\",\n size = \"md\",\n tone = \"neutral\",\n defaultValue,\n value,\n onChange,\n activation = \"automatic\",\n orientation = \"horizontal\",\n lazyMount = false,\n forceMount = false,\n renderTab,\n renderPanel,\n className,\n },\n ref,\n ) {\n const tabDefs = tabs.map((t) => ({ value: t.value, disabled: t.disabled }));\n\n const resolvedDefault =\n defaultValue ?? tabs.find((t) => !t.disabled)?.value;\n\n const { activeValue, getTabProps, getPanelProps } = useTabs({\n tabs: tabDefs,\n defaultValue: value === undefined ? resolvedDefault : undefined,\n value,\n onChange,\n activation,\n orientation,\n });\n\n const tabListRef = useRef<HTMLDivElement>(null);\n const indicatorStyle = useIndicator(tabListRef, activeValue, orientation);\n\n // Track which tabs have been activated for lazyMount.\n const activatedRef = useRef<Set<string>>(new Set());\n if (activeValue !== undefined) activatedRef.current.add(activeValue);\n\n const rootClass = [\"rtab-root\", className].filter(Boolean).join(\" \");\n\n return (\n <div\n ref={ref}\n className={rootClass}\n data-orientation={orientation}\n >\n <div\n ref={tabListRef}\n role=\"tablist\"\n aria-orientation={orientation}\n className=\"rtab-list\"\n data-variant={variant}\n data-size={size}\n data-tone={tone}\n data-orientation={orientation}\n style={indicatorStyle}\n >\n {tabs.map((tab, index) => {\n const isActive = activeValue === tab.value;\n const isDisabled = !!tab.disabled;\n return (\n <button\n key={tab.value}\n className=\"rtab-tab\"\n {...getTabProps(tab.value, { disabled: tab.disabled })}\n >\n {renderTab\n ? renderTab({ tab, index, isActive, isDisabled })\n : tab.label}\n </button>\n );\n })}\n {(variant === \"line\" || variant === \"solid\" || variant === \"pill\") && (\n <span className=\"rtab-indicator\" aria-hidden=\"true\" />\n )}\n </div>\n <div className=\"rtab-panels\">\n {tabs.map((tab) => {\n const isActive = activeValue === tab.value;\n const shouldRender =\n forceMount || !lazyMount || activatedRef.current.has(tab.value);\n return (\n <div\n key={tab.value}\n className=\"rtab-panel\"\n {...getPanelProps(tab.value)}\n >\n {shouldRender\n ? renderPanel\n ? renderPanel({ tab, isActive })\n : tab.content\n : null}\n </div>\n );\n })}\n </div>\n </div>\n );\n },\n);\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/useTabs.ts","../src/styled/TabsStyled.tsx"],"names":["useRef","useState","useCallback","useMemo","useLayoutEffect","useEffect","forwardRef","TabsStyled","jsxs","jsx"],"mappings":"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","file":"styled.cjs","sourcesContent":["import {\n type HTMLAttributes,\n type KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport type TabsActivation = \"automatic\" | \"manual\";\nexport type TabsOrientation = \"horizontal\" | \"vertical\";\nexport type TabsChangeReason = \"click\" | \"keyboard\" | \"programmatic\";\n\nexport interface UseTabsTab {\n value: string;\n disabled?: boolean;\n}\n\nexport interface UseTabsOptions {\n /** Tab definitions — needed for keyboard navigation between tabs. */\n tabs?: UseTabsTab[];\n /** Controlled active value. */\n value?: string;\n /** Initial active value when uncontrolled. */\n defaultValue?: string;\n /** Called when the active tab changes. Optional second arg reports the trigger reason. */\n onChange?: (value: string, reason: TabsChangeReason) => void;\n /** \"automatic\" (default) — arrow keys move focus AND activate. \"manual\" — arrows move focus only; Enter/Space activates. */\n activation?: TabsActivation;\n /** Affects keyboard nav. Default \"horizontal\". */\n orientation?: TabsOrientation;\n}\n\nexport interface TabProps extends HTMLAttributes<HTMLButtonElement> {\n id: string;\n role: \"tab\";\n \"aria-selected\": boolean;\n \"aria-controls\": string;\n \"aria-disabled\"?: boolean;\n \"data-state\": \"active\" | \"inactive\";\n tabIndex: number;\n}\n\nexport interface PanelProps extends HTMLAttributes<HTMLDivElement> {\n id: string;\n role: \"tabpanel\";\n \"aria-labelledby\": string;\n \"data-state\": \"active\" | \"inactive\";\n hidden: boolean;\n}\n\nexport interface UseTabsResult {\n /** Currently active tab value. */\n activeValue: string | undefined;\n /** Returns props to spread onto a tab trigger `<button>`. */\n getTabProps: (value: string, options?: { disabled?: boolean }) => TabProps;\n /** Returns props to spread onto a tab panel. */\n getPanelProps: (value: string) => PanelProps;\n /** Programmatically set the active tab. */\n setActiveValue: (value: string) => void;\n}\n\nconst tabId = (listId: string, value: string) => `${listId}-tab-${value}`;\nconst panelId = (listId: string, value: string) => `${listId}-panel-${value}`;\n\nlet counter = 0;\nfunction useStableId() {\n const ref = useRef<string | null>(null);\n if (ref.current === null) {\n ref.current = `rtabs-${++counter}`;\n }\n return ref.current;\n}\n\nexport function useTabs(opts: UseTabsOptions = {}): UseTabsResult {\n const {\n tabs = [],\n value: controlledValue,\n defaultValue,\n onChange,\n activation = \"automatic\",\n orientation = \"horizontal\",\n } = opts;\n\n const listId = useStableId();\n const isControlled = controlledValue !== undefined;\n\n const [internalValue, setInternalValue] = useState<string | undefined>(\n defaultValue,\n );\n\n const activeValue = isControlled ? controlledValue : internalValue;\n\n const tabRefs = useRef<Map<string, HTMLButtonElement>>(new Map());\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n const setActiveValue = useCallback(\n (next: string, reason: TabsChangeReason = \"programmatic\") => {\n const tab = tabs.find((t) => t.value === next);\n if (tab?.disabled) return;\n if (isControlled) {\n if (next !== controlledValue) onChangeRef.current?.(next, reason);\n } else {\n if (next === internalValue) return;\n setInternalValue(next);\n onChangeRef.current?.(next, reason);\n }\n },\n [tabs, isControlled, controlledValue, internalValue],\n );\n\n const focusTab = useCallback((value: string) => {\n tabRefs.current.get(value)?.focus();\n }, []);\n\n const handleKeyDown = useCallback(\n (currentValue: string) =>\n (event: KeyboardEvent<HTMLButtonElement>) => {\n const enabled = tabs.filter((t) => !t.disabled);\n if (enabled.length === 0) return;\n\n const currentIndex = enabled.findIndex((t) => t.value === currentValue);\n\n const isForward =\n orientation === \"vertical\"\n ? event.key === \"ArrowDown\"\n : event.key === \"ArrowRight\";\n const isBackward =\n orientation === \"vertical\"\n ? event.key === \"ArrowUp\"\n : event.key === \"ArrowLeft\";\n\n let nextValue: string | undefined;\n\n if (isForward) {\n const nextIndex = (currentIndex + 1) % enabled.length;\n nextValue = enabled[nextIndex]?.value;\n } else if (isBackward) {\n const prevIndex = (currentIndex - 1 + enabled.length) % enabled.length;\n nextValue = enabled[prevIndex]?.value;\n } else if (event.key === \"Home\") {\n nextValue = enabled[0]?.value;\n } else if (event.key === \"End\") {\n nextValue = enabled[enabled.length - 1]?.value;\n } else if (\n activation === \"manual\" &&\n (event.key === \"Enter\" || event.key === \" \")\n ) {\n event.preventDefault();\n setActiveValue(currentValue, \"keyboard\");\n return;\n } else {\n return;\n }\n\n if (nextValue === undefined || nextValue === currentValue) return;\n event.preventDefault();\n focusTab(nextValue);\n if (activation === \"automatic\") {\n setActiveValue(nextValue, \"keyboard\");\n }\n },\n [tabs, orientation, activation, setActiveValue, focusTab],\n );\n\n const getTabProps = useCallback(\n (value: string, options?: { disabled?: boolean }): TabProps => {\n const isDisabled =\n options?.disabled ?? tabs.find((t) => t.value === value)?.disabled;\n const isSelected = activeValue === value;\n return {\n id: tabId(listId, value),\n role: \"tab\",\n \"aria-selected\": isSelected,\n \"aria-controls\": panelId(listId, value),\n \"aria-disabled\": isDisabled || undefined,\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n tabIndex: isSelected ? 0 : -1,\n disabled: isDisabled,\n ref: (node: HTMLButtonElement | null) => {\n if (node) {\n tabRefs.current.set(value, node);\n } else {\n tabRefs.current.delete(value);\n }\n },\n onClick: () => {\n if (!isDisabled) setActiveValue(value, \"click\");\n },\n onKeyDown: handleKeyDown(value),\n } as TabProps & {\n disabled: boolean | undefined;\n ref: (node: HTMLButtonElement | null) => void;\n };\n },\n [activeValue, listId, tabs, setActiveValue, handleKeyDown],\n );\n\n const getPanelProps = useCallback(\n (value: string): PanelProps => {\n const isActive = activeValue === value;\n return {\n id: panelId(listId, value),\n role: \"tabpanel\",\n \"aria-labelledby\": tabId(listId, value),\n \"data-state\": isActive ? \"active\" : \"inactive\",\n hidden: !isActive,\n tabIndex: 0,\n };\n },\n [activeValue, listId],\n );\n\n return useMemo(\n () => ({ activeValue, getTabProps, getPanelProps, setActiveValue }),\n [activeValue, getTabProps, getPanelProps, setActiveValue],\n );\n}\n","import {\n type CSSProperties,\n type ReactNode,\n forwardRef,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n useTabs,\n type TabsActivation,\n type TabsChangeReason,\n type TabsOrientation,\n} from \"../useTabs\";\n\nexport type TabsVariant = \"line\" | \"solid\" | \"pill\";\nexport type TabsSize = \"sm\" | \"md\" | \"lg\";\nexport type TabsTone = \"neutral\" | \"primary\" | \"success\" | \"danger\";\n\nexport interface TabItem {\n value: string;\n label: ReactNode;\n content: ReactNode;\n disabled?: boolean;\n /** When true, renders a × button on the tab. Pair with `onTabClose`. */\n closable?: boolean;\n}\n\nexport interface TabsRenderTabContext {\n tab: TabItem;\n index: number;\n isActive: boolean;\n isDisabled: boolean;\n}\n\nexport interface TabsRenderPanelContext {\n tab: TabItem;\n isActive: boolean;\n}\n\nexport interface TabsStyledProps {\n tabs: TabItem[];\n variant?: TabsVariant;\n size?: TabsSize;\n tone?: TabsTone;\n defaultValue?: string;\n value?: string;\n /** Optional second arg reports the trigger reason (\"click\" | \"keyboard\" | \"programmatic\"). */\n onChange?: (value: string, reason: TabsChangeReason) => void;\n /** \"automatic\" (default) — arrow keys move focus AND activate. \"manual\" — arrows move focus only. */\n activation?: TabsActivation;\n /** Affects keyboard nav direction. Default \"horizontal\". */\n orientation?: TabsOrientation;\n /** Only mount panels after they've been activated at least once. Default: false (all panels mount eagerly). */\n lazyMount?: boolean;\n /** Keep all panels mounted regardless of activation (useful with `lazyMount` overrides). Default: false. */\n forceMount?: boolean;\n /** Fires when the × on a closable tab is clicked. */\n onTabClose?: (value: string) => void;\n /** When true, the tab list scrolls horizontally with chevron buttons at the edges instead of wrapping. */\n scrollable?: boolean;\n /** When true, tabs can be reordered by dragging. Fires `onReorder` with the new value order. */\n sortable?: boolean;\n onReorder?: (values: string[]) => void;\n /** When true, the active tab is scrolled into view on activation. Default: true when `scrollable`. */\n scrollActiveIntoView?: boolean;\n /** Replace the default tab button content. The button shell (a11y, ref, key) stays owned by the component. */\n renderTab?: (ctx: TabsRenderTabContext) => ReactNode;\n /** Replace the default panel rendering. */\n renderPanel?: (ctx: TabsRenderPanelContext) => ReactNode;\n className?: string;\n}\n\n// Run layout effects on the client; fall back to a no-op effect on the server.\nconst useIsoLayoutEffect =\n typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\nfunction useIndicator(\n tabListRef: React.RefObject<HTMLDivElement | null>,\n activeValue: string | undefined,\n orientation: TabsOrientation,\n) {\n const [style, setStyle] = useState<CSSProperties>({});\n\n useIsoLayoutEffect(() => {\n if (!tabListRef.current || activeValue === undefined) return;\n\n const measure = () => {\n const list = tabListRef.current;\n if (!list) return;\n const activeTab = list.querySelector<HTMLElement>(\n `[aria-selected=\"true\"]`,\n );\n if (!activeTab) return;\n\n const listRect = list.getBoundingClientRect();\n const tabRect = activeTab.getBoundingClientRect();\n\n if (orientation === \"vertical\") {\n const y = tabRect.top - listRect.top;\n const h = tabRect.height;\n setStyle({\n [\"--rtab-indicator-y\" as string]: `${y}px`,\n [\"--rtab-indicator-height\" as string]: `${h}px`,\n [\"--rtab-indicator-ready\" as string]: \"1\",\n });\n } else {\n const x = tabRect.left - listRect.left;\n const w = tabRect.width;\n setStyle({\n [\"--rtab-indicator-x\" as string]: `${x}px`,\n [\"--rtab-indicator-width\" as string]: `${w}px`,\n [\"--rtab-indicator-ready\" as string]: \"1\",\n });\n }\n };\n\n measure();\n\n if (typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(measure);\n ro.observe(tabListRef.current);\n return () => ro.disconnect();\n }, [activeValue, tabListRef, orientation]);\n\n return style;\n}\n\nexport const TabsStyled = forwardRef<HTMLDivElement, TabsStyledProps>(\n function TabsStyled(\n {\n tabs,\n variant = \"line\",\n size = \"md\",\n tone = \"neutral\",\n defaultValue,\n value,\n onChange,\n activation = \"automatic\",\n orientation = \"horizontal\",\n lazyMount = false,\n forceMount = false,\n onTabClose,\n scrollable = false,\n sortable = false,\n onReorder,\n scrollActiveIntoView,\n renderTab,\n renderPanel,\n className,\n },\n ref,\n ) {\n const autoScrollActive = scrollActiveIntoView ?? scrollable;\n const [scrollState, setScrollState] = useState<{ left: boolean; right: boolean }>({\n left: false,\n right: false,\n });\n const typeaheadBufferRef = useRef(\"\");\n const typeaheadTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const dragValueRef = useRef<string | null>(null);\n const tabDefs = tabs.map((t) => ({ value: t.value, disabled: t.disabled }));\n\n const resolvedDefault =\n defaultValue ?? tabs.find((t) => !t.disabled)?.value;\n\n const { activeValue, getTabProps, getPanelProps } = useTabs({\n tabs: tabDefs,\n defaultValue: value === undefined ? resolvedDefault : undefined,\n value,\n onChange,\n activation,\n orientation,\n });\n\n const tabListRef = useRef<HTMLDivElement>(null);\n const indicatorStyle = useIndicator(tabListRef, activeValue, orientation);\n\n // Track which tabs have been activated for lazyMount.\n const activatedRef = useRef<Set<string>>(new Set());\n if (activeValue !== undefined) activatedRef.current.add(activeValue);\n\n const rootClass = [\"rtab-root\", className].filter(Boolean).join(\" \");\n\n // Scroll-state: detect when there's content off the left/right edges so we can\n // toggle the chevron buttons. Only relevant when scrollable.\n useEffect(() => {\n if (!scrollable) return;\n const list = tabListRef.current;\n if (!list) return;\n const update = () => {\n setScrollState({\n left: list.scrollLeft > 4,\n right: list.scrollLeft + list.clientWidth < list.scrollWidth - 4,\n });\n };\n update();\n list.addEventListener(\"scroll\", update, { passive: true });\n const ro = typeof ResizeObserver !== \"undefined\" ? new ResizeObserver(update) : null;\n ro?.observe(list);\n return () => {\n list.removeEventListener(\"scroll\", update);\n ro?.disconnect();\n };\n }, [scrollable, tabs.length]);\n\n // Auto-scroll active tab into view\n useEffect(() => {\n if (!autoScrollActive || !activeValue) return;\n const list = tabListRef.current;\n if (!list) return;\n const activeEl = list.querySelector<HTMLElement>(`[aria-selected=\"true\"]`);\n if (!activeEl) return;\n activeEl.scrollIntoView({ behavior: \"smooth\", block: \"nearest\", inline: \"nearest\" });\n }, [autoScrollActive, activeValue]);\n\n const scrollByAmount = (delta: number) => {\n tabListRef.current?.scrollBy({ left: delta, behavior: \"smooth\" });\n };\n\n // Typeahead: letters jump to the next tab whose label starts with the buffer.\n const handleTypeahead = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key.length !== 1 || e.altKey || e.ctrlKey || e.metaKey) return;\n typeaheadBufferRef.current = (typeaheadBufferRef.current + e.key).toLowerCase();\n if (typeaheadTimerRef.current) clearTimeout(typeaheadTimerRef.current);\n typeaheadTimerRef.current = setTimeout(() => { typeaheadBufferRef.current = \"\"; }, 600);\n\n const buffer = typeaheadBufferRef.current;\n const startIdx = Math.max(0, tabs.findIndex((t) => t.value === activeValue));\n // Search starting just after the active tab, wrapping around.\n for (let i = 1; i <= tabs.length; i++) {\n const idx = (startIdx + i) % tabs.length;\n const tab = tabs[idx];\n if (!tab || tab.disabled) continue;\n const labelStr = typeof tab.label === \"string\" ? tab.label : \"\";\n if (labelStr.toLowerCase().startsWith(buffer)) {\n // Use the existing tab button's click via aria-selected target.\n const list = tabListRef.current;\n const btn = list?.querySelector<HTMLButtonElement>(`[data-value=\"${tab.value}\"]`);\n btn?.click();\n btn?.focus();\n break;\n }\n }\n };\n\n // Drag-to-reorder: HTML5 DnD is fine here — no external lib.\n const handleDragStart = (val: string) => (e: React.DragEvent<HTMLButtonElement>) => {\n if (!sortable) return;\n dragValueRef.current = val;\n e.dataTransfer.effectAllowed = \"move\";\n };\n const handleDragOver = (val: string) => (e: React.DragEvent<HTMLButtonElement>) => {\n if (!sortable || !dragValueRef.current || dragValueRef.current === val) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n };\n const handleDrop = (val: string) => (e: React.DragEvent<HTMLButtonElement>) => {\n if (!sortable) return;\n e.preventDefault();\n const from = dragValueRef.current;\n dragValueRef.current = null;\n if (!from || from === val || !onReorder) return;\n const order = tabs.map((t) => t.value);\n const fromIdx = order.indexOf(from);\n const toIdx = order.indexOf(val);\n if (fromIdx === -1 || toIdx === -1) return;\n const next = [...order];\n next.splice(fromIdx, 1);\n next.splice(toIdx, 0, from);\n onReorder(next);\n };\n\n return (\n <div\n ref={ref}\n className={rootClass}\n data-orientation={orientation}\n data-scrollable={scrollable || undefined}\n onKeyDown={handleTypeahead}\n >\n <div className=\"rtab-list-wrap\">\n {scrollable && scrollState.left && (\n <button\n type=\"button\"\n className=\"rtab-scroll-btn rtab-scroll-btn--left\"\n aria-label=\"Scroll left\"\n onClick={() => scrollByAmount(-200)}\n >\n <svg viewBox=\"0 0 12 12\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M7.5 3l-3 3 3 3\"/></svg>\n </button>\n )}\n <div\n ref={tabListRef}\n role=\"tablist\"\n aria-orientation={orientation}\n className=\"rtab-list\"\n data-variant={variant}\n data-size={size}\n data-tone={tone}\n data-orientation={orientation}\n data-scrollable={scrollable || undefined}\n style={indicatorStyle}\n >\n {tabs.map((tab, index) => {\n const isActive = activeValue === tab.value;\n const isDisabled = !!tab.disabled;\n const tabProps = getTabProps(tab.value, { disabled: tab.disabled });\n return (\n <button\n key={tab.value}\n data-value={tab.value}\n data-closable={tab.closable || undefined}\n className=\"rtab-tab\"\n {...tabProps}\n draggable={sortable && !isDisabled ? true : undefined}\n onDragStart={sortable ? handleDragStart(tab.value) : undefined}\n onDragOver={sortable ? handleDragOver(tab.value) : undefined}\n onDrop={sortable ? handleDrop(tab.value) : undefined}\n >\n {renderTab\n ? renderTab({ tab, index, isActive, isDisabled })\n : tab.label}\n {tab.closable && (\n <span\n className=\"rtab-close\"\n role=\"button\"\n tabIndex={-1}\n aria-label={`Close ${typeof tab.label === \"string\" ? tab.label : \"tab\"}`}\n onClick={(e) => {\n e.stopPropagation();\n onTabClose?.(tab.value);\n }}\n >\n <svg viewBox=\"0 0 12 12\" width=\"10\" height=\"10\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" aria-hidden=\"true\">\n <path d=\"M3 3l6 6M9 3l-6 6\"/>\n </svg>\n </span>\n )}\n </button>\n );\n })}\n {(variant === \"line\" || variant === \"solid\" || variant === \"pill\") && (\n <span className=\"rtab-indicator\" aria-hidden=\"true\" />\n )}\n </div>\n {scrollable && scrollState.right && (\n <button\n type=\"button\"\n className=\"rtab-scroll-btn rtab-scroll-btn--right\"\n aria-label=\"Scroll right\"\n onClick={() => scrollByAmount(200)}\n >\n <svg viewBox=\"0 0 12 12\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M4.5 3l3 3-3 3\"/></svg>\n </button>\n )}\n </div>\n <div className=\"rtab-panels\">\n {tabs.map((tab) => {\n const isActive = activeValue === tab.value;\n const shouldRender =\n forceMount || !lazyMount || activatedRef.current.has(tab.value);\n return (\n <div\n key={tab.value}\n className=\"rtab-panel\"\n {...getPanelProps(tab.value)}\n >\n {shouldRender\n ? renderPanel\n ? renderPanel({ tab, isActive })\n : tab.content\n : null}\n </div>\n );\n })}\n </div>\n </div>\n );\n },\n);\n"]}
|
package/dist/styled.d.cts
CHANGED
|
@@ -10,6 +10,8 @@ interface TabItem {
|
|
|
10
10
|
label: ReactNode;
|
|
11
11
|
content: ReactNode;
|
|
12
12
|
disabled?: boolean;
|
|
13
|
+
/** When true, renders a × button on the tab. Pair with `onTabClose`. */
|
|
14
|
+
closable?: boolean;
|
|
13
15
|
}
|
|
14
16
|
interface TabsRenderTabContext {
|
|
15
17
|
tab: TabItem;
|
|
@@ -38,6 +40,15 @@ interface TabsStyledProps {
|
|
|
38
40
|
lazyMount?: boolean;
|
|
39
41
|
/** Keep all panels mounted regardless of activation (useful with `lazyMount` overrides). Default: false. */
|
|
40
42
|
forceMount?: boolean;
|
|
43
|
+
/** Fires when the × on a closable tab is clicked. */
|
|
44
|
+
onTabClose?: (value: string) => void;
|
|
45
|
+
/** When true, the tab list scrolls horizontally with chevron buttons at the edges instead of wrapping. */
|
|
46
|
+
scrollable?: boolean;
|
|
47
|
+
/** When true, tabs can be reordered by dragging. Fires `onReorder` with the new value order. */
|
|
48
|
+
sortable?: boolean;
|
|
49
|
+
onReorder?: (values: string[]) => void;
|
|
50
|
+
/** When true, the active tab is scrolled into view on activation. Default: true when `scrollable`. */
|
|
51
|
+
scrollActiveIntoView?: boolean;
|
|
41
52
|
/** Replace the default tab button content. The button shell (a11y, ref, key) stays owned by the component. */
|
|
42
53
|
renderTab?: (ctx: TabsRenderTabContext) => ReactNode;
|
|
43
54
|
/** Replace the default panel rendering. */
|
package/dist/styled.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ interface TabItem {
|
|
|
10
10
|
label: ReactNode;
|
|
11
11
|
content: ReactNode;
|
|
12
12
|
disabled?: boolean;
|
|
13
|
+
/** When true, renders a × button on the tab. Pair with `onTabClose`. */
|
|
14
|
+
closable?: boolean;
|
|
13
15
|
}
|
|
14
16
|
interface TabsRenderTabContext {
|
|
15
17
|
tab: TabItem;
|
|
@@ -38,6 +40,15 @@ interface TabsStyledProps {
|
|
|
38
40
|
lazyMount?: boolean;
|
|
39
41
|
/** Keep all panels mounted regardless of activation (useful with `lazyMount` overrides). Default: false. */
|
|
40
42
|
forceMount?: boolean;
|
|
43
|
+
/** Fires when the × on a closable tab is clicked. */
|
|
44
|
+
onTabClose?: (value: string) => void;
|
|
45
|
+
/** When true, the tab list scrolls horizontally with chevron buttons at the edges instead of wrapping. */
|
|
46
|
+
scrollable?: boolean;
|
|
47
|
+
/** When true, tabs can be reordered by dragging. Fires `onReorder` with the new value order. */
|
|
48
|
+
sortable?: boolean;
|
|
49
|
+
onReorder?: (values: string[]) => void;
|
|
50
|
+
/** When true, the active tab is scrolled into view on activation. Default: true when `scrollable`. */
|
|
51
|
+
scrollActiveIntoView?: boolean;
|
|
41
52
|
/** Replace the default tab button content. The button shell (a11y, ref, key) stays owned by the component. */
|
|
42
53
|
renderTab?: (ctx: TabsRenderTabContext) => ReactNode;
|
|
43
54
|
/** Replace the default panel rendering. */
|
package/dist/styled.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useTabs } from './chunk-NNDW3W6L.js';
|
|
2
|
-
import { forwardRef, useRef,
|
|
2
|
+
import { forwardRef, useState, useRef, useEffect, useLayoutEffect } from 'react';
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
5
|
var useIsoLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
|
|
@@ -55,10 +55,23 @@ var TabsStyled = forwardRef(
|
|
|
55
55
|
orientation = "horizontal",
|
|
56
56
|
lazyMount = false,
|
|
57
57
|
forceMount = false,
|
|
58
|
+
onTabClose,
|
|
59
|
+
scrollable = false,
|
|
60
|
+
sortable = false,
|
|
61
|
+
onReorder,
|
|
62
|
+
scrollActiveIntoView,
|
|
58
63
|
renderTab,
|
|
59
64
|
renderPanel,
|
|
60
65
|
className
|
|
61
66
|
}, ref) {
|
|
67
|
+
const autoScrollActive = scrollActiveIntoView ?? scrollable;
|
|
68
|
+
const [scrollState, setScrollState] = useState({
|
|
69
|
+
left: false,
|
|
70
|
+
right: false
|
|
71
|
+
});
|
|
72
|
+
const typeaheadBufferRef = useRef("");
|
|
73
|
+
const typeaheadTimerRef = useRef(null);
|
|
74
|
+
const dragValueRef = useRef(null);
|
|
62
75
|
const tabDefs = tabs.map((t) => ({ value: t.value, disabled: t.disabled }));
|
|
63
76
|
const resolvedDefault = defaultValue ?? tabs.find((t) => !t.disabled)?.value;
|
|
64
77
|
const { activeValue, getTabProps, getPanelProps } = useTabs({
|
|
@@ -74,43 +87,169 @@ var TabsStyled = forwardRef(
|
|
|
74
87
|
const activatedRef = useRef(/* @__PURE__ */ new Set());
|
|
75
88
|
if (activeValue !== void 0) activatedRef.current.add(activeValue);
|
|
76
89
|
const rootClass = ["rtab-root", className].filter(Boolean).join(" ");
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (!scrollable) return;
|
|
92
|
+
const list = tabListRef.current;
|
|
93
|
+
if (!list) return;
|
|
94
|
+
const update = () => {
|
|
95
|
+
setScrollState({
|
|
96
|
+
left: list.scrollLeft > 4,
|
|
97
|
+
right: list.scrollLeft + list.clientWidth < list.scrollWidth - 4
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
update();
|
|
101
|
+
list.addEventListener("scroll", update, { passive: true });
|
|
102
|
+
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(update) : null;
|
|
103
|
+
ro?.observe(list);
|
|
104
|
+
return () => {
|
|
105
|
+
list.removeEventListener("scroll", update);
|
|
106
|
+
ro?.disconnect();
|
|
107
|
+
};
|
|
108
|
+
}, [scrollable, tabs.length]);
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (!autoScrollActive || !activeValue) return;
|
|
111
|
+
const list = tabListRef.current;
|
|
112
|
+
if (!list) return;
|
|
113
|
+
const activeEl = list.querySelector(`[aria-selected="true"]`);
|
|
114
|
+
if (!activeEl) return;
|
|
115
|
+
activeEl.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
|
|
116
|
+
}, [autoScrollActive, activeValue]);
|
|
117
|
+
const scrollByAmount = (delta) => {
|
|
118
|
+
tabListRef.current?.scrollBy({ left: delta, behavior: "smooth" });
|
|
119
|
+
};
|
|
120
|
+
const handleTypeahead = (e) => {
|
|
121
|
+
if (e.key.length !== 1 || e.altKey || e.ctrlKey || e.metaKey) return;
|
|
122
|
+
typeaheadBufferRef.current = (typeaheadBufferRef.current + e.key).toLowerCase();
|
|
123
|
+
if (typeaheadTimerRef.current) clearTimeout(typeaheadTimerRef.current);
|
|
124
|
+
typeaheadTimerRef.current = setTimeout(() => {
|
|
125
|
+
typeaheadBufferRef.current = "";
|
|
126
|
+
}, 600);
|
|
127
|
+
const buffer = typeaheadBufferRef.current;
|
|
128
|
+
const startIdx = Math.max(0, tabs.findIndex((t) => t.value === activeValue));
|
|
129
|
+
for (let i = 1; i <= tabs.length; i++) {
|
|
130
|
+
const idx = (startIdx + i) % tabs.length;
|
|
131
|
+
const tab = tabs[idx];
|
|
132
|
+
if (!tab || tab.disabled) continue;
|
|
133
|
+
const labelStr = typeof tab.label === "string" ? tab.label : "";
|
|
134
|
+
if (labelStr.toLowerCase().startsWith(buffer)) {
|
|
135
|
+
const list = tabListRef.current;
|
|
136
|
+
const btn = list?.querySelector(`[data-value="${tab.value}"]`);
|
|
137
|
+
btn?.click();
|
|
138
|
+
btn?.focus();
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const handleDragStart = (val) => (e) => {
|
|
144
|
+
if (!sortable) return;
|
|
145
|
+
dragValueRef.current = val;
|
|
146
|
+
e.dataTransfer.effectAllowed = "move";
|
|
147
|
+
};
|
|
148
|
+
const handleDragOver = (val) => (e) => {
|
|
149
|
+
if (!sortable || !dragValueRef.current || dragValueRef.current === val) return;
|
|
150
|
+
e.preventDefault();
|
|
151
|
+
e.dataTransfer.dropEffect = "move";
|
|
152
|
+
};
|
|
153
|
+
const handleDrop = (val) => (e) => {
|
|
154
|
+
if (!sortable) return;
|
|
155
|
+
e.preventDefault();
|
|
156
|
+
const from = dragValueRef.current;
|
|
157
|
+
dragValueRef.current = null;
|
|
158
|
+
if (!from || from === val || !onReorder) return;
|
|
159
|
+
const order = tabs.map((t) => t.value);
|
|
160
|
+
const fromIdx = order.indexOf(from);
|
|
161
|
+
const toIdx = order.indexOf(val);
|
|
162
|
+
if (fromIdx === -1 || toIdx === -1) return;
|
|
163
|
+
const next = [...order];
|
|
164
|
+
next.splice(fromIdx, 1);
|
|
165
|
+
next.splice(toIdx, 0, from);
|
|
166
|
+
onReorder(next);
|
|
167
|
+
};
|
|
77
168
|
return /* @__PURE__ */ jsxs(
|
|
78
169
|
"div",
|
|
79
170
|
{
|
|
80
171
|
ref,
|
|
81
172
|
className: rootClass,
|
|
82
173
|
"data-orientation": orientation,
|
|
174
|
+
"data-scrollable": scrollable || void 0,
|
|
175
|
+
onKeyDown: handleTypeahead,
|
|
83
176
|
children: [
|
|
84
|
-
/* @__PURE__ */ jsxs(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
177
|
+
/* @__PURE__ */ jsxs("div", { className: "rtab-list-wrap", children: [
|
|
178
|
+
scrollable && scrollState.left && /* @__PURE__ */ jsx(
|
|
179
|
+
"button",
|
|
180
|
+
{
|
|
181
|
+
type: "button",
|
|
182
|
+
className: "rtab-scroll-btn rtab-scroll-btn--left",
|
|
183
|
+
"aria-label": "Scroll left",
|
|
184
|
+
onClick: () => scrollByAmount(-200),
|
|
185
|
+
children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M7.5 3l-3 3 3 3" }) })
|
|
186
|
+
}
|
|
187
|
+
),
|
|
188
|
+
/* @__PURE__ */ jsxs(
|
|
189
|
+
"div",
|
|
190
|
+
{
|
|
191
|
+
ref: tabListRef,
|
|
192
|
+
role: "tablist",
|
|
193
|
+
"aria-orientation": orientation,
|
|
194
|
+
className: "rtab-list",
|
|
195
|
+
"data-variant": variant,
|
|
196
|
+
"data-size": size,
|
|
197
|
+
"data-tone": tone,
|
|
198
|
+
"data-orientation": orientation,
|
|
199
|
+
"data-scrollable": scrollable || void 0,
|
|
200
|
+
style: indicatorStyle,
|
|
201
|
+
children: [
|
|
202
|
+
tabs.map((tab, index) => {
|
|
203
|
+
const isActive = activeValue === tab.value;
|
|
204
|
+
const isDisabled = !!tab.disabled;
|
|
205
|
+
const tabProps = getTabProps(tab.value, { disabled: tab.disabled });
|
|
206
|
+
return /* @__PURE__ */ jsxs(
|
|
207
|
+
"button",
|
|
208
|
+
{
|
|
209
|
+
"data-value": tab.value,
|
|
210
|
+
"data-closable": tab.closable || void 0,
|
|
211
|
+
className: "rtab-tab",
|
|
212
|
+
...tabProps,
|
|
213
|
+
draggable: sortable && !isDisabled ? true : void 0,
|
|
214
|
+
onDragStart: sortable ? handleDragStart(tab.value) : void 0,
|
|
215
|
+
onDragOver: sortable ? handleDragOver(tab.value) : void 0,
|
|
216
|
+
onDrop: sortable ? handleDrop(tab.value) : void 0,
|
|
217
|
+
children: [
|
|
218
|
+
renderTab ? renderTab({ tab, index, isActive, isDisabled }) : tab.label,
|
|
219
|
+
tab.closable && /* @__PURE__ */ jsx(
|
|
220
|
+
"span",
|
|
221
|
+
{
|
|
222
|
+
className: "rtab-close",
|
|
223
|
+
role: "button",
|
|
224
|
+
tabIndex: -1,
|
|
225
|
+
"aria-label": `Close ${typeof tab.label === "string" ? tab.label : "tab"}`,
|
|
226
|
+
onClick: (e) => {
|
|
227
|
+
e.stopPropagation();
|
|
228
|
+
onTabClose?.(tab.value);
|
|
229
|
+
},
|
|
230
|
+
children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: "10", height: "10", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M3 3l6 6M9 3l-6 6" }) })
|
|
231
|
+
}
|
|
232
|
+
)
|
|
233
|
+
]
|
|
234
|
+
},
|
|
235
|
+
tab.value
|
|
236
|
+
);
|
|
237
|
+
}),
|
|
238
|
+
(variant === "line" || variant === "solid" || variant === "pill") && /* @__PURE__ */ jsx("span", { className: "rtab-indicator", "aria-hidden": "true" })
|
|
239
|
+
]
|
|
240
|
+
}
|
|
241
|
+
),
|
|
242
|
+
scrollable && scrollState.right && /* @__PURE__ */ jsx(
|
|
243
|
+
"button",
|
|
244
|
+
{
|
|
245
|
+
type: "button",
|
|
246
|
+
className: "rtab-scroll-btn rtab-scroll-btn--right",
|
|
247
|
+
"aria-label": "Scroll right",
|
|
248
|
+
onClick: () => scrollByAmount(200),
|
|
249
|
+
children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M4.5 3l3 3-3 3" }) })
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
] }),
|
|
114
253
|
/* @__PURE__ */ jsx("div", { className: "rtab-panels", children: tabs.map((tab) => {
|
|
115
254
|
const isActive = activeValue === tab.value;
|
|
116
255
|
const shouldRender = forceMount || !lazyMount || activatedRef.current.has(tab.value);
|
package/dist/styled.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/styled/TabsStyled.tsx"],"names":["TabsStyled"],"mappings":"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","file":"styled.js","sourcesContent":["import {\n type CSSProperties,\n type ReactNode,\n forwardRef,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n useTabs,\n type TabsActivation,\n type TabsChangeReason,\n type TabsOrientation,\n} from \"../useTabs\";\n\nexport type TabsVariant = \"line\" | \"solid\" | \"pill\";\nexport type TabsSize = \"sm\" | \"md\" | \"lg\";\nexport type TabsTone = \"neutral\" | \"primary\" | \"success\" | \"danger\";\n\nexport interface TabItem {\n value: string;\n label: ReactNode;\n content: ReactNode;\n disabled?: boolean;\n}\n\nexport interface TabsRenderTabContext {\n tab: TabItem;\n index: number;\n isActive: boolean;\n isDisabled: boolean;\n}\n\nexport interface TabsRenderPanelContext {\n tab: TabItem;\n isActive: boolean;\n}\n\nexport interface TabsStyledProps {\n tabs: TabItem[];\n variant?: TabsVariant;\n size?: TabsSize;\n tone?: TabsTone;\n defaultValue?: string;\n value?: string;\n /** Optional second arg reports the trigger reason (\"click\" | \"keyboard\" | \"programmatic\"). */\n onChange?: (value: string, reason: TabsChangeReason) => void;\n /** \"automatic\" (default) — arrow keys move focus AND activate. \"manual\" — arrows move focus only. */\n activation?: TabsActivation;\n /** Affects keyboard nav direction. Default \"horizontal\". */\n orientation?: TabsOrientation;\n /** Only mount panels after they've been activated at least once. Default: false (all panels mount eagerly). */\n lazyMount?: boolean;\n /** Keep all panels mounted regardless of activation (useful with `lazyMount` overrides). Default: false. */\n forceMount?: boolean;\n /** Replace the default tab button content. The button shell (a11y, ref, key) stays owned by the component. */\n renderTab?: (ctx: TabsRenderTabContext) => ReactNode;\n /** Replace the default panel rendering. */\n renderPanel?: (ctx: TabsRenderPanelContext) => ReactNode;\n className?: string;\n}\n\n// Run layout effects on the client; fall back to a no-op effect on the server.\nconst useIsoLayoutEffect =\n typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\nfunction useIndicator(\n tabListRef: React.RefObject<HTMLDivElement | null>,\n activeValue: string | undefined,\n orientation: TabsOrientation,\n) {\n const [style, setStyle] = useState<CSSProperties>({});\n\n useIsoLayoutEffect(() => {\n if (!tabListRef.current || activeValue === undefined) return;\n\n const measure = () => {\n const list = tabListRef.current;\n if (!list) return;\n const activeTab = list.querySelector<HTMLElement>(\n `[aria-selected=\"true\"]`,\n );\n if (!activeTab) return;\n\n const listRect = list.getBoundingClientRect();\n const tabRect = activeTab.getBoundingClientRect();\n\n if (orientation === \"vertical\") {\n const y = tabRect.top - listRect.top;\n const h = tabRect.height;\n setStyle({\n [\"--rtab-indicator-y\" as string]: `${y}px`,\n [\"--rtab-indicator-height\" as string]: `${h}px`,\n [\"--rtab-indicator-ready\" as string]: \"1\",\n });\n } else {\n const x = tabRect.left - listRect.left;\n const w = tabRect.width;\n setStyle({\n [\"--rtab-indicator-x\" as string]: `${x}px`,\n [\"--rtab-indicator-width\" as string]: `${w}px`,\n [\"--rtab-indicator-ready\" as string]: \"1\",\n });\n }\n };\n\n measure();\n\n if (typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(measure);\n ro.observe(tabListRef.current);\n return () => ro.disconnect();\n }, [activeValue, tabListRef, orientation]);\n\n return style;\n}\n\nexport const TabsStyled = forwardRef<HTMLDivElement, TabsStyledProps>(\n function TabsStyled(\n {\n tabs,\n variant = \"line\",\n size = \"md\",\n tone = \"neutral\",\n defaultValue,\n value,\n onChange,\n activation = \"automatic\",\n orientation = \"horizontal\",\n lazyMount = false,\n forceMount = false,\n renderTab,\n renderPanel,\n className,\n },\n ref,\n ) {\n const tabDefs = tabs.map((t) => ({ value: t.value, disabled: t.disabled }));\n\n const resolvedDefault =\n defaultValue ?? tabs.find((t) => !t.disabled)?.value;\n\n const { activeValue, getTabProps, getPanelProps } = useTabs({\n tabs: tabDefs,\n defaultValue: value === undefined ? resolvedDefault : undefined,\n value,\n onChange,\n activation,\n orientation,\n });\n\n const tabListRef = useRef<HTMLDivElement>(null);\n const indicatorStyle = useIndicator(tabListRef, activeValue, orientation);\n\n // Track which tabs have been activated for lazyMount.\n const activatedRef = useRef<Set<string>>(new Set());\n if (activeValue !== undefined) activatedRef.current.add(activeValue);\n\n const rootClass = [\"rtab-root\", className].filter(Boolean).join(\" \");\n\n return (\n <div\n ref={ref}\n className={rootClass}\n data-orientation={orientation}\n >\n <div\n ref={tabListRef}\n role=\"tablist\"\n aria-orientation={orientation}\n className=\"rtab-list\"\n data-variant={variant}\n data-size={size}\n data-tone={tone}\n data-orientation={orientation}\n style={indicatorStyle}\n >\n {tabs.map((tab, index) => {\n const isActive = activeValue === tab.value;\n const isDisabled = !!tab.disabled;\n return (\n <button\n key={tab.value}\n className=\"rtab-tab\"\n {...getTabProps(tab.value, { disabled: tab.disabled })}\n >\n {renderTab\n ? renderTab({ tab, index, isActive, isDisabled })\n : tab.label}\n </button>\n );\n })}\n {(variant === \"line\" || variant === \"solid\" || variant === \"pill\") && (\n <span className=\"rtab-indicator\" aria-hidden=\"true\" />\n )}\n </div>\n <div className=\"rtab-panels\">\n {tabs.map((tab) => {\n const isActive = activeValue === tab.value;\n const shouldRender =\n forceMount || !lazyMount || activatedRef.current.has(tab.value);\n return (\n <div\n key={tab.value}\n className=\"rtab-panel\"\n {...getPanelProps(tab.value)}\n >\n {shouldRender\n ? renderPanel\n ? renderPanel({ tab, isActive })\n : tab.content\n : null}\n </div>\n );\n })}\n </div>\n </div>\n );\n },\n);\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/styled/TabsStyled.tsx"],"names":["TabsStyled"],"mappings":"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","file":"styled.js","sourcesContent":["import {\n type CSSProperties,\n type ReactNode,\n forwardRef,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n useTabs,\n type TabsActivation,\n type TabsChangeReason,\n type TabsOrientation,\n} from \"../useTabs\";\n\nexport type TabsVariant = \"line\" | \"solid\" | \"pill\";\nexport type TabsSize = \"sm\" | \"md\" | \"lg\";\nexport type TabsTone = \"neutral\" | \"primary\" | \"success\" | \"danger\";\n\nexport interface TabItem {\n value: string;\n label: ReactNode;\n content: ReactNode;\n disabled?: boolean;\n /** When true, renders a × button on the tab. Pair with `onTabClose`. */\n closable?: boolean;\n}\n\nexport interface TabsRenderTabContext {\n tab: TabItem;\n index: number;\n isActive: boolean;\n isDisabled: boolean;\n}\n\nexport interface TabsRenderPanelContext {\n tab: TabItem;\n isActive: boolean;\n}\n\nexport interface TabsStyledProps {\n tabs: TabItem[];\n variant?: TabsVariant;\n size?: TabsSize;\n tone?: TabsTone;\n defaultValue?: string;\n value?: string;\n /** Optional second arg reports the trigger reason (\"click\" | \"keyboard\" | \"programmatic\"). */\n onChange?: (value: string, reason: TabsChangeReason) => void;\n /** \"automatic\" (default) — arrow keys move focus AND activate. \"manual\" — arrows move focus only. */\n activation?: TabsActivation;\n /** Affects keyboard nav direction. Default \"horizontal\". */\n orientation?: TabsOrientation;\n /** Only mount panels after they've been activated at least once. Default: false (all panels mount eagerly). */\n lazyMount?: boolean;\n /** Keep all panels mounted regardless of activation (useful with `lazyMount` overrides). Default: false. */\n forceMount?: boolean;\n /** Fires when the × on a closable tab is clicked. */\n onTabClose?: (value: string) => void;\n /** When true, the tab list scrolls horizontally with chevron buttons at the edges instead of wrapping. */\n scrollable?: boolean;\n /** When true, tabs can be reordered by dragging. Fires `onReorder` with the new value order. */\n sortable?: boolean;\n onReorder?: (values: string[]) => void;\n /** When true, the active tab is scrolled into view on activation. Default: true when `scrollable`. */\n scrollActiveIntoView?: boolean;\n /** Replace the default tab button content. The button shell (a11y, ref, key) stays owned by the component. */\n renderTab?: (ctx: TabsRenderTabContext) => ReactNode;\n /** Replace the default panel rendering. */\n renderPanel?: (ctx: TabsRenderPanelContext) => ReactNode;\n className?: string;\n}\n\n// Run layout effects on the client; fall back to a no-op effect on the server.\nconst useIsoLayoutEffect =\n typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\nfunction useIndicator(\n tabListRef: React.RefObject<HTMLDivElement | null>,\n activeValue: string | undefined,\n orientation: TabsOrientation,\n) {\n const [style, setStyle] = useState<CSSProperties>({});\n\n useIsoLayoutEffect(() => {\n if (!tabListRef.current || activeValue === undefined) return;\n\n const measure = () => {\n const list = tabListRef.current;\n if (!list) return;\n const activeTab = list.querySelector<HTMLElement>(\n `[aria-selected=\"true\"]`,\n );\n if (!activeTab) return;\n\n const listRect = list.getBoundingClientRect();\n const tabRect = activeTab.getBoundingClientRect();\n\n if (orientation === \"vertical\") {\n const y = tabRect.top - listRect.top;\n const h = tabRect.height;\n setStyle({\n [\"--rtab-indicator-y\" as string]: `${y}px`,\n [\"--rtab-indicator-height\" as string]: `${h}px`,\n [\"--rtab-indicator-ready\" as string]: \"1\",\n });\n } else {\n const x = tabRect.left - listRect.left;\n const w = tabRect.width;\n setStyle({\n [\"--rtab-indicator-x\" as string]: `${x}px`,\n [\"--rtab-indicator-width\" as string]: `${w}px`,\n [\"--rtab-indicator-ready\" as string]: \"1\",\n });\n }\n };\n\n measure();\n\n if (typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(measure);\n ro.observe(tabListRef.current);\n return () => ro.disconnect();\n }, [activeValue, tabListRef, orientation]);\n\n return style;\n}\n\nexport const TabsStyled = forwardRef<HTMLDivElement, TabsStyledProps>(\n function TabsStyled(\n {\n tabs,\n variant = \"line\",\n size = \"md\",\n tone = \"neutral\",\n defaultValue,\n value,\n onChange,\n activation = \"automatic\",\n orientation = \"horizontal\",\n lazyMount = false,\n forceMount = false,\n onTabClose,\n scrollable = false,\n sortable = false,\n onReorder,\n scrollActiveIntoView,\n renderTab,\n renderPanel,\n className,\n },\n ref,\n ) {\n const autoScrollActive = scrollActiveIntoView ?? scrollable;\n const [scrollState, setScrollState] = useState<{ left: boolean; right: boolean }>({\n left: false,\n right: false,\n });\n const typeaheadBufferRef = useRef(\"\");\n const typeaheadTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const dragValueRef = useRef<string | null>(null);\n const tabDefs = tabs.map((t) => ({ value: t.value, disabled: t.disabled }));\n\n const resolvedDefault =\n defaultValue ?? tabs.find((t) => !t.disabled)?.value;\n\n const { activeValue, getTabProps, getPanelProps } = useTabs({\n tabs: tabDefs,\n defaultValue: value === undefined ? resolvedDefault : undefined,\n value,\n onChange,\n activation,\n orientation,\n });\n\n const tabListRef = useRef<HTMLDivElement>(null);\n const indicatorStyle = useIndicator(tabListRef, activeValue, orientation);\n\n // Track which tabs have been activated for lazyMount.\n const activatedRef = useRef<Set<string>>(new Set());\n if (activeValue !== undefined) activatedRef.current.add(activeValue);\n\n const rootClass = [\"rtab-root\", className].filter(Boolean).join(\" \");\n\n // Scroll-state: detect when there's content off the left/right edges so we can\n // toggle the chevron buttons. Only relevant when scrollable.\n useEffect(() => {\n if (!scrollable) return;\n const list = tabListRef.current;\n if (!list) return;\n const update = () => {\n setScrollState({\n left: list.scrollLeft > 4,\n right: list.scrollLeft + list.clientWidth < list.scrollWidth - 4,\n });\n };\n update();\n list.addEventListener(\"scroll\", update, { passive: true });\n const ro = typeof ResizeObserver !== \"undefined\" ? new ResizeObserver(update) : null;\n ro?.observe(list);\n return () => {\n list.removeEventListener(\"scroll\", update);\n ro?.disconnect();\n };\n }, [scrollable, tabs.length]);\n\n // Auto-scroll active tab into view\n useEffect(() => {\n if (!autoScrollActive || !activeValue) return;\n const list = tabListRef.current;\n if (!list) return;\n const activeEl = list.querySelector<HTMLElement>(`[aria-selected=\"true\"]`);\n if (!activeEl) return;\n activeEl.scrollIntoView({ behavior: \"smooth\", block: \"nearest\", inline: \"nearest\" });\n }, [autoScrollActive, activeValue]);\n\n const scrollByAmount = (delta: number) => {\n tabListRef.current?.scrollBy({ left: delta, behavior: \"smooth\" });\n };\n\n // Typeahead: letters jump to the next tab whose label starts with the buffer.\n const handleTypeahead = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key.length !== 1 || e.altKey || e.ctrlKey || e.metaKey) return;\n typeaheadBufferRef.current = (typeaheadBufferRef.current + e.key).toLowerCase();\n if (typeaheadTimerRef.current) clearTimeout(typeaheadTimerRef.current);\n typeaheadTimerRef.current = setTimeout(() => { typeaheadBufferRef.current = \"\"; }, 600);\n\n const buffer = typeaheadBufferRef.current;\n const startIdx = Math.max(0, tabs.findIndex((t) => t.value === activeValue));\n // Search starting just after the active tab, wrapping around.\n for (let i = 1; i <= tabs.length; i++) {\n const idx = (startIdx + i) % tabs.length;\n const tab = tabs[idx];\n if (!tab || tab.disabled) continue;\n const labelStr = typeof tab.label === \"string\" ? tab.label : \"\";\n if (labelStr.toLowerCase().startsWith(buffer)) {\n // Use the existing tab button's click via aria-selected target.\n const list = tabListRef.current;\n const btn = list?.querySelector<HTMLButtonElement>(`[data-value=\"${tab.value}\"]`);\n btn?.click();\n btn?.focus();\n break;\n }\n }\n };\n\n // Drag-to-reorder: HTML5 DnD is fine here — no external lib.\n const handleDragStart = (val: string) => (e: React.DragEvent<HTMLButtonElement>) => {\n if (!sortable) return;\n dragValueRef.current = val;\n e.dataTransfer.effectAllowed = \"move\";\n };\n const handleDragOver = (val: string) => (e: React.DragEvent<HTMLButtonElement>) => {\n if (!sortable || !dragValueRef.current || dragValueRef.current === val) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n };\n const handleDrop = (val: string) => (e: React.DragEvent<HTMLButtonElement>) => {\n if (!sortable) return;\n e.preventDefault();\n const from = dragValueRef.current;\n dragValueRef.current = null;\n if (!from || from === val || !onReorder) return;\n const order = tabs.map((t) => t.value);\n const fromIdx = order.indexOf(from);\n const toIdx = order.indexOf(val);\n if (fromIdx === -1 || toIdx === -1) return;\n const next = [...order];\n next.splice(fromIdx, 1);\n next.splice(toIdx, 0, from);\n onReorder(next);\n };\n\n return (\n <div\n ref={ref}\n className={rootClass}\n data-orientation={orientation}\n data-scrollable={scrollable || undefined}\n onKeyDown={handleTypeahead}\n >\n <div className=\"rtab-list-wrap\">\n {scrollable && scrollState.left && (\n <button\n type=\"button\"\n className=\"rtab-scroll-btn rtab-scroll-btn--left\"\n aria-label=\"Scroll left\"\n onClick={() => scrollByAmount(-200)}\n >\n <svg viewBox=\"0 0 12 12\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M7.5 3l-3 3 3 3\"/></svg>\n </button>\n )}\n <div\n ref={tabListRef}\n role=\"tablist\"\n aria-orientation={orientation}\n className=\"rtab-list\"\n data-variant={variant}\n data-size={size}\n data-tone={tone}\n data-orientation={orientation}\n data-scrollable={scrollable || undefined}\n style={indicatorStyle}\n >\n {tabs.map((tab, index) => {\n const isActive = activeValue === tab.value;\n const isDisabled = !!tab.disabled;\n const tabProps = getTabProps(tab.value, { disabled: tab.disabled });\n return (\n <button\n key={tab.value}\n data-value={tab.value}\n data-closable={tab.closable || undefined}\n className=\"rtab-tab\"\n {...tabProps}\n draggable={sortable && !isDisabled ? true : undefined}\n onDragStart={sortable ? handleDragStart(tab.value) : undefined}\n onDragOver={sortable ? handleDragOver(tab.value) : undefined}\n onDrop={sortable ? handleDrop(tab.value) : undefined}\n >\n {renderTab\n ? renderTab({ tab, index, isActive, isDisabled })\n : tab.label}\n {tab.closable && (\n <span\n className=\"rtab-close\"\n role=\"button\"\n tabIndex={-1}\n aria-label={`Close ${typeof tab.label === \"string\" ? tab.label : \"tab\"}`}\n onClick={(e) => {\n e.stopPropagation();\n onTabClose?.(tab.value);\n }}\n >\n <svg viewBox=\"0 0 12 12\" width=\"10\" height=\"10\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" aria-hidden=\"true\">\n <path d=\"M3 3l6 6M9 3l-6 6\"/>\n </svg>\n </span>\n )}\n </button>\n );\n })}\n {(variant === \"line\" || variant === \"solid\" || variant === \"pill\") && (\n <span className=\"rtab-indicator\" aria-hidden=\"true\" />\n )}\n </div>\n {scrollable && scrollState.right && (\n <button\n type=\"button\"\n className=\"rtab-scroll-btn rtab-scroll-btn--right\"\n aria-label=\"Scroll right\"\n onClick={() => scrollByAmount(200)}\n >\n <svg viewBox=\"0 0 12 12\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M4.5 3l3 3-3 3\"/></svg>\n </button>\n )}\n </div>\n <div className=\"rtab-panels\">\n {tabs.map((tab) => {\n const isActive = activeValue === tab.value;\n const shouldRender =\n forceMount || !lazyMount || activatedRef.current.has(tab.value);\n return (\n <div\n key={tab.value}\n className=\"rtab-panel\"\n {...getPanelProps(tab.value)}\n >\n {shouldRender\n ? renderPanel\n ? renderPanel({ tab, isActive })\n : tab.content\n : null}\n </div>\n );\n })}\n </div>\n </div>\n );\n },\n);\n"]}
|
package/dist/styles.css
CHANGED
|
@@ -328,3 +328,91 @@
|
|
|
328
328
|
|
|
329
329
|
[data-theme="dark"] .rtab-list[data-tone="success"] { --rtab-fg-active: #bbf7d0; --rtab-bg-tab-active: #14532d; --rtab-bg-indicator: #4ade80; }
|
|
330
330
|
[data-theme="dark"] .rtab-list[data-tone="danger"] { --rtab-fg-active: #fecaca; --rtab-bg-tab-active: #7f1d1d; --rtab-bg-indicator: #f87171; }
|
|
331
|
+
|
|
332
|
+
/* ============================================================================
|
|
333
|
+
* Closeable / scrollable / sortable tabs (1.x additions)
|
|
334
|
+
* ============================================================================ */
|
|
335
|
+
|
|
336
|
+
/* Wrap that holds the list + the chevron scroll buttons */
|
|
337
|
+
.rtab-list-wrap {
|
|
338
|
+
position: relative;
|
|
339
|
+
display: flex;
|
|
340
|
+
align-items: stretch;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/* Scrollable mode — list itself becomes a horizontal scroll container */
|
|
344
|
+
.rtab-list[data-scrollable] {
|
|
345
|
+
overflow-x: auto;
|
|
346
|
+
scrollbar-width: none; /* Firefox */
|
|
347
|
+
scroll-behavior: smooth;
|
|
348
|
+
flex-wrap: nowrap;
|
|
349
|
+
}
|
|
350
|
+
.rtab-list[data-scrollable]::-webkit-scrollbar { display: none; }
|
|
351
|
+
.rtab-list[data-scrollable] .rtab-tab {
|
|
352
|
+
flex-shrink: 0;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/* Chevron scroll buttons */
|
|
356
|
+
.rtab-scroll-btn {
|
|
357
|
+
appearance: none;
|
|
358
|
+
background: var(--rtab-bg, transparent);
|
|
359
|
+
border: none;
|
|
360
|
+
width: 28px;
|
|
361
|
+
flex-shrink: 0;
|
|
362
|
+
display: inline-flex;
|
|
363
|
+
align-items: center;
|
|
364
|
+
justify-content: center;
|
|
365
|
+
cursor: pointer;
|
|
366
|
+
color: var(--rtab-fg-muted, currentColor);
|
|
367
|
+
opacity: 0.85;
|
|
368
|
+
transition: opacity 120ms ease, background 120ms ease;
|
|
369
|
+
}
|
|
370
|
+
.rtab-scroll-btn:hover { opacity: 1; }
|
|
371
|
+
.rtab-scroll-btn:focus-visible {
|
|
372
|
+
outline: 2px solid var(--rtab-color-active, #6366f1);
|
|
373
|
+
outline-offset: 1px;
|
|
374
|
+
}
|
|
375
|
+
.rtab-scroll-btn--left {
|
|
376
|
+
background: linear-gradient(to right, var(--rtab-bg, var(--bg, #fff)) 50%, transparent);
|
|
377
|
+
}
|
|
378
|
+
.rtab-scroll-btn--right {
|
|
379
|
+
background: linear-gradient(to left, var(--rtab-bg, var(--bg, #fff)) 50%, transparent);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/* Close (×) button on closable tabs */
|
|
383
|
+
.rtab-tab[data-closable] {
|
|
384
|
+
padding-right: 0.4rem;
|
|
385
|
+
}
|
|
386
|
+
.rtab-close {
|
|
387
|
+
display: inline-flex;
|
|
388
|
+
align-items: center;
|
|
389
|
+
justify-content: center;
|
|
390
|
+
width: 16px;
|
|
391
|
+
height: 16px;
|
|
392
|
+
margin-left: 0.4rem;
|
|
393
|
+
border-radius: 3px;
|
|
394
|
+
cursor: pointer;
|
|
395
|
+
color: var(--rtab-fg-muted, currentColor);
|
|
396
|
+
opacity: 0.55;
|
|
397
|
+
transition: background 120ms ease, opacity 120ms ease;
|
|
398
|
+
}
|
|
399
|
+
.rtab-close:hover {
|
|
400
|
+
opacity: 1;
|
|
401
|
+
background: var(--rtab-close-hover-bg, rgba(0, 0, 0, 0.08));
|
|
402
|
+
}
|
|
403
|
+
[data-theme="dark"] .rtab-close:hover {
|
|
404
|
+
background: var(--rtab-close-hover-bg, rgba(255, 255, 255, 0.12));
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/* Drag-to-reorder visuals */
|
|
408
|
+
.rtab-tab[draggable="true"] { cursor: grab; }
|
|
409
|
+
.rtab-tab[draggable="true"]:active { cursor: grabbing; }
|
|
410
|
+
.rtab-tab[draggable="true"]:hover {
|
|
411
|
+
background: var(--rtab-tab-hover-bg, rgba(0, 0, 0, 0.04));
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
@media (prefers-reduced-motion: reduce) {
|
|
415
|
+
.rtab-list { scroll-behavior: auto; }
|
|
416
|
+
.rtab-scroll-btn { transition: none; }
|
|
417
|
+
.rtab-close { transition: none; }
|
|
418
|
+
}
|
package/package.json
CHANGED