@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.
Files changed (261) hide show
  1. package/README.md +60 -0
  2. package/browser/battery/index.d.ts +34 -0
  3. package/browser/bluetooth/index.d.ts +56 -0
  4. package/browser/breakpoints/index.d.ts +32 -0
  5. package/browser/broadcast-channel/index.d.ts +42 -0
  6. package/browser/browser-language/index.d.ts +34 -0
  7. package/browser/clipboard/index.d.ts +48 -0
  8. package/browser/device-posture/index.d.ts +18 -0
  9. package/browser/display-media/index.d.ts +80 -0
  10. package/browser/eye-dropper/index.d.ts +47 -0
  11. package/browser/favicon/index.d.ts +39 -0
  12. package/browser/fps/index.d.ts +46 -0
  13. package/browser/gamepad/index.d.ts +28 -0
  14. package/browser/geolocation/index.d.ts +64 -0
  15. package/browser/index.d.ts +29 -0
  16. package/browser/input-modality/index.d.ts +26 -0
  17. package/browser/listener/index.d.ts +61 -0
  18. package/browser/media-query/index.d.ts +36 -0
  19. package/browser/network/index.d.ts +44 -0
  20. package/browser/online/index.d.ts +27 -0
  21. package/browser/page-visibility/index.d.ts +27 -0
  22. package/browser/picture-in-picture/index.d.ts +42 -0
  23. package/browser/pointer-lock-element/index.d.ts +22 -0
  24. package/browser/screen-orientation/index.d.ts +29 -0
  25. package/browser/speech-recognition/index.d.ts +77 -0
  26. package/browser/speech-synthesis/index.d.ts +76 -0
  27. package/browser/storage/index.d.ts +142 -0
  28. package/browser/text-direction/index.d.ts +43 -0
  29. package/browser/vibration/index.d.ts +37 -0
  30. package/browser/wake-lock/index.d.ts +37 -0
  31. package/browser/web-notification/index.d.ts +58 -0
  32. package/browser/web-share/index.d.ts +42 -0
  33. package/browser/web-worker/index.d.ts +52 -0
  34. package/elements/active-element/index.d.ts +27 -0
  35. package/elements/dropzone/index.d.ts +61 -0
  36. package/elements/element-focus/index.d.ts +38 -0
  37. package/elements/element-focus-within/index.d.ts +29 -0
  38. package/elements/element-hover/index.d.ts +27 -0
  39. package/elements/element-size/index.d.ts +40 -0
  40. package/elements/element-visibility/index.d.ts +53 -0
  41. package/elements/index.d.ts +16 -0
  42. package/elements/mouse-position/index.d.ts +64 -0
  43. package/elements/on-click-outside/index.d.ts +42 -0
  44. package/elements/on-disconnect/index.d.ts +45 -0
  45. package/elements/on-long-press/index.d.ts +44 -0
  46. package/elements/pointer-swipe/index.d.ts +58 -0
  47. package/elements/scroll-position/index.d.ts +96 -0
  48. package/elements/swipe/index.d.ts +49 -0
  49. package/elements/text-selection/index.d.ts +39 -0
  50. package/elements/window-size/index.d.ts +46 -0
  51. package/fesm2022/signality-core-browser-battery.mjs +80 -0
  52. package/fesm2022/signality-core-browser-battery.mjs.map +1 -0
  53. package/fesm2022/signality-core-browser-bluetooth.mjs +112 -0
  54. package/fesm2022/signality-core-browser-bluetooth.mjs.map +1 -0
  55. package/fesm2022/signality-core-browser-breakpoints.mjs +51 -0
  56. package/fesm2022/signality-core-browser-breakpoints.mjs.map +1 -0
  57. package/fesm2022/signality-core-browser-broadcast-channel.mjs +74 -0
  58. package/fesm2022/signality-core-browser-broadcast-channel.mjs.map +1 -0
  59. package/fesm2022/signality-core-browser-browser-language.mjs +48 -0
  60. package/fesm2022/signality-core-browser-browser-language.mjs.map +1 -0
  61. package/fesm2022/signality-core-browser-clipboard.mjs +102 -0
  62. package/fesm2022/signality-core-browser-clipboard.mjs.map +1 -0
  63. package/fesm2022/signality-core-browser-device-posture.mjs +40 -0
  64. package/fesm2022/signality-core-browser-device-posture.mjs.map +1 -0
  65. package/fesm2022/signality-core-browser-display-media.mjs +121 -0
  66. package/fesm2022/signality-core-browser-display-media.mjs.map +1 -0
  67. package/fesm2022/signality-core-browser-eye-dropper.mjs +82 -0
  68. package/fesm2022/signality-core-browser-eye-dropper.mjs.map +1 -0
  69. package/fesm2022/signality-core-browser-favicon.mjs +100 -0
  70. package/fesm2022/signality-core-browser-favicon.mjs.map +1 -0
  71. package/fesm2022/signality-core-browser-fps.mjs +103 -0
  72. package/fesm2022/signality-core-browser-fps.mjs.map +1 -0
  73. package/fesm2022/signality-core-browser-gamepad.mjs +93 -0
  74. package/fesm2022/signality-core-browser-gamepad.mjs.map +1 -0
  75. package/fesm2022/signality-core-browser-geolocation.mjs +120 -0
  76. package/fesm2022/signality-core-browser-geolocation.mjs.map +1 -0
  77. package/fesm2022/signality-core-browser-input-modality.mjs +64 -0
  78. package/fesm2022/signality-core-browser-input-modality.mjs.map +1 -0
  79. package/fesm2022/signality-core-browser-listener.mjs +132 -0
  80. package/fesm2022/signality-core-browser-listener.mjs.map +1 -0
  81. package/fesm2022/signality-core-browser-media-query.mjs +55 -0
  82. package/fesm2022/signality-core-browser-media-query.mjs.map +1 -0
  83. package/fesm2022/signality-core-browser-network.mjs +76 -0
  84. package/fesm2022/signality-core-browser-network.mjs.map +1 -0
  85. package/fesm2022/signality-core-browser-online.mjs +49 -0
  86. package/fesm2022/signality-core-browser-online.mjs.map +1 -0
  87. package/fesm2022/signality-core-browser-page-visibility.mjs +47 -0
  88. package/fesm2022/signality-core-browser-page-visibility.mjs.map +1 -0
  89. package/fesm2022/signality-core-browser-picture-in-picture.mjs +93 -0
  90. package/fesm2022/signality-core-browser-picture-in-picture.mjs.map +1 -0
  91. package/fesm2022/signality-core-browser-pointer-lock-element.mjs +43 -0
  92. package/fesm2022/signality-core-browser-pointer-lock-element.mjs.map +1 -0
  93. package/fesm2022/signality-core-browser-screen-orientation.mjs +43 -0
  94. package/fesm2022/signality-core-browser-screen-orientation.mjs.map +1 -0
  95. package/fesm2022/signality-core-browser-speech-recognition.mjs +171 -0
  96. package/fesm2022/signality-core-browser-speech-recognition.mjs.map +1 -0
  97. package/fesm2022/signality-core-browser-speech-synthesis.mjs +146 -0
  98. package/fesm2022/signality-core-browser-speech-synthesis.mjs.map +1 -0
  99. package/fesm2022/signality-core-browser-storage.mjs +261 -0
  100. package/fesm2022/signality-core-browser-storage.mjs.map +1 -0
  101. package/fesm2022/signality-core-browser-text-direction.mjs +62 -0
  102. package/fesm2022/signality-core-browser-text-direction.mjs.map +1 -0
  103. package/fesm2022/signality-core-browser-vibration.mjs +94 -0
  104. package/fesm2022/signality-core-browser-vibration.mjs.map +1 -0
  105. package/fesm2022/signality-core-browser-wake-lock.mjs +149 -0
  106. package/fesm2022/signality-core-browser-wake-lock.mjs.map +1 -0
  107. package/fesm2022/signality-core-browser-web-notification.mjs +137 -0
  108. package/fesm2022/signality-core-browser-web-notification.mjs.map +1 -0
  109. package/fesm2022/signality-core-browser-web-share.mjs +92 -0
  110. package/fesm2022/signality-core-browser-web-share.mjs.map +1 -0
  111. package/fesm2022/signality-core-browser-web-worker.mjs +105 -0
  112. package/fesm2022/signality-core-browser-web-worker.mjs.map +1 -0
  113. package/fesm2022/signality-core-browser.mjs +34 -0
  114. package/fesm2022/signality-core-browser.mjs.map +1 -0
  115. package/fesm2022/signality-core-elements-active-element.mjs +88 -0
  116. package/fesm2022/signality-core-elements-active-element.mjs.map +1 -0
  117. package/fesm2022/signality-core-elements-dropzone.mjs +158 -0
  118. package/fesm2022/signality-core-elements-dropzone.mjs.map +1 -0
  119. package/fesm2022/signality-core-elements-element-focus-within.mjs +56 -0
  120. package/fesm2022/signality-core-elements-element-focus-within.mjs.map +1 -0
  121. package/fesm2022/signality-core-elements-element-focus.mjs +54 -0
  122. package/fesm2022/signality-core-elements-element-focus.mjs.map +1 -0
  123. package/fesm2022/signality-core-elements-element-hover.mjs +48 -0
  124. package/fesm2022/signality-core-elements-element-hover.mjs.map +1 -0
  125. package/fesm2022/signality-core-elements-element-size.mjs +73 -0
  126. package/fesm2022/signality-core-elements-element-size.mjs.map +1 -0
  127. package/fesm2022/signality-core-elements-element-visibility.mjs +76 -0
  128. package/fesm2022/signality-core-elements-element-visibility.mjs.map +1 -0
  129. package/fesm2022/signality-core-elements-mouse-position.mjs +109 -0
  130. package/fesm2022/signality-core-elements-mouse-position.mjs.map +1 -0
  131. package/fesm2022/signality-core-elements-on-click-outside.mjs +97 -0
  132. package/fesm2022/signality-core-elements-on-click-outside.mjs.map +1 -0
  133. package/fesm2022/signality-core-elements-on-disconnect.mjs +99 -0
  134. package/fesm2022/signality-core-elements-on-disconnect.mjs.map +1 -0
  135. package/fesm2022/signality-core-elements-on-long-press.mjs +84 -0
  136. package/fesm2022/signality-core-elements-on-long-press.mjs.map +1 -0
  137. package/fesm2022/signality-core-elements-pointer-swipe.mjs +116 -0
  138. package/fesm2022/signality-core-elements-pointer-swipe.mjs.map +1 -0
  139. package/fesm2022/signality-core-elements-scroll-position.mjs +175 -0
  140. package/fesm2022/signality-core-elements-scroll-position.mjs.map +1 -0
  141. package/fesm2022/signality-core-elements-swipe.mjs +107 -0
  142. package/fesm2022/signality-core-elements-swipe.mjs.map +1 -0
  143. package/fesm2022/signality-core-elements-text-selection.mjs +70 -0
  144. package/fesm2022/signality-core-elements-text-selection.mjs.map +1 -0
  145. package/fesm2022/signality-core-elements-window-size.mjs +81 -0
  146. package/fesm2022/signality-core-elements-window-size.mjs.map +1 -0
  147. package/fesm2022/signality-core-elements.mjs +21 -0
  148. package/fesm2022/signality-core-elements.mjs.map +1 -0
  149. package/fesm2022/signality-core-forms-cva.mjs +140 -0
  150. package/fesm2022/signality-core-forms-cva.mjs.map +1 -0
  151. package/fesm2022/signality-core-forms.mjs +6 -0
  152. package/fesm2022/signality-core-forms.mjs.map +1 -0
  153. package/fesm2022/signality-core-internal.mjs +268 -0
  154. package/fesm2022/signality-core-internal.mjs.map +1 -0
  155. package/fesm2022/signality-core-observers-intersection-observer.mjs +70 -0
  156. package/fesm2022/signality-core-observers-intersection-observer.mjs.map +1 -0
  157. package/fesm2022/signality-core-observers-mutation-observer.mjs +77 -0
  158. package/fesm2022/signality-core-observers-mutation-observer.mjs.map +1 -0
  159. package/fesm2022/signality-core-observers-performance-observer.mjs +84 -0
  160. package/fesm2022/signality-core-observers-performance-observer.mjs.map +1 -0
  161. package/fesm2022/signality-core-observers-resize-observer.mjs +69 -0
  162. package/fesm2022/signality-core-observers-resize-observer.mjs.map +1 -0
  163. package/fesm2022/signality-core-observers.mjs +9 -0
  164. package/fesm2022/signality-core-observers.mjs.map +1 -0
  165. package/fesm2022/signality-core-reactivity-debounced.mjs +27 -0
  166. package/fesm2022/signality-core-reactivity-debounced.mjs.map +1 -0
  167. package/fesm2022/signality-core-reactivity-throttled.mjs +27 -0
  168. package/fesm2022/signality-core-reactivity-throttled.mjs.map +1 -0
  169. package/fesm2022/signality-core-reactivity-watcher.mjs +36 -0
  170. package/fesm2022/signality-core-reactivity-watcher.mjs.map +1 -0
  171. package/fesm2022/signality-core-reactivity.mjs +8 -0
  172. package/fesm2022/signality-core-reactivity.mjs.map +1 -0
  173. package/fesm2022/signality-core-router-fragment.mjs +41 -0
  174. package/fesm2022/signality-core-router-fragment.mjs.map +1 -0
  175. package/fesm2022/signality-core-router-params.mjs +45 -0
  176. package/fesm2022/signality-core-router-params.mjs.map +1 -0
  177. package/fesm2022/signality-core-router-query-params.mjs +67 -0
  178. package/fesm2022/signality-core-router-query-params.mjs.map +1 -0
  179. package/fesm2022/signality-core-router-route-data.mjs +46 -0
  180. package/fesm2022/signality-core-router-route-data.mjs.map +1 -0
  181. package/fesm2022/signality-core-router-router-listener.mjs +50 -0
  182. package/fesm2022/signality-core-router-router-listener.mjs.map +1 -0
  183. package/fesm2022/signality-core-router-title.mjs +54 -0
  184. package/fesm2022/signality-core-router-title.mjs.map +1 -0
  185. package/fesm2022/signality-core-router-url.mjs +53 -0
  186. package/fesm2022/signality-core-router-url.mjs.map +1 -0
  187. package/fesm2022/signality-core-router.mjs +12 -0
  188. package/fesm2022/signality-core-router.mjs.map +1 -0
  189. package/fesm2022/signality-core-scheduling-debounce-callback.mjs +59 -0
  190. package/fesm2022/signality-core-scheduling-debounce-callback.mjs.map +1 -0
  191. package/fesm2022/signality-core-scheduling-interval.mjs +110 -0
  192. package/fesm2022/signality-core-scheduling-interval.mjs.map +1 -0
  193. package/fesm2022/signality-core-scheduling-throttle-callback.mjs +66 -0
  194. package/fesm2022/signality-core-scheduling-throttle-callback.mjs.map +1 -0
  195. package/fesm2022/signality-core-scheduling.mjs +8 -0
  196. package/fesm2022/signality-core-scheduling.mjs.map +1 -0
  197. package/fesm2022/signality-core-types.mjs +4 -0
  198. package/fesm2022/signality-core-types.mjs.map +1 -0
  199. package/fesm2022/signality-core.mjs +13 -0
  200. package/fesm2022/signality-core.mjs.map +1 -0
  201. package/forms/cva/index.d.ts +60 -0
  202. package/forms/index.d.ts +1 -0
  203. package/index.d.ts +8 -0
  204. package/internal/constants/index.d.ts +2 -0
  205. package/internal/constants/mobile-regex.d.ts +1 -0
  206. package/internal/constants/stubs.d.ts +32 -0
  207. package/internal/index.d.ts +4 -0
  208. package/internal/providers/index.d.ts +3 -0
  209. package/internal/providers/is-browser.d.ts +2 -0
  210. package/internal/providers/is-mobile.d.ts +2 -0
  211. package/internal/providers/is-server.d.ts +2 -0
  212. package/internal/types/index.d.ts +2 -0
  213. package/internal/types/timer.d.ts +1 -0
  214. package/internal/types/union.d.ts +1 -0
  215. package/internal/utils/bom/index.d.ts +1 -0
  216. package/internal/utils/bom/is-window.d.ts +1 -0
  217. package/internal/utils/const-signal.d.ts +10 -0
  218. package/internal/utils/context.d.ts +18 -0
  219. package/internal/utils/create-token.d.ts +8 -0
  220. package/internal/utils/dom/get-active-element.d.ts +1 -0
  221. package/internal/utils/dom/get-event-target.d.ts +1 -0
  222. package/internal/utils/dom/get-pip-element.d.ts +1 -0
  223. package/internal/utils/dom/get-shadow-root.d.ts +1 -0
  224. package/internal/utils/dom/index.d.ts +6 -0
  225. package/internal/utils/dom/is-element.d.ts +1 -0
  226. package/internal/utils/dom/is-node-within.d.ts +1 -0
  227. package/internal/utils/index.d.ts +10 -0
  228. package/internal/utils/is-plain-object.d.ts +1 -0
  229. package/internal/utils/is-query-signal.d.ts +10 -0
  230. package/internal/utils/proxy-signal.d.ts +18 -0
  231. package/internal/utils/to-element.d.ts +12 -0
  232. package/internal/utils/to-value.d.ts +6 -0
  233. package/observers/index.d.ts +4 -0
  234. package/observers/intersection-observer/index.d.ts +42 -0
  235. package/observers/mutation-observer/index.d.ts +45 -0
  236. package/observers/performance-observer/index.d.ts +58 -0
  237. package/observers/resize-observer/index.d.ts +40 -0
  238. package/package.json +343 -0
  239. package/reactivity/debounced/index.d.ts +50 -0
  240. package/reactivity/index.d.ts +3 -0
  241. package/reactivity/throttled/index.d.ts +53 -0
  242. package/reactivity/watcher/index.d.ts +68 -0
  243. package/router/fragment/index.d.ts +26 -0
  244. package/router/index.d.ts +7 -0
  245. package/router/params/index.d.ts +28 -0
  246. package/router/query-params/index.d.ts +80 -0
  247. package/router/route-data/index.d.ts +28 -0
  248. package/router/router-listener/index.d.ts +83 -0
  249. package/router/title/index.d.ts +29 -0
  250. package/router/url/index.d.ts +32 -0
  251. package/scheduling/debounce-callback/index.d.ts +28 -0
  252. package/scheduling/index.d.ts +3 -0
  253. package/scheduling/interval/index.d.ts +51 -0
  254. package/scheduling/throttle-callback/index.d.ts +30 -0
  255. package/types/index.d.ts +6 -0
  256. package/types/maybe-element-signal.d.ts +2 -0
  257. package/types/maybe-signal.d.ts +2 -0
  258. package/types/signal-value.d.ts +2 -0
  259. package/types/signal-values.d.ts +5 -0
  260. package/types/unref-element.d.ts +2 -0
  261. package/types/with-injector.d.ts +8 -0
