···1212import { AddLeafletToHomepage } from "components/utils/AddLeafletToHomepage";
1313import { UpdateLeafletTitle } from "components/utils/UpdateLeafletTitle";
1414import { useUIState } from "src/useUIState";
1515-import { LeafletSidebar } from "./Sidebar";
1615import { LeafletLayout } from "components/LeafletLayout";
17161817export function Leaflet(props: {
···3736 <SelectionManager />
3837 {/* we need the padding bottom here because if we don't have it the mobile footer will cut off...
3938 the dropshadow on the page... the padding is compensated by a negative top margin in mobile footer */}
4040- <LeafletLayout className="!pb-[70px] sm:!pb-6">
3939+ <LeafletLayout className="!pb-[64px] sm:!pb-6">
4140 <Pages rootPage={props.leaflet_id} />
4241 </LeafletLayout>
4342 <LeafletFooter entityID={props.leaflet_id} />
···2020 let highlights = activeHighlight ? [activeHighlight] : [];
2121 let decodedQuote = quote ? decodeQuotePosition(quote as string) : null;
2222 if (decodedQuote) highlights.push(decodedQuote);
2323- console.log(highlights);
2423 return highlights
2524 .map((quotePosition) => {
2625 if (!quotePosition) return null;
+2-3
components/LeafletLayout.tsx
···1111 flex items-stretch grow`}
1212 id="page-carousel"
1313 >
1414- {/* if you adjust this padding, remember to adjust the negative margins on page
1515- in [rkey]/page/PostPage when card borders are hidden */}
1414+ {/* if you adjust this padding, remember to adjust the negative margins on page in components/Pages/Page.tsx in pageScrollWrapper when card borders are hidden */}
1615 <div
1716 id="pages"
1817 className={`pagesWrapper
···2827 );
2928};
30293131-export const BookendSpacers = (props: {
3030+export const BookendSpacer = (props: {
3231 onClick?: (e: React.MouseEvent) => void;
3332 children?: React.ReactNode;
3433}) => {
+200
components/Pages/Page.tsx
···11+"use client";
22+33+import React from "react";
44+import { useUIState } from "src/useUIState";
55+66+import { elementId } from "src/utils/elementId";
77+88+import { useEntity, useReferenceToEntity, useReplicache } from "src/replicache";
99+1010+import { DesktopPageFooter } from "../DesktopFooter";
1111+import { Canvas } from "../Canvas";
1212+import { Blocks } from "components/Blocks";
1313+import { PublicationMetadata } from "./PublicationMetadata";
1414+import { useCardBorderHidden } from "./useCardBorderHidden";
1515+import { focusPage } from ".";
1616+import { PageOptions } from "./PageOptions";
1717+import { CardThemeProvider } from "components/ThemeManager/ThemeProvider";
1818+1919+export function Page(props: {
2020+ entityID: string;
2121+ first?: boolean;
2222+ fullPageScroll: boolean;
2323+}) {
2424+ let { rep } = useReplicache();
2525+2626+ let isFocused = useUIState((s) => {
2727+ let focusedElement = s.focusedEntity;
2828+ let focusedPageID =
2929+ focusedElement?.entityType === "page"
3030+ ? focusedElement.entityID
3131+ : focusedElement?.parent;
3232+ return focusedPageID === props.entityID;
3333+ });
3434+ let pageType = useEntity(props.entityID, "page/type")?.data.value || "doc";
3535+ let cardBorderHidden = useCardBorderHidden(props.entityID);
3636+ return (
3737+ <CardThemeProvider entityID={props.entityID}>
3838+ <PageWrapper
3939+ onClickAction={(e) => {
4040+ if (e.defaultPrevented) return;
4141+ if (rep) {
4242+ if (isFocused) return;
4343+ focusPage(props.entityID, rep);
4444+ }
4545+ }}
4646+ id={elementId.page(props.entityID).container}
4747+ cardBorderHidden={!!cardBorderHidden}
4848+ isFocused={isFocused}
4949+ fullPageScroll={props.fullPageScroll}
5050+ pageType={pageType}
5151+ pageOptions={
5252+ <PageOptions
5353+ entityID={props.entityID}
5454+ first={props.first}
5555+ isFocused={isFocused}
5656+ />
5757+ }
5858+ >
5959+ {props.first && (
6060+ <>
6161+ <PublicationMetadata cardBorderHidden={!!cardBorderHidden} />
6262+ </>
6363+ )}
6464+ <PageContent entityID={props.entityID} />
6565+ </PageWrapper>
6666+ <DesktopPageFooter pageID={props.entityID} />
6767+ </CardThemeProvider>
6868+ );
6969+}
7070+7171+export const PageWrapper = (props: {
7272+ children: React.ReactNode;
7373+ pageOptions?: React.ReactNode;
7474+ id: string;
7575+ cardBorderHidden: boolean;
7676+ fullPageScroll: boolean;
7777+ isFocused?: boolean;
7878+ onClickAction?: (e: React.MouseEvent) => void;
7979+ pageType?: "canvas" | "doc";
8080+}) => {
8181+ return (
8282+ // this div wraps the contents AND the page options.
8383+ // it needs to be its own div because this container does NOT scroll, and therefore doesn't clip the absolutely positioned pageOptions
8484+ <div
8585+ className={`pageWrapper relative shrink-0 ${props.fullPageScroll ? "w-full" : "w-max"}`}
8686+ >
8787+ {/*
8888+ this div is the scrolling container that wraps only the contents div.
8989+9090+ it needs to be a separate div so that the user can scroll from anywhere on the page if there isn't a card border
9191+ */}
9292+ <div
9393+ onClick={props.onClickAction}
9494+ id={props.id}
9595+ className={`
9696+ pageScrollWrapper
9797+ grow
9898+ w-[10000px] sm:mx-0
9999+ shrink-0 snap-center
100100+ overflow-y-scroll
101101+ ${
102102+ !props.cardBorderHidden &&
103103+ `h-full rounded-lg border
104104+ bg-[rgba(var(--bg-page),var(--bg-page-alpha))]
105105+ ${props.isFocused ? "shadow-md border-border" : "border-border-light"}`
106106+ }
107107+ ${props.cardBorderHidden && "sm:h-[calc(100%+48px)] h-[calc(100%+20px)] sm:-my-6 -my-3 sm:pt-6 pt-3"}
108108+ }
109109+ ${props.fullPageScroll ? "max-w-full" : "max-w-[var(--page-width-units)]"}
110110+ `}
111111+ >
112112+ {/* this div controls the width of the content*/}
113113+ <div
114114+ className={`postPageContent mx-auto h-fit w-full
115115+ ${props.pageType === "canvas" ? "!lg:max-w-[1152px]" : "sm:max-w-[var(--page-width-units)]"}
116116+ `}
117117+ >
118118+ {props.children}
119119+ </div>
120120+ </div>
121121+ {props.pageOptions}
122122+ </div>
123123+ );
124124+};
125125+126126+const PageContent = (props: { entityID: string }) => {
127127+ let pageType = useEntity(props.entityID, "page/type")?.data.value || "doc";
128128+ if (pageType === "doc") return <DocContent entityID={props.entityID} />;
129129+ return <Canvas entityID={props.entityID} />;
130130+};
131131+132132+const DocContent = (props: { entityID: string }) => {
133133+ let { rootEntity } = useReplicache();
134134+135135+ let cardBorderHidden = useCardBorderHidden(props.entityID);
136136+ let rootBackgroundImage = useEntity(
137137+ rootEntity,
138138+ "theme/card-background-image",
139139+ );
140140+ let rootBackgroundRepeat = useEntity(
141141+ rootEntity,
142142+ "theme/card-background-image-repeat",
143143+ );
144144+ let rootBackgroundOpacity = useEntity(
145145+ rootEntity,
146146+ "theme/card-background-image-opacity",
147147+ );
148148+149149+ let cardBackgroundImage = useEntity(
150150+ props.entityID,
151151+ "theme/card-background-image",
152152+ );
153153+154154+ let cardBackgroundImageRepeat = useEntity(
155155+ props.entityID,
156156+ "theme/card-background-image-repeat",
157157+ );
158158+159159+ let cardBackgroundImageOpacity = useEntity(
160160+ props.entityID,
161161+ "theme/card-background-image-opacity",
162162+ );
163163+164164+ let backgroundImage = cardBackgroundImage || rootBackgroundImage;
165165+ let backgroundImageRepeat = cardBackgroundImage
166166+ ? cardBackgroundImageRepeat?.data?.value
167167+ : rootBackgroundRepeat?.data.value;
168168+ let backgroundImageOpacity = cardBackgroundImage
169169+ ? cardBackgroundImageOpacity?.data.value
170170+ : rootBackgroundOpacity?.data.value || 1;
171171+172172+ return (
173173+ <>
174174+ {!cardBorderHidden ? (
175175+ <div
176176+ className={`pageBackground
177177+ absolute top-0 left-0 right-0 bottom-0
178178+ pointer-events-none
179179+ rounded-lg
180180+ `}
181181+ style={{
182182+ backgroundImage: backgroundImage
183183+ ? `url(${backgroundImage.data.src}), url(${backgroundImage.data.fallback})`
184184+ : undefined,
185185+ backgroundRepeat: backgroundImageRepeat ? "repeat" : "no-repeat",
186186+ backgroundPosition: "center",
187187+ backgroundSize: !backgroundImageRepeat
188188+ ? "cover"
189189+ : backgroundImageRepeat,
190190+ opacity: backgroundImage?.data.src ? backgroundImageOpacity : 1,
191191+ }}
192192+ />
193193+ ) : null}
194194+ <Blocks entityID={props.entityID} />
195195+ {/* we handle page bg in this sepate div so that
196196+ we can apply an opacity the background image
197197+ without affecting the opacity of the rest of the page */}
198198+ </>
199199+ );
200200+};