diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index cc1c2b763b..b1d93ca06f 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -2256,7 +2256,7 @@ (rum/defc single-block-cp [block-uuid] - [:div.single-block-wrapper (single-block-cp-inner block-uuid)]) + [:div.single-block (single-block-cp-inner block-uuid)]) (defn non-dragging? [e] diff --git a/src/main/frontend/components/whiteboard.css b/src/main/frontend/components/whiteboard.css index db4afd3436..7561292319 100644 --- a/src/main/frontend/components/whiteboard.css +++ b/src/main/frontend/components/whiteboard.css @@ -9,9 +9,13 @@ background-color: var(--ls-secondary-background-color); } -.single-block-wrapper > .block-content-wrapper { +.single-block > :is(.block-content-wrapper, .editor-wrapper) { width: 100% !important; background-color: var(--ls-secondary-background-color); padding: 8px 12px; border-radius: 8px; } + +.tl-logseq-cp-container > .page { + padding: 12px; +} diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index e2f7372b9c..8c5c7ccf59 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -2417,7 +2417,7 @@ (let [el (rum/dom-node state)] (loop [el el] (cond (nil? el) false - (and (.-classList el) (.. el -classList (contains "single-block-wrapper"))) true + (and (.-classList el) (.. el -classList (contains "single-block"))) true :else (recur (.-parentElement el)))))) (defn keydown-new-block-handler [state e] diff --git a/src/main/frontend/handler/whiteboard.cljs b/src/main/frontend/handler/whiteboard.cljs index ef4e34f7d9..6bbb582236 100644 --- a/src/main/frontend/handler/whiteboard.cljs +++ b/src/main/frontend/handler/whiteboard.cljs @@ -86,7 +86,7 @@ (defn- whiteboard-clj->tldr [page-block blocks shape-id] (let [id (str (:block/uuid page-block)) - shapes (->> blocks + shapes (->> blocks (map block->shape) (filter #(= :whiteboard-shape (:ls-type %)))) page-properties (:block/properties page-block) @@ -138,9 +138,10 @@ ([page-name] (page-name->tldr! page-name nil)) ([page-name shape-id] - (if-let [[page-block blocks] (get-whiteboard-clj page-name)] - (whiteboard-clj->tldr page-block blocks shape-id) - (create-new-whiteboard-page! page-name)))) + (when page-name + (if-let [[page-block blocks] (get-whiteboard-clj page-name)] + (whiteboard-clj->tldr page-block blocks shape-id) + (create-new-whiteboard-page! page-name))))) (defn ->logseq-portal-shape [block-id point] diff --git a/tldraw/apps/tldraw-logseq/src/lib/shapes/LogseqPortalShape.tsx b/tldraw/apps/tldraw-logseq/src/lib/shapes/LogseqPortalShape.tsx index 483fc893d2..6e4e5c05a7 100644 --- a/tldraw/apps/tldraw-logseq/src/lib/shapes/LogseqPortalShape.tsx +++ b/tldraw/apps/tldraw-logseq/src/lib/shapes/LogseqPortalShape.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { MagnifyingGlassIcon } from '@radix-ui/react-icons' import { TLBoxShape, TLBoxShapeProps, validUUID } from '@tldraw/core' -import { HTMLContainer, TLComponentProps, TLContextBarProps, useApp } from '@tldraw/react' +import { HTMLContainer, TLComponentProps, TLReactApp, useApp } from '@tldraw/react' import { makeObservable } from 'mobx' import { observer } from 'mobx-react-lite' import * as React from 'react' @@ -117,11 +117,16 @@ export class LogseqPortalShape extends TLBoxShape { canFlip = true canEdit = true + persist: (() => void) | null = null + // For quick add shapes, we want to calculate the page height dynamically + initialHeightCalculated = true + getInnerHeight: (() => number) | null = null // will be overridden in the hook + constructor(props = {} as Partial) { super(props) makeObservable(this) - if (props.collapsed) { - this.canResize = [true, false] + if (props.collapsed || props.compact) { + Object.assign(this.canResize, [true, false]) } } @@ -133,6 +138,34 @@ export class LogseqPortalShape extends TLBoxShape { return false } + useComponentSize(ref: React.RefObject | null, selector = '') { + const [size, setSize] = React.useState<[number, number]>([0, 0]) + React.useEffect(() => { + console.log(ref?.current) + if (ref?.current) { + const el = selector ? ref.current.querySelector(selector) : ref.current + if (el) { + const updateSize = () => { + const { width, height } = el.getBoundingClientRect() + setSize([width, height]) + return [width, height] + } + updateSize() + this.getInnerHeight = () => updateSize()[1] + const resizeObserver = new ResizeObserver(() => { + updateSize() + }) + resizeObserver.observe(el) + return () => { + resizeObserver.disconnect() + } + } + } + return () => {} + }, [ref, selector]) + return size + } + ReactContextBar = observer(() => { const app = useApp() return ( @@ -179,10 +212,9 @@ export class LogseqPortalShape extends TLBoxShape { label="Compact" checked={this.props.compact} onCheckedChange={compact => { - this.update({ - compact: compact, - }) - app.persist() + this.update({ compact }) + this.canResize[1] = !compact + this.autoResizeHeight() }} /> )} @@ -190,14 +222,90 @@ export class LogseqPortalShape extends TLBoxShape { ) }) - ReactComponent = observer(({ events, isErasing, isEditing, isBinding }: TLComponentProps) => { + autoResizeHeight(ttl = 5) { + setTimeout(() => { + if (this.getInnerHeight) { + this.update({ + size: [ + this.props.size[0], + this.getInnerHeight() + (this.props.compact ? 0 : HEADER_HEIGHT), + ], + }) + this.persist?.() + this.initialHeightCalculated = true + } else if (ttl > 0) { + this.autoResizeHeight(ttl - 1) + } + }, 10) + } + + PortalComponent = observer(({ isBinding }: TLComponentProps) => { const { - props: { opacity, pageId, stroke, fill }, + props: { pageId, stroke, fill }, + } = this + const { renderers } = React.useContext(LogseqContext) + if (!renderers?.Page) { + return null // not being correctly configured + } + const { Page, Block, Breadcrumb, PageNameLink } = renderers + + const cpRefContainer = React.useRef(null) + + const [, innerHeight] = this.useComponentSize( + cpRefContainer, + this.props.compact + ? '.tl-logseq-cp-container > .single-block' + : '.tl-logseq-cp-container > .page' + ) + + return ( +
+ {!this.props.compact && ( + + {this.props.blockType === 'P' ? ( + + ) : ( + + )} + + )} +
+ {this.props.blockType === 'B' && this.props.compact ? ( + + ) : ( + + )} +
+
+ ) + }) + + ReactComponent = observer((componentProps: TLComponentProps) => { + const { events, isErasing, isEditing } = componentProps + const { + props: { opacity, pageId }, } = this const app = useApp() + this.persist = () => app.persist() const isMoving = useCameraMovingRef() - const { renderers } = React.useContext(LogseqContext) const isSelected = app.selectedIds.has(this.id) const isCreating = app.isIn('logseq-portal.creating') && !pageId const tlEventsEnabled = @@ -231,6 +339,7 @@ export class LogseqPortalShape extends TLBoxShape { }, [isEditing, this.props.collapsed]) const onPageNameChanged = React.useCallback((id: string) => { + this.initialHeightCalculated = false this.update({ pageId: id, size: [600, 320], @@ -241,11 +350,25 @@ export class LogseqPortalShape extends TLBoxShape { app.history.persist() }, []) - if (!renderers?.Page) { - return null // not being correctly configured - } + const showingPortal = !this.props.collapsed || isEditing - const { Page, Block, Breadcrumb, PageNameLink } = renderers + const PortalComponent = this.PortalComponent + + React.useLayoutEffect(() => { + if (this.props.compact && this.props.blockType === 'B') { + const newHeight = innerHeight + (this.props.compact ? 0 : HEADER_HEIGHT) + this.update({ + size: [this.props.size[0], newHeight], + }) + app.persist() + } + }, [innerHeight, this.props.compact]) + + React.useEffect(() => { + if (!this.initialHeightCalculated) { + this.autoResizeHeight() + } + }, [this.initialHeightCalculated]) return ( { > {isCreating ? ( - ) : ( -
- {!this.props.compact && ( - - {this.props.blockType === 'P' ? ( - - ) : ( - - )} - - )} - {(!this.props.collapsed || isEditing) && ( -
- {this.props.blockType === 'B' && this.props.compact ? ( - - ) : ( -
- -
- )} -
- )} -
- )} + ) : showingPortal ? ( + + ) : null}
) diff --git a/tldraw/apps/tldraw-logseq/src/styles.css b/tldraw/apps/tldraw-logseq/src/styles.css index e9fcd6b2b1..e8af6c37bb 100644 --- a/tldraw/apps/tldraw-logseq/src/styles.css +++ b/tldraw/apps/tldraw-logseq/src/styles.css @@ -564,13 +564,13 @@ .logseq-tldraw .tl-logseq-portal-container { width: 100%; - overflow: auto; - border-radius: 8px; overscroll-behavior: none; height: 100%; display: flex; flex-direction: column; opacity: 1; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; } .logseq-tldraw .tl-logseq-portal-header { @@ -578,6 +578,8 @@ width: 100%; flex-shrink: 0; background: transparent; + border-top-left-radius: 8px; + border-top-right-radius: 8px; display: flex; color: var(--ls-title-text-color); padding: 0 1rem; @@ -620,3 +622,12 @@ html[data-theme='dark'] .logseq-tldraw .tl-logseq-portal-header { width: 100% !important; margin: 0; } + +.tl-logseq-cp-container { + width: 100%; + border-radius: 8px; + overscroll-behavior: none; + height: 100%; + flex: 1 1 0%; + cursor: default; +} diff --git a/tldraw/demo/src/App.jsx b/tldraw/demo/src/App.jsx index c22c2a56f9..258a270190 100644 --- a/tldraw/demo/src/App.jsx +++ b/tldraw/demo/src/App.jsx @@ -33,7 +33,7 @@ const documentModel = onLoad() ?? { fill: '#ffffff', strokeWidth: 2, opacity: 1, - pageId: '', + pageId: 'aaasssdddfff', nonce: 1, }, ], @@ -49,7 +49,7 @@ const Page = props => { const [value, setValue] = React.useState(JSON.stringify(props, null, 2)) return (