@@ -0,0 +1,45 @@
1
+ import type { MaybeElementSignal, WithInjector } from '@signality/core/types';
2
+ export type OnDisconnectOptions = WithInjector;
3
+ export interface OnDisconnectRef {
4
+ readonly destroy: () => void;
5
+ }
6
+ /**
7
+ * Executes a callback when an element is disconnected from the DOM.
8
+ *
9
+ * @param target - The element to watch for disconnection
10
+ * @param callback - Callback to execute when the element is disconnected
11
+ * @param options - Optional configuration including injector
12
+ * @returns OnDisconnectRef with a destroy method to stop watching for disconnection
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * @Component({
17
+ * template: `
18
+ * <div #box>Content</div>
19
+ * <button (click)="remove()">Remove</button>
20
+ * `
21
+ * })
22
+ * class DisconnectComponent {
23
+ * readonly box = viewChild<ElementRef>('box');
24
+ *
25
+ * constructor() {
26
+ * onDisconnect(this.box, el => {
27
+ * console.log('Element disconnected: ', el.tagName);
28
+ * // perform cleanup without storing the reference
29
+ * });
30
+ * }
31
+ * }
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * // Manual cleanup
37
+ * const disconnectRef = onDisconnect(element, () => {
38
+ * console.log('Disconnected');
39
+ * });
40
+ *
41
+ * // Stop watching before disconnection
42
+ * disconnectRef.destroy();
43
+ * ```
44
+ */
45
+ export declare function onDisconnect<T extends Element>(target: MaybeElementSignal<T>, callback: (element: T) => void, options?: OnDisconnectOptions): OnDisconnectRef;
@@ -0,0 +1,44 @@
1
+ import type { MaybeElementSignal, MaybeSignal, WithInjector } from '@signality/core/types';
2
+ export interface OnLongPressOptions extends WithInjector {
3
+ /**
4
+ * Time in ms before the callback is triggered.
5
+ * @default 500
6
+ */
7
+ readonly delay?: MaybeSignal<number>;
8
+ /**
9
+ * Maximum distance (in pixels) the pointer can move before cancelling.
10
+ * Set to `false` to disable distance checking.
11
+ * @default 10
12
+ */
13
+ readonly distanceThreshold?: number | false;
14
+ }
15
+ export interface OnLongPressRef {
16
+ readonly destroy: () => void;
17
+ }
18
+ /**
19
+ * Detect long press gestures on an element.
20
+ * Calls a callback after a configurable delay if the pointer stays down
21
+ * without moving beyond the distance threshold.
22
+ *
23
+ * @param target - The element to detect long presses on
24
+ * @param handler - Callback invoked when a long press is detected
25
+ * @param options - Optional configuration including delay, distance threshold, and injector
26
+ * @returns A OnLongPressRef with a destroy method to stop detection
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * @Component({
31
+ * template: `<button #btn>Hold me</button>`
32
+ * })
33
+ * class LongPressComponent {
34
+ * readonly btn = viewChild<ElementRef>('btn');
35
+ *
36
+ * constructor() {
37
+ * onLongPress(this.btn, () => {
38
+ * console.log('Long press detected!');
39
+ * });
40
+ * }
41
+ * }
42
+ * ```
43
+ */
44
+ export declare function onLongPress(target: MaybeElementSignal<HTMLElement>, handler: (event: PointerEvent) => void, options?: OnLongPressOptions): OnLongPressRef;
@@ -0,0 +1,58 @@
1
+ import { type Signal } from '@angular/core';
2
+ import type { MaybeElementSignal, WithInjector } from '@signality/core/types';
3
+ /**
4
+ * Pointer type that triggered the event.
5
+ */
6
+ export type PointerType = 'mouse' | 'touch' | 'pen';
7
+ /**
8
+ * Possible swipe direction values.
9
+ */
10
+ export type PointerSwipeDirection = 'up' | 'down' | 'left' | 'right' | 'none';
11
+ export interface PointerSwipeOptions extends WithInjector {
12
+ /**
13
+ * Minimum distance in pixels before a swipe is recognized.
14
+ * @default 50
15
+ */
16
+ readonly threshold?: number;
17
+ /**
18
+ * Pointer types to listen for.
19
+ * @default ['mouse', 'touch', 'pen']
20
+ */
21
+ readonly pointerTypes?: PointerType[];
22
+ }
23
+ export interface PointerSwipeRef {
24
+ /** Whether a swipe gesture is currently in progress. */
25
+ readonly isSwiping: Signal<boolean>;
26
+ /** Current swipe direction, or `'none'` if a threshold has not been exceeded. */
27
+ readonly direction: Signal<PointerSwipeDirection>;
28
+ /** Horizontal distance from start (positive = swiped left). */
29
+ readonly distanceX: Signal<number>;
30
+ /** Vertical distance from start (positive = swiped up). */
31
+ readonly distanceY: Signal<number>;
32
+ }
33
+ /**
34
+ * Reactive pointer-swipe detection on an element.
35
+ * Tracks swipe gestures using Pointer Events and provides direction and distance signals.
36
+ * Works with mouse, touch, and pen input.
37
+ *
38
+ * @param target - Element to detect swipe gestures on
39
+ * @param options - Optional configuration including threshold, pointer types, and injector
40
+ * @returns A PointerSwipeRef with reactive signals for swipe state
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * @Component({
45
+ * template: `
46
+ * <div #area>
47
+ * <p>Swiping: {{ sw.isSwiping() }}</p>
48
+ * <p>Direction: {{ sw.direction() }}</p>
49
+ * </div>
50
+ * `
51
+ * })
52
+ * class PointerSwipeComponent {
53
+ * readonly area = viewChild<ElementRef>('area');
54
+ * readonly sw = pointerSwipe(this.area);
55
+ * }
56
+ * ```
57
+ */
58
+ export declare function pointerSwipe(target: MaybeElementSignal<HTMLElement>, options?: PointerSwipeOptions): PointerSwipeRef;
@@ -0,0 +1,96 @@
1
+ import { type Signal } from '@angular/core';
2
+ import type { MaybeElementSignal, WithInjector } from '@signality/core/types';
3
+ /**
4
+ * State indicating which edges have been reached.
5
+ */
6
+ export interface ArrivedState {
7
+ readonly top: boolean;
8
+ readonly bottom: boolean;
9
+ readonly left: boolean;
10
+ readonly right: boolean;
11
+ }
12
+ /**
13
+ * Current scroll directions.
14
+ */
15
+ export interface ScrollDirections {
16
+ readonly top: boolean;
17
+ readonly bottom: boolean;
18
+ readonly left: boolean;
19
+ readonly right: boolean;
20
+ }
21
+ export interface ScrollPositionOptions extends WithInjector {
22
+ /**
23
+ * Element or window to track scroll on.
24
+ * @default window
25
+ */
26
+ readonly target?: MaybeElementSignal<Element> | Window;
27
+ /**
28
+ * Throttle scroll events in milliseconds.
29
+ * @default 0
30
+ */
31
+ readonly throttle?: number;
32
+ /**
33
+ * Offset for arrived detection.
34
+ */
35
+ readonly offset?: {
36
+ readonly top?: number;
37
+ readonly bottom?: number;
38
+ readonly left?: number;
39
+ readonly right?: number;
40
+ };
41
+ }
42
+ export interface ScrollPositionRef {
43
+ /** Horizontal scroll position */
44
+ readonly x: Signal<number>;
45
+ /** Vertical scroll position */
46
+ readonly y: Signal<number>;
47
+ /** Whether currently scrolling */
48
+ readonly isScrolling: Signal<boolean>;
49
+ /** Which edges have been reached */
50
+ readonly arrivedState: Signal<ArrivedState>;
51
+ /** Current scroll direction */
52
+ readonly directions: Signal<ScrollDirections>;
53
+ }
54
+ /**
55
+ * Reactive tracking of scroll position.
56
+ * Track scroll offset of window or any scrollable element.
57
+ *
58
+ * @param options - Optional configuration
59
+ * @returns An object with x, y, isScrolling, arrivedState, and directions signals
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * @Component({
64
+ * template: `
65
+ * <p>Scroll Y: {{ scrollPos.y() }}px</p>
66
+ * @if (scrollPos.isScrolling()) {
67
+ * <p>Scrolling...</p>
68
+ * }
69
+ * @if (scrollPos.arrivedState().bottom) {
70
+ * <p>Reached bottom!</p>
71
+ * }
72
+ * `
73
+ * })
74
+ * class ScrollTracker {
75
+ * readonly scrollPos = scrollPosition();
76
+ * }
77
+ * ```
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * // Track scroll on a specific element
82
+ * @Component({
83
+ * template: `
84
+ * <div #scrollable style="overflow: auto; height: 200px;">
85
+ * <div style="height: 1000px;">Long content</div>
86
+ * </div>
87
+ * <p>Scroll position: {{ pos.y() }}</p>
88
+ * `
89
+ * })
90
+ * class ScrollableComponent {
91
+ * readonly scrollableEl = viewChild<ElementRef>('scrollable');
92
+ * readonly pos = scrollPosition({ target: this.scrollableEl });
93
+ * }
94
+ * ```
95
+ */
96
+ export declare function scrollPosition(options?: ScrollPositionOptions): ScrollPositionRef;
@@ -0,0 +1,49 @@
1
+ import { type Signal } from '@angular/core';
2
+ import type { MaybeElementSignal, WithInjector } from '@signality/core/types';
3
+ /**
4
+ * Possible swipe direction values.
5
+ */
6
+ export type SwipeDirection = 'up' | 'down' | 'left' | 'right' | 'none';
7
+ export interface SwipeOptions extends WithInjector {
8
+ /**
9
+ * Minimum distance in pixels before a swipe is recognized.
10
+ * @default 50
11
+ */
12
+ readonly threshold?: number;
13
+ }
14
+ export interface SwipeRef {
15
+ /** Whether a swipe gesture is currently in progress. */
16
+ readonly isSwiping: Signal<boolean>;
17
+ /** Current swipe direction, or `'none'` if a threshold has not been exceeded. */
18
+ readonly direction: Signal<SwipeDirection>;
19
+ /** Horizontal distance from start (positive = swiped left). */
20
+ readonly distanceX: Signal<number>;
21
+ /** Vertical distance from start (positive = swiped up). */
22
+ readonly distanceY: Signal<number>;
23
+ }
24
+ /**
25
+ * Reactive touch-swipe detection on an element.
26
+ * Uses Touch Events API — for mouse/pen input use PointerSwipe instead.
27
+ * Tracks single-finger swipe gestures and provides direction and distance signals.
28
+ *
29
+ * @param target - Element to detect swipe gestures on
30
+ * @param options - Optional configuration including threshold and injector
31
+ * @returns A SwipeRef with reactive signals for swipe state
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * @Component({
36
+ * template: `
37
+ * <div #area>
38
+ * <p>Swiping: {{ sw.isSwiping() }}</p>
39
+ * <p>Direction: {{ sw.direction() }}</p>
40
+ * </div>
41
+ * `
42
+ * })
43
+ * class SwipeComponent {
44
+ * readonly area = viewChild<ElementRef>('area');
45
+ * readonly sw = swipe(this.area);
46
+ * }
47
+ * ```
48
+ */
49
+ export declare function swipe(target: MaybeElementSignal<HTMLElement>, options?: SwipeOptions): SwipeRef;
@@ -0,0 +1,39 @@
1
+ import { type Signal } from '@angular/core';
2
+ import type { WithInjector } from '@signality/core/types';
3
+ export type TextSelectionOptions = WithInjector;
4
+ export interface TextSelectionRef {
5
+ /** The selected text content */
6
+ readonly text: Signal<string>;
7
+ /** Array of Range objects */
8
+ readonly ranges: Signal<Range[]>;
9
+ /** Bounding rectangles of selection */
10
+ readonly rects: Signal<DOMRect[]>;
11
+ /** The raw Selection object */
12
+ readonly selection: Signal<Selection | null>;
13
+ /** Clear the current text selection */
14
+ readonly clear: () => void;
15
+ }
16
+ /**
17
+ * Signal-based wrapper around the [Selection API](https://developer.mozilla.org/en-US/docs/Web/API/Selection_API).
18
+ *
19
+ * @param options - Optional configuration including injector
20
+ * @returns A TextSelectionRef with reactive signals for text, ranges, rects, and selection
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * @Component({
25
+ * template: `
26
+ * <p>Select some text below:</p>
27
+ * <div>Lorem ipsum dolor sit amet...</div>
28
+ * @if (selection.text(); as text) {
29
+ * <p>Selected: "{{ text }}"</p>
30
+ * }
31
+ * `
32
+ * })
33
+ * class TextSelectionComponent {
34
+ * readonly selection = textSelection();
35
+ * }
36
+ * ```
37
+ */
38
+ export declare function textSelection(options?: TextSelectionOptions): TextSelectionRef;
39
+ export declare const TEXT_SELECTION: import("@angular/core").ProviderToken<TextSelectionRef>;
@@ -0,0 +1,46 @@
1
+ import { type CreateSignalOptions, type Signal } from '@angular/core';
2
+ import type { WithInjector } from '@signality/core/types';
3
+ export interface WindowSizeOptions extends CreateSignalOptions<WindowSizeValue>, WithInjector {
4
+ /**
5
+ * Include scrollbar in dimensions calculation.
6
+ * @default false
7
+ */
8
+ readonly includeScrollbar?: boolean;
9
+ /**
10
+ * Initial dimensions for SSR.
11
+ */
12
+ readonly initialValue?: Pick<WindowSizeValue, 'width' | 'height'>;
13
+ }
14
+ export interface WindowSizeValue {
15
+ readonly width: number;
16
+ readonly height: number;
17
+ readonly innerWidth: number;
18
+ readonly innerHeight: number;
19
+ readonly outerWidth: number;
20
+ readonly outerHeight: number;
21
+ }
22
+ /**
23
+ * Signal-based wrapper around the [Window API](https://developer.mozilla.org/en-US/docs/Web/API/Window) dimensions.
24
+ *
25
+ * @param options - Optional configuration including initialValue for SSR
26
+ * @returns A signal containing the current window dimensions
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * @Component({
31
+ * template: `
32
+ * <div>
33
+ * Window: {{ size().width }} × {{ size().height }}px
34
+ * @if (size().width < 768) {
35
+ * <p>Mobile view</p>
36
+ * }
37
+ * </div>
38
+ * `
39
+ * })
40
+ * class WindowSizeComponent {
41
+ * readonly size = windowSize();
42
+ * }
43
+ * ```
44
+ */
45
+ export declare function windowSize(options?: WindowSizeOptions): Signal<WindowSizeValue>;
46
+ export declare const WINDOW_SIZE: import("@angular/core").ProviderToken<Signal<WindowSizeValue>>;
@@ -0,0 +1,80 @@
1
+ import { signal } from '@angular/core';
2
+ import { setupContext, constSignal } from '@signality/core/internal';
3
+ import { setupSync, listener } from '@signality/core/browser/listener';
4
+
5
+ /**
6
+ * Signal-based wrapper around the [Battery Status API](https://developer.mozilla.org/en-US/docs/Web/API/Battery_Status_API).
7
+ *
8
+ * @param options - Optional configuration with injector
9
+ * @returns A BatteryRef with battery status signals
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * @Component({
14
+ * template: `
15
+ * @if (batteryStatus.isSupported()) {
16
+ * <div>
17
+ * <p>Charging: {{ batteryStatus.charging() }}</p>
18
+ * <p>Level: {{ batteryStatus.level() * 100 }}%</p>
19
+ * </div>
20
+ * }
21
+ * `
22
+ * })
23
+ * class BatteryComponent {
24
+ * readonly batteryStatus = battery();
25
+ * }
26
+ * ```
27
+ */
28
+ function battery(options) {
29
+ const { runInContext } = setupContext(options?.injector, battery);
30
+ return runInContext(({ isBrowser, injector }) => {
31
+ const isSupported = constSignal(isBrowser && 'getBattery' in navigator && typeof navigator.getBattery === 'function');
32
+ if (!isSupported()) {
33
+ return {
34
+ isSupported,
35
+ charging: constSignal(false),
36
+ chargingTime: constSignal(0),
37
+ dischargingTime: constSignal(0),
38
+ level: constSignal(1),
39
+ };
40
+ }
41
+ const charging = signal(false, ...(ngDevMode ? [{ debugName: "charging" }] : []));
42
+ const chargingTime = signal(0, ...(ngDevMode ? [{ debugName: "chargingTime" }] : []));
43
+ const dischargingTime = signal(0, ...(ngDevMode ? [{ debugName: "dischargingTime" }] : []));
44
+ const level = signal(1, ...(ngDevMode ? [{ debugName: "level" }] : []));
45
+ function update() {
46
+ charging.set(this.charging);
47
+ chargingTime.set(this.chargingTime);
48
+ dischargingTime.set(this.dischargingTime);
49
+ level.set(this.level);
50
+ }
51
+ navigator.getBattery().then(battery => {
52
+ update.call(battery);
53
+ setupSync(() => {
54
+ for (const event of BATTERY_EVENTS) {
55
+ listener.passive(battery, event, update, { injector });
56
+ }
57
+ });
58
+ });
59
+ return {
60
+ isSupported,
61
+ charging: charging.asReadonly(),
62
+ chargingTime: chargingTime.asReadonly(),
63
+ dischargingTime: dischargingTime.asReadonly(),
64
+ level: level.asReadonly(),
65
+ };
66
+ });
67
+ }
68
+ const BATTERY_EVENTS = [
69
+ 'chargingchange',
70
+ 'chargingtimechange',
71
+ 'dischargingtimechange',
72
+ 'levelchange',
73
+ ];
74
+
75
+ /**
76
+ * Generated bundle index. Do not edit.
77
+ */
78
+
79
+ export { battery };
80
+ //# sourceMappingURL=signality-core-browser-battery.mjs.map
@@ -0,0 +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 charging: Signal<boolean>;\n readonly chargingTime: Signal<number>;\n readonly dischargingTime: Signal<number>;\n readonly level: Signal<number>;\n readonly isSupported: Signal<boolean>;\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 * class BatteryComponent {\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":";;;;AAeA;;;;;;;;;;;;;;;;;;;;;;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;;ACxGV;;AAEG;;;;"}
@@ -0,0 +1,112 @@
1
+ import { signal, untracked } from '@angular/core';
2
+ import { setupContext, constSignal, NOOP_FN, NOOP_ASYNC_FN } from '@signality/core/internal';
3
+ import { setupSync, listener } from '@signality/core/browser/listener';
4
+
5
+ /**
6
+ * Signal-based wrapper around the [Web Bluetooth API](https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth).
7
+ *
8
+ * @param options - Optional configuration
9
+ * @returns A BluetoothRef with connection state and control methods
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * @Component({
14
+ * template: `
15
+ * <button (click)="bt.request()">Connect</button>
16
+ * @if (bt.isConnected()) {
17
+ * <p>{{ bt.device()?.name }}</p>
18
+ * }
19
+ * `
20
+ * })
21
+ * class BluetoothComponent {
22
+ * readonly bt = bluetooth();
23
+ * }
24
+ * ```
25
+ */
26
+ function bluetooth(options) {
27
+ const { runInContext } = setupContext(options?.injector, bluetooth);
28
+ return runInContext(({ isBrowser, injector, onCleanup }) => {
29
+ const isSupported = constSignal(isBrowser && 'bluetooth' in navigator);
30
+ if (!isSupported()) {
31
+ return {
32
+ isSupported,
33
+ isConnected: constSignal(false),
34
+ isConnecting: constSignal(false),
35
+ device: constSignal(null),
36
+ server: constSignal(null),
37
+ error: constSignal(null),
38
+ request: NOOP_ASYNC_FN,
39
+ disconnect: NOOP_FN,
40
+ };
41
+ }
42
+ const { bluetooth } = navigator;
43
+ const isConnected = signal(false, ...(ngDevMode ? [{ debugName: "isConnected" }] : []));
44
+ const isConnecting = signal(false, ...(ngDevMode ? [{ debugName: "isConnecting" }] : []));
45
+ const device = signal(null, ...(ngDevMode ? [{ debugName: "device" }] : []));
46
+ const server = signal(null, ...(ngDevMode ? [{ debugName: "server" }] : []));
47
+ const error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
48
+ const request = async (requestOptions) => {
49
+ if (untracked(isConnecting)) {
50
+ return;
51
+ }
52
+ isConnecting.set(true);
53
+ error.set(null);
54
+ try {
55
+ const requestOpts = requestOptions ?? {
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);
61
+ device.set(btDevice);
62
+ setupSync(() => {
63
+ listener(btDevice, 'gattserverdisconnected', () => {
64
+ isConnected.set(false);
65
+ server.set(null);
66
+ }, { injector });
67
+ });
68
+ const gattServer = await btDevice.gatt?.connect();
69
+ if (gattServer) {
70
+ server.set(gattServer);
71
+ isConnected.set(true);
72
+ }
73
+ }
74
+ catch (e) {
75
+ error.set(e);
76
+ device.set(null);
77
+ server.set(null);
78
+ isConnected.set(false);
79
+ }
80
+ finally {
81
+ isConnecting.set(false);
82
+ }
83
+ };
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
+ onCleanup(disconnect);
94
+ return {
95
+ isSupported,
96
+ isConnected: isConnected.asReadonly(),
97
+ isConnecting: isConnecting.asReadonly(),
98
+ device: device.asReadonly(),
99
+ server: server.asReadonly(),
100
+ error: error.asReadonly(),
101
+ request,
102
+ disconnect,
103
+ };
104
+ });
105
+ }
106
+
107
+ /**
108
+ * Generated bundle index. Do not edit.
109
+ */
110
+
111
+ export { bluetooth };
112
+ //# sourceMappingURL=signality-core-browser-bluetooth.mjs.map
@@ -0,0 +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.\n */\n readonly filters?: BluetoothLEScanFilter[];\n\n /**\n * Optional services to access.\n */\n readonly optionalServices?: BluetoothServiceUUID[];\n}\n\nexport interface BluetoothRef {\n /** Whether Web Bluetooth API is supported */\n readonly isSupported: Signal<boolean>;\n\n /** Whether a device is currently connected */\n readonly isConnected: Signal<boolean>;\n\n /** Whether connection is in progress */\n readonly isConnecting: Signal<boolean>;\n\n /** Connected Bluetooth device */\n readonly device: Signal<BluetoothDevice | null>;\n\n /** GATT server of connected device */\n readonly server: Signal<BluetoothRemoteGATTServer | null>;\n\n /** Last error that occurred */\n readonly error: Signal<Error | null>;\n\n /** Request device connection */\n readonly request: (options?: RequestDeviceOptions) => Promise<void>;\n\n /** Disconnect from device */\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 * class BluetoothComponent {\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 { bluetooth } = navigator;\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 const request = async (requestOptions?: RequestDeviceOptions): Promise<void> => {\n if (untracked(isConnecting)) {\n return;\n }\n\n isConnecting.set(true);\n error.set(null);\n\n try {\n const requestOpts: RequestDeviceOptions = requestOptions ?? {\n acceptAllDevices: options?.acceptAllDevices ?? true,\n optionalServices: options?.optionalServices ?? [],\n ...(options?.filters ? { filters: options.filters, acceptAllDevices: false } : {}),\n };\n\n const btDevice = await bluetooth.requestDevice(requestOpts);\n\n device.set(btDevice);\n\n setupSync(() => {\n listener(\n btDevice,\n 'gattserverdisconnected',\n () => {\n isConnected.set(false);\n server.set(null);\n },\n { injector }\n );\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 device.set(null);\n server.set(null);\n isConnected.set(false);\n } finally {\n isConnecting.set(false);\n }\n };\n\n const disconnect = () => {\n const currentDevice = untracked(device);\n\n if (currentDevice?.gatt?.connected) {\n currentDevice.gatt.disconnect();\n }\n\n device.set(null);\n server.set(null);\n isConnected.set(false);\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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"}
@@ -0,0 +1,51 @@
1
+ import { computed } from '@angular/core';
2
+ import { setupContext, constSignal } from '@signality/core/internal';
3
+ import { mediaQuery } from '@signality/core/browser/media-query';
4
+
5
+ /**
6
+ * Reactive breakpoint matching using matchMedia.
7
+ * Track responsive breakpoints with Angular signals.
8
+ *
9
+ * @param map - Object mapping breakpoint names to media queries
10
+ * @param options - Optional configuration
11
+ * @returns An object with signals for each breakpoint
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const bp = breakpoints({
16
+ * mobile: '(max-width: 767px)',
17
+ * desktop: '(min-width: 768px)',
18
+ * });
19
+ *
20
+ * // In template: @if (bp.mobile()) { ... }
21
+ * ```
22
+ */
23
+ function breakpoints(map, options) {
24
+ const { runInContext } = setupContext(options?.injector, breakpoints);
25
+ return runInContext(({ isServer }) => {
26
+ const initialValues = (options?.initialValue ?? {});
27
+ const queries = {};
28
+ for (const key of Object.keys(map)) {
29
+ const query = map[key];
30
+ const initialValue = initialValues[key] ?? false;
31
+ queries[key] = mediaQuery(query, { initialValue });
32
+ }
33
+ if (isServer) {
34
+ return {
35
+ ...queries,
36
+ current: constSignal(Object.keys(map).filter(key => !!initialValues[key])),
37
+ };
38
+ }
39
+ return {
40
+ ...queries,
41
+ current: computed(() => Object.keys(map).filter(key => queries[key]())),
42
+ };
43
+ });
44
+ }
45
+
46
+ /**
47
+ * Generated bundle index. Do not edit.
48
+ */
49
+
50
+ export { breakpoints };
51
+ //# sourceMappingURL=signality-core-browser-breakpoints.mjs.map
@@ -0,0 +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 * Track responsive breakpoints with Angular signals.\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\n *\n * @example\n * ```typescript\n * const bp = breakpoints({\n * mobile: '(max-width: 767px)',\n * desktop: '(min-width: 768px)',\n * });\n *\n * // In template: @if (bp.mobile()) { ... }\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":";;;;AAkBA;;;;;;;;;;;;;;;;;AAiBG;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,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;aACtD;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;;AChEA;;AAEG;;;;"}