From 20b975482c232698dbd4eab8fd9d10e0f6ff8b67 Mon Sep 17 00:00:00 2001 From: meetzaveri Date: Sun, 22 Feb 2026 16:41:46 +0530 Subject: [PATCH 1/3] update: test new pencil behavior A --- src/components/elements/groupobject.js | 4 +- src/components/elements/pencil.js | 17 +-- src/factory/pencil.js | 40 +++++-- src/newCanvas.js | 153 +++++++++++++++++-------- src/utils/pencilHelper.js | 141 +++++++++++++++++++++++ temp.md | 101 ++++++++++++++++ 6 files changed, 392 insertions(+), 64 deletions(-) create mode 100644 src/utils/pencilHelper.js create mode 100644 temp.md diff --git a/src/components/elements/groupobject.js b/src/components/elements/groupobject.js index 4ac163b..801c2a7 100644 --- a/src/components/elements/groupobject.js +++ b/src/components/elements/groupobject.js @@ -119,8 +119,9 @@ function GroupedObjectWrapper(props) { if (element.elementData.componentType === 'pencil') { newMetadata = element.elementData.metadata.map( (vert, index) => { + const lwProp = vert.lw !== undefined ? { lw: vert.lw } : {} if (index === 0) { - return { x: newX, y: newY } + return { x: newX, y: newY, ...lwProp } } else if (index > 0) { // here the logic is to get relative vertex coordinates to the original metadata // so we want to get result of ( relative coordinate + orginal_vert(x) - originalX ) @@ -141,6 +142,7 @@ function GroupedObjectWrapper(props) { element.elementData .metadata[0].y ), + ...lwProp, } } } diff --git a/src/components/elements/pencil.js b/src/components/elements/pencil.js index c37e805..f657a4a 100644 --- a/src/components/elements/pencil.js +++ b/src/components/elements/pencil.js @@ -59,15 +59,16 @@ function Pencil(props) { }) // Get all instances of every sub child element const { group, path } = elementFactory.createElement() + const shapeRef = path || group.children[0] group.elementData = { ...props.itemData, ...props } if (props.parentGroup) { /** This element will be rendered and scoped in its parent group */ console.log('properties of pencil', props) const parentGroup = props.parentGroup - path.translation.x = props.properties.x - path.translation.y = props.properties.y - parentGroup.add(path) + shapeRef.translation.x = props.properties.x + shapeRef.translation.y = props.properties.y + parentGroup.add(shapeRef) two.update() } else { /** This element will render by creating it's own group wrapper */ @@ -76,7 +77,9 @@ function Pencil(props) { const { selector } = getEditComponents(two, group, 4) selectorInstance = selector - group.children.unshift(path) + if (path) { + group.children.unshift(path) + } two.update() // document @@ -100,7 +103,7 @@ function Pencil(props) { setInternalState((draft) => { draft.element = { - [path.id]: path, + [shapeRef.id]: shapeRef, [group.id]: group, // [selector.id]: selector, } @@ -109,8 +112,8 @@ function Pencil(props) { data: group, } draft.shape = { - id: path.id, - data: path, + id: shapeRef.id, + data: shapeRef, } draft.text = { data: {}, diff --git a/src/factory/pencil.js b/src/factory/pencil.js index 7cd917a..a959aaa 100644 --- a/src/factory/pencil.js +++ b/src/factory/pencil.js @@ -1,6 +1,6 @@ import Main from './main' -import { color_blue } from 'utils/constants' import Two from 'two.js' +import { mergeSegmentsByLinewidth, averageLinewidth } from 'utils/pencilHelper' export default class PencilFactory extends Main { createElement() { @@ -10,7 +10,37 @@ export default class PencilFactory extends Main { const { fill, width, height, radius, stroke, linewidth, metadata } = this.properties - // let paths = [] + const hasLwData = metadata.length > 0 && metadata[0].lw !== undefined + + if (hasLwData) { + // New format: multi-path rendering with variable linewidth + const segments = mergeSegmentsByLinewidth(metadata) + const group = two.makeGroup() + + segments.forEach((segmentPoints) => { + if (segmentPoints.length < 2) return + const path = two.makePath() + segmentPoints.forEach((point) => { + path.vertices.push( + new Two.Vector(point.x - prevX, point.y - prevY) + ) + }) + path.noFill() + path.stroke = stroke || '#000' + path.closed = false + path.cap = 'round' + path.join = 'round' + path.linewidth = averageLinewidth(segmentPoints) + group.add(path) + }) + + group.translation.x = parseInt(prevX) + group.translation.y = parseInt(prevY) + this.group = group + return { group: this.group } + } + + // Legacy format: single path with uniform linewidth (backward compatible) let path = two.makePath() if (metadata.length > 0) { metadata.forEach(function (point) { @@ -21,21 +51,15 @@ export default class PencilFactory extends Main { path.noFill() path.stroke = '#000' path.closed = false - // two.add(path) - // paths.push(path) } - // path.fill = fill ? fill : color_blue - path.linewidth = linewidth ? linewidth : 1 this.path = path - // Create group and take children elements as a parameter const group = two.makeGroup(path) group.translation.x = parseInt(prevX) group.translation.y = parseInt(prevY) this.group = group - console.log('group.id pencil', group.id) return { group: this.group, path } } } diff --git a/src/newCanvas.js b/src/newCanvas.js index 8dac2fc..080e035 100644 --- a/src/newCanvas.js +++ b/src/newCanvas.js @@ -13,6 +13,11 @@ import Spinner from 'components/common/spinner' import Loader from 'components/utils/loader' import { updateX1Y1Vertices, updateX2Y2Vertices } from 'utils/updateVertices' import { generateUUID } from 'utils/misc' +import { + velocityToLinewidth, + smoothLinewidth, + simplifyWithLinewidth, +} from 'utils/pencilHelper' function getComponentSchema(obj, boardId) { let generateId = generateUUID() @@ -86,6 +91,13 @@ function addZUI( let lastAddedPath let paths = [] + // Velocity-based pencil state + let pencilGroup = null + let pencilRawPoints = [] + let lastPencilPoint = null + let lastPencilTime = 0 + let lastPencilLinewidth = null + let scenario = null let SCENARIO_JUST_ADDED_ELEMENT = 'justAddedElement' let SCENARIO_PENCIL_MODE = 'pencilMode' @@ -304,17 +316,25 @@ function addZUI( document.getElementById('main-two-root').style.cursor = 'auto' break - case SCENARIO_PENCIL_MODE: - // do here + case SCENARIO_PENCIL_MODE: { domElement.addEventListener('mousemove', mousemove, false) domElement.addEventListener('mouseup', mouseup, false) - currentPath = two.makePath() - currentPath.linewidth = defaultLinewidthValue - currentPath.closed = false - two.add(currentPath) - paths.push(currentPath) + // Create a group for live preview segments + pencilGroup = two.makeGroup() + pencilRawPoints = [] + lastPencilLinewidth = defaultLinewidthValue + + const startCoords = zui.clientToSurface(e.clientX, e.clientY) + lastPencilPoint = { x: startCoords.x, y: startCoords.y } + lastPencilTime = performance.now() + pencilRawPoints.push({ + x: startCoords.x, + y: startCoords.y, + lw: lastPencilLinewidth, + }) break + } default: shape = null mouse.x = e.clientX @@ -667,19 +687,49 @@ function addZUI( two.update() } break - case SCENARIO_PENCIL_MODE: - let getCoordinate = zui.clientToSurface(e.clientX, e.clientY) - - currentPath.vertices.push( - new Two.Vector(getCoordinate.x, getCoordinate.y) + case SCENARIO_PENCIL_MODE: { + const pencilCoords = zui.clientToSurface(e.clientX, e.clientY) + + // Distance throttle: skip if too close to last point + const pdx = pencilCoords.x - lastPencilPoint.x + const pdy = pencilCoords.y - lastPencilPoint.y + const pDist = Math.sqrt(pdx * pdx + pdy * pdy) + if (pDist < 3) break + + // Compute velocity and map to linewidth + const now = performance.now() + const timeDelta = now - lastPencilTime + const velocity = timeDelta > 0 ? pDist / timeDelta : 0 + const targetLw = velocityToLinewidth(velocity, defaultLinewidthValue) + const smoothedLw = smoothLinewidth(lastPencilLinewidth, targetLw, 0.3) + + // Create a 2-point path segment for live preview + const segment = two.makePath( + lastPencilPoint.x, lastPencilPoint.y, + pencilCoords.x, pencilCoords.y ) - currentPath.vertices[currentPath.vertices.length - 1].command = - 'L' - currentPath.noFill() - currentPath.stroke = '#000' - currentPath.linewidth = defaultLinewidthValue + segment.noFill() + segment.stroke = '#000' + segment.linewidth = smoothedLw + segment.cap = 'round' + segment.join = 'round' + segment.closed = false + pencilGroup.add(segment) + + // Record point with linewidth + pencilRawPoints.push({ + x: pencilCoords.x, + y: pencilCoords.y, + lw: smoothedLw, + }) + + lastPencilPoint = { x: pencilCoords.x, y: pencilCoords.y } + lastPencilTime = now + lastPencilLinewidth = smoothedLw + two.update() break + } default: /** Currently "resize" event handling is at component level. @@ -1056,48 +1106,53 @@ function addZUI( domElement.removeEventListener('mousemove', mousemove, false) domElement.removeEventListener('mouseup', mouseup, false) break - case SCENARIO_PENCIL_MODE: - // isDrawing = false - // console.log( - // 'on mouse up pencil mode', - // paths, - // currentPath.vertices, - // currentPath.translation - // ) - - let generateId = generateUUID() - let componentData = { - id: generateId, + case SCENARIO_PENCIL_MODE: { + // Remove live preview group — React component will re-render from metadata + if (pencilGroup) { + two.remove(pencilGroup) + } + + if (pencilRawPoints.length < 2) { + // Too few points to form a stroke + pencilGroup = null + pencilRawPoints = [] + lastPencilPoint = null + lastPencilLinewidth = null + break + } + + // Simplify points while preserving lw + const simplifiedPoints = simplifyWithLinewidth(pencilRawPoints, 1.5) + + let pencilId = generateUUID() + let pencilComponentData = { + id: pencilId, boardId: props.boardId, componentType: 'pencil', children: {}, - metadata: [], + metadata: simplifiedPoints, x: 0, y: 0, - linewidth: currentPath.linewidth, - stroke: currentPath.stroke, + linewidth: defaultLinewidthValue, + stroke: '#000', } - componentData.metadata = currentPath.vertices.map( - function (vertex) { - return { x: vertex.x, y: vertex.y } - } - ) - componentData.x = Math.floor(componentData.metadata[0]?.x || 0) - componentData.y = Math.floor(componentData.metadata[0]?.y || 0) + pencilComponentData.x = Math.floor(simplifiedPoints[0]?.x || 0) + pencilComponentData.y = Math.floor(simplifiedPoints[0]?.y || 0) addToLocalComponentStore( - componentData.id, - componentData.componentType, - componentData + pencilComponentData.id, + pencilComponentData.componentType, + pencilComponentData ) - // let currentPathRef = currentPath - // setTimeout(() => { - // two.remove(currentPathRef) - // two.update() - // }, 5000) + // Reset pencil state + pencilGroup = null + pencilRawPoints = [] + lastPencilPoint = null + lastPencilLinewidth = null break + } default: // diff to check new x,y and prev x,y let oldShapeData = {} @@ -1546,8 +1601,9 @@ const Canvas = (props) => { let newMetadata = [] if (item.componentType === 'pencil') { newMetadata = item.metadata.map((vert, index) => { + const lwProp = vert.lw !== undefined ? { lw: vert.lw } : {} if (index === 0) { - return { x: relativeX, y: relativeY } + return { x: relativeX, y: relativeY, ...lwProp } } else if (index > 0) { // here the logic is to get relative vertex coordinates to the original metadata // so we want to get result of ( relative coordinate + orginal_vert(x) - originalX ) @@ -1560,6 +1616,7 @@ const Canvas = (props) => { y: relativeY + parseInt(vert.y - item.metadata[0].y), + ...lwProp, } } }) diff --git a/src/utils/pencilHelper.js b/src/utils/pencilHelper.js new file mode 100644 index 0000000..c2b1b13 --- /dev/null +++ b/src/utils/pencilHelper.js @@ -0,0 +1,141 @@ +/** + * Pencil helper utilities for velocity-based variable stroke width. + * + * Slow drawing = thick lines, fast drawing = thin lines. + */ + +// Velocity thresholds (px/ms) +const SLOW_VELOCITY = 0.1 +const FAST_VELOCITY = 1.5 + +/** + * Maps drawing velocity (px/ms) to a linewidth. + * Slow = thick (baseWidth * 2), fast = thin (baseWidth * 0.5). + */ +export function velocityToLinewidth(velocity, baseWidth) { + const maxWidth = baseWidth * 2.5 + const minWidth = baseWidth * 0.5 + + // Clamp velocity to range + const clampedVelocity = Math.max( + SLOW_VELOCITY, + Math.min(FAST_VELOCITY, velocity) + ) + + // Linear interpolation: slow -> maxWidth, fast -> minWidth + const t = + (clampedVelocity - SLOW_VELOCITY) / (FAST_VELOCITY - SLOW_VELOCITY) + return maxWidth - t * (maxWidth - minWidth) +} + +/** + * Exponential moving average to smooth linewidth transitions. + */ +export function smoothLinewidth(prevWidth, targetWidth, factor = 0.3) { + return prevWidth + factor * (targetWidth - prevWidth) +} + +/** + * Perpendicular distance from a point to a line segment (for RDP algorithm). + */ +function perpendicularDistance(point, lineStart, lineEnd) { + const dx = lineEnd.x - lineStart.x + const dy = lineEnd.y - lineStart.y + + if (dx === 0 && dy === 0) { + return Math.sqrt( + (point.x - lineStart.x) ** 2 + (point.y - lineStart.y) ** 2 + ) + } + + const t = + ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / + (dx * dx + dy * dy) + const clampedT = Math.max(0, Math.min(1, t)) + const projX = lineStart.x + clampedT * dx + const projY = lineStart.y + clampedT * dy + + return Math.sqrt((point.x - projX) ** 2 + (point.y - projY) ** 2) +} + +/** + * Ramer-Douglas-Peucker simplification that preserves {x, y, lw} tuples. + */ +export function simplifyWithLinewidth(points, epsilon) { + if (points.length <= 2) return points + + let maxDist = 0 + let maxIndex = 0 + + for (let i = 1; i < points.length - 1; i++) { + const dist = perpendicularDistance( + points[i], + points[0], + points[points.length - 1] + ) + if (dist > maxDist) { + maxDist = dist + maxIndex = i + } + } + + if (maxDist > epsilon) { + const left = simplifyWithLinewidth( + points.slice(0, maxIndex + 1), + epsilon + ) + const right = simplifyWithLinewidth(points.slice(maxIndex), epsilon) + return left.slice(0, -1).concat(right) + } + + return [points[0], points[points.length - 1]] +} + +/** + * Groups consecutive points with similar linewidths into longer path segments. + * Adjacent groups share an overlap point to prevent visual gaps. + * + * Returns array of point arrays, each representing one path segment. + */ +export function mergeSegmentsByLinewidth(points, lwTolerance = 0.3) { + if (points.length <= 1) return [points] + + const segments = [] + let currentSegment = [points[0]] + + for (let i = 1; i < points.length; i++) { + const prevLw = currentSegment[currentSegment.length - 1].lw || 1 + const currLw = points[i].lw || 1 + + if ( + Math.abs(currLw - prevLw) / Math.max(prevLw, currLw) <= + lwTolerance + ) { + // Similar enough linewidth, keep in same segment + currentSegment.push(points[i]) + } else { + // Linewidth difference too large, start new segment + // Share overlap point to prevent gaps + segments.push(currentSegment) + currentSegment = [ + currentSegment[currentSegment.length - 1], + points[i], + ] + } + } + + if (currentSegment.length > 0) { + segments.push(currentSegment) + } + + return segments +} + +/** + * Computes the average linewidth for a segment of points. + */ +export function averageLinewidth(points) { + if (points.length === 0) return 1 + const sum = points.reduce((acc, p) => acc + (p.lw || 1), 0) + return sum / points.length +} diff --git a/temp.md b/temp.md new file mode 100644 index 0000000..1af27b6 --- /dev/null +++ b/temp.md @@ -0,0 +1,101 @@ +Plan: Velocity-Based Variable Stroke Width for Pencil Tool + +Context + +The pencil tool currently draws strokes as a single Two.Path with uniform linewidth, resulting in flat, polygon-like lines. The goal is to make strokes feel natural and sketchy +by varying the stroke width based on drawing velocity: slow = thick, fast = thin. + +Since Two.js does not support per-vertex linewidth on a single path, we'll use multiple short path segments, each with its own linewidth derived from velocity. Consecutive +segments with similar widths are merged to keep path count low. + +Files to Modify + +File: src/utils/pencilHelper.js +Change: Add velocity-to-linewidth mapping, smoothing, and linewidth-aware simplification/merging utilities +──────────────────────────────────────── +File: src/newCanvas.js +Change: Rewrite pencil mousedown/mousemove/mouseup to track velocity and create per-segment paths; preserve lw in group selector metadata remapping +──────────────────────────────────────── +File: src/factory/pencil.js +Change: Reconstruct strokes as merged multi-path groups; backward-compatible with old {x,y} metadata +──────────────────────────────────────── +File: src/components/elements/pencil.js +Change: Adapt to factory returning {group} without a single path +──────────────────────────────────────── +File: src/components/elements/groupobject.js +Change: Preserve lw property during metadata remapping (~line 120-144) + +Implementation Details + +1. src/utils/pencilHelper.js — New utilities + +Add alongside existing simplifyPath and perpendicularDistance: + +- velocityToLinewidth(velocity, baseWidth) — Maps px/ms velocity to linewidth using linear interpolation between MAX_WIDTH (baseWidth _ 2.5) at slow speeds and MIN_WIDTH + (baseWidth _ 0.25) at fast speeds +- smoothLinewidth(prevWidth, targetWidth, factor=0.3) — Exponential moving average to prevent jarring width jumps between consecutive segments +- simplifyWithLinewidth(points, epsilon) — Modified RDP that preserves {x, y, lw} tuples +- mergeSegmentsByLinewidth(points, lwTolerance=0.3) — Groups consecutive points with similar linewidths into longer path segments for performance. Adjacent groups share an + overlap point to prevent visual gaps + +2. src/newCanvas.js — Drawing flow changes + +New variables (in addZUI, near line 88): + +- pencilSegments, pencilRawPoints, lastPencilPoint, lastPencilLinewidth, pencilGroup + +mousedown (~line 309): + +- Create a two.makeGroup() instead of a single path +- Record first point with timestamp via performance.now() + +mousemove (~line 685): + +- Keep 3px distance throttle +- Compute velocity = distance / time-delta between consecutive points +- Map velocity to linewidth via velocityToLinewidth(), smooth via smoothLinewidth() +- Create a 2-point two.makePath() segment with cap='round', join='round', closed=false +- Add segment to pencilGroup, record point as {x, y, lw} in pencilRawPoints + +mouseup (~line 1085): + +- Remove live pencilGroup from canvas (React component will re-render from metadata) +- Run simplifyWithLinewidth(pencilRawPoints, 1.5) to reduce point count while keeping lw +- Save component with metadata: [{x, y, lw}, ...] +- Reset all pencil state variables + +Group selector (~line 1573-1591): + +- Spread lw property through during metadata coordinate remapping: ...(vert.lw !== undefined ? { lw: vert.lw } : {}) + +3. src/factory/pencil.js — Reconstruction + +- Detect format: if metadata[0].lw !== undefined, use new multi-path rendering +- New format: Call mergeSegmentsByLinewidth() to group points, create one Two.Path per group with averaged linewidth, cap='round', join='round' +- Legacy format: Keep existing single-path behavior unchanged (backward compatible) +- Return { group } (no single path reference) + +4. src/components/elements/pencil.js — Minor adaptation + +- Change const { group, path } = elementFactory.createElement() to const { group } = elementFactory.createElement() +- Use group.children[0] as the shape reference for internal state + +5. src/components/elements/groupobject.js — Preserve lw + +- In metadata remapping (~line 120-144), spread lw property: ...(vert.lw !== undefined ? { lw: vert.lw } : {}) + +Performance + +- Typical stroke: ~60-80 raw points after distance throttle -> ~20-30 after simplification -> ~8-15 merged path groups +- During live drawing, ~60-80 temporary 2-point segments (removed on mouseup) +- No database schema changes needed (metadata is JSONB) + +Verification + +1. Run npm start and open a board +2. Activate pencil mode and draw strokes at varying speeds +3. Verify: slow strokes are thick, fast strokes are thin, transitions are smooth +4. Reload the page — verify strokes reconstruct correctly from saved metadata +5. Test backward compatibility: existing pencil drawings should render unchanged +6. Test group selection: select area containing pencil strokes, verify they group/ungroup correctly + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ From 43956d0fb6bd462e53efdbb9716276660e87efe8 Mon Sep 17 00:00:00 2001 From: meetzaveri Date: Sun, 22 Feb 2026 17:14:12 +0530 Subject: [PATCH 2/3] update: add toolbar support for pencil draw --- src/newCanvas.js | 9 +++-- src/views/Board/board.js | 71 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/newCanvas.js b/src/newCanvas.js index 080e035..0ddec48 100644 --- a/src/newCanvas.js +++ b/src/newCanvas.js @@ -64,6 +64,7 @@ function getComponentSchema(obj, boardId) { var isDrawing var defaultLinewidthValue = 1 +var pencilStrokeColorValue = '#000' function addZUI( props, @@ -709,7 +710,7 @@ function addZUI( pencilCoords.x, pencilCoords.y ) segment.noFill() - segment.stroke = '#000' + segment.stroke = pencilStrokeColorValue segment.linewidth = smoothedLw segment.cap = 'round' segment.join = 'round' @@ -1134,7 +1135,7 @@ function addZUI( x: 0, y: 0, linewidth: defaultLinewidthValue, - stroke: '#000', + stroke: pencilStrokeColorValue, } pencilComponentData.x = Math.floor(simplifiedPoints[0]?.x || 0) @@ -1551,6 +1552,10 @@ const Canvas = (props) => { defaultLinewidthValue = props.defaultLinewidth || 1 }, [props.defaultLinewidth]) + useEffect(() => { + pencilStrokeColorValue = props.pencilStrokeColor || '#000' + }, [props.pencilStrokeColor]) + // on group select use effect hook useEffect(() => { // let componentsArr = [...currentComponents] diff --git a/src/views/Board/board.js b/src/views/Board/board.js index ace462d..0927f8d 100644 --- a/src/views/Board/board.js +++ b/src/views/Board/board.js @@ -21,6 +21,7 @@ import Canvas from '../../newCanvas' import Sidebar from 'components/sidebar/primary' import Toolbar from 'components/floatingToolbar' import Spinner from 'components/common/spinnerWithSize' +import ColorPicker from 'components/utils/colorPicker' import { generateRandomUsernames } from 'utils/misc' const BoardContext = createContext() @@ -78,10 +79,7 @@ const BoardViewPage = (props) => { const [ createBoard, - { - loading: createBoardLoading, - data: createBoardData, - }, + { loading: createBoardLoading, data: createBoardData }, ] = useMutation(CREATE_BOARD) const [componentStore, setComponentStore] = useState({}) @@ -94,6 +92,7 @@ const BoardViewPage = (props) => { const [twoJSInstance, setTwoJSInstance] = useState(null) const [selectedComponent, setSelectedComponent] = useState(null) const [defaultLinewidth, setDefaultLinewidth] = useState(2) + const [pencilStrokeColor, setPencilStrokeColor] = useState('#000') const [currentElement, setCurrentElement] = useState(null) const { isDesktop, isMobile, isLaptop, isTablet } = useMediaQueryUtils() @@ -336,6 +335,10 @@ const BoardViewPage = (props) => { setDefaultLinewidth(val) } + const setPencilStrokeColorInBoard = (val) => { + setPencilStrokeColor(val) + } + const setCurrentElementInBoard = (val) => { setCurrentElement(val) } @@ -363,6 +366,26 @@ const BoardViewPage = (props) => { }) } + const renderBorderWidths = () => { + const widths = [0, 2, 4, 8].map((width, index) => { + return ( + + + + ) + }) + return widths + } + const isArrowSelected = selectedComponent !== null && (selectedComponent?.shape?.type === 'arrowLine' || @@ -387,6 +410,8 @@ const BoardViewPage = (props) => { setSelectedComponentInBoard, defaultLinewidth, setDefaultLinewidthInBoard, + pencilStrokeColor, + setPencilStrokeColorInBoard, currentElement, setCurrentElementInBoard, onCreateBoard, @@ -412,6 +437,43 @@ const BoardViewPage = (props) => { }} /> )} + {isPencilMode && ( +
+ { + setPencilStrokeColor(color) + }} + /> +
+
+ +
+ {renderBorderWidths()} +
+
+
+ )} { lastAddedElement={lastAddedElement} componentStore={componentStore} defaultLinewidth={defaultLinewidth} + pencilStrokeColor={pencilStrokeColor} /> From 65f996b31345b9457708b519c195878ae691415e Mon Sep 17 00:00:00 2001 From: meetzaveri Date: Sun, 22 Feb 2026 17:16:43 +0530 Subject: [PATCH 3/3] fix: bump version --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 5d4294b..2411653 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.1 \ No newline at end of file +0.5.2 \ No newline at end of file