@fieldnotes/core 0.26.0 → 0.27.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.cjs CHANGED
@@ -59,6 +59,7 @@ __export(index_exports, {
59
59
  getArrowTangentAngle: () => getArrowTangentAngle,
60
60
  getBendFromPoint: () => getBendFromPoint,
61
61
  getElementBounds: () => getElementBounds,
62
+ getElementStyle: () => getElementStyle,
62
63
  getElementsBoundingBox: () => getElementsBoundingBox,
63
64
  getHexCellsInCone: () => getHexCellsInCone,
64
65
  getHexCellsInLine: () => getHexCellsInLine,
@@ -70,6 +71,7 @@ __export(index_exports, {
70
71
  smartSnap: () => smartSnap,
71
72
  snapPoint: () => snapPoint,
72
73
  snapToHexCenter: () => snapToHexCenter,
74
+ styleToPatch: () => styleToPatch,
73
75
  toggleBold: () => toggleBold,
74
76
  toggleItalic: () => toggleItalic,
75
77
  toggleStrikethrough: () => toggleStrikethrough,
@@ -5234,7 +5236,103 @@ var MarginViewport = class {
5234
5236
  }
5235
5237
  };
5236
5238
 
5239
+ // src/elements/element-style.ts
5240
+ function styleToPatch(element, style) {
5241
+ const { color, fillColor, strokeWidth, opacity, fontSize } = style;
5242
+ switch (element.type) {
5243
+ case "stroke":
5244
+ return {
5245
+ ...color !== void 0 ? { color } : {},
5246
+ ...strokeWidth !== void 0 ? { width: strokeWidth } : {},
5247
+ ...opacity !== void 0 ? { opacity } : {}
5248
+ };
5249
+ case "arrow":
5250
+ return {
5251
+ ...color !== void 0 ? { color } : {},
5252
+ ...strokeWidth !== void 0 ? { width: strokeWidth } : {}
5253
+ };
5254
+ case "shape":
5255
+ return {
5256
+ ...color !== void 0 ? { strokeColor: color } : {},
5257
+ ...fillColor !== void 0 ? { fillColor } : {},
5258
+ ...strokeWidth !== void 0 ? { strokeWidth } : {}
5259
+ };
5260
+ case "text":
5261
+ return {
5262
+ ...color !== void 0 ? { color } : {},
5263
+ ...fontSize !== void 0 ? { fontSize } : {}
5264
+ };
5265
+ case "note":
5266
+ return {
5267
+ ...color !== void 0 ? { textColor: color } : {},
5268
+ ...fillColor !== void 0 ? { backgroundColor: fillColor } : {},
5269
+ ...fontSize !== void 0 ? { fontSize } : {}
5270
+ };
5271
+ case "grid":
5272
+ return {
5273
+ ...color !== void 0 ? { strokeColor: color } : {},
5274
+ ...strokeWidth !== void 0 ? { strokeWidth } : {},
5275
+ ...opacity !== void 0 ? { opacity } : {}
5276
+ };
5277
+ case "template":
5278
+ return {
5279
+ ...color !== void 0 ? { strokeColor: color } : {},
5280
+ ...fillColor !== void 0 ? { fillColor } : {},
5281
+ ...strokeWidth !== void 0 ? { strokeWidth } : {},
5282
+ ...opacity !== void 0 ? { opacity } : {}
5283
+ };
5284
+ default:
5285
+ return {};
5286
+ }
5287
+ }
5288
+ function getElementStyle(element) {
5289
+ switch (element.type) {
5290
+ case "stroke":
5291
+ return { color: element.color, strokeWidth: element.width, opacity: element.opacity };
5292
+ case "arrow":
5293
+ return { color: element.color, strokeWidth: element.width };
5294
+ case "shape":
5295
+ return {
5296
+ color: element.strokeColor,
5297
+ fillColor: element.fillColor,
5298
+ strokeWidth: element.strokeWidth
5299
+ };
5300
+ case "text":
5301
+ return { color: element.color, fontSize: element.fontSize };
5302
+ case "note":
5303
+ return {
5304
+ color: element.textColor,
5305
+ fillColor: element.backgroundColor,
5306
+ ...element.fontSize !== void 0 ? { fontSize: element.fontSize } : {}
5307
+ };
5308
+ case "grid":
5309
+ return {
5310
+ color: element.strokeColor,
5311
+ strokeWidth: element.strokeWidth,
5312
+ opacity: element.opacity
5313
+ };
5314
+ case "template":
5315
+ return {
5316
+ color: element.strokeColor,
5317
+ fillColor: element.fillColor,
5318
+ strokeWidth: element.strokeWidth,
5319
+ opacity: element.opacity
5320
+ };
5321
+ default:
5322
+ return {};
5323
+ }
5324
+ }
5325
+
5237
5326
  // src/canvas/viewport.ts
5327
+ var EMPTY_IDS = [];
5328
+ function noop() {
5329
+ }
5330
+ function sharedValue(values) {
5331
+ const present = values.filter((v) => v !== void 0);
5332
+ if (present.length === 0) return void 0;
5333
+ const first = present[0];
5334
+ return present.every((v) => v === first) ? first : void 0;
5335
+ }
5238
5336
  var Viewport = class {
5239
5337
  constructor(container, options = {}) {
5240
5338
  this.container = container;
@@ -5586,6 +5684,52 @@ var Viewport = class {
5586
5684
  this.gridChangeListeners.delete(listener);
5587
5685
  };
5588
5686
  }
5687
+ getSelectTool() {
5688
+ return this.toolManager.getTool("select");
5689
+ }
5690
+ getSelectedIds() {
5691
+ return this.getSelectTool()?.selectedIds ?? EMPTY_IDS;
5692
+ }
5693
+ onSelectionChange(listener) {
5694
+ const tool = this.getSelectTool();
5695
+ return tool ? tool.onSelectionChange(listener) : noop;
5696
+ }
5697
+ getSelectionStyle() {
5698
+ const ids = this.getSelectedIds();
5699
+ if (ids.length === 0) return null;
5700
+ const styles = [];
5701
+ for (const id of ids) {
5702
+ const el = this.store.getById(id);
5703
+ if (el) styles.push(getElementStyle(el));
5704
+ }
5705
+ if (styles.length === 0) return null;
5706
+ const result = {};
5707
+ const color = sharedValue(styles.map((s) => s.color));
5708
+ if (color !== void 0) result.color = color;
5709
+ const fillColor = sharedValue(styles.map((s) => s.fillColor));
5710
+ if (fillColor !== void 0) result.fillColor = fillColor;
5711
+ const strokeWidth = sharedValue(styles.map((s) => s.strokeWidth));
5712
+ if (strokeWidth !== void 0) result.strokeWidth = strokeWidth;
5713
+ const opacity = sharedValue(styles.map((s) => s.opacity));
5714
+ if (opacity !== void 0) result.opacity = opacity;
5715
+ const fontSize = sharedValue(styles.map((s) => s.fontSize));
5716
+ if (fontSize !== void 0) result.fontSize = fontSize;
5717
+ return result;
5718
+ }
5719
+ applyStyleToSelection(style) {
5720
+ const ids = this.getSelectedIds();
5721
+ if (ids.length === 0) return;
5722
+ this.historyRecorder.begin();
5723
+ for (const id of ids) {
5724
+ const el = this.store.getById(id);
5725
+ if (!el) continue;
5726
+ const patch = styleToPatch(el, style);
5727
+ if (Object.keys(patch).length > 0) {
5728
+ this.store.update(id, patch);
5729
+ }
5730
+ }
5731
+ this.historyRecorder.commit();
5732
+ }
5589
5733
  getRenderStats() {
5590
5734
  return this.renderLoop.getStats();
5591
5735
  }
@@ -6201,6 +6345,7 @@ var HANDLE_CURSORS = {
6201
6345
  var SelectTool = class {
6202
6346
  name = "select";
6203
6347
  _selectedIds = [];
6348
+ selectionListeners = /* @__PURE__ */ new Set();
6204
6349
  mode = { type: "idle" };
6205
6350
  lastWorld = { x: 0, y: 0 };
6206
6351
  currentWorld = { x: 0, y: 0 };
@@ -6210,10 +6355,22 @@ var SelectTool = class {
6210
6355
  resizeAspectRatio = 0;
6211
6356
  hoveredId = null;
6212
6357
  get selectedIds() {
6213
- return [...this._selectedIds];
6358
+ return this._selectedIds;
6214
6359
  }
6215
- setSelection(ids) {
6360
+ onSelectionChange(listener) {
6361
+ this.selectionListeners.add(listener);
6362
+ return () => {
6363
+ this.selectionListeners.delete(listener);
6364
+ };
6365
+ }
6366
+ setSelectedIds(ids) {
6367
+ const prev = this._selectedIds;
6368
+ if (prev.length === ids.length && prev.every((id, i) => id === ids[i])) return;
6216
6369
  this._selectedIds = ids;
6370
+ for (const listener of this.selectionListeners) listener();
6371
+ }
6372
+ setSelection(ids) {
6373
+ this.setSelectedIds(ids);
6217
6374
  this.ctx?.requestRender();
6218
6375
  }
6219
6376
  get isMarqueeActive() {
@@ -6223,7 +6380,7 @@ var SelectTool = class {
6223
6380
  this.ctx = ctx;
6224
6381
  }
6225
6382
  onDeactivate(ctx) {
6226
- this._selectedIds = [];
6383
+ this.setSelectedIds([]);
6227
6384
  this.mode = { type: "idle" };
6228
6385
  this.hoveredId = null;
6229
6386
  ctx.setCursor?.("default");
@@ -6274,22 +6431,22 @@ var SelectTool = class {
6274
6431
  const alreadySelected = this._selectedIds.includes(hit.id);
6275
6432
  if (state.shiftKey) {
6276
6433
  if (alreadySelected) {
6277
- this._selectedIds = this._selectedIds.filter((id) => id !== hit.id);
6434
+ this.setSelectedIds(this._selectedIds.filter((id) => id !== hit.id));
6278
6435
  this.mode = { type: "idle" };
6279
6436
  } else {
6280
- this._selectedIds = [...this._selectedIds, hit.id];
6437
+ this.setSelectedIds([...this._selectedIds, hit.id]);
6281
6438
  this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
6282
6439
  }
6283
6440
  } else {
6284
6441
  if (!alreadySelected) {
6285
- this._selectedIds = [hit.id];
6442
+ this.setSelectedIds([hit.id]);
6286
6443
  } else if (this._selectedIds.length > 1) {
6287
6444
  this.pendingSingleSelectId = hit.id;
6288
6445
  }
6289
6446
  this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
6290
6447
  }
6291
6448
  } else {
6292
- this._selectedIds = [];
6449
+ this.setSelectedIds([]);
6293
6450
  this.mode = { type: "marquee", start: world };
6294
6451
  }
6295
6452
  ctx.requestRender();
@@ -6362,12 +6519,12 @@ var SelectTool = class {
6362
6519
  if (this.mode.type === "marquee") {
6363
6520
  const rect = this.getMarqueeRect();
6364
6521
  if (rect) {
6365
- this._selectedIds = this.findElementsInRect(rect, ctx);
6522
+ this.setSelectedIds(this.findElementsInRect(rect, ctx));
6366
6523
  }
6367
6524
  ctx.requestRender();
6368
6525
  }
6369
6526
  if (!this.hasDragged && this.pendingSingleSelectId !== null) {
6370
- this._selectedIds = [this.pendingSingleSelectId];
6527
+ this.setSelectedIds([this.pendingSingleSelectId]);
6371
6528
  }
6372
6529
  this.pendingSingleSelectId = null;
6373
6530
  this.hasDragged = false;
@@ -7589,7 +7746,7 @@ var TemplateTool = class {
7589
7746
  };
7590
7747
 
7591
7748
  // src/index.ts
7592
- var VERSION = "0.26.0";
7749
+ var VERSION = "0.27.0";
7593
7750
  // Annotate the CommonJS export names for ESM import in node:
7594
7751
  0 && (module.exports = {
7595
7752
  ArrowTool,
@@ -7631,6 +7788,7 @@ var VERSION = "0.26.0";
7631
7788
  getArrowTangentAngle,
7632
7789
  getBendFromPoint,
7633
7790
  getElementBounds,
7791
+ getElementStyle,
7634
7792
  getElementsBoundingBox,
7635
7793
  getHexCellsInCone,
7636
7794
  getHexCellsInLine,
@@ -7642,6 +7800,7 @@ var VERSION = "0.26.0";
7642
7800
  smartSnap,
7643
7801
  snapPoint,
7644
7802
  snapToHexCenter,
7803
+ styleToPatch,
7645
7804
  toggleBold,
7646
7805
  toggleItalic,
7647
7806
  toggleStrikethrough,