"use client"; import { ColorPicker as SpectrumColorPicker, parseColor, Color, ColorThumb, ColorSlider, Input, ColorField, SliderTrack, ColorSwatch, } from "react-aria-components"; import { Checkbox } from "components/Checkbox"; import { useMemo, useState } from "react"; import { ReplicacheMutators, useEntity, useReplicache } from "src/replicache"; import { useColorAttribute } from "components/ThemeManager/useColorAttribute"; import { Separator } from "components/Layout"; import { onMouseDown } from "src/utils/iosInputMouseDown"; import { pickers, setColorAttribute } from "../ThemeSetter"; import { ImageInput, ImageSettings } from "./ImagePicker"; import { ColorPicker, thumbStyle } from "./ColorPicker"; import { BlockImageSmall } from "components/Icons/BlockImageSmall"; import { Replicache } from "replicache"; import { CanvasBackgroundPattern } from "components/Canvas"; import { Toggle } from "components/Toggle"; import { DeleteSmall } from "components/Icons/DeleteSmall"; export const PageThemePickers = (props: { entityID: string; openPicker: pickers; setOpenPicker: (thisPicker: pickers) => void; }) => { let { rep } = useReplicache(); let set = useMemo(() => { return setColorAttribute(rep, props.entityID); }, [rep, props.entityID]); let pageType = useEntity(props.entityID, "page/type")?.data.value || "doc"; let primaryValue = useColorAttribute(props.entityID, "theme/primary"); return (
{pageType === "canvas" && ( <> {" "}
)}
); }; // Page background picker for subpages - shows Page/Containers color with optional background image export const SubpageBackgroundPicker = (props: { entityID: string; openPicker: pickers; setOpenPicker: (p: pickers) => void; }) => { let { rep, rootEntity } = useReplicache(); let set = useMemo(() => { return setColorAttribute(rep, props.entityID); }, [rep, props.entityID]); let pageValue = useColorAttribute(props.entityID, "theme/card-background"); let pageBGImage = useEntity(props.entityID, "theme/card-background-image"); let rootPageBorderHidden = useEntity(rootEntity, "theme/card-border-hidden"); let entityPageBorderHidden = useEntity( props.entityID, "theme/card-border-hidden", ); let pageBorderHidden = (entityPageBorderHidden || rootPageBorderHidden)?.data.value || false; let hasPageBackground = !pageBorderHidden; // Label is "Page" when page background is visible, "Containers" when hidden let label = hasPageBackground ? "Page" : "Containers"; // If root page border is hidden, only show color picker (no image support) if (!hasPageBackground) { return ( props.setOpenPicker("null")} alpha /> ); } return ( <> {pageBGImage && ( )}
props.setOpenPicker("null")} alpha /> {!pageBGImage && ( )}
); }; const SubpageBackgroundImagePicker = (props: { entityID: string; openPicker: pickers; setOpenPicker: (p: pickers) => void; setValue: (c: Color) => void; }) => { let { rep } = useReplicache(); let bgImage = useEntity(props.entityID, "theme/card-background-image"); let bgRepeat = useEntity( props.entityID, "theme/card-background-image-repeat", ); let bgColor = useColorAttribute(props.entityID, "theme/card-background"); let bgAlpha = useEntity(props.entityID, "theme/card-background-image-opacity")?.data .value || 1; let alphaColor = useMemo(() => { return parseColor(`rgba(0,0,0,${bgAlpha})`); }, [bgAlpha]); let open = props.openPicker === "page-background-image"; return ( <>
{ let alpha = c.getChannelValue("alpha"); rep?.mutate.assertFact({ entity: props.entityID, attribute: "theme/card-background-image-opacity", data: { type: "number", value: alpha }, }); }} > { e.currentTarget.setSelectionRange( 0, e.currentTarget.value.length - 1, ); }} onKeyDown={(e) => { if (e.key === "Enter") { e.currentTarget.blur(); } else return; }} className="w-[48px] bg-transparent outline-hidden" />
{open && (

{ let alpha = c.getChannelValue("alpha"); rep?.mutate.assertFact({ entity: props.entityID, attribute: "theme/card-background-image-opacity", data: { type: "number", value: alpha }, }); }} >
)} ); }; // Unified background picker for leaflets - matches structure of BackgroundPicker for publications export const LeafletBackgroundPicker = (props: { entityID: string; openPicker: pickers; setOpenPicker: (p: pickers) => void; }) => { let { rep } = useReplicache(); let set = useMemo(() => { return setColorAttribute(rep, props.entityID); }, [rep, props.entityID]); let leafletBgValue = useColorAttribute( props.entityID, "theme/page-background", ); let pageValue = useColorAttribute(props.entityID, "theme/card-background"); let leafletBGImage = useEntity(props.entityID, "theme/background-image"); let leafletBGRepeat = useEntity( props.entityID, "theme/background-image-repeat", ); let pageBorderHidden = useEntity(props.entityID, "theme/card-border-hidden"); let hasPageBackground = !pageBorderHidden?.data.value; // When page background is hidden and no background image, only show the Background picker let showPagePicker = hasPageBackground || !!leafletBGImage; return ( <> {/* Background color/image picker */} {leafletBGImage ? ( ) : (
props.setOpenPicker("null")} />
)} {/* Page/Containers color picker - only shown when page background is visible OR there's a bg image */} {showPagePicker && ( props.setOpenPicker("null")} alpha /> )}
{/* Page Background toggle */} ); }; const LeafletBackgroundImagePicker = (props: { entityID: string; openPicker: pickers; setOpenPicker: (p: pickers) => void; }) => { let { rep } = useReplicache(); let bgImage = useEntity(props.entityID, "theme/background-image"); let bgRepeat = useEntity(props.entityID, "theme/background-image-repeat"); let bgColor = useColorAttribute(props.entityID, "theme/page-background"); let open = props.openPicker === "leaflet"; return ( <>
{open && (
{}} />
)} ); }; export const PageBackgroundColorPicker = (props: { disabled?: boolean; label: string; openPicker: pickers; thisPicker: pickers; setOpenPicker: (thisPicker: pickers) => void; setValue: (c: Color) => void; value: Color; alpha?: boolean; helpText?: string; }) => { return ( props.setOpenPicker("null")} alpha={props.alpha} /> ); }; export const PageBackgroundImagePicker = (props: { disabled?: boolean; entityID: string; openPicker: pickers; thisPicker: pickers; setOpenPicker: (thisPicker: pickers) => void; closePicker: () => void; setValue: (c: Color) => void; home?: boolean; }) => { let bgImage = useEntity(props.entityID, "theme/card-background-image"); let bgRepeat = useEntity( props.entityID, "theme/card-background-image-repeat", ); let bgColor = useColorAttribute(props.entityID, "theme/card-background"); let bgAlpha = useEntity(props.entityID, "theme/card-background-image-opacity")?.data .value || 1; let alphaColor = useMemo(() => { return parseColor(`rgba(0,0,0,${bgAlpha})`); }, [bgAlpha]); let open = props.openPicker == props.thisPicker; let { rep } = useReplicache(); return ( <>
{ let alpha = c.getChannelValue("alpha"); rep?.mutate.assertFact({ entity: props.entityID, attribute: "theme/card-background-image-opacity", data: { type: "number", value: alpha }, }); }} > { e.currentTarget.setSelectionRange( 0, e.currentTarget.value.length - 1, ); }} onKeyDown={(e) => { if (e.key === "Enter") { e.currentTarget.blur(); } else return; }} className={`w-[48px] bg-transparent outline-hidden disabled:text-[#969696]`} />
{open && (

{ let alpha = c.getChannelValue("alpha"); rep?.mutate.assertFact({ entity: props.entityID, attribute: "theme/card-background-image-opacity", data: { type: "number", value: alpha }, }); }} >
)} ); }; const CanvasBGPatternPicker = (props: { entityID: string; rep: Replicache | null; }) => { let selectedPattern = useEntity(props.entityID, "canvas/background-pattern") ?.data.value; return (
); }; export const TextPickers = (props: { openPicker: pickers; setOpenPicker: (thisPicker: pickers) => void; value: Color; setValue: (c: Color) => void; }) => { return ( props.setOpenPicker("null")} /> ); }; export const PageBorderHider = (props: { entityID: string; setOpenPicker: (p: pickers) => void; openPicker: pickers; }) => { let { rep, rootEntity } = useReplicache(); let rootPageBorderHidden = useEntity(rootEntity, "theme/card-border-hidden"); let entityPageBorderHidden = useEntity( props.entityID, "theme/card-border-hidden", ); let pageBorderHidden = (entityPageBorderHidden || rootPageBorderHidden)?.data.value || false; function handleToggle() { rep?.mutate.assertFact({ entity: props.entityID, attribute: "theme/card-border-hidden", data: { type: "boolean", value: !pageBorderHidden }, }); (pageBorderHidden && props.openPicker === "page") || (props.openPicker === "page-background-image" && props.setOpenPicker("null")); } return ( <> { handleToggle(); }} disabledColor1="#8C8C8C" disabledColor2="#DBDBDB" >
Page Background
{pageBorderHidden ? "none" : ""}
); };