Skip to content

Instantly share code, notes, and snippets.

@mostafizurhimself
Last active October 29, 2025 08:50
Show Gist options
  • Select an option

  • Save mostafizurhimself/0d7af0e86e8876ff5fb4b5bf6bce1fd2 to your computer and use it in GitHub Desktop.

Select an option

Save mostafizurhimself/0d7af0e86e8876ff5fb4b5bf6bce1fd2 to your computer and use it in GitHub Desktop.

Revisions

  1. mostafizurhimself revised this gist Oct 29, 2025. 1 changed file with 9 additions and 1 deletion.
    10 changes: 9 additions & 1 deletion StyleManager.tsx
    Original file line number Diff line number Diff line change
    @@ -17,6 +17,8 @@ type Props = {
    };

    const StyleManager: FC<Props> = memo(({ content, themeSettings }) => {
    let isServerStylesInjected = false;

    const breakpoints = BreakpointConfiguration.getBreakpoints();

    const style = createStyle();
    @@ -55,11 +57,17 @@ const StyleManager: FC<Props> = memo(({ content, themeSettings }) => {

    const fontsUrl = generateFontsUrl(styles);

    // For SSR - inject styles only once
    useServerInsertedHTML(() => {
    if (isServerStylesInjected) {
    return null;
    }
    isServerStylesInjected = true;

    return (
    <>
    <link href={fontsUrl} id="fonts" rel="stylesheet"></link>
    <style dangerouslySetInnerHTML={{ __html: styles }}></style>
    <style id="dynamic-styles" dangerouslySetInnerHTML={{ __html: styles }}></style>
    </>
    );
    });
  2. mostafizurhimself created this gist Oct 29, 2025.
    72 changes: 72 additions & 0 deletions StyleManager.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,72 @@
    'use client';

    import { BreakpointConfiguration } from '@/features/builder/config/breakpoints.config';
    import { BlockConfiguration } from '@/features/builder/config/editor.config';
    import { Block } from '@/features/builder/types/block';
    import { Breakpoint } from '@/features/builder/types/responsive';
    import { createStyle } from '@/features/builder/utils';
    import { generateContentStyles, generateFontsUrl } from '@/features/builder/utils/style';
    import { generateThemeStyles } from '@/features/builder/utils/theme';
    import { ThemeSettings } from '@/features/theme/types';
    import { useServerInsertedHTML } from 'next/navigation';
    import { FC, memo } from 'react';

    type Props = {
    content: Record<string, Block>;
    themeSettings: ThemeSettings;
    };

    const StyleManager: FC<Props> = memo(({ content, themeSettings }) => {
    const breakpoints = BreakpointConfiguration.getBreakpoints();

    const style = createStyle();

    style.register({
    $global: true,
    '.hide-on-desktop': {
    [BreakpointConfiguration.getMediaQuery(Breakpoint.DESKTOP)]: {
    display: 'none',
    },
    },
    '.hide-on-tablet': {
    [BreakpointConfiguration.getMediaQuery(Breakpoint.TABLET)]: {
    display: 'none',
    },
    },
    '.hide-on-mobile': {
    [BreakpointConfiguration.getMediaQuery(Breakpoint.MOBILE)]: {
    display: 'none',
    },
    },
    });

    const defaultStyles = style.get();

    const contentStyles = generateContentStyles({
    content,
    themeSettings,
    breakpoints,
    config: BlockConfiguration.getConfig(),
    });

    const themeStyles = generateThemeStyles({ settings: themeSettings, breakpoints });

    const styles = defaultStyles + themeStyles + contentStyles;

    const fontsUrl = generateFontsUrl(styles);

    useServerInsertedHTML(() => {
    return (
    <>
    <link href={fontsUrl} id="fonts" rel="stylesheet"></link>
    <style dangerouslySetInnerHTML={{ __html: styles }}></style>
    </>
    );
    });

    return null;
    });

    StyleManager.displayName = 'StyleManager';

    export default StyleManager;