@featherk/composables 0.0.6 → 0.0.7
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/README.md +6 -0
- package/dist/featherk-composables.es.js +136 -118
- package/dist/featherk-composables.umd.js +1 -1
- package/dist/useGridA11y.d.ts +0 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -21,6 +21,12 @@
|
|
|
21
21
|
- For row-level navigation, disable the Grid's cell-level dynamic tabindex behavior (omit or set `navigatable="false"` on the Grid).
|
|
22
22
|
- The composable returns helpers for keyboard handling, focus management, and sort/filter interactions.
|
|
23
23
|
|
|
24
|
+
### Styling and the .fk-grid class
|
|
25
|
+
|
|
26
|
+
- The composable will add the CSS class `.fk-grid` to the Grid's root element (see `setupGridStyling()` in the source). The composable itself does NOT include any CSS (no inline styles or stylesheet).
|
|
27
|
+
- The `.fk-grid` class is a hook used by the FeatherK stylesheet to apply visual styles. To see visual indicators (for example, the active/filtered status), you must include the appropriate FeatherK stylesheet for Kendo in your application.
|
|
28
|
+
- Ensure you are using the matching FeatherK styling release for correct visuals — e.g. `featherk-q3-2024-v#.css` (replace `#` with the patch version you are using).
|
|
29
|
+
|
|
24
30
|
## Prerequisites
|
|
25
31
|
|
|
26
32
|
- Vue 3 (script setup)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ref as E, onMounted as S, onBeforeUnmount as M, nextTick as p, onUnmounted as N } from "vue";
|
|
2
|
-
const G = (
|
|
2
|
+
const G = (f) => {
|
|
3
3
|
const s = E(null);
|
|
4
|
-
let
|
|
5
|
-
const
|
|
4
|
+
let m = null, u = null;
|
|
5
|
+
const b = [], y = ".k-table-row[data-grid-row-index] [tabindex]", k = () => f?.value?.columns, h = (t) => {
|
|
6
6
|
const o = t.key || t.code;
|
|
7
7
|
[" ", "Spacebar", "Space", "Enter"].includes(o) && (t.preventDefault(), t.stopPropagation(), s.value = t.target, t.target.click());
|
|
8
8
|
}, g = (t) => {
|
|
@@ -18,52 +18,52 @@ const G = (b) => {
|
|
|
18
18
|
), e = document.querySelector(".k-filter-menu-container");
|
|
19
19
|
if (e) {
|
|
20
20
|
if (t.code === "Tab") {
|
|
21
|
-
const
|
|
21
|
+
const r = [
|
|
22
22
|
".k-filter-menu-container .k-dropdownlist[tabindex='0']",
|
|
23
23
|
".k-filter-menu-container input.k-input-inner:not([tabindex='-1']):not([disabled])",
|
|
24
24
|
".k-filter-menu-container button:not([tabindex='-1']):not([disabled])"
|
|
25
|
-
],
|
|
26
|
-
e.querySelectorAll(
|
|
25
|
+
], n = Array.from(
|
|
26
|
+
e.querySelectorAll(r.join(","))
|
|
27
27
|
);
|
|
28
|
-
if (
|
|
29
|
-
const a =
|
|
28
|
+
if (n.length === 0) return;
|
|
29
|
+
const a = n.findIndex(
|
|
30
30
|
(l) => l === document.activeElement
|
|
31
31
|
);
|
|
32
32
|
let i;
|
|
33
|
-
a === -1 ? i = 0 : t.shiftKey ? i = (a - 1 +
|
|
33
|
+
a === -1 ? i = 0 : t.shiftKey ? i = (a - 1 + n.length) % n.length : i = (a + 1) % n.length, t.preventDefault(), t.stopPropagation(), n[i]?.focus();
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
36
|
} else if (t.code === "ArrowUp" || t.code === "ArrowDown") {
|
|
37
37
|
t.preventDefault(), t.stopPropagation();
|
|
38
|
-
const
|
|
38
|
+
const r = o.findIndex(
|
|
39
39
|
(a) => a === document.activeElement
|
|
40
40
|
);
|
|
41
|
-
let
|
|
42
|
-
t.code === "ArrowUp" ?
|
|
41
|
+
let n = r;
|
|
42
|
+
t.code === "ArrowUp" ? n = r > 0 ? r - 1 : o.length - 1 : t.code === "ArrowDown" && (n = r < o.length - 1 ? r + 1 : 0), o[n]?.focus();
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
t.code === "Tab" && (t.preventDefault(), t.stopPropagation(), t.shiftKey ? (s.value?.previousElementSibling).focus() : (s.value?.nextElementSibling).focus());
|
|
46
46
|
}, x = () => {
|
|
47
|
-
|
|
47
|
+
m = new MutationObserver((t) => {
|
|
48
48
|
t.forEach((o) => {
|
|
49
49
|
o.addedNodes.forEach((e) => {
|
|
50
50
|
if (e.nodeType === Node.ELEMENT_NODE) {
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
51
|
+
const r = e;
|
|
52
|
+
if (r.classList.contains("k-animation-container")) {
|
|
53
53
|
const a = s.value;
|
|
54
54
|
a && (a.dataset.featherKSortable === "true" || p(() => {
|
|
55
|
-
|
|
55
|
+
r.querySelectorAll(
|
|
56
56
|
".k-columnmenu-item-wrapper"
|
|
57
57
|
).forEach((d) => {
|
|
58
58
|
d.textContent?.toLowerCase().includes("sort") && d.remove();
|
|
59
59
|
});
|
|
60
|
-
})),
|
|
60
|
+
})), r.addEventListener(
|
|
61
61
|
"keydown",
|
|
62
62
|
g
|
|
63
63
|
), p(() => {
|
|
64
64
|
const i = () => {
|
|
65
65
|
const l = Array.from(
|
|
66
|
-
|
|
66
|
+
r.querySelectorAll(
|
|
67
67
|
".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item"
|
|
68
68
|
)
|
|
69
69
|
);
|
|
@@ -78,7 +78,7 @@ const G = (b) => {
|
|
|
78
78
|
i();
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
|
-
|
|
81
|
+
r.querySelectorAll(
|
|
82
82
|
".k-animation-container"
|
|
83
83
|
).forEach((a) => {
|
|
84
84
|
a.addEventListener(
|
|
@@ -89,11 +89,11 @@ const G = (b) => {
|
|
|
89
89
|
}
|
|
90
90
|
}), o.removedNodes.forEach((e) => {
|
|
91
91
|
if (e.nodeType === Node.ELEMENT_NODE) {
|
|
92
|
-
const
|
|
93
|
-
|
|
92
|
+
const r = e;
|
|
93
|
+
r.classList.contains("k-animation-container") && r.removeEventListener(
|
|
94
94
|
"keydown",
|
|
95
95
|
g
|
|
96
|
-
),
|
|
96
|
+
), r.querySelectorAll(
|
|
97
97
|
".k-animation-container"
|
|
98
98
|
).forEach((a) => {
|
|
99
99
|
a.removeEventListener(
|
|
@@ -104,7 +104,7 @@ const G = (b) => {
|
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
106
|
});
|
|
107
|
-
}),
|
|
107
|
+
}), m.observe(document.body, {
|
|
108
108
|
childList: !0,
|
|
109
109
|
subtree: !0
|
|
110
110
|
});
|
|
@@ -113,101 +113,119 @@ const G = (b) => {
|
|
|
113
113
|
return;
|
|
114
114
|
console.log("handleGridKeyDown", t, t.code);
|
|
115
115
|
const o = t.target;
|
|
116
|
-
if (o
|
|
117
|
-
"
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
116
|
+
if (o) {
|
|
117
|
+
if (t.code === "Escape") {
|
|
118
|
+
const e = document.activeElement?.closest(".k-table-row[data-grid-row-index]");
|
|
119
|
+
if (e) {
|
|
120
|
+
t.preventDefault(), t.stopPropagation();
|
|
121
|
+
try {
|
|
122
|
+
Array.from(
|
|
123
|
+
f?.value.$el.querySelectorAll(
|
|
124
|
+
".k-table-row[data-grid-row-index]"
|
|
125
|
+
)
|
|
126
|
+
).forEach((n) => n.setAttribute("tabindex", "-1"));
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
e.setAttribute("tabindex", "0"), e.focus();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
127
132
|
}
|
|
128
|
-
|
|
129
|
-
"
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (d.hasAttribute && d.hasAttribute("tabindex"))
|
|
139
|
-
return d;
|
|
140
|
-
} catch {
|
|
141
|
-
}
|
|
142
|
-
l = i === "next" ? l.nextElementSibling : l.previousElementSibling;
|
|
143
|
-
}
|
|
144
|
-
return null;
|
|
145
|
-
}, r = t.code === "ArrowDown" ? n(e, "next") : n(e, "previous");
|
|
146
|
-
r && (e.setAttribute("tabindex", "-1"), r.setAttribute("tabindex", "0"), r.focus());
|
|
133
|
+
if ([
|
|
134
|
+
"ArrowDown",
|
|
135
|
+
"ArrowLeft",
|
|
136
|
+
"ArrowRight",
|
|
137
|
+
"ArrowUp",
|
|
138
|
+
"Enter",
|
|
139
|
+
"Space"
|
|
140
|
+
].includes(t.code)) {
|
|
141
|
+
if (t.preventDefault(), o.classList.contains("k-grid-header-menu") && o.classList.contains("k-grid-column-menu")) {
|
|
142
|
+
s.value = o;
|
|
147
143
|
return;
|
|
148
144
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
145
|
+
const e = o.closest(
|
|
146
|
+
".k-table-row[data-grid-row-index]"
|
|
147
|
+
);
|
|
148
|
+
if (e) {
|
|
149
|
+
if (["ArrowDown", "ArrowUp"].includes(t.code)) {
|
|
150
|
+
const r = (a, i) => {
|
|
151
|
+
let l = i === "next" ? a.nextElementSibling : a.previousElementSibling;
|
|
152
|
+
for (; l; ) {
|
|
153
|
+
const d = l;
|
|
154
|
+
try {
|
|
155
|
+
if (d.hasAttribute && d.classList.contains("k-table-row"))
|
|
156
|
+
return d;
|
|
157
|
+
} catch {
|
|
158
|
+
}
|
|
159
|
+
l = i === "next" ? l.nextElementSibling : l.previousElementSibling;
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}, n = t.code === "ArrowDown" ? r(e, "next") : r(e, "previous");
|
|
163
|
+
n && (e.setAttribute("tabindex", "-1"), n.setAttribute("tabindex", "0"), n.focus());
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (["ArrowLeft", "ArrowRight"].includes(t.code)) {
|
|
167
|
+
t.preventDefault();
|
|
168
|
+
const r = e.querySelectorAll(
|
|
169
|
+
y
|
|
170
|
+
);
|
|
171
|
+
if (r.length === 0) return;
|
|
172
|
+
let n = Array.from(r).findIndex(
|
|
173
|
+
(a) => a === document.activeElement
|
|
174
|
+
);
|
|
175
|
+
if (n === -1 && document.activeElement === e) {
|
|
176
|
+
r[0].focus();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
t.code === "ArrowRight" ? n = n === r.length - 1 ? 0 : n + 1 : t.code === "ArrowLeft" && (n = n === r.length - 1 ? n - 1 : r.length - 1), r[n].focus();
|
|
160
180
|
return;
|
|
161
181
|
}
|
|
162
|
-
t.code === "ArrowRight" ? r = r === n.length - 1 ? 0 : r + 1 : t.code === "ArrowLeft" && (r = r === n.length - 1 ? r - 1 : n.length - 1), n[r].focus();
|
|
163
|
-
return;
|
|
164
182
|
}
|
|
165
183
|
}
|
|
166
184
|
}
|
|
167
185
|
}, D = () => {
|
|
168
186
|
p(() => {
|
|
169
|
-
const t =
|
|
187
|
+
const t = f.value.$el.closest(".k-grid");
|
|
170
188
|
t && t.classList.add("fk-grid");
|
|
171
189
|
});
|
|
172
|
-
},
|
|
190
|
+
}, q = () => {
|
|
173
191
|
try {
|
|
174
192
|
const t = () => {
|
|
175
193
|
try {
|
|
176
|
-
const
|
|
177
|
-
|
|
194
|
+
const r = Array.from(
|
|
195
|
+
f.value.$el.querySelectorAll(
|
|
178
196
|
".k-table-row[data-grid-row-index]"
|
|
179
197
|
)
|
|
180
198
|
);
|
|
181
|
-
if (!
|
|
199
|
+
if (!r || r.length === 0 || r.filter(
|
|
182
200
|
(i) => i.getAttribute("tabindex") === "0"
|
|
183
201
|
).length === 1) return;
|
|
184
|
-
const a =
|
|
202
|
+
const a = r.find(
|
|
185
203
|
(i) => i === document.activeElement || i.contains(document.activeElement)
|
|
186
204
|
);
|
|
187
|
-
if (
|
|
205
|
+
if (r.forEach((i) => i.setAttribute("tabindex", "-1")), a) {
|
|
188
206
|
a.setAttribute("tabindex", "0");
|
|
189
207
|
return;
|
|
190
208
|
}
|
|
191
|
-
|
|
192
|
-
} catch (
|
|
193
|
-
console.error("ensureSingleTabindex error:",
|
|
209
|
+
r[0].setAttribute("tabindex", "0");
|
|
210
|
+
} catch (r) {
|
|
211
|
+
console.error("ensureSingleTabindex error:", r);
|
|
194
212
|
}
|
|
195
213
|
}, o = Array.from(
|
|
196
|
-
|
|
214
|
+
f.value.$el.querySelectorAll(
|
|
197
215
|
".k-table-row[data-grid-row-index]"
|
|
198
216
|
)
|
|
199
217
|
);
|
|
200
|
-
o.length > 0 && o.forEach((
|
|
201
|
-
|
|
218
|
+
o.length > 0 && o.forEach((r, n) => {
|
|
219
|
+
r.setAttribute("tabindex", n === 0 ? "0" : "-1");
|
|
202
220
|
});
|
|
203
|
-
const e =
|
|
221
|
+
const e = f.value.$el.querySelector(".k-table-tbody");
|
|
204
222
|
e && (u = new MutationObserver(() => {
|
|
205
223
|
t();
|
|
206
224
|
}), u.observe(e, { childList: !0, subtree: !0 }));
|
|
207
225
|
} catch (t) {
|
|
208
226
|
console.error("Error setting up row navigation:", t);
|
|
209
227
|
}
|
|
210
|
-
},
|
|
228
|
+
}, T = () => {
|
|
211
229
|
p(() => {
|
|
212
230
|
const o = document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");
|
|
213
231
|
o && o.forEach((e) => {
|
|
@@ -224,36 +242,36 @@ const G = (b) => {
|
|
|
224
242
|
"keydown",
|
|
225
243
|
h
|
|
226
244
|
);
|
|
227
|
-
}),
|
|
245
|
+
}), m && (m.disconnect(), m = null), u && (u.disconnect(), u = null), b.forEach((e) => e()), b.length = 0;
|
|
228
246
|
}, I = () => {
|
|
229
247
|
document.querySelectorAll(
|
|
230
248
|
".k-grid-header .k-table-thead th"
|
|
231
|
-
).forEach((e,
|
|
232
|
-
const
|
|
249
|
+
).forEach((e, r) => {
|
|
250
|
+
const n = e.querySelector(
|
|
233
251
|
".k-grid-header-menu.k-grid-column-menu"
|
|
234
252
|
);
|
|
235
|
-
if (!
|
|
253
|
+
if (!n) return;
|
|
236
254
|
const a = k();
|
|
237
|
-
if (a && a[
|
|
238
|
-
const c = a[
|
|
255
|
+
if (a && a[r]) {
|
|
256
|
+
const c = a[r].field ?? "";
|
|
239
257
|
e.setAttribute("data-feather-k-field", c), e.setAttribute(
|
|
240
258
|
"data-feather-k-filterable",
|
|
241
|
-
a[
|
|
259
|
+
a[r].filterable === !1 ? "false" : "true"
|
|
242
260
|
), e.setAttribute(
|
|
243
261
|
"data-feather-k-sortable",
|
|
244
|
-
a[
|
|
262
|
+
a[r].sortable === !1 ? "false" : "true"
|
|
245
263
|
);
|
|
246
264
|
}
|
|
247
265
|
const i = e.dataset.featherKFilterable !== "false", l = e.dataset.featherKSortable !== "false";
|
|
248
|
-
|
|
266
|
+
n.setAttribute("tabindex", "-1"), i ? (e.setAttribute("tabindex", "0"), e.setAttribute("role", "button"), e.setAttribute("aria-haspopup", "menu"), e.style.cursor = "pointer") : (e.setAttribute("tabindex", "0"), e.setAttribute("role", "columnheader"), e.removeAttribute("aria-haspopup"), e.style.cursor = "default");
|
|
249
267
|
const d = (c) => {
|
|
250
|
-
c.target?.closest(".k-column-resizer") || (s.value = e,
|
|
251
|
-
},
|
|
268
|
+
c.target?.closest(".k-column-resizer") || (s.value = e, n.click());
|
|
269
|
+
}, v = (c) => {
|
|
252
270
|
if (i)
|
|
253
271
|
s.value = e, c.preventDefault(), c.stopPropagation(), d(c);
|
|
254
272
|
else if (l) {
|
|
255
273
|
s.value = e;
|
|
256
|
-
const
|
|
274
|
+
const w = new KeyboardEvent("keydown", {
|
|
257
275
|
key: "Enter",
|
|
258
276
|
code: "Enter",
|
|
259
277
|
keyCode: 13,
|
|
@@ -261,38 +279,38 @@ const G = (b) => {
|
|
|
261
279
|
bubbles: !0,
|
|
262
280
|
cancelable: !0
|
|
263
281
|
});
|
|
264
|
-
e.dispatchEvent(
|
|
282
|
+
e.dispatchEvent(w);
|
|
265
283
|
}
|
|
266
284
|
};
|
|
267
|
-
e.addEventListener("click",
|
|
268
|
-
e.removeEventListener("click",
|
|
285
|
+
e.addEventListener("click", v), b.push(() => {
|
|
286
|
+
e.removeEventListener("click", v);
|
|
269
287
|
});
|
|
270
288
|
const A = (c) => {
|
|
271
289
|
if ((c.code === "Enter" || c.code === "Space") && (i || l)) {
|
|
272
290
|
if (s.value = e, s.value.focus(), i)
|
|
273
291
|
c.preventDefault(), c.stopPropagation(), d(c);
|
|
274
292
|
else if (l) {
|
|
275
|
-
const
|
|
276
|
-
|
|
293
|
+
const w = e.querySelector(".k-link");
|
|
294
|
+
w && w.click();
|
|
277
295
|
}
|
|
278
296
|
}
|
|
279
297
|
};
|
|
280
|
-
e.addEventListener("keydown", A, !0),
|
|
298
|
+
e.addEventListener("keydown", A, !0), b.push(() => {
|
|
281
299
|
e.removeEventListener("keydown", A, !0);
|
|
282
300
|
});
|
|
283
301
|
});
|
|
284
302
|
const o = document.querySelector(".k-grid-header .k-table-thead");
|
|
285
303
|
if (o) {
|
|
286
|
-
const e = (
|
|
287
|
-
const
|
|
288
|
-
|
|
304
|
+
const e = (r) => {
|
|
305
|
+
const n = r.target.closest("th");
|
|
306
|
+
n && (r.code === "Enter" || r.code === "Space") && n.dataset.featherKFilterable === "false" && n.dataset.featherKSortable === "false" && (r.preventDefault(), r.stopImmediatePropagation());
|
|
289
307
|
};
|
|
290
308
|
o.addEventListener(
|
|
291
309
|
"keydown",
|
|
292
310
|
e,
|
|
293
311
|
!0
|
|
294
312
|
// NOTE: capture phase
|
|
295
|
-
),
|
|
313
|
+
), b.push(() => {
|
|
296
314
|
o.removeEventListener(
|
|
297
315
|
"keydown",
|
|
298
316
|
e,
|
|
@@ -301,10 +319,10 @@ const G = (b) => {
|
|
|
301
319
|
});
|
|
302
320
|
}
|
|
303
321
|
}, K = function(t, o) {
|
|
304
|
-
const e = t?.event.event.target,
|
|
305
|
-
if (!e || !
|
|
306
|
-
const
|
|
307
|
-
if (!
|
|
322
|
+
const e = t?.event.event.target, r = k();
|
|
323
|
+
if (!e || !r) return;
|
|
324
|
+
const n = e.classList.contains("k-link"), a = e.classList.contains("k-columnmenu-item"), i = r.find((l) => l.field === t.event.field)?.sortable && !0;
|
|
325
|
+
if (!n) {
|
|
308
326
|
if (a && !i) {
|
|
309
327
|
(t.event.sort && void 0)?.filter(
|
|
310
328
|
(d) => d.field !== t.event.field
|
|
@@ -317,7 +335,7 @@ const G = (b) => {
|
|
|
317
335
|
}
|
|
318
336
|
};
|
|
319
337
|
return S(() => {
|
|
320
|
-
D(),
|
|
338
|
+
D(), q(), T();
|
|
321
339
|
}), M(() => {
|
|
322
340
|
C();
|
|
323
341
|
}), {
|
|
@@ -326,30 +344,30 @@ const G = (b) => {
|
|
|
326
344
|
handleSortChange: K
|
|
327
345
|
};
|
|
328
346
|
};
|
|
329
|
-
function
|
|
330
|
-
const { activeByDefault: s = !1, autoActivateDelay:
|
|
331
|
-
function
|
|
347
|
+
function P(f = {}) {
|
|
348
|
+
const { activeByDefault: s = !1, autoActivateDelay: m = 0 } = f, u = E(s);
|
|
349
|
+
function b() {
|
|
332
350
|
u.value = !0;
|
|
333
351
|
}
|
|
334
|
-
function
|
|
352
|
+
function y() {
|
|
335
353
|
u.value = !1;
|
|
336
354
|
}
|
|
337
355
|
function k() {
|
|
338
356
|
u.value = !u.value;
|
|
339
357
|
}
|
|
340
358
|
return S(() => {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
},
|
|
359
|
+
m > 0 && !s && setTimeout(() => {
|
|
360
|
+
b();
|
|
361
|
+
}, m);
|
|
344
362
|
}), N(() => {
|
|
345
363
|
}), {
|
|
346
364
|
isGridActive: u,
|
|
347
|
-
activateGrid:
|
|
348
|
-
deactivateGrid:
|
|
365
|
+
activateGrid: b,
|
|
366
|
+
deactivateGrid: y,
|
|
349
367
|
toggleGrid: k
|
|
350
368
|
};
|
|
351
369
|
}
|
|
352
370
|
export {
|
|
353
371
|
G as useGridA11y,
|
|
354
|
-
|
|
372
|
+
P as useGridComposableEx
|
|
355
373
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(m,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],c):(m=typeof globalThis<"u"?globalThis:m||self,c(m.FeatherKComposables={},m.Vue))})(this,(function(m,c){"use strict";const S=
|
|
1
|
+
(function(m,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],c):(m=typeof globalThis<"u"?globalThis:m||self,c(m.FeatherKComposables={},m.Vue))})(this,(function(m,c){"use strict";const S=b=>{const s=c.ref(null);let p=null,d=null;const k=[],h=".k-table-row[data-grid-row-index] [tabindex]",g=()=>b?.value?.columns,v=t=>{const o=t.key||t.code;[" ","Spacebar","Space","Enter"].includes(o)&&(t.preventDefault(),t.stopPropagation(),s.value=t.target,t.target.click())},y=t=>{if(!s.value)return;if(t.code==="Escape"){t.preventDefault(),t.stopPropagation(),s.value&&s.value.focus();return}const o=Array.from(document.querySelectorAll(".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item")),e=document.querySelector(".k-filter-menu-container");if(e){if(t.code==="Tab"){const n=[".k-filter-menu-container .k-dropdownlist[tabindex='0']",".k-filter-menu-container input.k-input-inner:not([tabindex='-1']):not([disabled])",".k-filter-menu-container button:not([tabindex='-1']):not([disabled])"],r=Array.from(e.querySelectorAll(n.join(",")));if(r.length===0)return;const a=r.findIndex(l=>l===document.activeElement);let i;a===-1?i=0:t.shiftKey?i=(a-1+r.length)%r.length:i=(a+1)%r.length,t.preventDefault(),t.stopPropagation(),r[i]?.focus();return}}else if(t.code==="ArrowUp"||t.code==="ArrowDown"){t.preventDefault(),t.stopPropagation();const n=o.findIndex(a=>a===document.activeElement);let r=n;t.code==="ArrowUp"?r=n>0?n-1:o.length-1:t.code==="ArrowDown"&&(r=n<o.length-1?n+1:0),o[r]?.focus();return}t.code==="Tab"&&(t.preventDefault(),t.stopPropagation(),t.shiftKey?(s.value?.previousElementSibling).focus():(s.value?.nextElementSibling).focus())},L=()=>{p=new MutationObserver(t=>{t.forEach(o=>{o.addedNodes.forEach(e=>{if(e.nodeType===Node.ELEMENT_NODE){const n=e;if(n.classList.contains("k-animation-container")){const a=s.value;a&&(a.dataset.featherKSortable==="true"||c.nextTick(()=>{n.querySelectorAll(".k-columnmenu-item-wrapper").forEach(f=>{f.textContent?.toLowerCase().includes("sort")&&f.remove()})})),n.addEventListener("keydown",y),c.nextTick(()=>{const i=()=>{const l=Array.from(n.querySelectorAll(".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item"));if(l.length===1)l[0].focus(),l[0].click(),i.attempts=0;else if(l.length>1){i.attempts=0;return}else i.attempts===void 0&&(i.attempts=0),i.attempts++<3&&setTimeout(i,200)};i()})}n.querySelectorAll(".k-animation-container").forEach(a=>{a.addEventListener("keydown",y)})}}),o.removedNodes.forEach(e=>{if(e.nodeType===Node.ELEMENT_NODE){const n=e;n.classList.contains("k-animation-container")&&n.removeEventListener("keydown",y),n.querySelectorAll(".k-animation-container").forEach(a=>{a.removeEventListener("keydown",y)})}})})}),p.observe(document.body,{childList:!0,subtree:!0})},T=t=>{if(!t.type||!t)return;console.log("handleGridKeyDown",t,t.code);const o=t.target;if(o){if(t.code==="Escape"){const e=document.activeElement?.closest(".k-table-row[data-grid-row-index]");if(e){t.preventDefault(),t.stopPropagation();try{Array.from(b?.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]")).forEach(r=>r.setAttribute("tabindex","-1"))}catch{}e.setAttribute("tabindex","0"),e.focus();return}}if(["ArrowDown","ArrowLeft","ArrowRight","ArrowUp","Enter","Space"].includes(t.code)){if(t.preventDefault(),o.classList.contains("k-grid-header-menu")&&o.classList.contains("k-grid-column-menu")){s.value=o;return}const e=o.closest(".k-table-row[data-grid-row-index]");if(e){if(["ArrowDown","ArrowUp"].includes(t.code)){const n=(a,i)=>{let l=i==="next"?a.nextElementSibling:a.previousElementSibling;for(;l;){const f=l;try{if(f.hasAttribute&&f.classList.contains("k-table-row"))return f}catch{}l=i==="next"?l.nextElementSibling:l.previousElementSibling}return null},r=t.code==="ArrowDown"?n(e,"next"):n(e,"previous");r&&(e.setAttribute("tabindex","-1"),r.setAttribute("tabindex","0"),r.focus());return}if(["ArrowLeft","ArrowRight"].includes(t.code)){t.preventDefault();const n=e.querySelectorAll(h);if(n.length===0)return;let r=Array.from(n).findIndex(a=>a===document.activeElement);if(r===-1&&document.activeElement===e){n[0].focus();return}t.code==="ArrowRight"?r=r===n.length-1?0:r+1:t.code==="ArrowLeft"&&(r=r===n.length-1?r-1:n.length-1),n[r].focus();return}}}}},D=()=>{c.nextTick(()=>{const t=b.value.$el.closest(".k-grid");t&&t.classList.add("fk-grid")})},q=()=>{try{const t=()=>{try{const n=Array.from(b.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]"));if(!n||n.length===0||n.filter(i=>i.getAttribute("tabindex")==="0").length===1)return;const a=n.find(i=>i===document.activeElement||i.contains(document.activeElement));if(n.forEach(i=>i.setAttribute("tabindex","-1")),a){a.setAttribute("tabindex","0");return}n[0].setAttribute("tabindex","0")}catch(n){console.error("ensureSingleTabindex error:",n)}},o=Array.from(b.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]"));o.length>0&&o.forEach((n,r)=>{n.setAttribute("tabindex",r===0?"0":"-1")});const e=b.value.$el.querySelector(".k-table-tbody");e&&(d=new MutationObserver(()=>{t()}),d.observe(e,{childList:!0,subtree:!0}))}catch(t){console.error("Error setting up row navigation:",t)}},C=()=>{c.nextTick(()=>{const o=document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");o&&o.forEach(e=>{e.setAttribute("role","button"),e.addEventListener("keydown",v)}),L(),K()})},I=()=>{const o=document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");o&&o.forEach(e=>{e.removeEventListener("keydown",v)}),p&&(p.disconnect(),p=null),d&&(d.disconnect(),d=null),k.forEach(e=>e()),k.length=0},K=()=>{document.querySelectorAll(".k-grid-header .k-table-thead th").forEach((e,n)=>{const r=e.querySelector(".k-grid-header-menu.k-grid-column-menu");if(!r)return;const a=g();if(a&&a[n]){const u=a[n].field??"";e.setAttribute("data-feather-k-field",u),e.setAttribute("data-feather-k-filterable",a[n].filterable===!1?"false":"true"),e.setAttribute("data-feather-k-sortable",a[n].sortable===!1?"false":"true")}const i=e.dataset.featherKFilterable!=="false",l=e.dataset.featherKSortable!=="false";r.setAttribute("tabindex","-1"),i?(e.setAttribute("tabindex","0"),e.setAttribute("role","button"),e.setAttribute("aria-haspopup","menu"),e.style.cursor="pointer"):(e.setAttribute("tabindex","0"),e.setAttribute("role","columnheader"),e.removeAttribute("aria-haspopup"),e.style.cursor="default");const f=u=>{u.target?.closest(".k-column-resizer")||(s.value=e,r.click())},A=u=>{if(i)s.value=e,u.preventDefault(),u.stopPropagation(),f(u);else if(l){s.value=e;const w=new KeyboardEvent("keydown",{key:"Enter",code:"Enter",keyCode:13,which:13,bubbles:!0,cancelable:!0});e.dispatchEvent(w)}};e.addEventListener("click",A),k.push(()=>{e.removeEventListener("click",A)});const E=u=>{if((u.code==="Enter"||u.code==="Space")&&(i||l)){if(s.value=e,s.value.focus(),i)u.preventDefault(),u.stopPropagation(),f(u);else if(l){const w=e.querySelector(".k-link");w&&w.click()}}};e.addEventListener("keydown",E,!0),k.push(()=>{e.removeEventListener("keydown",E,!0)})});const o=document.querySelector(".k-grid-header .k-table-thead");if(o){const e=n=>{const r=n.target.closest("th");r&&(n.code==="Enter"||n.code==="Space")&&r.dataset.featherKFilterable==="false"&&r.dataset.featherKSortable==="false"&&(n.preventDefault(),n.stopImmediatePropagation())};o.addEventListener("keydown",e,!0),k.push(()=>{o.removeEventListener("keydown",e,!0)})}},M=function(t,o){const e=t?.event.event.target,n=g();if(!e||!n)return;const r=e.classList.contains("k-link"),a=e.classList.contains("k-columnmenu-item"),i=n.find(l=>l.field===t.event.field)?.sortable&&!0;if(!r){if(a&&!i){(t.event.sort&&void 0)?.filter(f=>f.field!==t.event.field);return}typeof o=="function"&&c.nextTick(()=>{s.value&&s.value.focus(),o(t)})}};return c.onMounted(()=>{D(),q(),C()}),c.onBeforeUnmount(()=>{I()}),{activeFilterButton:s,handleGridKeyDown:T,handleSortChange:M}};function x(b={}){const{activeByDefault:s=!1,autoActivateDelay:p=0}=b,d=c.ref(s);function k(){d.value=!0}function h(){d.value=!1}function g(){d.value=!d.value}return c.onMounted(()=>{p>0&&!s&&setTimeout(()=>{k()},p)}),c.onUnmounted(()=>{}),{isGridActive:d,activateGrid:k,deactivateGrid:h,toggleGrid:g}}m.useGridA11y=S,m.useGridComposableEx=x,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})}));
|
package/dist/useGridA11y.d.ts
CHANGED
|
@@ -3,9 +3,6 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Composable that augments a Kendo-based grid with accessible keyboard navigation,
|
|
5
5
|
* focus management, and custom behaviors for column header menus (filter/sort).
|
|
6
|
-
*
|
|
7
|
-
* (Contents preserved from previous grid-keyboard-navigation.ts; only the export name
|
|
8
|
-
* and filename were changed to reflect the new composable name.)
|
|
9
6
|
*/
|
|
10
7
|
import { type Ref } from "vue";
|
|
11
8
|
import type { GridSortChangeEvent } from "./types/kendo";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@featherk/composables",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"main": "dist/featherk-composables.umd.js",
|
|
5
5
|
"module": "dist/featherk-composables.es.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -29,4 +29,4 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"license": "MIT"
|
|
32
|
-
}
|
|
32
|
+
}
|