@aria-ui/core
Advanced tools
Comparing version 0.0.2 to 0.0.4
@@ -1,5 +0,93 @@ | ||
export { BaseElement } from "./base-element"; | ||
export { type ReadonlySignal, type Signal, batch, createComputed, createDeferComputed, createEffect, createSignal, untracked, } from "./signals"; | ||
export { SingalElement, defineSingalProperties } from "./singal-element"; | ||
export { type SingalState, mapStateSignals, mapStateValues, } from "./singal-state"; | ||
//# sourceMappingURL=index.d.ts.map | ||
import { Signal } from '@preact/signals-core'; | ||
export { ReadonlySignal, Signal, batch, computed as createComputed, signal as createSignal, untracked } from '@preact/signals-core'; | ||
import { AriaAttributes } from '@dddstack/ariatype-aria-attributes'; | ||
import { AriaRole } from '@dddstack/ariatype-aria-roles'; | ||
/** | ||
* Any HTML element that has implemented the `addConnectedCallback` method. | ||
*/ | ||
interface ConnectableElement extends HTMLElement { | ||
/** | ||
* Registers a callback to be called when the element is connected to the DOM. | ||
* This callback can return a cleanup function that will be called when the | ||
* element is disconnected from the DOM. | ||
*/ | ||
addConnectedCallback: (callback: () => VoidFunction | void) => void; | ||
} | ||
/** | ||
* Base class for all custom elements in Aria UI. It implements the | ||
* {@link ConnectableElement} interface. | ||
*/ | ||
declare class BaseElement extends HTMLElement implements ConnectableElement { | ||
private _connectedCallbacks; | ||
private _disconnectedCallback; | ||
private _connected; | ||
/** | ||
* @hidden | ||
*/ | ||
connectedCallback(): void; | ||
/** | ||
* @hidden | ||
*/ | ||
disconnectedCallback(): void; | ||
/** | ||
* @hidden | ||
*/ | ||
adoptedCallback(): void; | ||
/** | ||
* @hidden | ||
*/ | ||
addConnectedCallback(callback: () => VoidFunction | void): void; | ||
} | ||
declare function useEffect(element: ConnectableElement, callback: () => VoidFunction | void): () => void; | ||
type SignalValue<S> = S extends Signal<infer T> ? T : never; | ||
/** | ||
* A context is a way to provide and consume signals in a HTML tree. | ||
*/ | ||
interface Context<S extends Signal> { | ||
/** | ||
* Provides a signal to all children of the element. | ||
* @param element The element to provide the signal to. | ||
* @param signal The signal to provide. | ||
*/ | ||
provide(element: ConnectableElement, signal: S): void; | ||
/** | ||
* Receives the signal from a parent element. | ||
* @param element The element to consume the signal from. | ||
* @returns The signal or undefined if the signal is not provided. | ||
*/ | ||
consume(element: ConnectableElement): S | undefined; | ||
} | ||
/** | ||
* Creates a new context. | ||
*/ | ||
declare function createContext<S extends Signal>(key: string | symbol): Context<S>; | ||
declare function useEventListener<K extends keyof HTMLElementEventMap>(element: ConnectableElement, type: K, listener: (event: HTMLElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions): void; | ||
declare function useStyle<K extends keyof CSSStyleDeclaration>(element: ConnectableElement, key: K, compute: () => CSSStyleDeclaration[K]): () => void; | ||
declare function useAttribute(element: ConnectableElement, key: string, compute: () => string | number | undefined): () => void; | ||
declare function useAriaAttribute<K extends keyof AriaAttributes>(element: ConnectableElement, key: K, compute: () => AriaAttributes[K]): () => void; | ||
declare function useAriaRole(element: ConnectableElement, compute: () => AriaRole | undefined): () => void; | ||
/** | ||
* Merge two objects, with the second object taking precedence. Only keys | ||
* present in the first object will be included in the result. | ||
*/ | ||
declare function assignProps<T extends object>(defaultProps: Readonly<T>, props?: Partial<T>): Readonly<T>; | ||
type SingalState<T extends object> = { | ||
[K in keyof T]: Signal<T[K]>; | ||
}; | ||
/** | ||
* Maps every signal in the given object to its current value. | ||
*/ | ||
declare function mapValues<T extends object>(signals: SingalState<T>): T; | ||
/** | ||
* Maps every value in the given object to a signal. | ||
*/ | ||
declare function mapSignals<T extends object>(values: T): SingalState<T>; | ||
export { BaseElement, type ConnectableElement, type Context, type SignalValue, type SingalState, assignProps, createContext, mapSignals, mapValues, useAriaAttribute, useAriaRole, useAttribute, useEffect, useEventListener, useStyle }; |
@@ -1,4 +0,195 @@ | ||
export { BaseElement } from "./base-element"; | ||
export { batch, createComputed, createDeferComputed, createEffect, createSignal, untracked, } from "./signals"; | ||
export { SingalElement, defineSingalProperties } from "./singal-element"; | ||
export { mapStateSignals, mapStateValues, } from "./singal-state"; | ||
// src/base-element.ts | ||
var BaseElement = class extends HTMLElement { | ||
constructor() { | ||
super(...arguments); | ||
this._connectedCallbacks = []; | ||
this._disconnectedCallback = []; | ||
this._connected = false; | ||
} | ||
/** | ||
* @hidden | ||
*/ | ||
connectedCallback() { | ||
this._connected = true; | ||
for (const callback of this._connectedCallbacks) { | ||
const dispose = callback(); | ||
if (dispose) { | ||
this._disconnectedCallback.push(dispose); | ||
} | ||
} | ||
} | ||
/** | ||
* @hidden | ||
*/ | ||
disconnectedCallback() { | ||
this._connected = false; | ||
for (const callback of this._disconnectedCallback) { | ||
callback(); | ||
} | ||
this._disconnectedCallback = []; | ||
} | ||
/** | ||
* @hidden | ||
*/ | ||
adoptedCallback() { | ||
this.disconnectedCallback(); | ||
this.connectedCallback(); | ||
} | ||
/** | ||
* @hidden | ||
*/ | ||
addConnectedCallback(callback) { | ||
this._connectedCallbacks.push(callback); | ||
if (!this._connected) { | ||
return; | ||
} | ||
const dispose = callback(); | ||
if (dispose) { | ||
this._disconnectedCallback.push(dispose); | ||
} | ||
} | ||
}; | ||
// src/context.ts | ||
var ContextRequestEvent = class extends Event { | ||
constructor(key, callback) { | ||
super("aria-ui/context-request", { bubbles: true, composed: true }); | ||
this.key = key; | ||
this.callback = callback; | ||
} | ||
}; | ||
var ContextImpl = class { | ||
constructor(key) { | ||
this.key = key; | ||
this.provide = this.provide.bind(this); | ||
this.consume = this.consume.bind(this); | ||
} | ||
provide(element, signal3) { | ||
element.addEventListener("aria-ui/context-request", (event) => { | ||
const { key, callback } = event; | ||
if (key === this.key) { | ||
callback(signal3); | ||
} | ||
}); | ||
} | ||
consume(element) { | ||
let signal3; | ||
element.dispatchEvent( | ||
new ContextRequestEvent(this.key, (s) => { | ||
signal3 = s; | ||
}) | ||
); | ||
return signal3; | ||
} | ||
}; | ||
function createContext(key) { | ||
return new ContextImpl( | ||
typeof key === "string" ? `aira-ui/context/${key}` : key | ||
); | ||
} | ||
// src/signals.ts | ||
import { | ||
batch, | ||
computed, | ||
effect, | ||
signal, | ||
untracked | ||
} from "@preact/signals-core"; | ||
function useEffect(element, callback) { | ||
let cleanup = void 0; | ||
const dispose = () => { | ||
cleanup == null ? void 0 : cleanup(); | ||
cleanup = void 0; | ||
}; | ||
element.addConnectedCallback(() => { | ||
cleanup == null ? void 0 : cleanup(); | ||
cleanup = effect(callback); | ||
return dispose; | ||
}); | ||
return dispose; | ||
} | ||
// src/dom.ts | ||
function useEventListener(element, type, listener, options) { | ||
useEffect(element, () => { | ||
element.addEventListener(type, listener, options); | ||
return () => { | ||
element.removeEventListener(type, listener, options); | ||
}; | ||
}); | ||
} | ||
function useStyle(element, key, compute) { | ||
return useEffect(element, () => { | ||
element.style[key] = compute(); | ||
}); | ||
} | ||
function useAttribute(element, key, compute) { | ||
return useEffect(element, () => { | ||
const value = compute(); | ||
if (value == null) { | ||
element.removeAttribute(key); | ||
} else { | ||
element.setAttribute(key, String(value)); | ||
} | ||
}); | ||
} | ||
function useAriaAttribute(element, key, compute) { | ||
return useAttribute(element, key, compute); | ||
} | ||
function useAriaRole(element, compute) { | ||
return useAttribute(element, "role", compute); | ||
} | ||
// src/types.ts | ||
var getObjectEntries = Object.entries; | ||
var getObjectKeys = Object.keys; | ||
// src/props.ts | ||
function assignProps(defaultProps, props) { | ||
if (!props) { | ||
return defaultProps; | ||
} | ||
const merged = { ...defaultProps }; | ||
for (const key of getObjectKeys(defaultProps)) { | ||
const prop = props[key]; | ||
if (prop !== void 0) { | ||
merged[key] = prop; | ||
} | ||
} | ||
return merged; | ||
} | ||
// src/singal-state.ts | ||
import { signal as signal2 } from "@preact/signals-core"; | ||
function mapValues(signals) { | ||
const values = {}; | ||
for (const [key, signal3] of getObjectEntries(signals)) { | ||
values[key] = signal3.value; | ||
} | ||
return values; | ||
} | ||
function mapSignals(values) { | ||
const signals = {}; | ||
for (const [key, value] of getObjectEntries(values)) { | ||
signals[key] = signal2(value); | ||
} | ||
return signals; | ||
} | ||
export { | ||
BaseElement, | ||
assignProps, | ||
batch, | ||
computed as createComputed, | ||
createContext, | ||
signal as createSignal, | ||
mapSignals, | ||
mapValues, | ||
untracked, | ||
useAriaAttribute, | ||
useAriaRole, | ||
useAttribute, | ||
useEffect, | ||
useEventListener, | ||
useStyle | ||
}; |
{ | ||
"name": "@aria-ui/core", | ||
"version": "0.0.2", | ||
"module": "index.ts", | ||
"private": false, | ||
"type": "module", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"scripts": { | ||
"build": "tsc -b" | ||
}, | ||
"dependencies": { | ||
"@preact/signals-core": "^1.5.1" | ||
}, | ||
"devDependencies": { | ||
"typescript": "^5.0.0" | ||
} | ||
} | ||
"name": "@aria-ui/core", | ||
"type": "module", | ||
"version": "0.0.4", | ||
"private": false, | ||
"sideEffects": false, | ||
"main": "dist/index.js", | ||
"dependencies": { | ||
"@dddstack/ariatype-aria-attributes": "^2.0.0", | ||
"@dddstack/ariatype-aria-roles": "^2.0.0", | ||
"@preact/signals-core": "^1.5.1" | ||
}, | ||
"devDependencies": { | ||
"tsup": "^8.0.2", | ||
"typescript": "^5.3.3" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"scripts": { | ||
"build": "tsup" | ||
}, | ||
"module": "dist/index.js", | ||
"types": "dist/index.d.ts" | ||
} |
@@ -1,44 +0,57 @@ | ||
export class BaseElement extends HTMLElement { | ||
private _connectedCallbacks: Array<(() => VoidFunction) | (() => void)> = [] | ||
private _disconnectedCallback: VoidFunction[] = [] | ||
private _connected = false | ||
import type { ConnectableElement } from "./connectable-element" | ||
connectedCallback() { | ||
this._connected = true | ||
/** | ||
* Base class for all custom elements in Aria UI. It implements the | ||
* {@link ConnectableElement} interface. | ||
*/ | ||
export class BaseElement extends HTMLElement implements ConnectableElement { | ||
private _connectedCallbacks: Array<() => VoidFunction | void> = [] | ||
private _disconnectedCallback: VoidFunction[] = [] | ||
private _connected = false | ||
for (const callback of this._connectedCallbacks) { | ||
const dispose = callback() | ||
if (dispose) { | ||
this._disconnectedCallback.push(dispose) | ||
} | ||
} | ||
} | ||
/** | ||
* @hidden | ||
*/ | ||
connectedCallback() { | ||
this._connected = true | ||
for (const callback of this._connectedCallbacks) { | ||
const dispose = callback() | ||
if (dispose) { | ||
this._disconnectedCallback.push(dispose) | ||
} | ||
} | ||
} | ||
disconnectedCallback() { | ||
this._connected = false | ||
/** | ||
* @hidden | ||
*/ | ||
disconnectedCallback() { | ||
this._connected = false | ||
for (const callback of this._disconnectedCallback) { | ||
callback() | ||
} | ||
this._disconnectedCallback = [] | ||
} | ||
for (const callback of this._disconnectedCallback) { | ||
callback() | ||
} | ||
/** | ||
* @hidden | ||
*/ | ||
adoptedCallback() { | ||
this.disconnectedCallback() | ||
this.connectedCallback() | ||
} | ||
this._disconnectedCallback = [] | ||
} | ||
adoptedCallback() { | ||
this.disconnectedCallback() | ||
this.connectedCallback() | ||
} | ||
onConnected(callback: (() => VoidFunction) | (() => void)) { | ||
this._connectedCallbacks.push(callback) | ||
if (!this._connected) { | ||
return | ||
} | ||
const dispose = callback() | ||
if (dispose) { | ||
this._disconnectedCallback.push(dispose) | ||
} | ||
} | ||
/** | ||
* @hidden | ||
*/ | ||
addConnectedCallback(callback: () => VoidFunction | void) { | ||
this._connectedCallbacks.push(callback) | ||
if (!this._connected) { | ||
return | ||
} | ||
const dispose = callback() | ||
if (dispose) { | ||
this._disconnectedCallback.push(dispose) | ||
} | ||
} | ||
} |
export { BaseElement } from "./base-element" | ||
export type { ConnectableElement } from "./connectable-element" | ||
export { createContext, type Context } from "./context" | ||
export { | ||
type ReadonlySignal, | ||
type Signal, | ||
batch, | ||
createComputed, | ||
createDeferComputed, | ||
createEffect, | ||
createSignal, | ||
untracked, | ||
useAriaAttribute, | ||
useAriaRole, | ||
useAttribute, | ||
useEventListener, | ||
useStyle, | ||
} from "./dom" | ||
export { assignProps } from "./props" | ||
export { | ||
batch, | ||
createComputed, | ||
createSignal, | ||
untracked, | ||
useEffect, | ||
type ReadonlySignal, | ||
type Signal, | ||
type SignalValue, | ||
} from "./signals" | ||
export { SingalElement, defineSingalProperties } from "./singal-element" | ||
export { | ||
type SingalState, | ||
mapStateSignals, | ||
mapStateValues, | ||
mapSignals, | ||
mapValues, | ||
type SingalState, | ||
} from "./singal-state" |
import { | ||
type ReadonlySignal, | ||
type Signal, | ||
batch, | ||
computed, | ||
effect, | ||
signal, | ||
untracked, | ||
type ReadonlySignal, | ||
type Signal, | ||
batch, | ||
computed, | ||
effect, | ||
signal, | ||
untracked, | ||
} from "@preact/signals-core" | ||
import type { BaseElement } from "./base-element" | ||
import type { ConnectableElement } from "./connectable-element" | ||
export type { Signal, ReadonlySignal } | ||
export { signal as createSignal, computed as createComputed, batch, untracked } | ||
export function createEffect( | ||
host: BaseElement, | ||
callback: (() => VoidFunction) | (() => void), | ||
export function useEffect( | ||
element: ConnectableElement, | ||
callback: () => VoidFunction | void, | ||
) { | ||
host.onConnected((): VoidFunction => effect(callback)) | ||
} | ||
let cleanup: VoidFunction | undefined = undefined | ||
export function createDeferComputed<T>(compute: () => T): ReadonlySignal<T> { | ||
const computedSignal = computed(compute) | ||
const deferSignal = signal(computedSignal.value) | ||
let lastKey: never[] = [] | ||
const dispose = (): void => { | ||
cleanup?.() | ||
cleanup = undefined | ||
} | ||
effect(() => { | ||
const value = computedSignal.value | ||
element.addConnectedCallback((): VoidFunction => { | ||
cleanup?.() | ||
cleanup = effect(callback) | ||
return dispose | ||
}) | ||
if (deferSignal.peek() === value) { | ||
return | ||
} | ||
return dispose | ||
} | ||
const key: never[] = [] | ||
lastKey = key | ||
queueMicrotask(() => { | ||
if (lastKey === key) { | ||
deferSignal.value = value | ||
} | ||
}) | ||
}) | ||
return deferSignal | ||
} | ||
export type SignalValue<S> = S extends Signal<infer T> ? T : never |
import type { Signal } from "@preact/signals-core" | ||
import { signal } from "@preact/signals-core" | ||
import { getObjectEntries } from "./types" | ||
export type SingalState<T extends object> = { | ||
[K in keyof T]: Signal<T[K]> | ||
[K in keyof T]: Signal<T[K]> | ||
} | ||
export function mapStateValues<T extends object>(state: SingalState<T>): T { | ||
return Object.fromEntries( | ||
getObjectEntries(state).map(([key, value]) => [key, value.value]), | ||
) as T | ||
/** | ||
* Maps every signal in the given object to its current value. | ||
*/ | ||
export function mapValues<T extends object>(signals: SingalState<T>): T { | ||
const values = {} as T | ||
for (const [key, signal] of getObjectEntries(signals)) { | ||
values[key] = signal.value | ||
} | ||
return values | ||
} | ||
export function mapStateSignals<T extends object>( | ||
obj: T, | ||
// Force the keys to be passed in because `obj` might be a superset of `T`, | ||
// and we only want to map the keys in `T`. | ||
keys: (keyof T)[], | ||
): SingalState<T> { | ||
return Object.fromEntries( | ||
keys.map((key) => [key, signal(obj[key])]), | ||
) as SingalState<T> | ||
/** | ||
* Maps every value in the given object to a signal. | ||
*/ | ||
export function mapSignals<T extends object>(values: T): SingalState<T> { | ||
const signals = {} as SingalState<T> | ||
for (const [key, value] of getObjectEntries(values)) { | ||
signals[key] = signal(value) | ||
} | ||
return signals | ||
} |
/** | ||
* @internal | ||
*/ | ||
export type Constructor<T> = new () => T | ||
/** | ||
* @internal | ||
* | ||
@@ -18,3 +13,3 @@ * @example | ||
export type ObjectEntries<T extends object> = { | ||
[K in keyof T]: [K, T[K]] | ||
[K in keyof T]: [K, T[K]] | ||
}[keyof T] | ||
@@ -26,4 +21,4 @@ | ||
export const getObjectEntries = Object.entries as <T extends object>( | ||
obj: T, | ||
) => Array<[keyof T, T[keyof T]]> | ||
obj: T, | ||
) => ObjectEntries<T>[] | ||
@@ -34,3 +29,3 @@ /** | ||
export const getObjectKeys = Object.keys as <T extends object>( | ||
obj: T, | ||
obj: T, | ||
) => Array<keyof T> | ||
@@ -42,3 +37,3 @@ | ||
export const getObjectValues = Object.values as <T extends object>( | ||
obj: T, | ||
obj: T, | ||
) => Array<T[keyof T]> |
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"composite": true, | ||
"outDir": "temp" | ||
}, | ||
"references": [ | ||
{ | ||
"path": "./tsconfig.build.json" | ||
} | ||
], | ||
"include": [ | ||
"./*.js", | ||
"./*.ts" | ||
] | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"composite": true, | ||
"outDir": "temp", | ||
}, | ||
"include": ["."], | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
100028
42
0
1098
0
158
3
2
+ Added@dddstack/ariatype-aria-attributes@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-attributes-drag-and-drop@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-attributes-global@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-attributes-live-region@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-attributes-relationship@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-attributes-widget@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-roles@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-roles-composite@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-roles-document-structure@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-roles-generic@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-roles-landmark@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-roles-live-region@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-roles-widget@2.0.0(transitive)
+ Added@dddstack/ariatype-aria-roles-window@2.0.0(transitive)