@theaccessibleteam/a11y-feedback-vue 1.0.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/README.md +168 -0
- package/dist/index.cjs +143 -0
- package/dist/index.d.cts +213 -0
- package/dist/index.d.ts +213 -0
- package/dist/index.js +127 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# @theaccessibleteam/a11y-feedback-vue
|
|
2
|
+
|
|
3
|
+
Vue 3 composables for [a11y-feedback](https://www.npmjs.com/package/@theaccessibleteam/a11y-feedback) - the accessibility-first feedback library.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @theaccessibleteam/a11y-feedback @theaccessibleteam/a11y-feedback-vue
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Option 1: Using the Composable (Simple)
|
|
14
|
+
|
|
15
|
+
```vue
|
|
16
|
+
<script setup lang="ts">
|
|
17
|
+
import { useA11yFeedback } from '@theaccessibleteam/a11y-feedback-vue'
|
|
18
|
+
import { configureFeedback } from '@theaccessibleteam/a11y-feedback'
|
|
19
|
+
|
|
20
|
+
// Configure once at app startup
|
|
21
|
+
configureFeedback({ visual: true })
|
|
22
|
+
|
|
23
|
+
const feedback = useA11yFeedback()
|
|
24
|
+
|
|
25
|
+
async function handleSave() {
|
|
26
|
+
feedback.loading('Saving...', { id: 'save' })
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
await saveData()
|
|
30
|
+
feedback.success('Saved!', { id: 'save' })
|
|
31
|
+
} catch (e) {
|
|
32
|
+
feedback.error('Failed to save', { id: 'save' })
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<template>
|
|
38
|
+
<button @click="handleSave">Save</button>
|
|
39
|
+
</template>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Option 2: Using the Plugin (Recommended for Apps)
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
// main.ts
|
|
46
|
+
import { createApp } from 'vue'
|
|
47
|
+
import { a11yFeedbackPlugin } from '@theaccessibleteam/a11y-feedback-vue'
|
|
48
|
+
import App from './App.vue'
|
|
49
|
+
|
|
50
|
+
const app = createApp(App)
|
|
51
|
+
|
|
52
|
+
app.use(a11yFeedbackPlugin, {
|
|
53
|
+
config: {
|
|
54
|
+
visual: true,
|
|
55
|
+
visualPosition: 'top-right',
|
|
56
|
+
},
|
|
57
|
+
debug: import.meta.env.DEV,
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
app.mount('#app')
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then use in components:
|
|
64
|
+
|
|
65
|
+
```vue
|
|
66
|
+
<script setup lang="ts">
|
|
67
|
+
import { inject } from 'vue'
|
|
68
|
+
import { A11yFeedbackKey } from '@theaccessibleteam/a11y-feedback-vue'
|
|
69
|
+
|
|
70
|
+
const feedback = inject(A11yFeedbackKey)!
|
|
71
|
+
|
|
72
|
+
function handleAction() {
|
|
73
|
+
feedback.success('Action completed!')
|
|
74
|
+
}
|
|
75
|
+
</script>
|
|
76
|
+
|
|
77
|
+
<template>
|
|
78
|
+
<button @click="handleAction">Do Something</button>
|
|
79
|
+
</template>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Or with Options API:
|
|
83
|
+
|
|
84
|
+
```vue
|
|
85
|
+
<script lang="ts">
|
|
86
|
+
export default {
|
|
87
|
+
methods: {
|
|
88
|
+
handleAction() {
|
|
89
|
+
this.$a11yFeedback.success('Action completed!')
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
</script>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Composables
|
|
97
|
+
|
|
98
|
+
### `useA11yFeedback()`
|
|
99
|
+
|
|
100
|
+
Main composable providing all feedback methods.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const { success, error, warning, info, loading, dismiss, dismissAll } = useA11yFeedback()
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `useA11yAnnounce()`
|
|
107
|
+
|
|
108
|
+
Lightweight composable for screen reader announcements only.
|
|
109
|
+
|
|
110
|
+
```vue
|
|
111
|
+
<script setup lang="ts">
|
|
112
|
+
import { watch } from 'vue'
|
|
113
|
+
import { useA11yAnnounce } from '@theaccessibleteam/a11y-feedback-vue'
|
|
114
|
+
|
|
115
|
+
const props = defineProps<{ count: number }>()
|
|
116
|
+
const { announcePolite, announceAssertive } = useA11yAnnounce()
|
|
117
|
+
|
|
118
|
+
watch(() => props.count, (newCount) => {
|
|
119
|
+
announcePolite(`Found ${newCount} results`)
|
|
120
|
+
})
|
|
121
|
+
</script>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### `useFeedbackConfig()`
|
|
125
|
+
|
|
126
|
+
Composable for managing configuration reactively.
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
const { config, updateConfig, enableVisual, disableVisual, reset } = useFeedbackConfig()
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Plugin API
|
|
133
|
+
|
|
134
|
+
### `a11yFeedbackPlugin`
|
|
135
|
+
|
|
136
|
+
| Option | Type | Description |
|
|
137
|
+
|--------|------|-------------|
|
|
138
|
+
| `config` | `Partial<FeedbackConfig>` | Configuration options |
|
|
139
|
+
| `debug` | `boolean` | Enable debug mode |
|
|
140
|
+
|
|
141
|
+
### Injection Key
|
|
142
|
+
|
|
143
|
+
Use `A11yFeedbackKey` to inject the feedback instance:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { inject } from 'vue'
|
|
147
|
+
import { A11yFeedbackKey } from '@theaccessibleteam/a11y-feedback-vue'
|
|
148
|
+
|
|
149
|
+
const feedback = inject(A11yFeedbackKey)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## TypeScript
|
|
153
|
+
|
|
154
|
+
Full TypeScript support with exported types:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import type {
|
|
158
|
+
FeedbackType,
|
|
159
|
+
FeedbackOptions,
|
|
160
|
+
FeedbackEvent,
|
|
161
|
+
FeedbackConfig
|
|
162
|
+
} from '@theaccessibleteam/a11y-feedback-vue'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## License
|
|
166
|
+
|
|
167
|
+
MIT
|
|
168
|
+
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
a11yFeedbackPlugin: () => a11yFeedbackPlugin,
|
|
24
|
+
useA11yAnnounce: () => useA11yAnnounce,
|
|
25
|
+
useA11yFeedback: () => useA11yFeedback,
|
|
26
|
+
useFeedbackConfig: () => useFeedbackConfig
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
|
|
30
|
+
// src/useA11yFeedback.ts
|
|
31
|
+
var import_a11y_feedback = require("@theaccessibleteam/a11y-feedback");
|
|
32
|
+
function useA11yFeedback() {
|
|
33
|
+
const success = (message, options) => import_a11y_feedback.notify.success(message, options);
|
|
34
|
+
const error = (message, options) => import_a11y_feedback.notify.error(message, options);
|
|
35
|
+
const warning = (message, options) => import_a11y_feedback.notify.warning(message, options);
|
|
36
|
+
const info = (message, options) => import_a11y_feedback.notify.info(message, options);
|
|
37
|
+
const loading = (message, options) => import_a11y_feedback.notify.loading(message, options);
|
|
38
|
+
const dismiss = (id) => {
|
|
39
|
+
(0, import_a11y_feedback.dismissVisualFeedback)(id);
|
|
40
|
+
};
|
|
41
|
+
const dismissAll = () => {
|
|
42
|
+
(0, import_a11y_feedback.dismissAllVisualFeedback)();
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
success,
|
|
46
|
+
error,
|
|
47
|
+
warning,
|
|
48
|
+
info,
|
|
49
|
+
loading,
|
|
50
|
+
dismiss,
|
|
51
|
+
dismissAll
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/useA11yAnnounce.ts
|
|
56
|
+
var import_a11y_feedback2 = require("@theaccessibleteam/a11y-feedback");
|
|
57
|
+
function useA11yAnnounce() {
|
|
58
|
+
const announcePolite = async (message, options) => {
|
|
59
|
+
await import_a11y_feedback2.notify.info(message, options);
|
|
60
|
+
};
|
|
61
|
+
const announceAssertive = async (message, options) => {
|
|
62
|
+
await import_a11y_feedback2.notify.warning(message, options);
|
|
63
|
+
};
|
|
64
|
+
const announce = async (message, politeness, options) => {
|
|
65
|
+
if (politeness === "assertive") {
|
|
66
|
+
await import_a11y_feedback2.notify.warning(message, options);
|
|
67
|
+
} else {
|
|
68
|
+
await import_a11y_feedback2.notify.info(message, options);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
announcePolite,
|
|
73
|
+
announceAssertive,
|
|
74
|
+
announce
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/useFeedbackConfig.ts
|
|
79
|
+
var import_vue = require("vue");
|
|
80
|
+
var import_a11y_feedback3 = require("@theaccessibleteam/a11y-feedback");
|
|
81
|
+
function useFeedbackConfig() {
|
|
82
|
+
const config = (0, import_vue.ref)((0, import_a11y_feedback3.getConfig)());
|
|
83
|
+
const syncConfig = () => {
|
|
84
|
+
config.value = (0, import_a11y_feedback3.getConfig)();
|
|
85
|
+
};
|
|
86
|
+
const updateConfig = (updates) => {
|
|
87
|
+
(0, import_a11y_feedback3.configureFeedback)(updates);
|
|
88
|
+
syncConfig();
|
|
89
|
+
};
|
|
90
|
+
const reset = () => {
|
|
91
|
+
(0, import_a11y_feedback3.resetConfig)();
|
|
92
|
+
syncConfig();
|
|
93
|
+
};
|
|
94
|
+
const enableVisual = () => {
|
|
95
|
+
updateConfig({ visual: true });
|
|
96
|
+
};
|
|
97
|
+
const disableVisual = () => {
|
|
98
|
+
updateConfig({ visual: false });
|
|
99
|
+
};
|
|
100
|
+
(0, import_vue.onMounted)(() => {
|
|
101
|
+
syncConfig();
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
config: (0, import_vue.readonly)(config),
|
|
105
|
+
updateConfig,
|
|
106
|
+
reset,
|
|
107
|
+
enableVisual,
|
|
108
|
+
disableVisual
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/plugin.ts
|
|
113
|
+
var import_a11y_feedback4 = require("@theaccessibleteam/a11y-feedback");
|
|
114
|
+
var A11yFeedbackKey = /* @__PURE__ */ Symbol("a11y-feedback");
|
|
115
|
+
var a11yFeedbackPlugin = {
|
|
116
|
+
install(app, options = {}) {
|
|
117
|
+
const { config, debug = false } = options;
|
|
118
|
+
if (config) {
|
|
119
|
+
(0, import_a11y_feedback4.configureFeedback)(config);
|
|
120
|
+
}
|
|
121
|
+
if (debug) {
|
|
122
|
+
(0, import_a11y_feedback4.enableFeedbackDebug)();
|
|
123
|
+
}
|
|
124
|
+
const feedback = useA11yFeedback();
|
|
125
|
+
app.provide(A11yFeedbackKey, feedback);
|
|
126
|
+
app.config.globalProperties.$a11yFeedback = feedback;
|
|
127
|
+
app.unmount = /* @__PURE__ */ ((originalUnmount) => {
|
|
128
|
+
return function() {
|
|
129
|
+
(0, import_a11y_feedback4.resetConfig)();
|
|
130
|
+
(0, import_a11y_feedback4.disableFeedbackDebug)();
|
|
131
|
+
(0, import_a11y_feedback4.dismissAllVisualFeedback)();
|
|
132
|
+
return originalUnmount.call(this);
|
|
133
|
+
};
|
|
134
|
+
})(app.unmount);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
138
|
+
0 && (module.exports = {
|
|
139
|
+
a11yFeedbackPlugin,
|
|
140
|
+
useA11yAnnounce,
|
|
141
|
+
useA11yFeedback,
|
|
142
|
+
useFeedbackConfig
|
|
143
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { FeedbackOptions, FeedbackEvent, FeedbackConfig } from '@theaccessibleteam/a11y-feedback';
|
|
2
|
+
export { FeedbackConfig, FeedbackEvent, FeedbackOptions, FeedbackType } from '@theaccessibleteam/a11y-feedback';
|
|
3
|
+
import { DeepReadonly, Ref, App } from 'vue';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Main Vue composable for a11y-feedback
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Return type for useA11yFeedback composable
|
|
11
|
+
*/
|
|
12
|
+
interface UseA11yFeedbackReturn {
|
|
13
|
+
/** Send a success notification */
|
|
14
|
+
success: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
15
|
+
/** Send an error notification */
|
|
16
|
+
error: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
17
|
+
/** Send a warning notification */
|
|
18
|
+
warning: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
19
|
+
/** Send an info notification */
|
|
20
|
+
info: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
21
|
+
/** Send a loading notification */
|
|
22
|
+
loading: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
23
|
+
/** Dismiss a specific visual feedback item */
|
|
24
|
+
dismiss: (id: string) => void;
|
|
25
|
+
/** Dismiss all visual feedback items */
|
|
26
|
+
dismissAll: () => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Main composable for sending accessible feedback notifications
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```vue
|
|
33
|
+
* <script setup lang="ts">
|
|
34
|
+
* import { useA11yFeedback } from '@theaccessibleteam/a11y-feedback-vue'
|
|
35
|
+
*
|
|
36
|
+
* const feedback = useA11yFeedback()
|
|
37
|
+
*
|
|
38
|
+
* async function handleSave() {
|
|
39
|
+
* feedback.loading('Saving...', { id: 'save' })
|
|
40
|
+
*
|
|
41
|
+
* try {
|
|
42
|
+
* await saveData()
|
|
43
|
+
* feedback.success('Saved!', { id: 'save' })
|
|
44
|
+
* } catch (e) {
|
|
45
|
+
* feedback.error('Failed to save', { id: 'save' })
|
|
46
|
+
* }
|
|
47
|
+
* }
|
|
48
|
+
* </script>
|
|
49
|
+
*
|
|
50
|
+
* <template>
|
|
51
|
+
* <button @click="handleSave">Save</button>
|
|
52
|
+
* </template>
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
declare function useA11yFeedback(): UseA11yFeedbackReturn;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Simple composable for screen reader announcements
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Return type for useA11yAnnounce composable
|
|
63
|
+
*/
|
|
64
|
+
interface UseA11yAnnounceReturn {
|
|
65
|
+
/**
|
|
66
|
+
* Announce a message politely (for non-urgent updates)
|
|
67
|
+
* Screen reader will wait for current speech to finish
|
|
68
|
+
*/
|
|
69
|
+
announcePolite: (message: string, options?: FeedbackOptions) => Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Announce a message assertively (for urgent updates)
|
|
72
|
+
* Screen reader will interrupt current speech
|
|
73
|
+
*/
|
|
74
|
+
announceAssertive: (message: string, options?: FeedbackOptions) => Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Announce with custom options
|
|
77
|
+
*/
|
|
78
|
+
announce: (message: string, politeness: 'polite' | 'assertive', options?: FeedbackOptions) => Promise<void>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Simple composable for making screen reader announcements
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```vue
|
|
85
|
+
* <script setup lang="ts">
|
|
86
|
+
* import { watch } from 'vue'
|
|
87
|
+
* import { useA11yAnnounce } from '@theaccessibleteam/a11y-feedback-vue'
|
|
88
|
+
*
|
|
89
|
+
* const props = defineProps<{ count: number }>()
|
|
90
|
+
* const { announcePolite } = useA11yAnnounce()
|
|
91
|
+
*
|
|
92
|
+
* watch(() => props.count, (newCount) => {
|
|
93
|
+
* announcePolite(`Found ${newCount} results`)
|
|
94
|
+
* })
|
|
95
|
+
* </script>
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
declare function useA11yAnnounce(): UseA11yAnnounceReturn;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Composable for managing a11y-feedback configuration
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Return type for useFeedbackConfig composable
|
|
106
|
+
*/
|
|
107
|
+
interface UseFeedbackConfigReturn {
|
|
108
|
+
/** Current configuration (reactive, readonly) */
|
|
109
|
+
config: DeepReadonly<Ref<FeedbackConfig>>;
|
|
110
|
+
/** Update configuration (merges with existing) */
|
|
111
|
+
updateConfig: (updates: Partial<FeedbackConfig>) => void;
|
|
112
|
+
/** Reset configuration to defaults */
|
|
113
|
+
reset: () => void;
|
|
114
|
+
/** Enable visual feedback */
|
|
115
|
+
enableVisual: () => void;
|
|
116
|
+
/** Disable visual feedback */
|
|
117
|
+
disableVisual: () => void;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Composable for managing a11y-feedback configuration
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```vue
|
|
124
|
+
* <script setup lang="ts">
|
|
125
|
+
* import { useFeedbackConfig } from '@theaccessibleteam/a11y-feedback-vue'
|
|
126
|
+
*
|
|
127
|
+
* const { config, updateConfig, enableVisual, disableVisual } = useFeedbackConfig()
|
|
128
|
+
* </script>
|
|
129
|
+
*
|
|
130
|
+
* <template>
|
|
131
|
+
* <div>
|
|
132
|
+
* <label>
|
|
133
|
+
* <input
|
|
134
|
+
* type="checkbox"
|
|
135
|
+
* :checked="config.visual"
|
|
136
|
+
* @change="$event.target.checked ? enableVisual() : disableVisual()"
|
|
137
|
+
* />
|
|
138
|
+
* Show visual notifications
|
|
139
|
+
* </label>
|
|
140
|
+
*
|
|
141
|
+
* <select
|
|
142
|
+
* :value="config.visualPosition"
|
|
143
|
+
* @change="updateConfig({ visualPosition: $event.target.value })"
|
|
144
|
+
* >
|
|
145
|
+
* <option value="top-right">Top Right</option>
|
|
146
|
+
* <option value="bottom-right">Bottom Right</option>
|
|
147
|
+
* </select>
|
|
148
|
+
* </div>
|
|
149
|
+
* </template>
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
declare function useFeedbackConfig(): UseFeedbackConfigReturn;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Vue plugin for a11y-feedback
|
|
156
|
+
*/
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Plugin options
|
|
160
|
+
*/
|
|
161
|
+
interface A11yFeedbackPluginOptions {
|
|
162
|
+
/** Configuration options */
|
|
163
|
+
config?: Partial<FeedbackConfig>;
|
|
164
|
+
/** Enable debug mode */
|
|
165
|
+
debug?: boolean;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Vue plugin for a11y-feedback
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* // main.ts
|
|
173
|
+
* import { createApp } from 'vue'
|
|
174
|
+
* import { a11yFeedbackPlugin } from '@theaccessibleteam/a11y-feedback-vue'
|
|
175
|
+
* import App from './App.vue'
|
|
176
|
+
*
|
|
177
|
+
* const app = createApp(App)
|
|
178
|
+
*
|
|
179
|
+
* app.use(a11yFeedbackPlugin, {
|
|
180
|
+
* config: {
|
|
181
|
+
* visual: true,
|
|
182
|
+
* visualPosition: 'top-right',
|
|
183
|
+
* },
|
|
184
|
+
* debug: import.meta.env.DEV,
|
|
185
|
+
* })
|
|
186
|
+
*
|
|
187
|
+
* app.mount('#app')
|
|
188
|
+
* ```
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```vue
|
|
192
|
+
* <script setup lang="ts">
|
|
193
|
+
* import { inject } from 'vue'
|
|
194
|
+
* import { A11yFeedbackKey } from '@theaccessibleteam/a11y-feedback-vue'
|
|
195
|
+
*
|
|
196
|
+
* const feedback = inject(A11yFeedbackKey)!
|
|
197
|
+
*
|
|
198
|
+
* function handleClick() {
|
|
199
|
+
* feedback.success('Action completed!')
|
|
200
|
+
* }
|
|
201
|
+
* </script>
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
declare const a11yFeedbackPlugin: {
|
|
205
|
+
install(app: App, options?: A11yFeedbackPluginOptions): void;
|
|
206
|
+
};
|
|
207
|
+
declare module 'vue' {
|
|
208
|
+
interface ComponentCustomProperties {
|
|
209
|
+
$a11yFeedback: UseA11yFeedbackReturn;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export { a11yFeedbackPlugin, useA11yAnnounce, useA11yFeedback, useFeedbackConfig };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { FeedbackOptions, FeedbackEvent, FeedbackConfig } from '@theaccessibleteam/a11y-feedback';
|
|
2
|
+
export { FeedbackConfig, FeedbackEvent, FeedbackOptions, FeedbackType } from '@theaccessibleteam/a11y-feedback';
|
|
3
|
+
import { DeepReadonly, Ref, App } from 'vue';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Main Vue composable for a11y-feedback
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Return type for useA11yFeedback composable
|
|
11
|
+
*/
|
|
12
|
+
interface UseA11yFeedbackReturn {
|
|
13
|
+
/** Send a success notification */
|
|
14
|
+
success: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
15
|
+
/** Send an error notification */
|
|
16
|
+
error: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
17
|
+
/** Send a warning notification */
|
|
18
|
+
warning: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
19
|
+
/** Send an info notification */
|
|
20
|
+
info: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
21
|
+
/** Send a loading notification */
|
|
22
|
+
loading: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
23
|
+
/** Dismiss a specific visual feedback item */
|
|
24
|
+
dismiss: (id: string) => void;
|
|
25
|
+
/** Dismiss all visual feedback items */
|
|
26
|
+
dismissAll: () => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Main composable for sending accessible feedback notifications
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```vue
|
|
33
|
+
* <script setup lang="ts">
|
|
34
|
+
* import { useA11yFeedback } from '@theaccessibleteam/a11y-feedback-vue'
|
|
35
|
+
*
|
|
36
|
+
* const feedback = useA11yFeedback()
|
|
37
|
+
*
|
|
38
|
+
* async function handleSave() {
|
|
39
|
+
* feedback.loading('Saving...', { id: 'save' })
|
|
40
|
+
*
|
|
41
|
+
* try {
|
|
42
|
+
* await saveData()
|
|
43
|
+
* feedback.success('Saved!', { id: 'save' })
|
|
44
|
+
* } catch (e) {
|
|
45
|
+
* feedback.error('Failed to save', { id: 'save' })
|
|
46
|
+
* }
|
|
47
|
+
* }
|
|
48
|
+
* </script>
|
|
49
|
+
*
|
|
50
|
+
* <template>
|
|
51
|
+
* <button @click="handleSave">Save</button>
|
|
52
|
+
* </template>
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
declare function useA11yFeedback(): UseA11yFeedbackReturn;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Simple composable for screen reader announcements
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Return type for useA11yAnnounce composable
|
|
63
|
+
*/
|
|
64
|
+
interface UseA11yAnnounceReturn {
|
|
65
|
+
/**
|
|
66
|
+
* Announce a message politely (for non-urgent updates)
|
|
67
|
+
* Screen reader will wait for current speech to finish
|
|
68
|
+
*/
|
|
69
|
+
announcePolite: (message: string, options?: FeedbackOptions) => Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Announce a message assertively (for urgent updates)
|
|
72
|
+
* Screen reader will interrupt current speech
|
|
73
|
+
*/
|
|
74
|
+
announceAssertive: (message: string, options?: FeedbackOptions) => Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Announce with custom options
|
|
77
|
+
*/
|
|
78
|
+
announce: (message: string, politeness: 'polite' | 'assertive', options?: FeedbackOptions) => Promise<void>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Simple composable for making screen reader announcements
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```vue
|
|
85
|
+
* <script setup lang="ts">
|
|
86
|
+
* import { watch } from 'vue'
|
|
87
|
+
* import { useA11yAnnounce } from '@theaccessibleteam/a11y-feedback-vue'
|
|
88
|
+
*
|
|
89
|
+
* const props = defineProps<{ count: number }>()
|
|
90
|
+
* const { announcePolite } = useA11yAnnounce()
|
|
91
|
+
*
|
|
92
|
+
* watch(() => props.count, (newCount) => {
|
|
93
|
+
* announcePolite(`Found ${newCount} results`)
|
|
94
|
+
* })
|
|
95
|
+
* </script>
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
declare function useA11yAnnounce(): UseA11yAnnounceReturn;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Composable for managing a11y-feedback configuration
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Return type for useFeedbackConfig composable
|
|
106
|
+
*/
|
|
107
|
+
interface UseFeedbackConfigReturn {
|
|
108
|
+
/** Current configuration (reactive, readonly) */
|
|
109
|
+
config: DeepReadonly<Ref<FeedbackConfig>>;
|
|
110
|
+
/** Update configuration (merges with existing) */
|
|
111
|
+
updateConfig: (updates: Partial<FeedbackConfig>) => void;
|
|
112
|
+
/** Reset configuration to defaults */
|
|
113
|
+
reset: () => void;
|
|
114
|
+
/** Enable visual feedback */
|
|
115
|
+
enableVisual: () => void;
|
|
116
|
+
/** Disable visual feedback */
|
|
117
|
+
disableVisual: () => void;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Composable for managing a11y-feedback configuration
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```vue
|
|
124
|
+
* <script setup lang="ts">
|
|
125
|
+
* import { useFeedbackConfig } from '@theaccessibleteam/a11y-feedback-vue'
|
|
126
|
+
*
|
|
127
|
+
* const { config, updateConfig, enableVisual, disableVisual } = useFeedbackConfig()
|
|
128
|
+
* </script>
|
|
129
|
+
*
|
|
130
|
+
* <template>
|
|
131
|
+
* <div>
|
|
132
|
+
* <label>
|
|
133
|
+
* <input
|
|
134
|
+
* type="checkbox"
|
|
135
|
+
* :checked="config.visual"
|
|
136
|
+
* @change="$event.target.checked ? enableVisual() : disableVisual()"
|
|
137
|
+
* />
|
|
138
|
+
* Show visual notifications
|
|
139
|
+
* </label>
|
|
140
|
+
*
|
|
141
|
+
* <select
|
|
142
|
+
* :value="config.visualPosition"
|
|
143
|
+
* @change="updateConfig({ visualPosition: $event.target.value })"
|
|
144
|
+
* >
|
|
145
|
+
* <option value="top-right">Top Right</option>
|
|
146
|
+
* <option value="bottom-right">Bottom Right</option>
|
|
147
|
+
* </select>
|
|
148
|
+
* </div>
|
|
149
|
+
* </template>
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
declare function useFeedbackConfig(): UseFeedbackConfigReturn;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Vue plugin for a11y-feedback
|
|
156
|
+
*/
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Plugin options
|
|
160
|
+
*/
|
|
161
|
+
interface A11yFeedbackPluginOptions {
|
|
162
|
+
/** Configuration options */
|
|
163
|
+
config?: Partial<FeedbackConfig>;
|
|
164
|
+
/** Enable debug mode */
|
|
165
|
+
debug?: boolean;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Vue plugin for a11y-feedback
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* // main.ts
|
|
173
|
+
* import { createApp } from 'vue'
|
|
174
|
+
* import { a11yFeedbackPlugin } from '@theaccessibleteam/a11y-feedback-vue'
|
|
175
|
+
* import App from './App.vue'
|
|
176
|
+
*
|
|
177
|
+
* const app = createApp(App)
|
|
178
|
+
*
|
|
179
|
+
* app.use(a11yFeedbackPlugin, {
|
|
180
|
+
* config: {
|
|
181
|
+
* visual: true,
|
|
182
|
+
* visualPosition: 'top-right',
|
|
183
|
+
* },
|
|
184
|
+
* debug: import.meta.env.DEV,
|
|
185
|
+
* })
|
|
186
|
+
*
|
|
187
|
+
* app.mount('#app')
|
|
188
|
+
* ```
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```vue
|
|
192
|
+
* <script setup lang="ts">
|
|
193
|
+
* import { inject } from 'vue'
|
|
194
|
+
* import { A11yFeedbackKey } from '@theaccessibleteam/a11y-feedback-vue'
|
|
195
|
+
*
|
|
196
|
+
* const feedback = inject(A11yFeedbackKey)!
|
|
197
|
+
*
|
|
198
|
+
* function handleClick() {
|
|
199
|
+
* feedback.success('Action completed!')
|
|
200
|
+
* }
|
|
201
|
+
* </script>
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
declare const a11yFeedbackPlugin: {
|
|
205
|
+
install(app: App, options?: A11yFeedbackPluginOptions): void;
|
|
206
|
+
};
|
|
207
|
+
declare module 'vue' {
|
|
208
|
+
interface ComponentCustomProperties {
|
|
209
|
+
$a11yFeedback: UseA11yFeedbackReturn;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export { a11yFeedbackPlugin, useA11yAnnounce, useA11yFeedback, useFeedbackConfig };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// src/useA11yFeedback.ts
|
|
2
|
+
import {
|
|
3
|
+
notify,
|
|
4
|
+
dismissVisualFeedback,
|
|
5
|
+
dismissAllVisualFeedback
|
|
6
|
+
} from "@theaccessibleteam/a11y-feedback";
|
|
7
|
+
function useA11yFeedback() {
|
|
8
|
+
const success = (message, options) => notify.success(message, options);
|
|
9
|
+
const error = (message, options) => notify.error(message, options);
|
|
10
|
+
const warning = (message, options) => notify.warning(message, options);
|
|
11
|
+
const info = (message, options) => notify.info(message, options);
|
|
12
|
+
const loading = (message, options) => notify.loading(message, options);
|
|
13
|
+
const dismiss = (id) => {
|
|
14
|
+
dismissVisualFeedback(id);
|
|
15
|
+
};
|
|
16
|
+
const dismissAll = () => {
|
|
17
|
+
dismissAllVisualFeedback();
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
success,
|
|
21
|
+
error,
|
|
22
|
+
warning,
|
|
23
|
+
info,
|
|
24
|
+
loading,
|
|
25
|
+
dismiss,
|
|
26
|
+
dismissAll
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/useA11yAnnounce.ts
|
|
31
|
+
import { notify as notify2 } from "@theaccessibleteam/a11y-feedback";
|
|
32
|
+
function useA11yAnnounce() {
|
|
33
|
+
const announcePolite = async (message, options) => {
|
|
34
|
+
await notify2.info(message, options);
|
|
35
|
+
};
|
|
36
|
+
const announceAssertive = async (message, options) => {
|
|
37
|
+
await notify2.warning(message, options);
|
|
38
|
+
};
|
|
39
|
+
const announce = async (message, politeness, options) => {
|
|
40
|
+
if (politeness === "assertive") {
|
|
41
|
+
await notify2.warning(message, options);
|
|
42
|
+
} else {
|
|
43
|
+
await notify2.info(message, options);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
announcePolite,
|
|
48
|
+
announceAssertive,
|
|
49
|
+
announce
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/useFeedbackConfig.ts
|
|
54
|
+
import { ref, readonly, onMounted } from "vue";
|
|
55
|
+
import {
|
|
56
|
+
configureFeedback,
|
|
57
|
+
getConfig,
|
|
58
|
+
resetConfig
|
|
59
|
+
} from "@theaccessibleteam/a11y-feedback";
|
|
60
|
+
function useFeedbackConfig() {
|
|
61
|
+
const config = ref(getConfig());
|
|
62
|
+
const syncConfig = () => {
|
|
63
|
+
config.value = getConfig();
|
|
64
|
+
};
|
|
65
|
+
const updateConfig = (updates) => {
|
|
66
|
+
configureFeedback(updates);
|
|
67
|
+
syncConfig();
|
|
68
|
+
};
|
|
69
|
+
const reset = () => {
|
|
70
|
+
resetConfig();
|
|
71
|
+
syncConfig();
|
|
72
|
+
};
|
|
73
|
+
const enableVisual = () => {
|
|
74
|
+
updateConfig({ visual: true });
|
|
75
|
+
};
|
|
76
|
+
const disableVisual = () => {
|
|
77
|
+
updateConfig({ visual: false });
|
|
78
|
+
};
|
|
79
|
+
onMounted(() => {
|
|
80
|
+
syncConfig();
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
config: readonly(config),
|
|
84
|
+
updateConfig,
|
|
85
|
+
reset,
|
|
86
|
+
enableVisual,
|
|
87
|
+
disableVisual
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/plugin.ts
|
|
92
|
+
import {
|
|
93
|
+
configureFeedback as configureFeedback2,
|
|
94
|
+
resetConfig as resetConfig2,
|
|
95
|
+
enableFeedbackDebug,
|
|
96
|
+
disableFeedbackDebug,
|
|
97
|
+
dismissAllVisualFeedback as dismissAllVisualFeedback2
|
|
98
|
+
} from "@theaccessibleteam/a11y-feedback";
|
|
99
|
+
var A11yFeedbackKey = /* @__PURE__ */ Symbol("a11y-feedback");
|
|
100
|
+
var a11yFeedbackPlugin = {
|
|
101
|
+
install(app, options = {}) {
|
|
102
|
+
const { config, debug = false } = options;
|
|
103
|
+
if (config) {
|
|
104
|
+
configureFeedback2(config);
|
|
105
|
+
}
|
|
106
|
+
if (debug) {
|
|
107
|
+
enableFeedbackDebug();
|
|
108
|
+
}
|
|
109
|
+
const feedback = useA11yFeedback();
|
|
110
|
+
app.provide(A11yFeedbackKey, feedback);
|
|
111
|
+
app.config.globalProperties.$a11yFeedback = feedback;
|
|
112
|
+
app.unmount = /* @__PURE__ */ ((originalUnmount) => {
|
|
113
|
+
return function() {
|
|
114
|
+
resetConfig2();
|
|
115
|
+
disableFeedbackDebug();
|
|
116
|
+
dismissAllVisualFeedback2();
|
|
117
|
+
return originalUnmount.call(this);
|
|
118
|
+
};
|
|
119
|
+
})(app.unmount);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
export {
|
|
123
|
+
a11yFeedbackPlugin,
|
|
124
|
+
useA11yAnnounce,
|
|
125
|
+
useA11yFeedback,
|
|
126
|
+
useFeedbackConfig
|
|
127
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@theaccessibleteam/a11y-feedback-vue",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Vue composables for a11y-feedback - accessible notifications and screen reader announcements",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
28
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"lint": "eslint src --ext .ts"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"vue",
|
|
34
|
+
"vue3",
|
|
35
|
+
"accessibility",
|
|
36
|
+
"a11y",
|
|
37
|
+
"aria-live",
|
|
38
|
+
"screen-reader",
|
|
39
|
+
"composables",
|
|
40
|
+
"notifications",
|
|
41
|
+
"toast"
|
|
42
|
+
],
|
|
43
|
+
"author": "The Accessible Team <theaccessibleteam@gmail.com>",
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/WOLFIEEEE/a11y-feedback.git",
|
|
48
|
+
"directory": "packages/vue"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/WOLFIEEEE/a11y-feedback/issues"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/WOLFIEEEE/a11y-feedback/tree/main/packages/vue#readme",
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"@theaccessibleteam/a11y-feedback": "workspace:^",
|
|
56
|
+
"vue": "^3.3.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"tsup": "^8.0.0",
|
|
60
|
+
"typescript": "^5.4.0",
|
|
61
|
+
"vue": "^3.4.0"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|