@signality/core 0.0.1-alpha.2 → 0.0.1-alpha.3
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/browser/battery/index.d.ts +27 -2
- package/browser/bluetooth/index.d.ts +40 -13
- package/browser/breakpoints/index.d.ts +22 -9
- package/browser/broadcast-channel/index.d.ts +1 -1
- package/browser/browser-language/index.d.ts +1 -1
- package/browser/clipboard/index.d.ts +22 -6
- package/browser/device-posture/index.d.ts +23 -2
- package/browser/display-media/index.d.ts +34 -22
- package/browser/eye-dropper/index.d.ts +22 -6
- package/browser/favicon/index.d.ts +29 -2
- package/browser/file-dialog/index.d.ts +97 -0
- package/browser/fps/index.d.ts +1 -1
- package/browser/fullscreen/index.d.ts +78 -0
- package/browser/gamepad/index.d.ts +39 -9
- package/browser/geolocation/index.d.ts +44 -13
- package/browser/index.d.ts +8 -1
- package/browser/input-modality/index.d.ts +1 -1
- package/browser/listener/index.d.ts +1 -1
- package/browser/media-query/index.d.ts +1 -1
- package/browser/network/index.d.ts +37 -9
- package/browser/online/index.d.ts +1 -1
- package/browser/page-visibility/index.d.ts +1 -1
- package/browser/permission-state/index.d.ts +23 -0
- package/browser/picture-in-picture/index.d.ts +24 -6
- package/browser/screen-orientation/index.d.ts +1 -1
- package/browser/speech-recognition/index.d.ts +51 -13
- package/browser/speech-synthesis/index.d.ts +82 -42
- package/browser/storage/index.d.ts +1 -1
- package/browser/text-direction/index.d.ts +2 -5
- package/{elements → browser}/text-selection/index.d.ts +1 -1
- package/browser/vibration/index.d.ts +38 -9
- package/browser/wake-lock/index.d.ts +51 -12
- package/browser/web-notification/index.d.ts +35 -9
- package/browser/web-share/index.d.ts +19 -5
- package/browser/web-worker/index.d.ts +35 -11
- package/browser/window-focus/index.d.ts +27 -0
- package/{elements → browser}/window-size/index.d.ts +6 -7
- package/elements/active-element/index.d.ts +1 -1
- package/elements/dropzone/index.d.ts +60 -10
- package/elements/element-focus/index.d.ts +1 -1
- package/elements/element-focus-within/index.d.ts +1 -1
- package/elements/element-hover/index.d.ts +1 -1
- package/elements/element-size/index.d.ts +8 -5
- package/elements/element-visibility/index.d.ts +25 -7
- package/elements/index.d.ts +0 -2
- package/elements/mouse-position/index.d.ts +27 -7
- package/elements/on-click-outside/index.d.ts +1 -1
- package/elements/on-disconnect/index.d.ts +1 -1
- package/elements/on-long-press/index.d.ts +1 -1
- package/elements/pointer-swipe/index.d.ts +1 -1
- package/elements/scroll-position/index.d.ts +2 -2
- package/elements/swipe/index.d.ts +1 -1
- package/fesm2022/signality-core-browser-battery.mjs +1 -1
- package/fesm2022/signality-core-browser-battery.mjs.map +1 -1
- package/fesm2022/signality-core-browser-bluetooth.mjs +28 -27
- package/fesm2022/signality-core-browser-bluetooth.mjs.map +1 -1
- package/fesm2022/signality-core-browser-breakpoints.mjs +19 -10
- package/fesm2022/signality-core-browser-breakpoints.mjs.map +1 -1
- package/fesm2022/signality-core-browser-broadcast-channel.mjs +1 -1
- package/fesm2022/signality-core-browser-broadcast-channel.mjs.map +1 -1
- package/fesm2022/signality-core-browser-browser-language.mjs +1 -1
- package/fesm2022/signality-core-browser-browser-language.mjs.map +1 -1
- package/fesm2022/signality-core-browser-clipboard.mjs +1 -1
- package/fesm2022/signality-core-browser-clipboard.mjs.map +1 -1
- package/fesm2022/signality-core-browser-device-posture.mjs +13 -0
- package/fesm2022/signality-core-browser-device-posture.mjs.map +1 -1
- package/fesm2022/signality-core-browser-display-media.mjs +4 -17
- package/fesm2022/signality-core-browser-display-media.mjs.map +1 -1
- package/fesm2022/signality-core-browser-eye-dropper.mjs +1 -1
- package/fesm2022/signality-core-browser-eye-dropper.mjs.map +1 -1
- package/fesm2022/signality-core-browser-favicon.mjs +2 -2
- package/fesm2022/signality-core-browser-favicon.mjs.map +1 -1
- package/fesm2022/signality-core-browser-file-dialog.mjs +109 -0
- package/fesm2022/signality-core-browser-file-dialog.mjs.map +1 -0
- package/fesm2022/signality-core-browser-fps.mjs +1 -1
- package/fesm2022/signality-core-browser-fps.mjs.map +1 -1
- package/fesm2022/signality-core-browser-fullscreen.mjs +113 -0
- package/fesm2022/signality-core-browser-fullscreen.mjs.map +1 -0
- package/fesm2022/signality-core-browser-gamepad.mjs +14 -4
- package/fesm2022/signality-core-browser-gamepad.mjs.map +1 -1
- package/fesm2022/signality-core-browser-geolocation.mjs +8 -19
- package/fesm2022/signality-core-browser-geolocation.mjs.map +1 -1
- package/fesm2022/signality-core-browser-input-modality.mjs +1 -1
- package/fesm2022/signality-core-browser-input-modality.mjs.map +1 -1
- package/fesm2022/signality-core-browser-listener.mjs +18 -6
- package/fesm2022/signality-core-browser-listener.mjs.map +1 -1
- package/fesm2022/signality-core-browser-media-query.mjs +1 -1
- package/fesm2022/signality-core-browser-media-query.mjs.map +1 -1
- package/fesm2022/signality-core-browser-network.mjs +2 -2
- package/fesm2022/signality-core-browser-network.mjs.map +1 -1
- package/fesm2022/signality-core-browser-online.mjs +1 -1
- package/fesm2022/signality-core-browser-online.mjs.map +1 -1
- package/fesm2022/signality-core-browser-page-visibility.mjs +1 -1
- package/fesm2022/signality-core-browser-page-visibility.mjs.map +1 -1
- package/fesm2022/signality-core-browser-permission-state.mjs +57 -0
- package/fesm2022/signality-core-browser-permission-state.mjs.map +1 -0
- package/fesm2022/signality-core-browser-picture-in-picture.mjs +30 -13
- package/fesm2022/signality-core-browser-picture-in-picture.mjs.map +1 -1
- package/fesm2022/signality-core-browser-screen-orientation.mjs +1 -1
- package/fesm2022/signality-core-browser-screen-orientation.mjs.map +1 -1
- package/fesm2022/signality-core-browser-speech-recognition.mjs +7 -19
- package/fesm2022/signality-core-browser-speech-recognition.mjs.map +1 -1
- package/fesm2022/signality-core-browser-speech-synthesis.mjs +14 -16
- package/fesm2022/signality-core-browser-speech-synthesis.mjs.map +1 -1
- package/fesm2022/signality-core-browser-storage.mjs +1 -1
- package/fesm2022/signality-core-browser-storage.mjs.map +1 -1
- package/fesm2022/signality-core-browser-text-direction.mjs +1 -4
- package/fesm2022/signality-core-browser-text-direction.mjs.map +1 -1
- package/fesm2022/{signality-core-elements-text-selection.mjs → signality-core-browser-text-selection.mjs} +2 -2
- package/fesm2022/signality-core-browser-text-selection.mjs.map +1 -0
- package/fesm2022/signality-core-browser-vibration.mjs +14 -5
- package/fesm2022/signality-core-browser-vibration.mjs.map +1 -1
- package/fesm2022/signality-core-browser-wake-lock.mjs +33 -16
- package/fesm2022/signality-core-browser-wake-lock.mjs.map +1 -1
- package/fesm2022/signality-core-browser-web-notification.mjs +5 -7
- package/fesm2022/signality-core-browser-web-notification.mjs.map +1 -1
- package/fesm2022/signality-core-browser-web-share.mjs +3 -5
- package/fesm2022/signality-core-browser-web-share.mjs.map +1 -1
- package/fesm2022/signality-core-browser-web-worker.mjs +6 -3
- package/fesm2022/signality-core-browser-web-worker.mjs.map +1 -1
- package/fesm2022/signality-core-browser-window-focus.mjs +48 -0
- package/fesm2022/signality-core-browser-window-focus.mjs.map +1 -0
- package/fesm2022/{signality-core-elements-window-size.mjs → signality-core-browser-window-size.mjs} +4 -24
- package/fesm2022/signality-core-browser-window-size.mjs.map +1 -0
- package/fesm2022/signality-core-browser.mjs +8 -1
- package/fesm2022/signality-core-browser.mjs.map +1 -1
- package/fesm2022/signality-core-elements-active-element.mjs +1 -1
- package/fesm2022/signality-core-elements-active-element.mjs.map +1 -1
- package/fesm2022/signality-core-elements-dropzone.mjs +28 -29
- package/fesm2022/signality-core-elements-dropzone.mjs.map +1 -1
- package/fesm2022/signality-core-elements-element-focus-within.mjs +1 -1
- package/fesm2022/signality-core-elements-element-focus-within.mjs.map +1 -1
- package/fesm2022/signality-core-elements-element-focus.mjs +1 -1
- package/fesm2022/signality-core-elements-element-focus.mjs.map +1 -1
- package/fesm2022/signality-core-elements-element-hover.mjs +1 -1
- package/fesm2022/signality-core-elements-element-hover.mjs.map +1 -1
- package/fesm2022/signality-core-elements-element-size.mjs +19 -24
- package/fesm2022/signality-core-elements-element-size.mjs.map +1 -1
- package/fesm2022/signality-core-elements-element-visibility.mjs +2 -2
- package/fesm2022/signality-core-elements-element-visibility.mjs.map +1 -1
- package/fesm2022/signality-core-elements-mouse-position.mjs +3 -3
- package/fesm2022/signality-core-elements-mouse-position.mjs.map +1 -1
- package/fesm2022/signality-core-elements-on-click-outside.mjs +1 -1
- package/fesm2022/signality-core-elements-on-click-outside.mjs.map +1 -1
- package/fesm2022/signality-core-elements-on-disconnect.mjs +1 -1
- package/fesm2022/signality-core-elements-on-disconnect.mjs.map +1 -1
- package/fesm2022/signality-core-elements-on-long-press.mjs +1 -1
- package/fesm2022/signality-core-elements-on-long-press.mjs.map +1 -1
- package/fesm2022/signality-core-elements-pointer-swipe.mjs +1 -1
- package/fesm2022/signality-core-elements-pointer-swipe.mjs.map +1 -1
- package/fesm2022/signality-core-elements-scroll-position.mjs +2 -2
- package/fesm2022/signality-core-elements-scroll-position.mjs.map +1 -1
- package/fesm2022/signality-core-elements-swipe.mjs +1 -1
- package/fesm2022/signality-core-elements-swipe.mjs.map +1 -1
- package/fesm2022/signality-core-elements.mjs +0 -2
- package/fesm2022/signality-core-elements.mjs.map +1 -1
- package/fesm2022/signality-core-internal.mjs +54 -7
- package/fesm2022/signality-core-internal.mjs.map +1 -1
- package/fesm2022/signality-core-observers-intersection-observer.mjs +3 -2
- package/fesm2022/signality-core-observers-intersection-observer.mjs.map +1 -1
- package/fesm2022/signality-core-observers-mutation-observer.mjs +3 -2
- package/fesm2022/signality-core-observers-mutation-observer.mjs.map +1 -1
- package/fesm2022/signality-core-observers-resize-observer.mjs +3 -2
- package/fesm2022/signality-core-observers-resize-observer.mjs.map +1 -1
- package/fesm2022/signality-core-observers.mjs +0 -1
- package/fesm2022/signality-core-observers.mjs.map +1 -1
- package/fesm2022/signality-core-reactivity-debounced.mjs.map +1 -1
- package/fesm2022/signality-core-reactivity-throttled.mjs.map +1 -1
- package/fesm2022/signality-core-reactivity-watcher.mjs.map +1 -1
- package/fesm2022/signality-core-router-fragment.mjs +1 -1
- package/fesm2022/signality-core-router-fragment.mjs.map +1 -1
- package/fesm2022/signality-core-router-params.mjs +1 -1
- package/fesm2022/signality-core-router-params.mjs.map +1 -1
- package/fesm2022/signality-core-router-query-params.mjs.map +1 -1
- package/fesm2022/signality-core-router-route-data.mjs +1 -1
- package/fesm2022/signality-core-router-route-data.mjs.map +1 -1
- package/fesm2022/signality-core-router-router-listener.mjs.map +1 -1
- package/fesm2022/signality-core-router-title.mjs +1 -1
- package/fesm2022/signality-core-router-title.mjs.map +1 -1
- package/fesm2022/signality-core-router-url.mjs +1 -1
- package/fesm2022/signality-core-router-url.mjs.map +1 -1
- package/fesm2022/signality-core-scheduling-debounce-callback.mjs +1 -1
- package/fesm2022/signality-core-scheduling-debounce-callback.mjs.map +1 -1
- package/fesm2022/signality-core-scheduling-interval.mjs +27 -72
- package/fesm2022/signality-core-scheduling-interval.mjs.map +1 -1
- package/internal/utils/assert.d.ts +2 -0
- package/internal/utils/dom/index.d.ts +1 -0
- package/internal/utils/dom/is-element.d.ts +1 -1
- package/internal/utils/dom/is-event-target.d.ts +1 -0
- package/internal/utils/files/index.d.ts +1 -0
- package/internal/utils/files/is-accepted-file.d.ts +11 -0
- package/internal/utils/index.d.ts +3 -0
- package/internal/utils/to-element.d.ts +1 -1
- package/internal/utils/unref-element.d.ts +2 -0
- package/observers/index.d.ts +0 -1
- package/observers/intersection-observer/index.d.ts +22 -1
- package/observers/mutation-observer/index.d.ts +43 -1
- package/observers/resize-observer/index.d.ts +13 -1
- package/package.json +25 -17
- package/reactivity/debounced/index.d.ts +2 -2
- package/reactivity/throttled/index.d.ts +2 -2
- package/reactivity/watcher/index.d.ts +2 -2
- package/router/fragment/index.d.ts +1 -1
- package/router/params/index.d.ts +1 -1
- package/router/query-params/index.d.ts +5 -3
- package/router/route-data/index.d.ts +1 -1
- package/router/router-listener/index.d.ts +1 -1
- package/router/title/index.d.ts +1 -1
- package/router/url/index.d.ts +1 -1
- package/scheduling/debounce-callback/index.d.ts +1 -1
- package/scheduling/interval/index.d.ts +19 -27
- package/browser/pointer-lock-element/index.d.ts +0 -22
- package/fesm2022/signality-core-browser-pointer-lock-element.mjs +0 -43
- package/fesm2022/signality-core-browser-pointer-lock-element.mjs.map +0 -1
- package/fesm2022/signality-core-elements-text-selection.mjs.map +0 -1
- package/fesm2022/signality-core-elements-window-size.mjs.map +0 -1
- package/fesm2022/signality-core-observers-performance-observer.mjs +0 -84
- package/fesm2022/signality-core-observers-performance-observer.mjs.map +0 -1
- package/observers/performance-observer/index.d.ts +0 -58
|
@@ -2,37 +2,55 @@ import { type CreateSignalOptions, type Signal } from '@angular/core';
|
|
|
2
2
|
import type { MaybeElementSignal, MaybeSignal, WithInjector } from '@signality/core/types';
|
|
3
3
|
export interface ElementVisibilityOptions extends CreateSignalOptions<ElementVisibilityValue>, WithInjector {
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Fraction of the element that must be visible to trigger a change.
|
|
6
|
+
* A single number or an array of thresholds, each between `0` and `1`.
|
|
7
|
+
*
|
|
6
8
|
* @default 0
|
|
9
|
+
* @see [IntersectionObserver: thresholds on MDN](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/thresholds)
|
|
7
10
|
*/
|
|
8
11
|
readonly threshold?: MaybeSignal<number | number[]>;
|
|
9
12
|
/**
|
|
10
|
-
* Scrollable ancestor
|
|
13
|
+
* Scrollable ancestor used as the viewport for intersection checks.
|
|
14
|
+
* `null` or `undefined` defaults to the browser viewport.
|
|
15
|
+
*
|
|
11
16
|
* @default undefined
|
|
17
|
+
* @see [IntersectionObserver: root on MDN](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/root)
|
|
12
18
|
*/
|
|
13
19
|
readonly root?: MaybeElementSignal<Element> | Document;
|
|
14
20
|
/**
|
|
15
|
-
*
|
|
21
|
+
* CSS margin applied around the root before computing intersections.
|
|
22
|
+
* Accepts values in the same format as the CSS `margin` property (e.g. `'10px 0px'`).
|
|
23
|
+
*
|
|
16
24
|
* @default '0px'
|
|
25
|
+
* @see [IntersectionObserver: rootMargin on MDN](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin)
|
|
17
26
|
*/
|
|
18
27
|
readonly rootMargin?: MaybeSignal<string>;
|
|
19
28
|
/**
|
|
20
29
|
* Initial value for SSR.
|
|
30
|
+
*
|
|
21
31
|
* @default { isVisible: true, ratio: 1 }
|
|
22
32
|
*/
|
|
23
33
|
readonly initialValue?: ElementVisibilityValue;
|
|
24
34
|
}
|
|
25
35
|
export interface ElementVisibilityValue {
|
|
26
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Whether the element is currently intersecting the root (visible in the viewport).
|
|
38
|
+
*
|
|
39
|
+
* @see [IntersectionObserverEntry: isIntersecting on MDN](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry/isIntersecting)
|
|
40
|
+
*/
|
|
27
41
|
readonly isVisible: boolean;
|
|
28
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Fraction of the element visible within the root, from `0.0` (not visible) to `1.0` (fully visible).
|
|
44
|
+
*
|
|
45
|
+
* @see [IntersectionObserverEntry: intersectionRatio on MDN](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry/intersectionRatio)
|
|
46
|
+
*/
|
|
29
47
|
readonly ratio: number;
|
|
30
48
|
}
|
|
31
49
|
/**
|
|
32
50
|
* Signal-based wrapper around the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).
|
|
33
51
|
*
|
|
34
52
|
* @param target - The element to observe
|
|
35
|
-
* @param options - Optional configuration
|
|
53
|
+
* @param options - Optional configuration
|
|
36
54
|
* @returns A signal containing the current visibility state
|
|
37
55
|
*
|
|
38
56
|
* @example
|
|
@@ -44,7 +62,7 @@ export interface ElementVisibilityValue {
|
|
|
44
62
|
* </div>
|
|
45
63
|
* `
|
|
46
64
|
* })
|
|
47
|
-
* class
|
|
65
|
+
* export class VisibilityDemo {
|
|
48
66
|
* readonly section = viewChild<ElementRef>('section');
|
|
49
67
|
* readonly visibility = elementVisibility(this.section);
|
|
50
68
|
* }
|
package/elements/index.d.ts
CHANGED
|
@@ -12,5 +12,3 @@ export * from '@signality/core/elements/pointer-swipe';
|
|
|
12
12
|
export * from '@signality/core/elements/on-disconnect';
|
|
13
13
|
export * from '@signality/core/elements/scroll-position';
|
|
14
14
|
export * from '@signality/core/elements/swipe';
|
|
15
|
-
export * from '@signality/core/elements/text-selection';
|
|
16
|
-
export * from '@signality/core/elements/window-size';
|
|
@@ -1,33 +1,53 @@
|
|
|
1
1
|
import { type Signal } from '@angular/core';
|
|
2
2
|
import type { MaybeElementSignal, WithInjector } from '@signality/core/types';
|
|
3
3
|
export interface MousePosition {
|
|
4
|
+
/** Horizontal coordinate in pixels. */
|
|
4
5
|
readonly x: number;
|
|
6
|
+
/** Vertical coordinate in pixels. */
|
|
5
7
|
readonly y: number;
|
|
6
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Coordinate space used to report mouse position.
|
|
11
|
+
*
|
|
12
|
+
* - `'page'` — relative to the document origin, includes scroll offset.
|
|
13
|
+
* - `'client'` — relative to the viewport, unaffected by scroll.
|
|
14
|
+
* - `'screen'` — relative to the physical screen.
|
|
15
|
+
*
|
|
16
|
+
* @see [MouseEvent.pageX on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageX)
|
|
17
|
+
* @see [MouseEvent.clientX on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/clientX)
|
|
18
|
+
* @see [MouseEvent.screenX on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/screenX)
|
|
19
|
+
*/
|
|
7
20
|
export type MouseCoordinateType = 'page' | 'client' | 'screen';
|
|
8
21
|
export interface MousePositionOptions extends WithInjector {
|
|
9
22
|
/**
|
|
10
|
-
* Element or window to track mouse position on.
|
|
23
|
+
* Element or `window` to track mouse position on.
|
|
24
|
+
* When an element signal is provided, tracking stops on element disconnect.
|
|
25
|
+
*
|
|
11
26
|
* @default window
|
|
12
27
|
*/
|
|
13
28
|
readonly target?: MaybeElementSignal<Element> | Window;
|
|
14
29
|
/**
|
|
15
|
-
* Coordinate
|
|
30
|
+
* Coordinate space for the reported position. See {@link MouseCoordinateType}.
|
|
31
|
+
*
|
|
16
32
|
* @default 'page'
|
|
17
33
|
*/
|
|
18
34
|
readonly type?: MouseCoordinateType;
|
|
19
35
|
/**
|
|
20
|
-
* Whether to track touch events
|
|
36
|
+
* Whether to also track touch events (`touchmove`).
|
|
37
|
+
*
|
|
21
38
|
* @default true
|
|
39
|
+
* @see [TouchEvent on MDN](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent)
|
|
22
40
|
*/
|
|
23
41
|
readonly touch?: boolean;
|
|
24
42
|
/**
|
|
25
|
-
* Initial
|
|
43
|
+
* Initial value for SSR.
|
|
44
|
+
*
|
|
45
|
+
* @default { x: 0, y: 0 }
|
|
26
46
|
*/
|
|
27
47
|
readonly initialValue?: MousePosition;
|
|
28
48
|
}
|
|
29
49
|
/**
|
|
30
|
-
* Reactive tracking of mouse position.
|
|
50
|
+
* Reactive tracking of mouse position using the [mousemove](https://developer.mozilla.org/en-US/docs/Web/API/Element/mousemove_event) event.
|
|
31
51
|
* Track cursor coordinates globally or relative to an element.
|
|
32
52
|
*
|
|
33
53
|
* @param options - Optional configuration
|
|
@@ -40,7 +60,7 @@ export interface MousePositionOptions extends WithInjector {
|
|
|
40
60
|
* <p>Mouse position: X={{ position().x }}, Y={{ position().y }}</p>
|
|
41
61
|
* `
|
|
42
62
|
* })
|
|
43
|
-
* class MouseTracker {
|
|
63
|
+
* export class MouseTracker {
|
|
44
64
|
* readonly position = mousePosition();
|
|
45
65
|
* }
|
|
46
66
|
* ```
|
|
@@ -55,7 +75,7 @@ export interface MousePositionOptions extends WithInjector {
|
|
|
55
75
|
* </div>
|
|
56
76
|
* `
|
|
57
77
|
* })
|
|
58
|
-
* class MouseElementTracker {
|
|
78
|
+
* export class MouseElementTracker {
|
|
59
79
|
* readonly box = viewChild<ElementRef>('box');
|
|
60
80
|
* readonly position = mousePosition({ target: this.box });
|
|
61
81
|
* }
|
|
@@ -71,7 +71,7 @@ export interface ScrollPositionRef {
|
|
|
71
71
|
* }
|
|
72
72
|
* `
|
|
73
73
|
* })
|
|
74
|
-
* class ScrollTracker {
|
|
74
|
+
* export class ScrollTracker {
|
|
75
75
|
* readonly scrollPos = scrollPosition();
|
|
76
76
|
* }
|
|
77
77
|
* ```
|
|
@@ -87,7 +87,7 @@ export interface ScrollPositionRef {
|
|
|
87
87
|
* <p>Scroll position: {{ pos.y() }}</p>
|
|
88
88
|
* `
|
|
89
89
|
* })
|
|
90
|
-
* class ScrollableComponent {
|
|
90
|
+
* export class ScrollableComponent {
|
|
91
91
|
* readonly scrollableEl = viewChild<ElementRef>('scrollable');
|
|
92
92
|
* readonly pos = scrollPosition({ target: this.scrollableEl });
|
|
93
93
|
* }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signality-core-browser-battery.mjs","sources":["../../../projects/core/browser/battery/index.ts","../../../projects/core/browser/battery/signality-core-browser-battery.ts"],"sourcesContent":["import { type Signal, signal } from '@angular/core';\nimport { constSignal, setupContext } from '@signality/core/internal';\nimport type { WithInjector } from '@signality/core/types';\nimport { listener, setupSync } from '@signality/core/browser/listener';\n\nexport type BatteryOptions = WithInjector;\n\nexport interface BatteryRef {\n readonly
|
|
1
|
+
{"version":3,"file":"signality-core-browser-battery.mjs","sources":["../../../projects/core/browser/battery/index.ts","../../../projects/core/browser/battery/signality-core-browser-battery.ts"],"sourcesContent":["import { type Signal, signal } from '@angular/core';\nimport { constSignal, setupContext } from '@signality/core/internal';\nimport type { WithInjector } from '@signality/core/types';\nimport { listener, setupSync } from '@signality/core/browser/listener';\n\nexport type BatteryOptions = WithInjector;\n\nexport interface BatteryRef {\n /**\n * Whether the Battery Status API is supported in the current browser.\n *\n * @see [Battery Status API browser compatibility on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Battery_Status_API#browser_compatibility)\n */\n readonly isSupported: Signal<boolean>;\n\n /**\n * Whether the battery is currently charging.\n *\n * @see [BatteryManager: charging on MDN](https://developer.mozilla.org/en-US/docs/Web/API/BatteryManager/charging)\n */\n readonly charging: Signal<boolean>;\n\n /**\n * Time in seconds until the battery is fully charged. `Infinity` if not charging.\n *\n * @see [BatteryManager: chargingTime on MDN](https://developer.mozilla.org/en-US/docs/Web/API/BatteryManager/chargingTime)\n */\n readonly chargingTime: Signal<number>;\n\n /**\n * Time in seconds until the battery is fully discharged. `Infinity` if charging.\n *\n * @see [BatteryManager: dischargingTime on MDN](https://developer.mozilla.org/en-US/docs/Web/API/BatteryManager/dischargingTime)\n */\n readonly dischargingTime: Signal<number>;\n\n /**\n * Battery level as a value between `0.0` and `1.0`.\n *\n * @see [BatteryManager: level on MDN](https://developer.mozilla.org/en-US/docs/Web/API/BatteryManager/level)\n */\n readonly level: Signal<number>;\n}\n\n/**\n * Signal-based wrapper around the [Battery Status API](https://developer.mozilla.org/en-US/docs/Web/API/Battery_Status_API).\n *\n * @param options - Optional configuration with injector\n * @returns A BatteryRef with battery status signals\n *\n * @example\n * ```typescript\n * @Component({\n * template: `\n * @if (batteryStatus.isSupported()) {\n * <div>\n * <p>Charging: {{ batteryStatus.charging() }}</p>\n * <p>Level: {{ batteryStatus.level() * 100 }}%</p>\n * </div>\n * }\n * `\n * })\n * export class BatteryDemo {\n * readonly batteryStatus = battery();\n * }\n * ```\n */\nexport function battery(options?: BatteryOptions): BatteryRef {\n const { runInContext } = setupContext(options?.injector, battery);\n\n return runInContext(({ isBrowser, injector }) => {\n const isSupported = constSignal(\n isBrowser && 'getBattery' in navigator && typeof navigator.getBattery === 'function'\n );\n\n if (!isSupported()) {\n return {\n isSupported,\n charging: constSignal(false),\n chargingTime: constSignal(0),\n dischargingTime: constSignal(0),\n level: constSignal(1),\n };\n }\n\n const charging = signal(false);\n const chargingTime = signal(0);\n const dischargingTime = signal(0);\n const level = signal(1);\n\n function update(this: BatteryManager) {\n charging.set(this.charging);\n chargingTime.set(this.chargingTime);\n dischargingTime.set(this.dischargingTime);\n level.set(this.level);\n }\n\n (navigator as NavigatorWithBattery).getBattery().then(battery => {\n update.call(battery);\n\n setupSync(() => {\n for (const event of BATTERY_EVENTS) {\n listener.passive(battery, event, update, { injector });\n }\n });\n });\n\n return {\n isSupported,\n charging: charging.asReadonly(),\n chargingTime: chargingTime.asReadonly(),\n dischargingTime: dischargingTime.asReadonly(),\n level: level.asReadonly(),\n };\n });\n}\n\ninterface NavigatorWithBattery extends Navigator {\n readonly getBattery: () => Promise<BatteryManager>;\n}\n\ninterface BatteryManager extends EventTarget {\n readonly charging: boolean;\n readonly chargingTime: number;\n readonly dischargingTime: number;\n readonly level: number;\n}\n\nconst BATTERY_EVENTS = [\n 'chargingchange',\n 'chargingtimechange',\n 'dischargingtimechange',\n 'levelchange',\n] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AA4CA;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACG,SAAU,OAAO,CAAC,OAAwB,EAAA;AAC9C,IAAA,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC;IAEjE,OAAO,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAI;AAC9C,QAAA,MAAM,WAAW,GAAG,WAAW,CAC7B,SAAS,IAAI,YAAY,IAAI,SAAS,IAAI,OAAO,SAAS,CAAC,UAAU,KAAK,UAAU,CACrF;AAED,QAAA,IAAI,CAAC,WAAW,EAAE,EAAE;YAClB,OAAO;gBACL,WAAW;AACX,gBAAA,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC;AAC5B,gBAAA,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC;AAC5B,gBAAA,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC;AAC/B,gBAAA,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC;aACtB;QACH;AAEA,QAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,oDAAC;AAC9B,QAAA,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,wDAAC;AAC9B,QAAA,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,2DAAC;AACjC,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,iDAAC;AAEvB,QAAA,SAAS,MAAM,GAAA;AACb,YAAA,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;AAC3B,YAAA,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC;AACnC,YAAA,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC;AACzC,YAAA,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;QACvB;QAEC,SAAkC,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,OAAO,IAAG;AAC9D,YAAA,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;YAEpB,SAAS,CAAC,MAAK;AACb,gBAAA,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE;AAClC,oBAAA,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC;gBACxD;AACF,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;QAEF,OAAO;YACL,WAAW;AACX,YAAA,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE;AAC/B,YAAA,YAAY,EAAE,YAAY,CAAC,UAAU,EAAE;AACvC,YAAA,eAAe,EAAE,eAAe,CAAC,UAAU,EAAE;AAC7C,YAAA,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE;SAC1B;AACH,IAAA,CAAC,CAAC;AACJ;AAaA,MAAM,cAAc,GAAG;IACrB,gBAAgB;IAChB,oBAAoB;IACpB,uBAAuB;IACvB,aAAa;CACL;;ACrIV;;AAEG;;;;"}
|
|
@@ -18,7 +18,7 @@ import { setupSync, listener } from '@signality/core/browser/listener';
|
|
|
18
18
|
* }
|
|
19
19
|
* `
|
|
20
20
|
* })
|
|
21
|
-
* class
|
|
21
|
+
* export class BluetoothDemo {
|
|
22
22
|
* readonly bt = bluetooth();
|
|
23
23
|
* }
|
|
24
24
|
* ```
|
|
@@ -39,32 +39,44 @@ function bluetooth(options) {
|
|
|
39
39
|
disconnect: NOOP_FN,
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
-
const
|
|
42
|
+
const requestOptions = {
|
|
43
|
+
...(options?.filters?.length
|
|
44
|
+
? { filters: options.filters }
|
|
45
|
+
: { acceptAllDevices: options?.acceptAllDevices ?? true }),
|
|
46
|
+
optionalServices: options?.optionalServices ?? [],
|
|
47
|
+
};
|
|
43
48
|
const isConnected = signal(false, ...(ngDevMode ? [{ debugName: "isConnected" }] : []));
|
|
44
49
|
const isConnecting = signal(false, ...(ngDevMode ? [{ debugName: "isConnecting" }] : []));
|
|
45
50
|
const device = signal(null, ...(ngDevMode ? [{ debugName: "device" }] : []));
|
|
46
51
|
const server = signal(null, ...(ngDevMode ? [{ debugName: "server" }] : []));
|
|
47
52
|
const error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
48
|
-
|
|
53
|
+
let disconnectListener = null;
|
|
54
|
+
const disconnect = () => {
|
|
55
|
+
if (disconnectListener) {
|
|
56
|
+
disconnectListener?.destroy();
|
|
57
|
+
disconnectListener = null;
|
|
58
|
+
}
|
|
59
|
+
const activeDevice = untracked(device);
|
|
60
|
+
if (activeDevice?.gatt?.connected) {
|
|
61
|
+
activeDevice.gatt.disconnect();
|
|
62
|
+
}
|
|
63
|
+
device.set(null);
|
|
64
|
+
server.set(null);
|
|
65
|
+
isConnected.set(false);
|
|
66
|
+
};
|
|
67
|
+
const request = async () => {
|
|
49
68
|
if (untracked(isConnecting)) {
|
|
50
69
|
return;
|
|
51
70
|
}
|
|
71
|
+
if (untracked(isConnected)) {
|
|
72
|
+
disconnect();
|
|
73
|
+
}
|
|
52
74
|
isConnecting.set(true);
|
|
53
75
|
error.set(null);
|
|
54
76
|
try {
|
|
55
|
-
const
|
|
56
|
-
acceptAllDevices: options?.acceptAllDevices ?? true,
|
|
57
|
-
optionalServices: options?.optionalServices ?? [],
|
|
58
|
-
...(options?.filters ? { filters: options.filters, acceptAllDevices: false } : {}),
|
|
59
|
-
};
|
|
60
|
-
const btDevice = await bluetooth.requestDevice(requestOpts);
|
|
77
|
+
const btDevice = await navigator.bluetooth.requestDevice(requestOptions);
|
|
61
78
|
device.set(btDevice);
|
|
62
|
-
setupSync(() => {
|
|
63
|
-
listener(btDevice, 'gattserverdisconnected', () => {
|
|
64
|
-
isConnected.set(false);
|
|
65
|
-
server.set(null);
|
|
66
|
-
}, { injector });
|
|
67
|
-
});
|
|
79
|
+
disconnectListener = setupSync(() => listener(btDevice, 'gattserverdisconnected', disconnect, { injector }));
|
|
68
80
|
const gattServer = await btDevice.gatt?.connect();
|
|
69
81
|
if (gattServer) {
|
|
70
82
|
server.set(gattServer);
|
|
@@ -73,23 +85,12 @@ function bluetooth(options) {
|
|
|
73
85
|
}
|
|
74
86
|
catch (e) {
|
|
75
87
|
error.set(e);
|
|
76
|
-
|
|
77
|
-
server.set(null);
|
|
78
|
-
isConnected.set(false);
|
|
88
|
+
disconnect();
|
|
79
89
|
}
|
|
80
90
|
finally {
|
|
81
91
|
isConnecting.set(false);
|
|
82
92
|
}
|
|
83
93
|
};
|
|
84
|
-
const disconnect = () => {
|
|
85
|
-
const currentDevice = untracked(device);
|
|
86
|
-
if (currentDevice?.gatt?.connected) {
|
|
87
|
-
currentDevice.gatt.disconnect();
|
|
88
|
-
}
|
|
89
|
-
device.set(null);
|
|
90
|
-
server.set(null);
|
|
91
|
-
isConnected.set(false);
|
|
92
|
-
};
|
|
93
94
|
onCleanup(disconnect);
|
|
94
95
|
return {
|
|
95
96
|
isSupported,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signality-core-browser-bluetooth.mjs","sources":["../../../projects/core/browser/bluetooth/index.ts","../../../projects/core/browser/bluetooth/signality-core-browser-bluetooth.ts"],"sourcesContent":["import { type Signal, signal, untracked } from '@angular/core';\nimport { constSignal, NOOP_ASYNC_FN, NOOP_FN, setupContext } from '@signality/core/internal';\nimport type { WithInjector } from '@signality/core/types';\nimport { listener, setupSync } from '@signality/core/browser/listener';\n\nexport interface BluetoothOptions extends WithInjector {\n /**\n * Accept any Bluetooth device.\n */\n readonly acceptAllDevices?: boolean;\n\n /**\n * Filters for device selection
|
|
1
|
+
{"version":3,"file":"signality-core-browser-bluetooth.mjs","sources":["../../../projects/core/browser/bluetooth/index.ts","../../../projects/core/browser/bluetooth/signality-core-browser-bluetooth.ts"],"sourcesContent":["import { type Signal, signal, untracked } from '@angular/core';\nimport { constSignal, NOOP_ASYNC_FN, NOOP_FN, setupContext } from '@signality/core/internal';\nimport type { WithInjector } from '@signality/core/types';\nimport { listener, ListenerRef, setupSync } from '@signality/core/browser/listener';\n\nexport interface BluetoothOptions extends WithInjector {\n /**\n * Accept any Bluetooth device without filtering.\n *\n * @default true\n * @see [requestDevice: acceptAllDevices on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth/requestDevice#acceptalldevices)\n */\n readonly acceptAllDevices?: boolean;\n\n /**\n * Filters for device selection. Mutually exclusive with `acceptAllDevices`.\n *\n * @default undefined\n * @see [requestDevice: filters on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth/requestDevice#filters)\n */\n readonly filters?: BluetoothLEScanFilter[];\n\n /**\n * Optional GATT services to access on the connected device.\n *\n * @default []\n * @see [requestDevice: optionalServices on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth/requestDevice#optionalservices)\n */\n readonly optionalServices?: BluetoothServiceUUID[];\n}\n\nexport interface BluetoothRef {\n /**\n * Whether Web Bluetooth API is supported in the current browser.\n *\n * @see [Web Bluetooth API browser compatibility on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility)\n */\n readonly isSupported: Signal<boolean>;\n\n /**\n * Whether a device is currently connected.\n */\n readonly isConnected: Signal<boolean>;\n\n /**\n * Whether a connection is in progress.\n */\n readonly isConnecting: Signal<boolean>;\n\n /**\n * Connected Bluetooth device.\n */\n readonly device: Signal<BluetoothDevice | null>;\n\n /**\n * GATT server of a connected device.\n */\n readonly server: Signal<BluetoothRemoteGATTServer | null>;\n\n /**\n * The last error that occurred.\n */\n readonly error: Signal<Error | null>;\n\n /**\n * Request device connection.\n */\n readonly request: () => Promise<void>;\n\n /**\n * Disconnect from a device.\n */\n readonly disconnect: () => void;\n}\n\n/**\n * Signal-based wrapper around the [Web Bluetooth API](https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth).\n *\n * @param options - Optional configuration\n * @returns A BluetoothRef with connection state and control methods\n *\n * @example\n * ```typescript\n * @Component({\n * template: `\n * <button (click)=\"bt.request()\">Connect</button>\n * @if (bt.isConnected()) {\n * <p>{{ bt.device()?.name }}</p>\n * }\n * `\n * })\n * export class BluetoothDemo {\n * readonly bt = bluetooth();\n * }\n * ```\n */\nexport function bluetooth(options?: BluetoothOptions): BluetoothRef {\n const { runInContext } = setupContext(options?.injector, bluetooth);\n\n return runInContext(({ isBrowser, injector, onCleanup }) => {\n const isSupported = constSignal(isBrowser && 'bluetooth' in navigator);\n\n if (!isSupported()) {\n return {\n isSupported,\n isConnected: constSignal(false),\n isConnecting: constSignal(false),\n device: constSignal(null),\n server: constSignal(null),\n error: constSignal(null),\n request: NOOP_ASYNC_FN,\n disconnect: NOOP_FN,\n };\n }\n\n const requestOptions = {\n ...(options?.filters?.length\n ? { filters: options.filters }\n : { acceptAllDevices: options?.acceptAllDevices ?? true }),\n optionalServices: options?.optionalServices ?? [],\n };\n\n const isConnected = signal(false);\n const isConnecting = signal(false);\n const device = signal<BluetoothDevice | null>(null);\n const server = signal<BluetoothRemoteGATTServer | null>(null);\n const error = signal<Error | null>(null);\n\n let disconnectListener: ListenerRef | null = null;\n\n const disconnect = () => {\n if (disconnectListener) {\n disconnectListener?.destroy();\n disconnectListener = null;\n }\n\n const activeDevice = untracked(device);\n\n if (activeDevice?.gatt?.connected) {\n activeDevice.gatt.disconnect();\n }\n\n device.set(null);\n server.set(null);\n isConnected.set(false);\n };\n\n const request = async (): Promise<void> => {\n if (untracked(isConnecting)) {\n return;\n }\n\n if (untracked(isConnected)) {\n disconnect();\n }\n\n isConnecting.set(true);\n error.set(null);\n\n try {\n const btDevice = await navigator.bluetooth.requestDevice(requestOptions);\n\n device.set(btDevice);\n\n disconnectListener = setupSync(() =>\n listener(btDevice, 'gattserverdisconnected', disconnect, { injector })\n );\n\n const gattServer = await btDevice.gatt?.connect();\n\n if (gattServer) {\n server.set(gattServer);\n isConnected.set(true);\n }\n } catch (e) {\n error.set(e as Error);\n disconnect();\n } finally {\n isConnecting.set(false);\n }\n };\n\n onCleanup(disconnect);\n\n return {\n isSupported,\n isConnected: isConnected.asReadonly(),\n isConnecting: isConnecting.asReadonly(),\n device: device.asReadonly(),\n server: server.asReadonly(),\n error: error.asReadonly(),\n request,\n disconnect,\n };\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -3,21 +3,30 @@ import { setupContext, constSignal } from '@signality/core/internal';
|
|
|
3
3
|
import { mediaQuery } from '@signality/core/browser/media-query';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Reactive breakpoint matching using matchMedia.
|
|
7
|
-
* Track responsive breakpoints with Angular signals.
|
|
6
|
+
* Reactive breakpoint matching using [matchMedia](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia).
|
|
8
7
|
*
|
|
9
8
|
* @param map - Object mapping breakpoint names to media queries
|
|
10
9
|
* @param options - Optional configuration
|
|
11
|
-
* @returns An object with signals for each breakpoint
|
|
10
|
+
* @returns An object with signals for each breakpoint and a `current` signal with active breakpoint keys
|
|
12
11
|
*
|
|
13
12
|
* @example
|
|
14
13
|
* ```typescript
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
14
|
+
* @Component({
|
|
15
|
+
* template: `
|
|
16
|
+
* @if (bp.mobile()) {
|
|
17
|
+
* <p>Mobile layout</p>
|
|
18
|
+
* } @else {
|
|
19
|
+
* <p>Desktop layout</p>
|
|
20
|
+
* }
|
|
21
|
+
* <p>Active: {{ bp.current() }}</p>
|
|
22
|
+
* `
|
|
23
|
+
* })
|
|
24
|
+
* export class Layout {
|
|
25
|
+
* readonly bp = breakpoints({
|
|
26
|
+
* mobile: '(max-width: 767px)',
|
|
27
|
+
* desktop: '(min-width: 768px)',
|
|
28
|
+
* });
|
|
29
|
+
* }
|
|
21
30
|
* ```
|
|
22
31
|
*/
|
|
23
32
|
function breakpoints(map, options) {
|
|
@@ -33,7 +42,7 @@ function breakpoints(map, options) {
|
|
|
33
42
|
if (isServer) {
|
|
34
43
|
return {
|
|
35
44
|
...queries,
|
|
36
|
-
current: constSignal(Object.keys(map).filter(key =>
|
|
45
|
+
current: constSignal(Object.keys(map).filter(key => initialValues[key])),
|
|
37
46
|
};
|
|
38
47
|
}
|
|
39
48
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signality-core-browser-breakpoints.mjs","sources":["../../../projects/core/browser/breakpoints/index.ts","../../../projects/core/browser/breakpoints/signality-core-browser-breakpoints.ts"],"sourcesContent":["import { computed, type Signal } from '@angular/core';\nimport { constSignal, setupContext } from '@signality/core/internal';\nimport type { WithInjector } from '@signality/core/types';\nimport { mediaQuery } from '@signality/core/browser/media-query';\n\nexport interface BreakpointsOptions<T extends Record<string, string>> extends WithInjector {\n /**\n * Initial values for SSR.\n */\n readonly initialValue?: Partial<Record<keyof T, boolean>>;\n}\n\nexport type BreakpointsRef<T extends Record<string, string>> = {\n readonly [K in keyof T]: Signal<boolean>;\n} & {\n readonly current: Signal<(keyof T)[]>;\n};\n\n/**\n * Reactive breakpoint matching using matchMedia.\n
|
|
1
|
+
{"version":3,"file":"signality-core-browser-breakpoints.mjs","sources":["../../../projects/core/browser/breakpoints/index.ts","../../../projects/core/browser/breakpoints/signality-core-browser-breakpoints.ts"],"sourcesContent":["import { computed, type Signal } from '@angular/core';\nimport { constSignal, setupContext } from '@signality/core/internal';\nimport type { WithInjector } from '@signality/core/types';\nimport { mediaQuery } from '@signality/core/browser/media-query';\n\nexport interface BreakpointsOptions<T extends Record<string, string>> extends WithInjector {\n /**\n * Initial values for SSR.\n */\n readonly initialValue?: Partial<Record<keyof T, boolean>>;\n}\n\nexport type BreakpointsRef<T extends Record<string, string>> = {\n readonly [K in keyof T]: Signal<boolean>;\n} & {\n /**\n * List of currently active breakpoint keys — keys whose media query matches at the moment.\n * Updated reactively whenever any breakpoint changes.\n */\n readonly current: Signal<(keyof T)[]>;\n};\n\n/**\n * Reactive breakpoint matching using [matchMedia](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia).\n *\n * @param map - Object mapping breakpoint names to media queries\n * @param options - Optional configuration\n * @returns An object with signals for each breakpoint and a `current` signal with active breakpoint keys\n *\n * @example\n * ```typescript\n * @Component({\n * template: `\n * @if (bp.mobile()) {\n * <p>Mobile layout</p>\n * } @else {\n * <p>Desktop layout</p>\n * }\n * <p>Active: {{ bp.current() }}</p>\n * `\n * })\n * export class Layout {\n * readonly bp = breakpoints({\n * mobile: '(max-width: 767px)',\n * desktop: '(min-width: 768px)',\n * });\n * }\n * ```\n */\nexport function breakpoints<T extends Record<string, string>>(\n map: T,\n options?: BreakpointsOptions<T>\n): BreakpointsRef<T> {\n const { runInContext } = setupContext(options?.injector, breakpoints);\n\n return runInContext(({ isServer }) => {\n const initialValues = (options?.initialValue ?? {}) as Record<keyof T, boolean>;\n const queries: Record<string, Signal<boolean>> = {};\n\n for (const key of Object.keys(map)) {\n const query = map[key];\n const initialValue = initialValues[key] ?? false;\n queries[key] = mediaQuery(query, { initialValue });\n }\n\n if (isServer) {\n return {\n ...queries,\n current: constSignal(Object.keys(map).filter(key => initialValues[key])),\n } as BreakpointsRef<T>;\n }\n\n return {\n ...queries,\n current: computed(() => Object.keys(map).filter(key => queries[key]())),\n } as BreakpointsRef<T>;\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAsBA;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BG;AACG,SAAU,WAAW,CACzB,GAAM,EACN,OAA+B,EAAA;AAE/B,IAAA,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC;AAErE,IAAA,OAAO,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAI;QACnC,MAAM,aAAa,IAAI,OAAO,EAAE,YAAY,IAAI,EAAE,CAA6B;QAC/E,MAAM,OAAO,GAAoC,EAAE;QAEnD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;AAClC,YAAA,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC;YACtB,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,KAAK;AAChD,YAAA,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,KAAK,EAAE,EAAE,YAAY,EAAE,CAAC;QACpD;QAEA,IAAI,QAAQ,EAAE;YACZ,OAAO;AACL,gBAAA,GAAG,OAAO;gBACV,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;aACpD;QACxB;QAEA,OAAO;AACL,YAAA,GAAG,OAAO;YACV,OAAO,EAAE,QAAQ,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;SACnD;AACxB,IAAA,CAAC,CAAC;AACJ;;AC7EA;;AAEG;;;;"}
|
|
@@ -19,7 +19,7 @@ import { setupSync, listener } from '@signality/core/browser/listener';
|
|
|
19
19
|
* <button (click)="sendMessage()">Send Message</button>
|
|
20
20
|
* `
|
|
21
21
|
* })
|
|
22
|
-
* class
|
|
22
|
+
* export class ChatDemo {
|
|
23
23
|
* readonly channel = broadcastChannel<string>('my-channel');
|
|
24
24
|
*
|
|
25
25
|
* sendMessage() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signality-core-browser-broadcast-channel.mjs","sources":["../../../projects/core/browser/broadcast-channel/index.ts","../../../projects/core/browser/broadcast-channel/signality-core-browser-broadcast-channel.ts"],"sourcesContent":["import { type Signal, signal } from '@angular/core';\nimport { constSignal, NOOP_FN, setupContext } from '@signality/core/internal';\nimport type { WithInjector } from '@signality/core/types';\nimport { listener, setupSync } from '@signality/core/browser/listener';\n\nexport type BroadcastChannelOptions = WithInjector;\n\nexport interface BroadcastChannelRef<T> {\n /** Last received data */\n readonly data: Signal<T | null>;\n\n /** The last error that occurred */\n readonly error: Signal<MessageEvent | null>;\n\n /** Whether the channel is closed */\n readonly isClosed: Signal<boolean>;\n\n /** Send a message to all tabs */\n readonly post: (data: T) => void;\n\n /** Close the channel */\n readonly close: () => void;\n}\n\n/**\n * Signal-based wrapper around the [Broadcast Channel API](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API).\n *\n * @param name - Channel name (must match across tabs)\n * @param options - Optional configuration\n * @returns A BroadcastChannelRef with data signal and control methods\n *\n * @example\n * ```typescript\n * @Component({\n * template: `\n * @if (channel.data(); as data) {\n * <p>Received: {{ data }}</p>\n * }\n * <button (click)=\"sendMessage()\">Send Message</button>\n * `\n * })\n * class
|
|
1
|
+
{"version":3,"file":"signality-core-browser-broadcast-channel.mjs","sources":["../../../projects/core/browser/broadcast-channel/index.ts","../../../projects/core/browser/broadcast-channel/signality-core-browser-broadcast-channel.ts"],"sourcesContent":["import { type Signal, signal } from '@angular/core';\nimport { constSignal, NOOP_FN, setupContext } from '@signality/core/internal';\nimport type { WithInjector } from '@signality/core/types';\nimport { listener, setupSync } from '@signality/core/browser/listener';\n\nexport type BroadcastChannelOptions = WithInjector;\n\nexport interface BroadcastChannelRef<T> {\n /** Last received data */\n readonly data: Signal<T | null>;\n\n /** The last error that occurred */\n readonly error: Signal<MessageEvent | null>;\n\n /** Whether the channel is closed */\n readonly isClosed: Signal<boolean>;\n\n /** Send a message to all tabs */\n readonly post: (data: T) => void;\n\n /** Close the channel */\n readonly close: () => void;\n}\n\n/**\n * Signal-based wrapper around the [Broadcast Channel API](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API).\n *\n * @param name - Channel name (must match across tabs)\n * @param options - Optional configuration\n * @returns A BroadcastChannelRef with data signal and control methods\n *\n * @example\n * ```typescript\n * @Component({\n * template: `\n * @if (channel.data(); as data) {\n * <p>Received: {{ data }}</p>\n * }\n * <button (click)=\"sendMessage()\">Send Message</button>\n * `\n * })\n * export class ChatDemo {\n * readonly channel = broadcastChannel<string>('my-channel');\n *\n * sendMessage() {\n * this.channel.post('Hello from this tab!');\n * }\n * }\n * ```\n */\nexport function broadcastChannel<T>(\n name: string,\n options?: BroadcastChannelOptions\n): BroadcastChannelRef<T> {\n const { runInContext } = setupContext(options?.injector, broadcastChannel);\n\n return runInContext(({ isServer, onCleanup }) => {\n if (isServer) {\n return {\n data: constSignal(null),\n error: constSignal(null),\n isClosed: constSignal(false),\n post: NOOP_FN,\n close: NOOP_FN,\n };\n }\n\n const data = signal<T | null>(null);\n const error = signal<MessageEvent | null>(null);\n const isClosed = signal(false);\n\n const channel = new BroadcastChannel(name);\n\n const post = (message: T) => {\n channel.postMessage(message);\n };\n\n const close = () => {\n channel.close();\n isClosed.set(true);\n };\n\n setupSync(() => {\n listener(channel, 'message', (e: MessageEvent<T>) => data.set(e.data));\n listener(channel, 'messageerror', error.set);\n });\n\n onCleanup(close);\n\n return {\n data: data.asReadonly(),\n error: error.asReadonly(),\n isClosed: isClosed.asReadonly(),\n post,\n close,\n };\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAwBA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACG,SAAU,gBAAgB,CAC9B,IAAY,EACZ,OAAiC,EAAA;AAEjC,IAAA,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,gBAAgB,CAAC;IAE1E,OAAO,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAI;QAC9C,IAAI,QAAQ,EAAE;YACZ,OAAO;AACL,gBAAA,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC;AACvB,gBAAA,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC;AACxB,gBAAA,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC;AAC5B,gBAAA,IAAI,EAAE,OAAO;AACb,gBAAA,KAAK,EAAE,OAAO;aACf;QACH;AAEA,QAAA,MAAM,IAAI,GAAG,MAAM,CAAW,IAAI,gDAAC;AACnC,QAAA,MAAM,KAAK,GAAG,MAAM,CAAsB,IAAI,iDAAC;AAC/C,QAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,oDAAC;AAE9B,QAAA,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC;AAE1C,QAAA,MAAM,IAAI,GAAG,CAAC,OAAU,KAAI;AAC1B,YAAA,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;AAC9B,QAAA,CAAC;QAED,MAAM,KAAK,GAAG,MAAK;YACjB,OAAO,CAAC,KAAK,EAAE;AACf,YAAA,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;AACpB,QAAA,CAAC;QAED,SAAS,CAAC,MAAK;AACb,YAAA,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAkB,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACtE,QAAQ,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC;AAC9C,QAAA,CAAC,CAAC;QAEF,SAAS,CAAC,KAAK,CAAC;QAEhB,OAAO;AACL,YAAA,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE;AACvB,YAAA,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE;AACzB,YAAA,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE;YAC/B,IAAI;YACJ,KAAK;SACN;AACH,IAAA,CAAC,CAAC;AACJ;;ACjGA;;AAEG;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signality-core-browser-browser-language.mjs","sources":["../../../projects/core/browser/browser-language/index.ts","../../../projects/core/browser/browser-language/signality-core-browser-browser-language.ts"],"sourcesContent":["import { type CreateSignalOptions, type Signal, signal } from '@angular/core';\nimport { constSignal, createToken, setupContext } from '@signality/core/internal';\nimport type { WithInjector } from '@signality/core/types';\nimport { listener, setupSync } from '@signality/core/browser/listener';\n\nexport interface BrowserLanguageOptions extends CreateSignalOptions<string>, WithInjector {\n /**\n * Initial value for SSR.\n * @default ''\n */\n readonly initialValue?: string;\n}\n\n/**\n * Reactive wrapper around the [Navigator.language](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language) property.\n *\n * @param options - Optional configuration including signal options and injector\n * @returns A signal containing the current browser language in BCP 47 format (e.g., 'en-US', 'fr-FR')\n *\n * @example\n * ```typescript\n * @Component({\n * template: `\n * <p>Current language: {{ language() }}</p>\n * @if (language() === 'en-US') {\n * <p>Welcome!</p>\n * } @else if (language() === 'fr-FR') {\n * <p>Bienvenue!</p>\n * }\n * `\n * })\n * class
|
|
1
|
+
{"version":3,"file":"signality-core-browser-browser-language.mjs","sources":["../../../projects/core/browser/browser-language/index.ts","../../../projects/core/browser/browser-language/signality-core-browser-browser-language.ts"],"sourcesContent":["import { type CreateSignalOptions, type Signal, signal } from '@angular/core';\nimport { constSignal, createToken, setupContext } from '@signality/core/internal';\nimport type { WithInjector } from '@signality/core/types';\nimport { listener, setupSync } from '@signality/core/browser/listener';\n\nexport interface BrowserLanguageOptions extends CreateSignalOptions<string>, WithInjector {\n /**\n * Initial value for SSR.\n * @default ''\n */\n readonly initialValue?: string;\n}\n\n/**\n * Reactive wrapper around the [Navigator.language](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language) property.\n *\n * @param options - Optional configuration including signal options and injector\n * @returns A signal containing the current browser language in BCP 47 format (e.g., 'en-US', 'fr-FR')\n *\n * @example\n * ```typescript\n * @Component({\n * template: `\n * <p>Current language: {{ language() }}</p>\n * @if (language() === 'en-US') {\n * <p>Welcome!</p>\n * } @else if (language() === 'fr-FR') {\n * <p>Bienvenue!</p>\n * }\n * `\n * })\n * export class LanguageDemo {\n * readonly language = browserLanguage();\n * }\n * ```\n */\nexport function browserLanguage(options?: BrowserLanguageOptions): Signal<string> {\n const { runInContext } = setupContext(options?.injector, browserLanguage);\n\n return runInContext(({ isServer }) => {\n if (isServer) {\n return constSignal(options?.initialValue ?? '');\n }\n\n const language = signal(navigator.language, options);\n\n setupSync(() => {\n listener(window, 'languagechange', () => language.set(navigator.language));\n });\n\n return language.asReadonly();\n });\n}\n\nexport const BROWSER_LANGUAGE = /* @__PURE__ */ createToken(browserLanguage);\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAaA;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACG,SAAU,eAAe,CAAC,OAAgC,EAAA;AAC9D,IAAA,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC;AAEzE,IAAA,OAAO,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAI;QACnC,IAAI,QAAQ,EAAE;YACZ,OAAO,WAAW,CAAC,OAAO,EAAE,YAAY,IAAI,EAAE,CAAC;QACjD;QAEA,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC;QAEpD,SAAS,CAAC,MAAK;AACb,YAAA,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AAC5E,QAAA,CAAC,CAAC;AAEF,QAAA,OAAO,QAAQ,CAAC,UAAU,EAAE;AAC9B,IAAA,CAAC,CAAC;AACJ;AAEO,MAAM,gBAAgB,mBAAmB,WAAW,CAAC,eAAe;;ACtD3E;;AAEG;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signality-core-browser-clipboard.mjs","sources":["../../../projects/core/browser/clipboard/index.ts","../../../projects/core/browser/clipboard/signality-core-browser-clipboard.ts"],"sourcesContent":["import { type Signal, signal } from '@angular/core';\nimport {\n constSignal,\n NOOP_ASYNC_FN,\n setupContext,\n type Timer,\n toValue,\n} from '@signality/core/internal';\nimport type { MaybeSignal, WithInjector } from '@signality/core/types';\n\nexport interface ClipboardOptions extends WithInjector {\n /**\n * How long `copied` stays `true` after copy (ms).\n * @default 1500\n */\n readonly copiedDuration?: MaybeSignal<number>;\n}\n\nexport interface ClipboardRef {\n
|
|
1
|
+
{"version":3,"file":"signality-core-browser-clipboard.mjs","sources":["../../../projects/core/browser/clipboard/index.ts","../../../projects/core/browser/clipboard/signality-core-browser-clipboard.ts"],"sourcesContent":["import { type Signal, signal } from '@angular/core';\nimport {\n constSignal,\n NOOP_ASYNC_FN,\n setupContext,\n type Timer,\n toValue,\n} from '@signality/core/internal';\nimport type { MaybeSignal, WithInjector } from '@signality/core/types';\n\nexport interface ClipboardOptions extends WithInjector {\n /**\n * How long `copied` stays `true` after copy (ms).\n * @default 1500\n */\n readonly copiedDuration?: MaybeSignal<number>;\n}\n\nexport interface ClipboardRef {\n /**\n * Whether the Clipboard API is supported in the current browser.\n *\n * @see [Clipboard API browser compatibility on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API#browser_compatibility)\n */\n readonly isSupported: Signal<boolean>;\n\n /**\n * The most recently copied or pasted text.\n */\n readonly text: Signal<string>;\n\n /**\n * Whether the text was recently copied. Resets to `false` after `copiedDuration` ms.\n */\n readonly copied: Signal<boolean>;\n\n /**\n * Write text to the clipboard.\n *\n * @see [Clipboard: writeText() on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText)\n */\n readonly copy: (text: string) => Promise<void>;\n\n /**\n * Read text from the clipboard.\n *\n * @see [Clipboard: readText() on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/readText)\n */\n readonly paste: () => Promise<string>;\n}\n\n/**\n * Signal-based wrapper around the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API).\n *\n * @param options - Optional configuration\n * @returns A ClipboardRef with text, copied, isSupported signals and copy/paste methods\n *\n * @example\n * ```typescript\n * @Component({\n * template: `\n * <input #input value=\"Hello World!\" />\n * <button (click)=\"copyText(input.value)\">Copy</button>\n * @if (cb.copied()) {\n * <span>Copied!</span>\n * }\n * `\n * })\n * export class ClipboardDemo {\n * readonly cb = clipboard();\n *\n * async copyText(text: string) {\n * await this.cb.copy(text);\n * }\n * }\n * ```\n */\nexport function clipboard(options?: ClipboardOptions): ClipboardRef {\n const { runInContext } = setupContext(options?.injector, clipboard);\n\n return runInContext(({ isBrowser, onCleanup }) => {\n const isSupported = constSignal(\n isBrowser && 'clipboard' in navigator && typeof navigator.clipboard?.writeText === 'function'\n );\n\n if (!isSupported()) {\n return {\n isSupported,\n text: constSignal(''),\n copied: constSignal(false),\n copy: NOOP_ASYNC_FN,\n paste: () => Promise.resolve(''),\n };\n }\n\n const copiedDuration = options?.copiedDuration ?? 1500;\n\n const text = signal('');\n const copied = signal(false);\n\n let copiedTimeout: Timer;\n\n const copy = async (value: string): Promise<void> => {\n try {\n await navigator.clipboard.writeText(value);\n\n text.set(value);\n copied.set(true);\n\n if (copiedTimeout) {\n clearTimeout(copiedTimeout);\n }\n\n copiedTimeout = setTimeout(() => {\n copied.set(false);\n copiedTimeout = undefined;\n }, toValue.untracked(copiedDuration));\n } catch (error) {\n copied.set(false);\n if (ngDevMode) {\n console.warn(\n `[clipboard] Failed to copy text to clipboard. ` +\n `This may be due to permission denied or clipboard access failed.`,\n error\n );\n }\n }\n };\n\n const paste = async (): Promise<string> => {\n try {\n const value = await navigator.clipboard.readText();\n text.set(value);\n return value;\n } catch (error) {\n if (ngDevMode) {\n console.warn(\n `[clipboard] Failed to read text from clipboard. ` +\n `This may be due to permission denied or clipboard access failed.`,\n error\n );\n }\n return '';\n }\n };\n\n onCleanup(() => {\n if (copiedTimeout) {\n clearTimeout(copiedTimeout);\n }\n });\n\n return {\n isSupported,\n text: text.asReadonly(),\n copied: copied.asReadonly(),\n copy,\n paste,\n };\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAmDA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACG,SAAU,SAAS,CAAC,OAA0B,EAAA;AAClD,IAAA,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC;IAEnE,OAAO,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,KAAI;AAC/C,QAAA,MAAM,WAAW,GAAG,WAAW,CAC7B,SAAS,IAAI,WAAW,IAAI,SAAS,IAAI,OAAO,SAAS,CAAC,SAAS,EAAE,SAAS,KAAK,UAAU,CAC9F;AAED,QAAA,IAAI,CAAC,WAAW,EAAE,EAAE;YAClB,OAAO;gBACL,WAAW;AACX,gBAAA,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;AACrB,gBAAA,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC;AAC1B,gBAAA,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;aACjC;QACH;AAEA,QAAA,MAAM,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,IAAI;AAEtD,QAAA,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,gDAAC;AACvB,QAAA,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,kDAAC;AAE5B,QAAA,IAAI,aAAoB;AAExB,QAAA,MAAM,IAAI,GAAG,OAAO,KAAa,KAAmB;AAClD,YAAA,IAAI;gBACF,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC;AAE1C,gBAAA,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACf,gBAAA,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;gBAEhB,IAAI,aAAa,EAAE;oBACjB,YAAY,CAAC,aAAa,CAAC;gBAC7B;AAEA,gBAAA,aAAa,GAAG,UAAU,CAAC,MAAK;AAC9B,oBAAA,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;oBACjB,aAAa,GAAG,SAAS;gBAC3B,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;YACvC;YAAE,OAAO,KAAK,EAAE;AACd,gBAAA,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;gBACjB,IAAI,SAAS,EAAE;oBACb,OAAO,CAAC,IAAI,CACV,CAAA,8CAAA,CAAgD;wBAC9C,CAAA,gEAAA,CAAkE,EACpE,KAAK,CACN;gBACH;YACF;AACF,QAAA,CAAC;AAED,QAAA,MAAM,KAAK,GAAG,YAA4B;AACxC,YAAA,IAAI;gBACF,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,QAAQ,EAAE;AAClD,gBAAA,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACf,gBAAA,OAAO,KAAK;YACd;YAAE,OAAO,KAAK,EAAE;gBACd,IAAI,SAAS,EAAE;oBACb,OAAO,CAAC,IAAI,CACV,CAAA,gDAAA,CAAkD;wBAChD,CAAA,gEAAA,CAAkE,EACpE,KAAK,CACN;gBACH;AACA,gBAAA,OAAO,EAAE;YACX;AACF,QAAA,CAAC;QAED,SAAS,CAAC,MAAK;YACb,IAAI,aAAa,EAAE;gBACjB,YAAY,CAAC,aAAa,CAAC;YAC7B;AACF,QAAA,CAAC,CAAC;QAEF,OAAO;YACL,WAAW;AACX,YAAA,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE;AACvB,YAAA,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE;YAC3B,IAAI;YACJ,KAAK;SACN;AACH,IAAA,CAAC,CAAC;AACJ;;AChKA;;AAEG;;;;"}
|
|
@@ -9,6 +9,19 @@ import { setupSync, listener } from '@signality/core/browser/listener';
|
|
|
9
9
|
* @param options - Optional configuration including injector
|
|
10
10
|
* @returns A DevicePostureRef with type signal
|
|
11
11
|
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* @Component({
|
|
15
|
+
* template: `
|
|
16
|
+
* @if (posture.isSupported()) {
|
|
17
|
+
* <p>Device posture: {{ posture.type() }}</p>
|
|
18
|
+
* }
|
|
19
|
+
* `
|
|
20
|
+
* })
|
|
21
|
+
* export class PostureDemo {
|
|
22
|
+
* readonly posture = devicePosture();
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
12
25
|
*/
|
|
13
26
|
function devicePosture(options) {
|
|
14
27
|
const { runInContext } = setupContext(options?.injector, devicePosture);
|