@linkurious/ogma-annotations 2.0.2 → 2.1.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.
@@ -1 +1 @@
1
- :root{--handle-width: 2px;--point-handle-width: calc(3 * var(--handle-width));--point-handle-border: 2px;--point-handle-total: calc(var(--point-handle-width) + var(--point-handle-border));--handle-color: #38e;--handle-background: #fff;--active-color: #1a70e5;--disabled-color: #999;--hover-color: rgba(56, 136, 238, .2)}svg text{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.handle{position:absolute;background-color:var(--handle-color)}.handle.line{cursor:move}.ogma-annotation-text-editor{display:flex;flex-direction:column;align-items:flex-end;position:relative;width:100%;height:100%}.ogma-annotation-text-editor.animate-width{transition:width .2s ease-out,left .2s ease-out}.ogma-annotation-text-editor textarea{outline:none;padding:0;margin:0;border:0;width:100%;height:100%;cursor:text;z-index:1000;resize:none;white-space:break-spaces;background-color:transparent;overflow:hidden}.ogma-annotation-text-editor textarea::-webkit-scrollbar{width:6px}.ogma-annotation-text-editor textarea::-webkit-scrollbar-track{background:transparent}.ogma-annotation-text-editor textarea::-webkit-scrollbar-thumb{background:#0003;border-radius:3px}.ogma-annotation-text-editor textarea::-webkit-scrollbar-thumb:hover{background:#0000004d}.ogma-send-button{width:24px;height:24px;margin-left:auto;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:background-color .2s ease;z-index:1001}.ogma-send-button-icon{width:16px;height:16px;display:flex;align-items:center;justify-content:center;color:var(--handle-color, #38e)}.ogma-send-button-icon svg{width:100%;height:100%}.ogma-send-button:not(:disabled):hover{background-color:var(--hover-color);transform:scale(1.05)}.ogma-send-button:not(:disabled):hover .ogma-send-button-icon{color:var(--active-color)}.ogma-send-button:not(:disabled):active{background-color:var(--hover-color);transform:scale(.95)}.ogma-send-button:not(:disabled):active .ogma-send-button-icon{color:var(--active-color)}.ogma-send-button:disabled{cursor:not-allowed;opacity:.3}.ogma-send-button:disabled .ogma-send-button-icon{color:var(--disabled-color)}.annotation-text-handle .noevents{pointer-events:none;z-index:20}.line-handle,.point-handle{z-index:30}.line-handle.top{cursor:ns-resize;height:var(--handle-width);left:0;width:100%;top:calc(var(--handle-width) * -1)}.line-handle.bottom{cursor:ns-resize;height:var(--handle-width);width:100%;left:0;bottom:calc(var(--handle-width) * -1)}.line-handle.left{cursor:ew-resize;height:100%;top:0;left:calc(var(--handle-width) * -1);width:var(--handle-width)}.line-handle.right{cursor:ew-resize;height:100%;right:calc(var(--handle-width) * -1);top:0;width:var(--handle-width)}.line-handle.top,.line-handle.bottom,.line-handle.left,.line-handle.right{cursor:move}.point-handle{border-radius:50%;background-color:#fff;transform-origin:center;transform:translate(-50%,-50%);border:var(--point-handle-border) solid var(--handle-color);width:var(--point-handle-width);height:var(--point-handle-width)}.point-handle.top-left{transform:translate(-55%,-55%)}.point-handle.top-right{transform:translate(-45%,-55%)}.point-handle.bottom-left{transform:translate(-55%,-45%)}.point-handle.bottom-right{transform:translate(-45%,-45%)}.rotated .point-handle.bottom-left,.rotated .point-handle.top-right{display:none}.point-handle.top-left,.point-handle.bottom-right{cursor:nwse-resize}.point-handle.top-right,.point-handle.bottom-left{cursor:nesw-resize}.point-handle.bottom-left,.point-handle.bottom-right{top:100%}.point-handle.top-left,.point-handle.top-right{top:0}.point-handle.bottom-left,.point-handle.top-left{left:0}.point-handle.bottom-right,.point-handle.top-right{left:100%}.arrow-handle>.handle{height:var(--point-handle-width);width:var(--point-handle-width);border-radius:50%;cursor:move;transform:translate(-50%,-50%)}.arrow-handle>.line{height:var(--handle-width);border-radius:0;cursor:move}.arrow-handle>.point{background-color:var(--handle-background);border:2px solid var(--handle-color)}.annotations-hidden-input{position:absolute;bottom:0;left:0;visibility:hidden;display:block}.active{background-color:#38e}.annotation-text{cursor:pointer}.annotation-text:hover>rect{stroke:var(--handle-color)}.annotation-text a{fill:var(--handle-color)}.annotation-text a:hover{text-decoration:underline}.annotation-hovered,.annotation-selected{background:#f5f5f5;background-color:#f5f5f5}
1
+ :root{--handle-width: 2px;--point-handle-width: calc(3 * var(--handle-width));--point-handle-border: 2px;--point-handle-total: calc(var(--point-handle-width) + var(--point-handle-border));--handle-color: #38e;--annotation-link-color: var(--handle-color);--handle-background: #fff;--active-color: #1a70e5;--disabled-color: #999;--hover-color: rgba(56, 136, 238, .2)}svg text{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ogma-annotation-link{fill:var(--annotation-link-color, #38e);color:var(--annotation-link-color, #38e);text-decoration:none;pointer-events:auto;cursor:pointer}.handle{position:absolute;background-color:var(--handle-color)}.handle.line{cursor:move}.ogma-annotation-text-editor{display:flex;flex-direction:column;align-items:flex-end;position:relative;width:100%;height:100%}.ogma-annotation-text-editor.animate-width{transition:width .2s ease-out,left .2s ease-out}.ogma-annotation-text-editor textarea{outline:none;padding:0;margin:0;border:0;width:100%;height:100%;cursor:text;z-index:1000;resize:none;white-space:break-spaces;background-color:transparent;overflow:hidden}.ogma-annotation-text-editor textarea::-webkit-scrollbar{width:6px}.ogma-annotation-text-editor textarea::-webkit-scrollbar-track{background:transparent}.ogma-annotation-text-editor textarea::-webkit-scrollbar-thumb{background:#0003;border-radius:3px}.ogma-annotation-text-editor textarea::-webkit-scrollbar-thumb:hover{background:#0000004d}.ogma-send-button{width:24px;height:24px;margin-left:auto;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:background-color .2s ease;z-index:1001}.ogma-send-button-icon{width:16px;height:16px;display:flex;align-items:center;justify-content:center;color:var(--handle-color, #38e)}.ogma-send-button-icon svg{width:100%;height:100%}.ogma-send-button:not(:disabled):hover{background-color:var(--hover-color);transform:scale(1.05)}.ogma-send-button:not(:disabled):hover .ogma-send-button-icon{color:var(--active-color)}.ogma-send-button:not(:disabled):active{background-color:var(--hover-color);transform:scale(.95)}.ogma-send-button:not(:disabled):active .ogma-send-button-icon{color:var(--active-color)}.ogma-send-button:disabled{cursor:not-allowed;opacity:.3}.ogma-send-button:disabled .ogma-send-button-icon{color:var(--disabled-color)}.annotation-text-handle .noevents{pointer-events:none;z-index:20}.line-handle,.point-handle{z-index:30}.line-handle.top{cursor:ns-resize;height:var(--handle-width);left:0;width:100%;top:calc(var(--handle-width) * -1)}.line-handle.bottom{cursor:ns-resize;height:var(--handle-width);width:100%;left:0;bottom:calc(var(--handle-width) * -1)}.line-handle.left{cursor:ew-resize;height:100%;top:0;left:calc(var(--handle-width) * -1);width:var(--handle-width)}.line-handle.right{cursor:ew-resize;height:100%;right:calc(var(--handle-width) * -1);top:0;width:var(--handle-width)}.line-handle.top,.line-handle.bottom,.line-handle.left,.line-handle.right{cursor:move}.point-handle{border-radius:50%;background-color:#fff;transform-origin:center;transform:translate(-50%,-50%);border:var(--point-handle-border) solid var(--handle-color);width:var(--point-handle-width);height:var(--point-handle-width)}.point-handle.top-left{transform:translate(-55%,-55%)}.point-handle.top-right{transform:translate(-45%,-55%)}.point-handle.bottom-left{transform:translate(-55%,-45%)}.point-handle.bottom-right{transform:translate(-45%,-45%)}.rotated .point-handle.bottom-left,.rotated .point-handle.top-right{display:none}.point-handle.top-left,.point-handle.bottom-right{cursor:nwse-resize}.point-handle.top-right,.point-handle.bottom-left{cursor:nesw-resize}.point-handle.bottom-left,.point-handle.bottom-right{top:100%}.point-handle.top-left,.point-handle.top-right{top:0}.point-handle.bottom-left,.point-handle.top-left{left:0}.point-handle.bottom-right,.point-handle.top-right{left:100%}.arrow-handle>.handle{height:var(--point-handle-width);width:var(--point-handle-width);border-radius:50%;cursor:move;transform:translate(-50%,-50%)}.arrow-handle>.line{height:var(--handle-width);border-radius:0;cursor:move}.arrow-handle>.point{background-color:var(--handle-background);border:2px solid var(--handle-color)}.annotations-hidden-input{position:absolute;bottom:0;left:0;visibility:hidden;display:block}.active{background-color:#38e}.annotation-text{cursor:pointer}.annotation-text:hover>rect{stroke:var(--handle-color)}.annotation-text a{fill:var(--handle-color)}.annotation-text a:hover{text-decoration:underline}.annotation-hovered,.annotation-selected{background:#f5f5f5;background-color:#f5f5f5}
@@ -14,10 +14,16 @@ import { Position } from 'geojson';
14
14
  import { Size } from '@linkurious/ogma';
15
15
 
16
16
  /**
17
- * Automatically lightens or darkens a color (hex or rgba) for highlight purposes.
17
+ * Adjusts the brightness of a color (hex or rgba) based on its perceived luminance.
18
+ * For bright colors, the adjustment is applied as darkening; for dark colors, as lightening.
19
+ *
18
20
  * @param color - Color string in hex (#RRGGBB or #RGB) or rgba format
19
- * @param amount - Amount to lighten/darken (default 20 for lighter and -10 for darker)
20
- * @returns Highlighted color in rgba format
21
+ * @param amount - Adjustment factor between -1 and 1:
22
+ * - Positive values (0 to 1): lighten dark colors, darken bright colors
23
+ * - Negative values (-1 to 0): darken dark colors, lighten bright colors
24
+ * - 0: no change
25
+ * - Example: 0.2 applies a 20% adjustment, -0.1 applies a -10% adjustment
26
+ * @returns Adjusted color in rgba format
21
27
  */
22
28
  export declare function adjustColorBrightness(color: Color, amount: number): RgbaColor;
23
29
 
@@ -122,6 +128,19 @@ export declare type Bounds = [number, number, number, number];
122
128
  export declare interface Box extends AnnotationFeature<Point_2, BoxProperties> {
123
129
  }
124
130
 
131
+ /**
132
+ * Arrow snapped to a rectangular annotation (text, box, comment).
133
+ * nx/ny are center-relative fractions multiplied by width/height:
134
+ * left-center = { nx: -0.5, ny: 0 }
135
+ * right-center = { nx: 0.5, ny: 0 }
136
+ * center = { nx: 0, ny: 0 }
137
+ */
138
+ export declare type BoxMagnet = {
139
+ type: "box";
140
+ nx: number;
141
+ ny: number;
142
+ };
143
+
125
144
  /** Properties specific to box annotations. */
126
145
  export declare interface BoxProperties extends AnnotationProps {
127
146
  type: "box";
@@ -1203,6 +1222,12 @@ declare interface DragEvent_2 {
1203
1222
  }
1204
1223
  export { DragEvent_2 as DragEvent }
1205
1224
 
1225
+ /** Arrow snapped at parametric position t (0–1) along an edge path. */
1226
+ export declare type EdgeMagnet = {
1227
+ type: "edge";
1228
+ t: number;
1229
+ };
1230
+
1206
1231
  export declare const EVT_ADD = "add";
1207
1232
 
1208
1233
  export declare const EVT_CANCEL_DRAWING = "cancelDrawing";
@@ -1233,6 +1258,11 @@ export declare const EVT_UNSELECT = "unselect";
1233
1258
 
1234
1259
  export declare const EVT_UPDATE = "update";
1235
1260
 
1261
+ /**
1262
+ * Serialized link stored inside arrow.properties.link.
1263
+ * Uses plain { x, y } for backward compatibility with saved annotations.
1264
+ * Converted to the internal Magnet type by Links.add().
1265
+ */
1236
1266
  export declare type ExportedLink = {
1237
1267
  id: Id;
1238
1268
  side: Side;
@@ -1534,13 +1564,12 @@ export declare interface Link {
1534
1564
  target: Id;
1535
1565
  /** Text or node */
1536
1566
  targetType: TargetType;
1537
- /**
1538
- * On which point relative to topleft corner the arrow is tighten, in case of
1539
- * node, a 0 vector represents the center, otherwise it can be deduced from the arrow itself
1540
- */
1541
- magnet: Point;
1567
+ /** Typed snap point — semantics depend on targetType, see Magnet union. */
1568
+ magnet: Magnet;
1542
1569
  }
1543
1570
 
1571
+ export declare type Magnet = NodeMagnet | EdgeMagnet | BoxMagnet | PolygonMagnet;
1572
+
1544
1573
  /**
1545
1574
  * Migrates old Polygon-based Box/Text to new Point-based format
1546
1575
  * Called only when annotations are added/loaded
@@ -1548,6 +1577,12 @@ export declare interface Link {
1548
1577
  */
1549
1578
  export declare function migrateBoxOrTextIfNeeded<T extends Annotation>(annotation: T): T;
1550
1579
 
1580
+ /** Arrow snapped to the center or perimeter of a node. */
1581
+ export declare type NodeMagnet = {
1582
+ type: "node";
1583
+ center: boolean;
1584
+ };
1585
+
1551
1586
  export declare const NONE = -1;
1552
1587
 
1553
1588
  export declare function parseColor(color: Color): {
@@ -1569,6 +1604,16 @@ export declare type Point = {
1569
1604
  export declare interface Polygon extends AnnotationFeature<Polygon_2, PolygonProperties> {
1570
1605
  }
1571
1606
 
1607
+ /**
1608
+ * Arrow snapped to a polygon annotation.
1609
+ * rx/ry are 0–1 fractions of the polygon's bounding box from its top-left corner.
1610
+ */
1611
+ export declare type PolygonMagnet = {
1612
+ type: "polygon";
1613
+ rx: number;
1614
+ ry: number;
1615
+ };
1616
+
1572
1617
  export declare interface PolygonProperties extends AnnotationProps {
1573
1618
  type: "polygon";
1574
1619
  style?: PolygonStyle;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linkurious/ogma-annotations",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "Headless annotation plugin for Ogma",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -51,8 +51,8 @@
51
51
  "bump:minor": "bump2version minor && npm version --no-git-tag-version minor",
52
52
  "bump:major": "bump2version major && npm version --no-git-tag-version major",
53
53
  "build": "vite build",
54
- "lint:ci": "eslint -f checkstyle -o reports/checkstyle.xml --ext ts --ext js src",
55
- "lint": "eslint --ext ts --ext js src",
54
+ "lint": "npx oxlint -c oxlint.json src",
55
+ "lint:ci": "mkdir -p reports && npx oxlint -c oxlint.json -f checkstyle src > reports/checkstyle.xml",
56
56
  "types": "tsc --d -emitDeclarationOnly --outDir dist/types",
57
57
  "preview": "vite preview",
58
58
  "docs:build": "typedoc && node scripts/organize-sidebar.mjs",
@@ -85,10 +85,10 @@
85
85
  "author": "Linkurious SAS",
86
86
  "license": "Apache-2.0",
87
87
  "peerDependencies": {
88
- "@linkurious/ogma": ">=4.5.6 || ^5.0.0"
88
+ "@linkurious/ogma": ">=5.3.11"
89
89
  },
90
90
  "dependencies": {
91
- "@borgar/textbox": "1.8.0",
91
+ "@chenglou/pretext": "0.0.7",
92
92
  "eventemitter3": "5.0.1",
93
93
  "geojson": "0.5.0",
94
94
  "rbush": "4.0.1",
@@ -96,7 +96,8 @@
96
96
  "zustand": "5.0.7"
97
97
  },
98
98
  "devDependencies": {
99
- "@linkurious/eslint-config-ogma": "1.0.14",
99
+ "@linkurious/eslint-config-ogma": "2.1.0",
100
+ "oxlint": "0.16.0",
100
101
  "@types/geojson": "7946.0.13",
101
102
  "@types/rbush": "4.0.0",
102
103
  "get-port": "7.0.0",
@@ -107,25 +108,11 @@
107
108
  "typedoc-vitepress-theme": "1.1.2",
108
109
  "typescript": "5.3.3",
109
110
  "vanilla-colorful": "0.7.2",
110
- "vite": "latest",
111
+ "vite": "6.4.3",
111
112
  "vite-plugin-dts": "^4.1.0",
112
- "vitest": "latest",
113
+ "vitest": "3.2.6",
113
114
  "vitest-canvas-mock": "1.1.3"
114
115
  },
115
- "eslintConfig": {
116
- "extends": [
117
- "@linkurious/eslint-config-ogma"
118
- ],
119
- "rules": {
120
- "@typescript-eslint/no-unused-vars": [
121
- "error",
122
- {
123
- "argsIgnorePattern": "^_",
124
- "varsIgnorePattern": "^_"
125
- }
126
- ]
127
- }
128
- },
129
116
  "prettier": {
130
117
  "printWidth": 80,
131
118
  "trailingComma": "none"