@oberoncms/core
Version:
OberonCMS is a cloud deployable CMS written in typescript based on the Puck visual editor
193 lines (192 loc) • 5.48 kB
JavaScript
"use client";
import { jsxs, jsx } from "react/jsx-runtime";
import "@puckeditor/core/puck.css";
import { Puck } from "@puckeditor/core";
import { useState } from "react";
import { Button } from "@tohuhono/ui/button";
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem } from "@tohuhono/ui/dropdown-menu";
import { cn, isValidKey } from "@tohuhono/utils";
import { WidthIcon, DesktopIcon, LaptopIcon, MobileIcon, SunIcon, MoonIcon } from "../../node_modules/.pnpm/@radix-ui_react-icons@1.3.2_react@19.2.4/node_modules/@radix-ui/react-icons/dist/react-icons.esm.js";
import { useFitZoom } from "../../hooks/use-fit-zoom.js";
const viewPorts = {
small: {
width: 360,
height: "auto",
icon: MobileIcon,
label: "Small"
},
medium: {
width: 768,
height: "auto",
icon: LaptopIcon,
label: "Medium"
},
large: {
width: 1280,
height: "auto",
icon: DesktopIcon,
label: "Large"
},
full: {
width: "100%",
height: "auto",
icon: WidthIcon,
label: "Full-width"
}
};
const previewModes = {
follow: "Follow",
light: "Light",
dark: "Dark"
};
const useViewPort = () => {
const [currentViewport, setCurrentViewport] = useState("full");
return { currentViewport, setCurrentViewport };
};
const ViewPortSwitcher = ({
currentViewport,
setCurrentViewport
}) => {
return /* @__PURE__ */ jsx("div", { role: "group", "aria-label": "Viewport size", className: "flex flex-row", children: Object.entries(viewPorts).map(([value, { label, icon: Icon }]) => {
const isSelected = currentViewport === value;
return /* @__PURE__ */ jsxs(
Button,
{
title: label,
"aria-label": label,
"aria-selected": isSelected,
variant: "ghost",
size: "sm",
onClick: () => {
if (isValidKey(value, viewPorts)) {
setCurrentViewport(value);
}
},
children: [
/* @__PURE__ */ jsx(Icon, {}),
/* @__PURE__ */ jsx("span", { className: "sr-only", children: label })
]
},
value
);
}) });
};
const PreviewModeSwitcher = ({
previewMode,
setPreviewMode
}) => {
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
Button,
{
variant: "outline",
size: "sm",
className: "align-middle",
"aria-label": "Preview mode",
children: [
/* @__PURE__ */ jsx(
SunIcon,
{
className: cn(
"scale-100 rotate-0 transition-all",
previewMode === "follow" && "dark:scale-0 dark:-rotate-90",
previewMode === "dark" && "scale-0 -rotate-90"
)
}
),
/* @__PURE__ */ jsx(
MoonIcon,
{
className: cn(
"absolute scale-0 rotate-90 transition-all",
previewMode === "follow" && "dark:scale-100 dark:rotate-0",
previewMode === "dark" && "scale-100 rotate-0"
)
}
),
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Preview Theme switcher" })
]
}
) }),
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", children: /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
/* @__PURE__ */ jsx(
DropdownMenuItem,
{
"aria-selected": previewMode === "light",
onClick: () => {
setPreviewMode("light");
},
children: previewModes.light
}
),
/* @__PURE__ */ jsx(
DropdownMenuItem,
{
"aria-selected": previewMode === "dark",
onClick: () => {
setPreviewMode("dark");
},
children: previewModes.dark
}
),
/* @__PURE__ */ jsx(
DropdownMenuItem,
{
"aria-selected": previewMode === "follow",
onClick: () => {
setPreviewMode("follow");
},
children: previewModes.follow
}
)
] }) })
] });
};
const PreviewHeading = ({
currentViewport,
setCurrentViewport,
previewMode,
setPreviewMode,
className
}) => {
return /* @__PURE__ */ jsxs("div", { className, children: [
/* @__PURE__ */ jsx(
ViewPortSwitcher,
{
currentViewport,
setCurrentViewport
}
),
/* @__PURE__ */ jsx(
PreviewModeSwitcher,
{
previewMode,
setPreviewMode
}
)
] });
};
const Preview = ({
currentViewport,
className
}) => {
const currentViewportWidth = viewPorts[currentViewport].width;
const { ref, scale, scaledHeight } = useFitZoom(currentViewportWidth);
return /* @__PURE__ */ jsx("div", { className: cn(className, "overflow-hidden"), children: /* @__PURE__ */ jsx("div", { ref, className: "size-full", children: /* @__PURE__ */ jsx(
"div",
{
className: "\n mx-auto h-full origin-top-left overflow-hidden bg-background\n shadow-[0_0_3px_1px] shadow-foreground\n ",
style: {
width: currentViewportWidth,
height: scaledHeight,
transform: `scale(${scale})`
},
children: /* @__PURE__ */ jsx(Puck.Preview, { id: "preview-frame" })
}
) }) });
};
export {
Preview,
PreviewHeading,
useViewPort
};