@arun-dev/headless 4.5.1 → 4.6.0
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/tabs/index.cjs +389 -0
- package/dist/tabs/index.d.cts +116 -0
- package/dist/tabs/index.d.ts +116 -0
- package/dist/tabs/index.js +248 -0
- package/package.json +11 -1
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/tabs/index.ts
|
|
21
|
+
var tabs_exports = {};
|
|
22
|
+
__export(tabs_exports, {
|
|
23
|
+
Tabs: () => index_parts_exports
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(tabs_exports);
|
|
26
|
+
|
|
27
|
+
// src/tabs/index.parts.ts
|
|
28
|
+
var index_parts_exports = {};
|
|
29
|
+
__export(index_parts_exports, {
|
|
30
|
+
List: () => TabsList,
|
|
31
|
+
Panel: () => TabsPanel,
|
|
32
|
+
Root: () => TabsRoot,
|
|
33
|
+
Tab: () => TabsTab
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// src/tabs/TabsRoot.tsx
|
|
37
|
+
var import_react4 = require("react");
|
|
38
|
+
|
|
39
|
+
// src/core/useControlled.ts
|
|
40
|
+
var import_react = require("react");
|
|
41
|
+
function useControlled({
|
|
42
|
+
controlled,
|
|
43
|
+
default: defaultValue,
|
|
44
|
+
name = "Component",
|
|
45
|
+
state = "value"
|
|
46
|
+
}) {
|
|
47
|
+
const { current: isControlled } = (0, import_react.useRef)(controlled !== void 0);
|
|
48
|
+
const [uncontrolled, setUncontrolled] = (0, import_react.useState)(defaultValue);
|
|
49
|
+
const defaultRef = (0, import_react.useRef)(defaultValue);
|
|
50
|
+
const value = isControlled ? controlled : uncontrolled;
|
|
51
|
+
if (process.env.NODE_ENV !== "production") {
|
|
52
|
+
if (isControlled !== (controlled !== void 0)) {
|
|
53
|
+
console.error(
|
|
54
|
+
`${name}: cannot switch between controlled and uncontrolled \`${state}\`. Decide which one this component is for the whole of its life.`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
if (!isControlled && defaultRef.current !== defaultValue) {
|
|
58
|
+
console.error(
|
|
59
|
+
`${name}: cannot change the default \`${state}\` after mount. It is only read once, so later changes are silently ignored.`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const setValue = (0, import_react.useCallback)(
|
|
64
|
+
(next) => {
|
|
65
|
+
if (!isControlled) setUncontrolled(next);
|
|
66
|
+
},
|
|
67
|
+
[isControlled]
|
|
68
|
+
);
|
|
69
|
+
return [value, setValue];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/core/useRender.ts
|
|
73
|
+
var import_react2 = require("react");
|
|
74
|
+
|
|
75
|
+
// src/core/mergeProps.ts
|
|
76
|
+
function isEventHandler(key) {
|
|
77
|
+
return key.length > 2 && key.startsWith("on") && key[2] === key[2]?.toUpperCase();
|
|
78
|
+
}
|
|
79
|
+
function mergeRefs(...refs) {
|
|
80
|
+
return (node) => {
|
|
81
|
+
const cleanups = refs.map((ref) => {
|
|
82
|
+
if (typeof ref === "function") {
|
|
83
|
+
const result = ref(node);
|
|
84
|
+
return typeof result === "function" ? result : () => ref(null);
|
|
85
|
+
}
|
|
86
|
+
if (ref && typeof ref === "object") {
|
|
87
|
+
ref.current = node;
|
|
88
|
+
return () => {
|
|
89
|
+
ref.current = null;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return void 0;
|
|
93
|
+
});
|
|
94
|
+
return () => {
|
|
95
|
+
cleanups.forEach((cleanup) => {
|
|
96
|
+
if (typeof cleanup === "function") cleanup();
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function isSyntheticEvent(event) {
|
|
102
|
+
return typeof event === "object" && event !== null && "nativeEvent" in event;
|
|
103
|
+
}
|
|
104
|
+
function makeEventPreventable(event) {
|
|
105
|
+
if (Object.prototype.hasOwnProperty.call(event, "preventComponentHandler")) return;
|
|
106
|
+
const target = event;
|
|
107
|
+
target.preventComponentHandler = () => {
|
|
108
|
+
target.componentHandlerPrevented = true;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function isComponentHandlerPrevented(event) {
|
|
112
|
+
return typeof event === "object" && event !== null && event.componentHandlerPrevented === true;
|
|
113
|
+
}
|
|
114
|
+
function chainHandlers(earlier, value) {
|
|
115
|
+
return (...args) => {
|
|
116
|
+
const event = args[0];
|
|
117
|
+
if (isSyntheticEvent(event)) makeEventPreventable(event);
|
|
118
|
+
value(...args);
|
|
119
|
+
if (isComponentHandlerPrevented(event)) return;
|
|
120
|
+
earlier(...args);
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function mergeProps(...objects) {
|
|
124
|
+
const merged = {};
|
|
125
|
+
for (const props of objects) {
|
|
126
|
+
if (!props) continue;
|
|
127
|
+
for (const key of Object.keys(props)) {
|
|
128
|
+
const value = props[key];
|
|
129
|
+
if (value === void 0) continue;
|
|
130
|
+
if (isEventHandler(key) && typeof value === "function") {
|
|
131
|
+
const earlier = merged[key];
|
|
132
|
+
merged[key] = typeof earlier === "function" ? chainHandlers(earlier, value) : value;
|
|
133
|
+
} else if (key === "className") {
|
|
134
|
+
merged.className = merged.className ? `${String(merged.className)} ${String(value)}` : value;
|
|
135
|
+
} else if (key === "style") {
|
|
136
|
+
merged.style = { ...merged.style, ...value };
|
|
137
|
+
} else if (key === "ref") {
|
|
138
|
+
merged.ref = merged.ref ? mergeRefs(merged.ref, value) : value;
|
|
139
|
+
} else {
|
|
140
|
+
merged[key] = value;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return merged;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/core/useRender.ts
|
|
148
|
+
function useRender({
|
|
149
|
+
render,
|
|
150
|
+
defaultTagName,
|
|
151
|
+
props,
|
|
152
|
+
consumerProps
|
|
153
|
+
}) {
|
|
154
|
+
const merged = mergeProps(props, consumerProps);
|
|
155
|
+
if ((0, import_react2.isValidElement)(render)) {
|
|
156
|
+
return (0, import_react2.cloneElement)(render, mergeProps(merged, render.props));
|
|
157
|
+
}
|
|
158
|
+
return (0, import_react2.createElement)(defaultTagName, merged);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/tabs/TabsRootContext.ts
|
|
162
|
+
var import_react3 = require("react");
|
|
163
|
+
var TabsRootContext = (0, import_react3.createContext)(null);
|
|
164
|
+
function useTabsRootContext(part) {
|
|
165
|
+
const context = (0, import_react3.useContext)(TabsRootContext);
|
|
166
|
+
if (context === null) {
|
|
167
|
+
throw new Error(`<Tabs.${part}> must be rendered inside <Tabs.Root>.`);
|
|
168
|
+
}
|
|
169
|
+
return context;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/tabs/tabsDataAttributes.ts
|
|
173
|
+
function orientationDataAttributes(orientation) {
|
|
174
|
+
return { "data-orientation": orientation };
|
|
175
|
+
}
|
|
176
|
+
function selectedDataAttributes(selected, disabled = false) {
|
|
177
|
+
return {
|
|
178
|
+
"data-selected": selected ? "" : void 0,
|
|
179
|
+
"data-unselected": selected ? void 0 : "",
|
|
180
|
+
"data-disabled": disabled ? "" : void 0
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/tabs/TabsRoot.tsx
|
|
185
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
186
|
+
function idPart(value) {
|
|
187
|
+
return value.replace(/\s+/g, "_");
|
|
188
|
+
}
|
|
189
|
+
function documentOrder(a, b) {
|
|
190
|
+
const x = a.ref.current;
|
|
191
|
+
const y = b.ref.current;
|
|
192
|
+
if (!x || !y) return 0;
|
|
193
|
+
return x.compareDocumentPosition(y) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
|
|
194
|
+
}
|
|
195
|
+
function TabsRoot({
|
|
196
|
+
value: valueProp,
|
|
197
|
+
defaultValue,
|
|
198
|
+
onValueChange,
|
|
199
|
+
orientation = "horizontal",
|
|
200
|
+
activationMode = "automatic",
|
|
201
|
+
className,
|
|
202
|
+
children,
|
|
203
|
+
render,
|
|
204
|
+
...rest
|
|
205
|
+
}) {
|
|
206
|
+
const [value, setValueState] = useControlled({
|
|
207
|
+
controlled: valueProp,
|
|
208
|
+
default: defaultValue,
|
|
209
|
+
name: "Tabs.Root",
|
|
210
|
+
state: "value"
|
|
211
|
+
});
|
|
212
|
+
const setValue = (0, import_react4.useCallback)(
|
|
213
|
+
(next) => {
|
|
214
|
+
if (next === value) return;
|
|
215
|
+
setValueState(next);
|
|
216
|
+
onValueChange?.(next);
|
|
217
|
+
},
|
|
218
|
+
[value, setValueState, onValueChange]
|
|
219
|
+
);
|
|
220
|
+
const [tabs, setTabs] = (0, import_react4.useState)([]);
|
|
221
|
+
const register = (0, import_react4.useCallback)((entry) => {
|
|
222
|
+
setTabs(
|
|
223
|
+
(current) => [...current.filter((t) => t.value !== entry.value), entry].sort(documentOrder)
|
|
224
|
+
);
|
|
225
|
+
return () => setTabs((current) => current.filter((t) => t !== entry));
|
|
226
|
+
}, []);
|
|
227
|
+
const enabledTabs = (0, import_react4.useMemo)(() => tabs.filter((t) => !t.disabled), [tabs]);
|
|
228
|
+
const tabStopValue = tabs.length === 0 ? value : (enabledTabs.find((t) => t.value === value) ?? enabledTabs[0])?.value;
|
|
229
|
+
const baseId = (0, import_react4.useId)();
|
|
230
|
+
const context = (0, import_react4.useMemo)(
|
|
231
|
+
() => ({
|
|
232
|
+
value,
|
|
233
|
+
setValue,
|
|
234
|
+
orientation,
|
|
235
|
+
activationMode,
|
|
236
|
+
enabledTabs,
|
|
237
|
+
tabStopValue,
|
|
238
|
+
register,
|
|
239
|
+
tabId: (v) => `${baseId}-tab-${idPart(v)}`,
|
|
240
|
+
panelId: (v) => `${baseId}-panel-${idPart(v)}`
|
|
241
|
+
}),
|
|
242
|
+
[value, setValue, orientation, activationMode, enabledTabs, tabStopValue, register, baseId]
|
|
243
|
+
);
|
|
244
|
+
const element = useRender({
|
|
245
|
+
render,
|
|
246
|
+
defaultTagName: "div",
|
|
247
|
+
props: { ...orientationDataAttributes(orientation), className, children },
|
|
248
|
+
consumerProps: rest
|
|
249
|
+
});
|
|
250
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TabsRootContext.Provider, { value: context, children: element });
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/tabs/TabsList.tsx
|
|
254
|
+
var import_react5 = require("react");
|
|
255
|
+
|
|
256
|
+
// src/core/rovingFocus.ts
|
|
257
|
+
function rovingIndex(key, {
|
|
258
|
+
count,
|
|
259
|
+
current,
|
|
260
|
+
orientation,
|
|
261
|
+
rtl
|
|
262
|
+
}) {
|
|
263
|
+
if (count === 0) return null;
|
|
264
|
+
const [prevKey, nextKey] = orientation === "vertical" ? ["ArrowUp", "ArrowDown"] : rtl ? ["ArrowRight", "ArrowLeft"] : ["ArrowLeft", "ArrowRight"];
|
|
265
|
+
switch (key) {
|
|
266
|
+
case nextKey:
|
|
267
|
+
return current < 0 ? 0 : (current + 1) % count;
|
|
268
|
+
case prevKey:
|
|
269
|
+
return current < 0 ? count - 1 : (current - 1 + count) % count;
|
|
270
|
+
case "Home":
|
|
271
|
+
return 0;
|
|
272
|
+
case "End":
|
|
273
|
+
return count - 1;
|
|
274
|
+
default:
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// src/tabs/TabsList.tsx
|
|
280
|
+
function TabsList({ className, children, render, ...rest }) {
|
|
281
|
+
const { orientation, enabledTabs } = useTabsRootContext("List");
|
|
282
|
+
const elementRef = (0, import_react5.useRef)(null);
|
|
283
|
+
return useRender({
|
|
284
|
+
render,
|
|
285
|
+
defaultTagName: "div",
|
|
286
|
+
props: {
|
|
287
|
+
role: "tablist",
|
|
288
|
+
// Horizontal is the ARIA default for a tablist, so it is only stated when vertical.
|
|
289
|
+
"aria-orientation": orientation === "vertical" ? "vertical" : void 0,
|
|
290
|
+
...orientationDataAttributes(orientation),
|
|
291
|
+
className,
|
|
292
|
+
children,
|
|
293
|
+
ref: elementRef,
|
|
294
|
+
onKeyDown(event) {
|
|
295
|
+
const current = enabledTabs.findIndex((t) => t.ref.current === event.target);
|
|
296
|
+
if (current < 0) return;
|
|
297
|
+
const list = elementRef.current;
|
|
298
|
+
const rtl = list ? getComputedStyle(list).direction === "rtl" : false;
|
|
299
|
+
const next = rovingIndex(event.key, {
|
|
300
|
+
count: enabledTabs.length,
|
|
301
|
+
current,
|
|
302
|
+
orientation,
|
|
303
|
+
rtl
|
|
304
|
+
});
|
|
305
|
+
if (next === null) return;
|
|
306
|
+
event.preventDefault();
|
|
307
|
+
enabledTabs[next]?.ref.current?.focus();
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
consumerProps: rest
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/tabs/TabsTab.tsx
|
|
315
|
+
var import_react6 = require("react");
|
|
316
|
+
function TabsTab({
|
|
317
|
+
value,
|
|
318
|
+
disabled = false,
|
|
319
|
+
className,
|
|
320
|
+
children,
|
|
321
|
+
render,
|
|
322
|
+
...rest
|
|
323
|
+
}) {
|
|
324
|
+
const {
|
|
325
|
+
value: selectedValue,
|
|
326
|
+
setValue,
|
|
327
|
+
activationMode,
|
|
328
|
+
tabStopValue,
|
|
329
|
+
register,
|
|
330
|
+
tabId,
|
|
331
|
+
panelId
|
|
332
|
+
} = useTabsRootContext("Tab");
|
|
333
|
+
const elementRef = (0, import_react6.useRef)(null);
|
|
334
|
+
const selected = value === selectedValue;
|
|
335
|
+
(0, import_react6.useLayoutEffect)(
|
|
336
|
+
() => register({ value, disabled, ref: elementRef }),
|
|
337
|
+
[register, value, disabled]
|
|
338
|
+
);
|
|
339
|
+
return useRender({
|
|
340
|
+
render,
|
|
341
|
+
defaultTagName: "button",
|
|
342
|
+
props: {
|
|
343
|
+
type: "button",
|
|
344
|
+
role: "tab",
|
|
345
|
+
id: tabId(value),
|
|
346
|
+
"aria-selected": selected,
|
|
347
|
+
"aria-controls": panelId(value),
|
|
348
|
+
tabIndex: value === tabStopValue ? 0 : -1,
|
|
349
|
+
// The platform keeps a disabled button out of focus and activation.
|
|
350
|
+
disabled: disabled || void 0,
|
|
351
|
+
...selectedDataAttributes(selected, disabled),
|
|
352
|
+
className,
|
|
353
|
+
children,
|
|
354
|
+
ref: elementRef,
|
|
355
|
+
onClick() {
|
|
356
|
+
if (!disabled) setValue(value);
|
|
357
|
+
},
|
|
358
|
+
onFocus() {
|
|
359
|
+
if (activationMode === "automatic" && !disabled) setValue(value);
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
consumerProps: rest
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// src/tabs/TabsPanel.tsx
|
|
367
|
+
function TabsPanel({ value, className, children, render, ...rest }) {
|
|
368
|
+
const { value: selectedValue, tabId, panelId } = useTabsRootContext("Panel");
|
|
369
|
+
const selected = value === selectedValue;
|
|
370
|
+
return useRender({
|
|
371
|
+
render,
|
|
372
|
+
defaultTagName: "div",
|
|
373
|
+
props: {
|
|
374
|
+
role: "tabpanel",
|
|
375
|
+
id: panelId(value),
|
|
376
|
+
"aria-labelledby": tabId(value),
|
|
377
|
+
tabIndex: 0,
|
|
378
|
+
hidden: !selected || void 0,
|
|
379
|
+
...selectedDataAttributes(selected),
|
|
380
|
+
className,
|
|
381
|
+
children
|
|
382
|
+
},
|
|
383
|
+
consumerProps: rest
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
387
|
+
0 && (module.exports = {
|
|
388
|
+
Tabs
|
|
389
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactElement, Ref, ComponentPropsWithRef } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Roving focus for composite widgets — one Tab stop for the group, arrow keys within it.
|
|
6
|
+
* Tabs first; Menu and Toolbar reuse it. Internal: shared between components, not exported
|
|
7
|
+
* (decision 9).
|
|
8
|
+
*
|
|
9
|
+
* The caller owns the list of items and which are enabled — from component props, never
|
|
10
|
+
* read back from the DOM (decision 10). This only answers "where does this key go".
|
|
11
|
+
*/
|
|
12
|
+
type Orientation = 'horizontal' | 'vertical';
|
|
13
|
+
|
|
14
|
+
type TabsActivationMode = 'automatic' | 'manual';
|
|
15
|
+
/** The state Tabs.Root shares with its parts, and projects as `data-*` attributes. */
|
|
16
|
+
type TabsState = {
|
|
17
|
+
value: string | undefined;
|
|
18
|
+
orientation: Orientation;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type TabsRootOwnProps = {
|
|
22
|
+
/**
|
|
23
|
+
* Controlled selection: the `value` of the selected Tab. Provide `onValueChange` alongside.
|
|
24
|
+
*
|
|
25
|
+
* Never `undefined` once mounted: the mode is latched at mount, as for Switch.
|
|
26
|
+
*/
|
|
27
|
+
value?: string;
|
|
28
|
+
/** Initial selection when uncontrolled. Read once, at mount. Without one, none is selected. */
|
|
29
|
+
defaultValue?: string;
|
|
30
|
+
/** Called with the Tab's `value` whenever the selection changes. */
|
|
31
|
+
onValueChange?: (value: string) => void;
|
|
32
|
+
/** The axis the tabs run along, and so which arrow keys move between them. */
|
|
33
|
+
orientation?: Orientation;
|
|
34
|
+
/**
|
|
35
|
+
* `automatic` selects a tab as soon as it has focus; `manual` waits for Enter, Space or a
|
|
36
|
+
* click. Manual suits panels that are slow to show.
|
|
37
|
+
*/
|
|
38
|
+
activationMode?: TabsActivationMode;
|
|
39
|
+
/** Element to render instead of the default `<div>`. Props and ref are merged onto it. */
|
|
40
|
+
render?: ReactElement;
|
|
41
|
+
/** Ref to the rendered element. Merged with any ref on the `render` element. */
|
|
42
|
+
ref?: Ref<HTMLElement>;
|
|
43
|
+
};
|
|
44
|
+
type TabsRootProps = TabsRootOwnProps & Omit<ComponentPropsWithRef<'div'>, keyof TabsRootOwnProps | 'defaultValue' | 'onChange'>;
|
|
45
|
+
/**
|
|
46
|
+
* Tabs, by the WAI-ARIA pattern: a tablist of tabs, one panel each, one selected.
|
|
47
|
+
*
|
|
48
|
+
* There is no native element to lean on (decision 7), so the behaviour is built here: the
|
|
49
|
+
* selection, arrow-key focus with a single Tab stop (roving tabindex, `core/rovingFocus`),
|
|
50
|
+
* and the ids that wire each tab to its panel.
|
|
51
|
+
*
|
|
52
|
+
* Each Tab registers its own `value` and `disabled` from its props; the Root never reads
|
|
53
|
+
* them back from the DOM (decision 10). Elements are kept only to move focus to.
|
|
54
|
+
*/
|
|
55
|
+
declare function TabsRoot({ value: valueProp, defaultValue, onValueChange, orientation, activationMode, className, children, render, ...rest }: TabsRootProps): react.JSX.Element;
|
|
56
|
+
|
|
57
|
+
type TabsListOwnProps = {
|
|
58
|
+
/** Element to render instead of the default `<div>`. Props and ref are merged onto it. */
|
|
59
|
+
render?: ReactElement;
|
|
60
|
+
/** Ref to the rendered element. Merged with any ref on the `render` element. */
|
|
61
|
+
ref?: Ref<HTMLElement>;
|
|
62
|
+
};
|
|
63
|
+
type TabsListProps = TabsListOwnProps & Omit<ComponentPropsWithRef<'div'>, keyof TabsListOwnProps>;
|
|
64
|
+
/**
|
|
65
|
+
* The tablist. Holds the keyboard: arrows along the orientation, wrapping at the ends,
|
|
66
|
+
* Home and End — moving focus among the enabled tabs only. Whether focusing a tab also
|
|
67
|
+
* selects it is the Tab's to decide, by `activationMode`.
|
|
68
|
+
*
|
|
69
|
+
* Name it with `aria-label` or `aria-labelledby` when the page has more than one.
|
|
70
|
+
*/
|
|
71
|
+
declare function TabsList({ className, children, render, ...rest }: TabsListProps): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
|
|
72
|
+
|
|
73
|
+
type TabsTabOwnProps = {
|
|
74
|
+
/** Identifies this tab, and the Panel with the same `value`. */
|
|
75
|
+
value: string;
|
|
76
|
+
/** Skipped by the arrow keys and cannot be selected. */
|
|
77
|
+
disabled?: boolean;
|
|
78
|
+
/** Element to render instead of the default `<button>`. Props and ref are merged onto it. */
|
|
79
|
+
render?: ReactElement;
|
|
80
|
+
/** Ref to the rendered element. Merged with any ref on the `render` element. */
|
|
81
|
+
ref?: Ref<HTMLElement>;
|
|
82
|
+
};
|
|
83
|
+
type TabsTabProps = TabsTabOwnProps & Omit<ComponentPropsWithRef<'button'>, keyof TabsTabOwnProps | 'value'>;
|
|
84
|
+
/**
|
|
85
|
+
* One tab. A native `<button>`, so Enter, Space and a click select it with no key handling
|
|
86
|
+
* here. Only the tab holding the group's Tab stop has `tabIndex={0}` — roving tabindex — so
|
|
87
|
+
* Tab enters the list at the selected tab and leaves it after one press.
|
|
88
|
+
*
|
|
89
|
+
* With `activationMode="automatic"` (the default) focus selects: the arrow keys change the
|
|
90
|
+
* panel as they move. With `"manual"` they only move focus.
|
|
91
|
+
*/
|
|
92
|
+
declare function TabsTab({ value, disabled, className, children, render, ...rest }: TabsTabProps): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
|
|
93
|
+
|
|
94
|
+
type TabsPanelOwnProps = {
|
|
95
|
+
/** The `value` of the Tab this panel belongs to. */
|
|
96
|
+
value: string;
|
|
97
|
+
/** Element to render instead of the default `<div>`. Props and ref are merged onto it. */
|
|
98
|
+
render?: ReactElement;
|
|
99
|
+
/** Ref to the rendered element. Merged with any ref on the `render` element. */
|
|
100
|
+
ref?: Ref<HTMLElement>;
|
|
101
|
+
};
|
|
102
|
+
type TabsPanelProps = TabsPanelOwnProps & Omit<ComponentPropsWithRef<'div'>, keyof TabsPanelOwnProps>;
|
|
103
|
+
/**
|
|
104
|
+
* The content for one tab, labelled by it. Hidden with the `hidden` attribute while its tab
|
|
105
|
+
* is not selected, and stays mounted, so what is inside keeps its state between visits.
|
|
106
|
+
*
|
|
107
|
+
* `tabIndex={0}`, as the pattern recommends, so a panel with nothing focusable inside is
|
|
108
|
+
* still reached by Tab after the tablist.
|
|
109
|
+
*/
|
|
110
|
+
declare function TabsPanel({ value, className, children, render, ...rest }: TabsPanelProps): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
|
|
111
|
+
|
|
112
|
+
declare namespace index_parts {
|
|
113
|
+
export { TabsList as List, TabsPanel as Panel, TabsRoot as Root, TabsTab as Tab };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export { index_parts as Tabs, type TabsActivationMode, type TabsListProps, type TabsPanelProps, type TabsRootProps, type TabsState, type TabsTabProps };
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactElement, Ref, ComponentPropsWithRef } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Roving focus for composite widgets — one Tab stop for the group, arrow keys within it.
|
|
6
|
+
* Tabs first; Menu and Toolbar reuse it. Internal: shared between components, not exported
|
|
7
|
+
* (decision 9).
|
|
8
|
+
*
|
|
9
|
+
* The caller owns the list of items and which are enabled — from component props, never
|
|
10
|
+
* read back from the DOM (decision 10). This only answers "where does this key go".
|
|
11
|
+
*/
|
|
12
|
+
type Orientation = 'horizontal' | 'vertical';
|
|
13
|
+
|
|
14
|
+
type TabsActivationMode = 'automatic' | 'manual';
|
|
15
|
+
/** The state Tabs.Root shares with its parts, and projects as `data-*` attributes. */
|
|
16
|
+
type TabsState = {
|
|
17
|
+
value: string | undefined;
|
|
18
|
+
orientation: Orientation;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type TabsRootOwnProps = {
|
|
22
|
+
/**
|
|
23
|
+
* Controlled selection: the `value` of the selected Tab. Provide `onValueChange` alongside.
|
|
24
|
+
*
|
|
25
|
+
* Never `undefined` once mounted: the mode is latched at mount, as for Switch.
|
|
26
|
+
*/
|
|
27
|
+
value?: string;
|
|
28
|
+
/** Initial selection when uncontrolled. Read once, at mount. Without one, none is selected. */
|
|
29
|
+
defaultValue?: string;
|
|
30
|
+
/** Called with the Tab's `value` whenever the selection changes. */
|
|
31
|
+
onValueChange?: (value: string) => void;
|
|
32
|
+
/** The axis the tabs run along, and so which arrow keys move between them. */
|
|
33
|
+
orientation?: Orientation;
|
|
34
|
+
/**
|
|
35
|
+
* `automatic` selects a tab as soon as it has focus; `manual` waits for Enter, Space or a
|
|
36
|
+
* click. Manual suits panels that are slow to show.
|
|
37
|
+
*/
|
|
38
|
+
activationMode?: TabsActivationMode;
|
|
39
|
+
/** Element to render instead of the default `<div>`. Props and ref are merged onto it. */
|
|
40
|
+
render?: ReactElement;
|
|
41
|
+
/** Ref to the rendered element. Merged with any ref on the `render` element. */
|
|
42
|
+
ref?: Ref<HTMLElement>;
|
|
43
|
+
};
|
|
44
|
+
type TabsRootProps = TabsRootOwnProps & Omit<ComponentPropsWithRef<'div'>, keyof TabsRootOwnProps | 'defaultValue' | 'onChange'>;
|
|
45
|
+
/**
|
|
46
|
+
* Tabs, by the WAI-ARIA pattern: a tablist of tabs, one panel each, one selected.
|
|
47
|
+
*
|
|
48
|
+
* There is no native element to lean on (decision 7), so the behaviour is built here: the
|
|
49
|
+
* selection, arrow-key focus with a single Tab stop (roving tabindex, `core/rovingFocus`),
|
|
50
|
+
* and the ids that wire each tab to its panel.
|
|
51
|
+
*
|
|
52
|
+
* Each Tab registers its own `value` and `disabled` from its props; the Root never reads
|
|
53
|
+
* them back from the DOM (decision 10). Elements are kept only to move focus to.
|
|
54
|
+
*/
|
|
55
|
+
declare function TabsRoot({ value: valueProp, defaultValue, onValueChange, orientation, activationMode, className, children, render, ...rest }: TabsRootProps): react.JSX.Element;
|
|
56
|
+
|
|
57
|
+
type TabsListOwnProps = {
|
|
58
|
+
/** Element to render instead of the default `<div>`. Props and ref are merged onto it. */
|
|
59
|
+
render?: ReactElement;
|
|
60
|
+
/** Ref to the rendered element. Merged with any ref on the `render` element. */
|
|
61
|
+
ref?: Ref<HTMLElement>;
|
|
62
|
+
};
|
|
63
|
+
type TabsListProps = TabsListOwnProps & Omit<ComponentPropsWithRef<'div'>, keyof TabsListOwnProps>;
|
|
64
|
+
/**
|
|
65
|
+
* The tablist. Holds the keyboard: arrows along the orientation, wrapping at the ends,
|
|
66
|
+
* Home and End — moving focus among the enabled tabs only. Whether focusing a tab also
|
|
67
|
+
* selects it is the Tab's to decide, by `activationMode`.
|
|
68
|
+
*
|
|
69
|
+
* Name it with `aria-label` or `aria-labelledby` when the page has more than one.
|
|
70
|
+
*/
|
|
71
|
+
declare function TabsList({ className, children, render, ...rest }: TabsListProps): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
|
|
72
|
+
|
|
73
|
+
type TabsTabOwnProps = {
|
|
74
|
+
/** Identifies this tab, and the Panel with the same `value`. */
|
|
75
|
+
value: string;
|
|
76
|
+
/** Skipped by the arrow keys and cannot be selected. */
|
|
77
|
+
disabled?: boolean;
|
|
78
|
+
/** Element to render instead of the default `<button>`. Props and ref are merged onto it. */
|
|
79
|
+
render?: ReactElement;
|
|
80
|
+
/** Ref to the rendered element. Merged with any ref on the `render` element. */
|
|
81
|
+
ref?: Ref<HTMLElement>;
|
|
82
|
+
};
|
|
83
|
+
type TabsTabProps = TabsTabOwnProps & Omit<ComponentPropsWithRef<'button'>, keyof TabsTabOwnProps | 'value'>;
|
|
84
|
+
/**
|
|
85
|
+
* One tab. A native `<button>`, so Enter, Space and a click select it with no key handling
|
|
86
|
+
* here. Only the tab holding the group's Tab stop has `tabIndex={0}` — roving tabindex — so
|
|
87
|
+
* Tab enters the list at the selected tab and leaves it after one press.
|
|
88
|
+
*
|
|
89
|
+
* With `activationMode="automatic"` (the default) focus selects: the arrow keys change the
|
|
90
|
+
* panel as they move. With `"manual"` they only move focus.
|
|
91
|
+
*/
|
|
92
|
+
declare function TabsTab({ value, disabled, className, children, render, ...rest }: TabsTabProps): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
|
|
93
|
+
|
|
94
|
+
type TabsPanelOwnProps = {
|
|
95
|
+
/** The `value` of the Tab this panel belongs to. */
|
|
96
|
+
value: string;
|
|
97
|
+
/** Element to render instead of the default `<div>`. Props and ref are merged onto it. */
|
|
98
|
+
render?: ReactElement;
|
|
99
|
+
/** Ref to the rendered element. Merged with any ref on the `render` element. */
|
|
100
|
+
ref?: Ref<HTMLElement>;
|
|
101
|
+
};
|
|
102
|
+
type TabsPanelProps = TabsPanelOwnProps & Omit<ComponentPropsWithRef<'div'>, keyof TabsPanelOwnProps>;
|
|
103
|
+
/**
|
|
104
|
+
* The content for one tab, labelled by it. Hidden with the `hidden` attribute while its tab
|
|
105
|
+
* is not selected, and stays mounted, so what is inside keeps its state between visits.
|
|
106
|
+
*
|
|
107
|
+
* `tabIndex={0}`, as the pattern recommends, so a panel with nothing focusable inside is
|
|
108
|
+
* still reached by Tab after the tablist.
|
|
109
|
+
*/
|
|
110
|
+
declare function TabsPanel({ value, className, children, render, ...rest }: TabsPanelProps): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
|
|
111
|
+
|
|
112
|
+
declare namespace index_parts {
|
|
113
|
+
export { TabsList as List, TabsPanel as Panel, TabsRoot as Root, TabsTab as Tab };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export { index_parts as Tabs, type TabsActivationMode, type TabsListProps, type TabsPanelProps, type TabsRootProps, type TabsState, type TabsTabProps };
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useControlled
|
|
3
|
+
} from "../chunk-UEIB3I3T.js";
|
|
4
|
+
import {
|
|
5
|
+
__export,
|
|
6
|
+
useRender
|
|
7
|
+
} from "../chunk-OQTWWZ4B.js";
|
|
8
|
+
|
|
9
|
+
// src/tabs/index.parts.ts
|
|
10
|
+
var index_parts_exports = {};
|
|
11
|
+
__export(index_parts_exports, {
|
|
12
|
+
List: () => TabsList,
|
|
13
|
+
Panel: () => TabsPanel,
|
|
14
|
+
Root: () => TabsRoot,
|
|
15
|
+
Tab: () => TabsTab
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// src/tabs/TabsRoot.tsx
|
|
19
|
+
import { useCallback, useId, useMemo, useState } from "react";
|
|
20
|
+
|
|
21
|
+
// src/tabs/TabsRootContext.ts
|
|
22
|
+
import { createContext, useContext } from "react";
|
|
23
|
+
var TabsRootContext = createContext(null);
|
|
24
|
+
function useTabsRootContext(part) {
|
|
25
|
+
const context = useContext(TabsRootContext);
|
|
26
|
+
if (context === null) {
|
|
27
|
+
throw new Error(`<Tabs.${part}> must be rendered inside <Tabs.Root>.`);
|
|
28
|
+
}
|
|
29
|
+
return context;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/tabs/tabsDataAttributes.ts
|
|
33
|
+
function orientationDataAttributes(orientation) {
|
|
34
|
+
return { "data-orientation": orientation };
|
|
35
|
+
}
|
|
36
|
+
function selectedDataAttributes(selected, disabled = false) {
|
|
37
|
+
return {
|
|
38
|
+
"data-selected": selected ? "" : void 0,
|
|
39
|
+
"data-unselected": selected ? void 0 : "",
|
|
40
|
+
"data-disabled": disabled ? "" : void 0
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/tabs/TabsRoot.tsx
|
|
45
|
+
import { jsx } from "react/jsx-runtime";
|
|
46
|
+
function idPart(value) {
|
|
47
|
+
return value.replace(/\s+/g, "_");
|
|
48
|
+
}
|
|
49
|
+
function documentOrder(a, b) {
|
|
50
|
+
const x = a.ref.current;
|
|
51
|
+
const y = b.ref.current;
|
|
52
|
+
if (!x || !y) return 0;
|
|
53
|
+
return x.compareDocumentPosition(y) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
|
|
54
|
+
}
|
|
55
|
+
function TabsRoot({
|
|
56
|
+
value: valueProp,
|
|
57
|
+
defaultValue,
|
|
58
|
+
onValueChange,
|
|
59
|
+
orientation = "horizontal",
|
|
60
|
+
activationMode = "automatic",
|
|
61
|
+
className,
|
|
62
|
+
children,
|
|
63
|
+
render,
|
|
64
|
+
...rest
|
|
65
|
+
}) {
|
|
66
|
+
const [value, setValueState] = useControlled({
|
|
67
|
+
controlled: valueProp,
|
|
68
|
+
default: defaultValue,
|
|
69
|
+
name: "Tabs.Root",
|
|
70
|
+
state: "value"
|
|
71
|
+
});
|
|
72
|
+
const setValue = useCallback(
|
|
73
|
+
(next) => {
|
|
74
|
+
if (next === value) return;
|
|
75
|
+
setValueState(next);
|
|
76
|
+
onValueChange?.(next);
|
|
77
|
+
},
|
|
78
|
+
[value, setValueState, onValueChange]
|
|
79
|
+
);
|
|
80
|
+
const [tabs, setTabs] = useState([]);
|
|
81
|
+
const register = useCallback((entry) => {
|
|
82
|
+
setTabs(
|
|
83
|
+
(current) => [...current.filter((t) => t.value !== entry.value), entry].sort(documentOrder)
|
|
84
|
+
);
|
|
85
|
+
return () => setTabs((current) => current.filter((t) => t !== entry));
|
|
86
|
+
}, []);
|
|
87
|
+
const enabledTabs = useMemo(() => tabs.filter((t) => !t.disabled), [tabs]);
|
|
88
|
+
const tabStopValue = tabs.length === 0 ? value : (enabledTabs.find((t) => t.value === value) ?? enabledTabs[0])?.value;
|
|
89
|
+
const baseId = useId();
|
|
90
|
+
const context = useMemo(
|
|
91
|
+
() => ({
|
|
92
|
+
value,
|
|
93
|
+
setValue,
|
|
94
|
+
orientation,
|
|
95
|
+
activationMode,
|
|
96
|
+
enabledTabs,
|
|
97
|
+
tabStopValue,
|
|
98
|
+
register,
|
|
99
|
+
tabId: (v) => `${baseId}-tab-${idPart(v)}`,
|
|
100
|
+
panelId: (v) => `${baseId}-panel-${idPart(v)}`
|
|
101
|
+
}),
|
|
102
|
+
[value, setValue, orientation, activationMode, enabledTabs, tabStopValue, register, baseId]
|
|
103
|
+
);
|
|
104
|
+
const element = useRender({
|
|
105
|
+
render,
|
|
106
|
+
defaultTagName: "div",
|
|
107
|
+
props: { ...orientationDataAttributes(orientation), className, children },
|
|
108
|
+
consumerProps: rest
|
|
109
|
+
});
|
|
110
|
+
return /* @__PURE__ */ jsx(TabsRootContext.Provider, { value: context, children: element });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/tabs/TabsList.tsx
|
|
114
|
+
import { useRef } from "react";
|
|
115
|
+
|
|
116
|
+
// src/core/rovingFocus.ts
|
|
117
|
+
function rovingIndex(key, {
|
|
118
|
+
count,
|
|
119
|
+
current,
|
|
120
|
+
orientation,
|
|
121
|
+
rtl
|
|
122
|
+
}) {
|
|
123
|
+
if (count === 0) return null;
|
|
124
|
+
const [prevKey, nextKey] = orientation === "vertical" ? ["ArrowUp", "ArrowDown"] : rtl ? ["ArrowRight", "ArrowLeft"] : ["ArrowLeft", "ArrowRight"];
|
|
125
|
+
switch (key) {
|
|
126
|
+
case nextKey:
|
|
127
|
+
return current < 0 ? 0 : (current + 1) % count;
|
|
128
|
+
case prevKey:
|
|
129
|
+
return current < 0 ? count - 1 : (current - 1 + count) % count;
|
|
130
|
+
case "Home":
|
|
131
|
+
return 0;
|
|
132
|
+
case "End":
|
|
133
|
+
return count - 1;
|
|
134
|
+
default:
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/tabs/TabsList.tsx
|
|
140
|
+
function TabsList({ className, children, render, ...rest }) {
|
|
141
|
+
const { orientation, enabledTabs } = useTabsRootContext("List");
|
|
142
|
+
const elementRef = useRef(null);
|
|
143
|
+
return useRender({
|
|
144
|
+
render,
|
|
145
|
+
defaultTagName: "div",
|
|
146
|
+
props: {
|
|
147
|
+
role: "tablist",
|
|
148
|
+
// Horizontal is the ARIA default for a tablist, so it is only stated when vertical.
|
|
149
|
+
"aria-orientation": orientation === "vertical" ? "vertical" : void 0,
|
|
150
|
+
...orientationDataAttributes(orientation),
|
|
151
|
+
className,
|
|
152
|
+
children,
|
|
153
|
+
ref: elementRef,
|
|
154
|
+
onKeyDown(event) {
|
|
155
|
+
const current = enabledTabs.findIndex((t) => t.ref.current === event.target);
|
|
156
|
+
if (current < 0) return;
|
|
157
|
+
const list = elementRef.current;
|
|
158
|
+
const rtl = list ? getComputedStyle(list).direction === "rtl" : false;
|
|
159
|
+
const next = rovingIndex(event.key, {
|
|
160
|
+
count: enabledTabs.length,
|
|
161
|
+
current,
|
|
162
|
+
orientation,
|
|
163
|
+
rtl
|
|
164
|
+
});
|
|
165
|
+
if (next === null) return;
|
|
166
|
+
event.preventDefault();
|
|
167
|
+
enabledTabs[next]?.ref.current?.focus();
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
consumerProps: rest
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/tabs/TabsTab.tsx
|
|
175
|
+
import { useLayoutEffect, useRef as useRef2 } from "react";
|
|
176
|
+
function TabsTab({
|
|
177
|
+
value,
|
|
178
|
+
disabled = false,
|
|
179
|
+
className,
|
|
180
|
+
children,
|
|
181
|
+
render,
|
|
182
|
+
...rest
|
|
183
|
+
}) {
|
|
184
|
+
const {
|
|
185
|
+
value: selectedValue,
|
|
186
|
+
setValue,
|
|
187
|
+
activationMode,
|
|
188
|
+
tabStopValue,
|
|
189
|
+
register,
|
|
190
|
+
tabId,
|
|
191
|
+
panelId
|
|
192
|
+
} = useTabsRootContext("Tab");
|
|
193
|
+
const elementRef = useRef2(null);
|
|
194
|
+
const selected = value === selectedValue;
|
|
195
|
+
useLayoutEffect(
|
|
196
|
+
() => register({ value, disabled, ref: elementRef }),
|
|
197
|
+
[register, value, disabled]
|
|
198
|
+
);
|
|
199
|
+
return useRender({
|
|
200
|
+
render,
|
|
201
|
+
defaultTagName: "button",
|
|
202
|
+
props: {
|
|
203
|
+
type: "button",
|
|
204
|
+
role: "tab",
|
|
205
|
+
id: tabId(value),
|
|
206
|
+
"aria-selected": selected,
|
|
207
|
+
"aria-controls": panelId(value),
|
|
208
|
+
tabIndex: value === tabStopValue ? 0 : -1,
|
|
209
|
+
// The platform keeps a disabled button out of focus and activation.
|
|
210
|
+
disabled: disabled || void 0,
|
|
211
|
+
...selectedDataAttributes(selected, disabled),
|
|
212
|
+
className,
|
|
213
|
+
children,
|
|
214
|
+
ref: elementRef,
|
|
215
|
+
onClick() {
|
|
216
|
+
if (!disabled) setValue(value);
|
|
217
|
+
},
|
|
218
|
+
onFocus() {
|
|
219
|
+
if (activationMode === "automatic" && !disabled) setValue(value);
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
consumerProps: rest
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/tabs/TabsPanel.tsx
|
|
227
|
+
function TabsPanel({ value, className, children, render, ...rest }) {
|
|
228
|
+
const { value: selectedValue, tabId, panelId } = useTabsRootContext("Panel");
|
|
229
|
+
const selected = value === selectedValue;
|
|
230
|
+
return useRender({
|
|
231
|
+
render,
|
|
232
|
+
defaultTagName: "div",
|
|
233
|
+
props: {
|
|
234
|
+
role: "tabpanel",
|
|
235
|
+
id: panelId(value),
|
|
236
|
+
"aria-labelledby": tabId(value),
|
|
237
|
+
tabIndex: 0,
|
|
238
|
+
hidden: !selected || void 0,
|
|
239
|
+
...selectedDataAttributes(selected),
|
|
240
|
+
className,
|
|
241
|
+
children
|
|
242
|
+
},
|
|
243
|
+
consumerProps: rest
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
export {
|
|
247
|
+
index_parts_exports as Tabs
|
|
248
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arun-dev/headless",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "Unstyled React behaviour primitives — render engine, controlled/uncontrolled state, and data-* state projection. Ships no CSS and no class names.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -94,6 +94,16 @@
|
|
|
94
94
|
"default": "./dist/switch/index.cjs"
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
|
+
"./tabs": {
|
|
98
|
+
"import": {
|
|
99
|
+
"types": "./dist/tabs/index.d.ts",
|
|
100
|
+
"default": "./dist/tabs/index.js"
|
|
101
|
+
},
|
|
102
|
+
"require": {
|
|
103
|
+
"types": "./dist/tabs/index.d.cts",
|
|
104
|
+
"default": "./dist/tabs/index.cjs"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
97
107
|
"./tooltip": {
|
|
98
108
|
"import": {
|
|
99
109
|
"types": "./dist/tooltip/index.d.ts",
|