@zag-js/tabs 1.41.1 → 2.0.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tabs.connect.js +8 -13
- package/dist/tabs.connect.mjs +8 -13
- package/dist/tabs.dom.js +10 -11
- package/dist/tabs.dom.mjs +11 -12
- package/dist/tabs.machine.js +10 -7
- package/dist/tabs.machine.mjs +10 -7
- package/dist/tabs.props.js +1 -1
- package/dist/tabs.props.mjs +1 -1
- package/dist/tabs.types.d.mts +8 -2
- package/dist/tabs.types.d.ts +8 -2
- package/package.json +6 -6
package/dist/tabs.connect.js
CHANGED
|
@@ -43,7 +43,7 @@ function connect(service, normalize) {
|
|
|
43
43
|
const focused = state.matches("focused");
|
|
44
44
|
const isVertical = prop("orientation") === "vertical";
|
|
45
45
|
const isHorizontal = prop("orientation") === "horizontal";
|
|
46
|
-
const
|
|
46
|
+
const virtualFocus = prop("virtualFocus");
|
|
47
47
|
function getTriggerState(props) {
|
|
48
48
|
return {
|
|
49
49
|
selected: context.get("value") === props.value,
|
|
@@ -82,8 +82,7 @@ function connect(service, normalize) {
|
|
|
82
82
|
},
|
|
83
83
|
getRootProps() {
|
|
84
84
|
return normalize.element({
|
|
85
|
-
...import_tabs.parts.root.attrs,
|
|
86
|
-
id: dom.getRootId(scope),
|
|
85
|
+
...import_tabs.parts.root.attrs(scope.id),
|
|
87
86
|
"data-orientation": prop("orientation"),
|
|
88
87
|
"data-focus": (0, import_dom_query.dataAttr)(focused),
|
|
89
88
|
dir: prop("dir")
|
|
@@ -91,8 +90,7 @@ function connect(service, normalize) {
|
|
|
91
90
|
},
|
|
92
91
|
getListProps() {
|
|
93
92
|
return normalize.element({
|
|
94
|
-
...import_tabs.parts.list.attrs,
|
|
95
|
-
id: dom.getListId(scope),
|
|
93
|
+
...import_tabs.parts.list.attrs(scope.id),
|
|
96
94
|
role: "tablist",
|
|
97
95
|
dir: prop("dir"),
|
|
98
96
|
"data-focus": (0, import_dom_query.dataAttr)(focused),
|
|
@@ -145,7 +143,7 @@ function connect(service, normalize) {
|
|
|
145
143
|
const { value, disabled } = props;
|
|
146
144
|
const triggerState = getTriggerState(props);
|
|
147
145
|
return normalize.button({
|
|
148
|
-
...import_tabs.parts.trigger.attrs,
|
|
146
|
+
...import_tabs.parts.trigger.attrs(scope.id),
|
|
149
147
|
role: "tab",
|
|
150
148
|
type: "button",
|
|
151
149
|
disabled,
|
|
@@ -158,10 +156,9 @@ function connect(service, normalize) {
|
|
|
158
156
|
"data-selected": (0, import_dom_query.dataAttr)(triggerState.selected),
|
|
159
157
|
"data-focus": (0, import_dom_query.dataAttr)(triggerState.focused),
|
|
160
158
|
"aria-controls": triggerState.selected ? dom.getContentId(scope, value) : void 0,
|
|
161
|
-
"data-ownedby": dom.getListId(scope),
|
|
162
159
|
"data-ssr": (0, import_dom_query.dataAttr)(context.get("ssr")),
|
|
163
160
|
id: dom.getTriggerId(scope, value),
|
|
164
|
-
tabIndex: triggerState.selected &&
|
|
161
|
+
tabIndex: triggerState.selected && !virtualFocus ? 0 : -1,
|
|
165
162
|
onFocus() {
|
|
166
163
|
send({ type: "TAB_FOCUS", value });
|
|
167
164
|
},
|
|
@@ -186,13 +183,12 @@ function connect(service, normalize) {
|
|
|
186
183
|
const { value } = props;
|
|
187
184
|
const selected = context.get("value") === value;
|
|
188
185
|
return normalize.element({
|
|
189
|
-
...import_tabs.parts.content.attrs,
|
|
186
|
+
...import_tabs.parts.content.attrs(scope.id),
|
|
190
187
|
dir: prop("dir"),
|
|
191
188
|
id: dom.getContentId(scope, value),
|
|
192
|
-
tabIndex:
|
|
189
|
+
tabIndex: !virtualFocus ? 0 : -1,
|
|
193
190
|
"aria-labelledby": dom.getTriggerId(scope, value),
|
|
194
191
|
role: "tabpanel",
|
|
195
|
-
"data-ownedby": dom.getListId(scope),
|
|
196
192
|
"data-selected": (0, import_dom_query.dataAttr)(selected),
|
|
197
193
|
"data-orientation": prop("orientation"),
|
|
198
194
|
hidden: !selected
|
|
@@ -202,8 +198,7 @@ function connect(service, normalize) {
|
|
|
202
198
|
const rect = context.get("indicatorRect");
|
|
203
199
|
const animateIndicator = context.get("animateIndicator");
|
|
204
200
|
return normalize.element({
|
|
205
|
-
|
|
206
|
-
...import_tabs.parts.indicator.attrs,
|
|
201
|
+
...import_tabs.parts.indicator.attrs(scope.id),
|
|
207
202
|
dir: prop("dir"),
|
|
208
203
|
"data-orientation": prop("orientation"),
|
|
209
204
|
hidden: isRectEmpty(rect),
|
package/dist/tabs.connect.mjs
CHANGED
|
@@ -17,7 +17,7 @@ function connect(service, normalize) {
|
|
|
17
17
|
const focused = state.matches("focused");
|
|
18
18
|
const isVertical = prop("orientation") === "vertical";
|
|
19
19
|
const isHorizontal = prop("orientation") === "horizontal";
|
|
20
|
-
const
|
|
20
|
+
const virtualFocus = prop("virtualFocus");
|
|
21
21
|
function getTriggerState(props) {
|
|
22
22
|
return {
|
|
23
23
|
selected: context.get("value") === props.value,
|
|
@@ -56,8 +56,7 @@ function connect(service, normalize) {
|
|
|
56
56
|
},
|
|
57
57
|
getRootProps() {
|
|
58
58
|
return normalize.element({
|
|
59
|
-
...parts.root.attrs,
|
|
60
|
-
id: dom.getRootId(scope),
|
|
59
|
+
...parts.root.attrs(scope.id),
|
|
61
60
|
"data-orientation": prop("orientation"),
|
|
62
61
|
"data-focus": dataAttr(focused),
|
|
63
62
|
dir: prop("dir")
|
|
@@ -65,8 +64,7 @@ function connect(service, normalize) {
|
|
|
65
64
|
},
|
|
66
65
|
getListProps() {
|
|
67
66
|
return normalize.element({
|
|
68
|
-
...parts.list.attrs,
|
|
69
|
-
id: dom.getListId(scope),
|
|
67
|
+
...parts.list.attrs(scope.id),
|
|
70
68
|
role: "tablist",
|
|
71
69
|
dir: prop("dir"),
|
|
72
70
|
"data-focus": dataAttr(focused),
|
|
@@ -119,7 +117,7 @@ function connect(service, normalize) {
|
|
|
119
117
|
const { value, disabled } = props;
|
|
120
118
|
const triggerState = getTriggerState(props);
|
|
121
119
|
return normalize.button({
|
|
122
|
-
...parts.trigger.attrs,
|
|
120
|
+
...parts.trigger.attrs(scope.id),
|
|
123
121
|
role: "tab",
|
|
124
122
|
type: "button",
|
|
125
123
|
disabled,
|
|
@@ -132,10 +130,9 @@ function connect(service, normalize) {
|
|
|
132
130
|
"data-selected": dataAttr(triggerState.selected),
|
|
133
131
|
"data-focus": dataAttr(triggerState.focused),
|
|
134
132
|
"aria-controls": triggerState.selected ? dom.getContentId(scope, value) : void 0,
|
|
135
|
-
"data-ownedby": dom.getListId(scope),
|
|
136
133
|
"data-ssr": dataAttr(context.get("ssr")),
|
|
137
134
|
id: dom.getTriggerId(scope, value),
|
|
138
|
-
tabIndex: triggerState.selected &&
|
|
135
|
+
tabIndex: triggerState.selected && !virtualFocus ? 0 : -1,
|
|
139
136
|
onFocus() {
|
|
140
137
|
send({ type: "TAB_FOCUS", value });
|
|
141
138
|
},
|
|
@@ -160,13 +157,12 @@ function connect(service, normalize) {
|
|
|
160
157
|
const { value } = props;
|
|
161
158
|
const selected = context.get("value") === value;
|
|
162
159
|
return normalize.element({
|
|
163
|
-
...parts.content.attrs,
|
|
160
|
+
...parts.content.attrs(scope.id),
|
|
164
161
|
dir: prop("dir"),
|
|
165
162
|
id: dom.getContentId(scope, value),
|
|
166
|
-
tabIndex:
|
|
163
|
+
tabIndex: !virtualFocus ? 0 : -1,
|
|
167
164
|
"aria-labelledby": dom.getTriggerId(scope, value),
|
|
168
165
|
role: "tabpanel",
|
|
169
|
-
"data-ownedby": dom.getListId(scope),
|
|
170
166
|
"data-selected": dataAttr(selected),
|
|
171
167
|
"data-orientation": prop("orientation"),
|
|
172
168
|
hidden: !selected
|
|
@@ -176,8 +172,7 @@ function connect(service, normalize) {
|
|
|
176
172
|
const rect = context.get("indicatorRect");
|
|
177
173
|
const animateIndicator = context.get("animateIndicator");
|
|
178
174
|
return normalize.element({
|
|
179
|
-
|
|
180
|
-
...parts.indicator.attrs,
|
|
175
|
+
...parts.indicator.attrs(scope.id),
|
|
181
176
|
dir: prop("dir"),
|
|
182
177
|
"data-orientation": prop("orientation"),
|
|
183
178
|
hidden: isRectEmpty(rect),
|
package/dist/tabs.dom.js
CHANGED
|
@@ -40,19 +40,18 @@ __export(tabs_dom_exports, {
|
|
|
40
40
|
module.exports = __toCommonJS(tabs_dom_exports);
|
|
41
41
|
var import_dom_query = require("@zag-js/dom-query");
|
|
42
42
|
var import_utils = require("@zag-js/utils");
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
var
|
|
46
|
-
var
|
|
47
|
-
var
|
|
48
|
-
var
|
|
43
|
+
var import_tabs = require("./tabs.anatomy.js");
|
|
44
|
+
var getRootId = (ctx) => ctx.ids?.root ?? `${ctx.id}`;
|
|
45
|
+
var getListId = (ctx) => ctx.ids?.list ?? `${ctx.id}:list`;
|
|
46
|
+
var getContentId = (ctx, value) => ctx.ids?.content?.(value) ?? `${ctx.id}:content:${value}`;
|
|
47
|
+
var getTriggerId = (ctx, value) => ctx.ids?.trigger?.(value) ?? `${ctx.id}:trigger:${value}`;
|
|
48
|
+
var getIndicatorId = (ctx) => ctx.ids?.indicator ?? `${ctx.id}:indicator`;
|
|
49
|
+
var getListEl = (ctx) => ctx.query(ctx.selector(import_tabs.parts.list));
|
|
49
50
|
var getContentEl = (ctx, value) => ctx.getById(getContentId(ctx, value));
|
|
50
|
-
var getTriggerEl = (ctx, value) => value != null ? ctx.
|
|
51
|
-
var getIndicatorEl = (ctx) => ctx.
|
|
51
|
+
var getTriggerEl = (ctx, value) => value != null ? ctx.query(`${ctx.selector(import_tabs.parts.trigger)}[data-value="${value}"]`) : null;
|
|
52
|
+
var getIndicatorEl = (ctx) => ctx.query(ctx.selector(import_tabs.parts.indicator));
|
|
52
53
|
var getElements = (ctx) => {
|
|
53
|
-
|
|
54
|
-
const selector = `[role=tab][data-ownedby='${ownerId}']:not([disabled])`;
|
|
55
|
-
return (0, import_dom_query.queryAll)(getListEl(ctx), selector);
|
|
54
|
+
return ctx.queryAll(`${ctx.selector(import_tabs.parts.trigger)}:not([disabled])`);
|
|
56
55
|
};
|
|
57
56
|
var getFirstTriggerEl = (ctx) => (0, import_utils.first)(getElements(ctx));
|
|
58
57
|
var getLastTriggerEl = (ctx) => (0, import_utils.last)(getElements(ctx));
|
package/dist/tabs.dom.mjs
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
// src/tabs.dom.ts
|
|
2
|
-
import { itemById, nextById, prevById
|
|
2
|
+
import { itemById, nextById, prevById } from "@zag-js/dom-query";
|
|
3
3
|
import { first, last } from "@zag-js/utils";
|
|
4
|
-
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
4
|
+
import { parts } from "./tabs.anatomy.mjs";
|
|
5
|
+
var getRootId = (ctx) => ctx.ids?.root ?? `${ctx.id}`;
|
|
6
|
+
var getListId = (ctx) => ctx.ids?.list ?? `${ctx.id}:list`;
|
|
7
|
+
var getContentId = (ctx, value) => ctx.ids?.content?.(value) ?? `${ctx.id}:content:${value}`;
|
|
8
|
+
var getTriggerId = (ctx, value) => ctx.ids?.trigger?.(value) ?? `${ctx.id}:trigger:${value}`;
|
|
9
|
+
var getIndicatorId = (ctx) => ctx.ids?.indicator ?? `${ctx.id}:indicator`;
|
|
10
|
+
var getListEl = (ctx) => ctx.query(ctx.selector(parts.list));
|
|
10
11
|
var getContentEl = (ctx, value) => ctx.getById(getContentId(ctx, value));
|
|
11
|
-
var getTriggerEl = (ctx, value) => value != null ? ctx.
|
|
12
|
-
var getIndicatorEl = (ctx) => ctx.
|
|
12
|
+
var getTriggerEl = (ctx, value) => value != null ? ctx.query(`${ctx.selector(parts.trigger)}[data-value="${value}"]`) : null;
|
|
13
|
+
var getIndicatorEl = (ctx) => ctx.query(ctx.selector(parts.indicator));
|
|
13
14
|
var getElements = (ctx) => {
|
|
14
|
-
|
|
15
|
-
const selector = `[role=tab][data-ownedby='${ownerId}']:not([disabled])`;
|
|
16
|
-
return queryAll(getListEl(ctx), selector);
|
|
15
|
+
return ctx.queryAll(`${ctx.selector(parts.trigger)}:not([disabled])`);
|
|
17
16
|
};
|
|
18
17
|
var getFirstTriggerEl = (ctx) => first(getElements(ctx));
|
|
19
18
|
var getLastTriggerEl = (ctx) => last(getElements(ctx));
|
package/dist/tabs.machine.js
CHANGED
|
@@ -45,7 +45,6 @@ var machine = createMachine({
|
|
|
45
45
|
orientation: "horizontal",
|
|
46
46
|
activationMode: "automatic",
|
|
47
47
|
loopFocus: true,
|
|
48
|
-
composite: true,
|
|
49
48
|
navigate(details) {
|
|
50
49
|
(0, import_dom_query.clickIfLink)(details.node);
|
|
51
50
|
},
|
|
@@ -226,10 +225,12 @@ var machine = createMachine({
|
|
|
226
225
|
loopFocus: prop("loopFocus")
|
|
227
226
|
});
|
|
228
227
|
(0, import_dom_query.raf)(() => {
|
|
229
|
-
if (prop("
|
|
228
|
+
if (prop("virtualFocus")) {
|
|
229
|
+
if (triggerEl?.dataset.value != null) {
|
|
230
|
+
context.set("focusedValue", triggerEl.dataset.value);
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
230
233
|
triggerEl?.focus();
|
|
231
|
-
} else if (triggerEl?.dataset.value != null) {
|
|
232
|
-
context.set("focusedValue", triggerEl.dataset.value);
|
|
233
234
|
}
|
|
234
235
|
});
|
|
235
236
|
},
|
|
@@ -241,10 +242,12 @@ var machine = createMachine({
|
|
|
241
242
|
loopFocus: prop("loopFocus")
|
|
242
243
|
});
|
|
243
244
|
(0, import_dom_query.raf)(() => {
|
|
244
|
-
if (prop("
|
|
245
|
+
if (prop("virtualFocus")) {
|
|
246
|
+
if (triggerEl?.dataset.value != null) {
|
|
247
|
+
context.set("focusedValue", triggerEl.dataset.value);
|
|
248
|
+
}
|
|
249
|
+
} else {
|
|
245
250
|
triggerEl?.focus();
|
|
246
|
-
} else if (triggerEl?.dataset.value != null) {
|
|
247
|
-
context.set("focusedValue", triggerEl.dataset.value);
|
|
248
251
|
}
|
|
249
252
|
});
|
|
250
253
|
},
|
package/dist/tabs.machine.mjs
CHANGED
|
@@ -11,7 +11,6 @@ var machine = createMachine({
|
|
|
11
11
|
orientation: "horizontal",
|
|
12
12
|
activationMode: "automatic",
|
|
13
13
|
loopFocus: true,
|
|
14
|
-
composite: true,
|
|
15
14
|
navigate(details) {
|
|
16
15
|
clickIfLink(details.node);
|
|
17
16
|
},
|
|
@@ -192,10 +191,12 @@ var machine = createMachine({
|
|
|
192
191
|
loopFocus: prop("loopFocus")
|
|
193
192
|
});
|
|
194
193
|
raf(() => {
|
|
195
|
-
if (prop("
|
|
194
|
+
if (prop("virtualFocus")) {
|
|
195
|
+
if (triggerEl?.dataset.value != null) {
|
|
196
|
+
context.set("focusedValue", triggerEl.dataset.value);
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
196
199
|
triggerEl?.focus();
|
|
197
|
-
} else if (triggerEl?.dataset.value != null) {
|
|
198
|
-
context.set("focusedValue", triggerEl.dataset.value);
|
|
199
200
|
}
|
|
200
201
|
});
|
|
201
202
|
},
|
|
@@ -207,10 +208,12 @@ var machine = createMachine({
|
|
|
207
208
|
loopFocus: prop("loopFocus")
|
|
208
209
|
});
|
|
209
210
|
raf(() => {
|
|
210
|
-
if (prop("
|
|
211
|
+
if (prop("virtualFocus")) {
|
|
212
|
+
if (triggerEl?.dataset.value != null) {
|
|
213
|
+
context.set("focusedValue", triggerEl.dataset.value);
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
211
216
|
triggerEl?.focus();
|
|
212
|
-
} else if (triggerEl?.dataset.value != null) {
|
|
213
|
-
context.set("focusedValue", triggerEl.dataset.value);
|
|
214
217
|
}
|
|
215
218
|
});
|
|
216
219
|
},
|
package/dist/tabs.props.js
CHANGED
package/dist/tabs.props.mjs
CHANGED
package/dist/tabs.types.d.mts
CHANGED
|
@@ -70,9 +70,15 @@ interface TabsProps extends DirectionProperty, CommonProperties {
|
|
|
70
70
|
*/
|
|
71
71
|
onFocusChange?: ((details: FocusChangeDetails) => void) | undefined;
|
|
72
72
|
/**
|
|
73
|
-
* Whether the
|
|
73
|
+
* Whether the tabs use virtual focus instead of roving tabindex.
|
|
74
|
+
*
|
|
75
|
+
* When `true`, triggers receive no DOM focus — arrow keys update `focusedValue`
|
|
76
|
+
* and all triggers remain `tabIndex: -1`. Useful when tabs live inside another
|
|
77
|
+
* widget that manages focus (e.g. a combobox).
|
|
78
|
+
*
|
|
79
|
+
* @default false
|
|
74
80
|
*/
|
|
75
|
-
|
|
81
|
+
virtualFocus?: boolean | undefined;
|
|
76
82
|
/**
|
|
77
83
|
* Whether the active tab can be deselected when clicking on it.
|
|
78
84
|
*/
|
package/dist/tabs.types.d.ts
CHANGED
|
@@ -70,9 +70,15 @@ interface TabsProps extends DirectionProperty, CommonProperties {
|
|
|
70
70
|
*/
|
|
71
71
|
onFocusChange?: ((details: FocusChangeDetails) => void) | undefined;
|
|
72
72
|
/**
|
|
73
|
-
* Whether the
|
|
73
|
+
* Whether the tabs use virtual focus instead of roving tabindex.
|
|
74
|
+
*
|
|
75
|
+
* When `true`, triggers receive no DOM focus — arrow keys update `focusedValue`
|
|
76
|
+
* and all triggers remain `tabIndex: -1`. Useful when tabs live inside another
|
|
77
|
+
* widget that manages focus (e.g. a combobox).
|
|
78
|
+
*
|
|
79
|
+
* @default false
|
|
74
80
|
*/
|
|
75
|
-
|
|
81
|
+
virtualFocus?: boolean | undefined;
|
|
76
82
|
/**
|
|
77
83
|
* Whether the active tab can be deselected when clicking on it.
|
|
78
84
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zag-js/tabs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-next.0",
|
|
4
4
|
"description": "Core logic for the tabs widget implemented as a state machine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"js",
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"url": "https://github.com/chakra-ui/zag/issues"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@zag-js/anatomy": "
|
|
30
|
-
"@zag-js/dom-query": "
|
|
31
|
-
"@zag-js/utils": "
|
|
32
|
-
"@zag-js/core": "
|
|
33
|
-
"@zag-js/types": "
|
|
29
|
+
"@zag-js/anatomy": "2.0.0-next.0",
|
|
30
|
+
"@zag-js/dom-query": "2.0.0-next.0",
|
|
31
|
+
"@zag-js/utils": "2.0.0-next.0",
|
|
32
|
+
"@zag-js/core": "2.0.0-next.0",
|
|
33
|
+
"@zag-js/types": "2.0.0-next.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"clean-package": "2.2.0"
|