@featherk/composables 0.0.5 → 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 CHANGED
@@ -1,70 +1,130 @@
1
- # @featherk/composables — Summary
2
1
 
3
- IMPORTANT: This package is experimental and NOT READY FOR PRODUCTION.
2
+ # useGridA11y Integration Quick Reference
4
3
 
5
- > BIG DISCLAIMER — Do not use this package in production environments. The API, types, and build output are unstable. Tests and documentation are incomplete. You may encounter breaking changes, missing features, or rough edges. Use only for local experimentation or as a reference.
4
+ ## BIG DISCLAIMER
6
5
 
7
- ## Short description
6
+ > This package is experimental and NOT READY FOR PRODUCTION. Do not use this package in production environments. The API, types, and build output are unstable. Tests and documentation are incomplete. You may encounter breaking changes, missing features, or rough edges. Use only for local experimentation or as a reference.
8
7
 
9
- `@featherk/composables` provides small Vue 3 composables intended to augment and improve accessibility and behavior for Kendo UI components (Telerik). The library is developed alongside a demo app that shows usage patterns and integration points.
8
+ ## Compatibility
10
9
 
11
- ## Key points
10
+ > The current version of `useGridA11y` composable was developed targeting Kendo UI for Vue version 6.4.1.
11
+ >
12
+ > *This library is not affiliated with or approved by Telerik.*
12
13
 
13
- - Vue 3 + Composition API
14
- - TypeScript (partial coverage; some types may be missing or incomplete)
15
- - Designed to be used inside a monorepo (Turborepo) with a demo app at `demos/` and package sources in `packages/composables/src/`
14
+ ## Short description
16
15
 
17
- ## What this README contains
16
+ `@featherk/composables` provides small Vue 3 composables intended to augment and improve accessibility and behavior for Kendo UI components (Telerik). The library is developed alongside a demo app that shows usage patterns and integration points.
18
17
 
19
- - Purpose and high-level features
20
- - Current stability/status and the critical disclaimer
21
- - Quick local build / demo steps to try the code (for contributors)
22
- - Where to look in the repo for implementation and exports
18
+ ### Notes
23
19
 
24
- ## Status / Stability
20
+ - The composable expects a Grid ref (a Vue ref to the Grid component).
21
+ - For row-level navigation, disable the Grid's cell-level dynamic tabindex behavior (omit or set `navigatable="false"` on the Grid).
22
+ - The composable returns helpers for keyboard handling, focus management, and sort/filter interactions.
25
23
 
26
- This package is an early-stage library and intentionally marked as experimental:
24
+ ### Styling and the .fk-grid class
27
25
 
28
- - API: Unstable. Expect breaking changes.
29
- - Types: Partial. Some public functions and returned shapes may lack strict TypeScript types.
30
- - Tests: Minimal or missing. Run tests before trusting behavior.
31
- - Documentation: Sample usage is mainly in the demo app; inline documentation is minimal.
32
- - Compatibility: Not officially supported by or affiliated with Telerik.
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).
33
29
 
34
- If you need production-ready composables, consider using broadly-adopted libraries or implementing small, well-scoped utilities locally.
30
+ ## Prerequisites
35
31
 
36
- ## Quick start (for contributors)
32
+ - Vue 3 (script setup)
33
+ - `@progress/kendo-vue-grid` installed
34
+ - `@featherk/composables` installed
37
35
 
38
- From the repository root you can build and run the demo to exercise the composables locally. Replace `npm` with your package manager if needed.
36
+ Install (if needed)
39
37
 
40
38
  ```bash
41
- # build the composables package only
42
- npm run build:composables
39
+ npm install @featherk/composables
40
+ ```
41
+
42
+ ## 1) Minimal import + setup
43
+
44
+ Place inside a `<script setup lang="ts">` block. Provide a Grid ref and call the composable.
45
+
46
+ ```ts
47
+ import { ref } from 'vue';
48
+ import { useGridA11y } from '@featherk/composables';
43
49
 
44
- # run the demo app (dev server)
45
- npm run dev:demo
50
+ const gridRef = ref(null);
51
+
52
+ const { activeFilterButton, handleGridKeyDown, handleSortChange } = useGridA11y(gridRef);
46
53
  ```
47
54
 
48
- ## Where to look
55
+ ## 2) Wire keyboard handler on the Grid
56
+
57
+ Template snippet showing essential bindings (keep other Grid props as required by your app):
49
58
 
