📄 useLiveAnnouncer¶
📊 Analysis Summary¶
| Metric | Count |
|---|---|
| 🔧 Functions | 7 |
| 📦 Imports | 4 |
| 📊 Variables & Constants | 1 |
| 📐 Interfaces | 2 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 packages/core/useLiveAnnouncer/index.ts
📦 Imports¶
| Name | Source |
|---|---|
ConfigurableWindow |
../_configurable |
tryOnScopeDispose |
@vueuse/shared |
nextTick |
vue |
defaultWindow |
../_configurable |
Variables & Constants¶
| Name | Type | Kind | Value | Exported |
|---|---|---|---|---|
announcerMap |
Map<string, number> \| undefined |
let/var | *not shown* |
✗ |
Functions¶
useLiveAnnouncer(options: UseLiveAnnouncerOptions): UseLiveAnnouncerReturn¶
Parameters:
optionsUseLiveAnnouncerOptions
Returns: UseLiveAnnouncerReturn
Calls:
getAnnouncerMapmap.getmap.settryOnScopeDispose (from @vueuse/shared)timers.forEachwindow.clearTimeouttimers.clearcleanupdocument.getElementByIddocument.createElementdocument.body.appendChildpolite.setAttributecontainer.appendChildassertive.setAttributeensureAnnouncertimers.gettimers.deletenextTick (from vue)window.setTimeouttimers.setannounce
Internal Comments:
Code
export function useLiveAnnouncer(options: UseLiveAnnouncerOptions = {}): UseLiveAnnouncerReturn {
const {
idPrefix = 'vueuse-live-announcer',
window = defaultWindow,
} = options
const document = window?.document
const timers = new Map<'polite' | 'assertive', ReturnType<Window['setTimeout']>>()
if (window && document) {
const map = getAnnouncerMap()
const count = map.get(idPrefix) || 0
map.set(idPrefix, count + 1)
tryOnScopeDispose(() => {
timers.forEach(timer => window.clearTimeout(timer))
timers.clear()
cleanup(idPrefix, document)
})
}
function ensureAnnouncer() {
if (!document)
return
let container = document.getElementById(`${idPrefix}-container`)
if (!container) {
container = document.createElement('div')
container.id = `${idPrefix}-container`
container.style.position = 'absolute'
container.style.width = '1px'
container.style.height = '1px'
container.style.padding = '0'
container.style.margin = '-1px'
container.style.overflow = 'hidden'
container.style.clip = 'rect(0, 0, 0, 0)'
container.style.whiteSpace = 'nowrap'
container.style.border = '0'
container.style.wordWrap = 'normal'
container.style.clipPath = 'inset(50%)'
document.body.appendChild(container)
}
if (!document.getElementById(`${idPrefix}-polite`)) {
const polite = document.createElement('div')
polite.id = `${idPrefix}-polite`
polite.setAttribute('role', 'status')
polite.setAttribute('aria-live', 'polite')
polite.setAttribute('aria-atomic', 'true')
container.appendChild(polite)
}
if (!document.getElementById(`${idPrefix}-assertive`)) {
const assertive = document.createElement('div')
assertive.id = `${idPrefix}-assertive`
assertive.setAttribute('role', 'alert')
assertive.setAttribute('aria-live', 'assertive')
assertive.setAttribute('aria-atomic', 'true')
container.appendChild(assertive)
}
}
ensureAnnouncer()
function announce(message: string, mode: 'polite' | 'assertive' = 'polite', timeout?: number) {
if (!window || !document)
return
ensureAnnouncer()
const element = document.getElementById(`${idPrefix}-${mode}`)
if (element) {
// Cancel any pending auto-clear for this region so it can't wipe the new message.
const pending = timers.get(mode)
if (pending != null) {
window.clearTimeout(pending)
timers.delete(mode)
}
element.textContent = ''
nextTick(() => element.textContent = message)
if (timeout && timeout > 0) {
const timer = window.setTimeout(() => {
timers.delete(mode)
element.textContent = ''
}, timeout)
timers.set(mode, timer)
}
}
}
function polite(message: string, timeout?: number) {
announce(message, 'polite', timeout)
}
function assertive(message: string, timeout?: number) {
announce(message, 'assertive', timeout)
}
return {
announce,
polite,
assertive,
}
}
getAnnouncerMap(): Map<string, number>¶
Returns: Map<string, number>
cleanup(idPrefix: string, document: Document): void¶
Parameters:
idPrefixstringdocumentDocument
Returns: void
Calls:
getAnnouncerMapmap.getdocument.getElementByIdcontainer.removemap.deletemap.set
Code
function cleanup(idPrefix: string, document: Document) {
const map = getAnnouncerMap()
const count = map.get(idPrefix) || 0
if (count <= 1) {
const container = document.getElementById(`${idPrefix}-container`)
if (container) {
container.remove()
}
map.delete(idPrefix)
}
else {
map.set(idPrefix, count - 1)
}
}
Internal helpers¶
Declared inside another function in this file.
ensureAnnouncer(): void¶
Returns: void
Calls:
document.getElementByIddocument.createElementdocument.body.appendChildpolite.setAttributecontainer.appendChildassertive.setAttribute
Code
function ensureAnnouncer() {
if (!document)
return
let container = document.getElementById(`${idPrefix}-container`)
if (!container) {
container = document.createElement('div')
container.id = `${idPrefix}-container`
container.style.position = 'absolute'
container.style.width = '1px'
container.style.height = '1px'
container.style.padding = '0'
container.style.margin = '-1px'
container.style.overflow = 'hidden'
container.style.clip = 'rect(0, 0, 0, 0)'
container.style.whiteSpace = 'nowrap'
container.style.border = '0'
container.style.wordWrap = 'normal'
container.style.clipPath = 'inset(50%)'
document.body.appendChild(container)
}
if (!document.getElementById(`${idPrefix}-polite`)) {
const polite = document.createElement('div')
polite.id = `${idPrefix}-polite`
polite.setAttribute('role', 'status')
polite.setAttribute('aria-live', 'polite')
polite.setAttribute('aria-atomic', 'true')
container.appendChild(polite)
}
if (!document.getElementById(`${idPrefix}-assertive`)) {
const assertive = document.createElement('div')
assertive.id = `${idPrefix}-assertive`
assertive.setAttribute('role', 'alert')
assertive.setAttribute('aria-live', 'assertive')
assertive.setAttribute('aria-atomic', 'true')
container.appendChild(assertive)
}
}
announce(message: string, mode: 'polite' | 'assertive', timeout: number): void¶
Parameters:
messagestringmode'polite' | 'assertive'timeoutnumber
Returns: void
Calls:
ensureAnnouncerdocument.getElementByIdtimers.getwindow.clearTimeouttimers.deletenextTick (from vue)window.setTimeouttimers.set
Internal Comments:
Code
function announce(message: string, mode: 'polite' | 'assertive' = 'polite', timeout?: number) {
if (!window || !document)
return
ensureAnnouncer()
const element = document.getElementById(`${idPrefix}-${mode}`)
if (element) {
// Cancel any pending auto-clear for this region so it can't wipe the new message.
const pending = timers.get(mode)
if (pending != null) {
window.clearTimeout(pending)
timers.delete(mode)
}
element.textContent = ''
nextTick(() => element.textContent = message)
if (timeout && timeout > 0) {
const timer = window.setTimeout(() => {
timers.delete(mode)
element.textContent = ''
}, timeout)
timers.set(mode, timer)
}
}
}
polite(message: string, timeout: number): void¶
Parameters:
messagestringtimeoutnumber
Returns: void
Calls:
announce
assertive(message: string, timeout: number): void¶
Parameters:
messagestringtimeoutnumber
Returns: void
Calls:
announce
Code
Interfaces¶
UseLiveAnnouncerOptions¶
Interface Code
Properties¶
| Name | Type | Optional | Description |
|---|---|---|---|
idPrefix |
string |
✓ | not shown |
UseLiveAnnouncerReturn¶
Interface Code
Properties¶
| Name | Type | Optional | Description |
|---|---|---|---|
announce |
(message: string, mode?: 'polite' \| 'assertive', timeout?: number) => void |
✗ | not shown |
polite |
(message: string, timeout?: number) => void |
✗ | not shown |
assertive |
(message: string, timeout?: number) => void |
✗ | not shown |
Generated by Syntax Scribe