From 276a0d92788ed5f30755243a306d2e78fe93f19a Mon Sep 17 00:00:00 2001 From: Rajat Date: Sun, 21 Sep 2025 19:57:05 +0000 Subject: [PATCH 1/8] WIP: Page block background types --- apps/docs/src/pages/en/website/blocks.md | 10 +- apps/docs/src/pages/en/website/themes.md | 36 +- package.json | 2 +- .../src/widget-default-settings.ts | 3 +- packages/components-library/src/index.ts | 1 + .../src/section-background-panel.tsx | 434 ++++++++++++++++++ .../src/blocks/hero/admin-widget.tsx | 12 +- packages/page-models/src/index.ts | 1 + .../page-models/src/section-background.ts | 63 +++ pnpm-lock.yaml | 1 + 10 files changed, 537 insertions(+), 26 deletions(-) create mode 100644 packages/components-library/src/section-background-panel.tsx create mode 100644 packages/page-models/src/section-background.ts diff --git a/apps/docs/src/pages/en/website/blocks.md b/apps/docs/src/pages/en/website/blocks.md index 225de7931..614efceb2 100644 --- a/apps/docs/src/pages/en/website/blocks.md +++ b/apps/docs/src/pages/en/website/blocks.md @@ -36,7 +36,7 @@ You will also see the newly added link on the header itself. 3. Click on the pencil icon against the newly added link to edit it as shown above. 4. Change the label (displayed as text on the header block) and the URL (where the user should be taken upon clicking the label on the header) and click `Done` to save. ![Header edit link](/assets/pages/header-edit-link.png) - + ### [Rich Text](#rich-text) @@ -61,7 +61,7 @@ You can also use the floating controls to do the same as shown below. 2. Click on the floating `link` button to reveal a popup text input. 3. In the popup text input, enter the URL as shown below. ![Create a hyperlink in rich text block](/assets/pages/rich-text-create-hyperlink.gif) - + ### [Hero](#hero) @@ -87,7 +87,7 @@ Following is how it looks on a page. 4. In the button action, enter the URL the user should be taken to upon clicking. a. If the URL is from your own school, use its relative form, i.e., `/courses`. b. If the URL is from some external website, use the absolute (complete) URL, i.e., `https://website.com/courses`. - + ### [Grid](#grid) @@ -132,7 +132,7 @@ A grid block comes in handy when you want to show some sort of list, for example 4. In the button action, enter the URL the user should be taken to upon clicking. a. If the URL is from your own school, use its relative form, i.e., `/courses`. b. If the URL is from some external website, use the absolute (complete) URL, i.e., `https://website.com/courses`. - + ### [Featured](#featured) @@ -268,7 +268,7 @@ In the `Design` panel, you can customize: - Maximum width - Vertical padding - Social media links (Facebook, Twitter, Instagram, LinkedIn, YouTube, Discord, GitHub) - + ## [Shared blocks](#shared-blocks) diff --git a/apps/docs/src/pages/en/website/themes.md b/apps/docs/src/pages/en/website/themes.md index 0700d2e29..2d7bed189 100644 --- a/apps/docs/src/pages/en/website/themes.md +++ b/apps/docs/src/pages/en/website/themes.md @@ -192,14 +192,14 @@ The typography editor lets you customize text styles across your website. These - Header 3: Smaller titles for subsections - Header 4: Small titles for minor sections - Preheader: Introductory text that appears above headers - +
Subheaders - Subheader 1: Primary subheaders for section introductions - Subheader 2: Secondary subheaders for supporting text -
+
Body Text @@ -207,7 +207,7 @@ The typography editor lets you customize text styles across your website. These - Text 1: Main body text for content - Text 2: Secondary body text for supporting content - Caption: Small text for image captions and footnotes -
+
Interactive Elements @@ -215,7 +215,7 @@ The typography editor lets you customize text styles across your website. These - Link: Text for clickable links - Button: Text for buttons and calls-to-action - Input: Text for form fields and search boxes -
+ For each text style, you can customize: @@ -243,7 +243,7 @@ CourseLit provides a carefully curated selection of professional fonts, organize - **Mulish**: A geometric sans-serif with a modern feel - **Nunito**: A well-balanced font with rounded terminals - **Work Sans**: A clean, modern font with a geometric feel - +
Serif Fonts @@ -253,7 +253,7 @@ CourseLit provides a carefully curated selection of professional fonts, organize - **Playfair Display**: An elegant serif font for headings - **Roboto Slab**: A serif variant of Roboto - **Source Serif 4**: A serif font designed for digital reading -
+
Display Fonts @@ -264,7 +264,7 @@ CourseLit provides a carefully curated selection of professional fonts, organize - **Rubik**: A sans-serif with a geometric feel - **Oswald**: A reworking of the classic style - **Bebas Neue**: A display font with a strong personality -
+
Modern Fonts @@ -272,7 +272,7 @@ CourseLit provides a carefully curated selection of professional fonts, organize - **Lato**: A sans-serif font with a warm feel - **PT Sans**: A font designed for public use - **Quicksand**: A display sans-serif with rounded terminals -
+ Each font is optimized for web use and includes multiple weights for flexibility in design. All fonts support Latin characters and are carefully selected for their readability and professional appearance. @@ -290,7 +290,7 @@ The interactives editor allows you to customize the appearance of interactive el - Shadow effects: From None to 2X Large - Custom styles: Add your own custom styles using [supported Tailwind classes](#supported-tailwind-classes) - Disabled state: How the button looks when it can't be clicked - +
Link @@ -300,7 +300,7 @@ The interactives editor allows you to customize the appearance of interactive el - Text shadow: Add depth to your links - Custom styles: Add your own custom styles using [supported Tailwind classes](#supported-tailwind-classes) - Disabled state: How the link looks when it can't be clicked -
+
Card @@ -309,7 +309,7 @@ The interactives editor allows you to customize the appearance of interactive el - Border style: Choose from various border styles - Shadow effects: Add depth to your cards - Custom styles: Add your own custom styles using [supported Tailwind classes](#supported-tailwind-classes) -
+
Input @@ -320,7 +320,7 @@ The interactives editor allows you to customize the appearance of interactive el - Shadow effects: Add depth to your input fields - Custom styles: Add your own custom styles using [supported Tailwind classes](#supported-tailwind-classes) - Disabled state: How the input looks when it can't be used -
+ ### 4. Structure @@ -332,14 +332,14 @@ The structure editor lets you customize the layout of your pages, like section p Page - Maximum width options: - 2XL (42rem): Compact layout - 3XL (48rem): Standard layout - 4XL (56rem): Wide layout - 5XL (64rem): Extra wide layout - 6XL (72rem): Full width layout - +
Section - Horizontal padding: Space on the left and right sides (None to 9X Large) - Vertical padding: Space on the top and bottom (None to 9X Large) -
+ ## Publishing Changes @@ -387,7 +387,7 @@ When adding custom styles to interactive elements, you can use the following Tai - `text-6xl`: 6X large text - `text-7xl`: 7X large text - `text-8xl`: 8X large text - +
Padding @@ -399,7 +399,7 @@ When adding custom styles to interactive elements, you can use the following Tai #### Horizontal Padding - `px-4` to `px-20`: Horizontal padding from 1rem to 5rem -
+
Colors @@ -454,7 +454,7 @@ Variants available: `hover`, `disabled`, `dark` - `ease-out`: Ease out - `ease-in-out`: Ease in and out - `ease-linear`: Linear -
+
Transforms @@ -481,7 +481,7 @@ Variants available: `hover`, `disabled`, `dark` - `scale-110`: 110% scale - `scale-125`: 125% scale - `scale-150`: 150% scale -
+
Shadows diff --git a/package.json b/package.json index 8b21e27ff..ffb14f6a5 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "test:watch": "NODE_OPTIONS='--experimental-vm-modules' SUPPRESS_JEST_WARNINGS=1 jest --watch", "test:coverage": "NODE_OPTIONS='--experimental-vm-modules' SUPPRESS_JEST_WARNINGS=1 jest --coverage" }, - "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977", + "packageManager": "pnpm@10.17.0+sha512.fce8a3dd29a4ed2ec566fb53efbb04d8c44a0f05bc6f24a73046910fb9c3ce7afa35a0980500668fa3573345bd644644fa98338fa168235c80f4aa17aa17fbef", "devDependencies": { "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", diff --git a/packages/common-models/src/widget-default-settings.ts b/packages/common-models/src/widget-default-settings.ts index 0ed564433..ab5838b7f 100644 --- a/packages/common-models/src/widget-default-settings.ts +++ b/packages/common-models/src/widget-default-settings.ts @@ -4,7 +4,7 @@ import { PageTypeProduct, PageTypeSite, } from "."; -import type { ThemeStyle } from "@courselit/page-models"; +import type { SectionBackground, ThemeStyle } from "@courselit/page-models"; type PageType = | PageTypeProduct @@ -16,4 +16,5 @@ export default interface WidgetDefaultSettings { type: PageType; verticalPadding: ThemeStyle["structure"]["section"]["padding"]["y"]; maxWidth?: ThemeStyle["structure"]["page"]["width"]; + background?: SectionBackground; } diff --git a/packages/components-library/src/index.ts b/packages/components-library/src/index.ts index 2c37c6571..14b80cd50 100644 --- a/packages/components-library/src/index.ts +++ b/packages/components-library/src/index.ts @@ -61,6 +61,7 @@ export * from "./image"; export * from "./vertical-padding-selector"; export * from "./max-width-selector"; export * from "./lib/utils"; +export * from "./section-background-panel"; export { PriceTag, diff --git a/packages/components-library/src/section-background-panel.tsx b/packages/components-library/src/section-background-panel.tsx new file mode 100644 index 000000000..b00f49498 --- /dev/null +++ b/packages/components-library/src/section-background-panel.tsx @@ -0,0 +1,434 @@ +import * as React from "react"; +import { + SectionBackground, + BlendMode, + BackgroundRepeat, +} from "@courselit/page-models"; +import ColorSelector from "./color-selector"; +import PageBuilderSlider from "./page-builder-slider"; +import CustomSelect from "./select"; +import { Card, CardContent, CardHeader, CardTitle } from "./components/ui/card"; +import { Input } from "./components/ui/input"; +import { Label } from "./components/ui/label"; + +interface SectionBackgroundPanelProps { + value: SectionBackground; + onChange: (value: SectionBackground) => void; + className?: string; +} + +const BLEND_MODES: { label: string; value: BlendMode }[] = [ + { label: "Normal", value: "normal" }, + { label: "Multiply", value: "multiply" }, + { label: "Screen", value: "screen" }, + { label: "Overlay", value: "overlay" }, + { label: "Darken", value: "darken" }, + { label: "Lighten", value: "lighten" }, + { label: "Color Dodge", value: "color-dodge" }, + { label: "Color Burn", value: "color-burn" }, + { label: "Hard Light", value: "hard-light" }, + { label: "Soft Light", value: "soft-light" }, + { label: "Difference", value: "difference" }, + { label: "Exclusion", value: "exclusion" }, + { label: "Hue", value: "hue" }, + { label: "Saturation", value: "saturation" }, + { label: "Color", value: "color" }, + { label: "Luminosity", value: "luminosity" }, +]; + +const BACKGROUND_REPEAT_OPTIONS: { label: string; value: BackgroundRepeat }[] = + [ + { label: "No Repeat", value: "no-repeat" }, + { label: "Repeat", value: "repeat" }, + { label: "Repeat X", value: "repeat-x" }, + { label: "Repeat Y", value: "repeat-y" }, + { label: "Space", value: "space" }, + { label: "Round", value: "round" }, + ]; + +const BACKGROUND_SIZE_OPTIONS = [ + { label: "Auto", value: "auto" }, + { label: "Cover", value: "cover" }, + { label: "Contain", value: "contain" }, + { label: "100%", value: "100%" }, + { label: "50%", value: "50%" }, + { label: "200%", value: "200%" }, +]; + +const BACKGROUND_POSITION_OPTIONS = [ + { label: "Top Left", value: "top left" }, + { label: "Top Center", value: "top center" }, + { label: "Top Right", value: "top right" }, + { label: "Center Left", value: "center left" }, + { label: "Center", value: "center" }, + { label: "Center Right", value: "center right" }, + { label: "Bottom Left", value: "bottom left" }, + { label: "Bottom Center", value: "bottom center" }, + { label: "Bottom Right", value: "bottom right" }, +]; + +export function SectionBackgroundPanel({ + value, + onChange, + className, +}: SectionBackgroundPanelProps) { + const handleTypeChange = (type: SectionBackground["type"]) => { + switch (type) { + case "color": + onChange({ + type: "color", + backgroundColor: "#ffffff", + backgroundColorDark: undefined, + }); + break; + case "image": + onChange({ + type: "image", + overlay: { + color: "#000000", + blendMode: "normal", + opacity: 0.5, + }, + image: {}, + backgroundImage: "", + backgroundSize: "cover", + backgroundPosition: "center", + backgroundRepeat: "no-repeat", + maskImage: undefined, + }); + break; + case "gradient": + onChange({ + type: "gradient", + backgroundImage: "", + backgroundImageDark: undefined, + backgroundSize: "cover", + backgroundPosition: "center", + backgroundRepeat: "no-repeat", + maskImage: undefined, + }); + break; + } + }; + + const handleColorBackgroundChange = ( + updates: Partial>, + ) => { + if (value.type === "color") { + onChange({ ...value, ...updates }); + } + }; + + const handleImageBackgroundChange = ( + updates: Partial>, + ) => { + if (value.type === "image") { + onChange({ ...value, ...updates }); + } + }; + + const handleGradientBackgroundChange = ( + updates: Partial>, + ) => { + if (value.type === "gradient") { + onChange({ ...value, ...updates }); + } + }; + + const handleOverlayChange = ( + overlayUpdates: Partial< + Extract["overlay"] + >, + ) => { + if (value.type === "image") { + onChange({ + ...value, + overlay: { ...value.overlay, ...overlayUpdates }, + }); + } + }; + + return ( +
+ + + Section Background + + + {/* Background Type Selection */} +
+ + +
+ +
+ + {/* Color Background Controls */} + {value.type === "color" && ( +
+

+ Color Settings +

+ + handleColorBackgroundChange({ + backgroundColor: color || "#ffffff", + }) + } + tooltip="Choose the background color for this section" + /> + + handleColorBackgroundChange({ + backgroundColorDark: color, + }) + } + tooltip="Optional background color for dark mode" + allowReset={true} + /> +
+ )} + + {/* Image Background Controls */} + {value.type === "image" && ( +
+

+ Image Settings +

+ + {/* Image URL */} +
+ + + handleImageBackgroundChange({ + backgroundImage: e.target.value, + }) + } + placeholder="https://example.com/image.jpg" + /> +
+ + {/* Image Properties */} +
+ + handleImageBackgroundChange({ + backgroundSize: size, + }) + } + options={BACKGROUND_SIZE_OPTIONS} + /> + + handleImageBackgroundChange({ + backgroundPosition: position, + }) + } + options={BACKGROUND_POSITION_OPTIONS} + /> +
+ + + handleImageBackgroundChange({ + backgroundRepeat: + repeat as BackgroundRepeat, + }) + } + options={BACKGROUND_REPEAT_OPTIONS} + /> + + {/* Mask Image */} +
+ + + handleImageBackgroundChange({ + maskImage: + e.target.value || undefined, + }) + } + placeholder="https://example.com/mask.svg" + /> +
+ +
+ + {/* Overlay Settings */} +
+

+ Overlay Settings +

+ + handleOverlayChange({ + color: color || "#000000", + }) + } + tooltip="Color of the overlay on top of the background image" + /> + + handleOverlayChange({ + blendMode: mode as BlendMode, + }) + } + options={BLEND_MODES} + /> + + handleOverlayChange({ + opacity: (opacity || 0) / 100, + }) + } + tooltip="Opacity of the overlay (0-100%)" + /> +
+
+ )} + + {/* Gradient Background Controls */} + {value.type === "gradient" && ( +
+

+ Gradient Settings +

+ + {/* Gradient CSS */} +
+ + + handleGradientBackgroundChange({ + backgroundImage: e.target.value, + }) + } + placeholder="linear-gradient(45deg, #ff0000, #0000ff)" + /> +

+ Enter CSS gradient syntax (e.g., + linear-gradient, radial-gradient) +

+
+ + {/* Dark Mode Gradient */} +
+ + + handleGradientBackgroundChange({ + backgroundImageDark: + e.target.value || undefined, + }) + } + placeholder="linear-gradient(45deg, #333333, #666666)" + /> +
+ + {/* Gradient Properties */} +
+ + handleGradientBackgroundChange({ + backgroundSize: size, + }) + } + options={BACKGROUND_SIZE_OPTIONS} + /> + + handleGradientBackgroundChange({ + backgroundPosition: position, + }) + } + options={BACKGROUND_POSITION_OPTIONS} + /> +
+ + + handleGradientBackgroundChange({ + backgroundRepeat: + repeat as BackgroundRepeat, + }) + } + options={BACKGROUND_REPEAT_OPTIONS} + /> + + {/* Mask Image */} +
+ + + handleGradientBackgroundChange({ + maskImage: + e.target.value || undefined, + }) + } + placeholder="https://example.com/mask.svg" + /> +
+
+ )} + + +
+ ); +} diff --git a/packages/page-blocks/src/blocks/hero/admin-widget.tsx b/packages/page-blocks/src/blocks/hero/admin-widget.tsx index 904fd5ed9..004451790 100644 --- a/packages/page-blocks/src/blocks/hero/admin-widget.tsx +++ b/packages/page-blocks/src/blocks/hero/admin-widget.tsx @@ -5,7 +5,7 @@ import type { Media, Profile, } from "@courselit/common-models"; -import { Theme, ThemeStyle } from "@courselit/page-models"; +import { Theme, ThemeStyle, SectionBackground } from "@courselit/page-models"; import Settings from "./settings"; import { AdminWidgetPanel, @@ -27,6 +27,7 @@ import { Checkbox, VerticalPaddingSelector, MaxWidthSelector, + SectionBackgroundPanel, } from "@courselit/components-library"; import { isVideo } from "@courselit/utils"; @@ -107,6 +108,9 @@ export default function AdminWidget({ const [maxWidth, setMaxWidth] = useState< ThemeStyle["structure"]["page"]["width"] >(settings.maxWidth); + const [background, setBackground] = useState( + settings.background, + ); const onSettingsChanged = () => onChange({ @@ -130,6 +134,7 @@ export default function AdminWidget({ aspectRatio, objectFit, maxWidth, + background, }); useEffect(() => { @@ -155,6 +160,7 @@ export default function AdminWidget({ aspectRatio, objectFit, maxWidth, + background, ]); return ( @@ -374,6 +380,10 @@ export default function AdminWidget({ } onChange={setVerticalPadding} /> + diff --git a/packages/page-models/src/index.ts b/packages/page-models/src/index.ts index cb332219e..42ed69d5a 100644 --- a/packages/page-models/src/index.ts +++ b/packages/page-models/src/index.ts @@ -1,2 +1,3 @@ export * from "./theme"; export * from "./theme-style"; +export * from "./section-background"; diff --git a/packages/page-models/src/section-background.ts b/packages/page-models/src/section-background.ts new file mode 100644 index 000000000..7576eec70 --- /dev/null +++ b/packages/page-models/src/section-background.ts @@ -0,0 +1,63 @@ +export type BlendMode = + | "normal" + | "multiply" + | "screen" + | "overlay" + | "darken" + | "lighten" + | "color-dodge" + | "color-burn" + | "hard-light" + | "soft-light" + | "difference" + | "exclusion" + | "hue" + | "saturation" + | "color" + | "luminosity"; + +export type BackgroundRepeat = + | "no-repeat" + | "repeat" + | "repeat-x" + | "repeat-y" + | "space" + | "round"; + +export interface SectionBackgroundOverlay { + color: string; + blendMode: BlendMode; + opacity: number; +} + +export interface ColorSectionBackground { + type: "color"; + backgroundColor: string; + backgroundColorDark?: string; +} + +export interface ImageSectionBackground { + type: "image"; + overlay: SectionBackgroundOverlay; + image: Record; + backgroundImage: string; + backgroundSize?: string; + backgroundPosition?: string; + backgroundRepeat?: BackgroundRepeat; + maskImage?: string; +} + +export interface GradientSectionBackground { + type: "gradient"; + backgroundImage: string; + backgroundImageDark?: string; + backgroundSize?: string; + backgroundPosition?: string; + backgroundRepeat?: BackgroundRepeat; + maskImage?: string; +} + +export type SectionBackground = + | ColorSectionBackground + | ImageSectionBackground + | GradientSectionBackground; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb2d195d5..27eca256a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8076,6 +8076,7 @@ packages: muri@1.3.0: resolution: {integrity: sha512-FiaFwKl864onHFFUV/a2szAl7X0fxVlSKNdhTf+BM8i8goEgYut8u5P9MqQqIYwvaMxjzVESsoEm/2kfkFH1rg==} + deprecated: This package is no longer supported. Please use https://www.npmjs.com/package/mongodb-connection-string-url mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} From 20e2ffa9ff83490a851b57da82b7fc8424a39aca Mon Sep 17 00:00:00 2001 From: Rajat Date: Sun, 21 Sep 2025 19:57:51 +0000 Subject: [PATCH 2/8] Lint fixes --- apps/web/package.json | 204 +++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 0d18cc39f..2d4737928 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,105 +1,105 @@ { - "name": "@courselit/web", - "version": "0.63.0", - "private": true, - "scripts": { - "dev": "next dev --turbopack", - "build": "next build", - "start": "next start", - "lint": "next lint", - "prettier": "prettier --write **/*.ts" - }, - "dependencies": { - "@courselit/common-logic": "workspace:^", - "@courselit/common-models": "workspace:^", - "@courselit/components-library": "workspace:^", - "@courselit/email-editor": "workspace:^", - "@courselit/icons": "workspace:^", - "@courselit/page-blocks": "workspace:^", - "@courselit/page-models": "workspace:^", - "@courselit/page-primitives": "workspace:^", - "@courselit/utils": "workspace:^", - "@hookform/resolvers": "^3.9.1", - "@radix-ui/react-alert-dialog": "^1.1.2", - "@radix-ui/react-avatar": "^1.1.3", - "@radix-ui/react-checkbox": "^1.1.4", - "@radix-ui/react-collapsible": "^1.1.3", - "@radix-ui/react-compose-refs": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.6", - "@radix-ui/react-dropdown-menu": "^2.1.6", - "@radix-ui/react-label": "^2.1.2", - "@radix-ui/react-popover": "^1.1.6", - "@radix-ui/react-radio-group": "^1.2.3", - "@radix-ui/react-scroll-area": "^1.2.3", - "@radix-ui/react-select": "^2.1.6", - "@radix-ui/react-separator": "^1.1.2", - "@radix-ui/react-slot": "^1.1.2", - "@radix-ui/react-switch": "^1.1.3", - "@radix-ui/react-tabs": "^1.1.3", - "@radix-ui/react-toast": "^1.2.6", - "@radix-ui/react-toggle": "^1.1.6", - "@radix-ui/react-toggle-group": "^1.1.7", - "@radix-ui/react-tooltip": "^1.1.8", - "@radix-ui/react-visually-hidden": "^1.1.0", - "@stripe/stripe-js": "^5.4.0", - "@types/base-64": "^1.0.0", - "archiver": "^5.3.1", - "aws4": "^1.13.2", - "base-64": "^1.0.0", - "chart.js": "^4.4.7", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.1", - "color-convert": "^3.1.0", - "cookie": "^0.4.2", - "date-fns": "^4.1.0", - "graphql": "^16.10.0", - "graphql-type-json": "^0.3.2", - "jsdom": "^26.1.0", - "lodash.debounce": "^4.0.8", - "lucide-react": "^0.475.0", - "mongodb": "^6.15.0", - "mongoose": "^8.13.1", - "next": "15.5.3", - "next-auth": "^5.0.0-beta.29", - "next-themes": "^0.4.6", - "nodemailer": "^6.7.2", - "pug": "^3.0.2", - "razorpay": "^2.9.4", - "react": "19.1.1", - "react-chartjs-2": "^5.3.0", - "react-csv": "^2.2.2", - "react-dom": "19.1.1", - "react-hook-form": "^7.54.1", - "recharts": "^2.15.1", - "remirror": "^3.0.1", - "sharp": "^0.33.2", - "slugify": "^1.6.5", - "stripe": "^17.5.0", - "tailwind-merge": "^2.5.4", - "tailwindcss-animate": "^1.0.7", - "zod": "^3.24.1" - }, - "devDependencies": { - "@types/bcryptjs": "^2.4.2", - "@types/cookie": "^0.4.1", - "@types/mongodb": "^4.0.7", - "@types/node": "17.0.21", - "@types/nodemailer": "^6.4.4", - "@types/pug": "^2.0.6", - "@types/react": "19.1.13", - "eslint": "8.48.0", - "eslint-config-next": "15.5.3", - "eslint-config-prettier": "^9.0.0", - "postcss": "^8.4.27", - "prettier": "^3.0.2", - "tailwind-config": "workspace:^", - "tailwindcss": "^3.4.1", - "tsconfig": "workspace:^", - "typescript": "^5.6.2" - }, - "pnpm": { - "overrides": { - "@types/react": "19.1.13" + "name": "@courselit/web", + "version": "0.63.0", + "private": true, + "scripts": { + "dev": "next dev --turbopack", + "build": "next build", + "start": "next start", + "lint": "next lint", + "prettier": "prettier --write **/*.ts" + }, + "dependencies": { + "@courselit/common-logic": "workspace:^", + "@courselit/common-models": "workspace:^", + "@courselit/components-library": "workspace:^", + "@courselit/email-editor": "workspace:^", + "@courselit/icons": "workspace:^", + "@courselit/page-blocks": "workspace:^", + "@courselit/page-models": "workspace:^", + "@courselit/page-primitives": "workspace:^", + "@courselit/utils": "workspace:^", + "@hookform/resolvers": "^3.9.1", + "@radix-ui/react-alert-dialog": "^1.1.2", + "@radix-ui/react-avatar": "^1.1.3", + "@radix-ui/react-checkbox": "^1.1.4", + "@radix-ui/react-collapsible": "^1.1.3", + "@radix-ui/react-compose-refs": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", + "@radix-ui/react-label": "^2.1.2", + "@radix-ui/react-popover": "^1.1.6", + "@radix-ui/react-radio-group": "^1.2.3", + "@radix-ui/react-scroll-area": "^1.2.3", + "@radix-ui/react-select": "^2.1.6", + "@radix-ui/react-separator": "^1.1.2", + "@radix-ui/react-slot": "^1.1.2", + "@radix-ui/react-switch": "^1.1.3", + "@radix-ui/react-tabs": "^1.1.3", + "@radix-ui/react-toast": "^1.2.6", + "@radix-ui/react-toggle": "^1.1.6", + "@radix-ui/react-toggle-group": "^1.1.7", + "@radix-ui/react-tooltip": "^1.1.8", + "@radix-ui/react-visually-hidden": "^1.1.0", + "@stripe/stripe-js": "^5.4.0", + "@types/base-64": "^1.0.0", + "archiver": "^5.3.1", + "aws4": "^1.13.2", + "base-64": "^1.0.0", + "chart.js": "^4.4.7", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "color-convert": "^3.1.0", + "cookie": "^0.4.2", + "date-fns": "^4.1.0", + "graphql": "^16.10.0", + "graphql-type-json": "^0.3.2", + "jsdom": "^26.1.0", + "lodash.debounce": "^4.0.8", + "lucide-react": "^0.475.0", + "mongodb": "^6.15.0", + "mongoose": "^8.13.1", + "next": "15.5.3", + "next-auth": "^5.0.0-beta.29", + "next-themes": "^0.4.6", + "nodemailer": "^6.7.2", + "pug": "^3.0.2", + "razorpay": "^2.9.4", + "react": "19.1.1", + "react-chartjs-2": "^5.3.0", + "react-csv": "^2.2.2", + "react-dom": "19.1.1", + "react-hook-form": "^7.54.1", + "recharts": "^2.15.1", + "remirror": "^3.0.1", + "sharp": "^0.33.2", + "slugify": "^1.6.5", + "stripe": "^17.5.0", + "tailwind-merge": "^2.5.4", + "tailwindcss-animate": "^1.0.7", + "zod": "^3.24.1" + }, + "devDependencies": { + "@types/bcryptjs": "^2.4.2", + "@types/cookie": "^0.4.1", + "@types/mongodb": "^4.0.7", + "@types/node": "17.0.21", + "@types/nodemailer": "^6.4.4", + "@types/pug": "^2.0.6", + "@types/react": "19.1.13", + "eslint": "8.48.0", + "eslint-config-next": "15.5.3", + "eslint-config-prettier": "^9.0.0", + "postcss": "^8.4.27", + "prettier": "^3.0.2", + "tailwind-config": "workspace:^", + "tailwindcss": "^3.4.1", + "tsconfig": "workspace:^", + "typescript": "^5.6.2" + }, + "pnpm": { + "overrides": { + "@types/react": "19.1.13" + } } - } } From 0079d4e315a74e9bbec87aeefa7191b632f54bf0 Mon Sep 17 00:00:00 2001 From: Rajat Date: Mon, 22 Sep 2025 17:56:15 +0000 Subject: [PATCH 3/8] Almost finished section backgrounds logic; Removed card layout from hero block --- .../admin/page-editor/add-widget.tsx | 2 +- .../components/admin/page-editor/index.tsx | 52 +- .../base-layout/template/editable-widget.tsx | 2 +- .../src/page-builder-slider.tsx | 6 +- .../src/section-background-panel.tsx | 820 ++++++++++-------- .../src/blocks/hero/admin-widget.tsx | 18 +- .../page-blocks/src/blocks/hero/settings.ts | 1 - .../page-blocks/src/blocks/hero/widget.tsx | 18 +- .../page-models/src/section-background.ts | 38 +- packages/page-primitives/src/section.tsx | 126 ++- packages/page-primitives/tsconfig.json | 2 +- 11 files changed, 642 insertions(+), 443 deletions(-) diff --git a/apps/web/components/admin/page-editor/add-widget.tsx b/apps/web/components/admin/page-editor/add-widget.tsx index 636ecc4d1..a7debf9d4 100644 --- a/apps/web/components/admin/page-editor/add-widget.tsx +++ b/apps/web/components/admin/page-editor/add-widget.tsx @@ -21,7 +21,7 @@ function AddWidget({ pageType, onSelection, onClose }: WidgetsListProps) { .map((item, index) => widgets[item].metadata.compatibleWith.includes(pageType) ? (
  • onSelection(item)} > diff --git a/apps/web/components/admin/page-editor/index.tsx b/apps/web/components/admin/page-editor/index.tsx index c43643e6a..88f5e1eee 100644 --- a/apps/web/components/admin/page-editor/index.tsx +++ b/apps/web/components/admin/page-editor/index.tsx @@ -815,31 +815,6 @@ export default function PageEditor({
  • - {leftPaneContent !== "none" && ( -
    - - -
    - {activeSidePaneContent} -
    -
    -
    - )}
    + {leftPaneContent !== "none" && ( +
    + + +
    + {activeSidePaneContent} +
    +
    +
    + )}
    ); @@ -885,8 +885,8 @@ export default function PageEditor({
    - +
    ); diff --git a/apps/web/components/public/base-layout/template/editable-widget.tsx b/apps/web/components/public/base-layout/template/editable-widget.tsx index c21752ae9..bde834229 100644 --- a/apps/web/components/public/base-layout/template/editable-widget.tsx +++ b/apps/web/components/public/base-layout/template/editable-widget.tsx @@ -41,7 +41,7 @@ const EditableWidget = ({ onClick={() => onEditClick && onEditClick(item.widgetId)} className="relative cursor-pointer group" > -
    +
    Click to update
    diff --git a/packages/components-library/src/page-builder-slider.tsx b/packages/components-library/src/page-builder-slider.tsx index a806e7a1e..fd9076071 100644 --- a/packages/components-library/src/page-builder-slider.tsx +++ b/packages/components-library/src/page-builder-slider.tsx @@ -14,6 +14,7 @@ export default function PageBuilderSlider({ tooltip, className, allowsReset = false, + unit = "px", }: { title: string; min: number; @@ -23,6 +24,7 @@ export default function PageBuilderSlider({ tooltip?: string; className?: string; allowsReset?: boolean; + unit?: string; }) { return (
    @@ -54,10 +56,10 @@ export default function PageBuilderSlider({ ); onChange(clamped); }} - className="h-7 w-16 rounded-md border px-2 py-1 text-xs text-center bg-gray-50" + className="h-7 w-16 rounded-md border border-input bg-background px-2 py-1 text-xs text-center" /> - px + {unit}
    diff --git a/packages/components-library/src/section-background-panel.tsx b/packages/components-library/src/section-background-panel.tsx index b00f49498..2eb4b6264 100644 --- a/packages/components-library/src/section-background-panel.tsx +++ b/packages/components-library/src/section-background-panel.tsx @@ -1,20 +1,31 @@ import * as React from "react"; import { SectionBackground, + SectionBackgroundOverlay, BlendMode, BackgroundRepeat, } from "@courselit/page-models"; import ColorSelector from "./color-selector"; import PageBuilderSlider from "./page-builder-slider"; import CustomSelect from "./select"; -import { Card, CardContent, CardHeader, CardTitle } from "./components/ui/card"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs"; import { Input } from "./components/ui/input"; import { Label } from "./components/ui/label"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "./components/ui/accordion"; +import MediaSelector from "./media-selector"; +import { Address, Media, Profile } from "@courselit/common-models"; interface SectionBackgroundPanelProps { value: SectionBackground; onChange: (value: SectionBackground) => void; className?: string; + profile: Profile; + address: Address; } const BLEND_MODES: { label: string; value: BlendMode }[] = [ @@ -46,389 +57,510 @@ const BACKGROUND_REPEAT_OPTIONS: { label: string; value: BackgroundRepeat }[] = { label: "Round", value: "round" }, ]; -const BACKGROUND_SIZE_OPTIONS = [ - { label: "Auto", value: "auto" }, - { label: "Cover", value: "cover" }, - { label: "Contain", value: "contain" }, - { label: "100%", value: "100%" }, - { label: "50%", value: "50%" }, - { label: "200%", value: "200%" }, -]; - -const BACKGROUND_POSITION_OPTIONS = [ - { label: "Top Left", value: "top left" }, - { label: "Top Center", value: "top center" }, - { label: "Top Right", value: "top right" }, - { label: "Center Left", value: "center left" }, - { label: "Center", value: "center" }, - { label: "Center Right", value: "center right" }, - { label: "Bottom Left", value: "bottom left" }, - { label: "Bottom Center", value: "bottom center" }, - { label: "Bottom Right", value: "bottom right" }, -]; - export function SectionBackgroundPanel({ - value, + value = { + type: "color", + backgroundColor: "transparent", + backgroundColorDark: undefined, + }, onChange, className, + profile, + address, }: SectionBackgroundPanelProps) { const handleTypeChange = (type: SectionBackground["type"]) => { - switch (type) { - case "color": - onChange({ - type: "color", - backgroundColor: "#ffffff", - backgroundColorDark: undefined, - }); - break; - case "image": - onChange({ - type: "image", - overlay: { - color: "#000000", - blendMode: "normal", - opacity: 0.5, - }, - image: {}, - backgroundImage: "", - backgroundSize: "cover", - backgroundPosition: "center", - backgroundRepeat: "no-repeat", - maskImage: undefined, - }); - break; - case "gradient": - onChange({ - type: "gradient", - backgroundImage: "", - backgroundImageDark: undefined, - backgroundSize: "cover", - backgroundPosition: "center", - backgroundRepeat: "no-repeat", - maskImage: undefined, - }); - break; - } + // Simply change the type while preserving all existing properties + onChange({ + ...value, + type, + }); }; const handleColorBackgroundChange = ( - updates: Partial>, + updates: Partial, ) => { - if (value.type === "color") { - onChange({ ...value, ...updates }); - } + onChange({ ...value, ...updates }); }; const handleImageBackgroundChange = ( - updates: Partial>, + updates: Partial, ) => { - if (value.type === "image") { - onChange({ ...value, ...updates }); - } + onChange({ ...value, ...updates }); }; const handleGradientBackgroundChange = ( - updates: Partial>, + updates: Partial, ) => { - if (value.type === "gradient") { - onChange({ ...value, ...updates }); - } + onChange({ ...value, ...updates }); }; const handleOverlayChange = ( - overlayUpdates: Partial< - Extract["overlay"] - >, + overlayUpdates: Partial, ) => { - if (value.type === "image") { - onChange({ - ...value, - overlay: { ...value.overlay, ...overlayUpdates }, - }); - } + onChange({ + ...value, + overlay: { ...value.overlay, ...overlayUpdates }, + }); }; return (
    - - - Section Background - - - {/* Background Type Selection */} -
    - - -
    - -
    + + + + Background + + +
    + + + + Color + + + Image + + + Gradient + + - {/* Color Background Controls */} - {value.type === "color" && ( -
    -

    - Color Settings -

    - - handleColorBackgroundChange({ - backgroundColor: color || "#ffffff", - }) - } - tooltip="Choose the background color for this section" - /> - - handleColorBackgroundChange({ - backgroundColorDark: color, - }) - } - tooltip="Optional background color for dark mode" - allowReset={true} - /> -
    - )} + + + handleColorBackgroundChange({ + backgroundColor: + color || "#ffffff", + }) + } + tooltip="Choose the background color for this section" + /> + + handleColorBackgroundChange({ + backgroundColorDark: color, + }) + } + tooltip="Optional background color for dark mode" + allowReset={true} + /> + - {/* Image Background Controls */} - {value.type === "image" && ( -
    -

    - Image Settings -

    + + { + if (media) { + handleImageBackgroundChange({ + media: media as unknown as Record< + string, + unknown + >, + }); + } + }} + onRemove={() => { + handleImageBackgroundChange({ + media: {} as unknown as Record< + string, + unknown + >, + }); + }} + strings={{}} + access="public" + mediaId={ + value.media && + (value.media.mediaId as string) + } + type="page" + /> - {/* Image URL */} -
    - - - handleImageBackgroundChange({ - backgroundImage: e.target.value, - }) - } - placeholder="https://example.com/image.jpg" - /> -
    + {/* Blur Effect */} + + handleImageBackgroundChange({ + blur: blur || 0, + }) + } + tooltip="Blur effect to the background image" + unit="" + /> - {/* Image Properties */} -
    - - handleImageBackgroundChange({ - backgroundSize: size, - }) - } - options={BACKGROUND_SIZE_OPTIONS} - /> - - handleImageBackgroundChange({ - backgroundPosition: position, - }) - } - options={BACKGROUND_POSITION_OPTIONS} - /> -
    + {/* Overlay Settings */} + + + + Overlay Settings + + + + handleOverlayChange({ + color, + }) + } + tooltip="Color of the overlay on top of the background image" + /> + + handleOverlayChange({ + colorDark: color, + }) + } + tooltip="Optional overlay color for dark mode" + allowReset={true} + /> + + handleOverlayChange({ + opacity, + }) + } + tooltip="Opacity of the overlay" + unit="" + /> + + handleOverlayChange({ + blendMode: + mode as BlendMode, + }) + } + options={BLEND_MODES} + /> + + + - - handleImageBackgroundChange({ - backgroundRepeat: - repeat as BackgroundRepeat, - }) - } - options={BACKGROUND_REPEAT_OPTIONS} - /> + {/* Advanced Settings */} + + + + Advanced + + + {/* Image Properties */} +
    + + + handleImageBackgroundChange( + { + backgroundSize: + e.target + .value, + }, + ) + } + placeholder="cover, contain, 100%, etc." + /> +
    - {/* Mask Image */} -
    - - - handleImageBackgroundChange({ - maskImage: - e.target.value || undefined, - }) - } - placeholder="https://example.com/mask.svg" - /> -
    +
    + + + handleImageBackgroundChange( + { + backgroundPosition: + e.target + .value, + }, + ) + } + placeholder="center, top left, 50% 50%, etc." + /> +
    -
    + + handleImageBackgroundChange( + { + backgroundRepeat: + repeat as BackgroundRepeat, + }, + ) + } + options={ + BACKGROUND_REPEAT_OPTIONS + } + /> - {/* Overlay Settings */} -
    -

    - Overlay Settings -

    - - handleOverlayChange({ - color: color || "#000000", - }) - } - tooltip="Color of the overlay on top of the background image" - /> - - handleOverlayChange({ - blendMode: mode as BlendMode, - }) - } - options={BLEND_MODES} - /> - - handleOverlayChange({ - opacity: (opacity || 0) / 100, - }) - } - tooltip="Opacity of the overlay (0-100%)" - /> -
    -
    - )} + {/* Mask Image */} +
    + + + handleImageBackgroundChange( + { + maskImage: + e.target + .value || + undefined, + }, + ) + } + placeholder="https://example.com/mask.svg" + /> +
    +
    +
    +
    +
    - {/* Gradient Background Controls */} - {value.type === "gradient" && ( -
    -

    - Gradient Settings -

    + + {/* Gradient CSS */} +
    + + + handleGradientBackgroundChange({ + backgroundImage: + e.target.value, + }) + } + placeholder="linear-gradient(45deg, #ff0000, #0000ff)" + /> +

    + Enter CSS gradient syntax (e.g., + linear-gradient, radial-gradient) +

    +
    - {/* Gradient CSS */} -
    - - - handleGradientBackgroundChange({ - backgroundImage: e.target.value, - }) - } - placeholder="linear-gradient(45deg, #ff0000, #0000ff)" - /> -

    - Enter CSS gradient syntax (e.g., - linear-gradient, radial-gradient) -

    -
    + {/* Dark Mode Gradient */} +
    + + + handleGradientBackgroundChange({ + backgroundImageDark: + e.target.value || + undefined, + }) + } + placeholder="linear-gradient(45deg, #333333, #666666)" + /> +
    - {/* Dark Mode Gradient */} -
    - - - handleGradientBackgroundChange({ - backgroundImageDark: - e.target.value || undefined, - }) - } - placeholder="linear-gradient(45deg, #333333, #666666)" - /> -
    + {/* Advanced Settings */} + + + + Advanced + + + {/* Gradient Properties */} +
    + + + handleGradientBackgroundChange( + { + gradientBackgroundSize: + e.target + .value, + } as any, + ) + } + placeholder="cover, contain, 100%, etc." + /> +
    - {/* Gradient Properties */} -
    - - handleGradientBackgroundChange({ - backgroundSize: size, - }) - } - options={BACKGROUND_SIZE_OPTIONS} - /> - - handleGradientBackgroundChange({ - backgroundPosition: position, - }) - } - options={BACKGROUND_POSITION_OPTIONS} - /> -
    +
    + + + handleGradientBackgroundChange( + { + gradientBackgroundPosition: + e.target + .value, + } as any, + ) + } + placeholder="center, top left, 50% 50%, etc." + /> +
    - - handleGradientBackgroundChange({ - backgroundRepeat: - repeat as BackgroundRepeat, - }) - } - options={BACKGROUND_REPEAT_OPTIONS} - /> + + handleGradientBackgroundChange( + { + gradientBackgroundRepeat: + repeat as BackgroundRepeat, + } as any, + ) + } + options={ + BACKGROUND_REPEAT_OPTIONS + } + /> - {/* Mask Image */} -
    - - - handleGradientBackgroundChange({ - maskImage: - e.target.value || undefined, - }) - } - placeholder="https://example.com/mask.svg" - /> -
    + {/* Mask Image */} +
    + + + handleGradientBackgroundChange( + { + gradientMaskImage: + e.target + .value || + undefined, + } as any, + ) + } + placeholder="clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);" + /> +
    +
    +
    +
    +
    +
    - )} - - + + +
    ); } diff --git a/packages/page-blocks/src/blocks/hero/admin-widget.tsx b/packages/page-blocks/src/blocks/hero/admin-widget.tsx index 004451790..915ba77d3 100644 --- a/packages/page-blocks/src/blocks/hero/admin-widget.tsx +++ b/packages/page-blocks/src/blocks/hero/admin-widget.tsx @@ -76,7 +76,6 @@ export default function AdminWidget({ const [alignment, setAlignment] = useState(settings.alignment || "left"); const [media, setMedia] = useState>(settings.media || {}); - const [style, setStyle] = useState(settings.style || "normal"); const [secondaryButtonAction, setSecondaryButtonAction] = useState( settings.secondaryButtonAction, ); @@ -121,7 +120,6 @@ export default function AdminWidget({ youtubeLink, media, alignment, - style, mediaRadius: mediaBorderRadius, verticalPadding, secondaryButtonAction, @@ -146,7 +144,6 @@ export default function AdminWidget({ buttonCaption, youtubeLink, alignment, - style, media, mediaBorderRadius, verticalPadding, @@ -318,15 +315,6 @@ export default function AdminWidget({ - - + /> */} diff --git a/packages/page-blocks/src/blocks/hero/settings.ts b/packages/page-blocks/src/blocks/hero/settings.ts index 9a5245a6b..293c6412d 100644 --- a/packages/page-blocks/src/blocks/hero/settings.ts +++ b/packages/page-blocks/src/blocks/hero/settings.ts @@ -14,7 +14,6 @@ export default interface Settings extends WidgetDefaultSettings { media?: Media; youtubeLink?: string; alignment?: Alignment | "right"; - style: "card" | "normal"; mediaRadius?: number; secondaryButtonCaption?: string; secondaryButtonAction?: string; diff --git a/packages/page-blocks/src/blocks/hero/widget.tsx b/packages/page-blocks/src/blocks/hero/widget.tsx index 145438988..ac46b56ba 100644 --- a/packages/page-blocks/src/blocks/hero/widget.tsx +++ b/packages/page-blocks/src/blocks/hero/widget.tsx @@ -47,7 +47,6 @@ export default function Widget({ media, youtubeLink, alignment = "left", - style = "normal", mediaRadius = 2, verticalPadding, secondaryButtonAction, @@ -60,8 +59,10 @@ export default function Widget({ aspectRatio, objectFit, maxWidth, + background, }, state: { theme }, + nextTheme, }: WidgetProps) { const overiddenTheme: ThemeStyle = JSON.parse(JSON.stringify(theme.theme)); overiddenTheme.structure.page.width = @@ -83,14 +84,13 @@ export default function Widget({ } return ( -
    -
    +
    +
    {hasHeroGraphic && (
    ; - backgroundImage: string; - backgroundSize?: string; - backgroundPosition?: string; - backgroundRepeat?: BackgroundRepeat; - maskImage?: string; -} - -export interface GradientSectionBackground { - type: "gradient"; - backgroundImage: string; + backgroundImage?: string; backgroundImageDark?: string; backgroundSize?: string; backgroundPosition?: string; backgroundRepeat?: BackgroundRepeat; maskImage?: string; -} - -export type SectionBackground = - | ColorSectionBackground - | ImageSectionBackground - | GradientSectionBackground; + gradientBackgroundSize?: string; + gradientBackgroundPosition?: string; + gradientBackgroundRepeat?: BackgroundRepeat; + gradientMaskImage?: string; + blur?: number; + overlay?: SectionBackgroundOverlay; + media?: Record; +}; diff --git a/packages/page-primitives/src/section.tsx b/packages/page-primitives/src/section.tsx index 5f15bdd51..29a508782 100644 --- a/packages/page-primitives/src/section.tsx +++ b/packages/page-primitives/src/section.tsx @@ -1,30 +1,27 @@ import React from "react"; import { cn } from "./lib/utils"; -import type { ThemeStyle } from "@courselit/page-models"; +import type { SectionBackground, ThemeStyle } from "@courselit/page-models"; interface SectionProps extends React.HTMLAttributes { children: React.ReactNode; className?: string; theme?: ThemeStyle; component?: "header" | "footer" | "section"; - style?: Record; + background?: SectionBackground; + nextTheme?: "dark" | "light"; } export const Section: React.FC = ({ children, className = "", theme, - style, + background, + nextTheme, component = "section", ...props }) => { // const classes = cn(theme?.structure?.section?.verticalPadding, className); - const classes = cn("bg-background text-foreground", className); - const styleWithBackground = { - ...style, - backgroundColor: style?.backgroundColor, - color: style?.color, - }; + const classes = cn("bg-background text-foreground relative", className); return ( <> @@ -32,19 +29,110 @@ export const Section: React.FC = ({ component as React.ElementType, { className: classes, - style: styleWithBackground, ...props, }, -
    + {background && ( +
    )} - > - {children} -
    , + {background && background.type === "image" && ( +
    + )} + {background && background.type === "image" && ( +
    + )} +
    + {children} +
    + , )} ); diff --git a/packages/page-primitives/tsconfig.json b/packages/page-primitives/tsconfig.json index 1900be613..4035e8be3 100644 --- a/packages/page-primitives/tsconfig.json +++ b/packages/page-primitives/tsconfig.json @@ -3,7 +3,7 @@ "exclude": ["dist", "build", "node_modules"], "compilerOptions": { "outDir": "./dist", - "lib": ["ES2015"], + "lib": ["ES2020"], "strict": false, "paths": { "@/*": ["./src/*"], From fd6e2f822bcb2cb7079c3e92063b0114f2ea6c4a Mon Sep 17 00:00:00 2001 From: Rajat Date: Tue, 23 Sep 2025 17:54:13 +0000 Subject: [PATCH 4/8] Removed tooltips --- .../components-library/src/section-background-panel.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/components-library/src/section-background-panel.tsx b/packages/components-library/src/section-background-panel.tsx index 2eb4b6264..3cd4488e1 100644 --- a/packages/components-library/src/section-background-panel.tsx +++ b/packages/components-library/src/section-background-panel.tsx @@ -142,7 +142,6 @@ export function SectionBackgroundPanel({ color || "#ffffff", }) } - tooltip="Choose the background color for this section" /> @@ -212,7 +210,6 @@ export function SectionBackgroundPanel({ blur: blur || 0, }) } - tooltip="Blur effect to the background image" unit="" /> @@ -241,7 +238,6 @@ export function SectionBackgroundPanel({ color, }) } - tooltip="Color of the overlay on top of the background image" /> Date: Tue, 23 Sep 2025 19:37:11 +0000 Subject: [PATCH 5/8] UI improvements for background component --- apps/web/package.json | 4 +- .../components-library/src/color-selector.tsx | 21 ++- .../src/section-background-panel.tsx | 99 +++++++++-- pnpm-lock.yaml | 166 +++++++++++++++--- 4 files changed, 246 insertions(+), 44 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 2d4737928..6af3caae5 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -59,7 +59,7 @@ "lucide-react": "^0.475.0", "mongodb": "^6.15.0", "mongoose": "^8.13.1", - "next": "15.5.3", + "next": "^15.5.4", "next-auth": "^5.0.0-beta.29", "next-themes": "^0.4.6", "nodemailer": "^6.7.2", @@ -88,7 +88,7 @@ "@types/pug": "^2.0.6", "@types/react": "19.1.13", "eslint": "8.48.0", - "eslint-config-next": "15.5.3", + "eslint-config-next": "^15.5.4", "eslint-config-prettier": "^9.0.0", "postcss": "^8.4.27", "prettier": "^3.0.2", diff --git a/packages/components-library/src/color-selector.tsx b/packages/components-library/src/color-selector.tsx index 99e075237..648abe0c2 100644 --- a/packages/components-library/src/color-selector.tsx +++ b/packages/components-library/src/color-selector.tsx @@ -32,6 +32,7 @@ interface ColorSelectorProps tooltip?: string; className?: string; allowReset?: boolean; + description?: string; } export default function ColorSelector({ @@ -43,6 +44,7 @@ export default function ColorSelector({ size, className, allowReset = true, + description, }: ColorSelectorProps) { const [localValue, setLocalValue] = React.useState(value); @@ -76,12 +78,19 @@ export default function ColorSelector({
    -
    -

    {title}

    - {tooltip && ( - - - +
    +
    +

    {title}

    + {tooltip && ( + + + + )} +
    + {description && ( +

    + {description} +

    )}
    diff --git a/packages/components-library/src/section-background-panel.tsx b/packages/components-library/src/section-background-panel.tsx index 3cd4488e1..3750187bd 100644 --- a/packages/components-library/src/section-background-panel.tsx +++ b/packages/components-library/src/section-background-panel.tsx @@ -19,6 +19,7 @@ import { } from "./components/ui/accordion"; import MediaSelector from "./media-selector"; import { Address, Media, Profile } from "@courselit/common-models"; +import { Lightbulb } from "lucide-react"; interface SectionBackgroundPanelProps { value: SectionBackground; @@ -60,8 +61,15 @@ const BACKGROUND_REPEAT_OPTIONS: { label: string; value: BackgroundRepeat }[] = export function SectionBackgroundPanel({ value = { type: "color", - backgroundColor: "transparent", + backgroundColor: "#ff0000", backgroundColorDark: undefined, + blur: 5, + overlay: { + color: "#ff0000", + colorDark: undefined, + opacity: 3, + blendMode: "normal", + }, }, onChange, className, @@ -107,7 +115,7 @@ export function SectionBackgroundPanel({
    - + Background @@ -125,7 +133,7 @@ export function SectionBackgroundPanel({ Image - Gradient + Pattern @@ -134,7 +142,7 @@ export function SectionBackgroundPanel({ className="space-y-4 mt-6" > handleColorBackgroundChange({ @@ -152,6 +160,7 @@ export function SectionBackgroundPanel({ }) } allowReset={true} + description="Optional background color for dark mode" /> @@ -251,6 +260,7 @@ export function SectionBackgroundPanel({ }) } allowReset={true} + description="Optional overlay color for dark mode" />
    @@ -396,10 +414,32 @@ export function SectionBackgroundPanel({ value="gradient" className="space-y-4 mt-6" > +
    +

    + For advanced users who know CSS. +

    + {/*

    + You can find patterns on sites like {" "} + + PatternCraft and {" "} + + MagicPattern. +

    */} +
    {/* Gradient CSS */}
    -

    + {/*

    Enter CSS gradient syntax (e.g., linear-gradient, radial-gradient) -

    +

    */}
    {/* Dark Mode Gradient */}
    + +
    + +

    + You can find cool patterns on sites + like{" "} + + PatternCraft + {" "} + and{" "} + + MagicPattern + + . +

    +
    diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 27eca256a..06d212465 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -336,11 +336,11 @@ importers: specifier: ^8.13.1 version: 8.14.0(@aws-sdk/credential-providers@3.797.0)(socks@2.8.4) next: - specifier: 15.5.3 - version: 15.5.3(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^15.5.4 + version: 15.5.4(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-auth: specifier: ^5.0.0-beta.29 - version: 5.0.0-beta.29(next@15.5.3(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nodemailer@6.10.1)(react@18.3.1) + version: 5.0.0-beta.29(next@15.5.4(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nodemailer@6.10.1)(react@18.3.1) next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -418,8 +418,8 @@ importers: specifier: 8.48.0 version: 8.48.0 eslint-config-next: - specifier: 15.5.3 - version: 15.5.3(eslint@8.48.0)(typescript@4.9.5) + specifier: ^15.5.4 + version: 15.5.4(eslint@8.48.0)(typescript@4.9.5) eslint-config-prettier: specifier: ^9.0.0 version: 9.1.0(eslint@8.48.0) @@ -2710,8 +2710,11 @@ packages: '@next/env@15.5.3': resolution: {integrity: sha512-RSEDTRqyihYXygx/OJXwvVupfr9m04+0vH8vyy0HfZ7keRto6VX9BbEk0J2PUk0VGy6YhklJUSrgForov5F9pw==} - '@next/eslint-plugin-next@15.5.3': - resolution: {integrity: sha512-SdhaKdko6dpsSr0DldkESItVrnPYB1NS2NpShCSX5lc7SSQmLZt5Mug6t2xbiuVWEVDLZSuIAoQyYVBYp0dR5g==} + '@next/env@15.5.4': + resolution: {integrity: sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A==} + + '@next/eslint-plugin-next@15.5.4': + resolution: {integrity: sha512-SR1vhXNNg16T4zffhJ4TS7Xn7eq4NfKfcOsRwea7RIAHrjRpI9ALYbamqIJqkAhowLlERffiwk0FMvTLNdnVtw==} '@next/swc-darwin-arm64@15.5.3': resolution: {integrity: sha512-nzbHQo69+au9wJkGKTU9lP7PXv0d1J5ljFpvb+LnEomLtSbJkbZyEs6sbF3plQmiOB2l9OBtN2tNSvCH1nQ9Jg==} @@ -2719,48 +2722,96 @@ packages: cpu: [arm64] os: [darwin] + '@next/swc-darwin-arm64@15.5.4': + resolution: {integrity: sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + '@next/swc-darwin-x64@15.5.3': resolution: {integrity: sha512-w83w4SkOOhekJOcA5HBvHyGzgV1W/XvOfpkrxIse4uPWhYTTRwtGEM4v/jiXwNSJvfRvah0H8/uTLBKRXlef8g==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] + '@next/swc-darwin-x64@15.5.4': + resolution: {integrity: sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + '@next/swc-linux-arm64-gnu@15.5.3': resolution: {integrity: sha512-+m7pfIs0/yvgVu26ieaKrifV8C8yiLe7jVp9SpcIzg7XmyyNE7toC1fy5IOQozmr6kWl/JONC51osih2RyoXRw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + '@next/swc-linux-arm64-gnu@15.5.4': + resolution: {integrity: sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + '@next/swc-linux-arm64-musl@15.5.3': resolution: {integrity: sha512-u3PEIzuguSenoZviZJahNLgCexGFhso5mxWCrrIMdvpZn6lkME5vc/ADZG8UUk5K1uWRy4hqSFECrON6UKQBbQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + '@next/swc-linux-arm64-musl@15.5.4': + resolution: {integrity: sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + '@next/swc-linux-x64-gnu@15.5.3': resolution: {integrity: sha512-lDtOOScYDZxI2BENN9m0pfVPJDSuUkAD1YXSvlJF0DKwZt0WlA7T7o3wrcEr4Q+iHYGzEaVuZcsIbCps4K27sA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + '@next/swc-linux-x64-gnu@15.5.4': + resolution: {integrity: sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + '@next/swc-linux-x64-musl@15.5.3': resolution: {integrity: sha512-9vWVUnsx9PrY2NwdVRJ4dUURAQ8Su0sLRPqcCCxtX5zIQUBES12eRVHq6b70bbfaVaxIDGJN2afHui0eDm+cLg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + '@next/swc-linux-x64-musl@15.5.4': + resolution: {integrity: sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + '@next/swc-win32-arm64-msvc@15.5.3': resolution: {integrity: sha512-1CU20FZzY9LFQigRi6jM45oJMU3KziA5/sSG+dXeVaTm661snQP6xu3ykGxxwU5sLG3sh14teO/IOEPVsQMRfA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] + '@next/swc-win32-arm64-msvc@15.5.4': + resolution: {integrity: sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + '@next/swc-win32-x64-msvc@15.5.3': resolution: {integrity: sha512-JMoLAq3n3y5tKXPQwCK5c+6tmwkuFDa2XAxz8Wm4+IVthdBZdZGh+lmiLUHg9f9IDwIQpUjp+ysd6OkYTyZRZw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] + '@next/swc-win32-x64-msvc@15.5.4': + resolution: {integrity: sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -6253,8 +6304,8 @@ packages: engines: {node: '>=6.0'} hasBin: true - eslint-config-next@15.5.3: - resolution: {integrity: sha512-e6j+QhQFOr5pfsc8VJbuTD9xTXJaRvMHYjEeLPA2pFkheNlgPLCkxdvhxhfuM4KGcqSZj2qEnpHisdTVs3BxuQ==} + eslint-config-next@15.5.4: + resolution: {integrity: sha512-BzgVVuT3kfJes8i2GHenC1SRJ+W3BTML11lAOYFOOPzrk2xp66jBOAGEFRw+3LkYCln5UzvFsLhojrshb5Zfaw==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 typescript: ^4.9.5 @@ -8157,6 +8208,27 @@ packages: sass: optional: true + next@15.5.4: + resolution: {integrity: sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA==} + engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.51.1 + babel-plugin-react-compiler: '*' + react: ^18.3.1 + react-dom: ^18.3.1 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + nlcst-to-string@3.1.1: resolution: {integrity: sha512-63mVyqaqt0cmn2VcI2aH6kxe1rLAmSROqHMA0i4qqg1tidkfExgpb0FGMikMCn86mw5dFtBtEANfmSSK7TjNHw==} @@ -12538,40 +12610,66 @@ snapshots: '@napi-rs/wasm-runtime@0.2.9': dependencies: '@emnapi/core': 1.4.3 - '@emnapi/runtime': 1.4.3 + '@emnapi/runtime': 1.5.0 '@tybys/wasm-util': 0.9.0 optional: true '@next/env@15.5.3': {} - '@next/eslint-plugin-next@15.5.3': + '@next/env@15.5.4': {} + + '@next/eslint-plugin-next@15.5.4': dependencies: fast-glob: 3.3.1 '@next/swc-darwin-arm64@15.5.3': optional: true + '@next/swc-darwin-arm64@15.5.4': + optional: true + '@next/swc-darwin-x64@15.5.3': optional: true + '@next/swc-darwin-x64@15.5.4': + optional: true + '@next/swc-linux-arm64-gnu@15.5.3': optional: true + '@next/swc-linux-arm64-gnu@15.5.4': + optional: true + '@next/swc-linux-arm64-musl@15.5.3': optional: true + '@next/swc-linux-arm64-musl@15.5.4': + optional: true + '@next/swc-linux-x64-gnu@15.5.3': optional: true + '@next/swc-linux-x64-gnu@15.5.4': + optional: true + '@next/swc-linux-x64-musl@15.5.3': optional: true + '@next/swc-linux-x64-musl@15.5.4': + optional: true + '@next/swc-win32-arm64-msvc@15.5.3': optional: true + '@next/swc-win32-arm64-msvc@15.5.4': + optional: true + '@next/swc-win32-x64-msvc@15.5.3': optional: true + '@next/swc-win32-x64-msvc@15.5.4': + optional: true + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -17833,15 +17931,15 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-next@15.5.3(eslint@8.48.0)(typescript@4.9.5): + eslint-config-next@15.5.4(eslint@8.48.0)(typescript@4.9.5): dependencies: - '@next/eslint-plugin-next': 15.5.3 + '@next/eslint-plugin-next': 15.5.4 '@rushstack/eslint-patch': 1.11.0 '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint@8.48.0)(typescript@4.9.5) '@typescript-eslint/parser': 5.62.0(eslint@8.48.0)(typescript@4.9.5) eslint: 8.48.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint@8.48.0))(eslint@8.48.0) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.48.0) eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint-import-resolver-typescript@3.10.1)(eslint@8.48.0) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.48.0) eslint-plugin-react: 7.37.5(eslint@8.48.0) @@ -17869,7 +17967,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint@8.48.0))(eslint@8.48.0): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0)(eslint@8.48.0): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.0 @@ -17884,14 +17982,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint@8.48.0))(eslint@8.48.0))(eslint@8.48.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.48.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 5.62.0(eslint@8.48.0)(typescript@4.9.5) eslint: 8.48.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint@8.48.0))(eslint@8.48.0) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.48.0) transitivePeerDependencies: - supports-color @@ -17922,7 +18020,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.48.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint@8.48.0))(eslint@8.48.0))(eslint@8.48.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.48.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -18927,7 +19025,7 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.7.1 + semver: 7.7.2 is-callable@1.2.7: {} @@ -20407,10 +20505,10 @@ snapshots: transitivePeerDependencies: - supports-color - next-auth@5.0.0-beta.29(next@15.5.3(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nodemailer@6.10.1)(react@18.3.1): + next-auth@5.0.0-beta.29(next@15.5.4(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nodemailer@6.10.1)(react@18.3.1): dependencies: '@auth/core': 0.40.0(nodemailer@6.10.1) - next: 15.5.3(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 15.5.4(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 optionalDependencies: nodemailer: 6.10.1 @@ -20443,6 +20541,29 @@ snapshots: - '@babel/core' - babel-plugin-macros + next@15.5.4(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@next/env': 15.5.4 + '@swc/helpers': 0.5.15 + caniuse-lite: 1.0.30001715 + postcss: 8.4.31 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-jsx: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@18.3.1) + optionalDependencies: + '@next/swc-darwin-arm64': 15.5.4 + '@next/swc-darwin-x64': 15.5.4 + '@next/swc-linux-arm64-gnu': 15.5.4 + '@next/swc-linux-arm64-musl': 15.5.4 + '@next/swc-linux-x64-gnu': 15.5.4 + '@next/swc-linux-x64-musl': 15.5.4 + '@next/swc-win32-arm64-msvc': 15.5.4 + '@next/swc-win32-x64-msvc': 15.5.4 + sharp: 0.34.3 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + nlcst-to-string@3.1.1: dependencies: '@types/nlcst': 1.0.4 @@ -21768,8 +21889,7 @@ snapshots: semver@7.7.1: {} - semver@7.7.2: - optional: true + semver@7.7.2: {} send@0.19.0: dependencies: From b70a2491f288b24167cfc91ea01109ff5cab732f Mon Sep 17 00:00:00 2001 From: Rajat Date: Wed, 24 Sep 2025 10:32:33 +0000 Subject: [PATCH 6/8] Hack for dark theme --- packages/page-primitives/src/section.tsx | 10 +++++++++- packages/page-primitives/tsconfig.json | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/page-primitives/src/section.tsx b/packages/page-primitives/src/section.tsx index 29a508782..59720141b 100644 --- a/packages/page-primitives/src/section.tsx +++ b/packages/page-primitives/src/section.tsx @@ -34,6 +34,7 @@ export const Section: React.FC = ({ <> {background && (
    = ({ theme?.structure?.section?.padding?.x || "px-4", theme?.structure?.section?.padding?.y || "py-4", )} - style={{}} > + {" "} + {/** This is used to force re-render the component when the theme changes */} {children}
    , diff --git a/packages/page-primitives/tsconfig.json b/packages/page-primitives/tsconfig.json index 4035e8be3..60449f8c5 100644 --- a/packages/page-primitives/tsconfig.json +++ b/packages/page-primitives/tsconfig.json @@ -3,7 +3,7 @@ "exclude": ["dist", "build", "node_modules"], "compilerOptions": { "outDir": "./dist", - "lib": ["ES2020"], + "lib": ["dom","ES2020"], "strict": false, "paths": { "@/*": ["./src/*"], From 917c40c0c6fcc3aa24508088791351c25f3cd8a4 Mon Sep 17 00:00:00 2001 From: Rajat Date: Wed, 24 Sep 2025 10:33:05 +0000 Subject: [PATCH 7/8] Lint fix --- packages/page-primitives/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/page-primitives/tsconfig.json b/packages/page-primitives/tsconfig.json index 60449f8c5..70f9602bd 100644 --- a/packages/page-primitives/tsconfig.json +++ b/packages/page-primitives/tsconfig.json @@ -3,7 +3,7 @@ "exclude": ["dist", "build", "node_modules"], "compilerOptions": { "outDir": "./dist", - "lib": ["dom","ES2020"], + "lib": ["dom", "ES2020"], "strict": false, "paths": { "@/*": ["./src/*"], From f946ab56d5d8fc365530dca7a28f52348136991c Mon Sep 17 00:00:00 2001 From: Rajat Date: Wed, 24 Sep 2025 15:38:37 +0000 Subject: [PATCH 8/8] section overflow fix --- packages/page-primitives/src/section.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/page-primitives/src/section.tsx b/packages/page-primitives/src/section.tsx index 59720141b..a6a70cab0 100644 --- a/packages/page-primitives/src/section.tsx +++ b/packages/page-primitives/src/section.tsx @@ -124,7 +124,7 @@ export const Section: React.FC = ({ )}