50
- - Source code: `packages/composables/src/`
51
- - Public exports: `packages/composables/src/index.ts`
52
- - Types: `packages/composables/src/types/`
53
- - Demo usage: `demos/src/components/composables/` and `demos/src/App.vue`
59
+ ```html
60
+ <Grid
61
+ ref="gridRef"
62
+ :dataItems="dataResult.data"
63
+ :dataItemKey="'id'"
64
+ :rowRender="renderRow"
65
+ @keydown="handleGridKeyDown" <!-- keyboard navigation -->
66
+ @sortchange="handleSortChange" <!-- composable-aware sort handling -->
67
+ navigatable="false" <!-- optional: prefer row-level nav -->
68
+ />
69
+ ```
54
70
 
55
- ## Contributing notes
71
+ ## 3) Provide an accessible row renderer (`aria-label`)
56
72
 
57
- - Add composables inside `packages/composables/src/` and export them from `index.ts`.
58
- - Keep changes small and documented. Add tests for new behavior where reasonable.
59
- - Build the composables package before running the demo to ensure the demo picks up local changes.
73
+ > Not part of `@featherk/composable`, but good practice
60
74
 
61
- ## Next steps (recommended)
75
+ Kendo Grid `rowRender` allows you to add an `aria-label` so screen readers announce row contents.
76
+
77
+ ```ts
78
+ const renderRow = (h: any, trElement: any, defaultSlots: any, props: any) => {
79
+ const ariaLabel = `Name: ${props.dataItem.name}, Price: ${props.dataItem.price}`;
80
+ // merge existing props and add aria-label
81
+ const merged = { ...trElement.props, 'aria-label': ariaLabel };
82
+ return h('tr', merged, defaultSlots);
83
+ };
84
+ ```
62
85
 
63
- - Add unit tests and a CI job (currently missing or minimal).
64
- - Improve TypeScript coverage for public API shapes.
65
- - Add examples and API docs for each composable.
66
- - Consider adding a clear versioning strategy (semver) and a roadmap stating when the package will be considered stable.
86
+ ## 4) Focus the active filter button after filter changes
87
+
88
+ The composable returns `activeFilterButton` (a ref) which you can focus after DOM updates.
89
+
90
+ ```ts
91
+ import { nextTick } from 'vue';
92
+
93
+ function onFilterChange(event: any) {
94
+ // update your filter state and data here
95
+
96
+ nextTick(() => {
97
+ if (activeFilterButton.value) {
98
+ activeFilterButton.value.focus();
99
+ }
100
+ });
101
+ }
102
+ ```
103
+
104
+ ## 5) Custom sort handling with composable helper
105
+
106
+ If you need to show a loader or call an API, pass a custom callback into the composable's sort helper so the composable does its internal work and your app performs side effects.
107
+
108
+ ```ts
109
+ const optionalCustomSort = (event: any) => {
110
+ loader.value = true;
111
+ // example async
112
+ setTimeout(() => {
113
+ loader.value = false;
114
+ // apply sort state and reload data
115
+ }, 200);
116
+ };
117
+
118
+ function onSortChange(event: any) {
119
+ handleSortChange(event, optionalCustomSort);
120
+ }
121
+ ```
67
122
 
68
- ## License
123
+ ## 6) Summary checklist
69
124
 
70
- See top-level `LICENSE` for repository licensing information.
125
+ - Import and call `useGridA11y(gridRef)`
126
+ - Bind returned keyboard handler to Grid `@keydown`
127
+ - Bind returned sort handler to Grid `@sortchange` (and optionally pass a custom callback)
128
+ - Use returned `activeFilterButton` to manage focus after filter updates
129
+ - Provide a `rowRender` that adds a descriptive `aria-label` for each row
130
+ - Set `navigatable="false"` on the Grid to prefer row-level navigation
@@ -1,75 +1,75 @@
1
1
  import { ref as E, onMounted as S, onBeforeUnmount as M, nextTick as p, onUnmounted as N } from "vue";
