Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@primer/live-region-element

Package Overview
Dependencies
Maintainers
11
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@primer/live-region-element - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0

dist/cjs/MinHeap.d.cts

4

dist/esm/index.d.ts

@@ -18,3 +18,3 @@ import './define';

*/
export declare function announce(message: string, options?: GlobalAnnounceOptions): void;
export declare function announce(message: string, options?: GlobalAnnounceOptions): () => void;
/**

@@ -24,3 +24,3 @@ * Announce a message using the text content of an element using a live region

*/
export declare function announceFromElement(element: HTMLElement, options?: GlobalAnnounceOptions): void;
export declare function announceFromElement(element: HTMLElement, options?: GlobalAnnounceOptions): () => void;
export { LiveRegionElement, templateContent };

@@ -0,4 +1,198 @@

const Ordering = {
Less: "less",
Equal: "equal",
Greater: "greater"
};
var __accessCheck$1 = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet$1 = (obj, member, getter) => {
__accessCheck$1(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd$1 = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateSet$1 = (obj, member, value, setter) => {
__accessCheck$1(obj, member, "write to private field");
setter ? setter.call(obj, value) : member.set(obj, value);
return value;
};
var __privateMethod = (obj, member, method) => {
__accessCheck$1(obj, member, "access private method");
return method;
};
var _compareFn, _heap, _heapifyDown, heapifyDown_fn, _heapifyUp, heapifyUp_fn;
class MinHeap {
constructor({ compareFn }) {
__privateAdd$1(this, _heapifyDown);
__privateAdd$1(this, _heapifyUp);
__privateAdd$1(this, _compareFn, void 0);
__privateAdd$1(this, _heap, void 0);
__privateSet$1(this, _compareFn, compareFn);
__privateSet$1(this, _heap, []);
}
insert(value) {
__privateGet$1(this, _heap).push(value);
__privateMethod(this, _heapifyUp, heapifyUp_fn).call(this);
}
pop() {
const item = __privateGet$1(this, _heap)[0];
if (__privateGet$1(this, _heap)[__privateGet$1(this, _heap).length - 1]) {
__privateGet$1(this, _heap)[0] = __privateGet$1(this, _heap)[__privateGet$1(this, _heap).length - 1];
__privateGet$1(this, _heap).pop();
}
__privateMethod(this, _heapifyDown, heapifyDown_fn).call(this);
return item;
}
peek() {
return __privateGet$1(this, _heap)[0];
}
delete(value) {
const index = __privateGet$1(this, _heap).indexOf(value);
if (index === -1) {
return;
}
swap(__privateGet$1(this, _heap), index, __privateGet$1(this, _heap).length - 1);
__privateGet$1(this, _heap).pop();
__privateMethod(this, _heapifyDown, heapifyDown_fn).call(this);
}
clear() {
__privateSet$1(this, _heap, []);
}
get size() {
return __privateGet$1(this, _heap).length;
}
}
_compareFn = new WeakMap();
_heap = new WeakMap();
_heapifyDown = new WeakSet();
heapifyDown_fn = function() {
let index = 0;
while (hasLeftChild(index, __privateGet$1(this, _heap).length)) {
let smallerChildIndex = getLeftChildIndex(index);
if (hasRightChild(index, __privateGet$1(this, _heap).length) && __privateGet$1(this, _compareFn).call(this, rightChild(__privateGet$1(this, _heap), index), leftChild(__privateGet$1(this, _heap), index)) === Ordering.Less) {
smallerChildIndex = getRightChildIndex(index);
}
if (__privateGet$1(this, _compareFn).call(this, __privateGet$1(this, _heap)[index], __privateGet$1(this, _heap)[smallerChildIndex]) === Ordering.Less) {
break;
} else {
swap(__privateGet$1(this, _heap), index, smallerChildIndex);
}
index = smallerChildIndex;
}
};
_heapifyUp = new WeakSet();
heapifyUp_fn = function() {
let index = __privateGet$1(this, _heap).length - 1;
while (hasParent(index) && __privateGet$1(this, _compareFn).call(this, __privateGet$1(this, _heap)[index], parent(__privateGet$1(this, _heap), index)) === Ordering.Less) {
swap(__privateGet$1(this, _heap), index, getParentIndex(index));
index = getParentIndex(index);
}
};
function getLeftChildIndex(index) {
return 2 * index + 1;
}
function getRightChildIndex(index) {
return 2 * index + 2;
}
function getParentIndex(index) {
return Math.floor((index - 1) / 2);
}
function hasLeftChild(index, size) {
return getLeftChildIndex(index) < size;
}
function hasRightChild(index, size) {
return getRightChildIndex(index) < size;
}
function hasParent(index) {
return index > 0;
}
function leftChild(heap, index) {
return heap[getLeftChildIndex(index)];
}
function rightChild(heap, index) {
return heap[getRightChildIndex(index)];
}
function parent(heap, index) {
return heap[getParentIndex(index)];
}
function swap(heap, a, b) {
const tmp = heap[a];
heap[a] = heap[b];
heap[b] = tmp;
}
function throttle(fn, wait) {
const queue = [];
let timeoutId = null;
function processQueue() {
if (timeoutId !== null) {
return;
}
if (queue.length === 0) {
return;
}
const args = queue.shift();
if (args === void 0) {
return;
}
fn(...args);
timeoutId = window.setTimeout(() => {
timeoutId = null;
processQueue();
}, wait);
}
function throttled(...args) {
queue.push(args);
if (timeoutId === null) {
processQueue();
}
}
throttled.cancel = () => {
if (timeoutId !== null) {
clearTimeout(timeoutId);
timeoutId = null;
}
queue.length = 0;
};
return throttled;
}
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
var __accessCheck = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet = (obj, member, getter) => {
__accessCheck(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateSet = (obj, member, value, setter) => {
__accessCheck(obj, member, "write to private field");
setter ? setter.call(obj, value) : member.set(obj, value);
return value;
};
var _queue, _timeoutId;
const DEFAULT_THROTTLE_DELAY_MS = 500;
class LiveRegionElement extends HTMLElement {
constructor() {
constructor({ waitMs } = {}) {
super();
__privateAdd(this, _queue, void 0);
__privateAdd(this, _timeoutId, void 0);
__publicField(this, "updateContainerWithMessage");
if (!this.shadowRoot) {

@@ -9,2 +203,18 @@ const template2 = getTemplate();

}
__privateSet(this, _timeoutId, null);
__privateSet(this, _queue, new MinHeap({
compareFn: compareMessages
}));
this.updateContainerWithMessage = throttle((message) => {
const { contents, politeness } = message;
const container = this.shadowRoot?.getElementById(politeness);
if (!container) {
throw new Error(`Unable to find container for message. Expected a container with id="${politeness}"`);
}
if (container.textContent === contents) {
container.textContent = `${contents}\xA0`;
} else {
container.textContent = contents;
}
}, waitMs ?? DEFAULT_THROTTLE_DELAY_MS);
}

@@ -14,21 +224,15 @@ /**

* level.
*
* Note: a politeness level of `assertive` should only be used for
* time-sensistive or critical notifications that absolutely require the
* user's immediate attention
*
* @see https://www.w3.org/TR/wai-aria/#aria-live
* @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions
*/
announce(message, options = {}) {
const { politeness = "polite" } = options;
const container = this.shadowRoot?.getElementById(politeness);
if (!container) {
throw new Error("Unable to find container for message");
}
if (container.textContent === message) {
container.textContent = `${message}\xA0`;
} else {
container.textContent = message;
}
const { delayMs, politeness = "polite" } = options;
const item = {
politeness,
contents: message,
scheduled: delayMs !== void 0 ? Date.now() + delayMs : "immediate"
};
__privateGet(this, _queue).insert(item);
this.performWork();
return () => {
__privateGet(this, _queue).delete(item);
};
}

@@ -42,5 +246,38 @@ /**

if (textContent !== "") {
this.announce(textContent, options);
return this.announce(textContent, options);
}
return noop;
}
performWork() {
let message = __privateGet(this, _queue).peek();
if (!message) {
return;
}
if (__privateGet(this, _timeoutId) !== null) {
clearTimeout(__privateGet(this, _timeoutId));
__privateSet(this, _timeoutId, null);
}
if (message.scheduled === "immediate") {
message = __privateGet(this, _queue).pop();
if (message) {
this.updateContainerWithMessage(message);
}
this.performWork();
return;
}
const now = Date.now();
if (message.scheduled <= now) {
message = __privateGet(this, _queue).pop();
if (message) {
this.updateContainerWithMessage(message);
}
this.performWork();
return;
}
const timeout = message.scheduled > now ? message.scheduled - now : 0;
__privateSet(this, _timeoutId, window.setTimeout(() => {
__privateSet(this, _timeoutId, null);
this.performWork();
}, timeout));
}
getMessage(politeness = "polite") {

@@ -53,3 +290,16 @@ const container = this.shadowRoot?.getElementById(politeness);

}
/**
* Stop any pending messages from being announced by the live region
*/
clear() {
if (__privateGet(this, _timeoutId) !== null) {
clearTimeout(__privateGet(this, _timeoutId));
__privateSet(this, _timeoutId, null);
}
this.updateContainerWithMessage.cancel();
__privateGet(this, _queue).clear();
}
}
_queue = new WeakMap();
_timeoutId = new WeakMap();
function getTextContent(element) {

@@ -89,2 +339,19 @@ let value = "";

}
function compareMessages(a, b) {
if (a.scheduled === b.scheduled) {
return Ordering.Equal;
}
if (a.scheduled === "immediate" && b.scheduled !== "immediate") {
return Ordering.Less;
}
if (a.scheduled !== "immediate" && b.scheduled === "immediate") {
return Ordering.Greater;
}
if (a.scheduled < b.scheduled) {
return Ordering.Less;
}
return Ordering.Greater;
}
function noop() {
}

@@ -91,0 +358,0 @@ if (!customElements.get("live-region")) {

@@ -0,9 +1,10 @@

import { type Throttle } from './throttle';
type Politeness = 'polite' | 'assertive';
type AnnounceOptions = {
politeness?: 'polite' | 'assertive';
};
declare class LiveRegionElement extends HTMLElement {
constructor();
/**
* Announce a message using a live region with a corresponding politeness
* level.
* A delay in milliseconds to wait before announcing a message.
*/
delayMs?: number;
/**
* The politeness level for a message.
*

@@ -17,9 +18,35 @@ * Note: a politeness level of `assertive` should only be used for

*/
announce(message: string, options?: AnnounceOptions): void;
politeness?: Politeness;
};
type Message = {
contents: string;
politeness: Politeness;
scheduled: number | 'immediate';
};
/**
* A function to cancel a scheduled message.
*/
type Cancel = () => void;
declare class LiveRegionElement extends HTMLElement {
#private;
updateContainerWithMessage: Throttle<(message: Message) => void>;
constructor({ waitMs }?: {
waitMs?: number;
});
/**
* Announce a message using a live region with a corresponding politeness
* level.
*/
announce(message: string, options?: AnnounceOptions): Cancel;
/**
* Announce a message using the text content of an element with a
* corresponding politeness level
*/
announceFromElement(element: HTMLElement, options?: AnnounceOptions): void;
announceFromElement(element: HTMLElement, options?: AnnounceOptions): Cancel;
performWork(): void;
getMessage(politeness?: AnnounceOptions['politeness']): string | null;
/**
* Stop any pending messages from being announced by the live region
*/
clear(): void;
}

@@ -26,0 +53,0 @@ declare const templateContent = "\n<style>\n:host {\n clip-path: inset(50%);\n height: 1px;\n overflow: hidden;\n position: absolute;\n white-space: nowrap;\n width: 1px;\n}\n</style>\n<div id=\"polite\" aria-live=\"polite\" aria-atomic=\"true\"></div>\n<div id=\"assertive\" aria-live=\"assertive\" aria-atomic=\"true\"></div>\n";

import { HTMLElement, customElements } from '@lit-labs/ssr-dom-shim';
const Ordering = {
Less: "less",
Equal: "equal",
Greater: "greater"
};
var __accessCheck$1 = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet$1 = (obj, member, getter) => {
__accessCheck$1(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd$1 = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateSet$1 = (obj, member, value, setter) => {
__accessCheck$1(obj, member, "write to private field");
setter ? setter.call(obj, value) : member.set(obj, value);
return value;
};
var __privateMethod = (obj, member, method) => {
__accessCheck$1(obj, member, "access private method");
return method;
};
var _compareFn, _heap, _heapifyDown, heapifyDown_fn, _heapifyUp, heapifyUp_fn;
class MinHeap {
constructor({ compareFn }) {
__privateAdd$1(this, _heapifyDown);
__privateAdd$1(this, _heapifyUp);
__privateAdd$1(this, _compareFn, void 0);
__privateAdd$1(this, _heap, void 0);
__privateSet$1(this, _compareFn, compareFn);
__privateSet$1(this, _heap, []);
}
insert(value) {
__privateGet$1(this, _heap).push(value);
__privateMethod(this, _heapifyUp, heapifyUp_fn).call(this);
}
pop() {
const item = __privateGet$1(this, _heap)[0];
if (__privateGet$1(this, _heap)[__privateGet$1(this, _heap).length - 1]) {
__privateGet$1(this, _heap)[0] = __privateGet$1(this, _heap)[__privateGet$1(this, _heap).length - 1];
__privateGet$1(this, _heap).pop();
}
__privateMethod(this, _heapifyDown, heapifyDown_fn).call(this);
return item;
}
peek() {
return __privateGet$1(this, _heap)[0];
}
delete(value) {
const index = __privateGet$1(this, _heap).indexOf(value);
if (index === -1) {
return;
}
swap(__privateGet$1(this, _heap), index, __privateGet$1(this, _heap).length - 1);
__privateGet$1(this, _heap).pop();
__privateMethod(this, _heapifyDown, heapifyDown_fn).call(this);
}
clear() {
__privateSet$1(this, _heap, []);
}
get size() {
return __privateGet$1(this, _heap).length;
}
}
_compareFn = new WeakMap();
_heap = new WeakMap();
_heapifyDown = new WeakSet();
heapifyDown_fn = function() {
let index = 0;
while (hasLeftChild(index, __privateGet$1(this, _heap).length)) {
let smallerChildIndex = getLeftChildIndex(index);
if (hasRightChild(index, __privateGet$1(this, _heap).length) && __privateGet$1(this, _compareFn).call(this, rightChild(__privateGet$1(this, _heap), index), leftChild(__privateGet$1(this, _heap), index)) === Ordering.Less) {
smallerChildIndex = getRightChildIndex(index);
}
if (__privateGet$1(this, _compareFn).call(this, __privateGet$1(this, _heap)[index], __privateGet$1(this, _heap)[smallerChildIndex]) === Ordering.Less) {
break;
} else {
swap(__privateGet$1(this, _heap), index, smallerChildIndex);
}
index = smallerChildIndex;
}
};
_heapifyUp = new WeakSet();
heapifyUp_fn = function() {
let index = __privateGet$1(this, _heap).length - 1;
while (hasParent(index) && __privateGet$1(this, _compareFn).call(this, __privateGet$1(this, _heap)[index], parent(__privateGet$1(this, _heap), index)) === Ordering.Less) {
swap(__privateGet$1(this, _heap), index, getParentIndex(index));
index = getParentIndex(index);
}
};
function getLeftChildIndex(index) {
return 2 * index + 1;
}
function getRightChildIndex(index) {
return 2 * index + 2;
}
function getParentIndex(index) {
return Math.floor((index - 1) / 2);
}
function hasLeftChild(index, size) {
return getLeftChildIndex(index) < size;
}
function hasRightChild(index, size) {
return getRightChildIndex(index) < size;
}
function hasParent(index) {
return index > 0;
}
function leftChild(heap, index) {
return heap[getLeftChildIndex(index)];
}
function rightChild(heap, index) {
return heap[getRightChildIndex(index)];
}
function parent(heap, index) {
return heap[getParentIndex(index)];
}
function swap(heap, a, b) {
const tmp = heap[a];
heap[a] = heap[b];
heap[b] = tmp;
}
function throttle(fn, wait) {
const queue = [];
let timeoutId = null;
function processQueue() {
if (timeoutId !== null) {
return;
}
if (queue.length === 0) {
return;
}
const args = queue.shift();
if (args === void 0) {
return;
}
fn(...args);
timeoutId = window.setTimeout(() => {
timeoutId = null;
processQueue();
}, wait);
}
function throttled(...args) {
queue.push(args);
if (timeoutId === null) {
processQueue();
}
}
throttled.cancel = () => {
if (timeoutId !== null) {
clearTimeout(timeoutId);
timeoutId = null;
}
queue.length = 0;
};
return throttled;
}
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
var __accessCheck = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet = (obj, member, getter) => {
__accessCheck(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateSet = (obj, member, value, setter) => {
__accessCheck(obj, member, "write to private field");
setter ? setter.call(obj, value) : member.set(obj, value);
return value;
};
var _queue, _timeoutId;
const DEFAULT_THROTTLE_DELAY_MS = 500;
class LiveRegionElement extends (globalThis.HTMLElement ?? HTMLElement) {
constructor() {
constructor({ waitMs } = {}) {
super();
__privateAdd(this, _queue, void 0);
__privateAdd(this, _timeoutId, void 0);
__publicField(this, "updateContainerWithMessage");
if (!this.shadowRoot) {

@@ -11,2 +205,18 @@ const template2 = getTemplate();

}
__privateSet(this, _timeoutId, null);
__privateSet(this, _queue, new MinHeap({
compareFn: compareMessages
}));
this.updateContainerWithMessage = throttle((message) => {
const { contents, politeness } = message;
const container = this.shadowRoot?.getElementById(politeness);
if (!container) {
throw new Error(`Unable to find container for message. Expected a container with id="${politeness}"`);
}
if (container.textContent === contents) {
container.textContent = `${contents}\xA0`;
} else {
container.textContent = contents;
}
}, waitMs ?? DEFAULT_THROTTLE_DELAY_MS);
}

@@ -16,21 +226,15 @@ /**

* level.
*
* Note: a politeness level of `assertive` should only be used for
* time-sensistive or critical notifications that absolutely require the
* user's immediate attention
*
* @see https://www.w3.org/TR/wai-aria/#aria-live
* @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions
*/
announce(message, options = {}) {
const { politeness = "polite" } = options;
const container = this.shadowRoot?.getElementById(politeness);
if (!container) {
throw new Error("Unable to find container for message");
}
if (container.textContent === message) {
container.textContent = `${message}\xA0`;
} else {
container.textContent = message;
}
const { delayMs, politeness = "polite" } = options;
const item = {
politeness,
contents: message,
scheduled: delayMs !== void 0 ? Date.now() + delayMs : "immediate"
};
__privateGet(this, _queue).insert(item);
this.performWork();
return () => {
__privateGet(this, _queue).delete(item);
};
}

@@ -44,5 +248,38 @@ /**

if (textContent !== "") {
this.announce(textContent, options);
return this.announce(textContent, options);
}
return noop;
}
performWork() {
let message = __privateGet(this, _queue).peek();
if (!message) {
return;
}
if (__privateGet(this, _timeoutId) !== null) {
clearTimeout(__privateGet(this, _timeoutId));
__privateSet(this, _timeoutId, null);
}
if (message.scheduled === "immediate") {
message = __privateGet(this, _queue).pop();
if (message) {
this.updateContainerWithMessage(message);
}
this.performWork();
return;
}
const now = Date.now();
if (message.scheduled <= now) {
message = __privateGet(this, _queue).pop();
if (message) {
this.updateContainerWithMessage(message);
}
this.performWork();
return;
}
const timeout = message.scheduled > now ? message.scheduled - now : 0;
__privateSet(this, _timeoutId, window.setTimeout(() => {
__privateSet(this, _timeoutId, null);
this.performWork();
}, timeout));
}
getMessage(politeness = "polite") {

@@ -55,3 +292,16 @@ const container = this.shadowRoot?.getElementById(politeness);

}
/**
* Stop any pending messages from being announced by the live region
*/
clear() {
if (__privateGet(this, _timeoutId) !== null) {
clearTimeout(__privateGet(this, _timeoutId));
__privateSet(this, _timeoutId, null);
}
this.updateContainerWithMessage.cancel();
__privateGet(this, _queue).clear();
}
}
_queue = new WeakMap();
_timeoutId = new WeakMap();
function getTextContent(element) {

@@ -91,2 +341,19 @@ let value = "";

}
function compareMessages(a, b) {
if (a.scheduled === b.scheduled) {
return Ordering.Equal;
}
if (a.scheduled === "immediate" && b.scheduled !== "immediate") {
return Ordering.Less;
}
if (a.scheduled !== "immediate" && b.scheduled === "immediate") {
return Ordering.Greater;
}
if (a.scheduled < b.scheduled) {
return Ordering.Less;
}
return Ordering.Greater;
}
function noop() {
}

@@ -93,0 +360,0 @@ if (!customElements.get("live-region")) {

{
"name": "@primer/live-region-element",
"version": "0.2.0",
"version": "0.3.0",
"type": "module",

@@ -47,3 +47,3 @@ "main": "./dist/esm/index.js",

"devDependencies": {
"@custom-elements-manifest/analyzer": "^0.9.2",
"@custom-elements-manifest/analyzer": "^0.9.3",
"@rollup/plugin-inject": "^5.0.5",

@@ -56,3 +56,3 @@ "@rollup/plugin-replace": "^5.0.5",

"rollup-plugin-typescript2": "^0.36.0",
"typescript": "^5.3.3"
"typescript": "^5.4.3"
},

@@ -59,0 +59,0 @@ "sideEffects": [

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc