@featherk/composables 0.4.12 → 0.5.1

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,153 +1,93 @@
1
1
  # `@featherk/composables`
2
2
 
3
- > This package provides Vue 3 composables intended to augment and improve Kendo UI for Vue (Telerik) component behavior.
4
- >
5
- > *This package is not affiliated with or approved by Telerik.*
3
+ Vue 3 composables that improve Kendo UI for Vue behavior and accessibility.
6
4
 
7
- ## useGridA11y — Integration Quick Reference
8
-
9
- ### BIG DISCLAIMER
10
-
11
- > 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.
12
-
13
- ### Compatibility
14
-
15
- > The current version of `useGridA11y` composable was developed targeting Kendo UI for Vue version 6.4.1.
16
- >*Use of Kendo UI for Vue Grid requires a paid [license](https://www.telerik.com/purchase/kendo-ui) from Telerik.*
17
- >
18
- >See [Kendo UI for Vue Grid Documentation](https://www.telerik.com/kendo-vue-ui/components/grid)
19
-
20
- ### Notes
5
+ ## Importing Composables
21
6
 
22
- - The composable expects a Grid ref (a Vue ref to the Grid component).
23
- - For row-level navigation, disable the Grid's cell-level dynamic tabindex behavior (omit or set `navigatable="false"` on the Grid).
24
- - The composable returns helpers for keyboard handling, focus management, initialization (new `initA11y()`), and sort/filter interactions.
7
+ You can import directly from subpaths or from the package root.
25
8
 
26
- ### Styling and the `.fk-grid` class
9
+ Subpath imports (recommended for clarity):
27
10
 
28
- - 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).
29
- - 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.
30
- - 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).
31
-
32
- ### Prerequisites
33
-
34
- - Vue 3 (script setup)
35
- - `@progress/kendo-vue-grid` installed
36
- - `@featherk/composables` installed
37
-
38
- Install (if needed)
39
-
40
- ```bash
41
- npm install @featherk/composables
42
- ```
11
+ ```ts
12
+ // Date input
13
+ import { useMaskedDateInput, DateChangePayload } from '@featherk/composables/date';
43
14
 
44
- ### 1) Minimal import + setup
15
+ // Date range input
16
+ import { useMaskedDateRangeInput, RangeChangePayload } from '@featherk/composables/range';
45
17
 
46
- Place inside a `<script setup lang="ts">` block. Provide a Grid ref and call the composable.
18
+ // Time input
19
+ import { useMaskedTimeInput, TimeChangePayload } from '@featherk/composables/time';
47
20
 
48
- ```ts
49
- import { ref, onMounted, watch } from 'vue';
50
- import { useGridA11y } from '@featherk/composables';
51
-
52
- const gridRef = ref(null);
53
- const dataResult = ref({ data: [] }); // example data container
54
-
55
- const {
56
- activeFilterButton,
57
- handleGridKeyDown,
58
- handleSortChange,
59
- initA11y // NEW: must be called after Grid + data are present in DOM
60
- } = useGridA11y(gridRef);
21
+ // Popup focus trap utilities
22
+ import { usePopupTrap } from '@featherk/composables/trap';
61
23
  ```
62
24
 
63
- ### 2) Initialize accessibility after Grid mounts and data is available
64
-
65
- Call `initA11y()` once the Grid element is in the DOM and the initial (non-empty) data set is ready. If data loads async, watch it. `initA11y()` performs initial attribute setup, internal bookkeeping, and prepares focus targets.
25
+ Root imports (types are aliased to avoid name collisions):
66
26
 
67
27
  ```ts
