vue-a11y-directives 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/LICENSE +21 -0
- package/README.md +207 -0
- package/dist/vue-a11y-directives.cjs.js +1 -0
- package/dist/vue-a11y-directives.esm.js +315 -0
- package/dist/vue-a11y-directives.min.js +1 -0
- package/package.json +60 -0
- package/src/COMPLEX-SCENARIOS.md +722 -0
- package/src/README.md +1477 -0
- package/src/announce.directive.js +37 -0
- package/src/aria.directive.js +105 -0
- package/src/focus.directive.js +28 -0
- package/src/helpers.js +147 -0
- package/src/index.js +57 -0
- package/src/keyboard.directive.js +114 -0
- package/src/skip-link.directive.js +44 -0
- package/src/skip.directive.js +151 -0
- package/src/trap-focus.directive.js +82 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Vue A11y Directives Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Vue A11y Directives
|
|
2
|
+
|
|
3
|
+
A comprehensive collection of Vue 3 directives for building accessible web applications with WCAG compliance.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- **7 Powerful Directives** for complete accessibility control
|
|
8
|
+
- **Zero Dependencies** - Lightweight and performant
|
|
9
|
+
- **TypeScript Support** - Full type definitions included
|
|
10
|
+
- **WCAG Compliant** - Follow web accessibility standards
|
|
11
|
+
- **Easy to Use** - Simple directive-based API
|
|
12
|
+
- **Well Documented** - Comprehensive documentation and examples
|
|
13
|
+
|
|
14
|
+
## 📦 Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install vue-a11y-directives
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 🎯 Quick Start
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
import { createApp } from 'vue'
|
|
24
|
+
import App from './App.vue'
|
|
25
|
+
import { installA11yDirectives } from 'vue-a11y-directives'
|
|
26
|
+
|
|
27
|
+
const app = createApp(App)
|
|
28
|
+
|
|
29
|
+
// Install all directives globally
|
|
30
|
+
installA11yDirectives(app)
|
|
31
|
+
|
|
32
|
+
app.mount('#app')
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or import individual directives:
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
import { focusDirective, keyboardDirective, ariaDirective } from 'vue-a11y-directives'
|
|
39
|
+
|
|
40
|
+
export default {
|
|
41
|
+
directives: {
|
|
42
|
+
'a11y-focus': focusDirective,
|
|
43
|
+
'a11y-keyboard': keyboardDirective,
|
|
44
|
+
'a11y-aria': ariaDirective
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 📚 Available Directives
|
|
50
|
+
|
|
51
|
+
### 1. `v-a11y-focus`
|
|
52
|
+
Auto-focus elements with conditional logic.
|
|
53
|
+
|
|
54
|
+
```vue
|
|
55
|
+
<input v-a11y-focus />
|
|
56
|
+
<input v-a11y-focus="isEditing" />
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 2. `v-a11y-keyboard`
|
|
60
|
+
Enhanced keyboard navigation support.
|
|
61
|
+
|
|
62
|
+
```vue
|
|
63
|
+
<div v-a11y-keyboard="{
|
|
64
|
+
arrowDown: () => next(),
|
|
65
|
+
arrowUp: () => prev(),
|
|
66
|
+
enter: () => select()
|
|
67
|
+
}">
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 3. `v-a11y-aria`
|
|
71
|
+
Dynamic ARIA attributes management.
|
|
72
|
+
|
|
73
|
+
```vue
|
|
74
|
+
<button v-a11y-aria="{
|
|
75
|
+
label: 'Close dialog',
|
|
76
|
+
expanded: isOpen,
|
|
77
|
+
controls: 'menu-id'
|
|
78
|
+
}">
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 4. `v-a11y-announce`
|
|
82
|
+
Screen reader announcements.
|
|
83
|
+
|
|
84
|
+
```vue
|
|
85
|
+
<div v-a11y-announce="statusMessage"></div>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 5. `v-a11y-trap-focus`
|
|
89
|
+
Trap focus within modals/dialogs.
|
|
90
|
+
|
|
91
|
+
```vue
|
|
92
|
+
<div v-a11y-trap-focus="isModalOpen">
|
|
93
|
+
<!-- Focus stays within this container -->
|
|
94
|
+
</div>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 6. `v-a11y-skip-link`
|
|
98
|
+
Skip navigation links for keyboard users.
|
|
99
|
+
|
|
100
|
+
```vue
|
|
101
|
+
<a v-a11y-skip-link href="#main-content">Skip to main content</a>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 7. `v-a11y-skip`
|
|
105
|
+
Skip elements from keyboard navigation.
|
|
106
|
+
|
|
107
|
+
```vue
|
|
108
|
+
<!-- Always skip -->
|
|
109
|
+
<div v-a11y-skip>Hidden content</div>
|
|
110
|
+
|
|
111
|
+
<!-- Conditional skip -->
|
|
112
|
+
<button v-a11y-skip="item.disabled">Button</button>
|
|
113
|
+
|
|
114
|
+
<!-- With visual indication -->
|
|
115
|
+
<div v-a11y-skip.visual="item.inactive">Grayed out</div>
|
|
116
|
+
|
|
117
|
+
<!-- Block all interactions -->
|
|
118
|
+
<div v-a11y-skip.noInteraction="isProcessing">Processing...</div>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 🎨 Real-World Examples
|
|
122
|
+
|
|
123
|
+
### Accessible Navigation Menu
|
|
124
|
+
|
|
125
|
+
```vue
|
|
126
|
+
<template>
|
|
127
|
+
<nav>
|
|
128
|
+
<div v-a11y-announce="announcement"></div>
|
|
129
|
+
<ul v-a11y-keyboard="keyboardHandlers" tabindex="0">
|
|
130
|
+
<li v-for="item in menuItems" :key="item.id">
|
|
131
|
+
<button
|
|
132
|
+
v-a11y-aria="{
|
|
133
|
+
expanded: item.isOpen,
|
|
134
|
+
controls: `menu-${item.id}`
|
|
135
|
+
}"
|
|
136
|
+
@click="toggle(item)"
|
|
137
|
+
>
|
|
138
|
+
{{ item.label }}
|
|
139
|
+
</button>
|
|
140
|
+
</li>
|
|
141
|
+
</ul>
|
|
142
|
+
</nav>
|
|
143
|
+
</template>
|
|
144
|
+
|
|
145
|
+
<script>
|
|
146
|
+
export default {
|
|
147
|
+
data() {
|
|
148
|
+
return {
|
|
149
|
+
announcement: '',
|
|
150
|
+
menuItems: [
|
|
151
|
+
{ id: 1, label: 'Home', isOpen: false },
|
|
152
|
+
{ id: 2, label: 'Products', isOpen: false }
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
computed: {
|
|
157
|
+
keyboardHandlers() {
|
|
158
|
+
return {
|
|
159
|
+
arrowDown: () => this.navigateNext(),
|
|
160
|
+
arrowUp: () => this.navigatePrev(),
|
|
161
|
+
enter: () => this.selectItem()
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
</script>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Accessible Modal Dialog
|
|
170
|
+
|
|
171
|
+
```vue
|
|
172
|
+
<template>
|
|
173
|
+
<div v-if="isOpen" v-a11y-trap-focus="isOpen" class="modal">
|
|
174
|
+
<div v-a11y-announce="modalAnnouncement"></div>
|
|
175
|
+
<h2 v-a11y-focus>Modal Title</h2>
|
|
176
|
+
<button
|
|
177
|
+
v-a11y-aria="{ label: 'Close modal' }"
|
|
178
|
+
@click="close"
|
|
179
|
+
>
|
|
180
|
+
×
|
|
181
|
+
</button>
|
|
182
|
+
</div>
|
|
183
|
+
</template>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## 📖 Documentation
|
|
187
|
+
|
|
188
|
+
For complete documentation, examples, and interactive demos, visit:
|
|
189
|
+
- [GitHub Repository](https://github.com/shkelqimemerllahu/vue-a11y-directives)
|
|
190
|
+
- [Live Documentation](https://vue-a11y-directives.netlify.app) (coming soon)
|
|
191
|
+
|
|
192
|
+
## 🤝 Contributing
|
|
193
|
+
|
|
194
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
195
|
+
|
|
196
|
+
## 📄 License
|
|
197
|
+
|
|
198
|
+
MIT © [Shkelqim Emerllahu](https://github.com/shkelqimemerllahu)
|
|
199
|
+
|
|
200
|
+
## 🌟 Show Your Support
|
|
201
|
+
|
|
202
|
+
Give a ⭐️ if this project helped you!
|
|
203
|
+
|
|
204
|
+
## 📞 Support
|
|
205
|
+
|
|
206
|
+
- Create an [issue](https://github.com/shkelqimemerllahu/vue-a11y-directives/issues)
|
|
207
|
+
- Follow me on [GitHub](https://github.com/shkelqimemerllahu)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const y={mounted(e,i){const t=typeof i.value=="object"?i.value:{delay:i.value||0},n=t.delay||0,a=t.select||!1;setTimeout(()=>{e.focus&&(e.focus(),a&&(e.tagName==="INPUT"||e.tagName==="TEXTAREA")&&e.select())},n)}};function u(e){if(!e)return[];const i=["a[href]","button:not([disabled])","textarea:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])",'[tabindex]:not([tabindex="-1"])','[contenteditable="true"]',"audio[controls]","video[controls]"];return Array.from(e.querySelectorAll(i.join(", "))).filter(n=>{const a=window.getComputedStyle(n);return n.offsetWidth>0&&n.offsetHeight>0&&a.visibility!=="hidden"&&a.display!=="none"})}function c(e,i){Object.entries(i).forEach(([t,n])=>{n!=null&&e.setAttribute(t,n)})}function S(e,i){i.forEach(t=>{e.removeAttribute(t)})}function d(e,i="polite"){const t=document.createElement("div");t.setAttribute("role","status"),t.setAttribute("aria-live",i),t.setAttribute("aria-atomic","true"),t.style.position="absolute",t.style.left="-10000px",t.style.width="1px",t.style.height="1px",t.style.overflow="hidden",document.body.appendChild(t),setTimeout(()=>{t.textContent=e},100),setTimeout(()=>{document.body.removeChild(t)},3e3)}function w(e){const i=u(e);return i.length>0?i[0]:null}function x(e){const i=u(e);return i.length>0?i[i.length-1]:null}function E(e){return e.contains(document.activeElement)}function D(){return document.activeElement}function F(e){e&&e.focus&&e.focus()}function T(e="a11y"){return`${e}-${Math.random().toString(36).substr(2,9)}`}const p={mounted(e,i){const n=(i.value||{}).autoFocus!==!1,a=document.activeElement;e.__previousFocus=a,n&&setTimeout(()=>{const r=u(e);r.length>0&&r[0].focus()},100);const o=r=>{if(r.key!=="Tab")return;const s=u(e);if(s.length===0)return;const l=s[0],f=s[s.length-1];r.shiftKey&&document.activeElement===l?(r.preventDefault(),f.focus()):!r.shiftKey&&document.activeElement===f&&(r.preventDefault(),l.focus())};e.addEventListener("keydown",o),e.__handleKeydown=o},unmounted(e){e.__handleKeydown&&(e.removeEventListener("keydown",e.__handleKeydown),delete e.__handleKeydown),e.__previousFocus&&(setTimeout(()=>{if(e.__previousFocus&&document.body.contains(e.__previousFocus)&&typeof e.__previousFocus.focus=="function")try{e.__previousFocus.focus()}catch(i){console.warn("Could not restore focus:",i)}},0),delete e.__previousFocus)}},v={mounted(e,i){const t=i.value||{};console.log("Keyboard directive mounted with config:",t);const n=a=>{console.log("Key pressed:",a.key,"Config:",t);const o={Enter:"enter"," ":"space",Escape:"escape",ArrowUp:"arrowUp",ArrowDown:"arrowDown",ArrowLeft:"arrowLeft",ArrowRight:"arrowRight",Tab:"tab",Delete:"delete",Backspace:"backspace"};let r="";(a.ctrlKey||a.metaKey)&&(r+="ctrl+"),a.altKey&&(r+="alt+"),a.shiftKey&&(r+="shift+"),r+=a.key.toLowerCase();const s=o[a.key];if(s&&typeof t[s]=="function"){a.preventDefault(),t[s](a);return}if(t[r]&&typeof t[r]=="function"){a.preventDefault(),t[r](a);return}if(t[a.key]&&typeof t[a.key]=="function"){a.preventDefault(),t[a.key](a);return}if(t.arrows&&["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"].includes(a.key)&&typeof t.arrows=="function"){a.preventDefault(),t.arrows(a);return}if(t.handlers){if(t.handlers[a.key]&&typeof t.handlers[a.key]=="function"){a.preventDefault(),t.handlers[a.key](a);return}if(t.handlers[r]&&typeof t.handlers[r]=="function"){a.preventDefault(),t.handlers[r](a);return}}if(t.custom&&typeof t.custom=="function"){t.custom(a);return}t.enter===!0&&a.key==="Enter"&&!["INPUT","TEXTAREA","SELECT"].includes(a.target.tagName)&&(a.preventDefault(),e.click&&e.click()),t.space===!0&&a.key===" "&&["BUTTON","A"].includes(e.tagName)&&(a.preventDefault(),e.click&&e.click())};e.addEventListener("keydown",n),e.__keyboardHandler=n},unmounted(e){e.__keyboardHandler&&(e.removeEventListener("keydown",e.__keyboardHandler),delete e.__keyboardHandler)}},m={mounted(e,i){if(!i.value)return;const t=typeof i.value=="string"?{message:i.value,priority:"polite"}:i.value;t&&t.message&&d(t.message,t.priority||"polite")},updated(e,i){if(i.value!==i.oldValue&&i.value){const t=typeof i.value=="string"?{message:i.value,priority:"polite"}:i.value;t&&t.message&&d(t.message,t.priority||"polite")}}},_={mounted(e,i){const t=i.value,n=a=>{a.preventDefault();const o=document.querySelector(t);o&&(o.hasAttribute("tabindex")||o.setAttribute("tabindex","-1"),o.focus(),o.scrollIntoView({behavior:"smooth",block:"start"}))};e.addEventListener("click",n),e.__skipLinkHandler=n,e.setAttribute("role","link"),t&&e.setAttribute("aria-label",`Skip to ${t.replace("#","")}`)},unmounted(e){e.__skipLinkHandler&&(e.removeEventListener("click",e.__skipLinkHandler),delete e.__skipLinkHandler)}},k={mounted(e,i){b(e,i)},updated(e,i){b(e,i)},unmounted(e){delete e.__a11ySkipOriginalTabIndex,delete e.__a11ySkipOriginalAriaHidden,delete e.__a11ySkipChildrenState}};function b(e,i){if(i.value===void 0?!0:!!i.value){e.__a11ySkipOriginalTabIndex===void 0&&(e.__a11ySkipOriginalTabIndex=e.getAttribute("tabindex")),e.__a11ySkipOriginalAriaHidden===void 0&&(e.__a11ySkipOriginalAriaHidden=e.getAttribute("aria-hidden")),e.setAttribute("tabindex","-1"),e.setAttribute("aria-hidden","true"),e.setAttribute("data-a11y-skip","true");const n=e.querySelectorAll('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])');e.__a11ySkipChildrenState||(e.__a11ySkipChildrenState=[]),n.forEach((a,o)=>{e.__a11ySkipChildrenState[o]||(e.__a11ySkipChildrenState[o]={tabIndex:a.getAttribute("tabindex"),disabled:a.disabled}),a.setAttribute("tabindex","-1"),"disabled"in a&&(a.disabled=!0)}),i.modifiers.noInteraction&&(e.style.pointerEvents="none"),i.modifiers.visual&&(e.style.opacity="0.5",e.style.filter="grayscale(100%)",e.style.pointerEvents="none")}else{e.__a11ySkipOriginalTabIndex!==void 0?e.__a11ySkipOriginalTabIndex===null?e.removeAttribute("tabindex"):e.setAttribute("tabindex",e.__a11ySkipOriginalTabIndex):e.removeAttribute("tabindex"),e.__a11ySkipOriginalAriaHidden!==void 0?e.__a11ySkipOriginalAriaHidden===null?e.removeAttribute("aria-hidden"):e.setAttribute("aria-hidden",e.__a11ySkipOriginalAriaHidden):e.removeAttribute("aria-hidden"),e.removeAttribute("data-a11y-skip");const n=e.querySelectorAll("a, button, input, select, textarea, [tabindex]");e.__a11ySkipChildrenState&&n.forEach((a,o)=>{const r=e.__a11ySkipChildrenState[o];r&&(r.tabIndex===null?a.removeAttribute("tabindex"):a.setAttribute("tabindex",r.tabIndex),"disabled"in a&&(a.disabled=r.disabled))}),i.modifiers.noInteraction&&(e.style.pointerEvents=""),i.modifiers.visual&&(e.style.opacity="",e.style.filter="",e.style.pointerEvents="")}}const h={mounted(e,i){const t=i.value||{},n={label:"aria-label",labelledby:"aria-labelledby",describedby:"aria-describedby",expanded:"aria-expanded",pressed:"aria-pressed",selected:"aria-selected",checked:"aria-checked",disabled:"aria-disabled",hidden:"aria-hidden",invalid:"aria-invalid",required:"aria-required",live:"aria-live",atomic:"aria-atomic",busy:"aria-busy",controls:"aria-controls",owns:"aria-owns",haspopup:"aria-haspopup",level:"aria-level",modal:"aria-modal",multiselectable:"aria-multiselectable",orientation:"aria-orientation",placeholder:"aria-placeholder",readonly:"aria-readonly",relevant:"aria-relevant",valuemax:"aria-valuemax",valuemin:"aria-valuemin",valuenow:"aria-valuenow",valuetext:"aria-valuetext"},a={};Object.entries(t).forEach(([o,r])=>{const s=n[o]||o;a[s]=r}),c(e,a),e.__ariaAttributes=Object.keys(a)},updated(e,i){if(JSON.stringify(i.value)!==JSON.stringify(i.oldValue)){e.__ariaAttributes&&e.__ariaAttributes.forEach(o=>e.removeAttribute(o));const t=i.value||{},n={label:"aria-label",labelledby:"aria-labelledby",describedby:"aria-describedby",expanded:"aria-expanded",pressed:"aria-pressed",selected:"aria-selected",checked:"aria-checked",disabled:"aria-disabled",hidden:"aria-hidden",invalid:"aria-invalid",required:"aria-required",live:"aria-live",atomic:"aria-atomic",busy:"aria-busy",controls:"aria-controls",owns:"aria-owns",haspopup:"aria-haspopup",level:"aria-level",modal:"aria-modal"},a={};Object.entries(t).forEach(([o,r])=>{const s=n[o]||o;a[s]=r}),c(e,a),e.__ariaAttributes=Object.keys(a)}},unmounted(e){e.__ariaAttributes&&(e.__ariaAttributes.forEach(i=>e.removeAttribute(i)),delete e.__ariaAttributes)}},A={"a11y-focus":y,"a11y-trap-focus":p,"a11y-keyboard":v,"a11y-announce":m,"a11y-skip-link":_,"a11y-skip":k,"a11y-aria":h};function g(e){Object.entries(A).forEach(([i,t])=>{e.directive(i,t)})}const O={install:g};exports.a11yDirectives=A;exports.announce=d;exports.announceDirective=m;exports.ariaDirective=h;exports.containsActiveElement=E;exports.default=O;exports.focusDirective=y;exports.generateId=T;exports.getFirstFocusable=w;exports.getFocusableElements=u;exports.getLastFocusable=x;exports.installA11yDirectives=g;exports.keyboardDirective=v;exports.removeAriaAttributes=S;exports.restoreFocus=F;exports.saveFocus=D;exports.setAriaAttributes=c;exports.skipDirective=k;exports.skipLinkDirective=_;exports.trapFocusDirective=p;
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
const p = {
|
|
2
|
+
mounted(e, i) {
|
|
3
|
+
const t = typeof i.value == "object" ? i.value : { delay: i.value || 0 }, n = t.delay || 0, a = t.select || !1;
|
|
4
|
+
setTimeout(() => {
|
|
5
|
+
e.focus && (e.focus(), a && (e.tagName === "INPUT" || e.tagName === "TEXTAREA") && e.select());
|
|
6
|
+
}, n);
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
function u(e) {
|
|
10
|
+
if (!e) return [];
|
|
11
|
+
const i = [
|
|
12
|
+
"a[href]",
|
|
13
|
+
"button:not([disabled])",
|
|
14
|
+
"textarea:not([disabled])",
|
|
15
|
+
'input:not([disabled]):not([type="hidden"])',
|
|
16
|
+
"select:not([disabled])",
|
|
17
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
18
|
+
'[contenteditable="true"]',
|
|
19
|
+
"audio[controls]",
|
|
20
|
+
"video[controls]"
|
|
21
|
+
];
|
|
22
|
+
return Array.from(e.querySelectorAll(i.join(", "))).filter((n) => {
|
|
23
|
+
const a = window.getComputedStyle(n);
|
|
24
|
+
return n.offsetWidth > 0 && n.offsetHeight > 0 && a.visibility !== "hidden" && a.display !== "none";
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function l(e, i) {
|
|
28
|
+
Object.entries(i).forEach(([t, n]) => {
|
|
29
|
+
n != null && e.setAttribute(t, n);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function S(e, i) {
|
|
33
|
+
i.forEach((t) => {
|
|
34
|
+
e.removeAttribute(t);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function f(e, i = "polite") {
|
|
38
|
+
const t = document.createElement("div");
|
|
39
|
+
t.setAttribute("role", "status"), t.setAttribute("aria-live", i), t.setAttribute("aria-atomic", "true"), t.style.position = "absolute", t.style.left = "-10000px", t.style.width = "1px", t.style.height = "1px", t.style.overflow = "hidden", document.body.appendChild(t), setTimeout(() => {
|
|
40
|
+
t.textContent = e;
|
|
41
|
+
}, 100), setTimeout(() => {
|
|
42
|
+
document.body.removeChild(t);
|
|
43
|
+
}, 3e3);
|
|
44
|
+
}
|
|
45
|
+
function w(e) {
|
|
46
|
+
const i = u(e);
|
|
47
|
+
return i.length > 0 ? i[0] : null;
|
|
48
|
+
}
|
|
49
|
+
function x(e) {
|
|
50
|
+
const i = u(e);
|
|
51
|
+
return i.length > 0 ? i[i.length - 1] : null;
|
|
52
|
+
}
|
|
53
|
+
function E(e) {
|
|
54
|
+
return e.contains(document.activeElement);
|
|
55
|
+
}
|
|
56
|
+
function D() {
|
|
57
|
+
return document.activeElement;
|
|
58
|
+
}
|
|
59
|
+
function T(e) {
|
|
60
|
+
e && e.focus && e.focus();
|
|
61
|
+
}
|
|
62
|
+
function O(e = "a11y") {
|
|
63
|
+
return `${e}-${Math.random().toString(36).substr(2, 9)}`;
|
|
64
|
+
}
|
|
65
|
+
const b = {
|
|
66
|
+
mounted(e, i) {
|
|
67
|
+
const n = (i.value || {}).autoFocus !== !1, a = document.activeElement;
|
|
68
|
+
e.__previousFocus = a, n && setTimeout(() => {
|
|
69
|
+
const r = u(e);
|
|
70
|
+
r.length > 0 && r[0].focus();
|
|
71
|
+
}, 100);
|
|
72
|
+
const o = (r) => {
|
|
73
|
+
if (r.key !== "Tab") return;
|
|
74
|
+
const s = u(e);
|
|
75
|
+
if (s.length === 0) return;
|
|
76
|
+
const d = s[0], c = s[s.length - 1];
|
|
77
|
+
r.shiftKey && document.activeElement === d ? (r.preventDefault(), c.focus()) : !r.shiftKey && document.activeElement === c && (r.preventDefault(), d.focus());
|
|
78
|
+
};
|
|
79
|
+
e.addEventListener("keydown", o), e.__handleKeydown = o;
|
|
80
|
+
},
|
|
81
|
+
unmounted(e) {
|
|
82
|
+
e.__handleKeydown && (e.removeEventListener("keydown", e.__handleKeydown), delete e.__handleKeydown), e.__previousFocus && (setTimeout(() => {
|
|
83
|
+
if (e.__previousFocus && document.body.contains(e.__previousFocus) && typeof e.__previousFocus.focus == "function")
|
|
84
|
+
try {
|
|
85
|
+
e.__previousFocus.focus();
|
|
86
|
+
} catch (i) {
|
|
87
|
+
console.warn("Could not restore focus:", i);
|
|
88
|
+
}
|
|
89
|
+
}, 0), delete e.__previousFocus);
|
|
90
|
+
}
|
|
91
|
+
}, v = {
|
|
92
|
+
mounted(e, i) {
|
|
93
|
+
const t = i.value || {};
|
|
94
|
+
console.log("Keyboard directive mounted with config:", t);
|
|
95
|
+
const n = (a) => {
|
|
96
|
+
console.log("Key pressed:", a.key, "Config:", t);
|
|
97
|
+
const o = {
|
|
98
|
+
Enter: "enter",
|
|
99
|
+
" ": "space",
|
|
100
|
+
Escape: "escape",
|
|
101
|
+
ArrowUp: "arrowUp",
|
|
102
|
+
ArrowDown: "arrowDown",
|
|
103
|
+
ArrowLeft: "arrowLeft",
|
|
104
|
+
ArrowRight: "arrowRight",
|
|
105
|
+
Tab: "tab",
|
|
106
|
+
Delete: "delete",
|
|
107
|
+
Backspace: "backspace"
|
|
108
|
+
};
|
|
109
|
+
let r = "";
|
|
110
|
+
(a.ctrlKey || a.metaKey) && (r += "ctrl+"), a.altKey && (r += "alt+"), a.shiftKey && (r += "shift+"), r += a.key.toLowerCase();
|
|
111
|
+
const s = o[a.key];
|
|
112
|
+
if (s && typeof t[s] == "function") {
|
|
113
|
+
a.preventDefault(), t[s](a);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (t[r] && typeof t[r] == "function") {
|
|
117
|
+
a.preventDefault(), t[r](a);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (t[a.key] && typeof t[a.key] == "function") {
|
|
121
|
+
a.preventDefault(), t[a.key](a);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (t.arrows && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(a.key) && typeof t.arrows == "function") {
|
|
125
|
+
a.preventDefault(), t.arrows(a);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (t.handlers) {
|
|
129
|
+
if (t.handlers[a.key] && typeof t.handlers[a.key] == "function") {
|
|
130
|
+
a.preventDefault(), t.handlers[a.key](a);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (t.handlers[r] && typeof t.handlers[r] == "function") {
|
|
134
|
+
a.preventDefault(), t.handlers[r](a);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (t.custom && typeof t.custom == "function") {
|
|
139
|
+
t.custom(a);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
t.enter === !0 && a.key === "Enter" && !["INPUT", "TEXTAREA", "SELECT"].includes(a.target.tagName) && (a.preventDefault(), e.click && e.click()), t.space === !0 && a.key === " " && ["BUTTON", "A"].includes(e.tagName) && (a.preventDefault(), e.click && e.click());
|
|
143
|
+
};
|
|
144
|
+
e.addEventListener("keydown", n), e.__keyboardHandler = n;
|
|
145
|
+
},
|
|
146
|
+
unmounted(e) {
|
|
147
|
+
e.__keyboardHandler && (e.removeEventListener("keydown", e.__keyboardHandler), delete e.__keyboardHandler);
|
|
148
|
+
}
|
|
149
|
+
}, m = {
|
|
150
|
+
mounted(e, i) {
|
|
151
|
+
if (!i.value) return;
|
|
152
|
+
const t = typeof i.value == "string" ? { message: i.value, priority: "polite" } : i.value;
|
|
153
|
+
t && t.message && f(t.message, t.priority || "polite");
|
|
154
|
+
},
|
|
155
|
+
updated(e, i) {
|
|
156
|
+
if (i.value !== i.oldValue && i.value) {
|
|
157
|
+
const t = typeof i.value == "string" ? { message: i.value, priority: "polite" } : i.value;
|
|
158
|
+
t && t.message && f(t.message, t.priority || "polite");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}, _ = {
|
|
162
|
+
mounted(e, i) {
|
|
163
|
+
const t = i.value, n = (a) => {
|
|
164
|
+
a.preventDefault();
|
|
165
|
+
const o = document.querySelector(t);
|
|
166
|
+
o && (o.hasAttribute("tabindex") || o.setAttribute("tabindex", "-1"), o.focus(), o.scrollIntoView({ behavior: "smooth", block: "start" }));
|
|
167
|
+
};
|
|
168
|
+
e.addEventListener("click", n), e.__skipLinkHandler = n, e.setAttribute("role", "link"), t && e.setAttribute("aria-label", `Skip to ${t.replace("#", "")}`);
|
|
169
|
+
},
|
|
170
|
+
unmounted(e) {
|
|
171
|
+
e.__skipLinkHandler && (e.removeEventListener("click", e.__skipLinkHandler), delete e.__skipLinkHandler);
|
|
172
|
+
}
|
|
173
|
+
}, k = {
|
|
174
|
+
mounted(e, i) {
|
|
175
|
+
y(e, i);
|
|
176
|
+
},
|
|
177
|
+
updated(e, i) {
|
|
178
|
+
y(e, i);
|
|
179
|
+
},
|
|
180
|
+
unmounted(e) {
|
|
181
|
+
delete e.__a11ySkipOriginalTabIndex, delete e.__a11ySkipOriginalAriaHidden, delete e.__a11ySkipChildrenState;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
function y(e, i) {
|
|
185
|
+
if (i.value === void 0 ? !0 : !!i.value) {
|
|
186
|
+
e.__a11ySkipOriginalTabIndex === void 0 && (e.__a11ySkipOriginalTabIndex = e.getAttribute("tabindex")), e.__a11ySkipOriginalAriaHidden === void 0 && (e.__a11ySkipOriginalAriaHidden = e.getAttribute("aria-hidden")), e.setAttribute("tabindex", "-1"), e.setAttribute("aria-hidden", "true"), e.setAttribute("data-a11y-skip", "true");
|
|
187
|
+
const n = e.querySelectorAll(
|
|
188
|
+
'a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
189
|
+
);
|
|
190
|
+
e.__a11ySkipChildrenState || (e.__a11ySkipChildrenState = []), n.forEach((a, o) => {
|
|
191
|
+
e.__a11ySkipChildrenState[o] || (e.__a11ySkipChildrenState[o] = {
|
|
192
|
+
tabIndex: a.getAttribute("tabindex"),
|
|
193
|
+
disabled: a.disabled
|
|
194
|
+
}), a.setAttribute("tabindex", "-1"), "disabled" in a && (a.disabled = !0);
|
|
195
|
+
}), i.modifiers.noInteraction && (e.style.pointerEvents = "none"), i.modifiers.visual && (e.style.opacity = "0.5", e.style.filter = "grayscale(100%)", e.style.pointerEvents = "none");
|
|
196
|
+
} else {
|
|
197
|
+
e.__a11ySkipOriginalTabIndex !== void 0 ? e.__a11ySkipOriginalTabIndex === null ? e.removeAttribute("tabindex") : e.setAttribute("tabindex", e.__a11ySkipOriginalTabIndex) : e.removeAttribute("tabindex"), e.__a11ySkipOriginalAriaHidden !== void 0 ? e.__a11ySkipOriginalAriaHidden === null ? e.removeAttribute("aria-hidden") : e.setAttribute("aria-hidden", e.__a11ySkipOriginalAriaHidden) : e.removeAttribute("aria-hidden"), e.removeAttribute("data-a11y-skip");
|
|
198
|
+
const n = e.querySelectorAll(
|
|
199
|
+
"a, button, input, select, textarea, [tabindex]"
|
|
200
|
+
);
|
|
201
|
+
e.__a11ySkipChildrenState && n.forEach((a, o) => {
|
|
202
|
+
const r = e.__a11ySkipChildrenState[o];
|
|
203
|
+
r && (r.tabIndex === null ? a.removeAttribute("tabindex") : a.setAttribute("tabindex", r.tabIndex), "disabled" in a && (a.disabled = r.disabled));
|
|
204
|
+
}), i.modifiers.noInteraction && (e.style.pointerEvents = ""), i.modifiers.visual && (e.style.opacity = "", e.style.filter = "", e.style.pointerEvents = "");
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const h = {
|
|
208
|
+
mounted(e, i) {
|
|
209
|
+
const t = i.value || {}, n = {
|
|
210
|
+
label: "aria-label",
|
|
211
|
+
labelledby: "aria-labelledby",
|
|
212
|
+
describedby: "aria-describedby",
|
|
213
|
+
expanded: "aria-expanded",
|
|
214
|
+
pressed: "aria-pressed",
|
|
215
|
+
selected: "aria-selected",
|
|
216
|
+
checked: "aria-checked",
|
|
217
|
+
disabled: "aria-disabled",
|
|
218
|
+
hidden: "aria-hidden",
|
|
219
|
+
invalid: "aria-invalid",
|
|
220
|
+
required: "aria-required",
|
|
221
|
+
live: "aria-live",
|
|
222
|
+
atomic: "aria-atomic",
|
|
223
|
+
busy: "aria-busy",
|
|
224
|
+
controls: "aria-controls",
|
|
225
|
+
owns: "aria-owns",
|
|
226
|
+
haspopup: "aria-haspopup",
|
|
227
|
+
level: "aria-level",
|
|
228
|
+
modal: "aria-modal",
|
|
229
|
+
multiselectable: "aria-multiselectable",
|
|
230
|
+
orientation: "aria-orientation",
|
|
231
|
+
placeholder: "aria-placeholder",
|
|
232
|
+
readonly: "aria-readonly",
|
|
233
|
+
relevant: "aria-relevant",
|
|
234
|
+
valuemax: "aria-valuemax",
|
|
235
|
+
valuemin: "aria-valuemin",
|
|
236
|
+
valuenow: "aria-valuenow",
|
|
237
|
+
valuetext: "aria-valuetext"
|
|
238
|
+
}, a = {};
|
|
239
|
+
Object.entries(t).forEach(([o, r]) => {
|
|
240
|
+
const s = n[o] || o;
|
|
241
|
+
a[s] = r;
|
|
242
|
+
}), l(e, a), e.__ariaAttributes = Object.keys(a);
|
|
243
|
+
},
|
|
244
|
+
updated(e, i) {
|
|
245
|
+
if (JSON.stringify(i.value) !== JSON.stringify(i.oldValue)) {
|
|
246
|
+
e.__ariaAttributes && e.__ariaAttributes.forEach((o) => e.removeAttribute(o));
|
|
247
|
+
const t = i.value || {}, n = {
|
|
248
|
+
label: "aria-label",
|
|
249
|
+
labelledby: "aria-labelledby",
|
|
250
|
+
describedby: "aria-describedby",
|
|
251
|
+
expanded: "aria-expanded",
|
|
252
|
+
pressed: "aria-pressed",
|
|
253
|
+
selected: "aria-selected",
|
|
254
|
+
checked: "aria-checked",
|
|
255
|
+
disabled: "aria-disabled",
|
|
256
|
+
hidden: "aria-hidden",
|
|
257
|
+
invalid: "aria-invalid",
|
|
258
|
+
required: "aria-required",
|
|
259
|
+
live: "aria-live",
|
|
260
|
+
atomic: "aria-atomic",
|
|
261
|
+
busy: "aria-busy",
|
|
262
|
+
controls: "aria-controls",
|
|
263
|
+
owns: "aria-owns",
|
|
264
|
+
haspopup: "aria-haspopup",
|
|
265
|
+
level: "aria-level",
|
|
266
|
+
modal: "aria-modal"
|
|
267
|
+
}, a = {};
|
|
268
|
+
Object.entries(t).forEach(([o, r]) => {
|
|
269
|
+
const s = n[o] || o;
|
|
270
|
+
a[s] = r;
|
|
271
|
+
}), l(e, a), e.__ariaAttributes = Object.keys(a);
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
unmounted(e) {
|
|
275
|
+
e.__ariaAttributes && (e.__ariaAttributes.forEach((i) => e.removeAttribute(i)), delete e.__ariaAttributes);
|
|
276
|
+
}
|
|
277
|
+
}, A = {
|
|
278
|
+
"a11y-focus": p,
|
|
279
|
+
"a11y-trap-focus": b,
|
|
280
|
+
"a11y-keyboard": v,
|
|
281
|
+
"a11y-announce": m,
|
|
282
|
+
"a11y-skip-link": _,
|
|
283
|
+
"a11y-skip": k,
|
|
284
|
+
"a11y-aria": h
|
|
285
|
+
};
|
|
286
|
+
function g(e) {
|
|
287
|
+
Object.entries(A).forEach(([i, t]) => {
|
|
288
|
+
e.directive(i, t);
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
const F = {
|
|
292
|
+
install: g
|
|
293
|
+
};
|
|
294
|
+
export {
|
|
295
|
+
A as a11yDirectives,
|
|
296
|
+
f as announce,
|
|
297
|
+
m as announceDirective,
|
|
298
|
+
h as ariaDirective,
|
|
299
|
+
E as containsActiveElement,
|
|
300
|
+
F as default,
|
|
301
|
+
p as focusDirective,
|
|
302
|
+
O as generateId,
|
|
303
|
+
w as getFirstFocusable,
|
|
304
|
+
u as getFocusableElements,
|
|
305
|
+
x as getLastFocusable,
|
|
306
|
+
g as installA11yDirectives,
|
|
307
|
+
v as keyboardDirective,
|
|
308
|
+
S as removeAriaAttributes,
|
|
309
|
+
T as restoreFocus,
|
|
310
|
+
D as saveFocus,
|
|
311
|
+
l as setAriaAttributes,
|
|
312
|
+
k as skipDirective,
|
|
313
|
+
_ as skipLinkDirective,
|
|
314
|
+
b as trapFocusDirective
|
|
315
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(r,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(r=typeof globalThis<"u"?globalThis:r||self,d(r.VueA11yDirectives={}))})(this,function(r){"use strict";const d={mounted(e,a){const t=typeof a.value=="object"?a.value:{delay:a.value||0},o=t.delay||0,i=t.select||!1;setTimeout(()=>{e.focus&&(e.focus(),i&&(e.tagName==="INPUT"||e.tagName==="TEXTAREA")&&e.select())},o)}};function c(e){if(!e)return[];const a=["a[href]","button:not([disabled])","textarea:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])",'[tabindex]:not([tabindex="-1"])','[contenteditable="true"]',"audio[controls]","video[controls]"];return Array.from(e.querySelectorAll(a.join(", "))).filter(o=>{const i=window.getComputedStyle(o);return o.offsetWidth>0&&o.offsetHeight>0&&i.visibility!=="hidden"&&i.display!=="none"})}function l(e,a){Object.entries(a).forEach(([t,o])=>{o!=null&&e.setAttribute(t,o)})}function w(e,a){a.forEach(t=>{e.removeAttribute(t)})}function f(e,a="polite"){const t=document.createElement("div");t.setAttribute("role","status"),t.setAttribute("aria-live",a),t.setAttribute("aria-atomic","true"),t.style.position="absolute",t.style.left="-10000px",t.style.width="1px",t.style.height="1px",t.style.overflow="hidden",document.body.appendChild(t),setTimeout(()=>{t.textContent=e},100),setTimeout(()=>{document.body.removeChild(t)},3e3)}function E(e){const a=c(e);return a.length>0?a[0]:null}function D(e){const a=c(e);return a.length>0?a[a.length-1]:null}function F(e){return e.contains(document.activeElement)}function T(){return document.activeElement}function x(e){e&&e.focus&&e.focus()}function O(e="a11y"){return`${e}-${Math.random().toString(36).substr(2,9)}`}const y={mounted(e,a){const o=(a.value||{}).autoFocus!==!1,i=document.activeElement;e.__previousFocus=i,o&&setTimeout(()=>{const n=c(e);n.length>0&&n[0].focus()},100);const s=n=>{if(n.key!=="Tab")return;const u=c(e);if(u.length===0)return;const g=u[0],S=u[u.length-1];n.shiftKey&&document.activeElement===g?(n.preventDefault(),S.focus()):!n.shiftKey&&document.activeElement===S&&(n.preventDefault(),g.focus())};e.addEventListener("keydown",s),e.__handleKeydown=s},unmounted(e){e.__handleKeydown&&(e.removeEventListener("keydown",e.__handleKeydown),delete e.__handleKeydown),e.__previousFocus&&(setTimeout(()=>{if(e.__previousFocus&&document.body.contains(e.__previousFocus)&&typeof e.__previousFocus.focus=="function")try{e.__previousFocus.focus()}catch(a){console.warn("Could not restore focus:",a)}},0),delete e.__previousFocus)}},b={mounted(e,a){const t=a.value||{};console.log("Keyboard directive mounted with config:",t);const o=i=>{console.log("Key pressed:",i.key,"Config:",t);const s={Enter:"enter"," ":"space",Escape:"escape",ArrowUp:"arrowUp",ArrowDown:"arrowDown",ArrowLeft:"arrowLeft",ArrowRight:"arrowRight",Tab:"tab",Delete:"delete",Backspace:"backspace"};let n="";(i.ctrlKey||i.metaKey)&&(n+="ctrl+"),i.altKey&&(n+="alt+"),i.shiftKey&&(n+="shift+"),n+=i.key.toLowerCase();const u=s[i.key];if(u&&typeof t[u]=="function"){i.preventDefault(),t[u](i);return}if(t[n]&&typeof t[n]=="function"){i.preventDefault(),t[n](i);return}if(t[i.key]&&typeof t[i.key]=="function"){i.preventDefault(),t[i.key](i);return}if(t.arrows&&["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"].includes(i.key)&&typeof t.arrows=="function"){i.preventDefault(),t.arrows(i);return}if(t.handlers){if(t.handlers[i.key]&&typeof t.handlers[i.key]=="function"){i.preventDefault(),t.handlers[i.key](i);return}if(t.handlers[n]&&typeof t.handlers[n]=="function"){i.preventDefault(),t.handlers[n](i);return}}if(t.custom&&typeof t.custom=="function"){t.custom(i);return}t.enter===!0&&i.key==="Enter"&&!["INPUT","TEXTAREA","SELECT"].includes(i.target.tagName)&&(i.preventDefault(),e.click&&e.click()),t.space===!0&&i.key===" "&&["BUTTON","A"].includes(e.tagName)&&(i.preventDefault(),e.click&&e.click())};e.addEventListener("keydown",o),e.__keyboardHandler=o},unmounted(e){e.__keyboardHandler&&(e.removeEventListener("keydown",e.__keyboardHandler),delete e.__keyboardHandler)}},p={mounted(e,a){if(!a.value)return;const t=typeof a.value=="string"?{message:a.value,priority:"polite"}:a.value;t&&t.message&&f(t.message,t.priority||"polite")},updated(e,a){if(a.value!==a.oldValue&&a.value){const t=typeof a.value=="string"?{message:a.value,priority:"polite"}:a.value;t&&t.message&&f(t.message,t.priority||"polite")}}},v={mounted(e,a){const t=a.value,o=i=>{i.preventDefault();const s=document.querySelector(t);s&&(s.hasAttribute("tabindex")||s.setAttribute("tabindex","-1"),s.focus(),s.scrollIntoView({behavior:"smooth",block:"start"}))};e.addEventListener("click",o),e.__skipLinkHandler=o,e.setAttribute("role","link"),t&&e.setAttribute("aria-label",`Skip to ${t.replace("#","")}`)},unmounted(e){e.__skipLinkHandler&&(e.removeEventListener("click",e.__skipLinkHandler),delete e.__skipLinkHandler)}},m={mounted(e,a){_(e,a)},updated(e,a){_(e,a)},unmounted(e){delete e.__a11ySkipOriginalTabIndex,delete e.__a11ySkipOriginalAriaHidden,delete e.__a11ySkipChildrenState}};function _(e,a){if(a.value===void 0?!0:!!a.value){e.__a11ySkipOriginalTabIndex===void 0&&(e.__a11ySkipOriginalTabIndex=e.getAttribute("tabindex")),e.__a11ySkipOriginalAriaHidden===void 0&&(e.__a11ySkipOriginalAriaHidden=e.getAttribute("aria-hidden")),e.setAttribute("tabindex","-1"),e.setAttribute("aria-hidden","true"),e.setAttribute("data-a11y-skip","true");const o=e.querySelectorAll('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])');e.__a11ySkipChildrenState||(e.__a11ySkipChildrenState=[]),o.forEach((i,s)=>{e.__a11ySkipChildrenState[s]||(e.__a11ySkipChildrenState[s]={tabIndex:i.getAttribute("tabindex"),disabled:i.disabled}),i.setAttribute("tabindex","-1"),"disabled"in i&&(i.disabled=!0)}),a.modifiers.noInteraction&&(e.style.pointerEvents="none"),a.modifiers.visual&&(e.style.opacity="0.5",e.style.filter="grayscale(100%)",e.style.pointerEvents="none")}else{e.__a11ySkipOriginalTabIndex!==void 0?e.__a11ySkipOriginalTabIndex===null?e.removeAttribute("tabindex"):e.setAttribute("tabindex",e.__a11ySkipOriginalTabIndex):e.removeAttribute("tabindex"),e.__a11ySkipOriginalAriaHidden!==void 0?e.__a11ySkipOriginalAriaHidden===null?e.removeAttribute("aria-hidden"):e.setAttribute("aria-hidden",e.__a11ySkipOriginalAriaHidden):e.removeAttribute("aria-hidden"),e.removeAttribute("data-a11y-skip");const o=e.querySelectorAll("a, button, input, select, textarea, [tabindex]");e.__a11ySkipChildrenState&&o.forEach((i,s)=>{const n=e.__a11ySkipChildrenState[s];n&&(n.tabIndex===null?i.removeAttribute("tabindex"):i.setAttribute("tabindex",n.tabIndex),"disabled"in i&&(i.disabled=n.disabled))}),a.modifiers.noInteraction&&(e.style.pointerEvents=""),a.modifiers.visual&&(e.style.opacity="",e.style.filter="",e.style.pointerEvents="")}}const k={mounted(e,a){const t=a.value||{},o={label:"aria-label",labelledby:"aria-labelledby",describedby:"aria-describedby",expanded:"aria-expanded",pressed:"aria-pressed",selected:"aria-selected",checked:"aria-checked",disabled:"aria-disabled",hidden:"aria-hidden",invalid:"aria-invalid",required:"aria-required",live:"aria-live",atomic:"aria-atomic",busy:"aria-busy",controls:"aria-controls",owns:"aria-owns",haspopup:"aria-haspopup",level:"aria-level",modal:"aria-modal",multiselectable:"aria-multiselectable",orientation:"aria-orientation",placeholder:"aria-placeholder",readonly:"aria-readonly",relevant:"aria-relevant",valuemax:"aria-valuemax",valuemin:"aria-valuemin",valuenow:"aria-valuenow",valuetext:"aria-valuetext"},i={};Object.entries(t).forEach(([s,n])=>{const u=o[s]||s;i[u]=n}),l(e,i),e.__ariaAttributes=Object.keys(i)},updated(e,a){if(JSON.stringify(a.value)!==JSON.stringify(a.oldValue)){e.__ariaAttributes&&e.__ariaAttributes.forEach(s=>e.removeAttribute(s));const t=a.value||{},o={label:"aria-label",labelledby:"aria-labelledby",describedby:"aria-describedby",expanded:"aria-expanded",pressed:"aria-pressed",selected:"aria-selected",checked:"aria-checked",disabled:"aria-disabled",hidden:"aria-hidden",invalid:"aria-invalid",required:"aria-required",live:"aria-live",atomic:"aria-atomic",busy:"aria-busy",controls:"aria-controls",owns:"aria-owns",haspopup:"aria-haspopup",level:"aria-level",modal:"aria-modal"},i={};Object.entries(t).forEach(([s,n])=>{const u=o[s]||s;i[u]=n}),l(e,i),e.__ariaAttributes=Object.keys(i)}},unmounted(e){e.__ariaAttributes&&(e.__ariaAttributes.forEach(a=>e.removeAttribute(a)),delete e.__ariaAttributes)}},h={"a11y-focus":d,"a11y-trap-focus":y,"a11y-keyboard":b,"a11y-announce":p,"a11y-skip-link":v,"a11y-skip":m,"a11y-aria":k};function A(e){Object.entries(h).forEach(([a,t])=>{e.directive(a,t)})}const L={install:A};r.a11yDirectives=h,r.announce=f,r.announceDirective=p,r.ariaDirective=k,r.containsActiveElement=F,r.default=L,r.focusDirective=d,r.generateId=O,r.getFirstFocusable=E,r.getFocusableElements=c,r.getLastFocusable=D,r.installA11yDirectives=A,r.keyboardDirective=b,r.removeAriaAttributes=w,r.restoreFocus=x,r.saveFocus=T,r.setAriaAttributes=l,r.skipDirective=m,r.skipLinkDirective=v,r.trapFocusDirective=y,Object.defineProperties(r,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vue-a11y-directives",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A comprehensive set of Vue 3 directives for building accessible web applications with WCAG compliance",
|
|
5
|
+
"main": "dist/vue-a11y-directives.cjs.js",
|
|
6
|
+
"module": "dist/vue-a11y-directives.esm.js",
|
|
7
|
+
"unpkg": "dist/vue-a11y-directives.min.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"src"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"vue",
|
|
15
|
+
"vue3",
|
|
16
|
+
"accessibility",
|
|
17
|
+
"a11y",
|
|
18
|
+
"directives",
|
|
19
|
+
"wcag",
|
|
20
|
+
"aria",
|
|
21
|
+
"focus-management",
|
|
22
|
+
"keyboard-navigation",
|
|
23
|
+
"screen-reader"
|
|
24
|
+
],
|
|
25
|
+
"author": "Shkelqim Emerllahu",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/shkelqimemerllahu/vue-a11y-directives"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/shkelqimemerllahu/vue-a11y-directives/issues"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/shkelqimemerllahu/vue-a11y-directives#readme",
|
|
35
|
+
"scripts": {
|
|
36
|
+
"dev": "vite",
|
|
37
|
+
"build": "vite build",
|
|
38
|
+
"build:types": "tsc --declaration --emitDeclarationOnly --outDir dist",
|
|
39
|
+
"build:docs": "cd docs && npm run build",
|
|
40
|
+
"preview": "vite preview",
|
|
41
|
+
"docs:dev": "cd docs && npm run dev",
|
|
42
|
+
"lint": "eslint src --ext .js,.vue",
|
|
43
|
+
"prepublishOnly": "vite build"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"vue": "^3.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
50
|
+
"vite": "^5.0.0",
|
|
51
|
+
"vue": "^3.4.0"
|
|
52
|
+
},
|
|
53
|
+
"exports": {
|
|
54
|
+
".": {
|
|
55
|
+
"import": "./dist/vue-a11y-directives.esm.js",
|
|
56
|
+
"require": "./dist/vue-a11y-directives.cjs.js"
|
|
57
|
+
},
|
|
58
|
+
"./dist/style.css": "./dist/style.css"
|
|
59
|
+
}
|
|
60
|
+
}
|