@zag-js/tabs 0.1.14 → 0.1.15
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/index.d.ts +2 -2
- package/dist/index.js +39 -11
- package/dist/index.mjs +556 -0
- package/package.json +10 -10
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { RequiredBy, DirectionProperty, CommonProperties, Context, PropTypes, No
|
|
|
2
2
|
import * as _zag_js_core from '@zag-js/core';
|
|
3
3
|
import { StateMachine } from '@zag-js/core';
|
|
4
4
|
|
|
5
|
-
declare type
|
|
5
|
+
declare type IntlTranslations = {
|
|
6
6
|
tablistLabel?: string;
|
|
7
7
|
deleteLabel?(value: string): string;
|
|
8
8
|
};
|
|
@@ -21,7 +21,7 @@ declare type PublicContext = DirectionProperty & CommonProperties & {
|
|
|
21
21
|
/**
|
|
22
22
|
* Specifies the localized strings that identifies the accessibility elements and their states
|
|
23
23
|
*/
|
|
24
|
-
|
|
24
|
+
translations: IntlTranslations;
|
|
25
25
|
/**
|
|
26
26
|
* Whether the keyboard navigation will loop from last tab to first, and vice versa.
|
|
27
27
|
* @default true
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,31 @@
|
|
|
1
|
-
|
|
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/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
connect: () => connect,
|
|
24
|
+
machine: () => machine
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(src_exports);
|
|
27
|
+
|
|
28
|
+
// ../../utilities/dom/dist/index.mjs
|
|
2
29
|
var dataAttr = (guard) => {
|
|
3
30
|
return guard ? "" : void 0;
|
|
4
31
|
};
|
|
@@ -139,7 +166,7 @@ function prevById(v, id, loop = true) {
|
|
|
139
166
|
return v[idx];
|
|
140
167
|
}
|
|
141
168
|
|
|
142
|
-
// ../../utilities/core/dist/index.
|
|
169
|
+
// ../../utilities/core/dist/index.mjs
|
|
143
170
|
var first = (v) => v[0];
|
|
144
171
|
var last = (v) => v[v.length - 1];
|
|
145
172
|
|
|
@@ -208,7 +235,7 @@ var dom = defineDomHelpers({
|
|
|
208
235
|
|
|
209
236
|
// src/tabs.connect.ts
|
|
210
237
|
function connect(state, send, normalize) {
|
|
211
|
-
const
|
|
238
|
+
const translations = state.context.translations;
|
|
212
239
|
const isFocused = state.matches("focused");
|
|
213
240
|
return {
|
|
214
241
|
value: state.context.value,
|
|
@@ -231,7 +258,7 @@ function connect(state, send, normalize) {
|
|
|
231
258
|
"data-focus": dataAttr(isFocused),
|
|
232
259
|
"aria-orientation": state.context.orientation,
|
|
233
260
|
"data-orientation": state.context.orientation,
|
|
234
|
-
"aria-label":
|
|
261
|
+
"aria-label": translations.tablistLabel,
|
|
235
262
|
onKeyDown(event) {
|
|
236
263
|
const keyMap = {
|
|
237
264
|
ArrowDown() {
|
|
@@ -324,7 +351,7 @@ function connect(state, send, normalize) {
|
|
|
324
351
|
"data-part": "delete-button",
|
|
325
352
|
type: "button",
|
|
326
353
|
tabIndex: -1,
|
|
327
|
-
"aria-label": (_a =
|
|
354
|
+
"aria-label": (_a = translations.deleteLabel) == null ? void 0 : _a.call(translations, value),
|
|
328
355
|
disabled,
|
|
329
356
|
onClick() {
|
|
330
357
|
send({ type: "DELETE", value });
|
|
@@ -350,10 +377,10 @@ function connect(state, send, normalize) {
|
|
|
350
377
|
}
|
|
351
378
|
|
|
352
379
|
// src/tabs.machine.ts
|
|
353
|
-
|
|
354
|
-
var { not } = guards;
|
|
380
|
+
var import_core = require("@zag-js/core");
|
|
381
|
+
var { not } = import_core.guards;
|
|
355
382
|
function machine(ctx) {
|
|
356
|
-
return createMachine(
|
|
383
|
+
return (0, import_core.createMachine)(
|
|
357
384
|
{
|
|
358
385
|
initial: "unknown",
|
|
359
386
|
context: {
|
|
@@ -367,7 +394,7 @@ function machine(ctx) {
|
|
|
367
394
|
hasMeasuredRect: false,
|
|
368
395
|
isIndicatorRendered: false,
|
|
369
396
|
loop: true,
|
|
370
|
-
|
|
397
|
+
translations: {},
|
|
371
398
|
...ctx
|
|
372
399
|
},
|
|
373
400
|
computed: {
|
|
@@ -550,7 +577,8 @@ function machine(ctx) {
|
|
|
550
577
|
}
|
|
551
578
|
);
|
|
552
579
|
}
|
|
553
|
-
export
|
|
580
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
581
|
+
0 && (module.exports = {
|
|
554
582
|
connect,
|
|
555
583
|
machine
|
|
556
|
-
};
|
|
584
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
// ../../utilities/dom/dist/index.mjs
|
|
2
|
+
var dataAttr = (guard) => {
|
|
3
|
+
return guard ? "" : void 0;
|
|
4
|
+
};
|
|
5
|
+
var isDom = () => typeof window !== "undefined";
|
|
6
|
+
function getPlatform() {
|
|
7
|
+
const agent = navigator.userAgentData;
|
|
8
|
+
return (agent == null ? void 0 : agent.platform) ?? navigator.platform;
|
|
9
|
+
}
|
|
10
|
+
var pt = (v) => isDom() && v.test(getPlatform());
|
|
11
|
+
var vn = (v) => isDom() && v.test(navigator.vendor);
|
|
12
|
+
var isSafari = () => isApple() && vn(/apple/i);
|
|
13
|
+
var isApple = () => pt(/mac|iphone|ipad|ipod/i);
|
|
14
|
+
function isDocument(el) {
|
|
15
|
+
return el.nodeType === Node.DOCUMENT_NODE;
|
|
16
|
+
}
|
|
17
|
+
function isWindow(value) {
|
|
18
|
+
return (value == null ? void 0 : value.toString()) === "[object Window]";
|
|
19
|
+
}
|
|
20
|
+
function isFrame(element) {
|
|
21
|
+
return element.localName === "iframe";
|
|
22
|
+
}
|
|
23
|
+
function getDocument(el) {
|
|
24
|
+
if (isWindow(el))
|
|
25
|
+
return el.document;
|
|
26
|
+
if (isDocument(el))
|
|
27
|
+
return el;
|
|
28
|
+
return (el == null ? void 0 : el.ownerDocument) ?? document;
|
|
29
|
+
}
|
|
30
|
+
function defineDomHelpers(helpers) {
|
|
31
|
+
const dom2 = {
|
|
32
|
+
getRootNode: (ctx) => {
|
|
33
|
+
var _a;
|
|
34
|
+
return ((_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) ?? document;
|
|
35
|
+
},
|
|
36
|
+
getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
|
|
37
|
+
getWin: (ctx) => dom2.getDoc(ctx).defaultView ?? window,
|
|
38
|
+
getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
|
|
39
|
+
getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
...dom2,
|
|
43
|
+
...helpers
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function isHTMLElement(v) {
|
|
47
|
+
return typeof v === "object" && (v == null ? void 0 : v.nodeType) === Node.ELEMENT_NODE && typeof (v == null ? void 0 : v.nodeName) === "string";
|
|
48
|
+
}
|
|
49
|
+
function isVisible(el) {
|
|
50
|
+
if (!isHTMLElement(el))
|
|
51
|
+
return false;
|
|
52
|
+
return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
|
|
53
|
+
}
|
|
54
|
+
var focusableSelector = "input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type";
|
|
55
|
+
var getFocusables = (container, includeContainer = false) => {
|
|
56
|
+
if (!container)
|
|
57
|
+
return [];
|
|
58
|
+
const elements = Array.from(container.querySelectorAll(focusableSelector));
|
|
59
|
+
const include = includeContainer == true || includeContainer == "if-empty" && elements.length === 0;
|
|
60
|
+
if (include && isHTMLElement(container) && isFocusable(container)) {
|
|
61
|
+
elements.unshift(container);
|
|
62
|
+
}
|
|
63
|
+
const focusableElements = elements.filter(isFocusable);
|
|
64
|
+
focusableElements.forEach((element, i) => {
|
|
65
|
+
if (isFrame(element) && element.contentDocument) {
|
|
66
|
+
const frameBody = element.contentDocument.body;
|
|
67
|
+
focusableElements.splice(i, 1, ...getFocusables(frameBody));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return focusableElements;
|
|
71
|
+
};
|
|
72
|
+
function isFocusable(element) {
|
|
73
|
+
if (!element)
|
|
74
|
+
return false;
|
|
75
|
+
return element.matches(focusableSelector) && isVisible(element);
|
|
76
|
+
}
|
|
77
|
+
var rtlKeyMap = {
|
|
78
|
+
ArrowLeft: "ArrowRight",
|
|
79
|
+
ArrowRight: "ArrowLeft"
|
|
80
|
+
};
|
|
81
|
+
var sameKeyMap = {
|
|
82
|
+
Up: "ArrowUp",
|
|
83
|
+
Down: "ArrowDown",
|
|
84
|
+
Esc: "Escape",
|
|
85
|
+
" ": "Space",
|
|
86
|
+
",": "Comma",
|
|
87
|
+
Left: "ArrowLeft",
|
|
88
|
+
Right: "ArrowRight"
|
|
89
|
+
};
|
|
90
|
+
function getEventKey(event, options = {}) {
|
|
91
|
+
const { dir = "ltr", orientation = "horizontal" } = options;
|
|
92
|
+
let { key } = event;
|
|
93
|
+
key = sameKeyMap[key] ?? key;
|
|
94
|
+
const isRtl = dir === "rtl" && orientation === "horizontal";
|
|
95
|
+
if (isRtl && key in rtlKeyMap) {
|
|
96
|
+
key = rtlKeyMap[key];
|
|
97
|
+
}
|
|
98
|
+
return key;
|
|
99
|
+
}
|
|
100
|
+
function nextTick(fn) {
|
|
101
|
+
const set = /* @__PURE__ */ new Set();
|
|
102
|
+
function raf2(fn2) {
|
|
103
|
+
const id = globalThis.requestAnimationFrame(fn2);
|
|
104
|
+
set.add(() => globalThis.cancelAnimationFrame(id));
|
|
105
|
+
}
|
|
106
|
+
raf2(() => raf2(fn));
|
|
107
|
+
return function cleanup() {
|
|
108
|
+
set.forEach(function(fn2) {
|
|
109
|
+
fn2();
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function raf(fn) {
|
|
114
|
+
const id = globalThis.requestAnimationFrame(fn);
|
|
115
|
+
return function cleanup() {
|
|
116
|
+
globalThis.cancelAnimationFrame(id);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function queryAll(root, selector) {
|
|
120
|
+
return Array.from((root == null ? void 0 : root.querySelectorAll(selector)) ?? []);
|
|
121
|
+
}
|
|
122
|
+
function itemById(v, id) {
|
|
123
|
+
return v.find((node) => node.id === id);
|
|
124
|
+
}
|
|
125
|
+
function indexOfId(v, id) {
|
|
126
|
+
const item = itemById(v, id);
|
|
127
|
+
return item ? v.indexOf(item) : -1;
|
|
128
|
+
}
|
|
129
|
+
function nextById(v, id, loop = true) {
|
|
130
|
+
let idx = indexOfId(v, id);
|
|
131
|
+
idx = loop ? (idx + 1) % v.length : Math.min(idx + 1, v.length - 1);
|
|
132
|
+
return v[idx];
|
|
133
|
+
}
|
|
134
|
+
function prevById(v, id, loop = true) {
|
|
135
|
+
let idx = indexOfId(v, id);
|
|
136
|
+
if (idx === -1)
|
|
137
|
+
return loop ? v[v.length - 1] : null;
|
|
138
|
+
idx = loop ? (idx - 1 + v.length) % v.length : Math.max(0, idx - 1);
|
|
139
|
+
return v[idx];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ../../utilities/core/dist/index.mjs
|
|
143
|
+
var first = (v) => v[0];
|
|
144
|
+
var last = (v) => v[v.length - 1];
|
|
145
|
+
|
|
146
|
+
// src/tabs.dom.ts
|
|
147
|
+
var dom = defineDomHelpers({
|
|
148
|
+
getRootId: (ctx) => {
|
|
149
|
+
var _a;
|
|
150
|
+
return ((_a = ctx.ids) == null ? void 0 : _a.root) ?? `tabs:${ctx.id}`;
|
|
151
|
+
},
|
|
152
|
+
getTriggerGroupId: (ctx) => {
|
|
153
|
+
var _a;
|
|
154
|
+
return ((_a = ctx.ids) == null ? void 0 : _a.triggerGroup) ?? `tabs:${ctx.id}:trigger-group`;
|
|
155
|
+
},
|
|
156
|
+
getContentId: (ctx, id) => {
|
|
157
|
+
var _a;
|
|
158
|
+
return ((_a = ctx.ids) == null ? void 0 : _a.content) ?? `tabs:${ctx.id}:content-${id}`;
|
|
159
|
+
},
|
|
160
|
+
getContentGroupId: (ctx) => {
|
|
161
|
+
var _a;
|
|
162
|
+
return ((_a = ctx.ids) == null ? void 0 : _a.contentGroup) ?? `tabs:${ctx.id}:content-group`;
|
|
163
|
+
},
|
|
164
|
+
getTriggerId: (ctx, id) => {
|
|
165
|
+
var _a;
|
|
166
|
+
return ((_a = ctx.ids) == null ? void 0 : _a.trigger) ?? `tabs:${ctx.id}:trigger-${id}`;
|
|
167
|
+
},
|
|
168
|
+
getIndicatorId: (ctx) => `tabs:${ctx.id}:indicator`,
|
|
169
|
+
getTriggerGroupEl: (ctx) => dom.getById(ctx, dom.getTriggerGroupId(ctx)),
|
|
170
|
+
getContentEl: (ctx, id) => dom.getById(ctx, dom.getContentId(ctx, id)),
|
|
171
|
+
getTriggerEl: (ctx, id) => dom.getById(ctx, dom.getTriggerId(ctx, id)),
|
|
172
|
+
getIndicatorEl: (ctx) => dom.getById(ctx, dom.getIndicatorId(ctx)),
|
|
173
|
+
getElements: (ctx) => {
|
|
174
|
+
const ownerId = CSS.escape(dom.getTriggerGroupId(ctx));
|
|
175
|
+
const selector = `[role=tab][data-ownedby='${ownerId}']:not([disabled])`;
|
|
176
|
+
return queryAll(dom.getTriggerGroupEl(ctx), selector);
|
|
177
|
+
},
|
|
178
|
+
getFirstEl: (ctx) => first(dom.getElements(ctx)),
|
|
179
|
+
getLastEl: (ctx) => last(dom.getElements(ctx)),
|
|
180
|
+
getNextEl: (ctx, id) => nextById(dom.getElements(ctx), dom.getTriggerId(ctx, id), ctx.loop),
|
|
181
|
+
getPrevEl: (ctx, id) => prevById(dom.getElements(ctx), dom.getTriggerId(ctx, id), ctx.loop),
|
|
182
|
+
getActiveContentEl: (ctx) => {
|
|
183
|
+
if (!ctx.value)
|
|
184
|
+
return;
|
|
185
|
+
const id = dom.getContentId(ctx, ctx.value);
|
|
186
|
+
return dom.getById(ctx, id);
|
|
187
|
+
},
|
|
188
|
+
getRectById: (ctx, id) => {
|
|
189
|
+
const empty = {
|
|
190
|
+
offsetLeft: 0,
|
|
191
|
+
offsetTop: 0,
|
|
192
|
+
offsetWidth: 0,
|
|
193
|
+
offsetHeight: 0
|
|
194
|
+
};
|
|
195
|
+
const tab = itemById(dom.getElements(ctx), dom.getTriggerId(ctx, id)) ?? empty;
|
|
196
|
+
if (ctx.isVertical) {
|
|
197
|
+
return {
|
|
198
|
+
top: `${tab.offsetTop}px`,
|
|
199
|
+
height: `${tab.offsetHeight}px`
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
left: `${tab.offsetLeft}px`,
|
|
204
|
+
width: `${tab.offsetWidth}px`
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// src/tabs.connect.ts
|
|
210
|
+
function connect(state, send, normalize) {
|
|
211
|
+
const translations = state.context.translations;
|
|
212
|
+
const isFocused = state.matches("focused");
|
|
213
|
+
return {
|
|
214
|
+
value: state.context.value,
|
|
215
|
+
focusedValue: state.context.focusedValue,
|
|
216
|
+
previousValues: Array.from(state.context.previousValues),
|
|
217
|
+
setValue(value) {
|
|
218
|
+
send({ type: "SET_VALUE", value });
|
|
219
|
+
},
|
|
220
|
+
rootProps: normalize.element({
|
|
221
|
+
"data-part": "root",
|
|
222
|
+
id: dom.getRootId(state.context),
|
|
223
|
+
"data-orientation": state.context.orientation,
|
|
224
|
+
"data-focus": dataAttr(isFocused),
|
|
225
|
+
dir: state.context.dir
|
|
226
|
+
}),
|
|
227
|
+
triggerGroupProps: normalize.element({
|
|
228
|
+
"data-part": "trigger-group",
|
|
229
|
+
id: dom.getTriggerGroupId(state.context),
|
|
230
|
+
role: "tablist",
|
|
231
|
+
"data-focus": dataAttr(isFocused),
|
|
232
|
+
"aria-orientation": state.context.orientation,
|
|
233
|
+
"data-orientation": state.context.orientation,
|
|
234
|
+
"aria-label": translations.tablistLabel,
|
|
235
|
+
onKeyDown(event) {
|
|
236
|
+
const keyMap = {
|
|
237
|
+
ArrowDown() {
|
|
238
|
+
send("ARROW_DOWN");
|
|
239
|
+
},
|
|
240
|
+
ArrowUp() {
|
|
241
|
+
send("ARROW_UP");
|
|
242
|
+
},
|
|
243
|
+
ArrowLeft() {
|
|
244
|
+
send("ARROW_LEFT");
|
|
245
|
+
},
|
|
246
|
+
ArrowRight() {
|
|
247
|
+
send("ARROW_RIGHT");
|
|
248
|
+
},
|
|
249
|
+
Home() {
|
|
250
|
+
send("HOME");
|
|
251
|
+
},
|
|
252
|
+
End() {
|
|
253
|
+
send("END");
|
|
254
|
+
},
|
|
255
|
+
Enter() {
|
|
256
|
+
send({ type: "ENTER", value: state.context.focusedValue });
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
let key = getEventKey(event, state.context);
|
|
260
|
+
const exec = keyMap[key];
|
|
261
|
+
if (exec) {
|
|
262
|
+
event.preventDefault();
|
|
263
|
+
exec(event);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}),
|
|
267
|
+
getTriggerProps(props) {
|
|
268
|
+
const { value, disabled } = props;
|
|
269
|
+
const selected = state.context.value === value;
|
|
270
|
+
return normalize.button({
|
|
271
|
+
"data-part": "trigger",
|
|
272
|
+
role: "tab",
|
|
273
|
+
type: "button",
|
|
274
|
+
disabled,
|
|
275
|
+
"data-orientation": state.context.orientation,
|
|
276
|
+
"data-disabled": dataAttr(disabled),
|
|
277
|
+
"aria-disabled": disabled,
|
|
278
|
+
"data-value": value,
|
|
279
|
+
"aria-selected": selected,
|
|
280
|
+
"data-selected": dataAttr(selected),
|
|
281
|
+
"aria-controls": dom.getContentId(state.context, value),
|
|
282
|
+
"data-ownedby": dom.getTriggerGroupId(state.context),
|
|
283
|
+
id: dom.getTriggerId(state.context, value),
|
|
284
|
+
tabIndex: selected ? 0 : -1,
|
|
285
|
+
onFocus() {
|
|
286
|
+
send({ type: "TAB_FOCUS", value });
|
|
287
|
+
},
|
|
288
|
+
onBlur(event) {
|
|
289
|
+
const target = event.relatedTarget;
|
|
290
|
+
if ((target == null ? void 0 : target.getAttribute("role")) !== "tab") {
|
|
291
|
+
send({ type: "TAB_BLUR" });
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
onClick(event) {
|
|
295
|
+
if (disabled)
|
|
296
|
+
return;
|
|
297
|
+
if (isSafari()) {
|
|
298
|
+
event.currentTarget.focus();
|
|
299
|
+
}
|
|
300
|
+
send({ type: "TAB_CLICK", value });
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
},
|
|
304
|
+
contentGroupProps: normalize.element({
|
|
305
|
+
"data-part": "content-group",
|
|
306
|
+
id: dom.getContentGroupId(state.context),
|
|
307
|
+
"data-orientation": state.context.orientation
|
|
308
|
+
}),
|
|
309
|
+
getContentProps({ value }) {
|
|
310
|
+
const selected = state.context.value === value;
|
|
311
|
+
return normalize.element({
|
|
312
|
+
"data-part": "content",
|
|
313
|
+
id: dom.getContentId(state.context, value),
|
|
314
|
+
tabIndex: 0,
|
|
315
|
+
"aria-labelledby": dom.getTriggerId(state.context, value),
|
|
316
|
+
role: "tabpanel",
|
|
317
|
+
"data-ownedby": dom.getTriggerGroupId(state.context),
|
|
318
|
+
hidden: !selected
|
|
319
|
+
});
|
|
320
|
+
},
|
|
321
|
+
getDeleteButtonProps({ value, disabled }) {
|
|
322
|
+
var _a;
|
|
323
|
+
return normalize.button({
|
|
324
|
+
"data-part": "delete-button",
|
|
325
|
+
type: "button",
|
|
326
|
+
tabIndex: -1,
|
|
327
|
+
"aria-label": (_a = translations.deleteLabel) == null ? void 0 : _a.call(translations, value),
|
|
328
|
+
disabled,
|
|
329
|
+
onClick() {
|
|
330
|
+
send({ type: "DELETE", value });
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
},
|
|
334
|
+
indicatorProps: normalize.element({
|
|
335
|
+
id: dom.getIndicatorId(state.context),
|
|
336
|
+
"data-part": "indicator",
|
|
337
|
+
"data-orientation": state.context.orientation,
|
|
338
|
+
style: {
|
|
339
|
+
"--transition-duration": "200ms",
|
|
340
|
+
"--transition-property": "left, right, top, bottom, width, height",
|
|
341
|
+
position: "absolute",
|
|
342
|
+
willChange: "var(--transition-property)",
|
|
343
|
+
transitionProperty: "var(--transition-property)",
|
|
344
|
+
transitionDuration: state.context.hasMeasuredRect ? "var(--transition-duration)" : "0ms",
|
|
345
|
+
transitionTimingFunction: "var(--transition-timing-function)",
|
|
346
|
+
...state.context.indicatorRect
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// src/tabs.machine.ts
|
|
353
|
+
import { createMachine, guards } from "@zag-js/core";
|
|
354
|
+
var { not } = guards;
|
|
355
|
+
function machine(ctx) {
|
|
356
|
+
return createMachine(
|
|
357
|
+
{
|
|
358
|
+
initial: "unknown",
|
|
359
|
+
context: {
|
|
360
|
+
dir: "ltr",
|
|
361
|
+
orientation: "horizontal",
|
|
362
|
+
activationMode: "automatic",
|
|
363
|
+
value: null,
|
|
364
|
+
focusedValue: null,
|
|
365
|
+
previousValues: [],
|
|
366
|
+
indicatorRect: { left: "0px", top: "0px", width: "0px", height: "0px" },
|
|
367
|
+
hasMeasuredRect: false,
|
|
368
|
+
isIndicatorRendered: false,
|
|
369
|
+
loop: true,
|
|
370
|
+
translations: {},
|
|
371
|
+
...ctx
|
|
372
|
+
},
|
|
373
|
+
computed: {
|
|
374
|
+
isHorizontal: (ctx2) => ctx2.orientation === "horizontal",
|
|
375
|
+
isVertical: (ctx2) => ctx2.orientation === "vertical"
|
|
376
|
+
},
|
|
377
|
+
created: ["setPrevSelectedTabs"],
|
|
378
|
+
watch: {
|
|
379
|
+
focusedValue: "invokeOnFocus",
|
|
380
|
+
value: ["invokeOnChange", "setPrevSelectedTabs", "setIndicatorRect", "setContentTabIndex"],
|
|
381
|
+
dir: ["clearMeasured", "setIndicatorRect"]
|
|
382
|
+
},
|
|
383
|
+
on: {
|
|
384
|
+
SET_VALUE: {
|
|
385
|
+
actions: "setValue"
|
|
386
|
+
},
|
|
387
|
+
DELETE: {
|
|
388
|
+
actions: "deleteValue"
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
states: {
|
|
392
|
+
unknown: {
|
|
393
|
+
on: {
|
|
394
|
+
SETUP: {
|
|
395
|
+
target: "idle",
|
|
396
|
+
actions: ["checkRenderedElements", "setIndicatorRect", "setContentTabIndex"]
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
idle: {
|
|
401
|
+
on: {
|
|
402
|
+
TAB_FOCUS: {
|
|
403
|
+
guard: "selectOnFocus",
|
|
404
|
+
target: "focused",
|
|
405
|
+
actions: ["setFocusedValue", "setValue"]
|
|
406
|
+
},
|
|
407
|
+
TAB_CLICK: {
|
|
408
|
+
target: "focused",
|
|
409
|
+
actions: ["setFocusedValue", "setValue"]
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
focused: {
|
|
414
|
+
on: {
|
|
415
|
+
TAB_CLICK: {
|
|
416
|
+
target: "focused",
|
|
417
|
+
actions: ["setFocusedValue", "setValue"]
|
|
418
|
+
},
|
|
419
|
+
ARROW_LEFT: {
|
|
420
|
+
guard: "isHorizontal",
|
|
421
|
+
actions: "focusPrevTab"
|
|
422
|
+
},
|
|
423
|
+
ARROW_RIGHT: {
|
|
424
|
+
guard: "isHorizontal",
|
|
425
|
+
actions: "focusNextTab"
|
|
426
|
+
},
|
|
427
|
+
ARROW_UP: {
|
|
428
|
+
guard: "isVertical",
|
|
429
|
+
actions: "focusPrevTab"
|
|
430
|
+
},
|
|
431
|
+
ARROW_DOWN: {
|
|
432
|
+
guard: "isVertical",
|
|
433
|
+
actions: "focusNextTab"
|
|
434
|
+
},
|
|
435
|
+
HOME: {
|
|
436
|
+
actions: "focusFirstTab"
|
|
437
|
+
},
|
|
438
|
+
END: {
|
|
439
|
+
actions: "focusLastTab"
|
|
440
|
+
},
|
|
441
|
+
ENTER: {
|
|
442
|
+
guard: not("selectOnFocus"),
|
|
443
|
+
actions: "setValue"
|
|
444
|
+
},
|
|
445
|
+
TAB_FOCUS: [
|
|
446
|
+
{
|
|
447
|
+
guard: "selectOnFocus",
|
|
448
|
+
actions: ["setFocusedValue", "setValue"]
|
|
449
|
+
},
|
|
450
|
+
{ actions: "setFocusedValue" }
|
|
451
|
+
],
|
|
452
|
+
TAB_BLUR: {
|
|
453
|
+
target: "idle",
|
|
454
|
+
actions: "clearFocusedValue"
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
guards: {
|
|
462
|
+
isVertical: (ctx2) => ctx2.isVertical,
|
|
463
|
+
isHorizontal: (ctx2) => ctx2.isHorizontal,
|
|
464
|
+
selectOnFocus: (ctx2) => ctx2.activationMode === "automatic"
|
|
465
|
+
},
|
|
466
|
+
actions: {
|
|
467
|
+
setFocusedValue(ctx2, evt) {
|
|
468
|
+
ctx2.focusedValue = evt.value;
|
|
469
|
+
},
|
|
470
|
+
clearFocusedValue(ctx2) {
|
|
471
|
+
ctx2.focusedValue = null;
|
|
472
|
+
},
|
|
473
|
+
setValue(ctx2, evt) {
|
|
474
|
+
ctx2.value = evt.value;
|
|
475
|
+
},
|
|
476
|
+
invokeOnDelete(ctx2, evt) {
|
|
477
|
+
var _a;
|
|
478
|
+
(_a = ctx2.onDelete) == null ? void 0 : _a.call(ctx2, { value: evt.value });
|
|
479
|
+
},
|
|
480
|
+
focusFirstTab(ctx2) {
|
|
481
|
+
raf(() => {
|
|
482
|
+
var _a;
|
|
483
|
+
return (_a = dom.getFirstEl(ctx2)) == null ? void 0 : _a.focus();
|
|
484
|
+
});
|
|
485
|
+
},
|
|
486
|
+
focusLastTab(ctx2) {
|
|
487
|
+
raf(() => {
|
|
488
|
+
var _a;
|
|
489
|
+
return (_a = dom.getLastEl(ctx2)) == null ? void 0 : _a.focus();
|
|
490
|
+
});
|
|
491
|
+
},
|
|
492
|
+
focusNextTab(ctx2) {
|
|
493
|
+
if (!ctx2.focusedValue)
|
|
494
|
+
return;
|
|
495
|
+
const next = dom.getNextEl(ctx2, ctx2.focusedValue);
|
|
496
|
+
raf(() => next == null ? void 0 : next.focus());
|
|
497
|
+
},
|
|
498
|
+
focusPrevTab(ctx2) {
|
|
499
|
+
if (!ctx2.focusedValue)
|
|
500
|
+
return;
|
|
501
|
+
const prev = dom.getPrevEl(ctx2, ctx2.focusedValue);
|
|
502
|
+
raf(() => prev == null ? void 0 : prev.focus());
|
|
503
|
+
},
|
|
504
|
+
setIndicatorRect(ctx2) {
|
|
505
|
+
nextTick(() => {
|
|
506
|
+
if (!ctx2.isIndicatorRendered || !ctx2.value)
|
|
507
|
+
return;
|
|
508
|
+
ctx2.indicatorRect = dom.getRectById(ctx2, ctx2.value);
|
|
509
|
+
if (ctx2.hasMeasuredRect)
|
|
510
|
+
return;
|
|
511
|
+
nextTick(() => {
|
|
512
|
+
ctx2.hasMeasuredRect = true;
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
},
|
|
516
|
+
checkRenderedElements(ctx2) {
|
|
517
|
+
ctx2.isIndicatorRendered = !!dom.getIndicatorEl(ctx2);
|
|
518
|
+
},
|
|
519
|
+
clearMeasured(ctx2) {
|
|
520
|
+
ctx2.hasMeasuredRect = false;
|
|
521
|
+
},
|
|
522
|
+
invokeOnChange(ctx2) {
|
|
523
|
+
var _a;
|
|
524
|
+
(_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: ctx2.value });
|
|
525
|
+
},
|
|
526
|
+
invokeOnFocus(ctx2) {
|
|
527
|
+
var _a;
|
|
528
|
+
(_a = ctx2.onFocus) == null ? void 0 : _a.call(ctx2, { value: ctx2.focusedValue });
|
|
529
|
+
},
|
|
530
|
+
setPrevSelectedTabs(ctx2) {
|
|
531
|
+
if (ctx2.value != null) {
|
|
532
|
+
const newSelected = Array.from(ctx2.previousValues).concat(ctx2.value);
|
|
533
|
+
ctx2.previousValues = Array.from(new Set(newSelected));
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
setContentTabIndex(ctx2) {
|
|
537
|
+
raf(() => {
|
|
538
|
+
const panel = dom.getActiveContentEl(ctx2);
|
|
539
|
+
if (!panel)
|
|
540
|
+
return;
|
|
541
|
+
const focusables = getFocusables(panel);
|
|
542
|
+
if (focusables.length > 0) {
|
|
543
|
+
panel.removeAttribute("tabindex");
|
|
544
|
+
} else {
|
|
545
|
+
panel.setAttribute("tabindex", "0");
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
export {
|
|
554
|
+
connect,
|
|
555
|
+
machine
|
|
556
|
+
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"type": "module",
|
|
3
2
|
"name": "@zag-js/tabs",
|
|
4
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
5
4
|
"description": "Core logic for the tabs widget implemented as a state machine",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
6
8
|
"keywords": [
|
|
7
9
|
"js",
|
|
8
10
|
"machine",
|
|
@@ -15,8 +17,6 @@
|
|
|
15
17
|
"author": "Segun Adebayo <sage@adebayosegun.com>",
|
|
16
18
|
"homepage": "https://github.com/chakra-ui/zag#readme",
|
|
17
19
|
"license": "MIT",
|
|
18
|
-
"main": "dist/index.js",
|
|
19
|
-
"types": "dist/index.d.ts",
|
|
20
20
|
"repository": "https://github.com/chakra-ui/zag/tree/main/packages/tabs",
|
|
21
21
|
"sideEffects": false,
|
|
22
22
|
"files": [
|
|
@@ -29,17 +29,17 @@
|
|
|
29
29
|
"url": "https://github.com/chakra-ui/zag/issues"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@zag-js/core": "0.1.
|
|
33
|
-
"@zag-js/types": "0.2.
|
|
32
|
+
"@zag-js/core": "0.1.12",
|
|
33
|
+
"@zag-js/types": "0.2.7"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@zag-js/dom-utils": "0.1.
|
|
37
|
-
"@zag-js/utils": "0.1.
|
|
36
|
+
"@zag-js/dom-utils": "0.1.13",
|
|
37
|
+
"@zag-js/utils": "0.1.6"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
|
-
"build-fast": "tsup src/index.ts --format=esm",
|
|
40
|
+
"build-fast": "tsup src/index.ts --format=esm,cjs",
|
|
41
41
|
"start": "pnpm build --watch",
|
|
42
|
-
"build": "tsup src/index.ts --format=esm --dts",
|
|
42
|
+
"build": "tsup src/index.ts --format=esm,cjs --dts",
|
|
43
43
|
"test": "jest --config ../../../jest.config.js --rootDir . --passWithNoTests",
|
|
44
44
|
"lint": "eslint src --ext .ts,.tsx",
|
|
45
45
|
"test-ci": "pnpm test --ci --runInBand",
|