68
- onMounted(() => {
69
- // Adjust source as needed for your data state
70
- watch(
71
- () => dataResult.value.data,
72
- (rows) => {
73
- if (rows && rows.length && gridRef.value) {
74
- initA11y(); // safe to call again; will no-op after first successful init
75
- }
76
- },
77
- { immediate: true }
78
- );
79
- });
28
+ import {
29
+ useMaskedDateInput,
30
+ DateChangePayload,
31
+ useMaskedDateRangeInput,
32
+ RangeChangePayload,
33
+ useMaskedTimeInput,
34
+ TimeChangePayload,
35
+ usePopupTrap,
36
+ } from '@featherk/composables';
80
37
  ```
81
38
 
82
- If data can change from empty to non-empty multiple times, the composable guards against redundant full initialization.
83
-
84
- ### 3) Wire keyboard handler on the Grid
39
+ ## useGridA11y Integration Quick Reference
85
40
 
86
- Template snippet showing essential bindings (keep other `Grid` props as required by your app):
41
+ ## Composables Overview
87
42
 
88
- ```html
89
- <Grid
90
- ref="gridRef"
91
- :dataItems="dataResult.data"
92
- :dataItemKey="'id'"
93
- :rowRender="renderRow" // optional: aria-label for screen reader
94
- @keydown="handleGridKeyDown" // keyboard navigation
95
- @sortchange="handleSortChange" // composable-aware sort handling
96
- navigatable="false" // turn off cell to cell navigation
97
- />
98
- ```
43
+ - **Grid**: `useGridA11y` — Accessible row-level navigation and column menu keyboard support.
44
+ - Guide: [docs/grid/useGridA11y.md](https://github.com/NantHealth/featherk/blob/integration/packages/composables/docs/grid/useGridA11y.md)
45
+ - **Date**: `useMaskedDateInput` — Masked single-date input with steppers and validation.
46
+ - Guide: [docs/date/useMaskedDateInput.md](https://github.com/NantHealth/featherk/blob/integration/packages/composables/docs/date/useMaskedDateInput.md)
47
+ - **Range**: `useMaskedDateRangeInput` — Masked date range input with validation, clamp, and optional popup coordination.
48
+ - Guide: [docs/range/useMaskedDateRangeInput.md](https://github.com/NantHealth/featherk/blob/integration/packages/composables/docs/range/useMaskedDateRangeInput.md)
49
+ - **Time**: `useMaskedTimeInput` — Masked single-time input with AM/PM conveniences and bounds.
50
+ - Guide: [docs/time/useMaskedTimeInput.md](https://github.com/NantHealth/featherk/blob/integration/packages/composables/docs/time/useMaskedTimeInput.md)
51
+ - **Trap**: `usePopupTrap` Focus trap + Escape/Outside click close behavior for popups.
52
+ - Guide: [docs/trap/usePopupTrap.md](https://github.com/NantHealth/featherk/blob/integration/packages/composables/docs/trap/usePopupTrap.md)
99
53
 
100
- ### 4) Provide an accessible row renderer (`aria-label`)
54
+ ## Importing
101
55
 
102
- > Not part of `@featherk/composable`, but good practice
103
-
104
- Kendo Grid `rowRender` allows you to add an `aria-label` so screen readers announce row contents.
56
+ Subpath imports (recommended):
105
57
 
106
58
  ```ts
107
- const renderRow = (h: any, trElement: any, defaultSlots: any, props: any) => {
108
- const ariaLabel = `Name: ${props.dataItem.name}, Price: ${props.dataItem.price}`;
109
- const merged = { ...trElement.props, 'aria-label': ariaLabel };
110
- return h('tr', merged, defaultSlots);
111
- };
59
+ import { useGridA11y } from '@featherk/composables/grid';
60
+ import { useMaskedDateInput } from '@featherk/composables/date';
61
+ import { useMaskedDateRangeInput } from '@featherk/composables/range';
62
+ import { useMaskedTimeInput } from '@featherk/composables/time';
63
+ import { usePopupTrap } from '@featherk/composables/trap';
112
64
  ```
113
65
 
114
- ### 5) Focus the active filter button after filter changes
66
+ Root import (types are aliased to avoid collisions):
115
67
 
116
68
  ```ts
