فهرست منبع

feat: allow geometry shapes to be transparent

Peng Xiao 3 سال پیش
والد
کامیت
4ae06ad1ff

+ 21 - 2
tldraw/apps/tldraw-logseq/src/components/ContextBar/ContextBar.tsx

@@ -9,6 +9,7 @@ import { observer } from 'mobx-react-lite'
 import type { TextShape, Shape } from '~lib/shapes'
 import { NumberInput } from '~components/inputs/NumberInput'
 import { ColorInput } from '~components/inputs/ColorInput'
+import { SwitchInput } from '../inputs/SwitchInput'
 
 const _ContextBar: TLContextBarComponent<Shape> = ({ shapes, offsets }) => {
   const app = useApp()
@@ -17,26 +18,39 @@ const _ContextBar: TLContextBarComponent<Shape> = ({ shapes, offsets }) => {
 
   const updateStroke = React.useCallback<React.ChangeEventHandler<HTMLInputElement>>(e => {
     shapes.forEach(shape => shape.update({ stroke: e.currentTarget.value }))
+    app.persist()
   }, [])
 
   const updateFill = React.useCallback<React.ChangeEventHandler<HTMLInputElement>>(e => {
     shapes.forEach(shape => shape.update({ fill: e.currentTarget.value }))
+    app.persist()
   }, [])
 
   const updateStrokeWidth = React.useCallback<React.ChangeEventHandler<HTMLInputElement>>(e => {
     shapes.forEach(shape => shape.update({ strokeWidth: +e.currentTarget.value }))
+    app.persist()
   }, [])
 
   const updateOpacity = React.useCallback<React.ChangeEventHandler<HTMLInputElement>>(e => {
     shapes.forEach(shape => shape.update({ opacity: +e.currentTarget.value }))
+    app.persist()
   }, [])
 
   const updateFontSize = React.useCallback<React.ChangeEventHandler<HTMLInputElement>>(e => {
     textShapes.forEach(shape => shape.update({ fontSize: +e.currentTarget.value }))
+    app.persist()
   }, [])
 
   const updateFontWeight = React.useCallback<React.ChangeEventHandler<HTMLInputElement>>(e => {
     textShapes.forEach(shape => shape.update({ fontWeight: +e.currentTarget.value }))
+    app.persist()
+  }, [])
+
+  const updateTransparent = React.useCallback(transparent => {
+    // const transparent = shapes.some(s => s.props.fill !== 'transparent')
+    console.log(transparent)
+    shapes.forEach(shape => shape.update({ fill: transparent ? 'transparent' : '#fff' }))
+    app.persist()
   }, [])
 
   React.useLayoutEffect(() => {
@@ -59,9 +73,9 @@ const _ContextBar: TLContextBarComponent<Shape> = ({ shapes, offsets }) => {
   if (!app) return null
 
   const textShapes = shapes.filter(shape => shape.type === 'text') as TextShape[]
-
   const ShapeContent =
     shapes.length === 1 && 'ReactContextBar' in shapes[0] ? shapes[0]['ReactContextBar'] : null
+  const transparent = shapes.every(s => s.props.fill === 'transparent')
 
   return (
     <HTMLContainer centered>
@@ -71,7 +85,12 @@ const _ContextBar: TLContextBarComponent<Shape> = ({ shapes, offsets }) => {
         ) : (
           <>
             <ColorInput label="Stroke" value={shapes[0].props.stroke} onChange={updateStroke} />
-            <ColorInput label="Fill" value={shapes[0].props.fill} onChange={updateFill} />
+            {!transparent && <ColorInput label="Fill" value={shapes[0].props.fill} onChange={updateFill} />}
+            <SwitchInput
+              label="Transparent"
+              checked={transparent}
+              onCheckedChange={updateTransparent}
+            />
             <NumberInput
               label="Width"
               value={Math.max(...shapes.map(shape => shape.props.strokeWidth))}

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/shapes/BoxShape.tsx

@@ -43,7 +43,7 @@ export class BoxShape extends TLBoxShape<BoxShapeProps> {
       <SVGContainer {...events} opacity={isErasing ? 0.2 : opacity}>
         {isBinding && <BindingIndicator strokeWidth={strokeWidth} size={[w, h]} />}
         <rect
-          className={isSelected ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'}
+          className={isSelected || fill !== 'transparent' ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'}
           x={strokeWidth / 2}
           y={strokeWidth / 2}
           rx={borderRadius}

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/shapes/EllipseShape.tsx

@@ -36,7 +36,7 @@ export class EllipseShape extends TLEllipseShape<EllipseShapeProps> {
     return (
       <SVGContainer {...events} opacity={isErasing ? 0.2 : opacity}>
         <ellipse
-          className={isSelected ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'}
+          className={isSelected || fill !== 'transparent' ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'}
           cx={w / 2}
           cy={h / 2}
           rx={Math.max(0.01, (w - strokeWidth) / 2)}

+ 14 - 9
tldraw/apps/tldraw-logseq/src/lib/shapes/LogseqPortalShape.tsx

@@ -778,21 +778,26 @@ export class LogseqPortalShape extends TLBoxShape<LogseqPortalShapeProps> {
     return (
       <>
         <rect
-          stroke={this.props.stroke}
-          strokeWidth={this.props.strokeWidth ?? 2}
-          fill="#aaa"
-          width={bounds.width}
-          height={HEADER_HEIGHT}
-        />
-        <rect
-          y={HEADER_HEIGHT}
           fill={this.props.fill}
           stroke={this.props.stroke}
           strokeWidth={this.props.strokeWidth ?? 2}
           fillOpacity={this.props.opacity ?? 0.2}
           width={bounds.width}
-          height={bounds.height - HEADER_HEIGHT}
+          rx={8}
+          ry={8}
+          height={bounds.height}
         />
+        {!this.props.compact && (
+          <rect
+            fill="#aaa"
+            x={1}
+            y={1}
+            width={bounds.width - 2}
+            height={HEADER_HEIGHT - 2}
+            rx={8}
+            ry={8}
+          />
+        )}
         <text
           style={{
             transformOrigin: 'top left',

+ 6 - 1
tldraw/apps/tldraw-logseq/src/lib/shapes/PolygonShape.tsx

@@ -36,7 +36,12 @@ export class PolygonShape extends TLPolygonShape<PolygonShapeProps> {
     return (
       <SVGContainer {...events} opacity={isErasing ? 0.2 : opacity}>
         <g transform={`translate(${x}, ${y})`}>
-          <polygon className={isSelected ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'} points={path} />
+          <polygon
+            className={
+              isSelected || fill !== 'transparent' ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'
+            }
+            points={path}
+          />
           <polygon
             points={path}
             stroke={stroke}

+ 14 - 14
tldraw/apps/tldraw-logseq/src/styles.css

@@ -159,21 +159,21 @@
     &[data-state='checked'] {
       background: #8ec2c2;
     }
-  }
-
-  .switch-input-thumb {
-    display: block;
-    width: 16px;
-    height: 16px;
-    background-color: white;
-    border-radius: 9999px;
-    transition: transform 100ms ease 0s;
-    transform: translateX(3px);
-    will-change: transform;
-  }
 
-  &[data-state='checked'] {
-    transform: translateX(17px);
+    .switch-input-thumb {
+      display: block;
+      width: 16px;
+      height: 16px;
+      background-color: white;
+      border-radius: 9999px;
+      transition: transform 100ms ease 0s;
+      transform: translateX(3px);
+      will-change: transform;
+    }
+  
+    &[data-state='checked'] .switch-input-thumb {
+      transform: translateX(17px);
+    }
   }
 
   .tl-text-input {

+ 3 - 1
tldraw/packages/core/src/lib/shapes/TLShape/TLShape.tsx

@@ -355,7 +355,7 @@ export abstract class TLShape<P extends TLShapeProps = TLShapeProps, M = any> {
   getShapeSVGJsx(opts: any) {
     // Do not need to consider the original point here
     const bounds = this.getBounds()
-    const { stroke, strokeWidth, opacity, fill } = this.props as any
+    const { stroke, strokeWidth, opacity, fill, borderRadius } = this.props as any
     return (
       <rect
         fill={fill}
@@ -364,6 +364,8 @@ export abstract class TLShape<P extends TLShapeProps = TLShapeProps, M = any> {
         fillOpacity={opacity ?? 0.2}
         width={bounds.width}
         height={bounds.height}
+        rx={borderRadius}
+        ry={borderRadius}
       />
     )
   }