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/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/apps/web/package.json b/apps/web/package.json index 0d18cc39f..6af3caae5 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.4", + "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.4", + "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" + } } - } } 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/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/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/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 new file mode 100644 index 000000000..3750187bd --- /dev/null +++ b/packages/components-library/src/section-background-panel.tsx @@ -0,0 +1,633 @@ +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 { 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"; +import { Lightbulb } from "lucide-react"; + +interface SectionBackgroundPanelProps { + value: SectionBackground; + onChange: (value: SectionBackground) => void; + className?: string; + profile: Profile; + address: Address; +} + +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" }, + ]; + +export function SectionBackgroundPanel({ + value = { + type: "color", + backgroundColor: "#ff0000", + backgroundColorDark: undefined, + blur: 5, + overlay: { + color: "#ff0000", + colorDark: undefined, + opacity: 3, + blendMode: "normal", + }, + }, + onChange, + className, + profile, + address, +}: SectionBackgroundPanelProps) { + const handleTypeChange = (type: SectionBackground["type"]) => { + // Simply change the type while preserving all existing properties + onChange({ + ...value, + type, + }); + }; + + const handleColorBackgroundChange = ( + updates: Partial, + ) => { + onChange({ ...value, ...updates }); + }; + + const handleImageBackgroundChange = ( + updates: Partial, + ) => { + onChange({ ...value, ...updates }); + }; + + const handleGradientBackgroundChange = ( + updates: Partial, + ) => { + onChange({ ...value, ...updates }); + }; + + const handleOverlayChange = ( + overlayUpdates: Partial, + ) => { + onChange({ + ...value, + overlay: { ...value.overlay, ...overlayUpdates }, + }); + }; + + return ( +
    + + + + Background + + +
    + + + + Color + + + Image + + + Pattern + + + + + + handleColorBackgroundChange({ + backgroundColor: + color || "#ffffff", + }) + } + /> + + handleColorBackgroundChange({ + backgroundColorDark: color, + }) + } + allowReset={true} + description="Optional background color for dark mode" + /> + + + + { + 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" + /> + + {/* Blur Effect */} + + handleImageBackgroundChange({ + blur: blur || 0, + }) + } + unit="" + /> + + {/* Overlay Settings */} + + + + Overlay Settings + + + + handleOverlayChange({ + color, + }) + } + /> + + handleOverlayChange({ + colorDark: color, + }) + } + allowReset={true} + description="Optional overlay color for dark mode" + /> + + handleOverlayChange({ + opacity, + }) + } + unit="" + /> + + handleOverlayChange({ + blendMode: + mode as BlendMode, + }) + } + options={BLEND_MODES} + /> + + + + + {/* Advanced Settings */} + + + + Advanced + + + {/* Image Properties */} +
    + + + handleImageBackgroundChange( + { + backgroundSize: + e.target + .value, + }, + ) + } + placeholder="cover, contain, 100%, etc." + /> +
    + +
    + + + handleImageBackgroundChange( + { + backgroundPosition: + e.target + .value, + }, + ) + } + placeholder="center, top left, 50% 50%, etc." + /> +
    + + + handleImageBackgroundChange( + { + backgroundRepeat: + repeat as BackgroundRepeat, + }, + ) + } + options={ + BACKGROUND_REPEAT_OPTIONS + } + /> + + {/* Mask Image */} +
    + + + handleImageBackgroundChange( + { + maskImage: + e.target + .value || + undefined, + }, + ) + } + placeholder="linear-gradient(black, transparent)" + /> +
    +
    +
    +
    +
    + + +
    +

    + For advanced users who know CSS. +

    + {/*

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

    */} +
    + {/* 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)" + /> +
    + + {/* Advanced Settings */} + + + + Advanced + + + {/* Gradient Properties */} +
    + + + handleGradientBackgroundChange( + { + gradientBackgroundSize: + e.target + .value, + } as any, + ) + } + placeholder="cover, contain, 100%, etc." + /> +
    + +
    + + + handleGradientBackgroundChange( + { + gradientBackgroundPosition: + e.target + .value, + } as any, + ) + } + placeholder="center, top left, 50% 50%, etc." + /> +
    + + + handleGradientBackgroundChange( + { + gradientBackgroundRepeat: + repeat as BackgroundRepeat, + } as any, + ) + } + options={ + BACKGROUND_REPEAT_OPTIONS + } + /> + + {/* Mask Image */} +
    + + + handleGradientBackgroundChange( + { + gradientMaskImage: + e.target + .value || + undefined, + } as any, + ) + } + placeholder="linear-gradient(black, transparent)" + /> +
    +
    +
    +
    + +
    + +

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

    +
    +
    +
    +
    +
    +
    +
    +
    + ); +} diff --git a/packages/page-blocks/src/blocks/hero/admin-widget.tsx b/packages/page-blocks/src/blocks/hero/admin-widget.tsx index 904fd5ed9..915ba77d3 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"; @@ -75,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, ); @@ -107,6 +107,9 @@ export default function AdminWidget({ const [maxWidth, setMaxWidth] = useState< ThemeStyle["structure"]["page"]["width"] >(settings.maxWidth); + const [background, setBackground] = useState( + settings.background, + ); const onSettingsChanged = () => onChange({ @@ -117,7 +120,6 @@ export default function AdminWidget({ youtubeLink, media, alignment, - style, mediaRadius: mediaBorderRadius, verticalPadding, secondaryButtonAction, @@ -130,6 +132,7 @@ export default function AdminWidget({ aspectRatio, objectFit, maxWidth, + background, }); useEffect(() => { @@ -141,7 +144,6 @@ export default function AdminWidget({ buttonCaption, youtubeLink, alignment, - style, media, mediaBorderRadius, verticalPadding, @@ -155,6 +157,7 @@ export default function AdminWidget({ aspectRatio, objectFit, maxWidth, + background, ]); return ( @@ -312,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 && (
    ; +}; diff --git a/packages/page-primitives/src/section.tsx b/packages/page-primitives/src/section.tsx index 5f15bdd51..a6a70cab0 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,118 @@ export const Section: React.FC = ({ component as React.ElementType, { className: classes, - style: styleWithBackground, ...props, }, -
    + {background && ( +
    )} - > - {children} -
    , + {background && background.type === "image" && ( +
    + )} + {background && background.type === "image" && ( +
    + )} +
    + {" "} + {/** 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 1900be613..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": ["ES2015"], + "lib": ["dom", "ES2020"], "strict": false, "paths": { "@/*": ["./src/*"], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb2d195d5..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 @@ -8076,6 +8127,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==} @@ -8156,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==} @@ -12537,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 @@ -17832,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) @@ -17868,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 @@ -17883,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 @@ -17921,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 @@ -18926,7 +19025,7 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.7.1 + semver: 7.7.2 is-callable@1.2.7: {} @@ -20406,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 @@ -20442,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 @@ -21767,8 +21889,7 @@ snapshots: semver@7.7.1: {} - semver@7.7.2: - optional: true + semver@7.7.2: {} send@0.19.0: dependencies: