Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.
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
4 changes: 3 additions & 1 deletion src/lib/core/tokens/library-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface LayoutConfigOptions {
useColumnBasisZero?: boolean;
printWithBreakpoints?: string[];
mediaTriggerAutoRestore?: boolean;
ssrObserveBreakpoints?: string[];
}

export const DEFAULT_CONFIG: LayoutConfigOptions = {
Expand All @@ -27,7 +28,8 @@ export const DEFAULT_CONFIG: LayoutConfigOptions = {
serverLoaded: false,
useColumnBasisZero: true,
printWithBreakpoints: [],
mediaTriggerAutoRestore: true
mediaTriggerAutoRestore: true,
ssrObserveBreakpoints: [],
};

export const LAYOUT_CONFIG = new InjectionToken<LayoutConfigOptions>(
Expand Down
46 changes: 34 additions & 12 deletions src/lib/server/server-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import {
BreakPoint,
ɵMatchMedia as MatchMedia,
StylesheetMap,
sortAscendingPriority
sortAscendingPriority,
LayoutConfigOptions,
LAYOUT_CONFIG,
} from '@angular/flex-layout/core';

import {ServerMatchMedia} from './server-match-media';
Expand All @@ -27,10 +29,12 @@ import {ServerMatchMedia} from './server-match-media';
* element
* @param mediaController the MatchMedia service to activate/deactivate breakpoints
* @param breakpoints the registered breakpoints to activate/deactivate
* @param layoutConfig the library config, and specifically the breakpoints to activate
*/
export function generateStaticFlexLayoutStyles(serverSheet: StylesheetMap,
mediaController: MatchMedia,
breakpoints: BreakPoint[]) {
mediaController: ServerMatchMedia,
breakpoints: BreakPoint[],
layoutConfig: LayoutConfigOptions) {
// Store the custom classes in the following map, that way only
// one class gets allocated per HTMLElement, and each class can
// be referenced in the static media queries
Expand All @@ -43,14 +47,29 @@ export function generateStaticFlexLayoutStyles(serverSheet: StylesheetMap,

[...breakpoints].sort(sortAscendingPriority).forEach((bp, i) => {
serverSheet.clearStyles();
(mediaController as ServerMatchMedia).activateBreakpoint(bp);
mediaController.activateBreakpoint(bp);
const stylesheet = new Map(serverSheet.stylesheet);
if (stylesheet.size > 0) {
styleText += generateCss(stylesheet, bp.mediaQuery, classMap);
}
(mediaController as ServerMatchMedia).deactivateBreakpoint(breakpoints[i]);
mediaController.deactivateBreakpoint(breakpoints[i]);
});

const serverBps = layoutConfig.ssrObserveBreakpoints;
if (serverBps) {
serverBps
.reduce((acc: BreakPoint[], serverBp: string) => {
const foundBp = breakpoints.find(bp => serverBp === bp.alias);
if (!foundBp) {
console.warn(`FlexLayoutServerModule: unknown breakpoint alias "${serverBp}"`);
} else {
acc.push(foundBp);
}
return acc;
}, [])
.forEach(mediaController.activateBreakpoint);
}

return styleText;
}

Expand All @@ -59,14 +78,16 @@ export function generateStaticFlexLayoutStyles(serverSheet: StylesheetMap,
* components and attach it to the head of the DOM
*/
export function FLEX_SSR_SERIALIZER_FACTORY(serverSheet: StylesheetMap,
matchMedia: MatchMedia,
mediaController: ServerMatchMedia,
_document: Document,
breakpoints: BreakPoint[]) {
breakpoints: BreakPoint[],
layoutConfig: LayoutConfigOptions) {
return () => {
// This is the style tag that gets inserted into the head of the DOM,
// populated with the manual media queries
const styleTag = _document.createElement('style');
const styleText = generateStaticFlexLayoutStyles(serverSheet, matchMedia, breakpoints);
const styleText = generateStaticFlexLayoutStyles(serverSheet, mediaController, breakpoints,
layoutConfig);
styleTag.classList.add(`${CLASS_NAME}ssr`);
styleTag.textContent = styleText;
_document.head!.appendChild(styleTag);
Expand All @@ -85,6 +106,7 @@ export const SERVER_PROVIDERS = [
MatchMedia,
DOCUMENT,
BREAKPOINTS,
LAYOUT_CONFIG,
],
multi: true
},
Expand Down Expand Up @@ -117,7 +139,8 @@ export type ClassMap = Map<HTMLElement, string>;
function generateCss(stylesheet: StyleSheet, mediaQuery: string, classMap: ClassMap) {
let css = '';
stylesheet.forEach((styles, el) => {
let keyVals = '', className = getClassName(el, classMap);
let keyVals = '';
let className = getClassName(el, classMap);

styles.forEach((v, k) => {
keyVals += v ? format(`${k}:${v};`) : '';
Expand All @@ -138,13 +161,13 @@ function generateCss(stylesheet: StyleSheet, mediaQuery: string, classMap: Class
function format(...list: string[]): string {
let result = '';
list.forEach((css, i) => {
result += IS_DEBUG_MODE ? formatSegment(css, i != 0) : css;
result += IS_DEBUG_MODE ? formatSegment(css, i !== 0) : css;
});
return result;
}

function formatSegment(css: string, asPrefix: boolean = true): string {
return asPrefix ? '\n' + css : css + '\n';
return asPrefix ? `\n${css}` : `${css}\n`;
}

/**
Expand All @@ -162,4 +185,3 @@ function getClassName(element: HTMLElement, classMap: Map<HTMLElement, string>)

return className;
}