117
- import { nextTick } from 'vue';
118
-
119
- function onFilterChange(event: any) {
120
- // update filter state + reload data
121
- nextTick(() => {
122
- if (activeFilterButton.value) {
123
- activeFilterButton.value.focus();
124
- }
125
- });
126
- }
69
+ import {
70
+ useGridA11y,
71
+ useMaskedDateInput,
72
+ useMaskedDateRangeInput,
73
+ useMaskedTimeInput,
74
+ usePopupTrap,
75
+ } from '@featherk/composables';
127
76
  ```
128
77
 
129
- ### 6) Custom sort handling with composable helper
78
+ ## Peer Dependencies
130
79
 
131
- ```ts
132
- const optionalCustomSort = (event: any) => {
133
- loader.value = true;
134
- setTimeout(() => {
135
- loader.value = false;
136
- // apply sort state and reload data
137
- }, 200);
138
- };
139
-
140
- function onSortChange(event: any) {
141
- handleSortChange(event, optionalCustomSort);
142
- }
80
+ - Required: `vue`
81
+ - Optional (for `usePopupTrap`): `@vueuse/core`, `@vueuse/integrations`, `focus-trap`
82
+
83
+ ```bash
84
+ npm install vue
85
+ # If you use usePopupTrap
86
+ npm install @vueuse/core @vueuse/integrations focus-trap
143
87
  ```
144
88
 
145
- ### 7) Summary checklist
89
+ > Note: VueUse and focus-trap are declared as optional peer dependencies so apps that don’t use `usePopupTrap` aren’t forced to install them. They are present as devDependencies in this repo to enable local type-checking and builds.
90
+
91
+ ## Notes
146
92
 
147
- - Import and call `useGridA11y(gridRef)`
148
- - Wait for Grid mount + data, then call `initA11y()`
149
- - Bind returned keyboard handler to `Grid` `@keydown`
150
- - Bind returned sort handler to `Grid` `@sortchange` (optionally pass a custom callback)
151
- - Use returned `activeFilterButton` to manage focus after filter updates
152
- - Provide a `rowRender` that adds a descriptive `aria-label` for each row
153
- - Set `navigatable="false"` on the `Grid` to prefer row-level navigation
93
+ - The runtime file `useGridA11y.ts` currently lives at the package root for compatibility. It may move to `src/grid` in a future release, but root exports will remain to avoid breaking imports.
@@ -0,0 +1 @@
1
+ export * from "./useMaskedDateInput";
@@ -0,0 +1,33 @@
1
+ import { type Ref } from "vue";
2
+ export type ChangePayload = {
3
+ value: Date | null;
4
+ event: any;
5
+ };
6
+ export declare function useMaskedDateInput(args: {
7
+ id: string;
8
+ onChange: (p: ChangePayload) => void;
9
+ onShowCalendar: (e: KeyboardEvent) => void;
10
+ externalValue?: Ref<string | Date | null | undefined>;
11
+ minDate?: Ref<Date | null | undefined>;
12
+ maxDate?: Ref<Date | null | undefined>;
13
+ dateFormat?: string;
14
+ debug?: boolean;
15
+ }): {
16
+ raw: Ref<string, string>;
17
+ cursorPos: Ref<number, number>;
18
+ debugEnabled: Ref<boolean, boolean>;
19
+ debugLines: import("vue").ComputedRef<string[][]>;
20
+ placeholder: Ref<string, string>;
21
+ isValid: import("vue").ComputedRef<boolean>;
22
+ validationMessage: import("vue").ComputedRef<string>;
23
+ digitsOnly: import("vue").ComputedRef<string>;
24
+ month: Readonly<Ref<string, string>>;
25
+ day: Readonly<Ref<string, string>>;
26
+ year: Readonly<Ref<string, string>>;
27
+ datePart: (pos: number) => "mm" | "dd" | "yyyy";
28
+ handleChange: (event: any) => void;
29
+ handleKeyDown: (event: KeyboardEvent) => void;
30
+ handleWheel: (event: WheelEvent) => void;
31
+ handleKeyUp: (event: KeyboardEvent) => void;
32
+ handleClick: (event: MouseEvent) => void;
33
+ };