@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 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 IntlMessages = {
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
- messages: IntlMessages;
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
- // ../../utilities/dom/dist/index.js
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) ?? navigator.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) ?? document;
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)) ?? document;
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) => dom2.getDoc(ctx).defaultView ?? window,
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] ?? 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
- return Array.from((root == null ? void 0 : root.querySelectorAll(selector)) ?? []);
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.js
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) ?? `tabs:${ctx.id}`;
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) ?? `tabs:${ctx.id}:trigger-group`;
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) ?? `tabs:${ctx.id}:content-${id}`;
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) ?? `tabs:${ctx.id}:content-group`;
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) ?? `tabs:${ctx.id}:trigger-${id}`;
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)) ?? empty;
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 messages = state.context.messages;
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": messages.tablistLabel,
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 = messages.deleteLabel) == null ? void 0 : _a.call(messages, value),
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
- import { createMachine, guards } from "@zag-js/core";
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
- messages: {},
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.1.14",
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.1.11",
33
- "@zag-js/types": "0.2.6"
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.1.12",
37
- "@zag-js/utils": "0.1.5"
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",