tldraw/packages/tldraw/src/lib/shapes/shared/ShapeFill.tsx
Steve Ruiz 3e31ef2a7d
Remove helpers / extraneous API methods. (#1745)
This PR removes several extraneous computed values from the editor. It
adds some silly instance state onto the instance state record and
unifies a few methods which were inconsistent. This is fit and finish
work 🧽

## Computed Values

In general, where once we had a getter and setter for `isBlahMode`,
which really masked either an `_isBlahMode` atom on the editor or
`instanceState.isBlahMode`, these are merged into `instanceState`; they
can be accessed / updated via `editor.instanceState` /
`editor.updateInstanceState`.

## tldraw select tool specific things

This PR also removes some tldraw specific state checks and creates new
component overrides to allow us to include them in tldraw/tldraw.

### Change Type

- [x] `major` — Breaking change

### Test Plan

- [x] Unit Tests
- [x] End to end tests

### Release Notes

- [tldraw] rename `useReadonly` to `useReadOnly`
- [editor] remove `Editor.isDarkMode`
- [editor] remove `Editor.isChangingStyle`
- [editor] remove `Editor.isCoarsePointer`
- [editor] remove `Editor.isDarkMode`
- [editor] remove `Editor.isFocused`
- [editor] remove `Editor.isGridMode`
- [editor] remove `Editor.isPenMode`
- [editor] remove `Editor.isReadOnly`
- [editor] remove `Editor.isSnapMode`
- [editor] remove `Editor.isToolLocked`
- [editor] remove `Editor.locale`
- [editor] rename `Editor.pageState` to `Editor.currentPageState`
- [editor] add `Editor.pageStates`
- [editor] add `Editor.setErasingIds`
- [editor] add `Editor.setEditingId`
- [editor] add several new component overrides
2023-07-18 21:50:23 +00:00

120 lines
2.9 KiB
TypeScript

import {
HASH_PATTERN_ZOOM_NAMES,
TLDefaultColorStyle,
TLDefaultColorTheme,
TLDefaultFillStyle,
getDefaultColorTheme,
useEditor,
useValue,
} from '@tldraw/editor'
import React from 'react'
export interface ShapeFillProps {
d: string
fill: TLDefaultFillStyle
color: TLDefaultColorStyle
}
export function useDefaultColorTheme() {
const editor = useEditor()
return getDefaultColorTheme({ isDarkMode: editor.user.isDarkMode })
}
export const ShapeFill = React.memo(function ShapeFill({ d, color, fill }: ShapeFillProps) {
const theme = useDefaultColorTheme()
switch (fill) {
case 'none': {
return <path className={'tl-hitarea-stroke'} fill="none" d={d} />
}
case 'solid': {
return <path className={'tl-hitarea-fill-solid'} fill={theme[color].semi} d={d} />
}
case 'semi': {
return <path className={'tl-hitarea-fill-solid'} fill={theme.solid} d={d} />
}
case 'pattern': {
return <PatternFill color={color} fill={fill} d={d} />
}
}
})
const PatternFill = function PatternFill({ d, color }: ShapeFillProps) {
const editor = useEditor()
const theme = useDefaultColorTheme()
const zoomLevel = useValue('zoomLevel', () => editor.zoomLevel, [editor])
const isDarkMode = useValue('isDarkMode', () => editor.user.isDarkMode, [editor])
const intZoom = Math.ceil(zoomLevel)
const teenyTiny = editor.zoomLevel <= 0.18
return (
<>
<path className={'tl-hitarea-fill-solid'} fill={theme[color].pattern} d={d} />
<path
fill={
teenyTiny
? theme[color].semi
: `url(#${HASH_PATTERN_ZOOM_NAMES[intZoom + (isDarkMode ? '_dark' : '_light')]})`
}
d={d}
/>
</>
)
}
export function getShapeFillSvg({
d,
color,
fill,
theme,
}: ShapeFillProps & { theme: TLDefaultColorTheme }) {
if (fill === 'none') {
return
}
if (fill === 'pattern') {
const gEl = document.createElementNS('http://www.w3.org/2000/svg', 'g')
const path1El = document.createElementNS('http://www.w3.org/2000/svg', 'path')
path1El.setAttribute('d', d)
path1El.setAttribute('fill', theme[color].pattern)
const path2El = document.createElementNS('http://www.w3.org/2000/svg', 'path')
path2El.setAttribute('d', d)
path2El.setAttribute('fill', `url(#hash_pattern)`)
gEl.appendChild(path1El)
gEl.appendChild(path2El)
return gEl
}
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
path.setAttribute('d', d)
switch (fill) {
case 'semi': {
path.setAttribute('fill', theme.solid)
break
}
case 'solid': {
{
path.setAttribute('fill', theme[color].semi)
}
break
}
}
return path
}
export function getSvgWithShapeFill(foregroundPath: SVGElement, backgroundPath?: SVGElement) {
if (backgroundPath) {
// If there is a fill element, return a group containing the fill and the path
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')
g.appendChild(backgroundPath)
g.appendChild(foregroundPath)
return g
} else {
// Otherwise, just return the path
return foregroundPath
}
}