UNPKG

@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
"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 };