@signality/core 0.0.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -0
- package/browser/battery/index.d.ts +34 -0
- package/browser/bluetooth/index.d.ts +56 -0
- package/browser/breakpoints/index.d.ts +32 -0
- package/browser/broadcast-channel/index.d.ts +42 -0
- package/browser/browser-language/index.d.ts +34 -0
- package/browser/clipboard/index.d.ts +48 -0
- package/browser/device-posture/index.d.ts +18 -0
- package/browser/display-media/index.d.ts +80 -0
- package/browser/eye-dropper/index.d.ts +47 -0
- package/browser/favicon/index.d.ts +39 -0
- package/browser/fps/index.d.ts +46 -0
- package/browser/gamepad/index.d.ts +28 -0
- package/browser/geolocation/index.d.ts +64 -0
- package/browser/index.d.ts +29 -0
- package/browser/input-modality/index.d.ts +26 -0
- package/browser/listener/index.d.ts +61 -0
- package/browser/media-query/index.d.ts +36 -0
- package/browser/network/index.d.ts +44 -0
- package/browser/online/index.d.ts +27 -0
- package/browser/page-visibility/index.d.ts +27 -0
- package/browser/picture-in-picture/index.d.ts +42 -0
- package/browser/pointer-lock-element/index.d.ts +22 -0
- package/browser/screen-orientation/index.d.ts +29 -0
- package/browser/speech-recognition/index.d.ts +77 -0
- package/browser/speech-synthesis/index.d.ts +76 -0
- package/browser/storage/index.d.ts +142 -0
- package/browser/text-direction/index.d.ts +43 -0
- package/browser/vibration/index.d.ts +37 -0
- package/browser/wake-lock/index.d.ts +37 -0
- package/browser/web-notification/index.d.ts +58 -0
- package/browser/web-share/index.d.ts +42 -0
- package/browser/web-worker/index.d.ts +52 -0
- package/elements/active-element/index.d.ts +27 -0
- package/elements/dropzone/index.d.ts +61 -0
- package/elements/element-focus/index.d.ts +38 -0
- package/elements/element-focus-within/index.d.ts +29 -0
- package/elements/element-hover/index.d.ts +27 -0
- package/elements/element-size/index.d.ts +40 -0
- package/elements/element-visibility/index.d.ts +53 -0
- package/elements/index.d.ts +16 -0
- package/elements/mouse-position/index.d.ts +64 -0
- package/elements/on-click-outside/index.d.ts +42 -0
- package/elements/on-disconnect/index.d.ts +45 -0
- package/elements/on-long-press/index.d.ts +44 -0
- package/elements/pointer-swipe/index.d.ts +58 -0
- package/elements/scroll-position/index.d.ts +96 -0
- package/elements/swipe/index.d.ts +49 -0
- package/elements/text-selection/index.d.ts +39 -0
- package/elements/window-size/index.d.ts +46 -0
- package/fesm2022/signality-core-browser-battery.mjs +80 -0
- package/fesm2022/signality-core-browser-battery.mjs.map +1 -0
- package/fesm2022/signality-core-browser-bluetooth.mjs +112 -0
- package/fesm2022/signality-core-browser-bluetooth.mjs.map +1 -0
- package/fesm2022/signality-core-browser-breakpoints.mjs +51 -0
- package/fesm2022/signality-core-browser-breakpoints.mjs.map +1 -0
- package/fesm2022/signality-core-browser-broadcast-channel.mjs +74 -0
- package/fesm2022/signality-core-browser-broadcast-channel.mjs.map +1 -0
- package/fesm2022/signality-core-browser-browser-language.mjs +48 -0
- package/fesm2022/signality-core-browser-browser-language.mjs.map +1 -0
- package/fesm2022/signality-core-browser-clipboard.mjs +102 -0
- package/fesm2022/signality-core-browser-clipboard.mjs.map +1 -0
- package/fesm2022/signality-core-browser-device-posture.mjs +40 -0
- package/fesm2022/signality-core-browser-device-posture.mjs.map +1 -0
- package/fesm2022/signality-core-browser-display-media.mjs +121 -0
- package/fesm2022/signality-core-browser-display-media.mjs.map +1 -0
- package/fesm2022/signality-core-browser-eye-dropper.mjs +82 -0
- package/fesm2022/signality-core-browser-eye-dropper.mjs.map +1 -0
- package/fesm2022/signality-core-browser-favicon.mjs +100 -0
- package/fesm2022/signality-core-browser-favicon.mjs.map +1 -0
- package/fesm2022/signality-core-browser-fps.mjs +103 -0
- package/fesm2022/signality-core-browser-fps.mjs.map +1 -0
- package/fesm2022/signality-core-browser-gamepad.mjs +93 -0
- package/fesm2022/signality-core-browser-gamepad.mjs.map +1 -0
- package/fesm2022/signality-core-browser-geolocation.mjs +120 -0
- package/fesm2022/signality-core-browser-geolocation.mjs.map +1 -0
- package/fesm2022/signality-core-browser-input-modality.mjs +64 -0
- package/fesm2022/signality-core-browser-input-modality.mjs.map +1 -0
- package/fesm2022/signality-core-browser-listener.mjs +132 -0
- package/fesm2022/signality-core-browser-listener.mjs.map +1 -0
- package/fesm2022/signality-core-browser-media-query.mjs +55 -0
- package/fesm2022/signality-core-browser-media-query.mjs.map +1 -0
- package/fesm2022/signality-core-browser-network.mjs +76 -0
- package/fesm2022/signality-core-browser-network.mjs.map +1 -0
- package/fesm2022/signality-core-browser-online.mjs +49 -0
- package/fesm2022/signality-core-browser-online.mjs.map +1 -0
- package/fesm2022/signality-core-browser-page-visibility.mjs +47 -0
- package/fesm2022/signality-core-browser-page-visibility.mjs.map +1 -0
- package/fesm2022/signality-core-browser-picture-in-picture.mjs +93 -0
- package/fesm2022/signality-core-browser-picture-in-picture.mjs.map +1 -0
- package/fesm2022/signality-core-browser-pointer-lock-element.mjs +43 -0
- package/fesm2022/signality-core-browser-pointer-lock-element.mjs.map +1 -0
- package/fesm2022/signality-core-browser-screen-orientation.mjs +43 -0
- package/fesm2022/signality-core-browser-screen-orientation.mjs.map +1 -0
- package/fesm2022/signality-core-browser-speech-recognition.mjs +171 -0
- package/fesm2022/signality-core-browser-speech-recognition.mjs.map +1 -0
- package/fesm2022/signality-core-browser-speech-synthesis.mjs +146 -0
- package/fesm2022/signality-core-browser-speech-synthesis.mjs.map +1 -0
- package/fesm2022/signality-core-browser-storage.mjs +261 -0
- package/fesm2022/signality-core-browser-storage.mjs.map +1 -0
- package/fesm2022/signality-core-browser-text-direction.mjs +62 -0
- package/fesm2022/signality-core-browser-text-direction.mjs.map +1 -0
- package/fesm2022/signality-core-browser-vibration.mjs +94 -0
- package/fesm2022/signality-core-browser-vibration.mjs.map +1 -0
- package/fesm2022/signality-core-browser-wake-lock.mjs +149 -0
- package/fesm2022/signality-core-browser-wake-lock.mjs.map +1 -0
- package/fesm2022/signality-core-browser-web-notification.mjs +137 -0
- package/fesm2022/signality-core-browser-web-notification.mjs.map +1 -0
- package/fesm2022/signality-core-browser-web-share.mjs +92 -0
- package/fesm2022/signality-core-browser-web-share.mjs.map +1 -0
- package/fesm2022/signality-core-browser-web-worker.mjs +105 -0
- package/fesm2022/signality-core-browser-web-worker.mjs.map +1 -0
- package/fesm2022/signality-core-browser.mjs +34 -0
- package/fesm2022/signality-core-browser.mjs.map +1 -0
- package/fesm2022/signality-core-elements-active-element.mjs +88 -0
- package/fesm2022/signality-core-elements-active-element.mjs.map +1 -0
- package/fesm2022/signality-core-elements-dropzone.mjs +158 -0
- package/fesm2022/signality-core-elements-dropzone.mjs.map +1 -0
- package/fesm2022/signality-core-elements-element-focus-within.mjs +56 -0
- package/fesm2022/signality-core-elements-element-focus-within.mjs.map +1 -0
- package/fesm2022/signality-core-elements-element-focus.mjs +54 -0
- package/fesm2022/signality-core-elements-element-focus.mjs.map +1 -0
- package/fesm2022/signality-core-elements-element-hover.mjs +48 -0
- package/fesm2022/signality-core-elements-element-hover.mjs.map +1 -0
- package/fesm2022/signality-core-elements-element-size.mjs +73 -0
- package/fesm2022/signality-core-elements-element-size.mjs.map +1 -0
- package/fesm2022/signality-core-elements-element-visibility.mjs +76 -0
- package/fesm2022/signality-core-elements-element-visibility.mjs.map +1 -0
- package/fesm2022/signality-core-elements-mouse-position.mjs +109 -0
- package/fesm2022/signality-core-elements-mouse-position.mjs.map +1 -0
- package/fesm2022/signality-core-elements-on-click-outside.mjs +97 -0
- package/fesm2022/signality-core-elements-on-click-outside.mjs.map +1 -0
- package/fesm2022/signality-core-elements-on-disconnect.mjs +99 -0
- package/fesm2022/signality-core-elements-on-disconnect.mjs.map +1 -0
- package/fesm2022/signality-core-elements-on-long-press.mjs +84 -0
- package/fesm2022/signality-core-elements-on-long-press.mjs.map +1 -0
- package/fesm2022/signality-core-elements-pointer-swipe.mjs +116 -0
- package/fesm2022/signality-core-elements-pointer-swipe.mjs.map +1 -0
- package/fesm2022/signality-core-elements-scroll-position.mjs +175 -0
- package/fesm2022/signality-core-elements-scroll-position.mjs.map +1 -0
- package/fesm2022/signality-core-elements-swipe.mjs +107 -0
- package/fesm2022/signality-core-elements-swipe.mjs.map +1 -0
- package/fesm2022/signality-core-elements-text-selection.mjs +70 -0
- package/fesm2022/signality-core-elements-text-selection.mjs.map +1 -0
- package/fesm2022/signality-core-elements-window-size.mjs +81 -0
- package/fesm2022/signality-core-elements-window-size.mjs.map +1 -0
- package/fesm2022/signality-core-elements.mjs +21 -0
- package/fesm2022/signality-core-elements.mjs.map +1 -0
- package/fesm2022/signality-core-forms-cva.mjs +140 -0
- package/fesm2022/signality-core-forms-cva.mjs.map +1 -0
- package/fesm2022/signality-core-forms.mjs +6 -0
- package/fesm2022/signality-core-forms.mjs.map +1 -0
- package/fesm2022/signality-core-internal.mjs +268 -0
- package/fesm2022/signality-core-internal.mjs.map +1 -0
- package/fesm2022/signality-core-observers-intersection-observer.mjs +70 -0
- package/fesm2022/signality-core-observers-intersection-observer.mjs.map +1 -0
- package/fesm2022/signality-core-observers-mutation-observer.mjs +77 -0
- package/fesm2022/signality-core-observers-mutation-observer.mjs.map +1 -0
- package/fesm2022/signality-core-observers-performance-observer.mjs +84 -0
- package/fesm2022/signality-core-observers-performance-observer.mjs.map +1 -0
- package/fesm2022/signality-core-observers-resize-observer.mjs +69 -0
- package/fesm2022/signality-core-observers-resize-observer.mjs.map +1 -0
- package/fesm2022/signality-core-observers.mjs +9 -0
- package/fesm2022/signality-core-observers.mjs.map +1 -0
- package/fesm2022/signality-core-reactivity-debounced.mjs +27 -0
- package/fesm2022/signality-core-reactivity-debounced.mjs.map +1 -0
- package/fesm2022/signality-core-reactivity-throttled.mjs +27 -0
- package/fesm2022/signality-core-reactivity-throttled.mjs.map +1 -0
- package/fesm2022/signality-core-reactivity-watcher.mjs +36 -0
- package/fesm2022/signality-core-reactivity-watcher.mjs.map +1 -0
- package/fesm2022/signality-core-reactivity.mjs +8 -0
- package/fesm2022/signality-core-reactivity.mjs.map +1 -0
- package/fesm2022/signality-core-router-fragment.mjs +41 -0
- package/fesm2022/signality-core-router-fragment.mjs.map +1 -0
- package/fesm2022/signality-core-router-params.mjs +45 -0
- package/fesm2022/signality-core-router-params.mjs.map +1 -0
- package/fesm2022/signality-core-router-query-params.mjs +67 -0
- package/fesm2022/signality-core-router-query-params.mjs.map +1 -0
- package/fesm2022/signality-core-router-route-data.mjs +46 -0
- package/fesm2022/signality-core-router-route-data.mjs.map +1 -0
- package/fesm2022/signality-core-router-router-listener.mjs +50 -0
- package/fesm2022/signality-core-router-router-listener.mjs.map +1 -0
- package/fesm2022/signality-core-router-title.mjs +54 -0
- package/fesm2022/signality-core-router-title.mjs.map +1 -0
- package/fesm2022/signality-core-router-url.mjs +53 -0
- package/fesm2022/signality-core-router-url.mjs.map +1 -0
- package/fesm2022/signality-core-router.mjs +12 -0
- package/fesm2022/signality-core-router.mjs.map +1 -0
- package/fesm2022/signality-core-scheduling-debounce-callback.mjs +59 -0
- package/fesm2022/signality-core-scheduling-debounce-callback.mjs.map +1 -0
- package/fesm2022/signality-core-scheduling-interval.mjs +110 -0
- package/fesm2022/signality-core-scheduling-interval.mjs.map +1 -0
- package/fesm2022/signality-core-scheduling-throttle-callback.mjs +66 -0
- package/fesm2022/signality-core-scheduling-throttle-callback.mjs.map +1 -0
- package/fesm2022/signality-core-scheduling.mjs +8 -0
- package/fesm2022/signality-core-scheduling.mjs.map +1 -0
- package/fesm2022/signality-core-types.mjs +4 -0
- package/fesm2022/signality-core-types.mjs.map +1 -0
- package/fesm2022/signality-core.mjs +13 -0
- package/fesm2022/signality-core.mjs.map +1 -0
- package/forms/cva/index.d.ts +60 -0
- package/forms/index.d.ts +1 -0
- package/index.d.ts +8 -0
- package/internal/constants/index.d.ts +2 -0
- package/internal/constants/mobile-regex.d.ts +1 -0
- package/internal/constants/stubs.d.ts +32 -0
- package/internal/index.d.ts +4 -0
- package/internal/providers/index.d.ts +3 -0
- package/internal/providers/is-browser.d.ts +2 -0
- package/internal/providers/is-mobile.d.ts +2 -0
- package/internal/providers/is-server.d.ts +2 -0
- package/internal/types/index.d.ts +2 -0
- package/internal/types/timer.d.ts +1 -0
- package/internal/types/union.d.ts +1 -0
- package/internal/utils/bom/index.d.ts +1 -0
- package/internal/utils/bom/is-window.d.ts +1 -0
- package/internal/utils/const-signal.d.ts +10 -0
- package/internal/utils/context.d.ts +18 -0
- package/internal/utils/create-token.d.ts +8 -0
- package/internal/utils/dom/get-active-element.d.ts +1 -0
- package/internal/utils/dom/get-event-target.d.ts +1 -0
- package/internal/utils/dom/get-pip-element.d.ts +1 -0
- package/internal/utils/dom/get-shadow-root.d.ts +1 -0
- package/internal/utils/dom/index.d.ts +6 -0
- package/internal/utils/dom/is-element.d.ts +1 -0
- package/internal/utils/dom/is-node-within.d.ts +1 -0
- package/internal/utils/index.d.ts +10 -0
- package/internal/utils/is-plain-object.d.ts +1 -0
- package/internal/utils/is-query-signal.d.ts +10 -0
- package/internal/utils/proxy-signal.d.ts +18 -0
- package/internal/utils/to-element.d.ts +12 -0
- package/internal/utils/to-value.d.ts +6 -0
- package/observers/index.d.ts +4 -0
- package/observers/intersection-observer/index.d.ts +42 -0
- package/observers/mutation-observer/index.d.ts +45 -0
- package/observers/performance-observer/index.d.ts +58 -0
- package/observers/resize-observer/index.d.ts +40 -0
- package/package.json +343 -0
- package/reactivity/debounced/index.d.ts +50 -0
- package/reactivity/index.d.ts +3 -0
- package/reactivity/throttled/index.d.ts +53 -0
- package/reactivity/watcher/index.d.ts +68 -0
- package/router/fragment/index.d.ts +26 -0
- package/router/index.d.ts +7 -0
- package/router/params/index.d.ts +28 -0
- package/router/query-params/index.d.ts +80 -0
- package/router/route-data/index.d.ts +28 -0
- package/router/router-listener/index.d.ts +83 -0
- package/router/title/index.d.ts +29 -0
- package/router/url/index.d.ts +32 -0
- package/scheduling/debounce-callback/index.d.ts +28 -0
- package/scheduling/index.d.ts +3 -0
- package/scheduling/interval/index.d.ts +51 -0
- package/scheduling/throttle-callback/index.d.ts +30 -0
- package/types/index.d.ts +6 -0
- package/types/maybe-element-signal.d.ts +2 -0
- package/types/maybe-signal.d.ts +2 -0
- package/types/signal-value.d.ts +2 -0
- package/types/signal-values.d.ts +5 -0
- package/types/unref-element.d.ts +2 -0
- package/types/with-injector.d.ts +8 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Signal } from '@angular/core';
|
|
2
|
+
import type { WithInjector } from '@signality/core/types';
|
|
3
|
+
export type InputModality = 'keyboard' | 'mouse' | 'touch' | null;
|
|
4
|
+
/**
|
|
5
|
+
* Reactively track the user's current input method (keyboard, mouse, or touch).
|
|
6
|
+
*
|
|
7
|
+
* @param options - Optional configuration including injector
|
|
8
|
+
* @returns A signal containing the current input modality: `'keyboard'`, `'mouse'`, `'touch'`, or `null`
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* @Component({
|
|
13
|
+
* template: `
|
|
14
|
+
* <div [class.keyboard]="modality() === 'keyboard'">
|
|
15
|
+
* <p>Current input: {{ modality() ?? 'none' }}</p>
|
|
16
|
+
* <button>Button with conditional focus ring</button>
|
|
17
|
+
* </div>
|
|
18
|
+
* `
|
|
19
|
+
* })
|
|
20
|
+
* export class ModalityComponent {
|
|
21
|
+
* readonly modality = inputModality();
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function inputModality(options?: WithInjector): Signal<InputModality>;
|
|
26
|
+
export declare const INPUT_MODALITY: import("@angular/core").ProviderToken<Signal<InputModality>>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { MaybeElementSignal, MaybeSignal, WithInjector } from '@signality/core/types';
|
|
2
|
+
export type ListenerOptions = WithInjector;
|
|
3
|
+
export interface ListenerRef {
|
|
4
|
+
readonly destroy: () => void;
|
|
5
|
+
}
|
|
6
|
+
export interface ListenerFunction {
|
|
7
|
+
<E extends keyof WindowEventMap>(target: Window, event: MaybeSignal<E>, handler: (this: Window, e: WindowEventMap[E]) => any, options?: ListenerOptions): ListenerRef;
|
|
8
|
+
<E extends keyof DocumentEventMap>(target: Document, event: MaybeSignal<E>, handler: (this: Document, e: DocumentEventMap[E]) => any, options?: ListenerOptions): ListenerRef;
|
|
9
|
+
<E extends keyof ShadowRootEventMap>(target: MaybeSignal<ShadowRoot>, event: MaybeSignal<E>, handler: (this: ShadowRoot, e: ShadowRootEventMap[E]) => any, options?: ListenerOptions): ListenerRef;
|
|
10
|
+
<T extends HTMLElement, E extends keyof HTMLElementEventMap>(target: MaybeElementSignal<T>, event: MaybeSignal<E>, handler: (this: T, e: HTMLElementEventMap[E]) => any, options?: ListenerOptions): ListenerRef;
|
|
11
|
+
<T extends SVGElement, E extends keyof SVGElementEventMap>(target: MaybeElementSignal<T>, event: MaybeSignal<E>, handler: (this: T, e: SVGElementEventMap[E]) => any, options?: ListenerOptions): ListenerRef;
|
|
12
|
+
<Names extends string>(target: MaybeSignal<InferEventTarget<Names>>, event: MaybeSignal<Names>, handler: (e: Event) => void, options?: ListenerOptions): ListenerRef;
|
|
13
|
+
<EventType = Event>(target: MaybeSignal<EventTarget> | MaybeElementSignal<Element>, event: MaybeSignal<string>, handler: GeneralEventListener<EventType>, options?: ListenerOptions): ListenerRef;
|
|
14
|
+
readonly capture: ListenerFunction;
|
|
15
|
+
readonly passive: ListenerFunction;
|
|
16
|
+
readonly once: ListenerFunction;
|
|
17
|
+
readonly stop: ListenerFunction;
|
|
18
|
+
readonly prevent: ListenerFunction;
|
|
19
|
+
readonly self: ListenerFunction;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Signal-based wrapper around the [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) method.
|
|
23
|
+
*
|
|
24
|
+
* @param target - Event target
|
|
25
|
+
* @param event - Event type name
|
|
26
|
+
* @param handler - Event handler function
|
|
27
|
+
* @param options - Optional listener configuration
|
|
28
|
+
* @returns A ListenerRef that can be used to destroy the listener
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* @Component({
|
|
33
|
+
* template: `<button #btn>Click me</button>`,
|
|
34
|
+
* })
|
|
35
|
+
* class ListenerComponent {
|
|
36
|
+
* readonly btn = viewChild<ElementRef>('btn');
|
|
37
|
+
*
|
|
38
|
+
* constructor() {
|
|
39
|
+
* listener.capture.prevent(this.btn, 'click', event => {
|
|
40
|
+
* console.log('Button clicked!', event);
|
|
41
|
+
* });
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare const listener: ListenerFunction;
|
|
47
|
+
/**
|
|
48
|
+
* By default, `listener()` registers event listeners after the render cycle completes
|
|
49
|
+
* to ensure DOM elements exist. However, global targets (window, document, navigator.*, etc.)
|
|
50
|
+
* are not tied to the render cycle. Use `setupSync()` to wrap listener calls when you need to prevent
|
|
51
|
+
* race conditions where a global event is dispatched before Angular completes its scheduled rendering tasks.
|
|
52
|
+
*/
|
|
53
|
+
export declare function setupSync<T>(listenerFactoryExecFn: () => T): T;
|
|
54
|
+
interface InferEventTarget<Events> {
|
|
55
|
+
readonly addEventListener: (event: Events, fn?: any, options?: any) => any;
|
|
56
|
+
readonly removeEventListener: (event: Events, fn?: any, options?: any) => any;
|
|
57
|
+
}
|
|
58
|
+
interface GeneralEventListener<E = Event> {
|
|
59
|
+
(e: E): void;
|
|
60
|
+
}
|
|
61
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type CreateSignalOptions, type Signal } from '@angular/core';
|
|
2
|
+
import { type Union } from '@signality/core/internal';
|
|
3
|
+
import type { MaybeSignal, WithInjector } from '@signality/core/types';
|
|
4
|
+
export interface MediaQueryOptions extends CreateSignalOptions<boolean>, WithInjector {
|
|
5
|
+
/**
|
|
6
|
+
* Initial value for SSR.
|
|
7
|
+
* @default false
|
|
8
|
+
*/
|
|
9
|
+
readonly initialValue?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Reactive wrapper around the [Window.matchMedia](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia) method.
|
|
13
|
+
*
|
|
14
|
+
* @param query - CSS media query string (can be a signal)
|
|
15
|
+
* @param options - Optional configuration
|
|
16
|
+
* @returns A signal that is true when the media query matches
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* @Component({
|
|
21
|
+
* template: `
|
|
22
|
+
* @if (prefersDark()) {
|
|
23
|
+
* <p>Dark mode is preferred</p>
|
|
24
|
+
* } @else {
|
|
25
|
+
* <p>Light mode is preferred</p>
|
|
26
|
+
* }
|
|
27
|
+
* `
|
|
28
|
+
* })
|
|
29
|
+
* class ThemeComponent {
|
|
30
|
+
* readonly prefersDark = mediaQuery('(prefers-color-scheme: dark)');
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function mediaQuery(query: MaybeSignal<Union<MediaQueryFeature, string>>, options?: MediaQueryOptions): Signal<boolean>;
|
|
35
|
+
type MediaQueryFeature = `(any-hover: ${'none' | 'hover'})` | `(any-pointer: ${'none' | 'coarse' | 'fine'})` | `(aspect-ratio: ${string})` | `(color: ${string})` | `(color-gamut: ${'srgb' | 'p3' | 'rec2020'})` | `(color-index: ${string})` | `(device-aspect-ratio: ${string})` | `(device-height: ${string})` | `(device-posture: ${'flat' | 'folded' | 'continuous'})` | `(device-width: ${string})` | `(display-mode: ${'fullscreen' | 'standalone' | 'minimal-ui' | 'browser' | 'picture-in-picture' | 'window-controls-overlay'})` | `(dynamic-range: ${'standard' | 'high'})` | `(forced-colors: ${'none' | 'active'})` | `(grid: ${'0' | '1'})` | `(height: ${string})` | `(hover: ${'none' | 'hover'})` | `(inverted-colors: ${'none' | 'inverted'})` | `(monochrome: ${string})` | `(orientation: ${'portrait' | 'landscape'})` | `(overflow-block: ${'none' | 'scroll' | 'optional-paged' | 'paged'})` | `(overflow-inline: ${'none' | 'scroll'})` | `(pointer: ${'none' | 'coarse' | 'fine'})` | `(prefers-color-scheme: ${'light' | 'dark' | 'no-preference'})` | `(prefers-contrast: ${'no-preference' | 'more' | 'less' | 'custom'})` | `(prefers-reduced-data: ${'no-preference' | 'reduce'})` | `(prefers-reduced-motion: ${'no-preference' | 'reduce'})` | `(prefers-reduced-transparency: ${'no-preference' | 'reduce'})` | `(resolution: ${string})` | `(scan: ${'progressive' | 'interlace'})` | `(scripting: ${'none' | 'initial-only' | 'enabled'})` | `(shape: ${'rect' | 'round'})` | `(update: ${'none' | 'slow' | 'fast'})` | `(video-dynamic-range: ${'standard' | 'high'})` | `(width: ${string})` | `(min-width: ${string})` | `(max-width: ${string})` | `(min-height: ${string})` | `(max-height: ${string})` | `(min-aspect-ratio: ${string})` | `(max-aspect-ratio: ${string})` | `(min-resolution: ${string})` | `(max-resolution: ${string})` | `(min-color: ${string})` | `(max-color: ${string})` | `(min-color-index: ${string})` | `(max-color-index: ${string})` | `(min-monochrome: ${string})` | `(max-monochrome: ${string})`;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Signal } from '@angular/core';
|
|
2
|
+
import type { WithInjector } from '@signality/core/types';
|
|
3
|
+
export type EffectiveConnectionType = 'slow-2g' | '2g' | '3g' | '4g';
|
|
4
|
+
export type ConnectionType = 'bluetooth' | 'cellular' | 'ethernet' | 'wifi' | 'wimax' | 'none' | 'other' | 'unknown';
|
|
5
|
+
export type NetworkOptions = WithInjector;
|
|
6
|
+
export interface NetworkRef {
|
|
7
|
+
/** Whether Network Information API is supported */
|
|
8
|
+
readonly isSupported: Signal<boolean>;
|
|
9
|
+
/** Whether the browser is online */
|
|
10
|
+
readonly isOnline: Signal<boolean>;
|
|
11
|
+
/** Effective connection type */
|
|
12
|
+
readonly effectiveType: Signal<EffectiveConnectionType | undefined>;
|
|
13
|
+
/** Downlink speed in Mbps */
|
|
14
|
+
readonly downlink: Signal<number | undefined>;
|
|
15
|
+
/** Round-trip time in ms */
|
|
16
|
+
readonly rtt: Signal<number | undefined>;
|
|
17
|
+
/** Whether user has data saver enabled */
|
|
18
|
+
readonly saveData: Signal<boolean>;
|
|
19
|
+
/** Connection type (wifi, cellular, etc.) */
|
|
20
|
+
readonly type: Signal<ConnectionType | undefined>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Signal-based wrapper around the Network Information API and online/offline events.
|
|
24
|
+
*
|
|
25
|
+
* @param options - Optional configuration including injector
|
|
26
|
+
* @returns A NetworkRef with network status signals
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* @Component({
|
|
31
|
+
* template: `
|
|
32
|
+
* <p>{{ net.isOnline() ? 'Online' : 'Offline' }}</p>
|
|
33
|
+
* @if (net.effectiveType()) {
|
|
34
|
+
* <p>Connection: {{ net.effectiveType() }}</p>
|
|
35
|
+
* }
|
|
36
|
+
* `
|
|
37
|
+
* })
|
|
38
|
+
* class NetworkComponent {
|
|
39
|
+
* readonly net = network();
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare function network(options?: NetworkOptions): NetworkRef;
|
|
44
|
+
export declare const NETWORK: import("@angular/core").ProviderToken<NetworkRef>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type CreateSignalOptions, type Signal } from '@angular/core';
|
|
2
|
+
import type { WithInjector } from '@signality/core/types';
|
|
3
|
+
export type OnlineOptions = CreateSignalOptions<boolean> & WithInjector;
|
|
4
|
+
/**
|
|
5
|
+
* Reactive wrapper around the [Navigator.onLine](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine) property.
|
|
6
|
+
*
|
|
7
|
+
* @param options - Optional configuration including signal options and injector
|
|
8
|
+
* @returns A signal containing the current online status (`true` for online, `false` for offline)
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* @Component({
|
|
13
|
+
* template: `
|
|
14
|
+
* @if (isOnline()) {
|
|
15
|
+
* <p>You're online</p>
|
|
16
|
+
* } @else {
|
|
17
|
+
* <p>You're offline</p>
|
|
18
|
+
* }
|
|
19
|
+
* `
|
|
20
|
+
* })
|
|
21
|
+
* class NetworkStatusComponent {
|
|
22
|
+
* readonly isOnline = online();
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function online(options?: OnlineOptions): Signal<boolean>;
|
|
27
|
+
export declare const ONLINE: import("@angular/core").ProviderToken<Signal<boolean>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type CreateSignalOptions, type Signal } from '@angular/core';
|
|
2
|
+
import type { WithInjector } from '@signality/core/types';
|
|
3
|
+
export type PageVisibilityOptions = CreateSignalOptions<DocumentVisibilityState> & WithInjector;
|
|
4
|
+
/**
|
|
5
|
+
* Signal-based wrapper around the [Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API).
|
|
6
|
+
*
|
|
7
|
+
* @param options - Optional configuration including signal options and injector
|
|
8
|
+
* @returns A signal containing the current DocumentVisibilityState ('visible' or 'hidden')
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* @Component({
|
|
13
|
+
* template: `
|
|
14
|
+
* @if (visibility() === 'hidden') {
|
|
15
|
+
* <p>Page is hidden</p>
|
|
16
|
+
* } @else {
|
|
17
|
+
* <p>Page is visible</p>
|
|
18
|
+
* }
|
|
19
|
+
* `
|
|
20
|
+
* })
|
|
21
|
+
* class VisibilityComponent {
|
|
22
|
+
* readonly visibility = pageVisibility();
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function pageVisibility(options?: PageVisibilityOptions): Signal<DocumentVisibilityState>;
|
|
27
|
+
export declare const PAGE_VISIBILITY: import("@angular/core").ProviderToken<Signal<DocumentVisibilityState>>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type Signal } from '@angular/core';
|
|
2
|
+
import type { MaybeElementSignal, WithInjector } from '@signality/core/types';
|
|
3
|
+
export type PictureInPictureOptions = WithInjector;
|
|
4
|
+
export interface PictureInPictureRef {
|
|
5
|
+
/** Whether Picture-in-Picture API is supported */
|
|
6
|
+
readonly isSupported: Signal<boolean>;
|
|
7
|
+
/** Whether Picture-in-Picture is active */
|
|
8
|
+
readonly isActive: Signal<boolean>;
|
|
9
|
+
/** Enter Picture-in-Picture mode */
|
|
10
|
+
readonly enter: () => Promise<void>;
|
|
11
|
+
/** Exit Picture-in-Picture mode */
|
|
12
|
+
readonly exit: () => Promise<void>;
|
|
13
|
+
/** Toggle Picture-in-Picture mode */
|
|
14
|
+
readonly toggle: () => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Signal-based wrapper around the [Picture-in-Picture API](https://developer.mozilla.org/en-US/docs/Web/API/Picture-in-Picture_API).
|
|
18
|
+
*
|
|
19
|
+
* Automatically exits Picture-in-Picture when the target element is disconnected from the DOM.
|
|
20
|
+
*
|
|
21
|
+
* @param target - Video element
|
|
22
|
+
* @param options - Optional configuration
|
|
23
|
+
* @returns A {@link PictureInPictureRef} with `isSupported`, `isActive` signals and `enter`/`exit`/`toggle` methods
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* @Component({
|
|
28
|
+
* template: `
|
|
29
|
+
* @if (pip.isSupported()) {
|
|
30
|
+
* <video #video src="video.mp4"></video>
|
|
31
|
+
* <button (click)="pip.toggle()">Toggle PiP</button>
|
|
32
|
+
* <p>Active: {{ pip.isActive() }}</p>
|
|
33
|
+
* }
|
|
34
|
+
* `
|
|
35
|
+
* })
|
|
36
|
+
* class PiPComponent {
|
|
37
|
+
* readonly video = viewChild<HTMLVideoElement>('video');
|
|
38
|
+
* readonly pip = pictureInPicture(this.video);
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function pictureInPicture(target: MaybeElementSignal<HTMLVideoElement>, options?: PictureInPictureOptions): PictureInPictureRef;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type CreateSignalOptions, type Signal } from '@angular/core';
|
|
2
|
+
import type { WithInjector } from '@signality/core/types';
|
|
3
|
+
export type PointerLockElementOptions = CreateSignalOptions<Element | null> & WithInjector;
|
|
4
|
+
/**
|
|
5
|
+
* Reactive wrapper around the [Pointer Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API).
|
|
6
|
+
* Returns a signal that tracks the element that currently has pointer lock.
|
|
7
|
+
*
|
|
8
|
+
* @param options - Optional configuration including signal options and injector
|
|
9
|
+
* @returns A signal containing the element with pointer lock, or `null` if no element has lock
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const lockedElement = pointerLockElement();
|
|
14
|
+
*
|
|
15
|
+
* effect(() => {
|
|
16
|
+
* if (lockedElement()) {
|
|
17
|
+
* console.log('Pointer locked on:', lockedElement());
|
|
18
|
+
* }
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function pointerLockElement(options?: PointerLockElementOptions): Signal<Element | null>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type CreateSignalOptions, type Signal } from '@angular/core';
|
|
2
|
+
import type { WithInjector } from '@signality/core/types';
|
|
3
|
+
export interface ScreenOrientationOptions extends CreateSignalOptions<OrientationType>, WithInjector {
|
|
4
|
+
/**
|
|
5
|
+
* Initial value for SSR.
|
|
6
|
+
* @default 'portrait-primary'
|
|
7
|
+
*/
|
|
8
|
+
readonly initialValue?: OrientationType;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Reactive wrapper around the [Screen Orientation API](https://developer.mozilla.org/en-US/docs/Web/API/Screen_Orientation_API).
|
|
12
|
+
* Returns a signal that tracks the current screen orientation.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Optional configuration including signal options and injector
|
|
15
|
+
* @returns A signal containing the current orientation type (`'portrait-primary'`, `'portrait-secondary'`, `'landscape-primary'`, or `'landscape-secondary'`)
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* @Component({
|
|
20
|
+
* template: `
|
|
21
|
+
* <p>Orientation: {{ orientation() }}</p>
|
|
22
|
+
* `
|
|
23
|
+
* })
|
|
24
|
+
* class OrientationComponent {
|
|
25
|
+
* readonly orientation = screenOrientation();
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function screenOrientation(options?: ScreenOrientationOptions): Signal<OrientationType>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type Signal } from '@angular/core';
|
|
2
|
+
import type { MaybeSignal, WithInjector } from '@signality/core/types';
|
|
3
|
+
export interface SpeechRecognitionOptions extends WithInjector {
|
|
4
|
+
/**
|
|
5
|
+
* Language for speech recognition.
|
|
6
|
+
* @default 'en-US'
|
|
7
|
+
*/
|
|
8
|
+
readonly lang?: MaybeSignal<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Whether to return interim results.
|
|
11
|
+
* @default false
|
|
12
|
+
*/
|
|
13
|
+
readonly interimResults?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Whether to continue recognition after speech ends.
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
readonly continuous?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Maximum number of alternative transcripts.
|
|
21
|
+
* @default 1
|
|
22
|
+
*/
|
|
23
|
+
readonly maxAlternatives?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface SpeechRecognitionRef {
|
|
26
|
+
/** Whether Speech Recognition API is supported */
|
|
27
|
+
readonly isSupported: Signal<boolean>;
|
|
28
|
+
/** Whether recognition is currently active */
|
|
29
|
+
readonly isListening: Signal<boolean>;
|
|
30
|
+
/** Final transcript text */
|
|
31
|
+
readonly text: Signal<string>;
|
|
32
|
+
/** Interim transcript text */
|
|
33
|
+
readonly interimText: Signal<string>;
|
|
34
|
+
/** Error if recognition failed */
|
|
35
|
+
readonly error: Signal<SpeechRecognitionErrorEvent | Error | null>;
|
|
36
|
+
/** Start speech recognition */
|
|
37
|
+
readonly start: () => void;
|
|
38
|
+
/** Stop speech recognition */
|
|
39
|
+
readonly stop: () => void;
|
|
40
|
+
/** Abort speech recognition */
|
|
41
|
+
readonly abort: () => void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Signal-based wrapper around the [Speech Recognition API](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition).
|
|
45
|
+
*
|
|
46
|
+
* @param options - Optional configuration
|
|
47
|
+
* @returns A SpeechRecognitionRef with isSupported, isListening, text, interimText, error signals and control methods
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* @Component({
|
|
52
|
+
* template: `
|
|
53
|
+
* @if (recognition.isSupported()) {
|
|
54
|
+
* <button (click)="toggleRecognition()">
|
|
55
|
+
* {{ recognition.isListening() ? 'Stop' : 'Start' }} Recording
|
|
56
|
+
* </button>
|
|
57
|
+
* <p>{{ recognition.text() }}</p>
|
|
58
|
+
* @if (recognition.interimText()) {
|
|
59
|
+
* <p><em>{{ recognition.interimText() }}</em></p>
|
|
60
|
+
* }
|
|
61
|
+
* }
|
|
62
|
+
* `
|
|
63
|
+
* })
|
|
64
|
+
* class SpeechComponent {
|
|
65
|
+
* readonly recognition = speechRecognition();
|
|
66
|
+
*
|
|
67
|
+
* toggleRecognition() {
|
|
68
|
+
* if (this.recognition.isListening()) {
|
|
69
|
+
* this.recognition.stop();
|
|
70
|
+
* } else {
|
|
71
|
+
* this.recognition.start();
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare function speechRecognition(options?: SpeechRecognitionOptions): SpeechRecognitionRef;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { type Signal } from '@angular/core';
|
|
2
|
+
import type { WithInjector } from '@signality/core/types';
|
|
3
|
+
export interface SpeechSynthesisSpeakOptions {
|
|
4
|
+
/** Text to speak */
|
|
5
|
+
readonly text: string;
|
|
6
|
+
/** Language code (e.g., 'en-US') */
|
|
7
|
+
readonly lang?: string;
|
|
8
|
+
/** Speech rate (0.1 to 10) */
|
|
9
|
+
readonly rate?: number;
|
|
10
|
+
/** Speech pitch (0 to 2) */
|
|
11
|
+
readonly pitch?: number;
|
|
12
|
+
/** Speech volume (0 to 1) */
|
|
13
|
+
readonly volume?: number;
|
|
14
|
+
/** Voice to use */
|
|
15
|
+
readonly voice?: SpeechSynthesisVoice;
|
|
16
|
+
}
|
|
17
|
+
export interface SpeechSynthesisOptions extends WithInjector {
|
|
18
|
+
/** Default language */
|
|
19
|
+
readonly lang?: string;
|
|
20
|
+
/** Default speech rate */
|
|
21
|
+
readonly rate?: number;
|
|
22
|
+
/** Default pitch */
|
|
23
|
+
readonly pitch?: number;
|
|
24
|
+
/** Default volume */
|
|
25
|
+
readonly volume?: number;
|
|
26
|
+
/** Default voice */
|
|
27
|
+
readonly voice?: SpeechSynthesisVoice;
|
|
28
|
+
}
|
|
29
|
+
export interface SpeechSynthesisRef {
|
|
30
|
+
/** Whether Speech Synthesis API is supported */
|
|
31
|
+
readonly isSupported: Signal<boolean>;
|
|
32
|
+
/** Whether speech is currently playing */
|
|
33
|
+
readonly isSpeaking: Signal<boolean>;
|
|
34
|
+
/** Whether speech is currently paused */
|
|
35
|
+
readonly isPaused: Signal<boolean>;
|
|
36
|
+
/** Available voices */
|
|
37
|
+
readonly voices: Signal<SpeechSynthesisVoice[]>;
|
|
38
|
+
/** Current speaking text */
|
|
39
|
+
readonly currentText: Signal<string>;
|
|
40
|
+
/** Speak text */
|
|
41
|
+
readonly speak: (text: string, options?: Partial<SpeechSynthesisSpeakOptions>) => void;
|
|
42
|
+
/** Stop speaking */
|
|
43
|
+
readonly stop: () => void;
|
|
44
|
+
/** Pause speaking */
|
|
45
|
+
readonly pause: () => void;
|
|
46
|
+
/** Resume speaking */
|
|
47
|
+
readonly resume: () => void;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Signal-based wrapper around the [Speech Synthesis API](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis).
|
|
51
|
+
*
|
|
52
|
+
* @param options - Optional configuration
|
|
53
|
+
* @returns A SpeechSynthesisRef with isSupported, isSpeaking, isPaused, voices signals and control methods
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* @Component({
|
|
58
|
+
* template: `
|
|
59
|
+
* @if (synthesis.isSupported()) {
|
|
60
|
+
* <button (click)="speakText()" [disabled]="synthesis.isSpeaking()">
|
|
61
|
+
* {{ synthesis.isSpeaking() ? 'Speaking...' : 'Speak' }}
|
|
62
|
+
* </button>
|
|
63
|
+
* <button (click)="synthesis.stop()">Stop</button>
|
|
64
|
+
* }
|
|
65
|
+
* `
|
|
66
|
+
* })
|
|
67
|
+
* class TextToSpeechComponent {
|
|
68
|
+
* readonly synthesis = speechSynthesis();
|
|
69
|
+
*
|
|
70
|
+
* speakText() {
|
|
71
|
+
* this.synthesis.speak('Hello, world!');
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function speechSynthesis(options?: SpeechSynthesisOptions): SpeechSynthesisRef;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { type CreateSignalOptions, type WritableSignal } from '@angular/core';
|
|
2
|
+
import type { MaybeSignal, WithInjector } from '@signality/core/types';
|
|
3
|
+
export interface StorageOptions<T> extends CreateSignalOptions<T>, WithInjector {
|
|
4
|
+
/**
|
|
5
|
+
* Storage type to use.
|
|
6
|
+
* @default 'local'
|
|
7
|
+
*/
|
|
8
|
+
readonly type?: 'local' | 'session';
|
|
9
|
+
/**
|
|
10
|
+
* Custom serializer for read/write operations.
|
|
11
|
+
*
|
|
12
|
+
* If not provided, the serializer is automatically inferred from the initial value type:
|
|
13
|
+
* - `string` → pass-through (no transformation)
|
|
14
|
+
* - `number` → handles Infinity, -Infinity, NaN
|
|
15
|
+
* - `boolean` → strict true/false conversion
|
|
16
|
+
* - `bigint` → string representation
|
|
17
|
+
* - `Date` → ISO 8601 format
|
|
18
|
+
* - `Map` → JSON array of entries
|
|
19
|
+
* - `Set` → JSON array
|
|
20
|
+
* - `object/array` → JSON serialization
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Use built-in serializers
|
|
25
|
+
* import { Serializers } from '@signality/core';
|
|
26
|
+
*
|
|
27
|
+
* const counter = storage('count', 0, {
|
|
28
|
+
* serializer: Serializers.number,
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // or create a custom serializer
|
|
32
|
+
* const userSettings = storage('settings', defaultSettings, {
|
|
33
|
+
* serializer: {
|
|
34
|
+
* write: (v) => JSON.stringify(v),
|
|
35
|
+
* read: (s) => ({ ...defaultSettings, ...JSON.parse(s) }),
|
|
36
|
+
* },
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
readonly serializer?: Serializer<T>;
|
|
41
|
+
/**
|
|
42
|
+
* Merge resolver function when reading from storage.
|
|
43
|
+
*
|
|
44
|
+
* Receives stored value and default value, returns the final value.
|
|
45
|
+
* Default: shallow merge for objects ({ ...initialValue, ...stored })
|
|
46
|
+
*
|
|
47
|
+
* Useful for handling schema migrations when default has new properties.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const settings = storage('settings', { theme: 'dark', fontSize: 14 }, {
|
|
52
|
+
* mergeResolver: (stored, initial) => ({ ...initial, ...stored }),
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* // Or with custom merge
|
|
56
|
+
* const settings = storage('settings', defaultSettings, {
|
|
57
|
+
* mergeResolver: (stored, initial) => deepMerge(stored, initial),
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
readonly mergeResolver?: (storedValue: T, initialValue: T) => T;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Serializer interface for converting values to/from strings for storage.
|
|
65
|
+
*/
|
|
66
|
+
export interface Serializer<T> {
|
|
67
|
+
readonly write: (value: T) => string;
|
|
68
|
+
readonly read: (raw: string) => T;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Signal-based wrapper around the [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API) (localStorage/sessionStorage).
|
|
72
|
+
*
|
|
73
|
+
* @param key - Storage key (can be a signal for dynamic keys)
|
|
74
|
+
* @param initialValue - Default value if key doesn't exist
|
|
75
|
+
* @param options - Configuration options
|
|
76
|
+
* @returns A WritableSignal that automatically syncs with storage
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* Basic usage with automatic serialization:
|
|
80
|
+
* ```typescript
|
|
81
|
+
* @Component({
|
|
82
|
+
* template: '
|
|
83
|
+
* <input [(ngModel)]="username" />
|
|
84
|
+
* <p>Count: {{ count() }}</p>
|
|
85
|
+
* <button (click)="count.set(count() + 1)">Increment</button>
|
|
86
|
+
* '
|
|
87
|
+
* })
|
|
88
|
+
* class UserComponent {
|
|
89
|
+
* readonly username = storage('username', '');
|
|
90
|
+
* readonly count = storage('counter', 0); // number serialization inferred
|
|
91
|
+
* readonly lastVisit = storage('lastVisit', new Date()); // Date serialization inferred
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* With options:
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const preferences = storage('prefs', defaultPrefs, {
|
|
99
|
+
* type: 'session',
|
|
100
|
+
* mergeWithInitial: true,
|
|
101
|
+
* });
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare function storage<T>(key: MaybeSignal<string>, initialValue: T, options?: StorageOptions<T>): WritableSignal<T>;
|
|
105
|
+
export declare const Serializers: {
|
|
106
|
+
readonly string: {
|
|
107
|
+
read: (v: string) => string;
|
|
108
|
+
write: (v: string) => string;
|
|
109
|
+
};
|
|
110
|
+
readonly number: {
|
|
111
|
+
read: (v: string) => number;
|
|
112
|
+
write: (v: number) => string;
|
|
113
|
+
};
|
|
114
|
+
readonly boolean: {
|
|
115
|
+
read: (v: string) => boolean;
|
|
116
|
+
write: (v: boolean) => string;
|
|
117
|
+
};
|
|
118
|
+
readonly bigint: {
|
|
119
|
+
read: (v: string) => bigint;
|
|
120
|
+
write: (v: bigint) => string;
|
|
121
|
+
};
|
|
122
|
+
readonly date: {
|
|
123
|
+
read: (v: string) => Date;
|
|
124
|
+
write: (v: Date) => string;
|
|
125
|
+
};
|
|
126
|
+
readonly object: {
|
|
127
|
+
read: <T>(v: string) => T;
|
|
128
|
+
write: <T>(v: T) => string;
|
|
129
|
+
};
|
|
130
|
+
readonly map: {
|
|
131
|
+
read: <K, V>(v: string) => Map<K, V>;
|
|
132
|
+
write: <K, V>(v: Map<K, V>) => string;
|
|
133
|
+
};
|
|
134
|
+
readonly set: {
|
|
135
|
+
read: <T>(v: string) => Set<T>;
|
|
136
|
+
write: <T>(v: Set<T>) => string;
|
|
137
|
+
};
|
|
138
|
+
readonly any: {
|
|
139
|
+
read: <T>(v: string) => T;
|
|
140
|
+
write: (v: unknown) => string;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CreateSignalOptions, WritableSignal } from '@angular/core';
|
|
2
|
+
import type { MaybeElementSignal, WithInjector } from '@signality/core/types';
|
|
3
|
+
/**
|
|
4
|
+
* Possible text direction values matching the HTML `dir` attribute.
|
|
5
|
+
*/
|
|
6
|
+
export type TextDirection = 'ltr' | 'rtl' | 'auto';
|
|
7
|
+
export interface TextDirectionOptions extends CreateSignalOptions<TextDirection>, WithInjector {
|
|
8
|
+
/**
|
|
9
|
+
* Element to observe. Defaults to `document.documentElement` (`<html>`).
|
|
10
|
+
*/
|
|
11
|
+
readonly target?: MaybeElementSignal<HTMLElement>;
|
|
12
|
+
/**
|
|
13
|
+
* Initial direction value used during SSR or before the DOM is read.
|
|
14
|
+
* @default 'ltr'
|
|
15
|
+
*/
|
|
16
|
+
readonly initialValue?: TextDirection;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Reactive read/write wrapper around an element's `dir` attribute for detecting and controlling
|
|
20
|
+
* [text directionality](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir).
|
|
21
|
+
*
|
|
22
|
+
* Returns a `WritableSignal` that reflects the current `dir` attribute value and updates the DOM
|
|
23
|
+
* when written to. Changes made to the attribute externally are picked up via `MutationObserver`.
|
|
24
|
+
*
|
|
25
|
+
* @param options - Optional configuration including target element, initial value and injector
|
|
26
|
+
* @returns A writable signal of the current text direction
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* @Component({
|
|
31
|
+
* template: `
|
|
32
|
+
* <p>Current direction: {{ dir() }}</p>
|
|
33
|
+
* <button (click)="dir.set('rtl')">Set RTL</button>
|
|
34
|
+
* <button (click)="dir.set('ltr')">Set LTR</button>
|
|
35
|
+
* `
|
|
36
|
+
* })
|
|
37
|
+
* class TextDirectionComponent {
|
|
38
|
+
* readonly dir = textDirection();
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function textDirection(options?: TextDirectionOptions): WritableSignal<TextDirection>;
|
|
43
|
+
export declare const TEXT_DIRECTION: import("@angular/core").ProviderToken<WritableSignal<TextDirection>>;
|