@theaccessibleteam/a11y-feedback-react 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 +147 -0
- package/dist/index.cjs +215 -0
- package/dist/index.d.cts +241 -0
- package/dist/index.d.ts +241 -0
- package/dist/index.js +206 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# @theaccessibleteam/a11y-feedback-react
|
|
2
|
+
|
|
3
|
+
React bindings 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-react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Option 1: Using the Hook (Simple)
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { useA11yFeedback } from '@theaccessibleteam/a11y-feedback-react'
|
|
17
|
+
import { configureFeedback } from '@theaccessibleteam/a11y-feedback'
|
|
18
|
+
|
|
19
|
+
// Configure once at app startup
|
|
20
|
+
configureFeedback({ visual: true })
|
|
21
|
+
|
|
22
|
+
function SaveButton() {
|
|
23
|
+
const feedback = useA11yFeedback()
|
|
24
|
+
|
|
25
|
+
const handleSave = async () => {
|
|
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', focus: '#save-btn' })
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return <button id="save-btn" onClick={handleSave}>Save</button>
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Option 2: Using the Provider (Recommended for Apps)
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { A11yFeedbackProvider, useA11yFeedbackContext } from '@theaccessibleteam/a11y-feedback-react'
|
|
44
|
+
|
|
45
|
+
function App() {
|
|
46
|
+
return (
|
|
47
|
+
<A11yFeedbackProvider config={{ visual: true }} debug>
|
|
48
|
+
<MyApp />
|
|
49
|
+
</A11yFeedbackProvider>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function MyComponent() {
|
|
54
|
+
const { success, error } = useA11yFeedbackContext()
|
|
55
|
+
|
|
56
|
+
const handleAction = async () => {
|
|
57
|
+
try {
|
|
58
|
+
await performAction()
|
|
59
|
+
success('Action completed!')
|
|
60
|
+
} catch (e) {
|
|
61
|
+
error('Action failed')
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return <button onClick={handleAction}>Do Something</button>
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Hooks
|
|
70
|
+
|
|
71
|
+
### `useA11yFeedback()`
|
|
72
|
+
|
|
73
|
+
Main hook providing all feedback methods. Can be used without a provider.
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
const { success, error, warning, info, loading, dismiss, dismissAll } = useA11yFeedback()
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### `useA11yAnnounce()`
|
|
80
|
+
|
|
81
|
+
Lightweight hook for screen reader announcements only.
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
const { announcePolite, announceAssertive } = useA11yAnnounce()
|
|
85
|
+
|
|
86
|
+
// Polite announcements wait for current speech to finish
|
|
87
|
+
announcePolite('Results updated')
|
|
88
|
+
|
|
89
|
+
// Assertive announcements interrupt immediately
|
|
90
|
+
announceAssertive('Error: Please fix the form')
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### `useFeedbackConfig()`
|
|
94
|
+
|
|
95
|
+
Hook for managing configuration reactively.
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
const { config, updateConfig, enableVisual, disableVisual } = useFeedbackConfig()
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### `useA11yFeedbackContext()`
|
|
102
|
+
|
|
103
|
+
Access the provider context. Must be used inside `A11yFeedbackProvider`.
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
const ctx = useA11yFeedbackContext()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## API
|
|
110
|
+
|
|
111
|
+
### `A11yFeedbackProvider`
|
|
112
|
+
|
|
113
|
+
| Prop | Type | Description |
|
|
114
|
+
|------|------|-------------|
|
|
115
|
+
| `config` | `Partial<FeedbackConfig>` | Configuration options |
|
|
116
|
+
| `debug` | `boolean` | Enable debug mode |
|
|
117
|
+
| `children` | `ReactNode` | Child components |
|
|
118
|
+
|
|
119
|
+
### `useA11yFeedback()` Return
|
|
120
|
+
|
|
121
|
+
| Method | Description |
|
|
122
|
+
|--------|-------------|
|
|
123
|
+
| `success(message, options?)` | Send success notification |
|
|
124
|
+
| `error(message, options?)` | Send error notification |
|
|
125
|
+
| `warning(message, options?)` | Send warning notification |
|
|
126
|
+
| `info(message, options?)` | Send info notification |
|
|
127
|
+
| `loading(message, options?)` | Send loading notification |
|
|
128
|
+
| `dismiss(id)` | Dismiss specific notification |
|
|
129
|
+
| `dismissAll()` | Dismiss all notifications |
|
|
130
|
+
|
|
131
|
+
## TypeScript
|
|
132
|
+
|
|
133
|
+
Full TypeScript support with exported types:
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import type {
|
|
137
|
+
FeedbackType,
|
|
138
|
+
FeedbackOptions,
|
|
139
|
+
FeedbackEvent,
|
|
140
|
+
FeedbackConfig
|
|
141
|
+
} from '@theaccessibleteam/a11y-feedback-react'
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT
|
|
147
|
+
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
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
|
+
A11yFeedbackProvider: () => A11yFeedbackProvider,
|
|
24
|
+
useA11yAnnounce: () => useA11yAnnounce,
|
|
25
|
+
useA11yFeedback: () => useA11yFeedback,
|
|
26
|
+
useA11yFeedbackContext: () => useA11yFeedbackContext,
|
|
27
|
+
useFeedbackConfig: () => useFeedbackConfig
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/provider.tsx
|
|
32
|
+
var import_react = require("react");
|
|
33
|
+
var import_a11y_feedback = require("@theaccessibleteam/a11y-feedback");
|
|
34
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
+
var A11yFeedbackContext = (0, import_react.createContext)(null);
|
|
36
|
+
function A11yFeedbackProvider({
|
|
37
|
+
children,
|
|
38
|
+
config,
|
|
39
|
+
debug = false
|
|
40
|
+
}) {
|
|
41
|
+
(0, import_react.useEffect)(() => {
|
|
42
|
+
if (config) {
|
|
43
|
+
(0, import_a11y_feedback.configureFeedback)(config);
|
|
44
|
+
}
|
|
45
|
+
if (debug) {
|
|
46
|
+
(0, import_a11y_feedback.enableFeedbackDebug)();
|
|
47
|
+
}
|
|
48
|
+
return () => {
|
|
49
|
+
(0, import_a11y_feedback.resetConfig)();
|
|
50
|
+
(0, import_a11y_feedback.disableFeedbackDebug)();
|
|
51
|
+
(0, import_a11y_feedback.dismissAllVisualFeedback)();
|
|
52
|
+
};
|
|
53
|
+
}, []);
|
|
54
|
+
(0, import_react.useEffect)(() => {
|
|
55
|
+
if (config) {
|
|
56
|
+
(0, import_a11y_feedback.configureFeedback)(config);
|
|
57
|
+
}
|
|
58
|
+
}, [config]);
|
|
59
|
+
(0, import_react.useEffect)(() => {
|
|
60
|
+
if (debug) {
|
|
61
|
+
(0, import_a11y_feedback.enableFeedbackDebug)();
|
|
62
|
+
} else {
|
|
63
|
+
(0, import_a11y_feedback.disableFeedbackDebug)();
|
|
64
|
+
}
|
|
65
|
+
}, [debug]);
|
|
66
|
+
const contextValue = (0, import_react.useMemo)(
|
|
67
|
+
() => ({
|
|
68
|
+
success: (message, options) => import_a11y_feedback.notify.success(message, options),
|
|
69
|
+
error: (message, options) => import_a11y_feedback.notify.error(message, options),
|
|
70
|
+
warning: (message, options) => import_a11y_feedback.notify.warning(message, options),
|
|
71
|
+
info: (message, options) => import_a11y_feedback.notify.info(message, options),
|
|
72
|
+
loading: (message, options) => import_a11y_feedback.notify.loading(message, options),
|
|
73
|
+
notify: import_a11y_feedback.notify,
|
|
74
|
+
dismissAll: import_a11y_feedback.dismissAllVisualFeedback,
|
|
75
|
+
getLog: () => [...(0, import_a11y_feedback.getFeedbackLog)()],
|
|
76
|
+
clearLog: import_a11y_feedback.clearFeedbackLog
|
|
77
|
+
}),
|
|
78
|
+
[]
|
|
79
|
+
);
|
|
80
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A11yFeedbackContext.Provider, { value: contextValue, children });
|
|
81
|
+
}
|
|
82
|
+
function useA11yFeedbackContext() {
|
|
83
|
+
const context = (0, import_react.useContext)(A11yFeedbackContext);
|
|
84
|
+
if (context === null) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
"useA11yFeedbackContext must be used within an A11yFeedbackProvider"
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return context;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/useA11yFeedback.ts
|
|
93
|
+
var import_react2 = require("react");
|
|
94
|
+
var import_a11y_feedback2 = require("@theaccessibleteam/a11y-feedback");
|
|
95
|
+
function useA11yFeedback() {
|
|
96
|
+
const success = (0, import_react2.useCallback)(
|
|
97
|
+
(message, options) => import_a11y_feedback2.notify.success(message, options),
|
|
98
|
+
[]
|
|
99
|
+
);
|
|
100
|
+
const error = (0, import_react2.useCallback)(
|
|
101
|
+
(message, options) => import_a11y_feedback2.notify.error(message, options),
|
|
102
|
+
[]
|
|
103
|
+
);
|
|
104
|
+
const warning = (0, import_react2.useCallback)(
|
|
105
|
+
(message, options) => import_a11y_feedback2.notify.warning(message, options),
|
|
106
|
+
[]
|
|
107
|
+
);
|
|
108
|
+
const info = (0, import_react2.useCallback)(
|
|
109
|
+
(message, options) => import_a11y_feedback2.notify.info(message, options),
|
|
110
|
+
[]
|
|
111
|
+
);
|
|
112
|
+
const loading = (0, import_react2.useCallback)(
|
|
113
|
+
(message, options) => import_a11y_feedback2.notify.loading(message, options),
|
|
114
|
+
[]
|
|
115
|
+
);
|
|
116
|
+
const dismiss = (0, import_react2.useCallback)((id) => {
|
|
117
|
+
(0, import_a11y_feedback2.dismissVisualFeedback)(id);
|
|
118
|
+
}, []);
|
|
119
|
+
const dismissAll = (0, import_react2.useCallback)(() => {
|
|
120
|
+
(0, import_a11y_feedback2.dismissAllVisualFeedback)();
|
|
121
|
+
}, []);
|
|
122
|
+
return (0, import_react2.useMemo)(
|
|
123
|
+
() => ({
|
|
124
|
+
success,
|
|
125
|
+
error,
|
|
126
|
+
warning,
|
|
127
|
+
info,
|
|
128
|
+
loading,
|
|
129
|
+
dismiss,
|
|
130
|
+
dismissAll
|
|
131
|
+
}),
|
|
132
|
+
[success, error, warning, info, loading, dismiss, dismissAll]
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/useA11yAnnounce.ts
|
|
137
|
+
var import_react3 = require("react");
|
|
138
|
+
var import_a11y_feedback3 = require("@theaccessibleteam/a11y-feedback");
|
|
139
|
+
function useA11yAnnounce() {
|
|
140
|
+
const announcePolite = (0, import_react3.useCallback)(
|
|
141
|
+
async (message, options) => {
|
|
142
|
+
await import_a11y_feedback3.notify.info(message, options);
|
|
143
|
+
},
|
|
144
|
+
[]
|
|
145
|
+
);
|
|
146
|
+
const announceAssertive = (0, import_react3.useCallback)(
|
|
147
|
+
async (message, options) => {
|
|
148
|
+
await import_a11y_feedback3.notify.warning(message, options);
|
|
149
|
+
},
|
|
150
|
+
[]
|
|
151
|
+
);
|
|
152
|
+
const announce = (0, import_react3.useCallback)(
|
|
153
|
+
async (message, politeness, options) => {
|
|
154
|
+
if (politeness === "assertive") {
|
|
155
|
+
await import_a11y_feedback3.notify.warning(message, options);
|
|
156
|
+
} else {
|
|
157
|
+
await import_a11y_feedback3.notify.info(message, options);
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
[]
|
|
161
|
+
);
|
|
162
|
+
return (0, import_react3.useMemo)(
|
|
163
|
+
() => ({
|
|
164
|
+
announcePolite,
|
|
165
|
+
announceAssertive,
|
|
166
|
+
announce
|
|
167
|
+
}),
|
|
168
|
+
[announcePolite, announceAssertive, announce]
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/useFeedbackConfig.ts
|
|
173
|
+
var import_react4 = require("react");
|
|
174
|
+
var import_a11y_feedback4 = require("@theaccessibleteam/a11y-feedback");
|
|
175
|
+
function useFeedbackConfig() {
|
|
176
|
+
const [config, setConfig] = (0, import_react4.useState)(() => (0, import_a11y_feedback4.getConfig)());
|
|
177
|
+
const syncConfig = (0, import_react4.useCallback)(() => {
|
|
178
|
+
setConfig((0, import_a11y_feedback4.getConfig)());
|
|
179
|
+
}, []);
|
|
180
|
+
const updateConfig = (0, import_react4.useCallback)(
|
|
181
|
+
(updates) => {
|
|
182
|
+
(0, import_a11y_feedback4.configureFeedback)(updates);
|
|
183
|
+
syncConfig();
|
|
184
|
+
},
|
|
185
|
+
[syncConfig]
|
|
186
|
+
);
|
|
187
|
+
const reset = (0, import_react4.useCallback)(() => {
|
|
188
|
+
(0, import_a11y_feedback4.resetConfig)();
|
|
189
|
+
syncConfig();
|
|
190
|
+
}, [syncConfig]);
|
|
191
|
+
const enableVisual = (0, import_react4.useCallback)(() => {
|
|
192
|
+
updateConfig({ visual: true });
|
|
193
|
+
}, [updateConfig]);
|
|
194
|
+
const disableVisual = (0, import_react4.useCallback)(() => {
|
|
195
|
+
updateConfig({ visual: false });
|
|
196
|
+
}, [updateConfig]);
|
|
197
|
+
(0, import_react4.useEffect)(() => {
|
|
198
|
+
syncConfig();
|
|
199
|
+
}, [syncConfig]);
|
|
200
|
+
return {
|
|
201
|
+
config,
|
|
202
|
+
updateConfig,
|
|
203
|
+
resetConfig: reset,
|
|
204
|
+
enableVisual,
|
|
205
|
+
disableVisual
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
209
|
+
0 && (module.exports = {
|
|
210
|
+
A11yFeedbackProvider,
|
|
211
|
+
useA11yAnnounce,
|
|
212
|
+
useA11yFeedback,
|
|
213
|
+
useA11yFeedbackContext,
|
|
214
|
+
useFeedbackConfig
|
|
215
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { FeedbackConfig, FeedbackOptions, FeedbackEvent, notify, FeedbackLogEntry } from '@theaccessibleteam/a11y-feedback';
|
|
3
|
+
export { FeedbackConfig, FeedbackEvent, FeedbackOptions, FeedbackType } from '@theaccessibleteam/a11y-feedback';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* React Context Provider for a11y-feedback
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Context value interface
|
|
11
|
+
*/
|
|
12
|
+
interface A11yFeedbackContextValue {
|
|
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
|
+
/** Generic notify function */
|
|
24
|
+
notify: typeof notify;
|
|
25
|
+
/** Dismiss all visual feedback */
|
|
26
|
+
dismissAll: () => void;
|
|
27
|
+
/** Get the feedback log (when debug is enabled) */
|
|
28
|
+
getLog: () => FeedbackLogEntry[];
|
|
29
|
+
/** Clear the feedback log */
|
|
30
|
+
clearLog: () => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Provider props
|
|
34
|
+
*/
|
|
35
|
+
interface A11yFeedbackProviderProps {
|
|
36
|
+
/** React children */
|
|
37
|
+
children: ReactNode;
|
|
38
|
+
/** Configuration options */
|
|
39
|
+
config?: Partial<FeedbackConfig>;
|
|
40
|
+
/** Enable debug mode */
|
|
41
|
+
debug?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Provider component for a11y-feedback
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* import { A11yFeedbackProvider } from '@theaccessibleteam/a11y-feedback-react'
|
|
49
|
+
*
|
|
50
|
+
* function App() {
|
|
51
|
+
* return (
|
|
52
|
+
* <A11yFeedbackProvider config={{ visual: true }}>
|
|
53
|
+
* <MyApp />
|
|
54
|
+
* </A11yFeedbackProvider>
|
|
55
|
+
* )
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
declare function A11yFeedbackProvider({ children, config, debug, }: A11yFeedbackProviderProps): JSX.Element;
|
|
60
|
+
/**
|
|
61
|
+
* Hook to access the a11y-feedback context
|
|
62
|
+
*
|
|
63
|
+
* @throws Error if used outside of A11yFeedbackProvider
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```tsx
|
|
67
|
+
* function MyComponent() {
|
|
68
|
+
* const { success, error } = useA11yFeedbackContext()
|
|
69
|
+
*
|
|
70
|
+
* const handleSave = async () => {
|
|
71
|
+
* try {
|
|
72
|
+
* await saveData()
|
|
73
|
+
* success('Data saved successfully')
|
|
74
|
+
* } catch (e) {
|
|
75
|
+
* error('Failed to save data')
|
|
76
|
+
* }
|
|
77
|
+
* }
|
|
78
|
+
*
|
|
79
|
+
* return <button onClick={handleSave}>Save</button>
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare function useA11yFeedbackContext(): A11yFeedbackContextValue;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Return type for useA11yFeedback hook
|
|
87
|
+
*/
|
|
88
|
+
interface UseA11yFeedbackReturn {
|
|
89
|
+
/** Send a success notification */
|
|
90
|
+
success: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
91
|
+
/** Send an error notification */
|
|
92
|
+
error: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
93
|
+
/** Send a warning notification */
|
|
94
|
+
warning: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
95
|
+
/** Send an info notification */
|
|
96
|
+
info: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
97
|
+
/** Send a loading notification */
|
|
98
|
+
loading: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
99
|
+
/** Dismiss a specific visual feedback item */
|
|
100
|
+
dismiss: (id: string) => void;
|
|
101
|
+
/** Dismiss all visual feedback items */
|
|
102
|
+
dismissAll: () => void;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Main hook for sending accessible feedback notifications
|
|
106
|
+
*
|
|
107
|
+
* Can be used without a provider for simple use cases.
|
|
108
|
+
* For app-wide configuration, use with A11yFeedbackProvider.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```tsx
|
|
112
|
+
* function SaveButton() {
|
|
113
|
+
* const feedback = useA11yFeedback()
|
|
114
|
+
*
|
|
115
|
+
* const handleSave = async () => {
|
|
116
|
+
* feedback.loading('Saving...', { id: 'save' })
|
|
117
|
+
*
|
|
118
|
+
* try {
|
|
119
|
+
* await saveData()
|
|
120
|
+
* feedback.success('Saved successfully!', { id: 'save' })
|
|
121
|
+
* } catch (e) {
|
|
122
|
+
* feedback.error('Failed to save', { id: 'save', focus: '#save-btn' })
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
*
|
|
126
|
+
* return <button id="save-btn" onClick={handleSave}>Save</button>
|
|
127
|
+
* }
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
declare function useA11yFeedback(): UseA11yFeedbackReturn;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Return type for useA11yAnnounce hook
|
|
134
|
+
*/
|
|
135
|
+
interface UseA11yAnnounceReturn {
|
|
136
|
+
/**
|
|
137
|
+
* Announce a message politely (for non-urgent updates)
|
|
138
|
+
* Screen reader will wait for current speech to finish
|
|
139
|
+
*/
|
|
140
|
+
announcePolite: (message: string, options?: FeedbackOptions) => Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Announce a message assertively (for urgent updates)
|
|
143
|
+
* Screen reader will interrupt current speech
|
|
144
|
+
*/
|
|
145
|
+
announceAssertive: (message: string, options?: FeedbackOptions) => Promise<void>;
|
|
146
|
+
/**
|
|
147
|
+
* Announce with custom options
|
|
148
|
+
*/
|
|
149
|
+
announce: (message: string, politeness: 'polite' | 'assertive', options?: FeedbackOptions) => Promise<void>;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Simple hook for making screen reader announcements
|
|
153
|
+
*
|
|
154
|
+
* This is a lightweight alternative to useA11yFeedback when you only
|
|
155
|
+
* need to announce messages without visual feedback or complex options.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```tsx
|
|
159
|
+
* function SearchResults({ count }: { count: number }) {
|
|
160
|
+
* const { announcePolite } = useA11yAnnounce()
|
|
161
|
+
*
|
|
162
|
+
* useEffect(() => {
|
|
163
|
+
* announcePolite(`Found ${count} results`)
|
|
164
|
+
* }, [count, announcePolite])
|
|
165
|
+
*
|
|
166
|
+
* return <div>{count} results found</div>
|
|
167
|
+
* }
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```tsx
|
|
172
|
+
* function Timer({ secondsLeft }: { secondsLeft: number }) {
|
|
173
|
+
* const { announceAssertive } = useA11yAnnounce()
|
|
174
|
+
*
|
|
175
|
+
* useEffect(() => {
|
|
176
|
+
* if (secondsLeft <= 10) {
|
|
177
|
+
* announceAssertive(`${secondsLeft} seconds remaining`)
|
|
178
|
+
* }
|
|
179
|
+
* }, [secondsLeft, announceAssertive])
|
|
180
|
+
*
|
|
181
|
+
* return <div>{secondsLeft}s</div>
|
|
182
|
+
* }
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
declare function useA11yAnnounce(): UseA11yAnnounceReturn;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Return type for useFeedbackConfig hook
|
|
189
|
+
*/
|
|
190
|
+
interface UseFeedbackConfigReturn {
|
|
191
|
+
/** Current configuration */
|
|
192
|
+
config: FeedbackConfig;
|
|
193
|
+
/** Update configuration (merges with existing) */
|
|
194
|
+
updateConfig: (updates: Partial<FeedbackConfig>) => void;
|
|
195
|
+
/** Reset configuration to defaults */
|
|
196
|
+
resetConfig: () => void;
|
|
197
|
+
/** Enable visual feedback */
|
|
198
|
+
enableVisual: () => void;
|
|
199
|
+
/** Disable visual feedback */
|
|
200
|
+
disableVisual: () => void;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Hook for managing a11y-feedback configuration
|
|
204
|
+
*
|
|
205
|
+
* Provides reactive access to the configuration and methods to update it.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```tsx
|
|
209
|
+
* function SettingsPanel() {
|
|
210
|
+
* const { config, updateConfig, enableVisual, disableVisual } = useFeedbackConfig()
|
|
211
|
+
*
|
|
212
|
+
* return (
|
|
213
|
+
* <div>
|
|
214
|
+
* <label>
|
|
215
|
+
* <input
|
|
216
|
+
* type="checkbox"
|
|
217
|
+
* checked={config.visual}
|
|
218
|
+
* onChange={(e) =>
|
|
219
|
+
* e.target.checked ? enableVisual() : disableVisual()
|
|
220
|
+
* }
|
|
221
|
+
* />
|
|
222
|
+
* Show visual notifications
|
|
223
|
+
* </label>
|
|
224
|
+
*
|
|
225
|
+
* <select
|
|
226
|
+
* value={config.visualPosition}
|
|
227
|
+
* onChange={(e) =>
|
|
228
|
+
* updateConfig({ visualPosition: e.target.value as any })
|
|
229
|
+
* }
|
|
230
|
+
* >
|
|
231
|
+
* <option value="top-right">Top Right</option>
|
|
232
|
+
* <option value="bottom-right">Bottom Right</option>
|
|
233
|
+
* </select>
|
|
234
|
+
* </div>
|
|
235
|
+
* )
|
|
236
|
+
* }
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
declare function useFeedbackConfig(): UseFeedbackConfigReturn;
|
|
240
|
+
|
|
241
|
+
export { A11yFeedbackProvider, useA11yAnnounce, useA11yFeedback, useA11yFeedbackContext, useFeedbackConfig };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { FeedbackConfig, FeedbackOptions, FeedbackEvent, notify, FeedbackLogEntry } from '@theaccessibleteam/a11y-feedback';
|
|
3
|
+
export { FeedbackConfig, FeedbackEvent, FeedbackOptions, FeedbackType } from '@theaccessibleteam/a11y-feedback';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* React Context Provider for a11y-feedback
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Context value interface
|
|
11
|
+
*/
|
|
12
|
+
interface A11yFeedbackContextValue {
|
|
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
|
+
/** Generic notify function */
|
|
24
|
+
notify: typeof notify;
|
|
25
|
+
/** Dismiss all visual feedback */
|
|
26
|
+
dismissAll: () => void;
|
|
27
|
+
/** Get the feedback log (when debug is enabled) */
|
|
28
|
+
getLog: () => FeedbackLogEntry[];
|
|
29
|
+
/** Clear the feedback log */
|
|
30
|
+
clearLog: () => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Provider props
|
|
34
|
+
*/
|
|
35
|
+
interface A11yFeedbackProviderProps {
|
|
36
|
+
/** React children */
|
|
37
|
+
children: ReactNode;
|
|
38
|
+
/** Configuration options */
|
|
39
|
+
config?: Partial<FeedbackConfig>;
|
|
40
|
+
/** Enable debug mode */
|
|
41
|
+
debug?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Provider component for a11y-feedback
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* import { A11yFeedbackProvider } from '@theaccessibleteam/a11y-feedback-react'
|
|
49
|
+
*
|
|
50
|
+
* function App() {
|
|
51
|
+
* return (
|
|
52
|
+
* <A11yFeedbackProvider config={{ visual: true }}>
|
|
53
|
+
* <MyApp />
|
|
54
|
+
* </A11yFeedbackProvider>
|
|
55
|
+
* )
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
declare function A11yFeedbackProvider({ children, config, debug, }: A11yFeedbackProviderProps): JSX.Element;
|
|
60
|
+
/**
|
|
61
|
+
* Hook to access the a11y-feedback context
|
|
62
|
+
*
|
|
63
|
+
* @throws Error if used outside of A11yFeedbackProvider
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```tsx
|
|
67
|
+
* function MyComponent() {
|
|
68
|
+
* const { success, error } = useA11yFeedbackContext()
|
|
69
|
+
*
|
|
70
|
+
* const handleSave = async () => {
|
|
71
|
+
* try {
|
|
72
|
+
* await saveData()
|
|
73
|
+
* success('Data saved successfully')
|
|
74
|
+
* } catch (e) {
|
|
75
|
+
* error('Failed to save data')
|
|
76
|
+
* }
|
|
77
|
+
* }
|
|
78
|
+
*
|
|
79
|
+
* return <button onClick={handleSave}>Save</button>
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare function useA11yFeedbackContext(): A11yFeedbackContextValue;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Return type for useA11yFeedback hook
|
|
87
|
+
*/
|
|
88
|
+
interface UseA11yFeedbackReturn {
|
|
89
|
+
/** Send a success notification */
|
|
90
|
+
success: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
91
|
+
/** Send an error notification */
|
|
92
|
+
error: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
93
|
+
/** Send a warning notification */
|
|
94
|
+
warning: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
95
|
+
/** Send an info notification */
|
|
96
|
+
info: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
97
|
+
/** Send a loading notification */
|
|
98
|
+
loading: (message: string, options?: FeedbackOptions) => Promise<FeedbackEvent>;
|
|
99
|
+
/** Dismiss a specific visual feedback item */
|
|
100
|
+
dismiss: (id: string) => void;
|
|
101
|
+
/** Dismiss all visual feedback items */
|
|
102
|
+
dismissAll: () => void;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Main hook for sending accessible feedback notifications
|
|
106
|
+
*
|
|
107
|
+
* Can be used without a provider for simple use cases.
|
|
108
|
+
* For app-wide configuration, use with A11yFeedbackProvider.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```tsx
|
|
112
|
+
* function SaveButton() {
|
|
113
|
+
* const feedback = useA11yFeedback()
|
|
114
|
+
*
|
|
115
|
+
* const handleSave = async () => {
|
|
116
|
+
* feedback.loading('Saving...', { id: 'save' })
|
|
117
|
+
*
|
|
118
|
+
* try {
|
|
119
|
+
* await saveData()
|
|
120
|
+
* feedback.success('Saved successfully!', { id: 'save' })
|
|
121
|
+
* } catch (e) {
|
|
122
|
+
* feedback.error('Failed to save', { id: 'save', focus: '#save-btn' })
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
*
|
|
126
|
+
* return <button id="save-btn" onClick={handleSave}>Save</button>
|
|
127
|
+
* }
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
declare function useA11yFeedback(): UseA11yFeedbackReturn;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Return type for useA11yAnnounce hook
|
|
134
|
+
*/
|
|
135
|
+
interface UseA11yAnnounceReturn {
|
|
136
|
+
/**
|
|
137
|
+
* Announce a message politely (for non-urgent updates)
|
|
138
|
+
* Screen reader will wait for current speech to finish
|
|
139
|
+
*/
|
|
140
|
+
announcePolite: (message: string, options?: FeedbackOptions) => Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Announce a message assertively (for urgent updates)
|
|
143
|
+
* Screen reader will interrupt current speech
|
|
144
|
+
*/
|
|
145
|
+
announceAssertive: (message: string, options?: FeedbackOptions) => Promise<void>;
|
|
146
|
+
/**
|
|
147
|
+
* Announce with custom options
|
|
148
|
+
*/
|
|
149
|
+
announce: (message: string, politeness: 'polite' | 'assertive', options?: FeedbackOptions) => Promise<void>;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Simple hook for making screen reader announcements
|
|
153
|
+
*
|
|
154
|
+
* This is a lightweight alternative to useA11yFeedback when you only
|
|
155
|
+
* need to announce messages without visual feedback or complex options.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```tsx
|
|
159
|
+
* function SearchResults({ count }: { count: number }) {
|
|
160
|
+
* const { announcePolite } = useA11yAnnounce()
|
|
161
|
+
*
|
|
162
|
+
* useEffect(() => {
|
|
163
|
+
* announcePolite(`Found ${count} results`)
|
|
164
|
+
* }, [count, announcePolite])
|
|
165
|
+
*
|
|
166
|
+
* return <div>{count} results found</div>
|
|
167
|
+
* }
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```tsx
|
|
172
|
+
* function Timer({ secondsLeft }: { secondsLeft: number }) {
|
|
173
|
+
* const { announceAssertive } = useA11yAnnounce()
|
|
174
|
+
*
|
|
175
|
+
* useEffect(() => {
|
|
176
|
+
* if (secondsLeft <= 10) {
|
|
177
|
+
* announceAssertive(`${secondsLeft} seconds remaining`)
|
|
178
|
+
* }
|
|
179
|
+
* }, [secondsLeft, announceAssertive])
|
|
180
|
+
*
|
|
181
|
+
* return <div>{secondsLeft}s</div>
|
|
182
|
+
* }
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
declare function useA11yAnnounce(): UseA11yAnnounceReturn;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Return type for useFeedbackConfig hook
|
|
189
|
+
*/
|
|
190
|
+
interface UseFeedbackConfigReturn {
|
|
191
|
+
/** Current configuration */
|
|
192
|
+
config: FeedbackConfig;
|
|
193
|
+
/** Update configuration (merges with existing) */
|
|
194
|
+
updateConfig: (updates: Partial<FeedbackConfig>) => void;
|
|
195
|
+
/** Reset configuration to defaults */
|
|
196
|
+
resetConfig: () => void;
|
|
197
|
+
/** Enable visual feedback */
|
|
198
|
+
enableVisual: () => void;
|
|
199
|
+
/** Disable visual feedback */
|
|
200
|
+
disableVisual: () => void;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Hook for managing a11y-feedback configuration
|
|
204
|
+
*
|
|
205
|
+
* Provides reactive access to the configuration and methods to update it.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```tsx
|
|
209
|
+
* function SettingsPanel() {
|
|
210
|
+
* const { config, updateConfig, enableVisual, disableVisual } = useFeedbackConfig()
|
|
211
|
+
*
|
|
212
|
+
* return (
|
|
213
|
+
* <div>
|
|
214
|
+
* <label>
|
|
215
|
+
* <input
|
|
216
|
+
* type="checkbox"
|
|
217
|
+
* checked={config.visual}
|
|
218
|
+
* onChange={(e) =>
|
|
219
|
+
* e.target.checked ? enableVisual() : disableVisual()
|
|
220
|
+
* }
|
|
221
|
+
* />
|
|
222
|
+
* Show visual notifications
|
|
223
|
+
* </label>
|
|
224
|
+
*
|
|
225
|
+
* <select
|
|
226
|
+
* value={config.visualPosition}
|
|
227
|
+
* onChange={(e) =>
|
|
228
|
+
* updateConfig({ visualPosition: e.target.value as any })
|
|
229
|
+
* }
|
|
230
|
+
* >
|
|
231
|
+
* <option value="top-right">Top Right</option>
|
|
232
|
+
* <option value="bottom-right">Bottom Right</option>
|
|
233
|
+
* </select>
|
|
234
|
+
* </div>
|
|
235
|
+
* )
|
|
236
|
+
* }
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
declare function useFeedbackConfig(): UseFeedbackConfigReturn;
|
|
240
|
+
|
|
241
|
+
export { A11yFeedbackProvider, useA11yAnnounce, useA11yFeedback, useA11yFeedbackContext, useFeedbackConfig };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// src/provider.tsx
|
|
2
|
+
import {
|
|
3
|
+
createContext,
|
|
4
|
+
useContext,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo
|
|
7
|
+
} from "react";
|
|
8
|
+
import {
|
|
9
|
+
notify,
|
|
10
|
+
configureFeedback,
|
|
11
|
+
resetConfig,
|
|
12
|
+
enableFeedbackDebug,
|
|
13
|
+
disableFeedbackDebug,
|
|
14
|
+
getFeedbackLog,
|
|
15
|
+
clearFeedbackLog,
|
|
16
|
+
dismissAllVisualFeedback
|
|
17
|
+
} from "@theaccessibleteam/a11y-feedback";
|
|
18
|
+
import { jsx } from "react/jsx-runtime";
|
|
19
|
+
var A11yFeedbackContext = createContext(null);
|
|
20
|
+
function A11yFeedbackProvider({
|
|
21
|
+
children,
|
|
22
|
+
config,
|
|
23
|
+
debug = false
|
|
24
|
+
}) {
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (config) {
|
|
27
|
+
configureFeedback(config);
|
|
28
|
+
}
|
|
29
|
+
if (debug) {
|
|
30
|
+
enableFeedbackDebug();
|
|
31
|
+
}
|
|
32
|
+
return () => {
|
|
33
|
+
resetConfig();
|
|
34
|
+
disableFeedbackDebug();
|
|
35
|
+
dismissAllVisualFeedback();
|
|
36
|
+
};
|
|
37
|
+
}, []);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (config) {
|
|
40
|
+
configureFeedback(config);
|
|
41
|
+
}
|
|
42
|
+
}, [config]);
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (debug) {
|
|
45
|
+
enableFeedbackDebug();
|
|
46
|
+
} else {
|
|
47
|
+
disableFeedbackDebug();
|
|
48
|
+
}
|
|
49
|
+
}, [debug]);
|
|
50
|
+
const contextValue = useMemo(
|
|
51
|
+
() => ({
|
|
52
|
+
success: (message, options) => notify.success(message, options),
|
|
53
|
+
error: (message, options) => notify.error(message, options),
|
|
54
|
+
warning: (message, options) => notify.warning(message, options),
|
|
55
|
+
info: (message, options) => notify.info(message, options),
|
|
56
|
+
loading: (message, options) => notify.loading(message, options),
|
|
57
|
+
notify,
|
|
58
|
+
dismissAll: dismissAllVisualFeedback,
|
|
59
|
+
getLog: () => [...getFeedbackLog()],
|
|
60
|
+
clearLog: clearFeedbackLog
|
|
61
|
+
}),
|
|
62
|
+
[]
|
|
63
|
+
);
|
|
64
|
+
return /* @__PURE__ */ jsx(A11yFeedbackContext.Provider, { value: contextValue, children });
|
|
65
|
+
}
|
|
66
|
+
function useA11yFeedbackContext() {
|
|
67
|
+
const context = useContext(A11yFeedbackContext);
|
|
68
|
+
if (context === null) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
"useA11yFeedbackContext must be used within an A11yFeedbackProvider"
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return context;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/useA11yFeedback.ts
|
|
77
|
+
import { useCallback, useMemo as useMemo2 } from "react";
|
|
78
|
+
import {
|
|
79
|
+
notify as notify2,
|
|
80
|
+
dismissVisualFeedback,
|
|
81
|
+
dismissAllVisualFeedback as dismissAllVisualFeedback2
|
|
82
|
+
} from "@theaccessibleteam/a11y-feedback";
|
|
83
|
+
function useA11yFeedback() {
|
|
84
|
+
const success = useCallback(
|
|
85
|
+
(message, options) => notify2.success(message, options),
|
|
86
|
+
[]
|
|
87
|
+
);
|
|
88
|
+
const error = useCallback(
|
|
89
|
+
(message, options) => notify2.error(message, options),
|
|
90
|
+
[]
|
|
91
|
+
);
|
|
92
|
+
const warning = useCallback(
|
|
93
|
+
(message, options) => notify2.warning(message, options),
|
|
94
|
+
[]
|
|
95
|
+
);
|
|
96
|
+
const info = useCallback(
|
|
97
|
+
(message, options) => notify2.info(message, options),
|
|
98
|
+
[]
|
|
99
|
+
);
|
|
100
|
+
const loading = useCallback(
|
|
101
|
+
(message, options) => notify2.loading(message, options),
|
|
102
|
+
[]
|
|
103
|
+
);
|
|
104
|
+
const dismiss = useCallback((id) => {
|
|
105
|
+
dismissVisualFeedback(id);
|
|
106
|
+
}, []);
|
|
107
|
+
const dismissAll = useCallback(() => {
|
|
108
|
+
dismissAllVisualFeedback2();
|
|
109
|
+
}, []);
|
|
110
|
+
return useMemo2(
|
|
111
|
+
() => ({
|
|
112
|
+
success,
|
|
113
|
+
error,
|
|
114
|
+
warning,
|
|
115
|
+
info,
|
|
116
|
+
loading,
|
|
117
|
+
dismiss,
|
|
118
|
+
dismissAll
|
|
119
|
+
}),
|
|
120
|
+
[success, error, warning, info, loading, dismiss, dismissAll]
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/useA11yAnnounce.ts
|
|
125
|
+
import { useCallback as useCallback2, useMemo as useMemo3 } from "react";
|
|
126
|
+
import { notify as notify3 } from "@theaccessibleteam/a11y-feedback";
|
|
127
|
+
function useA11yAnnounce() {
|
|
128
|
+
const announcePolite = useCallback2(
|
|
129
|
+
async (message, options) => {
|
|
130
|
+
await notify3.info(message, options);
|
|
131
|
+
},
|
|
132
|
+
[]
|
|
133
|
+
);
|
|
134
|
+
const announceAssertive = useCallback2(
|
|
135
|
+
async (message, options) => {
|
|
136
|
+
await notify3.warning(message, options);
|
|
137
|
+
},
|
|
138
|
+
[]
|
|
139
|
+
);
|
|
140
|
+
const announce = useCallback2(
|
|
141
|
+
async (message, politeness, options) => {
|
|
142
|
+
if (politeness === "assertive") {
|
|
143
|
+
await notify3.warning(message, options);
|
|
144
|
+
} else {
|
|
145
|
+
await notify3.info(message, options);
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
[]
|
|
149
|
+
);
|
|
150
|
+
return useMemo3(
|
|
151
|
+
() => ({
|
|
152
|
+
announcePolite,
|
|
153
|
+
announceAssertive,
|
|
154
|
+
announce
|
|
155
|
+
}),
|
|
156
|
+
[announcePolite, announceAssertive, announce]
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/useFeedbackConfig.ts
|
|
161
|
+
import { useCallback as useCallback3, useEffect as useEffect2, useState } from "react";
|
|
162
|
+
import {
|
|
163
|
+
configureFeedback as configureFeedback2,
|
|
164
|
+
getConfig,
|
|
165
|
+
resetConfig as resetConfig2
|
|
166
|
+
} from "@theaccessibleteam/a11y-feedback";
|
|
167
|
+
function useFeedbackConfig() {
|
|
168
|
+
const [config, setConfig] = useState(() => getConfig());
|
|
169
|
+
const syncConfig = useCallback3(() => {
|
|
170
|
+
setConfig(getConfig());
|
|
171
|
+
}, []);
|
|
172
|
+
const updateConfig = useCallback3(
|
|
173
|
+
(updates) => {
|
|
174
|
+
configureFeedback2(updates);
|
|
175
|
+
syncConfig();
|
|
176
|
+
},
|
|
177
|
+
[syncConfig]
|
|
178
|
+
);
|
|
179
|
+
const reset = useCallback3(() => {
|
|
180
|
+
resetConfig2();
|
|
181
|
+
syncConfig();
|
|
182
|
+
}, [syncConfig]);
|
|
183
|
+
const enableVisual = useCallback3(() => {
|
|
184
|
+
updateConfig({ visual: true });
|
|
185
|
+
}, [updateConfig]);
|
|
186
|
+
const disableVisual = useCallback3(() => {
|
|
187
|
+
updateConfig({ visual: false });
|
|
188
|
+
}, [updateConfig]);
|
|
189
|
+
useEffect2(() => {
|
|
190
|
+
syncConfig();
|
|
191
|
+
}, [syncConfig]);
|
|
192
|
+
return {
|
|
193
|
+
config,
|
|
194
|
+
updateConfig,
|
|
195
|
+
resetConfig: reset,
|
|
196
|
+
enableVisual,
|
|
197
|
+
disableVisual
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
export {
|
|
201
|
+
A11yFeedbackProvider,
|
|
202
|
+
useA11yAnnounce,
|
|
203
|
+
useA11yFeedback,
|
|
204
|
+
useA11yFeedbackContext,
|
|
205
|
+
useFeedbackConfig
|
|
206
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@theaccessibleteam/a11y-feedback-react",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "React bindings 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,.tsx"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"react",
|
|
34
|
+
"accessibility",
|
|
35
|
+
"a11y",
|
|
36
|
+
"aria-live",
|
|
37
|
+
"screen-reader",
|
|
38
|
+
"hooks",
|
|
39
|
+
"notifications",
|
|
40
|
+
"toast"
|
|
41
|
+
],
|
|
42
|
+
"author": "The Accessible Team <theaccessibleteam@gmail.com>",
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/WOLFIEEEE/a11y-feedback.git",
|
|
47
|
+
"directory": "packages/react"
|
|
48
|
+
},
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/WOLFIEEEE/a11y-feedback/issues"
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://github.com/WOLFIEEEE/a11y-feedback/tree/main/packages/react#readme",
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"@theaccessibleteam/a11y-feedback": "workspace:^",
|
|
55
|
+
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/react": "^18.2.0",
|
|
59
|
+
"react": "^18.2.0",
|
|
60
|
+
"tsup": "^8.0.0",
|
|
61
|
+
"typescript": "^5.4.0"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|