Skip to content

Next (angular 19) #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/demo/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,10 @@ module.exports = [
...config.rules,
},
})),
{
files: ['**/*.ts'],
rules: {
'@angular-eslint/prefer-standalone': 'off',
},
},
];
1 change: 0 additions & 1 deletion apps/demo/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Installation } from './components/installation';
import { Usage } from './components/usage';

@Component({
standalone: true,
imports: [Header, Installation, Demo, Usage, Footer],
selector: 'demo-root',
template: `
Expand Down
1 change: 0 additions & 1 deletion apps/demo/src/app/components/breakpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ChangeDetectionStrategy, Component, input } from '@angular/core';

@Component({
selector: 'demo-breakpoint',
standalone: true,
template: `
<p>
{{ name() }}:
Expand Down
1 change: 0 additions & 1 deletion apps/demo/src/app/components/code-block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ hljs.registerLanguage('xml', xml);

@Component({
selector: 'demo-code-block',
standalone: true,
template: `
<div class="group relative">
<button
Expand Down
5 changes: 2 additions & 3 deletions apps/demo/src/app/components/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import { JsonPipe } from '@angular/common';
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import {
breakpointsTailwind,
observeBreakpoints,
injectBreakpoints,
} from 'ngx-breakpoint-observer';
import { Breakpoint } from './breakpoint';

@Component({
selector: 'demo-demo',
standalone: true,
imports: [Breakpoint, JsonPipe],
template: `
<h2>Demo</h2>
Expand All @@ -32,7 +31,7 @@ import { Breakpoint } from './breakpoint';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class Demo {
breakpoints = observeBreakpoints(breakpointsTailwind);
breakpoints = injectBreakpoints(breakpointsTailwind);

reactiveStuff = signal<keyof typeof breakpointsTailwind>('sm');
isGreaterThanSignal = this.breakpoints.greaterOrEqual(this.reactiveStuff);
Expand Down
1 change: 0 additions & 1 deletion apps/demo/src/app/components/footer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Component } from '@angular/core';

@Component({
selector: 'demo-footer',
standalone: true,
template: `
<footer class="border-t py-4">
<p>Made with ❤️ by Tutkli.</p>
Expand Down
1 change: 0 additions & 1 deletion apps/demo/src/app/components/github-icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
selector: 'demo-github-icon',
standalone: true,
template: `
<svg
role="img"
Expand Down
1 change: 0 additions & 1 deletion apps/demo/src/app/components/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { GitHubIcon } from './github-icon';

@Component({
selector: 'demo-header',
standalone: true,
imports: [GitHubIcon],
host: {
class: 'flex flex-col w-full justify-center gap-5',
Expand Down
1 change: 0 additions & 1 deletion apps/demo/src/app/components/installation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { CodeBlock } from './code-block';

@Component({
selector: 'demo-installation',
standalone: true,
imports: [CodeBlock],
template: `
<h2>Installation</h2>
Expand Down
1 change: 0 additions & 1 deletion apps/demo/src/app/components/usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { CodeBlock } from './code-block';

@Component({
selector: 'demo-usage',
standalone: true,
imports: [CodeBlock],
template: `
<h2>Usage</h2>
Expand Down
4 changes: 2 additions & 2 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module.exports = [
},
...compat.config({ extends: ['plugin:@nx/typescript'] }).map(config => ({
...config,
files: ['**/*.ts', '**/*.tsx'],
files: ['**/*.ts', '**/*.tsx', '**/*.cts', '**/*.mts'],
rules: {
...config.rules,
'@typescript-eslint/no-extra-semi': 'error',
Expand All @@ -38,7 +38,7 @@ module.exports = [
})),
...compat.config({ extends: ['plugin:@nx/javascript'] }).map(config => ({
...config,
files: ['**/*.js', '**/*.jsx'],
files: ['**/*.js', '**/*.jsx', '**/*.cjs', '**/*.mjs'],
rules: {
...config.rules,
'@typescript-eslint/no-extra-semi': 'error',
Expand Down
8 changes: 4 additions & 4 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getJestProjects } from '@nx/jest';
import { getJestProjectsAsync } from '@nx/jest';

export default {
projects: getJestProjects(),
};
export default async () => ({
projects: await getJestProjectsAsync(),
});
6 changes: 6 additions & 0 deletions libs/ngx-breakpoint-observer/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,10 @@ module.exports = [
'@nx/dependency-checks': 'error',
},
})),
{
files: ['**/*.ts'],
rules: {
'@angular-eslint/prefer-standalone': 'off',
},
},
];
2 changes: 1 addition & 1 deletion libs/ngx-breakpoint-observer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-breakpoint-observer",
"version": "2.0.0",
"version": "3.0.0",
"description": "Angular reactive breakpoint observer based on Signals.",
"bugs": {
"url": "https://github.com/tutkli/ngx-breakpoint-observer/issues"
Expand Down
2 changes: 2 additions & 0 deletions libs/ngx-breakpoint-observer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*/

export * from './lib/breakpoints';
export * from './lib/inject-breakpoints';
export * from './lib/inject-media-query';
export * from './lib/observe-breakpoints';
export * from './lib/observe-media-query';
export * from './lib/types';
122 changes: 122 additions & 0 deletions libs/ngx-breakpoint-observer/src/lib/inject-breakpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { computed, Signal } from '@angular/core';
import { injectMediaQuery } from './inject-media-query';
import {
Breakpoints,
MaybeSignalOrGetter,
ObserveBreakpointsOptions,
} from './types';
import { defaultWindow, increaseWithUnit, toValue } from './utils';

/**
* Reactive viewport breakpoints.
*
* This function provides a set of reactive utilities to handle viewport breakpoints.
* It includes shortcut methods like `greaterOrEqual`, `smallerOrEqual`, `between`, etc.
*
* @param breakpoints A map of breakpoint names and their corresponding values.
* @param options Configuration options such as window and strategy.
* @returns An object with breakpoint utilities and shortcut methods.
*/
export function injectBreakpoints<K extends string>(
breakpoints: Breakpoints<K>,
options: ObserveBreakpointsOptions = {}
) {
const { window = defaultWindow, strategy = 'min-width' } = options;

function getValue(k: MaybeSignalOrGetter<K>, delta?: number): string {
let v = breakpoints[toValue(k)];

if (delta !== null && delta !== undefined) {
v = increaseWithUnit(v, delta);
}

if (typeof v === 'number') {
v = `${v}px`;
}

return v;
}

function match(query: string): boolean {
if (!window) return false;

return window.matchMedia(query).matches;
}

const greaterOrEqual = (k: MaybeSignalOrGetter<K>): Signal<boolean> => {
return injectMediaQuery(() => `(min-width: ${getValue(k)})`, options);
};

const smallerOrEqual = (k: MaybeSignalOrGetter<K>): Signal<boolean> => {
return injectMediaQuery(() => `(max-width: ${getValue(k)})`, options);
};

function current() {
const points = Object.keys(breakpoints).map(
i => [i, greaterOrEqual(i as K)] as const
);
return computed(() => points.filter(([, v]) => v()).map(([k]) => k));
}

const shortcutMethods = Object.keys(breakpoints).reduce((shortcuts, k) => {
Object.defineProperty(shortcuts, k, {
get: () =>
strategy === 'min-width'
? greaterOrEqual(k as K)
: smallerOrEqual(k as K),
enumerable: true,
configurable: true,
});
return shortcuts;
}, {} as Record<K, Signal<boolean>>);

return Object.assign(shortcutMethods, {
greaterOrEqual,
smallerOrEqual,
greater(k: MaybeSignalOrGetter<K>) {
return injectMediaQuery(
() => `(min-width: ${getValue(k, 0.1)})`,
options
);
},
smaller(k: MaybeSignalOrGetter<K>) {
return injectMediaQuery(
() => `(max-width: ${getValue(k, -0.1)})`,
options
);
},
between(a: MaybeSignalOrGetter<K>, b: MaybeSignalOrGetter<K>) {
return injectMediaQuery(
() =>
`(min-width: ${getValue(a)}) and (max-width: ${getValue(b, -0.1)})`,
options
);
},
isGreater(k: MaybeSignalOrGetter<K>) {
return match(`(min-width: ${getValue(k, 0.1)})`);
},
isGreaterOrEqual(k: MaybeSignalOrGetter<K>) {
return match(`(min-width: ${getValue(k)})`);
},
isSmaller(k: MaybeSignalOrGetter<K>) {
return match(`(max-width: ${getValue(k, -0.1)})`);
},
isSmallerOrEqual(k: MaybeSignalOrGetter<K>) {
return match(`(max-width: ${getValue(k)})`);
},
isInBetween(a: MaybeSignalOrGetter<K>, b: MaybeSignalOrGetter<K>) {
return match(
`(min-width: ${getValue(a)}) and (max-width: ${getValue(b, -0.1)})`
);
},
current,
active() {
const breakpoints = current();
return computed(() =>
breakpoints().length === 0
? ''
: breakpoints()[breakpoints().length - 1]
);
},
});
}
47 changes: 47 additions & 0 deletions libs/ngx-breakpoint-observer/src/lib/inject-media-query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { DestroyRef, inject, signal, Signal } from '@angular/core';
import { ConfigurableWindow, MaybeSignalOrGetter } from './types';
import { defaultWindow, toValue } from './utils';

/**
* Reactive Media Query.
*
* @param query Media query as a signal or getter or string.
* @param options Configuration options for window.
* @returns A read-only signal indicating whether the media query matches.
*/
export function injectMediaQuery(
query: MaybeSignalOrGetter<string>,
options: ConfigurableWindow = {}
): Signal<boolean> {
const destroyRef = inject(DestroyRef);
const { window = defaultWindow } = options;
const isSupported =
window && 'matchMedia' in window && typeof window.matchMedia === 'function';

let mediaQuery: MediaQueryList | undefined;
const matches = signal(false);

const handler = (event: MediaQueryListEvent) => {
matches.set(event.matches);
};

if (isSupported) {
mediaQuery = window.matchMedia(toValue(query));
matches.set(mediaQuery.matches);
if ('addEventListener' in mediaQuery)
mediaQuery.addEventListener('change', handler);
// @ts-expect-error deprecated API
else mediaQuery.addListener(handler);
}

destroyRef.onDestroy(() => {
if (!mediaQuery) return;

if ('removeEventListener' in mediaQuery)
mediaQuery.removeEventListener('change', handler);
// @ts-expect-error deprecated API
else mediaQuery.removeListener(handler);
});

return matches.asReadonly();
}
6 changes: 5 additions & 1 deletion libs/ngx-breakpoint-observer/src/lib/observe-breakpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import {
import { defaultWindow, increaseWithUnit, toValue } from './utils';

/**
* Reactive viewport breakpoints
* **@deprecated** Use `injectBreakpoints` instead.
*
* This function will be removed in version `4.0.0`.
*
* Reactive viewport breakpoints.
*
* @param breakpoints
* @param options
Expand Down
4 changes: 4 additions & 0 deletions libs/ngx-breakpoint-observer/src/lib/observe-media-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { ConfigurableWindow, MaybeSignalOrGetter } from './types';
import { defaultWindow, toValue } from './utils';

/**
* **@deprecated** Use `injectMediaQuery` instead.
*
* This function will be removed in version `4.0.0`.
*
* Reactive Media Query.
*
* @param query
Expand Down
3 changes: 2 additions & 1 deletion nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@
}
},
"useInferencePlugins": false,
"defaultBase": "master"
"defaultBase": "master",
"useLegacyCache": true
}
Loading
Loading