ngx-mq 2.11.3 → 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.
@@ -1,5 +1,4 @@
1
- import { InjectionToken, inject, isDevMode, signal, DestroyRef, assertInInjectionContext } from '@angular/core';
2
- import { createComputed, SIGNAL } from '@angular/core/primitives/signals';
1
+ import { InjectionToken, inject, isDevMode, signal, DestroyRef, computed, assertInInjectionContext } from '@angular/core';
3
2
 
4
3
  const TAILWIND_BREAKPOINTS = {
5
4
  sm: 640,
@@ -23,11 +22,29 @@ const MATERIAL_BREAKPOINTS = {
23
22
  };
24
23
  const DEFAULT_BREAKPOINT_EPSILON = 0.02;
25
24
 
25
+ /**
26
+ * Holds the active {@link MqBreakpoints} map. Has no default: configure it with
27
+ * {@link provideBreakpoints} or a preset. Inject it to read breakpoints directly.
28
+ *
29
+ * @category Injection Tokens
30
+ */
26
31
  const MQ_BREAKPOINTS = new InjectionToken('MQ_BREAKPOINTS');
32
+ /**
33
+ * Holds the epsilon used for exclusive upper bounds. Set it with
34
+ * {@link provideBreakpointEpsilon}; defaults to `0.02`.
35
+ *
36
+ * @category Injection Tokens
37
+ */
27
38
  const MQ_BREAKPOINT_EPSILON = new InjectionToken('MQ_BREAKPOINT_EPSILON', {
28
39
  providedIn: 'root',
29
40
  factory: () => DEFAULT_BREAKPOINT_EPSILON,
30
41
  });
42
+ /**
43
+ * Holds the value query signals report during SSR. Set it with
44
+ * {@link provideSsrValue}; defaults to `false`.
45
+ *
46
+ * @category Injection Tokens
47
+ */
31
48
  const NGX_MQ_SSR_VALUE = new InjectionToken('NGX_MQ_SSR_VALUE', {
32
49
  providedIn: 'root',
33
50
  factory: () => false,
@@ -54,18 +71,22 @@ function resolveBreakpoint(bp) {
54
71
  const breakpoints = assertBreakpointsProvided();
55
72
  return assertBreakpointExists(bp.trim(), breakpoints);
56
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
+ }
57
82
  function normalizeBreakpoints(bps) {
58
83
  const out = {};
59
84
  for (const [rawKey, value] of Object.entries(bps)) {
60
85
  const key = rawKey.trim();
61
- if (isDevMode()) {
62
- if (!Number.isFinite(value)) {
63
- throw new Error(`[ngx-mq] Breakpoint "${key}" must be a finite number, got ${value}.`);
64
- }
65
- if (value <= 0) {
66
- throw new Error(`[ngx-mq] Breakpoint "${key}" must be > 0, got ${value}.`);
67
- }
68
- }
86
+ // Dev-only guard; the false branch never runs in production builds.
87
+ /* v8 ignore next */
88
+ if (isDevMode())
89
+ validateBreakpointValue(key, value);
69
90
  out[key] = value;
70
91
  }
71
92
  return Object.freeze(out);
@@ -167,11 +188,7 @@ function createConsumer(query, options) {
167
188
  const defaultSsrValue = inject(NGX_MQ_SSR_VALUE);
168
189
  const effectiveSsrValue = options?.ssrValue ?? defaultSsrValue;
169
190
  const querySignal = retainUntilDestroy(query, effectiveSsrValue);
170
- const getter = createComputed(() => querySignal());
171
- if (isDevMode()) {
172
- getter[SIGNAL].debugName = options?.debugName;
173
- }
174
- return getter;
191
+ return computed(() => querySignal(), { debugName: options?.debugName });
175
192
  }
176
193
  function createConsumerLabel(descriptor) {
177
194
  return `[NgxMq Signal: ${descriptor}]`;
@@ -181,6 +198,29 @@ function normalizeQuery(value) {
181
198
  return value.trim().replace(/\s+/g, ' ').toLowerCase();
182
199
  }
183
200
 
201
+ /**
202
+ * Tracks whether the viewport width is **at or above** a breakpoint.
203
+ *
204
+ * Builds a `(min-width: <bp>px)` query from the value registered for `bp` via
205
+ * {@link provideBreakpoints} (or a preset like {@link provideTailwindBreakpoints}).
206
+ *
207
+ * @param bp - Name of a configured breakpoint, e.g. `'md'`.
208
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
209
+ * @returns A `Signal<boolean>` that is `true` while the viewport width is `>=` the breakpoint.
210
+ *
211
+ * @remarks Must be called within an Angular
212
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
213
+ *
214
+ * @example
215
+ * ```ts
216
+ * export class LayoutComponent {
217
+ * readonly isDesktop = up('lg');
218
+ * }
219
+ * ```
220
+ *
221
+ * @see {@link down} and {@link between} for the complementary ranges.
222
+ * @category Breakpoints
223
+ */
184
224
  function up(bp, options) {
185
225
  isDevMode() && assertInInjectionContext(up);
186
226
  const query = normalizeQuery(`(min-width: ${resolveBreakpoint(bp)}px)`);
@@ -188,6 +228,29 @@ function up(bp, options) {
188
228
  consumer.toString = () => createConsumerLabel(`up(${bp})`);
189
229
  return consumer;
190
230
  }
231
+ /**
232
+ * Tracks whether the viewport width is **below** a breakpoint.
233
+ *
234
+ * Builds a `(max-width: <bp - epsilon>px)` query. The upper bound is **exclusive**:
235
+ * a small epsilon is subtracted so `down('md')` and {@link up}`('md')` never overlap.
236
+ *
237
+ * @param bp - Name of a configured breakpoint, e.g. `'md'`.
238
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
239
+ * @returns A `Signal<boolean>` that is `true` while the viewport width is `<` the breakpoint.
240
+ *
241
+ * @remarks Must be called within an Angular
242
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * export class NavComponent {
247
+ * readonly isMobile = down('md');
248
+ * }
249
+ * ```
250
+ *
251
+ * @see {@link provideBreakpointEpsilon} to tune the exclusive-bound epsilon.
252
+ * @category Breakpoints
253
+ */
191
254
  function down(bp, options) {
192
255
  isDevMode() && assertInInjectionContext(down);
193
256
  const query = normalizeQuery(`(max-width: ${applyMaxEpsilon(resolveBreakpoint(bp))}px)`);
@@ -195,6 +258,29 @@ function down(bp, options) {
195
258
  consumer.toString = () => createConsumerLabel(`down(${bp})`);
196
259
  return consumer;
197
260
  }
261
+ /**
262
+ * Tracks whether the viewport width falls within the range `[minBp, maxBp)`.
263
+ *
264
+ * Combines `min-width` and `max-width` into a single query. The lower bound is
265
+ * inclusive and the upper bound is **exclusive** (epsilon is subtracted from `maxBp`).
266
+ *
267
+ * @param minBp - Name of the lower (inclusive) breakpoint.
268
+ * @param maxBp - Name of the upper (exclusive) breakpoint.
269
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
270
+ * @returns A `Signal<boolean>` that is `true` while the width is in `[minBp, maxBp)`.
271
+ *
272
+ * @remarks Must be called within an Angular
273
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
274
+ *
275
+ * @example
276
+ * ```ts
277
+ * export class GridComponent {
278
+ * readonly isTablet = between('md', 'lg');
279
+ * }
280
+ * ```
281
+ *
282
+ * @category Breakpoints
283
+ */
198
284
  function between(minBp, maxBp, options) {
199
285
  isDevMode() && assertInInjectionContext(between);
200
286
  const minPx = resolveBreakpoint(minBp);
@@ -204,6 +290,24 @@ function between(minBp, maxBp, options) {
204
290
  consumer.toString = () => createConsumerLabel(`between(${minBp}, ${maxBp})`);
205
291
  return consumer;
206
292
  }
293
+ /**
294
+ * Tracks the screen orientation via the `(orientation: ...)` media feature.
295
+ *
296
+ * @param value - `'portrait'` (height `>=` width) or `'landscape'` (width `>` height).
297
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
298
+ * @returns A `Signal<boolean>` that is `true` while the orientation matches `value`.
299
+ *
300
+ * @remarks Must be called within an Angular
301
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
302
+ *
303
+ * @example
304
+ * ```ts
305
+ * readonly isLandscape = orientation('landscape');
306
+ * ```
307
+ *
308
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/orientation | MDN: orientation}
309
+ * @category Media Features
310
+ */
207
311
  function orientation(value, options) {
208
312
  isDevMode() && assertInInjectionContext(orientation);
209
313
  const query = normalizeQuery(`(orientation: ${value})`);
@@ -211,6 +315,24 @@ function orientation(value, options) {
211
315
  consumer.toString = () => createConsumerLabel(`orientation(${value})`);
212
316
  return consumer;
213
317
  }
318
+ /**
319
+ * Tracks the user's preferred color scheme via `(prefers-color-scheme: ...)`.
320
+ *
321
+ * @param value - `'light'` or `'dark'`.
322
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
323
+ * @returns A `Signal<boolean>` that is `true` while the system scheme matches `value`.
324
+ *
325
+ * @remarks Must be called within an Angular
326
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
327
+ *
328
+ * @example
329
+ * ```ts
330
+ * readonly isDark = colorScheme('dark');
331
+ * ```
332
+ *
333
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme | MDN: prefers-color-scheme}
334
+ * @category Media Features
335
+ */
214
336
  function colorScheme(value, options) {
215
337
  isDevMode() && assertInInjectionContext(colorScheme);
216
338
  const query = normalizeQuery(`(prefers-color-scheme: ${value})`);
@@ -218,6 +340,25 @@ function colorScheme(value, options) {
218
340
  consumer.toString = () => createConsumerLabel(`colorScheme(${value})`);
219
341
  return consumer;
220
342
  }
343
+ /**
344
+ * Tracks how the app is being displayed via the `(display-mode: ...)` feature,
345
+ * useful for detecting installed PWAs.
346
+ *
347
+ * @param value - One of {@link DisplayModeOption}, e.g. `'standalone'`.
348
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
349
+ * @returns A `Signal<boolean>` that is `true` while the display mode matches `value`.
350
+ *
351
+ * @remarks Must be called within an Angular
352
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
353
+ *
354
+ * @example
355
+ * ```ts
356
+ * readonly isInstalledPwa = displayMode('standalone');
357
+ * ```
358
+ *
359
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode | MDN: display-mode}
360
+ * @category Media Features
361
+ */
221
362
  function displayMode(value, options) {
222
363
  isDevMode() && assertInInjectionContext(displayMode);
223
364
  const query = normalizeQuery(`(display-mode: ${value})`);
@@ -225,6 +366,24 @@ function displayMode(value, options) {
225
366
  consumer.toString = () => createConsumerLabel(`displayMode(${value})`);
226
367
  return consumer;
227
368
  }
369
+ /**
370
+ * Tracks whether the user has requested reduced motion via
371
+ * `(prefers-reduced-motion: reduce)`.
372
+ *
373
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
374
+ * @returns A `Signal<boolean>` that is `true` while reduced motion is preferred.
375
+ *
376
+ * @remarks Must be called within an Angular
377
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
378
+ *
379
+ * @example
380
+ * ```ts
381
+ * readonly reduceMotion = reducedMotion();
382
+ * ```
383
+ *
384
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion | MDN: prefers-reduced-motion}
385
+ * @category Media Features
386
+ */
228
387
  function reducedMotion(options) {
229
388
  isDevMode() && assertInInjectionContext(reducedMotion);
230
389
  const query = normalizeQuery('(prefers-reduced-motion: reduce)');
@@ -232,6 +391,49 @@ function reducedMotion(options) {
232
391
  consumer.toString = () => createConsumerLabel('reducedMotion');
233
392
  return consumer;
234
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
+ }
419
+ /**
420
+ * Tracks whether the **primary** input device can hover via `(hover: hover)`.
421
+ *
422
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
423
+ * @returns A `Signal<boolean>` that is `true` while the primary pointer supports hover.
424
+ *
425
+ * @remarks Must be called within an Angular
426
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
427
+ *
428
+ * @example
429
+ * ```ts
430
+ * readonly canHover = hover();
431
+ * ```
432
+ *
433
+ * @see {@link anyHover} to test **any** available input device.
434
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover | MDN: hover}
435
+ * @category Media Features
436
+ */
235
437
  function hover(options) {
236
438
  isDevMode() && assertInInjectionContext(hover);
237
439
  const query = normalizeQuery('(hover: hover)');
@@ -239,6 +441,24 @@ function hover(options) {
239
441
  consumer.toString = () => createConsumerLabel('hover');
240
442
  return consumer;
241
443
  }
444
+ /**
445
+ * Tracks whether **any** available input device can hover via `(any-hover: hover)`.
446
+ *
447
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
448
+ * @returns A `Signal<boolean>` that is `true` while at least one pointer supports hover.
449
+ *
450
+ * @remarks Must be called within an Angular
451
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
452
+ *
453
+ * @example
454
+ * ```ts
455
+ * readonly anyCanHover = anyHover();
456
+ * ```
457
+ *
458
+ * @see {@link hover} to test only the primary input device.
459
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/any-hover | MDN: any-hover}
460
+ * @category Media Features
461
+ */
242
462
  function anyHover(options) {
243
463
  isDevMode() && assertInInjectionContext(anyHover);
244
464
  const query = normalizeQuery('(any-hover: hover)');
@@ -246,6 +466,25 @@ function anyHover(options) {
246
466
  consumer.toString = () => createConsumerLabel('anyHover');
247
467
  return consumer;
248
468
  }
469
+ /**
470
+ * Tracks the accuracy of the **primary** pointer via `(pointer: ...)`.
471
+ *
472
+ * @param value - `'fine'` (mouse/stylus), `'coarse'` (touch), or `'none'`.
473
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
474
+ * @returns A `Signal<boolean>` that is `true` while the primary pointer matches `value`.
475
+ *
476
+ * @remarks Must be called within an Angular
477
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
478
+ *
479
+ * @example
480
+ * ```ts
481
+ * readonly isTouch = pointer('coarse');
482
+ * ```
483
+ *
484
+ * @see {@link anyPointer} to test **any** available input device.
485
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer | MDN: pointer}
486
+ * @category Media Features
487
+ */
249
488
  function pointer(value, options) {
250
489
  isDevMode() && assertInInjectionContext(pointer);
251
490
  const query = normalizeQuery(`(pointer: ${value})`);
@@ -253,6 +492,25 @@ function pointer(value, options) {
253
492
  consumer.toString = () => createConsumerLabel(`pointer(${value})`);
254
493
  return consumer;
255
494
  }
495
+ /**
496
+ * Tracks the accuracy of **any** available pointer via `(any-pointer: ...)`.
497
+ *
498
+ * @param value - `'fine'` (mouse/stylus), `'coarse'` (touch), or `'none'`.
499
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
500
+ * @returns A `Signal<boolean>` that is `true` while at least one pointer matches `value`.
501
+ *
502
+ * @remarks Must be called within an Angular
503
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
504
+ *
505
+ * @example
506
+ * ```ts
507
+ * readonly hasFinePointer = anyPointer('fine');
508
+ * ```
509
+ *
510
+ * @see {@link pointer} to test only the primary input device.
511
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/any-pointer | MDN: any-pointer}
512
+ * @category Media Features
513
+ */
256
514
  function anyPointer(value, options) {
257
515
  isDevMode() && assertInInjectionContext(anyPointer);
258
516
  const query = normalizeQuery(`(any-pointer: ${value})`);
@@ -260,6 +518,24 @@ function anyPointer(value, options) {
260
518
  consumer.toString = () => createConsumerLabel(`anyPointer(${value})`);
261
519
  return consumer;
262
520
  }
521
+ /**
522
+ * Tracks the approximate color gamut of the display via `(color-gamut: ...)`.
523
+ *
524
+ * @param value - `'srgb'`, `'p3'`, or `'rec2020'` (ordered by increasing range).
525
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
526
+ * @returns A `Signal<boolean>` that is `true` while the display covers `value`.
527
+ *
528
+ * @remarks Must be called within an Angular
529
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
530
+ *
531
+ * @example
532
+ * ```ts
533
+ * readonly isWideGamut = colorGamut('p3');
534
+ * ```
535
+ *
536
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@media/color-gamut | MDN: color-gamut}
537
+ * @category Media Features
538
+ */
263
539
  function colorGamut(value, options) {
264
540
  isDevMode() && assertInInjectionContext(colorGamut);
265
541
  const query = normalizeQuery(`(color-gamut: ${value})`);
@@ -267,6 +543,27 @@ function colorGamut(value, options) {
267
543
  consumer.toString = () => createConsumerLabel(`colorGamut(${value})`);
268
544
  return consumer;
269
545
  }
546
+ /**
547
+ * Tracks an arbitrary, raw CSS media query.
548
+ *
549
+ * Use this escape hatch for any feature not covered by the dedicated helpers.
550
+ * The query is normalized (trimmed, collapsed whitespace, lower-cased) before use.
551
+ *
552
+ * @param query - A valid CSS media query, e.g. `'(min-resolution: 2dppx)'`.
553
+ * @param options - Optional per-call settings ({@link CreateMediaQueryOptions}).
554
+ * @returns A `Signal<boolean>` that reflects the live result of the query.
555
+ *
556
+ * @remarks Must be called within an Angular
557
+ * [injection context](https://angular.dev/guide/di/dependency-injection-context).
558
+ *
559
+ * @example
560
+ * ```ts
561
+ * readonly isRetina = matchMediaSignal('(min-resolution: 2dppx)');
562
+ * ```
563
+ *
564
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries | MDN: CSS media queries}
565
+ * @category Custom Queries
566
+ */
270
567
  function matchMediaSignal(query, options) {
271
568
  isDevMode() && assertInInjectionContext(matchMediaSignal);
272
569
  const media = normalizeQuery(query);
@@ -275,30 +572,182 @@ function matchMediaSignal(query, options) {
275
572
  return consumer;
276
573
  }
277
574
 
575
+ const LABEL_RE = /^\[NgxMq Signal: (.+)]$/;
576
+ /** Extracts the inner descriptor from an ngx-mq signal label, or falls back to its raw toString(). */
577
+ function describe(condition) {
578
+ const raw = condition.toString();
579
+ const match = LABEL_RE.exec(raw);
580
+ return match ? match[1] : raw;
581
+ }
582
+ /**
583
+ * Combines boolean signals with logical **AND**.
584
+ *
585
+ * Composition happens at the signal level, so the underlying media-query
586
+ * listeners stay shared and are still cleaned up automatically.
587
+ *
588
+ * @param conditions - Boolean signals to combine. An empty call returns a
589
+ * signal that is always `true` (vacuous truth).
590
+ * @returns A `Signal<boolean>` that is `true` only when **every** condition is `true`.
591
+ *
592
+ * @example
593
+ * ```ts
594
+ * readonly isLandscapeDesktop = and(up('lg'), orientation('landscape'), hover());
595
+ * ```
596
+ *
597
+ * @see {@link or} and {@link not}.
598
+ * @category Combining Signals
599
+ */
600
+ function and(...conditions) {
601
+ const result = computed(() => conditions.every((condition) => condition()), ...(ngDevMode ? [{ debugName: "result" }] : []));
602
+ result.toString = () => createConsumerLabel(`and(${conditions.map(describe).join(', ')})`);
603
+ return result;
604
+ }
605
+ /**
606
+ * Combines boolean signals with logical **OR**.
607
+ *
608
+ * Composition happens at the signal level, so the underlying media-query
609
+ * listeners stay shared and are still cleaned up automatically.
610
+ *
611
+ * @param conditions - Boolean signals to combine. An empty call returns a
612
+ * signal that is always `false`.
613
+ * @returns A `Signal<boolean>` that is `true` when **at least one** condition is `true`.
614
+ *
615
+ * @example
616
+ * ```ts
617
+ * readonly prefersSimpleUi = or(down('md'), reducedMotion());
618
+ * ```
619
+ *
620
+ * @see {@link and} and {@link not}.
621
+ * @category Combining Signals
622
+ */
623
+ function or(...conditions) {
624
+ const result = computed(() => conditions.some((condition) => condition()), ...(ngDevMode ? [{ debugName: "result" }] : []));
625
+ result.toString = () => createConsumerLabel(`or(${conditions.map(describe).join(', ')})`);
626
+ return result;
627
+ }
628
+ /**
629
+ * Negates a boolean signal.
630
+ *
631
+ * Useful for features that have no direct inverse helper, such as
632
+ * "devices without hover": `not(hover())`.
633
+ *
634
+ * @param condition - The boolean signal to invert.
635
+ * @returns A `Signal<boolean>` that is `true` when `condition` is `false`, and vice versa.
636
+ *
637
+ * @example
638
+ * ```ts
639
+ * readonly isTouchLike = not(hover());
640
+ * ```
641
+ *
642
+ * @see {@link and} and {@link or}.
643
+ * @category Combining Signals
644
+ */
645
+ function not(condition) {
646
+ const result = computed(() => !condition(), ...(ngDevMode ? [{ debugName: "result" }] : []));
647
+ result.toString = () => createConsumerLabel(`not(${describe(condition)})`);
648
+ return result;
649
+ }
650
+
651
+ /**
652
+ * Registers a custom breakpoint map, enabling {@link up}, {@link down} and {@link between}.
653
+ *
654
+ * Provide once at bootstrap, or at any injector level to scope/override breakpoints.
655
+ *
656
+ * @param bps - A {@link MqBreakpoints} map of names to minimum widths in pixels.
657
+ * @returns An Angular {@link Provider}.
658
+ *
659
+ * @example
660
+ * ```ts
661
+ * bootstrapApplication(AppComponent, {
662
+ * providers: [provideBreakpoints({ sm: 640, md: 768, lg: 1024 })],
663
+ * });
664
+ * ```
665
+ *
666
+ * @category Providers
667
+ */
278
668
  function provideBreakpoints(bps) {
279
669
  return { provide: MQ_BREAKPOINTS, useValue: normalizeBreakpoints(bps) };
280
670
  }
671
+ /**
672
+ * Registers the default Tailwind CSS breakpoints:
673
+ * `sm: 640, md: 768, lg: 1024, xl: 1280, 2xl: 1536`.
674
+ *
675
+ * @returns An Angular {@link Provider}.
676
+ * @category Providers
677
+ */
281
678
  function provideTailwindBreakpoints() {
282
679
  return provideBreakpoints(TAILWIND_BREAKPOINTS);
283
680
  }
681
+ /**
682
+ * Registers the default Bootstrap breakpoints:
683
+ * `sm: 576, md: 768, lg: 992, xl: 1200, xxl: 1400`.
684
+ *
685
+ * @returns An Angular {@link Provider}.
686
+ * @category Providers
687
+ */
284
688
  function provideBootstrapBreakpoints() {
285
689
  return provideBreakpoints(BOOTSTRAP_BREAKPOINTS);
286
690
  }
691
+ /**
692
+ * Registers the default Material 2 breakpoints:
693
+ * `sm: 600, md: 905, lg: 1240, xl: 1440`.
694
+ *
695
+ * @returns An Angular {@link Provider}.
696
+ * @category Providers
697
+ */
287
698
  function provideMaterialBreakpoints() {
288
699
  return provideBreakpoints(MATERIAL_BREAKPOINTS);
289
700
  }
701
+ /**
702
+ * Sets the epsilon subtracted from exclusive upper bounds in {@link down} and
703
+ * {@link between}, preventing adjacent ranges from overlapping.
704
+ *
705
+ * @param epsilon - A value in the range `(0, 1]`. Defaults to `0.02`.
706
+ * @returns An Angular {@link Provider}.
707
+ *
708
+ * @example
709
+ * ```ts
710
+ * provideBreakpointEpsilon(0.02);
711
+ * ```
712
+ *
713
+ * @category Providers
714
+ */
290
715
  function provideBreakpointEpsilon(epsilon = DEFAULT_BREAKPOINT_EPSILON) {
716
+ // Dev-only guard; the false branch never runs in production builds.
717
+ /* v8 ignore next */
291
718
  if (isDevMode())
292
719
  validateEpsilon(epsilon);
293
720
  return { provide: MQ_BREAKPOINT_EPSILON, useValue: epsilon };
294
721
  }
722
+ /**
723
+ * Sets the app-wide value query signals report during server-side rendering,
724
+ * where `matchMedia` is unavailable. A per-call `ssrValue` overrides this.
725
+ *
726
+ * @param value - The boolean returned by every signal on the server.
727
+ * @returns An Angular {@link Provider}.
728
+ *
729
+ * @example
730
+ * ```ts
731
+ * provideSsrValue(true);
732
+ * ```
733
+ *
734
+ * @category Providers
735
+ */
295
736
  function provideSsrValue(value) {
296
737
  return { provide: NGX_MQ_SSR_VALUE, useValue: value };
297
738
  }
298
739
 
740
+ /**
741
+ * @packageDocumentation
742
+ *
743
+ * @document ../guides/getting-started.md
744
+ * @document ../guides/ssr.md
745
+ * @document ../guides/recipes.md
746
+ */
747
+
299
748
  /**
300
749
  * Generated bundle index. Do not edit.
301
750
  */
302
751
 
303
- export { MQ_BREAKPOINTS, MQ_BREAKPOINT_EPSILON, NGX_MQ_SSR_VALUE, anyHover, anyPointer, between, colorGamut, colorScheme, displayMode, down, hover, matchMediaSignal, 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 };
304
753
  //# sourceMappingURL=ngx-mq.mjs.map