ngx-mq 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -169
- package/fesm2022/ngx-mq.mjs +41 -12
- package/fesm2022/ngx-mq.mjs.map +1 -1
- package/index.d.ts +20 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/martsinlabs/ngx-mq/refs/heads/main/assets/logo.svg" width="
|
|
2
|
+
<img src="https://raw.githubusercontent.com/martsinlabs/ngx-mq/refs/heads/main/assets/logo.svg" width="130" alt="ngx-mq logo" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
<h3 align="center">Signal-
|
|
6
|
-
|
|
7
|
-
<p align="center">
|
|
8
|
-
Reactive <code>matchMedia</code> as Angular signals. SSR-safe, zoneless-ready, and free of RxJS.
|
|
9
|
-
</p>
|
|
5
|
+
<h3 align="center">Signal-powered breakpoints & media queries for Angular</h3>
|
|
6
|
+
<br />
|
|
10
7
|
|
|
11
8
|
<p align="center">
|
|
12
9
|
<a href="https://github.com/martsinlabs/ngx-mq/actions/workflows/ci.yml">
|
|
@@ -29,237 +26,211 @@
|
|
|
29
26
|
</a>
|
|
30
27
|
</p>
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
- **Efficient**: one shared `matchMedia` listener per unique query, reused across the app.
|
|
40
|
-
- **Batteries included**: Tailwind, Bootstrap and Material breakpoint presets out of the box.
|
|
41
|
-
- **Composable**: combine any signals with `and` / `or` / `not`.
|
|
42
|
-
- **Tiny and tested**: ~1.9 kB gzipped, 100% line coverage.
|
|
43
|
-
|
|
44
|
-
## Why ngx-mq?
|
|
29
|
+
<p align="center">
|
|
30
|
+
<a href="https://martsinlabs.github.io/ngx-mq"><b>Documentation</b></a>
|
|
31
|
+
·
|
|
32
|
+
<a href="https://stackblitz.com/github/martsinlabs/ngx-mq-demo/tree/demo/v3"><b>Live demo</b></a>
|
|
33
|
+
·
|
|
34
|
+
<a href="#why-ngx-mq"><b>Why ngx-mq?</b></a>
|
|
35
|
+
</p>
|
|
45
36
|
|
|
46
|
-
|
|
47
|
-
works well but is built around RxJS and raw query strings. `ngx-mq` is designed for the signals era:
|
|
48
|
-
templates read a value directly, there is nothing to subscribe to, and cleanup is automatic.
|
|
37
|
+
---
|
|
49
38
|
|
|
50
|
-
|
|
51
|
-
| --------------------- | ------------------------------------------------- | ----------------------------------------- |
|
|
52
|
-
| Reactivity | `Signal<boolean>` | `Observable<BreakpointState>` |
|
|
53
|
-
| Cleanup | Automatic via `DestroyRef` | Manual (`unsubscribe` / `takeUntilDestroyed`) |
|
|
54
|
-
| Template usage | `@if (isDesktop())` | `async` pipe or manual subscription |
|
|
55
|
-
| Named breakpoints | Tailwind, Bootstrap, Material presets or your own | Material breakpoints or raw strings |
|
|
56
|
-
| Media-feature helpers | `colorScheme`, `hover`, `pointer`, ... | Raw query strings |
|
|
57
|
-
| Composition | `and` / `or` / `not` | RxJS operators |
|
|
58
|
-
| SSR | Configurable static value | Handle it yourself |
|
|
59
|
-
| Footprint | ~1.9 kB standalone | Part of `@angular/cdk` |
|
|
39
|
+
## Overview
|
|
60
40
|
|
|
61
|
-
|
|
62
|
-
want a signals-first, zoneless-friendly API with batteries included, reach for `ngx-mq`.
|
|
41
|
+
A responsive value is just a signal: read it in the template, compose it, and never wire up cleanup.
|
|
63
42
|
|
|
64
|
-
|
|
43
|
+
```ts
|
|
44
|
+
import { Component } from '@angular/core';
|
|
45
|
+
import { up } from 'ngx-mq';
|
|
65
46
|
|
|
66
|
-
|
|
67
|
-
|
|
47
|
+
@Component({
|
|
48
|
+
selector: 'app-root',
|
|
49
|
+
template: `
|
|
50
|
+
@if (isDesktop()) {
|
|
51
|
+
<app-sidebar />
|
|
52
|
+
}
|
|
53
|
+
`,
|
|
54
|
+
})
|
|
55
|
+
export class AppComponent {
|
|
56
|
+
readonly isDesktop = up('lg');
|
|
57
|
+
}
|
|
58
|
+
```
|
|
68
59
|
|
|
69
|
-
|
|
60
|
+
- **Signal-native** so it works anywhere signals do, zoneless apps included.
|
|
61
|
+
- **Zero boilerplate**: no subscriptions, no `unsubscribe`, cleanup is automatic.
|
|
62
|
+
- **SSR-safe** with a value you control on the server.
|
|
63
|
+
- **Batteries included**: Tailwind, Bootstrap and Material presets, plus `and` / `or` / `not`.
|
|
64
|
+
- **Tiny**: ~1.9 kB gzipped, and no RxJS.
|
|
70
65
|
|
|
71
|
-
Install
|
|
66
|
+
## Install
|
|
72
67
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
| 19 | `npm i ngx-mq@2` |
|
|
77
|
-
| 16 - 18 | `npm i ngx-mq@1` |
|
|
68
|
+
```bash
|
|
69
|
+
npm i ngx-mq # Angular 20-22
|
|
70
|
+
```
|
|
78
71
|
|
|
79
|
-
|
|
72
|
+
<sub>Angular 19 -> <code>ngx-mq@2</code> · Angular 16-18 -> <code>ngx-mq@1</code></sub>
|
|
80
73
|
|
|
81
|
-
|
|
74
|
+
Then register your breakpoints once, at bootstrap:
|
|
82
75
|
|
|
83
76
|
```ts
|
|
84
|
-
import { bootstrapApplication } from '@angular/platform-browser';
|
|
85
77
|
import { provideBreakpoints } from 'ngx-mq';
|
|
86
|
-
import { AppComponent } from './app/app.component';
|
|
87
78
|
|
|
88
79
|
bootstrapApplication(AppComponent, {
|
|
89
80
|
providers: [provideBreakpoints({ sm: 640, md: 768, lg: 1024 })],
|
|
81
|
+
// or a preset: provideTailwindBreakpoints() / provideBootstrapBreakpoints() / provideMaterialBreakpoints()
|
|
90
82
|
});
|
|
91
83
|
```
|
|
92
84
|
|
|
93
|
-
|
|
85
|
+
> Call the helpers inside an [injection context](https://angular.dev/guide/di/dependency-injection-context): a component field, a constructor, or a DI factory.
|
|
86
|
+
|
|
87
|
+
## Examples
|
|
88
|
+
|
|
89
|
+
#### Show different layouts per screen size
|
|
94
90
|
|
|
95
91
|
```ts
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
readonly isMobile = down('md');
|
|
93
|
+
readonly isTablet = between('md', 'lg');
|
|
94
|
+
readonly isDesktop = up('lg');
|
|
95
|
+
```
|
|
98
96
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<app-sidebar />
|
|
104
|
-
}
|
|
105
|
-
`,
|
|
106
|
-
})
|
|
107
|
-
export class AppComponent {
|
|
108
|
-
readonly isMobile = down('md');
|
|
109
|
-
readonly isTablet = between('md', 'lg');
|
|
110
|
-
readonly isDesktop = up('lg');
|
|
111
|
-
}
|
|
97
|
+
#### Follow the system dark mode
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
readonly prefersDark = colorScheme('dark');
|
|
112
101
|
```
|
|
113
102
|
|
|
114
|
-
|
|
103
|
+
#### Drop hover styles on touch devices
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
// `hover()` has no direct inverse, so compose it
|
|
107
|
+
readonly isTouchLike = not(hover());
|
|
108
|
+
```
|
|
115
109
|
|
|
116
|
-
|
|
110
|
+
#### Combine any conditions
|
|
117
111
|
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
```ts
|
|
113
|
+
// Large screen, in landscape, with a hover-capable pointer
|
|
114
|
+
readonly isLandscapeDesktop = and(up('lg'), orientation('landscape'), hover());
|
|
120
115
|
|
|
121
|
-
|
|
116
|
+
// Small screens OR a reduced-motion preference
|
|
117
|
+
readonly prefersSimpleUi = or(down('md'), reducedMotion());
|
|
118
|
+
```
|
|
122
119
|
|
|
123
|
-
|
|
120
|
+
#### Respect reduced motion
|
|
124
121
|
|
|
125
122
|
```ts
|
|
126
|
-
|
|
127
|
-
provideBreakpoints,
|
|
128
|
-
provideTailwindBreakpoints,
|
|
129
|
-
provideBootstrapBreakpoints,
|
|
130
|
-
provideMaterialBreakpoints,
|
|
131
|
-
} from 'ngx-mq';
|
|
123
|
+
readonly reduceMotion = reducedMotion();
|
|
132
124
|
```
|
|
133
125
|
|
|
134
|
-
|
|
135
|
-
| ----------- | ------------------------------------------------ |
|
|
136
|
-
| Tailwind | `sm: 640, md: 768, lg: 1024, xl: 1280, 2xl: 1536` |
|
|
137
|
-
| Bootstrap | `sm: 576, md: 768, lg: 992, xl: 1200, xxl: 1400` |
|
|
138
|
-
| Material | `sm: 600, md: 905, lg: 1240, xl: 1440` |
|
|
126
|
+
#### Anything else, with a raw query
|
|
139
127
|
|
|
140
|
-
|
|
128
|
+
```ts
|
|
129
|
+
readonly isRetina = matchMediaSignal('(min-resolution: 2dppx)');
|
|
130
|
+
```
|
|
141
131
|
|
|
142
|
-
|
|
143
|
-
| --------- | ---------------- | ------------------------------------ |
|
|
144
|
-
| `up` | `bp` | viewport width `>=` `bp` |
|
|
145
|
-
| `down` | `bp` | viewport width `<` `bp` |
|
|
146
|
-
| `between` | `minBp`, `maxBp` | viewport width is in `[minBp, maxBp)` |
|
|
132
|
+
## Why ngx-mq?
|
|
147
133
|
|
|
148
|
-
|
|
149
|
-
> from the max so adjacent ranges (e.g. `down('md')` and `up('md')`) never overlap. Tune it with
|
|
150
|
-
> [`provideBreakpointEpsilon`](#providers).
|
|
134
|
+
Angular's CDK ships [`BreakpointObserver`](https://material.angular.io/cdk/layout/overview), which works well but is built around RxJS and raw query strings. `ngx-mq` is built for the signals era: read a value in the template, subscribe to nothing, clean up automatically.
|
|
151
135
|
|
|
152
|
-
|
|
136
|
+
| | `ngx-mq` | CDK `BreakpointObserver` |
|
|
137
|
+
| --------------------- | ------------------------------------------- | ------------------------------------- |
|
|
138
|
+
| Reactivity | `Signal<boolean>` | `Observable<BreakpointState>` |
|
|
139
|
+
| Cleanup | Automatic via `DestroyRef` | Manual (`takeUntilDestroyed`) |
|
|
140
|
+
| Named breakpoints | Tailwind / Bootstrap / Material or your own | Material breakpoints or raw strings |
|
|
141
|
+
| Media-feature helpers | `colorScheme`, `hover`, `pointer`, ... | Raw query strings |
|
|
142
|
+
| Composition | `and` / `or` / `not` | RxJS operators |
|
|
143
|
+
| SSR | Configurable static value | Handle it yourself |
|
|
144
|
+
| Footprint | ~1.9 kB standalone | Part of `@angular/cdk` |
|
|
153
145
|
|
|
154
|
-
|
|
155
|
-
| --------------- | ------------------------------ | ------------------------------------ |
|
|
156
|
-
| `orientation` | `'portrait' \| 'landscape'` | the screen orientation matches |
|
|
157
|
-
| `colorScheme` | `'light' \| 'dark'` | the system color scheme matches |
|
|
158
|
-
| `displayMode` | `DisplayModeOption` | the display mode matches (PWA detection) |
|
|
159
|
-
| `reducedMotion` | none | the user prefers reduced motion |
|
|
160
|
-
| `hover` | none | the primary pointer can hover |
|
|
161
|
-
| `anyHover` | none | any available pointer can hover |
|
|
162
|
-
| `pointer` | `'fine' \| 'coarse' \| 'none'` | the primary pointer matches |
|
|
163
|
-
| `anyPointer` | `'fine' \| 'coarse' \| 'none'` | any available pointer matches |
|
|
164
|
-
| `colorGamut` | `'srgb' \| 'p3' \| 'rec2020'` | the display covers the gamut |
|
|
146
|
+
## Documentation
|
|
165
147
|
|
|
166
|
-
|
|
148
|
+
Spin it up in seconds on [StackBlitz](https://stackblitz.com/github/martsinlabs/ngx-mq-demo/tree/demo/v3), no setup required.
|
|
167
149
|
|
|
168
|
-
|
|
150
|
+
Full API reference, guides and recipes live at **[martsinlabs.github.io/ngx-mq](https://martsinlabs.github.io/ngx-mq)**.
|
|
169
151
|
|
|
170
|
-
|
|
171
|
-
|
|
152
|
+
<details>
|
|
153
|
+
<summary><b>API reference</b> (quick view)</summary>
|
|
172
154
|
|
|
173
|
-
|
|
174
|
-
|
|
155
|
+
<br>
|
|
156
|
+
|
|
157
|
+
Every query helper returns a `Signal<boolean>` and accepts an optional `options` argument
|
|
158
|
+
([`CreateMediaQueryOptions`](#options-and-types)).
|
|
175
159
|
|
|
176
|
-
|
|
160
|
+
**Breakpoints**
|
|
177
161
|
|
|
178
|
-
|
|
179
|
-
|
|
162
|
+
| Helper | Arguments | `true` when |
|
|
163
|
+
| --------- | ---------------- | ------------------------------------ |
|
|
164
|
+
| `up` | `bp` | viewport width `>=` `bp` |
|
|
165
|
+
| `down` | `bp` | viewport width `<` `bp` (exclusive) |
|
|
166
|
+
| `between` | `minBp`, `maxBp` | viewport width is in `[minBp, maxBp)` |
|
|
180
167
|
|
|
181
|
-
|
|
182
|
-
| ------ | ---------------------------------- | ------------------------------------------ |
|
|
183
|
-
| `and` | `...conditions: Signal<boolean>[]` | every condition is `true` (empty: `true`) |
|
|
184
|
-
| `or` | `...conditions: Signal<boolean>[]` | any condition is `true` (empty: `false`) |
|
|
185
|
-
| `not` | `condition: Signal<boolean>` | the condition is `false` |
|
|
168
|
+
`down` and `between` upper bounds are exclusive: a small epsilon (default `0.02`, set via `provideBreakpointEpsilon`) is subtracted from the max so adjacent ranges never overlap.
|
|
186
169
|
|
|
187
|
-
|
|
188
|
-
import { and, or, not, up, down, hover, orientation, reducedMotion } from 'ngx-mq';
|
|
170
|
+
**Media features**
|
|
189
171
|
|
|
190
|
-
|
|
191
|
-
|
|
172
|
+
| Helper | Arguments | `true` when |
|
|
173
|
+
| --------------- | ------------------------------ | ---------------------------------------- |
|
|
174
|
+
| `orientation` | `'portrait' \| 'landscape'` | the screen orientation matches |
|
|
175
|
+
| `colorScheme` | `'light' \| 'dark'` | the system color scheme matches |
|
|
176
|
+
| `displayMode` | `DisplayModeOption` | the display mode matches (PWA detection) |
|
|
177
|
+
| `reducedMotion` | none | the user prefers reduced motion |
|
|
178
|
+
| `prefersContrast` | `'more' \| 'less' \| 'no-preference' \| 'custom'` | the user's contrast preference matches |
|
|
179
|
+
| `hover` | none | the primary pointer can hover |
|
|
180
|
+
| `anyHover` | none | any available pointer can hover |
|
|
181
|
+
| `pointer` | `'fine' \| 'coarse' \| 'none'` | the primary pointer matches |
|
|
182
|
+
| `anyPointer` | `'fine' \| 'coarse' \| 'none'` | any available pointer matches |
|
|
183
|
+
| `colorGamut` | `'srgb' \| 'p3' \| 'rec2020'` | the display covers the gamut |
|
|
192
184
|
|
|
193
|
-
|
|
194
|
-
readonly prefersSimpleUi = or(down('md'), reducedMotion());
|
|
185
|
+
**Composition**
|
|
195
186
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
187
|
+
| Helper | Arguments | `true` when |
|
|
188
|
+
| ------ | ---------------------------------- | ----------------------------------------- |
|
|
189
|
+
| `and` | `...conditions: Signal<boolean>[]` | every condition is `true` (empty: `true`) |
|
|
190
|
+
| `or` | `...conditions: Signal<boolean>[]` | any condition is `true` (empty: `false`) |
|
|
191
|
+
| `not` | `condition: Signal<boolean>` | the condition is `false` |
|
|
199
192
|
|
|
200
|
-
|
|
193
|
+
**Custom queries**
|
|
201
194
|
|
|
202
|
-
|
|
195
|
+
| Helper | Arguments | Description |
|
|
196
|
+
| ------------------ | --------------- | -------------------------------------------- |
|
|
197
|
+
| `matchMediaSignal` | `query: string` | A signal for any raw CSS media query |
|
|
203
198
|
|
|
204
|
-
|
|
205
|
-
| ------------------------------- | -------------------- | ----------------------------------------------------- |
|
|
206
|
-
| `provideBreakpoints` | `bps: MqBreakpoints` | Registers a custom breakpoint map. |
|
|
207
|
-
| `provideTailwindBreakpoints` | none | Registers the Tailwind preset. |
|
|
208
|
-
| `provideBootstrapBreakpoints` | none | Registers the Bootstrap preset. |
|
|
209
|
-
| `provideMaterialBreakpoints` | none | Registers the Material 2 preset. |
|
|
210
|
-
| `provideBreakpointEpsilon` | `epsilon: number` | Sets the exclusive-bound epsilon (default `0.02`). |
|
|
211
|
-
| `provideSsrValue` | `value: boolean` | Sets the value signals report during SSR (default `false`). |
|
|
199
|
+
**Providers**
|
|
212
200
|
|
|
213
|
-
|
|
214
|
-
|
|
201
|
+
| Provider | Argument | Description |
|
|
202
|
+
| ----------------------------- | -------------------- | ------------------------------------------------------- |
|
|
203
|
+
| `provideBreakpoints` | `bps: MqBreakpoints` | Registers a custom breakpoint map |
|
|
204
|
+
| `provideTailwindBreakpoints` | none | Registers the Tailwind preset |
|
|
205
|
+
| `provideBootstrapBreakpoints` | none | Registers the Bootstrap preset |
|
|
206
|
+
| `provideMaterialBreakpoints` | none | Registers the Material 2 preset |
|
|
207
|
+
| `provideBreakpointEpsilon` | `epsilon: number` | Sets the exclusive-bound epsilon (default `0.02`) |
|
|
208
|
+
| `provideSsrValue` | `value: boolean` | Sets the value signals report during SSR (default `false`) |
|
|
215
209
|
|
|
216
|
-
|
|
210
|
+
**Options and types**
|
|
217
211
|
|
|
218
212
|
```ts
|
|
219
213
|
interface CreateMediaQueryOptions {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
/** Debug name shown for the signal in Angular DevTools. */
|
|
223
|
-
debugName?: string;
|
|
214
|
+
ssrValue?: boolean; // value reported during SSR; overrides provideSsrValue
|
|
215
|
+
debugName?: string; // shown for the signal in Angular DevTools
|
|
224
216
|
}
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### Types
|
|
228
217
|
|
|
229
|
-
```ts
|
|
230
218
|
type MqBreakpoints = Record<string, number>;
|
|
231
219
|
|
|
232
220
|
type DisplayModeOption =
|
|
233
|
-
| 'browser'
|
|
234
|
-
| '
|
|
235
|
-
| 'standalone'
|
|
236
|
-
| 'minimal-ui'
|
|
237
|
-
| 'window-controls-overlay'
|
|
238
|
-
| 'picture-in-picture';
|
|
221
|
+
| 'browser' | 'fullscreen' | 'standalone'
|
|
222
|
+
| 'minimal-ui' | 'window-controls-overlay' | 'picture-in-picture';
|
|
239
223
|
```
|
|
240
224
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
`matchMedia` does not exist on the server, so during SSR every signal returns a static value and
|
|
244
|
-
no listeners are created. Set the default with `provideSsrValue`, or override it per call:
|
|
225
|
+
</details>
|
|
245
226
|
|
|
246
|
-
|
|
247
|
-
provideSsrValue(false); // app-wide default
|
|
248
|
-
up('lg', { ssrValue: true }); // per-call override
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
Once the app hydrates in the browser, each signal switches to the live query result.
|
|
252
|
-
|
|
253
|
-
## How it works
|
|
227
|
+
## Server-side rendering
|
|
254
228
|
|
|
255
|
-
`
|
|
256
|
-
(Multiton + Flyweight). Callers share that signal, and a reference count tied to `DestroyRef`
|
|
257
|
-
removes the listener and registry entry once the last consumer is destroyed. No manual cleanup, no
|
|
258
|
-
duplicate listeners.
|
|
229
|
+
`matchMedia` does not exist on the server, so each signal returns a static value during SSR and switches to the live result after hydration. Set the default with `provideSsrValue(true)`, or override per call with `up('lg', { ssrValue: true })`.
|
|
259
230
|
|
|
260
231
|
## Contributing
|
|
261
232
|
|
|
262
|
-
Contributions are welcome. See [CONTRIBUTING.md](https://github.com/martsinlabs/ngx-mq/blob/main/CONTRIBUTING.md).
|
|
233
|
+
Contributions are welcome. See [CONTRIBUTING.md](https://github.com/martsinlabs/ngx-mq/blob/main/CONTRIBUTING.md) and [ARCHITECTURE.md](https://github.com/martsinlabs/ngx-mq/blob/main/ARCHITECTURE.md).
|
|
263
234
|
|
|
264
235
|
## License
|
|
265
236
|
|
package/fesm2022/ngx-mq.mjs
CHANGED
|
@@ -71,18 +71,22 @@ function resolveBreakpoint(bp) {
|
|
|
71
71
|
const breakpoints = assertBreakpointsProvided();
|
|
72
72
|
return assertBreakpointExists(bp.trim(), breakpoints);
|
|
73
73
|
}
|
|
74
|
+
function validateBreakpointValue(key, value) {
|
|
75
|
+
if (!Number.isFinite(value)) {
|
|
76
|
+
throw new Error(`[ngx-mq] Breakpoint "${key}" must be a finite number, got ${value}.`);
|
|
77
|
+
}
|
|
78
|
+
if (value <= 0) {
|
|
79
|
+
throw new Error(`[ngx-mq] Breakpoint "${key}" must be > 0, got ${value}.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
74
82
|
function normalizeBreakpoints(bps) {
|
|
75
83
|
const out = {};
|
|
76
84
|
for (const [rawKey, value] of Object.entries(bps)) {
|
|
77
85
|
const key = rawKey.trim();
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (value <= 0) {
|
|
83
|
-
throw new Error(`[ngx-mq] Breakpoint "${key}" must be > 0, got ${value}.`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
+
// Dev-only guard; the false branch never runs in production builds.
|
|
87
|
+
/* v8 ignore next */
|
|
88
|
+
if (isDevMode())
|
|
89
|
+
validateBreakpointValue(key, value);
|
|
86
90
|
out[key] = value;
|
|
87
91
|
}
|
|
88
92
|
return Object.freeze(out);
|
|
@@ -184,9 +188,7 @@ function createConsumer(query, options) {
|
|
|
184
188
|
const defaultSsrValue = inject(NGX_MQ_SSR_VALUE);
|
|
185
189
|
const effectiveSsrValue = options?.ssrValue ?? defaultSsrValue;
|
|
186
190
|
const querySignal = retainUntilDestroy(query, effectiveSsrValue);
|
|
187
|
-
return computed(() => querySignal(), {
|
|
188
|
-
debugName: isDevMode() ? options?.debugName : undefined,
|
|
189
|
-
});
|
|
191
|
+
return computed(() => querySignal(), { debugName: options?.debugName });
|
|
190
192
|
}
|
|
191
193
|
function createConsumerLabel(descriptor) {
|
|
192
194
|
return `[NgxMq Signal: ${descriptor}]`;
|
|
@@ -389,6 +391,31 @@ function reducedMotion(options) {
|
|
|
389
391
|
consumer.toString = () => createConsumerLabel('reducedMotion');
|
|
390
392
|
return consumer;
|
|
391
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* Tracks the user's contrast preference via `(prefers-contrast: ...)`.
|
|
396
|
+
*
|
|
397
|
+
* @param value - `'more'`, `'less'`, `'no-preference'`, or `'custom'`.
|
|
398
|
+
* @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
|
|
399
|
+
* @returns A `Signal<boolean>` that is `true` while the contrast preference matches `value`.
|
|
400
|
+
*
|
|
401
|
+
* @remarks Must be called within an Angular
|
|
402
|
+
* [injection context](https://angular.dev/guide/di/dependency-injection-context).
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* ```ts
|
|
406
|
+
* readonly wantsMoreContrast = prefersContrast('more');
|
|
407
|
+
* ```
|
|
408
|
+
*
|
|
409
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-contrast | MDN: prefers-contrast}
|
|
410
|
+
* @category Media Features
|
|
411
|
+
*/
|
|
412
|
+
function prefersContrast(value, options) {
|
|
413
|
+
isDevMode() && assertInInjectionContext(prefersContrast);
|
|
414
|
+
const query = normalizeQuery(`(prefers-contrast: ${value})`);
|
|
415
|
+
const consumer = createConsumer(query, options);
|
|
416
|
+
consumer.toString = () => createConsumerLabel(`prefersContrast(${value})`);
|
|
417
|
+
return consumer;
|
|
418
|
+
}
|
|
392
419
|
/**
|
|
393
420
|
* Tracks whether the **primary** input device can hover via `(hover: hover)`.
|
|
394
421
|
*
|
|
@@ -686,6 +713,8 @@ function provideMaterialBreakpoints() {
|
|
|
686
713
|
* @category Providers
|
|
687
714
|
*/
|
|
688
715
|
function provideBreakpointEpsilon(epsilon = DEFAULT_BREAKPOINT_EPSILON) {
|
|
716
|
+
// Dev-only guard; the false branch never runs in production builds.
|
|
717
|
+
/* v8 ignore next */
|
|
689
718
|
if (isDevMode())
|
|
690
719
|
validateEpsilon(epsilon);
|
|
691
720
|
return { provide: MQ_BREAKPOINT_EPSILON, useValue: epsilon };
|
|
@@ -720,5 +749,5 @@ function provideSsrValue(value) {
|
|
|
720
749
|
* Generated bundle index. Do not edit.
|
|
721
750
|
*/
|
|
722
751
|
|
|
723
|
-
export { MQ_BREAKPOINTS, MQ_BREAKPOINT_EPSILON, NGX_MQ_SSR_VALUE, and, anyHover, anyPointer, between, colorGamut, colorScheme, displayMode, down, hover, matchMediaSignal, not, or, orientation, pointer, provideBootstrapBreakpoints, provideBreakpointEpsilon, provideBreakpoints, provideMaterialBreakpoints, provideSsrValue, provideTailwindBreakpoints, reducedMotion, up };
|
|
752
|
+
export { MQ_BREAKPOINTS, MQ_BREAKPOINT_EPSILON, NGX_MQ_SSR_VALUE, and, anyHover, anyPointer, between, colorGamut, colorScheme, displayMode, down, hover, matchMediaSignal, not, or, orientation, pointer, prefersContrast, provideBootstrapBreakpoints, provideBreakpointEpsilon, provideBreakpoints, provideMaterialBreakpoints, provideSsrValue, provideTailwindBreakpoints, reducedMotion, up };
|
|
724
753
|
//# sourceMappingURL=ngx-mq.mjs.map
|
package/fesm2022/ngx-mq.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngx-mq.mjs","sources":["../../src/lib/constants.ts","../../src/lib/tokens.ts","../../src/lib/utils/breakpoints.utils.ts","../../src/lib/mql-registry/mql-registry.listeners.ts","../../src/lib/mql-registry/mql-registry.ts","../../src/lib/mql-registry/mql-registry.extensions.ts","../../src/lib/core.ts","../../src/lib/utils/common.utils.ts","../../src/lib/api.ts","../../src/lib/composition.ts","../../src/lib/providers.ts","../../src/index.ts","../../src/ngx-mq.ts"],"sourcesContent":["import { MqBreakpoints } from './models';\n\nexport const TAILWIND_BREAKPOINTS: MqBreakpoints = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536,\n};\n\nexport const BOOTSTRAP_BREAKPOINTS: MqBreakpoints = {\n sm: 576,\n md: 768,\n lg: 992,\n xl: 1200,\n xxl: 1400,\n};\n\nexport const MATERIAL_BREAKPOINTS: MqBreakpoints = {\n sm: 600,\n md: 905,\n lg: 1240,\n xl: 1440,\n};\n\nexport const DEFAULT_BREAKPOINT_EPSILON: number = 0.02;\n","import { InjectionToken } from '@angular/core';\nimport { DEFAULT_BREAKPOINT_EPSILON } from './constants';\nimport { MqBreakpoints } from './models';\n\n/**\n * Holds the active {@link MqBreakpoints} map. Has no default: configure it with\n * {@link provideBreakpoints} or a preset. Inject it to read breakpoints directly.\n *\n * @category Injection Tokens\n */\nexport const MQ_BREAKPOINTS: InjectionToken<MqBreakpoints> = new InjectionToken('MQ_BREAKPOINTS');\n\n/**\n * Holds the epsilon used for exclusive upper bounds. Set it with\n * {@link provideBreakpointEpsilon}; defaults to `0.02`.\n *\n * @category Injection Tokens\n */\nexport const MQ_BREAKPOINT_EPSILON: InjectionToken<number> = new InjectionToken('MQ_BREAKPOINT_EPSILON', {\n providedIn: 'root',\n factory: () => DEFAULT_BREAKPOINT_EPSILON,\n});\n\n/**\n * Holds the value query signals report during SSR. Set it with\n * {@link provideSsrValue}; defaults to `false`.\n *\n * @category Injection Tokens\n */\nexport const NGX_MQ_SSR_VALUE: InjectionToken<boolean> = new InjectionToken('NGX_MQ_SSR_VALUE', {\n providedIn: 'root',\n factory: () => false,\n});\n","import { inject, isDevMode } from '@angular/core';\nimport { MQ_BREAKPOINT_EPSILON, MQ_BREAKPOINTS } from '../tokens';\nimport { MqBreakpoints } from '../models';\n\nfunction assertBreakpointsProvided(): MqBreakpoints {\n const breakpoints: MqBreakpoints | null = inject(MQ_BREAKPOINTS, { optional: true });\n\n if (isDevMode() && !breakpoints) {\n throw new Error(\n '[ngx-mq]: No breakpoints provided.\\n' +\n 'Please configure your app with provideBreakpoints(), ' +\n 'or use one of the built-in presets: ' +\n 'provideTailwindBreakpoints(), provideBootstrapBreakpoints(), provideMaterialBreakpoints().'\n );\n }\n\n return breakpoints!;\n}\n\nfunction assertBreakpointExists(bp: string, breakpoints: MqBreakpoints): number {\n if (isDevMode() && !(bp in breakpoints)) {\n throw new Error(\n `[ngx-mq]: Breakpoint \"${bp}\" not found in provided configuration.\\n` +\n `Available breakpoints: ${Object.keys(breakpoints).join(', ')}.`\n );\n }\n\n return breakpoints[bp];\n}\n\nexport function resolveBreakpoint(bp: string): number {\n const breakpoints: MqBreakpoints = assertBreakpointsProvided();\n\n return assertBreakpointExists(bp.trim(), breakpoints);\n}\n\nexport function normalizeBreakpoints(bps: MqBreakpoints): Readonly<MqBreakpoints> {\n const out: Record<string, number> = {};\n\n for (const [rawKey, value] of Object.entries(bps)) {\n const key = rawKey.trim();\n\n if (isDevMode()) {\n if (!Number.isFinite(value)) {\n throw new Error(`[ngx-mq] Breakpoint \"${key}\" must be a finite number, got ${value}.`);\n }\n\n if (value <= 0) {\n throw new Error(`[ngx-mq] Breakpoint \"${key}\" must be > 0, got ${value}.`);\n }\n }\n\n out[key] = value;\n }\n\n return Object.freeze(out);\n}\n\nexport function validateEpsilon(epsilon: number): void {\n if (!Number.isFinite(epsilon) || epsilon <= 0 || epsilon > 1) {\n throw new Error(`[ngx-mq] Epsilon must be in (0, 1]. Got: ${epsilon}`);\n }\n}\n\nexport function applyMaxEpsilon(value: number): number {\n const epsilon: number = inject(MQ_BREAKPOINT_EPSILON);\n\n return value - epsilon;\n}\n","export function addChangeListenerToMql(mql: MediaQueryList, onChange: (event?: MediaQueryListEvent) => void): void {\n if (typeof mql.addEventListener === 'function') {\n // Modern browsers\n mql.addEventListener('change', onChange);\n } else {\n // Legacy fallback (Safari < 14)\n (mql as any).addListener(onChange);\n }\n}\n\nexport function removeChangeListenerFromMql(\n mql: MediaQueryList,\n onChange: (event?: MediaQueryListEvent) => void\n): void {\n if (typeof mql.removeEventListener === 'function') {\n // Modern browsers\n mql.removeEventListener('change', onChange);\n } else {\n // Legacy fallback (Safari < 14)\n (mql as any).removeListener(onChange);\n }\n}\n","import { signal as createSignal, Signal, WritableSignal } from '@angular/core';\nimport { addChangeListenerToMql, removeChangeListenerFromMql } from './mql-registry.listeners';\nimport { MqlRegistry, MqRetainToken, MqHandle } from './mql-registry.models';\n\nconst REGISTRY_KEY: symbol = Symbol.for('ngx-mq:mql-registry');\n\nconst getRegistry = (): MqlRegistry => {\n const realmGlobal: Record<PropertyKey, unknown> = globalThis;\n\n return (realmGlobal[REGISTRY_KEY] ??= new Map()) as MqlRegistry;\n};\n\nconst createMqHandle = (query: string): MqHandle => {\n const mql: MediaQueryList = matchMedia(query);\n const signal: WritableSignal<boolean> = createSignal(mql.matches, { debugName: `ngx-mq: ${query}` });\n\n const onChange = (event?: MediaQueryListEvent) => signal.set(event?.matches ?? mql.matches);\n\n addChangeListenerToMql(mql, onChange);\n\n return { mql, signal, onChange, retainers: new Set() };\n};\n\nexport function retain(query: string, token: MqRetainToken, ssrValue: boolean): Signal<boolean> {\n // SSR mode\n if (typeof globalThis.matchMedia !== 'function') {\n return createSignal(ssrValue).asReadonly();\n }\n\n const registry: MqlRegistry = getRegistry();\n\n let handle: MqHandle | undefined = registry.get(query);\n\n if (!handle) {\n handle = createMqHandle(query);\n registry.set(query, handle);\n }\n\n handle.retainers.add(token);\n\n return handle.signal.asReadonly();\n}\n\nexport function release(query: string, token: MqRetainToken): boolean {\n const registry: MqlRegistry = getRegistry();\n\n let handle: MqHandle | undefined = registry.get(query);\n\n if (!handle) return false;\n\n const removed: boolean = handle.retainers.delete(token);\n\n if (handle.retainers.size === 0) {\n removeChangeListenerFromMql(handle.mql, handle.onChange);\n registry.delete(query);\n }\n\n return removed;\n}\n\n/* @internal\n * Returns the current registry (used only in tests).\n */\nexport function _getRegistry(): MqlRegistry {\n return getRegistry();\n}\n\n/* @internal\n * Clears all registry entries and removes media-query listeners.\n */\nexport function _resetRegistry(): void {\n const registry: MqlRegistry = getRegistry();\n\n registry.forEach((handle: MqHandle) => {\n removeChangeListenerFromMql(handle.mql, handle.onChange);\n });\n\n registry.clear();\n}\n","import { DestroyRef, inject, Signal } from '@angular/core';\nimport { retain, release } from './mql-registry';\n\nexport function retainUntilDestroy(query: string, ssrValue: boolean): Signal<boolean> {\n const destroyRef: DestroyRef = inject(DestroyRef);\n\n const querySignal: Signal<boolean> = retain(query, destroyRef, ssrValue);\n\n destroyRef.onDestroy(() => release(query, destroyRef));\n\n return querySignal;\n}\n","import { computed, isDevMode, Signal, inject } from '@angular/core';\nimport { retainUntilDestroy } from './mql-registry';\nimport { CreateMediaQueryOptions } from './models';\nimport { NGX_MQ_SSR_VALUE } from './tokens';\n\nexport function createConsumer(query: string, options?: CreateMediaQueryOptions): Signal<boolean> {\n const defaultSsrValue: boolean = inject(NGX_MQ_SSR_VALUE);\n const effectiveSsrValue: boolean = options?.ssrValue ?? defaultSsrValue;\n\n const querySignal: Signal<boolean> = retainUntilDestroy(query, effectiveSsrValue);\n\n return computed(() => querySignal(), {\n debugName: isDevMode() ? options?.debugName : undefined,\n });\n}\n\nexport function createConsumerLabel(descriptor: string): string {\n return `[NgxMq Signal: ${descriptor}]`;\n}\n","export function normalizeQuery(value: string): string {\n return value.trim().replace(/\\s+/g, ' ').toLowerCase();\n}\n","import { assertInInjectionContext, isDevMode, Signal } from '@angular/core';\nimport { applyMaxEpsilon, resolveBreakpoint } from './utils/breakpoints.utils';\nimport { CreateMediaQueryOptions, DisplayModeOption } from './models';\nimport { createConsumer, createConsumerLabel } from './core';\nimport { normalizeQuery } from './utils/common.utils';\n\n/**\n * Tracks whether the viewport width is **at or above** a breakpoint.\n *\n * Builds a `(min-width: <bp>px)` query from the value registered for `bp` via\n * {@link provideBreakpoints} (or a preset like {@link provideTailwindBreakpoints}).\n *\n * @param bp - Name of a configured breakpoint, e.g. `'md'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the viewport width is `>=` the breakpoint.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * export class LayoutComponent {\n * readonly isDesktop = up('lg');\n * }\n * ```\n *\n * @see {@link down} and {@link between} for the complementary ranges.\n * @category Breakpoints\n */\nexport function up(bp: string, options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(up);\n\n const query: string = normalizeQuery(`(min-width: ${resolveBreakpoint(bp)}px)`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`up(${bp})`);\n\n return consumer;\n}\n\n/**\n * Tracks whether the viewport width is **below** a breakpoint.\n *\n * Builds a `(max-width: <bp - epsilon>px)` query. The upper bound is **exclusive**:\n * a small epsilon is subtracted so `down('md')` and {@link up}`('md')` never overlap.\n *\n * @param bp - Name of a configured breakpoint, e.g. `'md'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the viewport width is `<` the breakpoint.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * export class NavComponent {\n * readonly isMobile = down('md');\n * }\n * ```\n *\n * @see {@link provideBreakpointEpsilon} to tune the exclusive-bound epsilon.\n * @category Breakpoints\n */\nexport function down(bp: string, options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(down);\n\n const query: string = normalizeQuery(`(max-width: ${applyMaxEpsilon(resolveBreakpoint(bp))}px)`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`down(${bp})`);\n\n return consumer;\n}\n\n/**\n * Tracks whether the viewport width falls within the range `[minBp, maxBp)`.\n *\n * Combines `min-width` and `max-width` into a single query. The lower bound is\n * inclusive and the upper bound is **exclusive** (epsilon is subtracted from `maxBp`).\n *\n * @param minBp - Name of the lower (inclusive) breakpoint.\n * @param maxBp - Name of the upper (exclusive) breakpoint.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the width is in `[minBp, maxBp)`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * export class GridComponent {\n * readonly isTablet = between('md', 'lg');\n * }\n * ```\n *\n * @category Breakpoints\n */\nexport function between(minBp: string, maxBp: string, options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(between);\n\n const minPx: number = resolveBreakpoint(minBp);\n const maxPx: number = resolveBreakpoint(maxBp);\n const query: string = normalizeQuery(`(min-width: ${minPx}px) and (max-width: ${applyMaxEpsilon(maxPx)}px)`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`between(${minBp}, ${maxBp})`);\n\n return consumer;\n}\n\n/**\n * Tracks the screen orientation via the `(orientation: ...)` media feature.\n *\n * @param value - `'portrait'` (height `>=` width) or `'landscape'` (width `>` height).\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the orientation matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isLandscape = orientation('landscape');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/orientation | MDN: orientation}\n * @category Media Features\n */\nexport function orientation(value: 'portrait' | 'landscape', options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(orientation);\n\n const query: string = normalizeQuery(`(orientation: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`orientation(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks the user's preferred color scheme via `(prefers-color-scheme: ...)`.\n *\n * @param value - `'light'` or `'dark'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the system scheme matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isDark = colorScheme('dark');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme | MDN: prefers-color-scheme}\n * @category Media Features\n */\nexport function colorScheme(value: 'light' | 'dark', options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(colorScheme);\n\n const query: string = normalizeQuery(`(prefers-color-scheme: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`colorScheme(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks how the app is being displayed via the `(display-mode: ...)` feature,\n * useful for detecting installed PWAs.\n *\n * @param value - One of {@link DisplayModeOption}, e.g. `'standalone'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the display mode matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isInstalledPwa = displayMode('standalone');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode | MDN: display-mode}\n * @category Media Features\n */\nexport function displayMode(value: DisplayModeOption, options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(displayMode);\n\n const query = normalizeQuery(`(display-mode: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`displayMode(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks whether the user has requested reduced motion via\n * `(prefers-reduced-motion: reduce)`.\n *\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while reduced motion is preferred.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly reduceMotion = reducedMotion();\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion | MDN: prefers-reduced-motion}\n * @category Media Features\n */\nexport function reducedMotion(options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(reducedMotion);\n\n const query: string = normalizeQuery('(prefers-reduced-motion: reduce)');\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel('reducedMotion');\n\n return consumer;\n}\n\n/**\n * Tracks whether the **primary** input device can hover via `(hover: hover)`.\n *\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the primary pointer supports hover.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly canHover = hover();\n * ```\n *\n * @see {@link anyHover} to test **any** available input device.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover | MDN: hover}\n * @category Media Features\n */\nexport function hover(options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(hover);\n\n const query: string = normalizeQuery('(hover: hover)');\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel('hover');\n\n return consumer;\n}\n\n/**\n * Tracks whether **any** available input device can hover via `(any-hover: hover)`.\n *\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while at least one pointer supports hover.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly anyCanHover = anyHover();\n * ```\n *\n * @see {@link hover} to test only the primary input device.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/any-hover | MDN: any-hover}\n * @category Media Features\n */\nexport function anyHover(options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(anyHover);\n\n const query: string = normalizeQuery('(any-hover: hover)');\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel('anyHover');\n\n return consumer;\n}\n\n/**\n * Tracks the accuracy of the **primary** pointer via `(pointer: ...)`.\n *\n * @param value - `'fine'` (mouse/stylus), `'coarse'` (touch), or `'none'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the primary pointer matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isTouch = pointer('coarse');\n * ```\n *\n * @see {@link anyPointer} to test **any** available input device.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer | MDN: pointer}\n * @category Media Features\n */\nexport function pointer(value: 'fine' | 'coarse' | 'none', options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(pointer);\n\n const query: string = normalizeQuery(`(pointer: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`pointer(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks the accuracy of **any** available pointer via `(any-pointer: ...)`.\n *\n * @param value - `'fine'` (mouse/stylus), `'coarse'` (touch), or `'none'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while at least one pointer matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly hasFinePointer = anyPointer('fine');\n * ```\n *\n * @see {@link pointer} to test only the primary input device.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/any-pointer | MDN: any-pointer}\n * @category Media Features\n */\nexport function anyPointer(value: 'fine' | 'coarse' | 'none', options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(anyPointer);\n\n const query: string = normalizeQuery(`(any-pointer: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`anyPointer(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks the approximate color gamut of the display via `(color-gamut: ...)`.\n *\n * @param value - `'srgb'`, `'p3'`, or `'rec2020'` (ordered by increasing range).\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the display covers `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isWideGamut = colorGamut('p3');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/color-gamut | MDN: color-gamut}\n * @category Media Features\n */\nexport function colorGamut(value: 'srgb' | 'p3' | 'rec2020', options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(colorGamut);\n\n const query: string = normalizeQuery(`(color-gamut: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`colorGamut(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks an arbitrary, raw CSS media query.\n *\n * Use this escape hatch for any feature not covered by the dedicated helpers.\n * The query is normalized (trimmed, collapsed whitespace, lower-cased) before use.\n *\n * @param query - A valid CSS media query, e.g. `'(min-resolution: 2dppx)'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that reflects the live result of the query.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isRetina = matchMediaSignal('(min-resolution: 2dppx)');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries | MDN: CSS media queries}\n * @category Custom Queries\n */\nexport function matchMediaSignal(query: string, options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(matchMediaSignal);\n\n const media: string = normalizeQuery(query);\n const consumer: Signal<boolean> = createConsumer(media, options);\n\n consumer.toString = () => createConsumerLabel(`matchMediaSignal(${query})`);\n\n return consumer;\n}\n","import { computed, Signal } from '@angular/core';\nimport { createConsumerLabel } from './core';\n\nconst LABEL_RE = /^\\[NgxMq Signal: (.+)]$/;\n\n/** Extracts the inner descriptor from an ngx-mq signal label, or falls back to its raw toString(). */\nfunction describe(condition: Signal<boolean>): string {\n const raw: string = condition.toString();\n const match: RegExpExecArray | null = LABEL_RE.exec(raw);\n\n return match ? match[1] : raw;\n}\n\n/**\n * Combines boolean signals with logical **AND**.\n *\n * Composition happens at the signal level, so the underlying media-query\n * listeners stay shared and are still cleaned up automatically.\n *\n * @param conditions - Boolean signals to combine. An empty call returns a\n * signal that is always `true` (vacuous truth).\n * @returns A `Signal<boolean>` that is `true` only when **every** condition is `true`.\n *\n * @example\n * ```ts\n * readonly isLandscapeDesktop = and(up('lg'), orientation('landscape'), hover());\n * ```\n *\n * @see {@link or} and {@link not}.\n * @category Combining Signals\n */\nexport function and(...conditions: Signal<boolean>[]): Signal<boolean> {\n const result: Signal<boolean> = computed(() => conditions.every((condition: Signal<boolean>) => condition()));\n\n result.toString = () => createConsumerLabel(`and(${conditions.map(describe).join(', ')})`);\n\n return result;\n}\n\n/**\n * Combines boolean signals with logical **OR**.\n *\n * Composition happens at the signal level, so the underlying media-query\n * listeners stay shared and are still cleaned up automatically.\n *\n * @param conditions - Boolean signals to combine. An empty call returns a\n * signal that is always `false`.\n * @returns A `Signal<boolean>` that is `true` when **at least one** condition is `true`.\n *\n * @example\n * ```ts\n * readonly prefersSimpleUi = or(down('md'), reducedMotion());\n * ```\n *\n * @see {@link and} and {@link not}.\n * @category Combining Signals\n */\nexport function or(...conditions: Signal<boolean>[]): Signal<boolean> {\n const result: Signal<boolean> = computed(() => conditions.some((condition: Signal<boolean>) => condition()));\n\n result.toString = () => createConsumerLabel(`or(${conditions.map(describe).join(', ')})`);\n\n return result;\n}\n\n/**\n * Negates a boolean signal.\n *\n * Useful for features that have no direct inverse helper, such as\n * \"devices without hover\": `not(hover())`.\n *\n * @param condition - The boolean signal to invert.\n * @returns A `Signal<boolean>` that is `true` when `condition` is `false`, and vice versa.\n *\n * @example\n * ```ts\n * readonly isTouchLike = not(hover());\n * ```\n *\n * @see {@link and} and {@link or}.\n * @category Combining Signals\n */\nexport function not(condition: Signal<boolean>): Signal<boolean> {\n const result: Signal<boolean> = computed(() => !condition());\n\n result.toString = () => createConsumerLabel(`not(${describe(condition)})`);\n\n return result;\n}\n","import { isDevMode, Provider } from '@angular/core';\nimport { MQ_BREAKPOINT_EPSILON, MQ_BREAKPOINTS, NGX_MQ_SSR_VALUE } from './tokens';\nimport { normalizeBreakpoints, validateEpsilon } from './utils/breakpoints.utils';\nimport { MqBreakpoints } from './models';\nimport {\n BOOTSTRAP_BREAKPOINTS,\n DEFAULT_BREAKPOINT_EPSILON,\n MATERIAL_BREAKPOINTS,\n TAILWIND_BREAKPOINTS,\n} from './constants';\n\n/**\n * Registers a custom breakpoint map, enabling {@link up}, {@link down} and {@link between}.\n *\n * Provide once at bootstrap, or at any injector level to scope/override breakpoints.\n *\n * @param bps - A {@link MqBreakpoints} map of names to minimum widths in pixels.\n * @returns An Angular {@link Provider}.\n *\n * @example\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideBreakpoints({ sm: 640, md: 768, lg: 1024 })],\n * });\n * ```\n *\n * @category Providers\n */\nexport function provideBreakpoints(bps: MqBreakpoints): Provider {\n return { provide: MQ_BREAKPOINTS, useValue: normalizeBreakpoints(bps) };\n}\n\n/**\n * Registers the default Tailwind CSS breakpoints:\n * `sm: 640, md: 768, lg: 1024, xl: 1280, 2xl: 1536`.\n *\n * @returns An Angular {@link Provider}.\n * @category Providers\n */\nexport function provideTailwindBreakpoints(): Provider {\n return provideBreakpoints(TAILWIND_BREAKPOINTS);\n}\n\n/**\n * Registers the default Bootstrap breakpoints:\n * `sm: 576, md: 768, lg: 992, xl: 1200, xxl: 1400`.\n *\n * @returns An Angular {@link Provider}.\n * @category Providers\n */\nexport function provideBootstrapBreakpoints(): Provider {\n return provideBreakpoints(BOOTSTRAP_BREAKPOINTS);\n}\n\n/**\n * Registers the default Material 2 breakpoints:\n * `sm: 600, md: 905, lg: 1240, xl: 1440`.\n *\n * @returns An Angular {@link Provider}.\n * @category Providers\n */\nexport function provideMaterialBreakpoints(): Provider {\n return provideBreakpoints(MATERIAL_BREAKPOINTS);\n}\n\n/**\n * Sets the epsilon subtracted from exclusive upper bounds in {@link down} and\n * {@link between}, preventing adjacent ranges from overlapping.\n *\n * @param epsilon - A value in the range `(0, 1]`. Defaults to `0.02`.\n * @returns An Angular {@link Provider}.\n *\n * @example\n * ```ts\n * provideBreakpointEpsilon(0.02);\n * ```\n *\n * @category Providers\n */\nexport function provideBreakpointEpsilon(epsilon: number = DEFAULT_BREAKPOINT_EPSILON): Provider {\n if (isDevMode()) validateEpsilon(epsilon);\n\n return { provide: MQ_BREAKPOINT_EPSILON, useValue: epsilon };\n}\n\n/**\n * Sets the app-wide value query signals report during server-side rendering,\n * where `matchMedia` is unavailable. A per-call `ssrValue` overrides this.\n *\n * @param value - The boolean returned by every signal on the server.\n * @returns An Angular {@link Provider}.\n *\n * @example\n * ```ts\n * provideSsrValue(true);\n * ```\n *\n * @category Providers\n */\nexport function provideSsrValue(value: boolean): Provider {\n return { provide: NGX_MQ_SSR_VALUE, useValue: value };\n}\n","/**\n * @packageDocumentation\n *\n * @document ../guides/getting-started.md\n * @document ../guides/ssr.md\n * @document ../guides/recipes.md\n */\n\nexport * from './lib/api';\nexport * from './lib/composition';\nexport * from './lib/tokens';\nexport * from './lib/providers';\nexport * from './lib/models';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["signal","createSignal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngx-mq.mjs","sources":["../../src/lib/constants.ts","../../src/lib/tokens.ts","../../src/lib/utils/breakpoints.utils.ts","../../src/lib/mql-registry/mql-registry.listeners.ts","../../src/lib/mql-registry/mql-registry.ts","../../src/lib/mql-registry/mql-registry.extensions.ts","../../src/lib/core.ts","../../src/lib/utils/common.utils.ts","../../src/lib/api.ts","../../src/lib/composition.ts","../../src/lib/providers.ts","../../src/index.ts","../../src/ngx-mq.ts"],"sourcesContent":["import { MqBreakpoints } from './models';\n\nexport const TAILWIND_BREAKPOINTS: MqBreakpoints = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536,\n};\n\nexport const BOOTSTRAP_BREAKPOINTS: MqBreakpoints = {\n sm: 576,\n md: 768,\n lg: 992,\n xl: 1200,\n xxl: 1400,\n};\n\nexport const MATERIAL_BREAKPOINTS: MqBreakpoints = {\n sm: 600,\n md: 905,\n lg: 1240,\n xl: 1440,\n};\n\nexport const DEFAULT_BREAKPOINT_EPSILON: number = 0.02;\n","import { InjectionToken } from '@angular/core';\nimport { DEFAULT_BREAKPOINT_EPSILON } from './constants';\nimport { MqBreakpoints } from './models';\n\n/**\n * Holds the active {@link MqBreakpoints} map. Has no default: configure it with\n * {@link provideBreakpoints} or a preset. Inject it to read breakpoints directly.\n *\n * @category Injection Tokens\n */\nexport const MQ_BREAKPOINTS: InjectionToken<MqBreakpoints> = new InjectionToken('MQ_BREAKPOINTS');\n\n/**\n * Holds the epsilon used for exclusive upper bounds. Set it with\n * {@link provideBreakpointEpsilon}; defaults to `0.02`.\n *\n * @category Injection Tokens\n */\nexport const MQ_BREAKPOINT_EPSILON: InjectionToken<number> = new InjectionToken('MQ_BREAKPOINT_EPSILON', {\n providedIn: 'root',\n factory: () => DEFAULT_BREAKPOINT_EPSILON,\n});\n\n/**\n * Holds the value query signals report during SSR. Set it with\n * {@link provideSsrValue}; defaults to `false`.\n *\n * @category Injection Tokens\n */\nexport const NGX_MQ_SSR_VALUE: InjectionToken<boolean> = new InjectionToken('NGX_MQ_SSR_VALUE', {\n providedIn: 'root',\n factory: () => false,\n});\n","import { inject, isDevMode } from '@angular/core';\nimport { MQ_BREAKPOINT_EPSILON, MQ_BREAKPOINTS } from '../tokens';\nimport { MqBreakpoints } from '../models';\n\nfunction assertBreakpointsProvided(): MqBreakpoints {\n const breakpoints: MqBreakpoints | null = inject(MQ_BREAKPOINTS, { optional: true });\n\n if (isDevMode() && !breakpoints) {\n throw new Error(\n '[ngx-mq]: No breakpoints provided.\\n' +\n 'Please configure your app with provideBreakpoints(), ' +\n 'or use one of the built-in presets: ' +\n 'provideTailwindBreakpoints(), provideBootstrapBreakpoints(), provideMaterialBreakpoints().'\n );\n }\n\n return breakpoints!;\n}\n\nfunction assertBreakpointExists(bp: string, breakpoints: MqBreakpoints): number {\n if (isDevMode() && !(bp in breakpoints)) {\n throw new Error(\n `[ngx-mq]: Breakpoint \"${bp}\" not found in provided configuration.\\n` +\n `Available breakpoints: ${Object.keys(breakpoints).join(', ')}.`\n );\n }\n\n return breakpoints[bp];\n}\n\nexport function resolveBreakpoint(bp: string): number {\n const breakpoints: MqBreakpoints = assertBreakpointsProvided();\n\n return assertBreakpointExists(bp.trim(), breakpoints);\n}\n\nfunction validateBreakpointValue(key: string, value: number): void {\n if (!Number.isFinite(value)) {\n throw new Error(`[ngx-mq] Breakpoint \"${key}\" must be a finite number, got ${value}.`);\n }\n\n if (value <= 0) {\n throw new Error(`[ngx-mq] Breakpoint \"${key}\" must be > 0, got ${value}.`);\n }\n}\n\nexport function normalizeBreakpoints(bps: MqBreakpoints): Readonly<MqBreakpoints> {\n const out: Record<string, number> = {};\n\n for (const [rawKey, value] of Object.entries(bps)) {\n const key = rawKey.trim();\n\n // Dev-only guard; the false branch never runs in production builds.\n /* v8 ignore next */\n if (isDevMode()) validateBreakpointValue(key, value);\n\n out[key] = value;\n }\n\n return Object.freeze(out);\n}\n\nexport function validateEpsilon(epsilon: number): void {\n if (!Number.isFinite(epsilon) || epsilon <= 0 || epsilon > 1) {\n throw new Error(`[ngx-mq] Epsilon must be in (0, 1]. Got: ${epsilon}`);\n }\n}\n\nexport function applyMaxEpsilon(value: number): number {\n const epsilon: number = inject(MQ_BREAKPOINT_EPSILON);\n\n return value - epsilon;\n}\n","export function addChangeListenerToMql(mql: MediaQueryList, onChange: (event?: MediaQueryListEvent) => void): void {\n if (typeof mql.addEventListener === 'function') {\n // Modern browsers\n mql.addEventListener('change', onChange);\n } else {\n // Legacy fallback (Safari < 14)\n (mql as any).addListener(onChange);\n }\n}\n\nexport function removeChangeListenerFromMql(\n mql: MediaQueryList,\n onChange: (event?: MediaQueryListEvent) => void\n): void {\n if (typeof mql.removeEventListener === 'function') {\n // Modern browsers\n mql.removeEventListener('change', onChange);\n } else {\n // Legacy fallback (Safari < 14)\n (mql as any).removeListener(onChange);\n }\n}\n","import { signal as createSignal, Signal, WritableSignal } from '@angular/core';\nimport { addChangeListenerToMql, removeChangeListenerFromMql } from './mql-registry.listeners';\nimport { MqlRegistry, MqRetainToken, MqHandle } from './mql-registry.models';\n\nconst REGISTRY_KEY: symbol = Symbol.for('ngx-mq:mql-registry');\n\nconst getRegistry = (): MqlRegistry => {\n const realmGlobal: Record<PropertyKey, unknown> = globalThis;\n\n return (realmGlobal[REGISTRY_KEY] ??= new Map()) as MqlRegistry;\n};\n\nconst createMqHandle = (query: string): MqHandle => {\n const mql: MediaQueryList = matchMedia(query);\n const signal: WritableSignal<boolean> = createSignal(mql.matches, { debugName: `ngx-mq: ${query}` });\n\n const onChange = (event?: MediaQueryListEvent) => signal.set(event?.matches ?? mql.matches);\n\n addChangeListenerToMql(mql, onChange);\n\n return { mql, signal, onChange, retainers: new Set() };\n};\n\nexport function retain(query: string, token: MqRetainToken, ssrValue: boolean): Signal<boolean> {\n // SSR mode\n if (typeof globalThis.matchMedia !== 'function') {\n return createSignal(ssrValue).asReadonly();\n }\n\n const registry: MqlRegistry = getRegistry();\n\n let handle: MqHandle | undefined = registry.get(query);\n\n if (!handle) {\n handle = createMqHandle(query);\n registry.set(query, handle);\n }\n\n handle.retainers.add(token);\n\n return handle.signal.asReadonly();\n}\n\nexport function release(query: string, token: MqRetainToken): boolean {\n const registry: MqlRegistry = getRegistry();\n\n let handle: MqHandle | undefined = registry.get(query);\n\n if (!handle) return false;\n\n const removed: boolean = handle.retainers.delete(token);\n\n if (handle.retainers.size === 0) {\n removeChangeListenerFromMql(handle.mql, handle.onChange);\n registry.delete(query);\n }\n\n return removed;\n}\n\n/* @internal\n * Returns the current registry (used only in tests).\n */\nexport function _getRegistry(): MqlRegistry {\n return getRegistry();\n}\n\n/* @internal\n * Clears all registry entries and removes media-query listeners.\n */\nexport function _resetRegistry(): void {\n const registry: MqlRegistry = getRegistry();\n\n registry.forEach((handle: MqHandle) => {\n removeChangeListenerFromMql(handle.mql, handle.onChange);\n });\n\n registry.clear();\n}\n","import { DestroyRef, inject, Signal } from '@angular/core';\nimport { retain, release } from './mql-registry';\n\nexport function retainUntilDestroy(query: string, ssrValue: boolean): Signal<boolean> {\n const destroyRef: DestroyRef = inject(DestroyRef);\n\n const querySignal: Signal<boolean> = retain(query, destroyRef, ssrValue);\n\n destroyRef.onDestroy(() => release(query, destroyRef));\n\n return querySignal;\n}\n","import { computed, Signal, inject } from '@angular/core';\nimport { retainUntilDestroy } from './mql-registry';\nimport { CreateMediaQueryOptions } from './models';\nimport { NGX_MQ_SSR_VALUE } from './tokens';\n\nexport function createConsumer(query: string, options?: CreateMediaQueryOptions): Signal<boolean> {\n const defaultSsrValue: boolean = inject(NGX_MQ_SSR_VALUE);\n const effectiveSsrValue: boolean = options?.ssrValue ?? defaultSsrValue;\n\n const querySignal: Signal<boolean> = retainUntilDestroy(query, effectiveSsrValue);\n\n return computed(() => querySignal(), { debugName: options?.debugName });\n}\n\nexport function createConsumerLabel(descriptor: string): string {\n return `[NgxMq Signal: ${descriptor}]`;\n}\n","export function normalizeQuery(value: string): string {\n return value.trim().replace(/\\s+/g, ' ').toLowerCase();\n}\n","import { assertInInjectionContext, isDevMode, Signal } from '@angular/core';\nimport { applyMaxEpsilon, resolveBreakpoint } from './utils/breakpoints.utils';\nimport { CreateMediaQueryOptions, DisplayModeOption } from './models';\nimport { createConsumer, createConsumerLabel } from './core';\nimport { normalizeQuery } from './utils/common.utils';\n\n/**\n * Tracks whether the viewport width is **at or above** a breakpoint.\n *\n * Builds a `(min-width: <bp>px)` query from the value registered for `bp` via\n * {@link provideBreakpoints} (or a preset like {@link provideTailwindBreakpoints}).\n *\n * @param bp - Name of a configured breakpoint, e.g. `'md'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the viewport width is `>=` the breakpoint.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * export class LayoutComponent {\n * readonly isDesktop = up('lg');\n * }\n * ```\n *\n * @see {@link down} and {@link between} for the complementary ranges.\n * @category Breakpoints\n */\nexport function up(bp: string, options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(up);\n\n const query: string = normalizeQuery(`(min-width: ${resolveBreakpoint(bp)}px)`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`up(${bp})`);\n\n return consumer;\n}\n\n/**\n * Tracks whether the viewport width is **below** a breakpoint.\n *\n * Builds a `(max-width: <bp - epsilon>px)` query. The upper bound is **exclusive**:\n * a small epsilon is subtracted so `down('md')` and {@link up}`('md')` never overlap.\n *\n * @param bp - Name of a configured breakpoint, e.g. `'md'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the viewport width is `<` the breakpoint.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * export class NavComponent {\n * readonly isMobile = down('md');\n * }\n * ```\n *\n * @see {@link provideBreakpointEpsilon} to tune the exclusive-bound epsilon.\n * @category Breakpoints\n */\nexport function down(bp: string, options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(down);\n\n const query: string = normalizeQuery(`(max-width: ${applyMaxEpsilon(resolveBreakpoint(bp))}px)`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`down(${bp})`);\n\n return consumer;\n}\n\n/**\n * Tracks whether the viewport width falls within the range `[minBp, maxBp)`.\n *\n * Combines `min-width` and `max-width` into a single query. The lower bound is\n * inclusive and the upper bound is **exclusive** (epsilon is subtracted from `maxBp`).\n *\n * @param minBp - Name of the lower (inclusive) breakpoint.\n * @param maxBp - Name of the upper (exclusive) breakpoint.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the width is in `[minBp, maxBp)`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * export class GridComponent {\n * readonly isTablet = between('md', 'lg');\n * }\n * ```\n *\n * @category Breakpoints\n */\nexport function between(minBp: string, maxBp: string, options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(between);\n\n const minPx: number = resolveBreakpoint(minBp);\n const maxPx: number = resolveBreakpoint(maxBp);\n const query: string = normalizeQuery(`(min-width: ${minPx}px) and (max-width: ${applyMaxEpsilon(maxPx)}px)`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`between(${minBp}, ${maxBp})`);\n\n return consumer;\n}\n\n/**\n * Tracks the screen orientation via the `(orientation: ...)` media feature.\n *\n * @param value - `'portrait'` (height `>=` width) or `'landscape'` (width `>` height).\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the orientation matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isLandscape = orientation('landscape');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/orientation | MDN: orientation}\n * @category Media Features\n */\nexport function orientation(value: 'portrait' | 'landscape', options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(orientation);\n\n const query: string = normalizeQuery(`(orientation: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`orientation(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks the user's preferred color scheme via `(prefers-color-scheme: ...)`.\n *\n * @param value - `'light'` or `'dark'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the system scheme matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isDark = colorScheme('dark');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme | MDN: prefers-color-scheme}\n * @category Media Features\n */\nexport function colorScheme(value: 'light' | 'dark', options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(colorScheme);\n\n const query: string = normalizeQuery(`(prefers-color-scheme: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`colorScheme(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks how the app is being displayed via the `(display-mode: ...)` feature,\n * useful for detecting installed PWAs.\n *\n * @param value - One of {@link DisplayModeOption}, e.g. `'standalone'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the display mode matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isInstalledPwa = displayMode('standalone');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode | MDN: display-mode}\n * @category Media Features\n */\nexport function displayMode(value: DisplayModeOption, options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(displayMode);\n\n const query = normalizeQuery(`(display-mode: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`displayMode(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks whether the user has requested reduced motion via\n * `(prefers-reduced-motion: reduce)`.\n *\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while reduced motion is preferred.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly reduceMotion = reducedMotion();\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion | MDN: prefers-reduced-motion}\n * @category Media Features\n */\nexport function reducedMotion(options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(reducedMotion);\n\n const query: string = normalizeQuery('(prefers-reduced-motion: reduce)');\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel('reducedMotion');\n\n return consumer;\n}\n\n/**\n * Tracks the user's contrast preference via `(prefers-contrast: ...)`.\n *\n * @param value - `'more'`, `'less'`, `'no-preference'`, or `'custom'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the contrast preference matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly wantsMoreContrast = prefersContrast('more');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-contrast | MDN: prefers-contrast}\n * @category Media Features\n */\nexport function prefersContrast(\n value: 'more' | 'less' | 'no-preference' | 'custom',\n options?: CreateMediaQueryOptions\n): Signal<boolean> {\n isDevMode() && assertInInjectionContext(prefersContrast);\n\n const query: string = normalizeQuery(`(prefers-contrast: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`prefersContrast(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks whether the **primary** input device can hover via `(hover: hover)`.\n *\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the primary pointer supports hover.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly canHover = hover();\n * ```\n *\n * @see {@link anyHover} to test **any** available input device.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover | MDN: hover}\n * @category Media Features\n */\nexport function hover(options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(hover);\n\n const query: string = normalizeQuery('(hover: hover)');\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel('hover');\n\n return consumer;\n}\n\n/**\n * Tracks whether **any** available input device can hover via `(any-hover: hover)`.\n *\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while at least one pointer supports hover.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly anyCanHover = anyHover();\n * ```\n *\n * @see {@link hover} to test only the primary input device.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/any-hover | MDN: any-hover}\n * @category Media Features\n */\nexport function anyHover(options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(anyHover);\n\n const query: string = normalizeQuery('(any-hover: hover)');\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel('anyHover');\n\n return consumer;\n}\n\n/**\n * Tracks the accuracy of the **primary** pointer via `(pointer: ...)`.\n *\n * @param value - `'fine'` (mouse/stylus), `'coarse'` (touch), or `'none'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the primary pointer matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isTouch = pointer('coarse');\n * ```\n *\n * @see {@link anyPointer} to test **any** available input device.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer | MDN: pointer}\n * @category Media Features\n */\nexport function pointer(value: 'fine' | 'coarse' | 'none', options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(pointer);\n\n const query: string = normalizeQuery(`(pointer: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`pointer(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks the accuracy of **any** available pointer via `(any-pointer: ...)`.\n *\n * @param value - `'fine'` (mouse/stylus), `'coarse'` (touch), or `'none'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while at least one pointer matches `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly hasFinePointer = anyPointer('fine');\n * ```\n *\n * @see {@link pointer} to test only the primary input device.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/any-pointer | MDN: any-pointer}\n * @category Media Features\n */\nexport function anyPointer(value: 'fine' | 'coarse' | 'none', options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(anyPointer);\n\n const query: string = normalizeQuery(`(any-pointer: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`anyPointer(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks the approximate color gamut of the display via `(color-gamut: ...)`.\n *\n * @param value - `'srgb'`, `'p3'`, or `'rec2020'` (ordered by increasing range).\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that is `true` while the display covers `value`.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isWideGamut = colorGamut('p3');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/color-gamut | MDN: color-gamut}\n * @category Media Features\n */\nexport function colorGamut(value: 'srgb' | 'p3' | 'rec2020', options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(colorGamut);\n\n const query: string = normalizeQuery(`(color-gamut: ${value})`);\n const consumer: Signal<boolean> = createConsumer(query, options);\n\n consumer.toString = () => createConsumerLabel(`colorGamut(${value})`);\n\n return consumer;\n}\n\n/**\n * Tracks an arbitrary, raw CSS media query.\n *\n * Use this escape hatch for any feature not covered by the dedicated helpers.\n * The query is normalized (trimmed, collapsed whitespace, lower-cased) before use.\n *\n * @param query - A valid CSS media query, e.g. `'(min-resolution: 2dppx)'`.\n * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).\n * @returns A `Signal<boolean>` that reflects the live result of the query.\n *\n * @remarks Must be called within an Angular\n * [injection context](https://angular.dev/guide/di/dependency-injection-context).\n *\n * @example\n * ```ts\n * readonly isRetina = matchMediaSignal('(min-resolution: 2dppx)');\n * ```\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries | MDN: CSS media queries}\n * @category Custom Queries\n */\nexport function matchMediaSignal(query: string, options?: CreateMediaQueryOptions): Signal<boolean> {\n isDevMode() && assertInInjectionContext(matchMediaSignal);\n\n const media: string = normalizeQuery(query);\n const consumer: Signal<boolean> = createConsumer(media, options);\n\n consumer.toString = () => createConsumerLabel(`matchMediaSignal(${query})`);\n\n return consumer;\n}\n","import { computed, Signal } from '@angular/core';\nimport { createConsumerLabel } from './core';\n\nconst LABEL_RE = /^\\[NgxMq Signal: (.+)]$/;\n\n/** Extracts the inner descriptor from an ngx-mq signal label, or falls back to its raw toString(). */\nfunction describe(condition: Signal<boolean>): string {\n const raw: string = condition.toString();\n const match: RegExpExecArray | null = LABEL_RE.exec(raw);\n\n return match ? match[1] : raw;\n}\n\n/**\n * Combines boolean signals with logical **AND**.\n *\n * Composition happens at the signal level, so the underlying media-query\n * listeners stay shared and are still cleaned up automatically.\n *\n * @param conditions - Boolean signals to combine. An empty call returns a\n * signal that is always `true` (vacuous truth).\n * @returns A `Signal<boolean>` that is `true` only when **every** condition is `true`.\n *\n * @example\n * ```ts\n * readonly isLandscapeDesktop = and(up('lg'), orientation('landscape'), hover());\n * ```\n *\n * @see {@link or} and {@link not}.\n * @category Combining Signals\n */\nexport function and(...conditions: Signal<boolean>[]): Signal<boolean> {\n const result: Signal<boolean> = computed(() => conditions.every((condition: Signal<boolean>) => condition()));\n\n result.toString = () => createConsumerLabel(`and(${conditions.map(describe).join(', ')})`);\n\n return result;\n}\n\n/**\n * Combines boolean signals with logical **OR**.\n *\n * Composition happens at the signal level, so the underlying media-query\n * listeners stay shared and are still cleaned up automatically.\n *\n * @param conditions - Boolean signals to combine. An empty call returns a\n * signal that is always `false`.\n * @returns A `Signal<boolean>` that is `true` when **at least one** condition is `true`.\n *\n * @example\n * ```ts\n * readonly prefersSimpleUi = or(down('md'), reducedMotion());\n * ```\n *\n * @see {@link and} and {@link not}.\n * @category Combining Signals\n */\nexport function or(...conditions: Signal<boolean>[]): Signal<boolean> {\n const result: Signal<boolean> = computed(() => conditions.some((condition: Signal<boolean>) => condition()));\n\n result.toString = () => createConsumerLabel(`or(${conditions.map(describe).join(', ')})`);\n\n return result;\n}\n\n/**\n * Negates a boolean signal.\n *\n * Useful for features that have no direct inverse helper, such as\n * \"devices without hover\": `not(hover())`.\n *\n * @param condition - The boolean signal to invert.\n * @returns A `Signal<boolean>` that is `true` when `condition` is `false`, and vice versa.\n *\n * @example\n * ```ts\n * readonly isTouchLike = not(hover());\n * ```\n *\n * @see {@link and} and {@link or}.\n * @category Combining Signals\n */\nexport function not(condition: Signal<boolean>): Signal<boolean> {\n const result: Signal<boolean> = computed(() => !condition());\n\n result.toString = () => createConsumerLabel(`not(${describe(condition)})`);\n\n return result;\n}\n","import { isDevMode, Provider } from '@angular/core';\nimport { MQ_BREAKPOINT_EPSILON, MQ_BREAKPOINTS, NGX_MQ_SSR_VALUE } from './tokens';\nimport { normalizeBreakpoints, validateEpsilon } from './utils/breakpoints.utils';\nimport { MqBreakpoints } from './models';\nimport {\n BOOTSTRAP_BREAKPOINTS,\n DEFAULT_BREAKPOINT_EPSILON,\n MATERIAL_BREAKPOINTS,\n TAILWIND_BREAKPOINTS,\n} from './constants';\n\n/**\n * Registers a custom breakpoint map, enabling {@link up}, {@link down} and {@link between}.\n *\n * Provide once at bootstrap, or at any injector level to scope/override breakpoints.\n *\n * @param bps - A {@link MqBreakpoints} map of names to minimum widths in pixels.\n * @returns An Angular {@link Provider}.\n *\n * @example\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideBreakpoints({ sm: 640, md: 768, lg: 1024 })],\n * });\n * ```\n *\n * @category Providers\n */\nexport function provideBreakpoints(bps: MqBreakpoints): Provider {\n return { provide: MQ_BREAKPOINTS, useValue: normalizeBreakpoints(bps) };\n}\n\n/**\n * Registers the default Tailwind CSS breakpoints:\n * `sm: 640, md: 768, lg: 1024, xl: 1280, 2xl: 1536`.\n *\n * @returns An Angular {@link Provider}.\n * @category Providers\n */\nexport function provideTailwindBreakpoints(): Provider {\n return provideBreakpoints(TAILWIND_BREAKPOINTS);\n}\n\n/**\n * Registers the default Bootstrap breakpoints:\n * `sm: 576, md: 768, lg: 992, xl: 1200, xxl: 1400`.\n *\n * @returns An Angular {@link Provider}.\n * @category Providers\n */\nexport function provideBootstrapBreakpoints(): Provider {\n return provideBreakpoints(BOOTSTRAP_BREAKPOINTS);\n}\n\n/**\n * Registers the default Material 2 breakpoints:\n * `sm: 600, md: 905, lg: 1240, xl: 1440`.\n *\n * @returns An Angular {@link Provider}.\n * @category Providers\n */\nexport function provideMaterialBreakpoints(): Provider {\n return provideBreakpoints(MATERIAL_BREAKPOINTS);\n}\n\n/**\n * Sets the epsilon subtracted from exclusive upper bounds in {@link down} and\n * {@link between}, preventing adjacent ranges from overlapping.\n *\n * @param epsilon - A value in the range `(0, 1]`. Defaults to `0.02`.\n * @returns An Angular {@link Provider}.\n *\n * @example\n * ```ts\n * provideBreakpointEpsilon(0.02);\n * ```\n *\n * @category Providers\n */\nexport function provideBreakpointEpsilon(epsilon: number = DEFAULT_BREAKPOINT_EPSILON): Provider {\n // Dev-only guard; the false branch never runs in production builds.\n /* v8 ignore next */\n if (isDevMode()) validateEpsilon(epsilon);\n\n return { provide: MQ_BREAKPOINT_EPSILON, useValue: epsilon };\n}\n\n/**\n * Sets the app-wide value query signals report during server-side rendering,\n * where `matchMedia` is unavailable. A per-call `ssrValue` overrides this.\n *\n * @param value - The boolean returned by every signal on the server.\n * @returns An Angular {@link Provider}.\n *\n * @example\n * ```ts\n * provideSsrValue(true);\n * ```\n *\n * @category Providers\n */\nexport function provideSsrValue(value: boolean): Provider {\n return { provide: NGX_MQ_SSR_VALUE, useValue: value };\n}\n","/**\n * @packageDocumentation\n *\n * @document ../guides/getting-started.md\n * @document ../guides/ssr.md\n * @document ../guides/recipes.md\n */\n\nexport * from './lib/api';\nexport * from './lib/composition';\nexport * from './lib/tokens';\nexport * from './lib/providers';\nexport * from './lib/models';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["signal","createSignal"],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -190,6 +190,25 @@ declare function displayMode(value: DisplayModeOption, options?: CreateMediaQuer
|
|
|
190
190
|
* @category Media Features
|
|
191
191
|
*/
|
|
192
192
|
declare function reducedMotion(options?: CreateMediaQueryOptions): Signal<boolean>;
|
|
193
|
+
/**
|
|
194
|
+
* Tracks the user's contrast preference via `(prefers-contrast: ...)`.
|
|
195
|
+
*
|
|
196
|
+
* @param value - `'more'`, `'less'`, `'no-preference'`, or `'custom'`.
|
|
197
|
+
* @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
|
|
198
|
+
* @returns A `Signal<boolean>` that is `true` while the contrast preference matches `value`.
|
|
199
|
+
*
|
|
200
|
+
* @remarks Must be called within an Angular
|
|
201
|
+
* [injection context](https://angular.dev/guide/di/dependency-injection-context).
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```ts
|
|
205
|
+
* readonly wantsMoreContrast = prefersContrast('more');
|
|
206
|
+
* ```
|
|
207
|
+
*
|
|
208
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-contrast | MDN: prefers-contrast}
|
|
209
|
+
* @category Media Features
|
|
210
|
+
*/
|
|
211
|
+
declare function prefersContrast(value: 'more' | 'less' | 'no-preference' | 'custom', options?: CreateMediaQueryOptions): Signal<boolean>;
|
|
193
212
|
/**
|
|
194
213
|
* Tracks whether the **primary** input device can hover via `(hover: hover)`.
|
|
195
214
|
*
|
|
@@ -462,5 +481,5 @@ declare function provideBreakpointEpsilon(epsilon?: number): Provider;
|
|
|
462
481
|
*/
|
|
463
482
|
declare function provideSsrValue(value: boolean): Provider;
|
|
464
483
|
|
|
465
|
-
export { MQ_BREAKPOINTS, MQ_BREAKPOINT_EPSILON, NGX_MQ_SSR_VALUE, and, anyHover, anyPointer, between, colorGamut, colorScheme, displayMode, down, hover, matchMediaSignal, not, or, orientation, pointer, provideBootstrapBreakpoints, provideBreakpointEpsilon, provideBreakpoints, provideMaterialBreakpoints, provideSsrValue, provideTailwindBreakpoints, reducedMotion, up };
|
|
484
|
+
export { MQ_BREAKPOINTS, MQ_BREAKPOINT_EPSILON, NGX_MQ_SSR_VALUE, and, anyHover, anyPointer, between, colorGamut, colorScheme, displayMode, down, hover, matchMediaSignal, not, or, orientation, pointer, prefersContrast, provideBootstrapBreakpoints, provideBreakpointEpsilon, provideBreakpoints, provideMaterialBreakpoints, provideSsrValue, provideTailwindBreakpoints, reducedMotion, up };
|
|
466
485
|
export type { CreateMediaQueryOptions, DisplayModeOption, MqBreakpoints };
|