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