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 */}
+
+
+ Background Size
+
+
+ handleImageBackgroundChange(
+ {
+ backgroundSize:
+ e.target
+ .value,
+ },
+ )
+ }
+ placeholder="cover, contain, 100%, etc."
+ />
+
+
+
+
+ Background Position
+
+
+ handleImageBackgroundChange(
+ {
+ backgroundPosition:
+ e.target
+ .value,
+ },
+ )
+ }
+ placeholder="center, top left, 50% 50%, etc."
+ />
+
+
+
+ handleImageBackgroundChange(
+ {
+ backgroundRepeat:
+ repeat as BackgroundRepeat,
+ },
+ )
+ }
+ options={
+ BACKGROUND_REPEAT_OPTIONS
+ }
+ />
+
+ {/* Mask Image */}
+
+
+ Mask Image{" "}
+
+ Learn more
+
+
+
+ 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 */}
+
+
+ Background Image
+
+
+ handleGradientBackgroundChange({
+ backgroundImage:
+ e.target.value,
+ })
+ }
+ placeholder="linear-gradient(45deg, #ff0000, #0000ff)"
+ />
+ {/*
+ Enter CSS gradient syntax (e.g.,
+ linear-gradient, radial-gradient)
+
*/}
+
+
+ {/* Dark Mode Gradient */}
+
+
+ Dark Mode Background Image
+
+
+ handleGradientBackgroundChange({
+ backgroundImageDark:
+ e.target.value ||
+ undefined,
+ })
+ }
+ placeholder="linear-gradient(45deg, #333333, #666666)"
+ />
+
+
+ {/* Advanced Settings */}
+
+
+
+ Advanced
+
+
+ {/* Gradient Properties */}
+
+
+ Background Size
+
+
+ handleGradientBackgroundChange(
+ {
+ gradientBackgroundSize:
+ e.target
+ .value,
+ } as any,
+ )
+ }
+ placeholder="cover, contain, 100%, etc."
+ />
+
+
+
+
+ Background Position
+
+
+ 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 */}
+
+
+ Mask Image{" "}
+
+ Learn more
+
+
+
+ handleGradientBackgroundChange(
+ {
+ gradientMaskImage:
+ e.target
+ .value ||
+ undefined,
+ } as any,
+ )
+ }
+ placeholder="linear-gradient(black, transparent)"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
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({
- setStyle(value)}
- />
-
+ /> */}
+
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" && (
+
+ )}
+
+
+ {nextTheme}
+
{" "}
+ {/** 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: