Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit 73323b4

Browse files
committed
rfc: new layout system
1 parent 6c143f0 commit 73323b4

40 files changed

+2774
-680
lines changed

package.json

+14-14
Original file line numberDiff line numberDiff line change
@@ -28,29 +28,29 @@
2828
"postinstall": "ngcc --properties es2015 browser module main --create-ivy-entry-points"
2929
},
3030
"version": "9.0.0-beta.29",
31-
"requiredAngularVersion": ">=9.0.0-rc.11",
31+
"requiredAngularVersion": ">=9.0.0",
3232
"dependencies": {
33-
"@angular/cdk": "^9.0.0-rc.8",
34-
"@angular/common": "^9.0.0-rc.11",
35-
"@angular/compiler": "^9.0.0-rc.11",
36-
"@angular/core": "^9.0.0-rc.11",
37-
"@angular/platform-browser": "^9.0.0-rc.11",
33+
"@angular/cdk": "^9.0.0",
34+
"@angular/common": "^9.0.0",
35+
"@angular/compiler": "^9.0.0",
36+
"@angular/core": "^9.0.0",
37+
"@angular/platform-browser": "^9.0.0",
3838
"core-js": "^2.5.7",
3939
"karma-parallel": "^0.3.1",
4040
"rxjs": "^6.5.1",
4141
"systemjs": "0.19.43",
42-
"tsickle": "^0.37.1",
42+
"tsickle": "^0.38.0",
4343
"tslib": "^1.9.3",
4444
"zone.js": "~0.10.2"
4545
},
4646
"devDependencies": {
47-
"@angular/animations": "^9.0.0-rc.11",
48-
"@angular/compiler-cli": "^9.0.0-rc.11",
49-
"@angular/forms": "^9.0.0-rc.11",
50-
"@angular/material": "^9.0.0-rc.8",
51-
"@angular/platform-browser-dynamic": "^9.0.0-rc.11",
52-
"@angular/platform-server": "^9.0.0-rc.11",
53-
"@angular/router": "^9.0.0-rc.11",
47+
"@angular/animations": "^9.0.0",
48+
"@angular/compiler-cli": "^9.0.0",
49+
"@angular/forms": "^9.0.0",
50+
"@angular/material": "^9.0.0",
51+
"@angular/platform-browser-dynamic": "^9.0.0",
52+
"@angular/platform-server": "^9.0.0",
53+
"@angular/router": "^9.0.0",
5454
"@firebase/app-types": "^0.3.2",
5555
"@types/chalk": "^0.4.31",
5656
"@types/fs-extra": "^4.0.5",

src/lib/uni/README.md

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
The `uni` entrypoint is a completely new approach to the Layout library. The emphasis here
2+
is on simplicity, with as little defined in the library as possible. The goal is to create
3+
a utility around the hardest part of layout management: creating and defining interchangeable
4+
builders and coordinating that with the media query system in the browser.
5+
6+
This is a backwards-incompatible approach to the current version of Angular Flex Layout, but
7+
we believe that this approach is more ergonomic in nature, and is the right way of doing things
8+
moving forward. That being said, this is completely opt-in, with no actual plans to transition
9+
anywhere in the near- or long-term.
10+
11+
To use this is quite simple:
12+
13+
### Step 1: Import the new module
14+
```ts
15+
// app.module.ts
16+
17+
@NgModule({
18+
imports: [UnifiedModule.withDefaults()] // brings in default tags and breakpoints
19+
})
20+
export class AppModule {}
21+
```
22+
23+
### Step 2: Use the new syntax
24+
```html
25+
<div ngl flexAlign="start">
26+
<bp tag="xs" flexAlign="end"></bp>
27+
<bp tag="md" flexAlign="center"></bp>
28+
</div>
29+
```
30+
31+
Here, `ngl` stands for "Angular (ng) Layout (l)". The `bp` elements are optional if
32+
you don't plan to use breakpoints in your template. Conceptually, it's cleaner than
33+
cramming all of the breakpoints on one root element, and the `bp` elements don't
34+
actually render in the template anyway.
35+
36+
We've removed the `fx` and `gd` prefixes, since now we can rely on attributes that
37+
are only applicable on the `bp` and root `ngl` elements.
38+
39+
Again, our goal here is simplicity. The most basic usage could be construed as the
40+
following:
41+
42+
```html
43+
<div ngl flex></div>
44+
```
45+
46+
This roughly corresponds to the old syntax for accomplishing the same:
47+
48+
```html
49+
<div fxFlex></div>
50+
```
51+
52+
While users who don't use many attributes per directive may not see a difference,
53+
it will become quite apparent to those who use many, or as you scale.
54+
55+
This is only a proposal, and all feedback is welcome.

src/lib/uni/index.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
export * from './public-api';

src/lib/uni/module.ts

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import {ModuleWithProviders, NgModule} from '@angular/core';
9+
10+
import {BreakpointDirective, UnifiedDirective} from './src/unified';
11+
import {FLEX_PROVIDER, GRID_PROVIDER, TAGS_PROVIDER} from './src/tags/tags';
12+
import {BREAKPOINTS_PROVIDER} from './src/breakpoint';
13+
14+
15+
@NgModule({
16+
declarations: [UnifiedDirective, BreakpointDirective],
17+
exports: [UnifiedDirective, BreakpointDirective]
18+
})
19+
export class UnifiedModule {
20+
static withDefaults(withDefaultBp: boolean = true): ModuleWithProviders<UnifiedModule> {
21+
return {
22+
ngModule: UnifiedModule,
23+
providers: withDefaultBp ? [
24+
TAGS_PROVIDER,
25+
BREAKPOINTS_PROVIDER,
26+
] : [TAGS_PROVIDER],
27+
};
28+
}
29+
30+
static withFlex(withDefaultBp: boolean = true): ModuleWithProviders<UnifiedModule> {
31+
return {
32+
ngModule: UnifiedModule,
33+
providers: withDefaultBp ? [
34+
FLEX_PROVIDER,
35+
BREAKPOINTS_PROVIDER
36+
] : [FLEX_PROVIDER]
37+
};
38+
}
39+
40+
static withGrid(withDefaultBp: boolean = true): ModuleWithProviders<UnifiedModule> {
41+
return {
42+
ngModule: UnifiedModule,
43+
providers: withDefaultBp ? [
44+
GRID_PROVIDER,
45+
BREAKPOINTS_PROVIDER
46+
] : [GRID_PROVIDER]
47+
};
48+
}
49+
}

src/lib/uni/public-api.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
export * from './src/uni';
10+
export * from './module';

src/lib/uni/src/breakpoint.ts

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import {inject, InjectionToken} from '@angular/core';
9+
10+
11+
/**
12+
* A breakpoint is a wrapper interface around the browser's mediaQuery,
13+
* which is a condition string used for matching based on browser window
14+
* parameters. Here, a breakpoint has a shortcut name, e.g. 'xs', the
15+
* corresponding mediaQuery, and a priority in case the mediaQuery overlaps
16+
* with other registered breakpoints.
17+
*
18+
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries
19+
*/
20+
export interface Breakpoint {
21+
/** The shortcut name for the breakpoint, e.g. 'xs' */
22+
name: string;
23+
/** The mediaQuery for the breakpoint, e.g. 'screen and (max-width: 500px)' */
24+
media: string;
25+
/** The priority of the breakpoint compared to other breakpoints */
26+
priority: number;
27+
}
28+
29+
export const FALLBACK_BREAKPOINT_KEY: string = '__FALLBACK__';
30+
31+
/**
32+
* The fallback breakpoint, which has no real name and is
33+
* superseded by any other breakpoint value
34+
*/
35+
export const FALLBACK_BREAKPOINT: Breakpoint = {
36+
name: FALLBACK_BREAKPOINT_KEY,
37+
media: 'all',
38+
priority: -Number.MAX_SAFE_INTEGER,
39+
};
40+
41+
/**
42+
* The default breakpoints as provided by Google's Material Design.
43+
* These do not include orientation breakpoints or device breakpoints.
44+
*/
45+
export const DEFAULT_BREAKPOINTS: Breakpoint[] = [
46+
{
47+
name: 'xs',
48+
media: 'screen and (min-width: 0px) and (max-width: 599.9px)',
49+
priority: 1000,
50+
},
51+
{
52+
name: 'sm',
53+
media: 'screen and (min-width: 600px) and (max-width: 959.9px)',
54+
priority: 900,
55+
},
56+
{
57+
name: 'md',
58+
media: 'screen and (min-width: 960px) and (max-width: 1279.9px)',
59+
priority: 800,
60+
},
61+
{
62+
name: 'lg',
63+
media: 'screen and (min-width: 1280px) and (max-width: 1919.9px)',
64+
priority: 700,
65+
},
66+
{
67+
name: 'xl',
68+
media: 'screen and (min-width: 1920px) and (max-width: 4999.9px)',
69+
priority: 600,
70+
},
71+
{
72+
name: 'lt-sm',
73+
media: 'screen and (max-width: 599.9px)',
74+
priority: 950,
75+
},
76+
{
77+
name: 'lt-md',
78+
media: 'screen and (max-width: 959.9px)',
79+
priority: 850,
80+
},
81+
{
82+
name: 'lt-lg',
83+
media: 'screen and (max-width: 1279.9px)',
84+
priority: 750,
85+
},
86+
{
87+
name: 'lt-xl',
88+
priority: 650,
89+
media: 'screen and (max-width: 1919.9px)',
90+
},
91+
{
92+
name: 'gt-xs',
93+
media: 'screen and (min-width: 600px)',
94+
priority: -950,
95+
},
96+
{
97+
name: 'gt-sm',
98+
media: 'screen and (min-width: 960px)',
99+
priority: -850,
100+
}, {
101+
name: 'gt-md',
102+
media: 'screen and (min-width: 1280px)',
103+
priority: -750,
104+
},
105+
{
106+
name: 'gt-lg',
107+
media: 'screen and (min-width: 1920px)',
108+
priority: -650,
109+
}
110+
];
111+
112+
/**
113+
* The user-facing injection token for providing breakpoints,
114+
* this is meant to be provided as a multi-provider, and
115+
* consolidated later.
116+
*/
117+
export const BREAKPOINTS =
118+
new InjectionToken<Array<Array<Breakpoint>>>('Angular Layout Breakpoints');
119+
120+
/** An internal-facing provider for the default breakpoints */
121+
export const BREAKPOINTS_PROVIDER = {
122+
provide: BREAKPOINTS,
123+
useValue: DEFAULT_BREAKPOINTS,
124+
multi: true,
125+
};
126+
127+
/**
128+
* An internal-facing injection token to consolidate all registered
129+
* breakpoints for use in the application.
130+
*/
131+
export const BPS = new InjectionToken<Breakpoint[]>('Angular Layout Condensed Breakpoints', {
132+
providedIn: 'root',
133+
factory: () => {
134+
const providedBps = inject(BREAKPOINTS);
135+
const bpMap: Map<string, Breakpoint> = new Map();
136+
137+
providedBps.forEach(bps => {
138+
bps.forEach(bp => {
139+
bpMap.set(bp.name, bp);
140+
});
141+
});
142+
143+
return [...Array.from(bpMap.values()), FALLBACK_BREAKPOINT];
144+
}
145+
});

0 commit comments

Comments
 (0)