2
- const G = (m) => {
3
- const l = E(null);
4
- let d = null, u = null;
5
- const f = [], v = ".k-table-row[data-grid-row-index] [tabindex]", k = () => m?.value?.columns, h = (e) => {
6
- const o = e.key || e.code;
7
- [" ", "Spacebar", "Space", "Enter"].includes(o) && (e.preventDefault(), e.stopPropagation(), l.value = e.target, e.target.click());
8
- }, g = (e) => {
9
- if (!l.value) return;
10
- if (e.code === "Escape") {
11
- e.preventDefault(), e.stopPropagation(), l.value && l.value.focus();
2
+ const G = (f) => {
3
+ const s = E(null);
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
+ const o = t.key || t.code;
7
+ [" ", "Spacebar", "Space", "Enter"].includes(o) && (t.preventDefault(), t.stopPropagation(), s.value = t.target, t.target.click());
8
+ }, g = (t) => {
9
+ if (!s.value) return;
10
+ if (t.code === "Escape") {
11
+ t.preventDefault(), t.stopPropagation(), s.value && s.value.focus();
12
12
  return;
13
13
  }
14
14
  const o = Array.from(
15
15
  document.querySelectorAll(
16
16
  ".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item"
17
17
  )
18
- ), t = document.querySelector(".k-filter-menu-container");
19
- if (t) {
20
- if (e.code === "Tab") {
18
+ ), e = document.querySelector(".k-filter-menu-container");
19
+ if (e) {
20
+ if (t.code === "Tab") {
21
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
25
  ], n = Array.from(
26
- t.querySelectorAll(r.join(","))
26
+ e.querySelectorAll(r.join(","))
27
27
  );
28
28
  if (n.length === 0) return;
29
29
  const a = n.findIndex(
30
- (s) => s === document.activeElement
30
+ (l) => l === document.activeElement
31
31
  );
32
32
  let i;
33
- a === -1 ? i = 0 : e.shiftKey ? i = (a - 1 + n.length) % n.length : i = (a + 1) % n.length, e.preventDefault(), e.stopPropagation(), n[i]?.focus();
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
- } else if (e.code === "ArrowUp" || e.code === "ArrowDown") {
37
- e.preventDefault(), e.stopPropagation();
36
+ } else if (t.code === "ArrowUp" || t.code === "ArrowDown") {
37
+ t.preventDefault(), t.stopPropagation();
38
38
  const r = o.findIndex(
39
39
  (a) => a === document.activeElement
40
40
  );
41
41
  let n = r;
42
- e.code === "ArrowUp" ? n = r > 0 ? r - 1 : o.length - 1 : e.code === "ArrowDown" && (n = r < o.length - 1 ? r + 1 : 0), o[n]?.focus();
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
- e.code === "Tab" && (e.preventDefault(), e.stopPropagation(), e.shiftKey ? (l.value?.previousElementSibling).focus() : (l.value?.nextElementSibling).focus());
45
+ t.code === "Tab" && (t.preventDefault(), t.stopPropagation(), t.shiftKey ? (s.value?.previousElementSibling).focus() : (s.value?.nextElementSibling).focus());
46
46
  }, x = () => {
47
- d = new MutationObserver((e) => {
48
- e.forEach((o) => {
49
- o.addedNodes.forEach((t) => {
50
- if (t.nodeType === Node.ELEMENT_NODE) {
51
- const r = t;
47
+ m = new MutationObserver((t) => {
48
+ t.forEach((o) => {
49
+ o.addedNodes.forEach((e) => {
50
+ if (e.nodeType === Node.ELEMENT_NODE) {
51
+ const r = e;
52
52
  if (r.classList.contains("k-animation-container")) {
53
- const a = l.value;
53
+ const a = s.value;
54
54
  a && (a.dataset.featherKSortable === "true" || p(() => {
55
55
  r.querySelectorAll(
56
56
  ".k-columnmenu-item-wrapper"
57
- ).forEach((b) => {
58
- b.textContent?.toLowerCase().includes("sort") && b.remove();
57
+ ).forEach((d) => {
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
- const s = Array.from(
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
  );
70
- if (s.length === 1)
71
- s[0].focus(), s[0].click(), i.attempts = 0;
72
- else if (s.length > 1) {
70
+ if (l.length === 1)
71
+ l[0].focus(), l[0].click(), i.attempts = 0;
72
+ else if (l.length > 1) {
73
73
  i.attempts = 0;
74
74
  return;
75
75
  } else
@@ -87,9 +87,9 @@ const G = (m) => {
87
87
  );
88
88
  });
89
89
  }
90
- }), o.removedNodes.forEach((t) => {
91
- if (t.nodeType === Node.ELEMENT_NODE) {
92
- const r = t;
90
+ }), o.removedNodes.forEach((e) => {
91
+ if (e.nodeType === Node.ELEMENT_NODE) {
92
+ const r = e;
93
93
  r.classList.contains("k-animation-container") && r.removeEventListener(
94
94
  "keydown",
95
95
  g
@@ -104,65 +104,95 @@ const G = (m) => {
104
104
  }
105
105
  });
106
106
  });
107
- }), d.observe(document.body, {
107
+ }), m.observe(document.body, {
108
108
  childList: !0,
109
109
  subtree: !0
110
110
  });
111
- }, L = (e) => {
112
- if (!e.type || !e)
111
+ }, L = (t) => {
112
+ if (!t.type || !t)
113
113
  return;
114
- console.log("handleGridKeyDown", e, e.code);
115
- const o = e.target;
116
- if (o && [
117
- "ArrowDown",
118
- "ArrowLeft",
119
- "ArrowRight",
120
- "ArrowUp",
121
- "Enter",
122
- "Space"
123
- ].includes(e.code)) {
124
- if (e.preventDefault(), o.classList.contains("k-grid-header-menu") && o.classList.contains("k-grid-column-menu")) {
125
- l.value = o;
126
- return;
114
+ console.log("handleGridKeyDown", t, t.code);
115
+ const o = t.target;
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
- const t = o.closest(
129
- ".k-table-row[data-grid-row-index]"
130
- );
131
- if (t) {
132
- if (["ArrowDown", "ArrowUp"].includes(e.code)) {
133
- let r = null;
134
- e.code === "ArrowDown" ? r = t.nextElementSibling : e.code === "ArrowUp" && (r = t.previousElementSibling), r && r.hasAttribute("tabindex") && (t.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;
135
143
  return;
136
144
  }
137
- if (["ArrowLeft", "ArrowRight"].includes(e.code)) {
138
- e.preventDefault();
139
- const r = t.querySelectorAll(
140
- v
141
- );
142
- if (r.length === 0) return;
143
- let n = Array.from(r).findIndex(
144
- (a) => a === document.activeElement
145
- );
146
- if (n === -1 && document.activeElement === t) {
147
- r[0].focus();
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();
148
180
  return;
149
181
  }
150
- e.code === "ArrowRight" ? n = n === r.length - 1 ? 0 : n + 1 : e.code === "ArrowLeft" && (n = n === r.length - 1 ? n - 1 : r.length - 1), r[n].focus();
151
- return;
152
182
  }
153
183
  }
154
184
  }
155
185
  }, D = () => {
156
186
  p(() => {
157
- const e = m.value.$el.closest(".k-grid");
158
- e && e.classList.add("fk-grid");
187
+ const t = f.value.$el.closest(".k-grid");
188
+ t && t.classList.add("fk-grid");
159
189
  });
160
- }, T = () => {
190
+ }, q = () => {
161
191
  try {
162
- const e = () => {
192
+ const t = () => {
163
193
  try {
164
194
  const r = Array.from(
165
- m.value.$el.querySelectorAll(
195
+ f.value.$el.querySelectorAll(
166
196
  ".k-table-row[data-grid-row-index]"
167
197
  )
168
198
  );
@@ -181,25 +211,25 @@ const G = (m) => {
181
211
  console.error("ensureSingleTabindex error:", r);
182
212
  }
183
213
  }, o = Array.from(
184
- m.value.$el.querySelectorAll(
214
+ f.value.$el.querySelectorAll(
185
215
  ".k-table-row[data-grid-row-index]"
186
216
  )
187
217
  );
188
218
  o.length > 0 && o.forEach((r, n) => {
189
219
  r.setAttribute("tabindex", n === 0 ? "0" : "-1");
190
220
  });
191
- const t = m.value.$el.querySelector(".k-table-tbody");
192
- t && (u = new MutationObserver(() => {
193
- e();
194
- }), u.observe(t, { childList: !0, subtree: !0 }));
195
- } catch (e) {
196
- console.error("Error setting up row navigation:", e);
221
+ const e = f.value.$el.querySelector(".k-table-tbody");
222
+ e && (u = new MutationObserver(() => {
223
+ t();
224
+ }), u.observe(e, { childList: !0, subtree: !0 }));
225
+ } catch (t) {
226
+ console.error("Error setting up row navigation:", t);
197
227
  }
198
- }, q = () => {
228
+ }, T = () => {
199
229
  p(() => {
200
230
  const o = document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");
201
- o && o.forEach((t) => {
202
- t.setAttribute("role", "button"), t.addEventListener(
231
+ o && o.forEach((e) => {
232
+ e.setAttribute("role", "button"), e.addEventListener(
203
233
  "keydown",
204
234
  h
205
235
  );
@@ -207,41 +237,41 @@ const G = (m) => {
207
237
  });
208
238
  }, C = () => {
209
239
  const o = document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");
210
- o && o.forEach((t) => {
211
- t.removeEventListener(
240
+ o && o.forEach((e) => {
241
+ e.removeEventListener(
212
242
  "keydown",
213
243
  h
214
244
  );
215
- }), d && (d.disconnect(), d = null), u && (u.disconnect(), u = null), f.forEach((t) => t()), f.length = 0;
245
+ }), m && (m.disconnect(), m = null), u && (u.disconnect(), u = null), b.forEach((e) => e()), b.length = 0;
216
246
  }, I = () => {
217
247
  document.querySelectorAll(
218
248
  ".k-grid-header .k-table-thead th"
219
- ).forEach((t, r) => {
220
- const n = t.querySelector(
249
+ ).forEach((e, r) => {
250
+ const n = e.querySelector(
221
251
  ".k-grid-header-menu.k-grid-column-menu"
222
252
  );
223
253
  if (!n) return;
224
254
  const a = k();
225
255
  if (a && a[r]) {
226
256
  const c = a[r].field ?? "";
227
- t.setAttribute("data-feather-k-field", c), t.setAttribute(
257
+ e.setAttribute("data-feather-k-field", c), e.setAttribute(
228
258
  "data-feather-k-filterable",
229
259
  a[r].filterable === !1 ? "false" : "true"
230
- ), t.setAttribute(
260
+ ), e.setAttribute(
231
261
  "data-feather-k-sortable",
232
262
  a[r].sortable === !1 ? "false" : "true"
233
263
  );
234
264
  }
235
- const i = t.dataset.featherKFilterable !== "false", s = t.dataset.featherKSortable !== "false";
236
- n.setAttribute("tabindex", "-1"), i ? (t.setAttribute("tabindex", "0"), t.setAttribute("role", "button"), t.setAttribute("aria-haspopup", "menu"), t.style.cursor = "pointer") : (t.setAttribute("tabindex", "0"), t.setAttribute("role", "columnheader"), t.removeAttribute("aria-haspopup"), t.style.cursor = "default");
237
- const b = (c) => {
238
- c.target?.closest(".k-column-resizer") || (l.value = t, n.click());
239
- }, w = (c) => {
265
+ const i = e.dataset.featherKFilterable !== "false", l = e.dataset.featherKSortable !== "false";
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");
267
+ const d = (c) => {
268
+ c.target?.closest(".k-column-resizer") || (s.value = e, n.click());
269
+ }, v = (c) => {
240
270
  if (i)
241
- l.value = t, c.preventDefault(), c.stopPropagation(), b(c);
242
- else if (s) {
243
- l.value = t;
244
- const y = new KeyboardEvent("keydown", {
271
+ s.value = e, c.preventDefault(), c.stopPropagation(), d(c);
272
+ else if (l) {
273
+ s.value = e;
274
+ const w = new KeyboardEvent("keydown", {
245
275
  key: "Enter",
246
276
  code: "Enter",
247
277
  keyCode: 13,
@@ -249,95 +279,95 @@ const G = (m) => {
249
279
  bubbles: !0,
250
280
  cancelable: !0
251
281
  });
252
- t.dispatchEvent(y);
282
+ e.dispatchEvent(w);
253
283
  }
254
284
  };
255
- t.addEventListener("click", w), f.push(() => {
256
- t.removeEventListener("click", w);
285
+ e.addEventListener("click", v), b.push(() => {
286
+ e.removeEventListener("click", v);
257
287
  });
258
288
  const A = (c) => {
259
- if ((c.code === "Enter" || c.code === "Space") && (i || s)) {
260
- if (l.value = t, l.value.focus(), i)
261
- c.preventDefault(), c.stopPropagation(), b(c);
262
- else if (s) {
263
- const y = t.querySelector(".k-link");
264
- y && y.click();
289
+ if ((c.code === "Enter" || c.code === "Space") && (i || l)) {
290
+ if (s.value = e, s.value.focus(), i)
291
+ c.preventDefault(), c.stopPropagation(), d(c);
292
+ else if (l) {
293
+ const w = e.querySelector(".k-link");
294
+ w && w.click();
265
295
  }
266
296
  }
267
297
  };
268
- t.addEventListener("keydown", A, !0), f.push(() => {
269
- t.removeEventListener("keydown", A, !0);
298
+ e.addEventListener("keydown", A, !0), b.push(() => {
299
+ e.removeEventListener("keydown", A, !0);
270
300
  });
271
301
  });
272
302
  const o = document.querySelector(".k-grid-header .k-table-thead");
273
303
  if (o) {
274
- const t = (r) => {
304
+ const e = (r) => {
275
305
  const n = r.target.closest("th");
276
306
  n && (r.code === "Enter" || r.code === "Space") && n.dataset.featherKFilterable === "false" && n.dataset.featherKSortable === "false" && (r.preventDefault(), r.stopImmediatePropagation());
277
307
  };
278
308
  o.addEventListener(
279
309
  "keydown",
280
- t,
310
+ e,
281
311
  !0
282
312
  // NOTE: capture phase
283
- ), f.push(() => {
313
+ ), b.push(() => {
284
314
  o.removeEventListener(
285
315
  "keydown",
286
- t,
316
+ e,
287
317
  !0
288
318
  );
289
319
  });
290
320
  }
291
- }, K = function(e, o) {
292
- const t = e?.event.event.target, r = k();
293
- if (!t || !r) return;
294
- const n = t.classList.contains("k-link"), a = t.classList.contains("k-columnmenu-item"), i = r.find((s) => s.field === e.event.field)?.sortable && !0;
321
+ }, K = function(t, o) {
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;
295
325
  if (!n) {
296
326
  if (a && !i) {
297
- (e.event.sort && void 0)?.filter(
298
- (b) => b.field !== e.event.field
327
+ (t.event.sort && void 0)?.filter(
328
+ (d) => d.field !== t.event.field
299
329
  );
300
330
  return;
301
331
  }
302
332
  typeof o == "function" && p(() => {
303
- l.value && l.value.focus(), o(e);
333
+ s.value && s.value.focus(), o(t);
304
334
  });
305
335
  }
306
336
  };
307
337
  return S(() => {
308
- D(), T(), q();
338
+ D(), q(), T();
309
339
  }), M(() => {
310
340
  C();
311
341
  }), {
312
- activeFilterButton: l,
342
+ activeFilterButton: s,
313
343
  handleGridKeyDown: L,
314
344
  handleSortChange: K
315
345
  };
316
346
  };
317
- function B(m = {}) {
318
- const { activeByDefault: l = !1, autoActivateDelay: d = 0 } = m, u = E(l);
319
- function f() {
347
+ function P(f = {}) {
348
+ const { activeByDefault: s = !1, autoActivateDelay: m = 0 } = f, u = E(s);
349
+ function b() {
320
350
  u.value = !0;
321
351
  }
322
- function v() {
352
+ function y() {
323
353
  u.value = !1;
324
354
  }
325
355
  function k() {
326
356
  u.value = !u.value;
327
357
  }
328
358
  return S(() => {
329
- d > 0 && !l && setTimeout(() => {
330
- f();
331
- }, d);
359
+ m > 0 && !s && setTimeout(() => {
360
+ b();
361
+ }, m);
332
362
  }), N(() => {
333
363
  }), {
334
364
  isGridActive: u,
335
- activateGrid: f,
336
- deactivateGrid: v,
365
+ activateGrid: b,
366
+ deactivateGrid: y,
337
367
  toggleGrid: k
338
368
  };
339
369
  }
340
370
  export {
341
371
  G as useGridA11y,
342
- B as useGridComposableEx
372
+ P as useGridComposableEx
343
373
  };
@@ -1 +1 @@
1
- (function(f,s){typeof exports=="object"&&typeof module<"u"?s(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],s):(f=typeof globalThis<"u"?globalThis:f||self,s(f.FeatherKComposables={},f.Vue))})(this,(function(f,s){"use strict";const S=p=>{const l=s.ref(null);let m=null,d=null;const b=[],h=".k-table-row[data-grid-row-index] [tabindex]",g=()=>p?.value?.columns,v=e=>{const o=e.key||e.code;[" ","Spacebar","Space","Enter"].includes(o)&&(e.preventDefault(),e.stopPropagation(),l.value=e.target,e.target.click())},y=e=>{if(!l.value)return;if(e.code==="Escape"){e.preventDefault(),e.stopPropagation(),l.value&&l.value.focus();return}const o=Array.from(document.querySelectorAll(".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item")),t=document.querySelector(".k-filter-menu-container");if(t){if(e.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(t.querySelectorAll(n.join(",")));if(r.length===0)return;const a=r.findIndex(c=>c===document.activeElement);let i;a===-1?i=0:e.shiftKey?i=(a-1+r.length)%r.length:i=(a+1)%r.length,e.preventDefault(),e.stopPropagation(),r[i]?.focus();return}}else if(e.code==="ArrowUp"||e.code==="ArrowDown"){e.preventDefault(),e.stopPropagation();const n=o.findIndex(a=>a===document.activeElement);let r=n;e.code==="ArrowUp"?r=n>0?n-1:o.length-1:e.code==="ArrowDown"&&(r=n<o.length-1?n+1:0),o[r]?.focus();return}e.code==="Tab"&&(e.preventDefault(),e.stopPropagation(),e.shiftKey?(l.value?.previousElementSibling).focus():(l.value?.nextElementSibling).focus())},L=()=>{m=new MutationObserver(e=>{e.forEach(o=>{o.addedNodes.forEach(t=>{if(t.nodeType===Node.ELEMENT_NODE){const n=t;if(n.classList.contains("k-animation-container")){const a=l.value;a&&(a.dataset.featherKSortable==="true"||s.nextTick(()=>{n.querySelectorAll(".k-columnmenu-item-wrapper").forEach(k=>{k.textContent?.toLowerCase().includes("sort")&&k.remove()})})),n.addEventListener("keydown",y),s.nextTick(()=>{const i=()=>{const c=Array.from(n.querySelectorAll(".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item"));if(c.length===1)c[0].focus(),c[0].click(),i.attempts=0;else if(c.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(t=>{if(t.nodeType===Node.ELEMENT_NODE){const n=t;n.classList.contains("k-animation-container")&&n.removeEventListener("keydown",y),n.querySelectorAll(".k-animation-container").forEach(a=>{a.removeEventListener("keydown",y)})}})})}),m.observe(document.body,{childList:!0,subtree:!0})},T=e=>{if(!e.type||!e)return;console.log("handleGridKeyDown",e,e.code);const o=e.target;if(o&&["ArrowDown","ArrowLeft","ArrowRight","ArrowUp","Enter","Space"].includes(e.code)){if(e.preventDefault(),o.classList.contains("k-grid-header-menu")&&o.classList.contains("k-grid-column-menu")){l.value=o;return}const t=o.closest(".k-table-row[data-grid-row-index]");if(t){if(["ArrowDown","ArrowUp"].includes(e.code)){let n=null;e.code==="ArrowDown"?n=t.nextElementSibling:e.code==="ArrowUp"&&(n=t.previousElementSibling),n&&n.hasAttribute("tabindex")&&(t.setAttribute("tabindex","-1"),n.setAttribute("tabindex","0"),n.focus());return}if(["ArrowLeft","ArrowRight"].includes(e.code)){e.preventDefault();const n=t.querySelectorAll(h);if(n.length===0)return;let r=Array.from(n).findIndex(a=>a===document.activeElement);if(r===-1&&document.activeElement===t){n[0].focus();return}e.code==="ArrowRight"?r=r===n.length-1?0:r+1:e.code==="ArrowLeft"&&(r=r===n.length-1?r-1:n.length-1),n[r].focus();return}}}},D=()=>{s.nextTick(()=>{const e=p.value.$el.closest(".k-grid");e&&e.classList.add("fk-grid")})},q=()=>{try{const e=()=>{try{const n=Array.from(p.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(p.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 t=p.value.$el.querySelector(".k-table-tbody");t&&(d=new MutationObserver(()=>{e()}),d.observe(t,{childList:!0,subtree:!0}))}catch(e){console.error("Error setting up row navigation:",e)}},C=()=>{s.nextTick(()=>{const o=document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");o&&o.forEach(t=>{t.setAttribute("role","button"),t.addEventListener("keydown",v)}),L(),K()})},I=()=>{const o=document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");o&&o.forEach(t=>{t.removeEventListener("keydown",v)}),m&&(m.disconnect(),m=null),d&&(d.disconnect(),d=null),b.forEach(t=>t()),b.length=0},K=()=>{document.querySelectorAll(".k-grid-header .k-table-thead th").forEach((t,n)=>{const r=t.querySelector(".k-grid-header-menu.k-grid-column-menu");if(!r)return;const a=g();if(a&&a[n]){const u=a[n].field??"";t.setAttribute("data-feather-k-field",u),t.setAttribute("data-feather-k-filterable",a[n].filterable===!1?"false":"true"),t.setAttribute("data-feather-k-sortable",a[n].sortable===!1?"false":"true")}const i=t.dataset.featherKFilterable!=="false",c=t.dataset.featherKSortable!=="false";r.setAttribute("tabindex","-1"),i?(t.setAttribute("tabindex","0"),t.setAttribute("role","button"),t.setAttribute("aria-haspopup","menu"),t.style.cursor="pointer"):(t.setAttribute("tabindex","0"),t.setAttribute("role","columnheader"),t.removeAttribute("aria-haspopup"),t.style.cursor="default");const k=u=>{u.target?.closest(".k-column-resizer")||(l.value=t,r.click())},A=u=>{if(i)l.value=t,u.preventDefault(),u.stopPropagation(),k(u);else if(c){l.value=t;const w=new KeyboardEvent("keydown",{key:"Enter",code:"Enter",keyCode:13,which:13,bubbles:!0,cancelable:!0});t.dispatchEvent(w)}};t.addEventListener("click",A),b.push(()=>{t.removeEventListener("click",A)});const E=u=>{if((u.code==="Enter"||u.code==="Space")&&(i||c)){if(l.value=t,l.value.focus(),i)u.preventDefault(),u.stopPropagation(),k(u);else if(c){const w=t.querySelector(".k-link");w&&w.click()}}};t.addEventListener("keydown",E,!0),b.push(()=>{t.removeEventListener("keydown",E,!0)})});const o=document.querySelector(".k-grid-header .k-table-thead");if(o){const t=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",t,!0),b.push(()=>{o.removeEventListener("keydown",t,!0)})}},M=function(e,o){const t=e?.event.event.target,n=g();if(!t||!n)return;const r=t.classList.contains("k-link"),a=t.classList.contains("k-columnmenu-item"),i=n.find(c=>c.field===e.event.field)?.sortable&&!0;if(!r){if(a&&!i){(e.event.sort&&void 0)?.filter(k=>k.field!==e.event.field);return}typeof o=="function"&&s.nextTick(()=>{l.value&&l.value.focus(),o(e)})}};return s.onMounted(()=>{D(),q(),C()}),s.onBeforeUnmount(()=>{I()}),{activeFilterButton:l,handleGridKeyDown:T,handleSortChange:M}};function x(p={}){const{activeByDefault:l=!1,autoActivateDelay:m=0}=p,d=s.ref(l);function b(){d.value=!0}function h(){d.value=!1}function g(){d.value=!d.value}return s.onMounted(()=>{m>0&&!l&&setTimeout(()=>{b()},m)}),s.onUnmounted(()=>{}),{isGridActive:d,activateGrid:b,deactivateGrid:h,toggleGrid:g}}f.useGridA11y=S,f.useGridComposableEx=x,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));
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/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { useGridA11y } from './useGridA11y';
2
- export { useGridComposableEx } from './useGridComposableEx';
1
+ export { useGridA11y } from "./useGridA11y";
2
+ export { useGridComposableEx } from "./useGridComposableEx";
@@ -4,7 +4,7 @@
4
4
  */
5
5
  export interface SortDescriptor {
6
6
  field?: string;
7
- dir?: 'asc' | 'desc';
7
+ dir?: "asc" | "desc";
8
8
  }
9
9
  export interface GridColumnProps {
10
10
  field?: string;
@@ -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.5",
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",
@@ -11,7 +11,6 @@
11
11
  "build": "vite build && npm run build:types",
12
12
  "build:types": "vue-tsc --emitDeclarationOnly --declaration --declarationDir dist",
13
13
  "test": "vitest",
14
- "lint": "eslint src --ext .ts,.vue",
15
14
  "clean": "rm -rf dist",
16
15
  "prepublishOnly": "npm run build"
17
16
  },
@@ -21,7 +20,6 @@
21
20
  "devDependencies": {
22
21
  "@types/node": "^24.5.2",
23
22
  "@vitejs/plugin-vue": "^6.0.1",
24
- "eslint": "^8.0.0",
25
23
  "typescript": "~5.8.3",
26
24
  "vite": "^7.1.7",
27
25
  "vitest": "^3.2.4",