mirror of https://github.com/logseq/logseq
feat(whiteboard): show shape references
parent
962998a7b2
commit
f322160ca6
|
@ -46,39 +46,53 @@
|
|||
(when generate-preview
|
||||
(generate-preview tldr))))
|
||||
|
||||
;; TODO: use frontend.ui instead of making a new one
|
||||
(rum/defc dropdown
|
||||
[label children show? outside-click-hander]
|
||||
[label children show? outside-click-hander portal?]
|
||||
(let [[anchor-ref anchor-rect] (use-bounding-client-rect show?)
|
||||
[content-ref content-rect] (use-bounding-client-rect show?)
|
||||
offset-x (when (and anchor-rect content-rect)
|
||||
(let [offset-x (+ (* 0.5 (- (.-width anchor-rect) (.-width content-rect)))
|
||||
(.-x anchor-rect))
|
||||
vp-w (.-innerWidth js/window)
|
||||
right (+ offset-x (.-width content-rect) 16)
|
||||
offset-x (if (> right vp-w) (- offset-x (- right vp-w)) offset-x)]
|
||||
offset-x))
|
||||
(if portal?
|
||||
(let [offset-x (+ (* 0.5 (- (.-width anchor-rect) (.-width content-rect)))
|
||||
(.-x anchor-rect))
|
||||
vp-w (.-innerWidth js/window)
|
||||
right (+ offset-x (.-width content-rect) 16)
|
||||
offset-x (if (> right vp-w) (- offset-x (- right vp-w)) offset-x)]
|
||||
offset-x)
|
||||
(* 0.5 (- (.-width anchor-rect) (.-width content-rect)))))
|
||||
offset-y (when (and anchor-rect content-rect)
|
||||
(+ (.-y anchor-rect) (.-height anchor-rect) 8))
|
||||
click-outside-ref (use-click-outside outside-click-hander)
|
||||
[d-open set-d-open] (rum/use-state false)
|
||||
_ (rum/use-effect! (fn [] (js/setTimeout #(set-d-open show?) 100))
|
||||
[show?])]
|
||||
[:div.dropdown-anchor {:ref anchor-ref}
|
||||
[:div.inline-block.dropdown-anchor {:ref anchor-ref}
|
||||
label
|
||||
(ui/portal
|
||||
[:div.fixed.shadow-lg.color-level.px-2.rounded-lg.transition.md:w-64.lg:w-128.overflow-auto
|
||||
{:ref (juxt content-ref click-outside-ref)
|
||||
:style {:opacity (if d-open 1 0)
|
||||
:pointer-events (if d-open "auto" "none")
|
||||
:transform (str "translateY(" (if d-open 0 10) "px)")
|
||||
:min-height "40px"
|
||||
:max-height "420px"
|
||||
:left offset-x
|
||||
:top offset-y}}
|
||||
(when d-open children)])]))
|
||||
(if portal?
|
||||
;; FIXME: refactor the following code
|
||||
(ui/portal
|
||||
[:div.fixed.shadow-lg.color-level.px-2.rounded-lg.transition.md:w-64.lg:w-128.overflow-auto
|
||||
{:ref (juxt content-ref click-outside-ref)
|
||||
:style {:opacity (if d-open 1 0)
|
||||
:pointer-events (if d-open "auto" "none")
|
||||
:transform (str "translateY(" (if d-open 0 10) "px)")
|
||||
:min-height "40px"
|
||||
:max-height "420px"
|
||||
:left offset-x
|
||||
:top offset-y}}
|
||||
(when d-open children)])
|
||||
[:div.absolute.shadow-lg.color-level.px-2.rounded-lg.transition.md:w-64.lg:w-128.overflow-auto
|
||||
{:ref (juxt content-ref click-outside-ref)
|
||||
:style {:opacity (if d-open 1 0)
|
||||
:pointer-events (if d-open "auto" "none")
|
||||
:transform (str "translateY(" (if d-open 0 10) "px)")
|
||||
:min-height "40px"
|
||||
:max-height "420px"
|
||||
:left offset-x}}
|
||||
(when d-open children)])]))
|
||||
|
||||
(rum/defc dropdown-menu
|
||||
[{:keys [label children classname hover?]}]
|
||||
[{:keys [label children classname hover? portal?]}]
|
||||
(let [[open-flag set-open-flag] (rum/use-state 0)
|
||||
open? (> open-flag (if hover? 0 1))
|
||||
d-open-flag (rum/use-memo #(util/debounce 200 set-open-flag) [])]
|
||||
|
@ -90,22 +104,30 @@
|
|||
(util/stop e)
|
||||
(d-open-flag (fn [o] (if (not= o 2) 2 0))))}
|
||||
(if (fn? label) (label open?) label)]
|
||||
children open? #(set-open-flag 0))))
|
||||
children open? #(set-open-flag 0) portal?)))
|
||||
|
||||
(rum/defc page-refs-count < rum/static
|
||||
([page-name classname]
|
||||
(page-refs-count page-name classname nil))
|
||||
([page-name classname render-fn]
|
||||
(let [page-entity (model/get-page page-name)
|
||||
;; TODO: move to frontend.components.reference
|
||||
;; TODO: reactivity when ref count change
|
||||
(rum/defc references-count < rum/static
|
||||
"Shows a references count for any block or page.
|
||||
When clicked, a dropdown menu will show the reference details"
|
||||
([page-name-or-uuid classname]
|
||||
(references-count page-name-or-uuid classname nil))
|
||||
([page-name-or-uuid classname {:keys [render-fn
|
||||
hover?
|
||||
portal?]
|
||||
:or {portal? true}}]
|
||||
(let [page-entity (model/get-page page-name-or-uuid)
|
||||
block-uuid (:block/uuid page-entity)
|
||||
refs-count (count (:block/_refs page-entity))]
|
||||
(when (> refs-count 0)
|
||||
(dropdown-menu {:classname classname
|
||||
:label (fn [open?]
|
||||
[:div.flex.items-center.gap-2
|
||||
[:div.inline-flex.items-center.gap-2
|
||||
[:div.open-page-ref-link refs-count]
|
||||
(when render-fn (render-fn open? refs-count))])
|
||||
:hover? true
|
||||
:hover? hover?
|
||||
:portal? portal?
|
||||
:children (reference/block-linked-references block-uuid)})))))
|
||||
|
||||
(defn- get-page-display-name
|
||||
|
@ -151,7 +173,7 @@
|
|||
[:div.flex.w-full.opacity-50
|
||||
[:div (get-page-human-update-time page-name)]
|
||||
[:div.flex-1]
|
||||
(page-refs-count page-name nil)]]
|
||||
(references-count page-name nil {:hover? true})]]
|
||||
[:div.p-4.h-64.flex.justify-center
|
||||
(tldraw-preview page-name)]])
|
||||
|
||||
|
@ -255,12 +277,13 @@
|
|||
false)]
|
||||
|
||||
[:div.whiteboard-page-refs
|
||||
(page-refs-count page-name
|
||||
"text-md px-3 py-2 cursor-default whiteboard-page-refs-count"
|
||||
(fn [open? refs-count] [:span.whiteboard-page-refs-count-label
|
||||
(if (> refs-count 1) "References" "Reference")
|
||||
(ui/icon (if open? "references-hide" "references-show")
|
||||
{:extension? true})]))]]
|
||||
(references-count page-name
|
||||
"text-md px-3 py-2 cursor-default whiteboard-page-refs-count"
|
||||
{:hover? true
|
||||
:render-fn (fn [open? refs-count] [:span.whiteboard-page-refs-count-label
|
||||
(if (> refs-count 1) "References" "Reference")
|
||||
(ui/icon (if open? "references-hide" "references-show")
|
||||
{:extension? true})])})]]
|
||||
(tldraw-app page-name block-id)]))
|
||||
|
||||
(rum/defc whiteboard-route
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
[goog.object :as gobj]
|
||||
[promesa.core :as p]
|
||||
[rum.core :as rum]
|
||||
[frontend.ui :as ui]))
|
||||
[frontend.ui :as ui]
|
||||
[frontend.components.whiteboard :as whiteboard]))
|
||||
|
||||
(def tldraw (r/adapt-class (gobj/get TldrawLogseq "App")))
|
||||
|
||||
|
@ -54,12 +55,18 @@
|
|||
(when-let [[asset-file-name _ full-file-path] (and (seq res) (first res))]
|
||||
(editor-handler/resolve-relative-path (or full-file-path asset-file-name)))))))
|
||||
|
||||
(defn references-count
|
||||
[props]
|
||||
(apply whiteboard/references-count
|
||||
(map (fn [k] (js->clj (gobj/get props k) {:keywordize-keys true})) ["id" "className" "options"])))
|
||||
|
||||
(def tldraw-renderers {:Page page-cp
|
||||
:Block block-cp
|
||||
:Breadcrumb breadcrumb
|
||||
:PageNameLink page-name-link})
|
||||
:PageNameLink page-name-link
|
||||
:ReferencesCount references-count})
|
||||
|
||||
(defn get-tldraw-handlers [name]
|
||||
(defn get-tldraw-handlers [current-whiteboard-name]
|
||||
{:search search-handler
|
||||
:queryBlockByUUID #(clj->js (model/query-block-by-uuid (parse-uuid %)))
|
||||
:isWhiteboardPage model/whiteboard-page?
|
||||
|
@ -68,7 +75,7 @@
|
|||
:addNewWhiteboard (fn [page-name]
|
||||
(whiteboard-handler/create-new-whiteboard-page! page-name))
|
||||
:addNewBlock (fn [content]
|
||||
(str (whiteboard-handler/add-new-block! name content)))
|
||||
(str (whiteboard-handler/add-new-block! current-whiteboard-name content)))
|
||||
:sidebarAddBlock (fn [uuid type]
|
||||
(state/sidebar-add-block! (state/get-current-repo)
|
||||
(:db/id (model/get-page uuid))
|
||||
|
|
|
@ -68,8 +68,9 @@
|
|||
|
||||
(defn- get-whiteboard-tldr-from-text
|
||||
[text]
|
||||
(when-let [matched-text (util/safe-re-find #"<whiteboard-tldr>(.*)</whiteboard-tldr>" text)]
|
||||
(try-parse-as-json (gp-util/safe-decode-uri-component (second matched-text)))))
|
||||
(when-let [matched-text (util/safe-re-find #"<whiteboard-tldr>(.*)</whiteboard-tldr>"
|
||||
(gp-util/safe-decode-uri-component text))]
|
||||
(try-parse-as-json (second matched-text))))
|
||||
|
||||
(defn- get-whiteboard-shape-refs-text
|
||||
[text]
|
||||
|
|
|
@ -34,10 +34,6 @@ import {
|
|||
} from './lib'
|
||||
import { LogseqContext, type LogseqContextValue } from './lib/logseq-context'
|
||||
|
||||
const components: TLReactComponents<Shape> = {
|
||||
ContextBar: ContextBar,
|
||||
}
|
||||
|
||||
const tools: TLReactToolConstructor<Shape>[] = [
|
||||
BoxTool,
|
||||
// DotTool,
|
||||
|
@ -62,9 +58,24 @@ interface LogseqTldrawProps {
|
|||
onPersist?: TLReactCallbacks<Shape>['onPersist']
|
||||
}
|
||||
|
||||
const ReferencesCount: LogseqContextValue['renderers']['ReferencesCount'] = props => {
|
||||
const { renderers } = React.useContext(LogseqContext)
|
||||
|
||||
const options = { 'portal?': false }
|
||||
|
||||
return <renderers.ReferencesCount {...props} options={options} />
|
||||
}
|
||||
|
||||
const AppImpl = () => {
|
||||
const ref = React.useRef<HTMLDivElement>(null)
|
||||
const app = useApp()
|
||||
const components = React.useMemo(
|
||||
() => ({
|
||||
ContextBar,
|
||||
ReferencesCount,
|
||||
}),
|
||||
[]
|
||||
)
|
||||
return (
|
||||
<ContextMenu collisionRef={ref}>
|
||||
<div ref={ref} className="logseq-tldraw logseq-tldraw-wrapper" data-tlapp={app.uuid}>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import * as Separator from '@radix-ui/react-separator'
|
||||
import {
|
||||
getContextBarTranslation,
|
||||
HTMLContainer,
|
||||
|
@ -5,11 +6,10 @@ import {
|
|||
useApp,
|
||||
} from '@tldraw/react'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import * as Separator from '@radix-ui/react-separator'
|
||||
|
||||
import * as React from 'react'
|
||||
import type { Shape } from '~lib/shapes'
|
||||
import { getContextBarActionsForTypes as getContextBarActionsForShapes } from './contextBarActionFactory'
|
||||
import type { Shape } from '../../lib'
|
||||
import { getContextBarActionsForShapes } from './contextBarActionFactory'
|
||||
|
||||
const _ContextBar: TLContextBarComponent<Shape> = ({ shapes, offsets, hidden }) => {
|
||||
const app = useApp()
|
||||
|
|
|
@ -512,7 +512,7 @@ const getContextBarActionTypes = (type: ShapeType) => {
|
|||
return (shapeMapping[type] ?? []).filter(isNonNullable)
|
||||
}
|
||||
|
||||
export const getContextBarActionsForTypes = (shapes: Shape[]) => {
|
||||
export const getContextBarActionsForShapes = (shapes: Shape[]) => {
|
||||
const types = shapes.map(s => s.props.type)
|
||||
const actionTypes = new Set(shapes.length > 0 ? getContextBarActionTypes(types[0]) : [])
|
||||
for (let i = 1; i < types.length && actionTypes.size > 0; i++) {
|
||||
|
|
|
@ -20,6 +20,15 @@ export interface LogseqContextValue {
|
|||
PageNameLink: React.FC<{
|
||||
pageName: string
|
||||
}>
|
||||
ReferencesCount: React.FC<{
|
||||
id: string
|
||||
className?: string
|
||||
options?: {
|
||||
'portal?'?: boolean
|
||||
'hover?'?: boolean
|
||||
renderFn?: (open?: boolean, count?: number) => React.ReactNode
|
||||
}
|
||||
}>
|
||||
}
|
||||
handlers: {
|
||||
search: (
|
||||
|
|
|
@ -42,7 +42,7 @@ export class LineShape extends TLLineShape<LineShapeProps> {
|
|||
label: '',
|
||||
}
|
||||
|
||||
hideSelection = true
|
||||
hideSelection = false
|
||||
canEdit = true
|
||||
|
||||
ReactComponent = observer(({ events, isErasing, isEditing, onEditingEnd }: TLComponentProps) => {
|
||||
|
|
|
@ -82,7 +82,7 @@ const LogseqPortalShapeHeader = observer(
|
|||
children,
|
||||
}: {
|
||||
type: 'P' | 'B'
|
||||
fill: string
|
||||
fill?: string
|
||||
opacity: number
|
||||
children: React.ReactNode
|
||||
}) => {
|
||||
|
|
|
@ -8,7 +8,7 @@ interface ShapeStyles {
|
|||
stroke: string
|
||||
strokeWidth: number
|
||||
strokeType: 'line' | 'dashed'
|
||||
fill: string
|
||||
fill?: string
|
||||
}
|
||||
|
||||
interface ArrowSvgProps {
|
||||
|
|
|
@ -319,7 +319,7 @@ button.tl-select-input-trigger {
|
|||
}
|
||||
|
||||
&[data-state='checked'] {
|
||||
background-color: #4285f4;
|
||||
background-color: var(--color-selectedFill);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
@ -987,3 +987,10 @@ html[data-theme='dark'] {
|
|||
background-color: var(--ls-tertiary-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
.tl-reference-count-container {
|
||||
@apply inline-flex items-center justify-center p-1;
|
||||
background-color: var(--color-selectedFill);
|
||||
border-top-right-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
}
|
|
@ -83,6 +83,10 @@ const PageNameLink = props => {
|
|||
)
|
||||
}
|
||||
|
||||
const ReferencesCount = props => {
|
||||
return <div className="open-page-ref-link rounded bg-gray-400 p-0.5">3</div>
|
||||
}
|
||||
|
||||
const StatusBarSwitcher = ({ label, onClick }) => {
|
||||
const [anchor, setAnchor] = React.useState(null)
|
||||
React.useEffect(() => {
|
||||
|
@ -210,6 +214,7 @@ export default function App() {
|
|||
Block,
|
||||
Breadcrumb,
|
||||
PageNameLink,
|
||||
ReferencesCount,
|
||||
}}
|
||||
handlers={{
|
||||
search: searchHandler,
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
"postinstall": "yarn build",
|
||||
"dev": "cd demo && yarn dev",
|
||||
"fix:style": "yarn run pretty-quick",
|
||||
"pretty-quick": "pretty-quick --pattern 'tldraw/**/*.{js,jsx,ts,tsx,css,html}'"
|
||||
"pretty-quick": "pretty-quick --pattern 'tldraw/**/*.{js,jsx,ts,tsx,html}'"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^17.0.42",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Color } from '../types'
|
||||
|
||||
export function getComputedColor(color: string, type: string): string {
|
||||
export function getComputedColor(color: string | undefined, type: string): string {
|
||||
if (Object.values(Color).includes(color as Color) || color == null) {
|
||||
return `var(--ls-wb-${type}-color-${color ? color : 'default'})`
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import { Container } from '../Container'
|
|||
import { ContextBarContainer } from '../ContextBarContainer'
|
||||
import { HTMLLayer } from '../HTMLLayer'
|
||||
import { Indicator } from '../Indicator'
|
||||
import { ReferencesCountContainer } from '../ReferencesCountContainer'
|
||||
import { SelectionDetailContainer } from '../SelectionDetailContainer'
|
||||
import { Shape } from '../Shape'
|
||||
import { SVGContainer } from '../SVGContainer'
|
||||
|
@ -107,6 +108,7 @@ export const Canvas = observer(function Renderer<S extends TLReactShape>({
|
|||
onlySelectedShape && 'handles' in onlySelectedShape.props ? selectedShapes?.[0] : undefined
|
||||
const selectedShapesSet = React.useMemo(() => new Set(selectedShapes || []), [selectedShapes])
|
||||
const erasingShapesSet = React.useMemo(() => new Set(erasingShapes || []), [erasingShapes])
|
||||
const singleSelectedShape = selectedShapes?.length === 1 ? selectedShapes[0] : undefined
|
||||
|
||||
return (
|
||||
<div ref={rContainer} className={`tl-container ${className ?? ''}`}>
|
||||
|
@ -170,6 +172,13 @@ export const Canvas = observer(function Renderer<S extends TLReactShape>({
|
|||
/>
|
||||
</Container>
|
||||
)}
|
||||
{showSelection && singleSelectedShape && components.ReferencesCount && (
|
||||
<ReferencesCountContainer
|
||||
hidden={false}
|
||||
bounds={singleSelectedShape.bounds}
|
||||
shape={singleSelectedShape}
|
||||
/>
|
||||
)}
|
||||
{showHandles && onlySelectedShapeWithHandles && components.Handle && (
|
||||
<Container
|
||||
data-type="onlySelectedShapeWithHandles"
|
||||
|
@ -204,8 +213,8 @@ export const Canvas = observer(function Renderer<S extends TLReactShape>({
|
|||
key={'context' + selectedShapes.map(shape => shape.id).join('')}
|
||||
shapes={selectedShapes}
|
||||
hidden={!showContextBar}
|
||||
bounds={selectedShapes.length === 1 ? selectedShapes[0].bounds : selectionBounds}
|
||||
rotation={selectedShapes.length === 1 ? selectedShapes[0].props.rotation : 0}
|
||||
bounds={singleSelectedShape ? singleSelectedShape.bounds : selectionBounds}
|
||||
rotation={singleSelectedShape ? singleSelectedShape.props.rotation : 0}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import type { TLBounds } from '@tldraw/core'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { useRendererContext } from '../../hooks'
|
||||
import type { TLReactShape } from '../../lib'
|
||||
import { Container } from '../Container'
|
||||
import { HTMLContainer } from '../HTMLContainer'
|
||||
|
||||
export interface TLReferencesCountContainerProps<S extends TLReactShape> {
|
||||
hidden: boolean
|
||||
bounds: TLBounds
|
||||
shape: S
|
||||
}
|
||||
|
||||
export const ReferencesCountContainer = observer(function ReferencesCountContainer<
|
||||
S extends TLReactShape
|
||||
>({ bounds, hidden, shape }: TLReferencesCountContainerProps<S>) {
|
||||
const {
|
||||
components: { ReferencesCount },
|
||||
} = useRendererContext()
|
||||
|
||||
if (!ReferencesCount) throw Error('Expected a ReferencesCount component.')
|
||||
|
||||
const stop: React.EventHandler<any> = e => e.stopPropagation()
|
||||
|
||||
return (
|
||||
<Container
|
||||
style={{
|
||||
zIndex: 20000,
|
||||
}}
|
||||
bounds={bounds}
|
||||
aria-label="references-count-container"
|
||||
>
|
||||
<HTMLContainer>
|
||||
<span
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: '100%',
|
||||
pointerEvents: 'all',
|
||||
transformOrigin: 'left top',
|
||||
transform: 'scale(var(--tl-scale)) translateY(8px)',
|
||||
}}
|
||||
onPointerDown={stop}
|
||||
onWheelCapture={stop}
|
||||
>
|
||||
<ReferencesCount className="tl-reference-count-container" id={shape.id} shape={shape} />
|
||||
</span>
|
||||
</HTMLContainer>
|
||||
</Container>
|
||||
)
|
||||
})
|
|
@ -0,0 +1 @@
|
|||
export * from './ReferencesCountContainer'
|
|
@ -59,6 +59,7 @@ export const RendererContext = observer(function App<S extends TLReactShape>({
|
|||
SelectionBackground,
|
||||
SelectionDetail,
|
||||
SelectionForeground,
|
||||
...rest
|
||||
} = components
|
||||
|
||||
return {
|
||||
|
@ -68,6 +69,7 @@ export const RendererContext = observer(function App<S extends TLReactShape>({
|
|||
callbacks,
|
||||
meta,
|
||||
components: {
|
||||
...rest,
|
||||
Brush: Brush === null ? undefined : _Brush,
|
||||
ContextBar,
|
||||
DirectionIndicator: DirectionIndicator === null ? undefined : _DirectionIndicator,
|
||||
|
@ -90,6 +92,7 @@ export const RendererContext = observer(function App<S extends TLReactShape>({
|
|||
SelectionBackground,
|
||||
SelectionDetail,
|
||||
SelectionForeground,
|
||||
...rest
|
||||
} = components
|
||||
|
||||
return autorun(() => {
|
||||
|
@ -100,6 +103,7 @@ export const RendererContext = observer(function App<S extends TLReactShape>({
|
|||
callbacks,
|
||||
meta,
|
||||
components: {
|
||||
...rest,
|
||||
Brush: Brush === null ? undefined : _Brush,
|
||||
ContextBar,
|
||||
DirectionIndicator: DirectionIndicator === null ? undefined : _DirectionIndicator,
|
||||
|
|
|
@ -69,7 +69,7 @@ const defaultTheme: TLTheme = {
|
|||
accent: 'rgb(255, 0, 0)',
|
||||
brushFill: 'var(--ls-scrollbar-background-color, rgba(0, 0, 0, .05))',
|
||||
brushStroke: 'var(--ls-scrollbar-thumb-hover-color, rgba(0, 0, 0, .05))',
|
||||
selectStroke: 'rgb(66, 133, 244)',
|
||||
selectStroke: 'var(--color-selectedFill)',
|
||||
selectFill: 'rgba(65, 132, 244, 0.05)',
|
||||
binding: 'rgba(65, 132, 244, 0.5)',
|
||||
background: 'var(--ls-primary-background-color)',
|
||||
|
|
|
@ -72,6 +72,16 @@ export type TLHandleComponent<
|
|||
H extends TLHandle = TLHandle
|
||||
> = (props: TLHandleComponentProps<S, H>) => JSX.Element | null
|
||||
|
||||
export interface TLReferencesCountComponentProps<S extends TLReactShape = TLReactShape> {
|
||||
shape: S
|
||||
id: string
|
||||
className?: string
|
||||
}
|
||||
|
||||
export type TLReferencesCountComponent<S extends TLReactShape = TLReactShape> = (
|
||||
props: TLReferencesCountComponentProps<S>
|
||||
) => JSX.Element | null
|
||||
|
||||
export interface TLGridProps {
|
||||
size: number
|
||||
}
|
||||
|
@ -82,6 +92,7 @@ export type TLReactComponents<S extends TLReactShape = TLReactShape> = {
|
|||
SelectionBackground?: TLBoundsComponent<S> | null
|
||||
SelectionForeground?: TLBoundsComponent<S> | null
|
||||
SelectionDetail?: TLSelectionDetailComponent<S> | null
|
||||
ReferencesCount?: TLReferencesCountComponent<S> | null
|
||||
DirectionIndicator?: TLDirectionIndicatorComponent<S> | null
|
||||
Handle?: TLHandleComponent<S> | null
|
||||
ContextBar?: TLContextBarComponent<S> | null
|
||||
|
|
Loading…
Reference in New Issue