@tsdraw/react 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,6 +1,22 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { CSSProperties, ReactNode } from 'react';
3
- import { ToolId, Editor, ColorStyle, DashStyle, SizeStyle, ToolDefinition } from '@tsdraw/core';
2
+ import { ReactNode, CSSProperties } from 'react';
3
+ import { ColorStyle, DashStyle, FillStyle, SizeStyle, ToolId, Editor, ToolDefinition } from '@tsdraw/core';
4
+
5
+ type TsdrawStylePanelPartItem = 'colors' | 'dashes' | 'fills' | 'sizes' | (string & {});
6
+ interface TsdrawStylePanelRenderContext {
7
+ drawColor: ColorStyle;
8
+ drawDash: DashStyle;
9
+ drawFill: FillStyle;
10
+ drawSize: SizeStyle;
11
+ onColorSelect: (color: ColorStyle) => void;
12
+ onDashSelect: (dash: DashStyle) => void;
13
+ onFillSelect: (fill: FillStyle) => void;
14
+ onSizeSelect: (size: SizeStyle) => void;
15
+ }
16
+ interface TsdrawStylePanelCustomPart {
17
+ id: string;
18
+ render: (context: TsdrawStylePanelRenderContext) => ReactNode;
19
+ }
4
20
 
5
21
  interface TsdrawCursorContext {
6
22
  currentTool: ToolId;
@@ -32,6 +48,7 @@ interface TsdrawMountApi {
32
48
  applyDrawStyle: (partial: Partial<{
33
49
  color: ColorStyle;
34
50
  dash: DashStyle;
51
+ fill: FillStyle;
35
52
  size: SizeStyle;
36
53
  }>) => void;
37
54
  }
@@ -45,7 +62,10 @@ interface TsdrawCustomTool {
45
62
  icon: ReactNode;
46
63
  iconSelected?: ReactNode;
47
64
  definition: ToolDefinition;
48
- showStylePanel?: boolean;
65
+ stylePanel?: {
66
+ parts?: TsdrawStylePanelPartItem[];
67
+ customParts?: TsdrawStylePanelCustomPart[];
68
+ };
49
69
  }
50
70
  type TsdrawToolbarBuiltInAction = 'undo' | 'redo';
51
71
  type ToolbarPartItem = ToolId | TsdrawToolbarBuiltInAction;
@@ -57,10 +77,12 @@ interface TsdrawUiPlacement {
57
77
  }
58
78
  interface TsdrawUiOptions {
59
79
  toolbar?: {
80
+ hide?: boolean;
60
81
  placement?: TsdrawUiPlacement;
61
82
  parts?: ToolbarPartItem[][];
62
83
  };
63
84
  stylePanel?: {
85
+ hide?: boolean;
64
86
  placement?: TsdrawUiPlacement;
65
87
  };
66
88
  customElements?: TsdrawCustomElement[];
@@ -81,6 +103,7 @@ interface TsdrawCustomElementRenderArgs {
81
103
  applyDrawStyle: (partial: Partial<{
82
104
  color: ColorStyle;
83
105
  dash: DashStyle;
106
+ fill: FillStyle;
84
107
  size: SizeStyle;
85
108
  }>) => void;
86
109
  }
@@ -125,4 +148,4 @@ interface ToolbarPart {
125
148
  }
126
149
  declare function getDefaultToolbarIcon(toolId: ToolId, isActive: boolean): ReactNode;
127
150
 
128
- export { type ToolbarActionItem, type ToolbarPart, type ToolbarPartItem, type ToolbarRenderItem, type ToolbarToolItem, Tsdraw, TsdrawCanvas, type TsdrawCanvasProps, type TsdrawCursorContext, type TsdrawCustomElement, type TsdrawCustomElementRenderArgs, type TsdrawCustomTool, type TsdrawMountApi, type TsdrawProps, type TsdrawToolOverlayState, type TsdrawToolbarBuiltInAction, type TsdrawUiOptions, type TsdrawUiPlacement, type UiAnchor, getDefaultToolbarIcon };
151
+ export { type ToolbarActionItem, type ToolbarPart, type ToolbarPartItem, type ToolbarRenderItem, type ToolbarToolItem, Tsdraw, TsdrawCanvas, type TsdrawCanvasProps, type TsdrawCursorContext, type TsdrawCustomElement, type TsdrawCustomElementRenderArgs, type TsdrawCustomTool, type TsdrawMountApi, type TsdrawProps, type TsdrawStylePanelCustomPart, type TsdrawStylePanelPartItem, type TsdrawStylePanelRenderContext, type TsdrawToolOverlayState, type TsdrawToolbarBuiltInAction, type TsdrawUiOptions, type TsdrawUiPlacement, type UiAnchor, getDefaultToolbarIcon };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,22 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { CSSProperties, ReactNode } from 'react';
3
- import { ToolId, Editor, ColorStyle, DashStyle, SizeStyle, ToolDefinition } from '@tsdraw/core';
2
+ import { ReactNode, CSSProperties } from 'react';
3
+ import { ColorStyle, DashStyle, FillStyle, SizeStyle, ToolId, Editor, ToolDefinition } from '@tsdraw/core';
4
+
5
+ type TsdrawStylePanelPartItem = 'colors' | 'dashes' | 'fills' | 'sizes' | (string & {});
6
+ interface TsdrawStylePanelRenderContext {
7
+ drawColor: ColorStyle;
8
+ drawDash: DashStyle;
9
+ drawFill: FillStyle;
10
+ drawSize: SizeStyle;
11
+ onColorSelect: (color: ColorStyle) => void;
12
+ onDashSelect: (dash: DashStyle) => void;
13
+ onFillSelect: (fill: FillStyle) => void;
14
+ onSizeSelect: (size: SizeStyle) => void;
15
+ }
16
+ interface TsdrawStylePanelCustomPart {
17
+ id: string;
18
+ render: (context: TsdrawStylePanelRenderContext) => ReactNode;
19
+ }
4
20
 
5
21
  interface TsdrawCursorContext {
6
22
  currentTool: ToolId;
@@ -32,6 +48,7 @@ interface TsdrawMountApi {
32
48
  applyDrawStyle: (partial: Partial<{
33
49
  color: ColorStyle;
34
50
  dash: DashStyle;
51
+ fill: FillStyle;
35
52
  size: SizeStyle;
36
53
  }>) => void;
37
54
  }
@@ -45,7 +62,10 @@ interface TsdrawCustomTool {
45
62
  icon: ReactNode;
46
63
  iconSelected?: ReactNode;
47
64
  definition: ToolDefinition;
48
- showStylePanel?: boolean;
65
+ stylePanel?: {
66
+ parts?: TsdrawStylePanelPartItem[];
67
+ customParts?: TsdrawStylePanelCustomPart[];
68
+ };
49
69
  }
50
70
  type TsdrawToolbarBuiltInAction = 'undo' | 'redo';
51
71
  type ToolbarPartItem = ToolId | TsdrawToolbarBuiltInAction;
@@ -57,10 +77,12 @@ interface TsdrawUiPlacement {
57
77
  }
58
78
  interface TsdrawUiOptions {
59
79
  toolbar?: {
80
+ hide?: boolean;
60
81
  placement?: TsdrawUiPlacement;
61
82
  parts?: ToolbarPartItem[][];
62
83
  };
63
84
  stylePanel?: {
85
+ hide?: boolean;
64
86
  placement?: TsdrawUiPlacement;
65
87
  };
66
88
  customElements?: TsdrawCustomElement[];
@@ -81,6 +103,7 @@ interface TsdrawCustomElementRenderArgs {
81
103
  applyDrawStyle: (partial: Partial<{
82
104
  color: ColorStyle;
83
105
  dash: DashStyle;
106
+ fill: FillStyle;
84
107
  size: SizeStyle;
85
108
  }>) => void;
86
109
  }
@@ -125,4 +148,4 @@ interface ToolbarPart {
125
148
  }
126
149
  declare function getDefaultToolbarIcon(toolId: ToolId, isActive: boolean): ReactNode;
127
150
 
128
- export { type ToolbarActionItem, type ToolbarPart, type ToolbarPartItem, type ToolbarRenderItem, type ToolbarToolItem, Tsdraw, TsdrawCanvas, type TsdrawCanvasProps, type TsdrawCursorContext, type TsdrawCustomElement, type TsdrawCustomElementRenderArgs, type TsdrawCustomTool, type TsdrawMountApi, type TsdrawProps, type TsdrawToolOverlayState, type TsdrawToolbarBuiltInAction, type TsdrawUiOptions, type TsdrawUiPlacement, type UiAnchor, getDefaultToolbarIcon };
151
+ export { type ToolbarActionItem, type ToolbarPart, type ToolbarPartItem, type ToolbarRenderItem, type ToolbarToolItem, Tsdraw, TsdrawCanvas, type TsdrawCanvasProps, type TsdrawCursorContext, type TsdrawCustomElement, type TsdrawCustomElementRenderArgs, type TsdrawCustomTool, type TsdrawMountApi, type TsdrawProps, type TsdrawStylePanelCustomPart, type TsdrawStylePanelPartItem, type TsdrawStylePanelRenderContext, type TsdrawToolOverlayState, type TsdrawToolbarBuiltInAction, type TsdrawUiOptions, type TsdrawUiPlacement, type UiAnchor, getDefaultToolbarIcon };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { useState, useMemo, useEffect, useCallback, useRef } from 'react';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import { DEFAULT_COLORS, getSelectionBoundsPage, buildTransformSnapshots, Editor, STROKE_WIDTHS, ERASER_MARGIN, resolveThemeColor, getTopShapeAtPoint, buildStartPositions, applyRotation, applyResize, applyMove, normalizeSelectionBounds, getShapesInBounds, isSelectTool } from '@tsdraw/core';
4
- import { IconPointer, IconPencil, IconEraser, IconHandStop, IconArrowBackUp, IconArrowForwardUp } from '@tabler/icons-react';
4
+ import { IconPointer, IconPencil, IconSquare, IconCircle, IconEraser, IconHandStop, IconArrowBackUp, IconArrowForwardUp } from '@tabler/icons-react';
5
5
 
6
6
  // src/components/TsdrawCanvas.tsx
7
7
  function SelectionOverlay({
@@ -98,66 +98,106 @@ function SelectionOverlay({
98
98
  }
99
99
  var STYLE_COLORS = Object.entries(DEFAULT_COLORS).filter(([key]) => key !== "white").map(([value]) => ({ value }));
100
100
  var STYLE_DASHES = ["draw", "solid", "dashed", "dotted"];
101
+ var STYLE_FILLS = ["none", "blank", "semi", "solid"];
101
102
  var STYLE_SIZES = ["s", "m", "l", "xl"];
102
103
  function StylePanel({
103
104
  visible,
105
+ parts,
106
+ customParts,
104
107
  style,
105
108
  theme,
106
109
  drawColor,
107
110
  drawDash,
111
+ drawFill,
108
112
  drawSize,
109
113
  onColorSelect,
110
114
  onDashSelect,
115
+ onFillSelect,
111
116
  onSizeSelect
112
117
  }) {
113
- if (!visible) return null;
114
- return /* @__PURE__ */ jsxs("div", { className: "tsdraw-style-panel", style, "aria-label": "Draw style panel", children: [
115
- /* @__PURE__ */ jsx("div", { className: "tsdraw-style-colors", children: STYLE_COLORS.map((item) => /* @__PURE__ */ jsx(
116
- "button",
117
- {
118
- type: "button",
119
- className: "tsdraw-style-color",
120
- "data-active": drawColor === item.value ? "true" : void 0,
121
- "aria-label": `Color ${item.value}`,
122
- title: item.value,
123
- onClick: () => onColorSelect(item.value),
124
- children: /* @__PURE__ */ jsx(
125
- "span",
126
- {
127
- className: "tsdraw-style-color-dot",
128
- style: { background: resolveThemeColor(item.value, theme) }
129
- }
130
- )
131
- },
132
- item.value
133
- )) }),
134
- /* @__PURE__ */ jsx("div", { className: "tsdraw-style-section", children: STYLE_DASHES.map((dash) => /* @__PURE__ */ jsx(
135
- "button",
136
- {
137
- type: "button",
138
- className: "tsdraw-style-row",
139
- "data-active": drawDash === dash ? "true" : void 0,
140
- "aria-label": `Stroke ${dash}`,
141
- title: dash,
142
- onClick: () => onDashSelect(dash),
143
- children: /* @__PURE__ */ jsx("span", { className: "tsdraw-style-preview", children: /* @__PURE__ */ jsx("span", { className: `tsdraw-style-preview-line tsdraw-style-preview-line--${dash}` }) })
144
- },
145
- dash
146
- )) }),
147
- /* @__PURE__ */ jsx("div", { className: "tsdraw-style-section", children: STYLE_SIZES.map((size) => /* @__PURE__ */ jsx(
148
- "button",
149
- {
150
- type: "button",
151
- className: "tsdraw-style-row",
152
- "data-active": drawSize === size ? "true" : void 0,
153
- "aria-label": `Thickness ${size}`,
154
- title: size,
155
- onClick: () => onSizeSelect(size),
156
- children: /* @__PURE__ */ jsx("span", { className: "tsdraw-style-preview", children: /* @__PURE__ */ jsx("span", { className: `tsdraw-style-size tsdraw-style-size--${size}` }) })
157
- },
158
- size
159
- )) })
160
- ] });
118
+ if (!visible || parts.length === 0) return null;
119
+ const context = {
120
+ drawColor,
121
+ drawDash,
122
+ drawFill,
123
+ drawSize,
124
+ onColorSelect,
125
+ onDashSelect,
126
+ onFillSelect,
127
+ onSizeSelect
128
+ };
129
+ const customPartMap = new Map((customParts ?? []).map((customPart) => [customPart.id, customPart]));
130
+ return /* @__PURE__ */ jsx("div", { className: "tsdraw-style-panel", style, "aria-label": "Draw style panel", children: parts.map((part) => {
131
+ if (part === "colors") {
132
+ return /* @__PURE__ */ jsx("div", { className: "tsdraw-style-colors", children: STYLE_COLORS.map((item) => /* @__PURE__ */ jsx(
133
+ "button",
134
+ {
135
+ type: "button",
136
+ className: "tsdraw-style-color",
137
+ "data-active": drawColor === item.value ? "true" : void 0,
138
+ "aria-label": `Color ${item.value}`,
139
+ title: item.value,
140
+ onClick: () => onColorSelect(item.value),
141
+ children: /* @__PURE__ */ jsx(
142
+ "span",
143
+ {
144
+ className: "tsdraw-style-color-dot",
145
+ style: { background: resolveThemeColor(item.value, theme) }
146
+ }
147
+ )
148
+ },
149
+ item.value
150
+ )) }, part);
151
+ }
152
+ if (part === "dashes") {
153
+ return /* @__PURE__ */ jsx("div", { className: "tsdraw-style-section", children: STYLE_DASHES.map((dash) => /* @__PURE__ */ jsx(
154
+ "button",
155
+ {
156
+ type: "button",
157
+ className: "tsdraw-style-row",
158
+ "data-active": drawDash === dash ? "true" : void 0,
159
+ "aria-label": `Stroke ${dash}`,
160
+ title: dash,
161
+ onClick: () => onDashSelect(dash),
162
+ children: /* @__PURE__ */ jsx("span", { className: "tsdraw-style-preview", children: /* @__PURE__ */ jsx("span", { className: `tsdraw-style-preview-line tsdraw-style-preview-line--${dash}` }) })
163
+ },
164
+ dash
165
+ )) }, part);
166
+ }
167
+ if (part === "fills") {
168
+ return /* @__PURE__ */ jsx("div", { className: "tsdraw-style-section", children: STYLE_FILLS.map((fill) => /* @__PURE__ */ jsx(
169
+ "button",
170
+ {
171
+ type: "button",
172
+ className: "tsdraw-style-row",
173
+ "data-active": drawFill === fill ? "true" : void 0,
174
+ "aria-label": `Fill ${fill}`,
175
+ title: fill,
176
+ onClick: () => onFillSelect(fill),
177
+ children: /* @__PURE__ */ jsx("span", { className: "tsdraw-style-preview", children: /* @__PURE__ */ jsx("span", { className: `tsdraw-style-fill tsdraw-style-fill--${fill}` }) })
178
+ },
179
+ fill
180
+ )) }, part);
181
+ }
182
+ if (part === "sizes") {
183
+ return /* @__PURE__ */ jsx("div", { className: "tsdraw-style-section", children: STYLE_SIZES.map((size) => /* @__PURE__ */ jsx(
184
+ "button",
185
+ {
186
+ type: "button",
187
+ className: "tsdraw-style-row",
188
+ "data-active": drawSize === size ? "true" : void 0,
189
+ "aria-label": `Thickness ${size}`,
190
+ title: size,
191
+ onClick: () => onSizeSelect(size),
192
+ children: /* @__PURE__ */ jsx("span", { className: "tsdraw-style-preview", children: /* @__PURE__ */ jsx("span", { className: `tsdraw-style-size tsdraw-style-size--${size}` }) })
193
+ },
194
+ size
195
+ )) }, part);
196
+ }
197
+ const customPart = customPartMap.get(part);
198
+ if (!customPart) return null;
199
+ return /* @__PURE__ */ jsx("div", { className: "tsdraw-style-section tsdraw-style-section--custom", children: customPart.render(context) }, part);
200
+ }) });
161
201
  }
162
202
  function ToolOverlay({
163
203
  visible,
@@ -197,6 +237,8 @@ function ToolOverlay({
197
237
  function getDefaultToolbarIcon(toolId, isActive) {
198
238
  if (toolId === "select") return /* @__PURE__ */ jsx(IconPointer, { size: 16, stroke: 1.8, fill: isActive ? "currentColor" : "none" });
199
239
  if (toolId === "pen") return /* @__PURE__ */ jsx(IconPencil, { size: 16, stroke: 1.8, fill: isActive ? "currentColor" : "none" });
240
+ if (toolId === "square") return /* @__PURE__ */ jsx(IconSquare, { size: 16, stroke: 1.8, fill: isActive ? "currentColor" : "none" });
241
+ if (toolId === "circle") return /* @__PURE__ */ jsx(IconCircle, { size: 16, stroke: 1.8, fill: isActive ? "currentColor" : "none" });
200
242
  if (toolId === "eraser") return /* @__PURE__ */ jsx(IconEraser, { size: 16, stroke: 1.8, fill: isActive ? "currentColor" : "none" });
201
243
  if (toolId === "hand") return /* @__PURE__ */ jsx(IconHandStop, { size: 16, stroke: isActive ? 1 : 1.8, fill: isActive ? "currentColor" : "none", style: isActive ? { stroke: "#000000" } : void 0 });
202
244
  return null;
@@ -388,8 +430,6 @@ function resolveDrawColor(colorStyle, theme) {
388
430
  return resolveThemeColor(colorStyle, theme);
389
431
  }
390
432
  function useTsdrawCanvasController(options = {}) {
391
- const stylePanelToolIds = options.stylePanelToolIds ?? ["pen"];
392
- const stylePanelToolIdsRef = useRef(stylePanelToolIds);
393
433
  const onMountRef = useRef(options.onMount);
394
434
  const containerRef = useRef(null);
395
435
  const canvasRef = useRef(null);
@@ -424,6 +464,7 @@ function useTsdrawCanvasController(options = {}) {
424
464
  const [currentTool, setCurrentToolState] = useState(options.initialTool ?? "pen");
425
465
  const [drawColor, setDrawColor] = useState("black");
426
466
  const [drawDash, setDrawDash] = useState("draw");
467
+ const [drawFill, setDrawFill] = useState("none");
427
468
  const [drawSize, setDrawSize] = useState("m");
428
469
  const [selectedShapeIds, setSelectedShapeIds] = useState([]);
429
470
  const [selectionBrush, setSelectionBrush] = useState(null);
@@ -440,9 +481,6 @@ function useTsdrawCanvasController(options = {}) {
440
481
  useEffect(() => {
441
482
  currentToolRef.current = currentTool;
442
483
  }, [currentTool]);
443
- useEffect(() => {
444
- stylePanelToolIdsRef.current = stylePanelToolIds;
445
- }, [stylePanelToolIds]);
446
484
  useEffect(() => {
447
485
  onMountRef.current = options.onMount;
448
486
  }, [options.onMount]);
@@ -454,7 +492,7 @@ function useTsdrawCanvasController(options = {}) {
454
492
  }, [selectionRotationDeg]);
455
493
  useEffect(() => {
456
494
  schedulePersistRef.current?.();
457
- }, [selectedShapeIds, currentTool, drawColor, drawDash, drawSize]);
495
+ }, [selectedShapeIds, currentTool, drawColor, drawDash, drawFill, drawSize]);
458
496
  const render = useCallback(() => {
459
497
  const canvas = canvasRef.current;
460
498
  const editor = editorRef.current;
@@ -590,6 +628,7 @@ function useTsdrawCanvasController(options = {}) {
590
628
  const initialStyle = editor.getCurrentDrawStyle();
591
629
  setDrawColor(initialStyle.color);
592
630
  setDrawDash(initialStyle.dash);
631
+ setDrawFill(initialStyle.fill);
593
632
  setDrawSize(initialStyle.size);
594
633
  const resize = () => {
595
634
  const dpr = window.devicePixelRatio ?? 1;
@@ -671,6 +710,7 @@ function useTsdrawCanvasController(options = {}) {
671
710
  const nextDrawStyle = editor.getCurrentDrawStyle();
672
711
  setDrawColor(nextDrawStyle.color);
673
712
  setDrawDash(nextDrawStyle.dash);
713
+ setDrawFill(nextDrawStyle.fill);
674
714
  setDrawSize(nextDrawStyle.size);
675
715
  setSelectionRotationDeg(0);
676
716
  render();
@@ -1049,6 +1089,7 @@ function useTsdrawCanvasController(options = {}) {
1049
1089
  editor.setCurrentDrawStyle(partial);
1050
1090
  if (partial.color) setDrawColor(partial.color);
1051
1091
  if (partial.dash) setDrawDash(partial.dash);
1092
+ if (partial.fill) setDrawFill(partial.fill);
1052
1093
  if (partial.size) setDrawSize(partial.size);
1053
1094
  render();
1054
1095
  }
@@ -1106,6 +1147,7 @@ function useTsdrawCanvasController(options = {}) {
1106
1147
  editor.setCurrentDrawStyle(partial);
1107
1148
  if (partial.color) setDrawColor(partial.color);
1108
1149
  if (partial.dash) setDrawDash(partial.dash);
1150
+ if (partial.fill) setDrawFill(partial.fill);
1109
1151
  if (partial.size) setDrawSize(partial.size);
1110
1152
  render();
1111
1153
  },
@@ -1173,6 +1215,7 @@ function useTsdrawCanvasController(options = {}) {
1173
1215
  currentTool,
1174
1216
  drawColor,
1175
1217
  drawDash,
1218
+ drawFill,
1176
1219
  drawSize,
1177
1220
  selectedShapeIds,
1178
1221
  selectionBrush,
@@ -1182,7 +1225,6 @@ function useTsdrawCanvasController(options = {}) {
1182
1225
  cursorContext,
1183
1226
  toolOverlay,
1184
1227
  isPersistenceReady,
1185
- showStylePanel: stylePanelToolIdsRef.current.includes(currentTool),
1186
1228
  canUndo,
1187
1229
  canRedo,
1188
1230
  undo,
@@ -1193,12 +1235,21 @@ function useTsdrawCanvasController(options = {}) {
1193
1235
  handleRotatePointerDown
1194
1236
  };
1195
1237
  }
1196
- var DEFAULT_TOOLBAR_PARTS = [["undo", "redo"], ["select", "hand", "pen", "eraser"]];
1238
+ var DEFAULT_TOOLBAR_PARTS = [["undo", "redo"], ["select", "hand", "pen", "eraser", "square", "circle"]];
1197
1239
  var EMPTY_CUSTOM_TOOLS = [];
1198
1240
  var EMPTY_CUSTOM_ELEMENTS = [];
1241
+ var EMPTY_STYLE_PANEL_PARTS = [];
1242
+ var EMPTY_STYLE_PANEL_CUSTOM_PARTS = [];
1243
+ var DEFAULT_STYLE_PANEL_PARTS_BY_TOOL = {
1244
+ pen: ["colors", "dashes", "sizes"],
1245
+ square: ["colors", "dashes", "fills", "sizes"],
1246
+ circle: ["colors", "dashes", "fills", "sizes"]
1247
+ };
1199
1248
  var DEFAULT_TOOL_LABELS = {
1200
1249
  select: "Select",
1201
1250
  pen: "Pen",
1251
+ square: "Rectangle",
1252
+ circle: "Ellipse",
1202
1253
  eraser: "Eraser",
1203
1254
  hand: "Hand"
1204
1255
  };
@@ -1270,21 +1321,6 @@ function Tsdraw(props) {
1270
1321
  () => customTools.filter((customTool) => toolbarToolIds.has(customTool.id)).map((customTool) => customTool.definition),
1271
1322
  [customTools, toolbarToolIds]
1272
1323
  );
1273
- const stylePanelToolIds = useMemo(
1274
- () => {
1275
- const nextToolIds = /* @__PURE__ */ new Set();
1276
- if (toolbarToolIds.has("pen")) {
1277
- nextToolIds.add("pen");
1278
- }
1279
- for (const customTool of customTools) {
1280
- if ((customTool.showStylePanel ?? false) && toolbarToolIds.has(customTool.id)) {
1281
- nextToolIds.add(customTool.id);
1282
- }
1283
- }
1284
- return [...nextToolIds];
1285
- },
1286
- [customTools, toolbarToolIds]
1287
- );
1288
1324
  const firstToolbarTool = useMemo(() => {
1289
1325
  for (const toolbarPart of toolbarPartIds) {
1290
1326
  for (const item of toolbarPart) {
@@ -1313,6 +1349,7 @@ function Tsdraw(props) {
1313
1349
  currentTool,
1314
1350
  drawColor,
1315
1351
  drawDash,
1352
+ drawFill,
1316
1353
  drawSize,
1317
1354
  selectedShapeIds,
1318
1355
  selectionBrush,
@@ -1322,7 +1359,6 @@ function Tsdraw(props) {
1322
1359
  cursorContext,
1323
1360
  toolOverlay,
1324
1361
  isPersistenceReady,
1325
- showStylePanel,
1326
1362
  canUndo,
1327
1363
  canRedo,
1328
1364
  undo,
@@ -1336,11 +1372,12 @@ function Tsdraw(props) {
1336
1372
  initialTool,
1337
1373
  theme: resolvedTheme,
1338
1374
  persistenceKey: props.persistenceKey,
1339
- stylePanelToolIds,
1340
1375
  onMount: props.onMount
1341
1376
  });
1342
1377
  const toolbarPlacementStyle = resolvePlacementStyle(props.uiOptions?.toolbar?.placement, "bottom-center", 0, 14);
1343
1378
  const stylePanelPlacementStyle = resolvePlacementStyle(props.uiOptions?.stylePanel?.placement, "top-right", 8, 8);
1379
+ const isToolbarHidden = props.uiOptions?.toolbar?.hide === true;
1380
+ const isStylePanelHidden = props.uiOptions?.stylePanel?.hide === true;
1344
1381
  const canvasCursor = props.uiOptions?.cursor?.getCursor?.(cursorContext) ?? defaultCanvasCursor;
1345
1382
  const defaultToolOverlay = /* @__PURE__ */ jsx(
1346
1383
  ToolOverlay,
@@ -1362,9 +1399,24 @@ function Tsdraw(props) {
1362
1399
  const onDashSelect = useCallback((dash) => {
1363
1400
  applyDrawStyle({ dash });
1364
1401
  }, [applyDrawStyle]);
1402
+ const onFillSelect = useCallback((fill) => {
1403
+ applyDrawStyle({ fill });
1404
+ }, [applyDrawStyle]);
1365
1405
  const onSizeSelect = useCallback((size) => {
1366
1406
  applyDrawStyle({ size });
1367
1407
  }, [applyDrawStyle]);
1408
+ const activeCustomTool = customToolMap.get(currentTool);
1409
+ const stylePanelParts = useMemo(
1410
+ () => {
1411
+ const fromCustomTool = activeCustomTool?.stylePanel?.parts;
1412
+ if (fromCustomTool && fromCustomTool.length > 0) return fromCustomTool;
1413
+ if (activeCustomTool?.stylePanel?.customParts && activeCustomTool.stylePanel.customParts.length > 0) return activeCustomTool.stylePanel.customParts.map((customPart) => customPart.id);
1414
+ if (currentTool in DEFAULT_STYLE_PANEL_PARTS_BY_TOOL) return DEFAULT_STYLE_PANEL_PARTS_BY_TOOL[currentTool] ?? EMPTY_STYLE_PANEL_PARTS;
1415
+ return EMPTY_STYLE_PANEL_PARTS;
1416
+ },
1417
+ [activeCustomTool, currentTool]
1418
+ );
1419
+ const stylePanelCustomParts = activeCustomTool?.stylePanel?.customParts ?? EMPTY_STYLE_PANEL_CUSTOM_PARTS;
1368
1420
  const toolbarParts = useMemo(
1369
1421
  () => toolbarPartIds.map((toolbarPart, partIndex) => {
1370
1422
  const items = toolbarPart.map((item) => {
@@ -1453,14 +1505,18 @@ function Tsdraw(props) {
1453
1505
  /* @__PURE__ */ jsx(
1454
1506
  StylePanel,
1455
1507
  {
1456
- visible: isPersistenceReady && showStylePanel,
1508
+ visible: !isStylePanelHidden && isPersistenceReady && stylePanelParts.length > 0,
1509
+ parts: stylePanelParts,
1510
+ customParts: stylePanelCustomParts,
1457
1511
  style: stylePanelPlacementStyle,
1458
1512
  theme: resolvedTheme,
1459
1513
  drawColor,
1460
1514
  drawDash,
1515
+ drawFill,
1461
1516
  drawSize,
1462
1517
  onColorSelect,
1463
1518
  onDashSelect,
1519
+ onFillSelect,
1464
1520
  onSizeSelect
1465
1521
  }
1466
1522
  ),
@@ -1477,7 +1533,7 @@ function Tsdraw(props) {
1477
1533
  },
1478
1534
  customElement.id
1479
1535
  )),
1480
- /* @__PURE__ */ jsx(
1536
+ !isToolbarHidden ? /* @__PURE__ */ jsx(
1481
1537
  Toolbar,
1482
1538
  {
1483
1539
  parts: toolbarParts,
@@ -1486,7 +1542,7 @@ function Tsdraw(props) {
1486
1542
  onToolChange: setTool,
1487
1543
  disabled: !isPersistenceReady
1488
1544
  }
1489
- )
1545
+ ) : null
1490
1546
  ]
1491
1547
  }
1492
1548
  );