@vertexvis/viewer 0.24.4-canary.16 → 0.24.4-canary.18

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.
Files changed (46) hide show
  1. package/dist/cjs/{cursors-2dfb0ef3.js → cursors-17ad74ac.js} +2 -2
  2. package/dist/cjs/{cursors-2dfb0ef3.js.map → cursors-17ad74ac.js.map} +1 -1
  3. package/dist/cjs/index.cjs.js +1 -1
  4. package/dist/cjs/vertex-viewer-box-query-tool.cjs.entry.js +1 -1
  5. package/dist/cjs/vertex-viewer-measurement-distance.cjs.entry.js +1 -1
  6. package/dist/cjs/vertex-viewer-measurement-precise.cjs.entry.js +1 -1
  7. package/dist/cjs/vertex-viewer-pin-group.cjs.entry.js +2 -2
  8. package/dist/cjs/vertex-viewer-pin-group.cjs.entry.js.map +1 -1
  9. package/dist/cjs/vertex-viewer-pin-tool.cjs.entry.js +1 -1
  10. package/dist/cjs/vertex-viewer.cjs.entry.js +1 -1
  11. package/dist/collection/components/viewer-pin-group/viewer-pin-group.css +5 -0
  12. package/dist/collection/lib/cursors.js +1 -1
  13. package/dist/collection/lib/cursors.js.map +1 -1
  14. package/dist/components/cursors.js +1 -1
  15. package/dist/components/cursors.js.map +1 -1
  16. package/dist/components/viewer-pin-group.js +1 -1
  17. package/dist/components/viewer-pin-group.js.map +1 -1
  18. package/dist/esm/{cursors-9e349d61.js → cursors-3806bc04.js} +2 -2
  19. package/dist/esm/{cursors-9e349d61.js.map → cursors-3806bc04.js.map} +1 -1
  20. package/dist/esm/index.js +1 -1
  21. package/dist/esm/index.mjs +1 -1
  22. package/dist/esm/vertex-viewer-box-query-tool.entry.js +1 -1
  23. package/dist/esm/vertex-viewer-measurement-distance.entry.js +1 -1
  24. package/dist/esm/vertex-viewer-measurement-precise.entry.js +1 -1
  25. package/dist/esm/vertex-viewer-pin-group.entry.js +2 -2
  26. package/dist/esm/vertex-viewer-pin-group.entry.js.map +1 -1
  27. package/dist/esm/vertex-viewer-pin-tool.entry.js +1 -1
  28. package/dist/esm/vertex-viewer.entry.js +1 -1
  29. package/dist/viewer/index.esm.js +1 -1
  30. package/dist/viewer/{p-fd9cc338.entry.js → p-0988832f.entry.js} +2 -2
  31. package/dist/viewer/p-18ce3f3b.entry.js +5 -0
  32. package/dist/viewer/{p-45358fa6.entry.js.map → p-18ce3f3b.entry.js.map} +1 -1
  33. package/dist/viewer/{p-07e955f9.entry.js → p-75f5ae33.entry.js} +2 -2
  34. package/dist/viewer/{p-40496ce6.entry.js → p-89d93218.entry.js} +2 -2
  35. package/dist/viewer/{p-a470aecd.entry.js → p-8c53ed63.entry.js} +2 -2
  36. package/dist/viewer/{p-6cb3ab60.entry.js → p-ebea8f56.entry.js} +2 -2
  37. package/dist/viewer/{p-342dac8b.js → p-eda9f5d4.js} +2 -2
  38. package/dist/viewer/{p-342dac8b.js.map → p-eda9f5d4.js.map} +1 -1
  39. package/dist/viewer/viewer.esm.js +1 -1
  40. package/package.json +7 -7
  41. package/dist/viewer/p-45358fa6.entry.js +0 -5
  42. /package/dist/viewer/{p-fd9cc338.entry.js.map → p-0988832f.entry.js.map} +0 -0
  43. /package/dist/viewer/{p-07e955f9.entry.js.map → p-75f5ae33.entry.js.map} +0 -0
  44. /package/dist/viewer/{p-40496ce6.entry.js.map → p-89d93218.entry.js.map} +0 -0
  45. /package/dist/viewer/{p-a470aecd.entry.js.map → p-8c53ed63.entry.js.map} +0 -0
  46. /package/dist/viewer/{p-6cb3ab60.entry.js.map → p-ebea8f56.entry.js.map} +0 -0
@@ -112,7 +112,7 @@ const measurementWithArrowCursor = {
112
112
  const pinCursor = {
113
113
  url: "data:image/svg+xml,%3Csvg width='36px' height='36px' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath d='M12,2 C7.581722,2 4,5.581722 4,10 C4.00435812,11.7714969 4.41127263,13.5188357 5.19,15.11 C6.15517666,17.0237439 7.49502409,18.7240579 9.13,20.11 C9.86916736,20.7592093 10.6620019,21.3446357 11.5,21.86 L12,22.14 L12.5,21.86 C13.8750156,21.0120029 15.1296156,19.9827599 16.23,18.8 C17.2698142,17.7023203 18.1394508,16.4551671 18.81,15.1 C19.5872532,13.5118707 19.9941287,11.7681184 20,10 C20,5.581722 16.418278,2 12,2 Z M12,13 C10.3431458,13 9,11.6568542 9,10 C9,8.34314575 10.3431458,7 12,7 C13.6568542,7 15,8.34314575 15,10 C15,10.7956495 14.6839295,11.5587112 14.1213203,12.1213203 C13.5587112,12.6839295 12.7956495,13 12,13 Z' id='path-1'%3E%3C/path%3E%3C/defs%3E%3Cg id='icons/pin-filled' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cmask id='mask-2' fill='white'%3E%3Cuse xlink:href='%23path-1'%3E%3C/use%3E%3C/mask%3E%3Cuse id='Shape' stroke='%23FAFAFA' fill='%23BDBDBD' fill-rule='nonzero' xlink:href='%23path-1'%3E%3C/use%3E%3C/g%3E%3C/svg%3E",
114
114
  offsetX: 17,
115
- offsetY: 22,
115
+ offsetY: 32,
116
116
  };
117
117
  const labelPinCursor = {
118
118
  url: "data:image/svg+xml,%3Csvg width='36px' height='36px' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 16 24' %3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D.cls-2%7Bfill:%23616161;%7D.cls-3%7Bclip-path:url(%23clip-path);%7D%3C/style%3E%3CclipPath id='clip-path'%3E%3Ccircle cx='-576.76' cy='-107.26' r='4'/%3E%3C/clipPath%3E%3C/defs%3E%3Cpath d='M8,16H8a.48.48,0,0,1-.42-.23L5.75,13H3.51A1.5,1.5,0,0,1,2,11.5v-8A1.5,1.5,0,0,1,3.51,2h9A1.51,1.51,0,0,1,14,3.5v8a1.5,1.5,0,0,1-1.5,1.5H10.22L8.39,15.81A.5.5,0,0,1,8,16ZM3.51,3a.5.5,0,0,0-.5.5v8a.5.5,0,0,0,.5.5H6a.5.5,0,0,1,.42.23L8,14.61l1.55-2.38A.5.5,0,0,1,10,12h2.56a.5.5,0,0,0,.5-.5v-8a.51.51,0,0,0-.5-.5Z'/%3E%3Ccircle cx='8.01' cy='20' r='2'/%3E%3C/svg%3E%0A",
@@ -132,4 +132,4 @@ exports.measurementCursor = measurementCursor;
132
132
  exports.measurementWithArrowCursor = measurementWithArrowCursor;
133
133
  exports.pinCursor = pinCursor;
134
134
 
135
- //# sourceMappingURL=cursors-2dfb0ef3.js.map
135
+ //# sourceMappingURL=cursors-17ad74ac.js.map
@@ -1 +1 @@
1
- {"file":"cursors-2dfb0ef3.js","mappings":";;;;;;;AAiEA;;;;;;;MAOa,aAAa;EAA1B;;;;;;;IAuBkB,cAAS,GAAG,IAAIA,2BAAe,EAAQ,CAAC;IAEhD,YAAO,GAAqB,EAAE,CAAC;IAE/B,WAAM,GAAG,CAAC,CAAC;GA2EpB;;;;;;;;;;;EA/DQ,GAAG,CACR,MAAc,EACd,QAAQ,GAAG,aAAa,CAAC,eAAe;;;;;IAMxC,MAAM,eAAe,GAAG,IAAI,CAAC,0BAA0B,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1E,IAAI,eAAe,IAAI,IAAI,EAAE;MAC3B,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;KACjC;IAED,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC;IACzB,MAAM,QAAQ,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1E,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACtB,OAAO,QAAQ,CAAC;GACjB;;;;;;EAOO,MAAM,CAAC,QAAgB;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,QAAQ,CAAC,CAAC;IAClE,IAAI,KAAK,IAAI,CAAC,EAAE;MACd,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;MAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;KACvB;GACF;;;;;;;;EASO,0BAA0B,CAChC,aAAqB,EACrB,eAAuB;IAEvB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CACtB,CAAC,MAAM,KACL,MAAM,CAAC,MAAM,KAAK,aAAa,IAAI,MAAM,CAAC,QAAQ,KAAK,eAAe,CACzE,CAAC;GACH;;;;;;EAOM,eAAe;;IACpB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO;OACxB,MAAM,EAAE;OACR,OAAO,EAAE;OACT,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE3C,OAAO,MAAA,MAAM,CAAC,CAAC,CAAC,0CAAE,MAAM,CAAC;GAC1B;;AApGD;;;AAGuB,0BAAY,GAAG,CAAC,CAAC;AAExC;;;;AAIuB,6BAAe,GAAG,EAAE,CAAC;AAE5C;;;AAGuB,2BAAa,GAAG,EAAE,CAAC;AAyF5C;MAEa,iBAAiB,GAAG;EAC/B,GAAG,EAAE,irBAAirB;EACtrB,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;EACZ;MAEW,0BAA0B,GAAG;EACxC,GAAG,EAAE,siCAAsiC;EAC3iC,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;EACZ;MAEW,SAAS,GAAG;EACvB,GAAG,EAAE,2oCAA2oC;EAChpC,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,EAAE;EACX;MAEW,cAAc,GAAG;EAC5B,GAAG,EAAE,mvBAAmvB;EACxvB,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,EAAE;EACX;MAEW,cAAc,GAAG;EAC5B,GAAG,EAAE,+0BAA+0B;EACp1B,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;;;;;;;;;;","names":["EventDispatcher"],"sources":["./src/lib/cursors.ts"],"sourcesContent":["import { Disposable, EventDispatcher } from '@vertexvis/utils';\n\n/**\n * Represents a built-in [browser CSS\n * cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).\n */\nexport type CssCursor =\n | 'auto'\n | 'default'\n | 'none'\n | 'context-menu'\n | 'help'\n | 'pointer'\n | 'progress'\n | 'wait'\n | 'cell'\n | 'crosshair'\n | 'text'\n | 'vertical-text'\n | 'alias'\n | 'copy'\n | 'move'\n | 'no-drop'\n | 'not-allowed'\n | 'grab'\n | 'grabbing'\n | 'all-scroll'\n | 'col-resize'\n | 'row-resize'\n | 'n-resize'\n | 'e-resize'\n | 's-resize'\n | 'w-resize'\n | 'ne-resize'\n | 'nw-resize'\n | 'se-resize'\n | 'sw-resize'\n | 'ew-resize'\n | 'ns-resize'\n | 'nesw-resize'\n | 'nwse-resize'\n | 'zoom-in'\n | 'zoom-out'\n | string;\n\n/**\n * Represents a custom cursor that points to an image file and offset.\n */\nexport interface CustomCursor {\n url: string;\n offsetX?: number;\n offsetY?: number;\n}\n\n/**\n * Represents all possible cursor types.\n */\nexport type Cursor = CssCursor | CustomCursor;\n\ninterface CursorInstance extends Disposable {\n id: number;\n cursor: Cursor;\n priority: number;\n}\n\n/**\n * The cursor manager maintains a prioritized list of cursors for the viewer.\n *\n * Cursors with the highest priority will be considered active, where the most\n * recently added cursor will take precedence if there are multiple cursors with\n * the same priority.\n */\nexport class CursorManager {\n /**\n * A constant representing the lowest priority cursors.\n */\n public static readonly LOW_PRIORITY = 0;\n\n /**\n * A constant representing a priority between `LOW_PRIORITY` and\n * `HIGH_PRIORITY`.\n */\n public static readonly NORMAL_PRIORITY = 10;\n\n /**\n * A constant representing the high priority cursors.\n */\n public static readonly HIGH_PRIORITY = 20;\n\n /**\n * An event dispatcher that emits an event when a cursor is added or removed.\n *\n * @see {@link CursorManager.add} to add a cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public readonly onChanged = new EventDispatcher<void>();\n\n private cursors: CursorInstance[] = [];\n\n private nextId = 0;\n\n /**\n * Adds a cursor to the cursor manager, and returns an identifier that can be\n * used to remove the cursor.\n *\n * @param cursor The cursor to add.\n * @param priority The priority of the cursor. Higher values have higher\n * \tpriority over lower values.\n * @returns An identifier for the cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public add(\n cursor: Cursor,\n priority = CursorManager.NORMAL_PRIORITY\n ): Disposable {\n // Ensure a duplicate cursor will not be added to the cursor manager.\n // If a matching cursor exists, delete it before proceeding.\n // Note that deleting the old cursor and adding the new one results in the\n // new cursor taking precedent over other existing cursors with the same priority.\n const duplicateCursor = this.getExistingDuplicateCursor(cursor, priority);\n if (duplicateCursor != null) {\n this.remove(duplicateCursor.id);\n }\n\n const id = ++this.nextId;\n const instance = { id, cursor, priority, dispose: () => this.remove(id) };\n this.cursors.push(instance);\n this.onChanged.emit();\n return instance;\n }\n\n /**\n * Removes a cursor with the given ID, if it exists.\n *\n * @param cursorId The ID of the cursor to remove.\n */\n private remove(cursorId: number): void {\n const index = this.cursors.findIndex(({ id }) => id === cursorId);\n if (index >= 0) {\n this.cursors.splice(index, 1);\n this.onChanged.emit();\n }\n }\n\n /**\n * Checks to see if an existing cursor matches the provided cursor and priority level.\n * The matching cursor is returned if found.\n *\n * @param cursorToCheck The cursor to check for duplicates against.\n * @param priorityToCheck The priority level to check for duplicates against.\n */\n private getExistingDuplicateCursor(\n cursorToCheck: Cursor,\n priorityToCheck: number\n ): CursorInstance | undefined {\n return this.cursors.find(\n (cursor) =>\n cursor.cursor === cursorToCheck && cursor.priority === priorityToCheck\n );\n }\n\n /**\n * Returns the active cursor based on priority and insertion order.\n *\n * @see {@link CursorManager.add} to add a cursor.\n */\n public getActiveCursor(): Cursor | undefined {\n const sorted = this.cursors\n .concat()\n .reverse()\n .sort((a, b) => b.priority - a.priority);\n\n return sorted[0]?.cursor;\n }\n}\n\n// CSS SVG images need to be URL encoded: https://yoksel.github.io/url-encoder/\n\nexport const measurementCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' stroke='%23fff' stroke-width='1.25' stroke-opacity='0.5' stroke-miterlimit='10' shape-rendering='crispEdges'/%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' shape-rendering='crispEdges'/%3E%3C/svg%3E\",\n offsetX: -24,\n offsetY: -24,\n};\n\nexport const measurementWithArrowCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-1' d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath class='cls-2' d='M1,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.08,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E%3Cpath class='cls-3' d='M8.75,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n\nexport const pinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath d='M12,2 C7.581722,2 4,5.581722 4,10 C4.00435812,11.7714969 4.41127263,13.5188357 5.19,15.11 C6.15517666,17.0237439 7.49502409,18.7240579 9.13,20.11 C9.86916736,20.7592093 10.6620019,21.3446357 11.5,21.86 L12,22.14 L12.5,21.86 C13.8750156,21.0120029 15.1296156,19.9827599 16.23,18.8 C17.2698142,17.7023203 18.1394508,16.4551671 18.81,15.1 C19.5872532,13.5118707 19.9941287,11.7681184 20,10 C20,5.581722 16.418278,2 12,2 Z M12,13 C10.3431458,13 9,11.6568542 9,10 C9,8.34314575 10.3431458,7 12,7 C13.6568542,7 15,8.34314575 15,10 C15,10.7956495 14.6839295,11.5587112 14.1213203,12.1213203 C13.5587112,12.6839295 12.7956495,13 12,13 Z' id='path-1'%3E%3C/path%3E%3C/defs%3E%3Cg id='icons/pin-filled' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cmask id='mask-2' fill='white'%3E%3Cuse xlink:href='%23path-1'%3E%3C/use%3E%3C/mask%3E%3Cuse id='Shape' stroke='%23FAFAFA' fill='%23BDBDBD' fill-rule='nonzero' xlink:href='%23path-1'%3E%3C/use%3E%3C/g%3E%3C/svg%3E\",\n offsetX: 17,\n offsetY: 22,\n};\n\nexport const labelPinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 16 24' %3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D.cls-2%7Bfill:%23616161;%7D.cls-3%7Bclip-path:url(%23clip-path);%7D%3C/style%3E%3CclipPath id='clip-path'%3E%3Ccircle cx='-576.76' cy='-107.26' r='4'/%3E%3C/clipPath%3E%3C/defs%3E%3Cpath d='M8,16H8a.48.48,0,0,1-.42-.23L5.75,13H3.51A1.5,1.5,0,0,1,2,11.5v-8A1.5,1.5,0,0,1,3.51,2h9A1.51,1.51,0,0,1,14,3.5v8a1.5,1.5,0,0,1-1.5,1.5H10.22L8.39,15.81A.5.5,0,0,1,8,16ZM3.51,3a.5.5,0,0,0-.5.5v8a.5.5,0,0,0,.5.5H6a.5.5,0,0,1,.42.23L8,14.61l1.55-2.38A.5.5,0,0,1,10,12h2.56a.5.5,0,0,0,.5-.5v-8a.51.51,0,0,0-.5-.5Z'/%3E%3Ccircle cx='8.01' cy='20' r='2'/%3E%3C/svg%3E%0A\",\n offsetX: 17,\n offsetY: 29,\n};\n\nexport const boxQueryCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-2' d='M1.25,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.33,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E %3Cpath class='cls-3' d='M9,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2.25,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3Cpath class='cls-1' d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E %3Cpath d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n"],"version":3}
1
+ {"file":"cursors-17ad74ac.js","mappings":";;;;;;;AAiEA;;;;;;;MAOa,aAAa;EAA1B;;;;;;;IAuBkB,cAAS,GAAG,IAAIA,2BAAe,EAAQ,CAAC;IAEhD,YAAO,GAAqB,EAAE,CAAC;IAE/B,WAAM,GAAG,CAAC,CAAC;GA2EpB;;;;;;;;;;;EA/DQ,GAAG,CACR,MAAc,EACd,QAAQ,GAAG,aAAa,CAAC,eAAe;;;;;IAMxC,MAAM,eAAe,GAAG,IAAI,CAAC,0BAA0B,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1E,IAAI,eAAe,IAAI,IAAI,EAAE;MAC3B,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;KACjC;IAED,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC;IACzB,MAAM,QAAQ,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1E,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACtB,OAAO,QAAQ,CAAC;GACjB;;;;;;EAOO,MAAM,CAAC,QAAgB;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,QAAQ,CAAC,CAAC;IAClE,IAAI,KAAK,IAAI,CAAC,EAAE;MACd,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;MAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;KACvB;GACF;;;;;;;;EASO,0BAA0B,CAChC,aAAqB,EACrB,eAAuB;IAEvB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CACtB,CAAC,MAAM,KACL,MAAM,CAAC,MAAM,KAAK,aAAa,IAAI,MAAM,CAAC,QAAQ,KAAK,eAAe,CACzE,CAAC;GACH;;;;;;EAOM,eAAe;;IACpB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO;OACxB,MAAM,EAAE;OACR,OAAO,EAAE;OACT,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE3C,OAAO,MAAA,MAAM,CAAC,CAAC,CAAC,0CAAE,MAAM,CAAC;GAC1B;;AApGD;;;AAGuB,0BAAY,GAAG,CAAC,CAAC;AAExC;;;;AAIuB,6BAAe,GAAG,EAAE,CAAC;AAE5C;;;AAGuB,2BAAa,GAAG,EAAE,CAAC;AAyF5C;MAEa,iBAAiB,GAAG;EAC/B,GAAG,EAAE,irBAAirB;EACtrB,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;EACZ;MAEW,0BAA0B,GAAG;EACxC,GAAG,EAAE,siCAAsiC;EAC3iC,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;EACZ;MAEW,SAAS,GAAG;EACvB,GAAG,EAAE,2oCAA2oC;EAChpC,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,EAAE;EACX;MAEW,cAAc,GAAG;EAC5B,GAAG,EAAE,mvBAAmvB;EACxvB,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,EAAE;EACX;MAEW,cAAc,GAAG;EAC5B,GAAG,EAAE,+0BAA+0B;EACp1B,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;;;;;;;;;;","names":["EventDispatcher"],"sources":["./src/lib/cursors.ts"],"sourcesContent":["import { Disposable, EventDispatcher } from '@vertexvis/utils';\n\n/**\n * Represents a built-in [browser CSS\n * cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).\n */\nexport type CssCursor =\n | 'auto'\n | 'default'\n | 'none'\n | 'context-menu'\n | 'help'\n | 'pointer'\n | 'progress'\n | 'wait'\n | 'cell'\n | 'crosshair'\n | 'text'\n | 'vertical-text'\n | 'alias'\n | 'copy'\n | 'move'\n | 'no-drop'\n | 'not-allowed'\n | 'grab'\n | 'grabbing'\n | 'all-scroll'\n | 'col-resize'\n | 'row-resize'\n | 'n-resize'\n | 'e-resize'\n | 's-resize'\n | 'w-resize'\n | 'ne-resize'\n | 'nw-resize'\n | 'se-resize'\n | 'sw-resize'\n | 'ew-resize'\n | 'ns-resize'\n | 'nesw-resize'\n | 'nwse-resize'\n | 'zoom-in'\n | 'zoom-out'\n | string;\n\n/**\n * Represents a custom cursor that points to an image file and offset.\n */\nexport interface CustomCursor {\n url: string;\n offsetX?: number;\n offsetY?: number;\n}\n\n/**\n * Represents all possible cursor types.\n */\nexport type Cursor = CssCursor | CustomCursor;\n\ninterface CursorInstance extends Disposable {\n id: number;\n cursor: Cursor;\n priority: number;\n}\n\n/**\n * The cursor manager maintains a prioritized list of cursors for the viewer.\n *\n * Cursors with the highest priority will be considered active, where the most\n * recently added cursor will take precedence if there are multiple cursors with\n * the same priority.\n */\nexport class CursorManager {\n /**\n * A constant representing the lowest priority cursors.\n */\n public static readonly LOW_PRIORITY = 0;\n\n /**\n * A constant representing a priority between `LOW_PRIORITY` and\n * `HIGH_PRIORITY`.\n */\n public static readonly NORMAL_PRIORITY = 10;\n\n /**\n * A constant representing the high priority cursors.\n */\n public static readonly HIGH_PRIORITY = 20;\n\n /**\n * An event dispatcher that emits an event when a cursor is added or removed.\n *\n * @see {@link CursorManager.add} to add a cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public readonly onChanged = new EventDispatcher<void>();\n\n private cursors: CursorInstance[] = [];\n\n private nextId = 0;\n\n /**\n * Adds a cursor to the cursor manager, and returns an identifier that can be\n * used to remove the cursor.\n *\n * @param cursor The cursor to add.\n * @param priority The priority of the cursor. Higher values have higher\n * \tpriority over lower values.\n * @returns An identifier for the cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public add(\n cursor: Cursor,\n priority = CursorManager.NORMAL_PRIORITY\n ): Disposable {\n // Ensure a duplicate cursor will not be added to the cursor manager.\n // If a matching cursor exists, delete it before proceeding.\n // Note that deleting the old cursor and adding the new one results in the\n // new cursor taking precedent over other existing cursors with the same priority.\n const duplicateCursor = this.getExistingDuplicateCursor(cursor, priority);\n if (duplicateCursor != null) {\n this.remove(duplicateCursor.id);\n }\n\n const id = ++this.nextId;\n const instance = { id, cursor, priority, dispose: () => this.remove(id) };\n this.cursors.push(instance);\n this.onChanged.emit();\n return instance;\n }\n\n /**\n * Removes a cursor with the given ID, if it exists.\n *\n * @param cursorId The ID of the cursor to remove.\n */\n private remove(cursorId: number): void {\n const index = this.cursors.findIndex(({ id }) => id === cursorId);\n if (index >= 0) {\n this.cursors.splice(index, 1);\n this.onChanged.emit();\n }\n }\n\n /**\n * Checks to see if an existing cursor matches the provided cursor and priority level.\n * The matching cursor is returned if found.\n *\n * @param cursorToCheck The cursor to check for duplicates against.\n * @param priorityToCheck The priority level to check for duplicates against.\n */\n private getExistingDuplicateCursor(\n cursorToCheck: Cursor,\n priorityToCheck: number\n ): CursorInstance | undefined {\n return this.cursors.find(\n (cursor) =>\n cursor.cursor === cursorToCheck && cursor.priority === priorityToCheck\n );\n }\n\n /**\n * Returns the active cursor based on priority and insertion order.\n *\n * @see {@link CursorManager.add} to add a cursor.\n */\n public getActiveCursor(): Cursor | undefined {\n const sorted = this.cursors\n .concat()\n .reverse()\n .sort((a, b) => b.priority - a.priority);\n\n return sorted[0]?.cursor;\n }\n}\n\n// CSS SVG images need to be URL encoded: https://yoksel.github.io/url-encoder/\n\nexport const measurementCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' stroke='%23fff' stroke-width='1.25' stroke-opacity='0.5' stroke-miterlimit='10' shape-rendering='crispEdges'/%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' shape-rendering='crispEdges'/%3E%3C/svg%3E\",\n offsetX: -24,\n offsetY: -24,\n};\n\nexport const measurementWithArrowCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-1' d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath class='cls-2' d='M1,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.08,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E%3Cpath class='cls-3' d='M8.75,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n\nexport const pinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath d='M12,2 C7.581722,2 4,5.581722 4,10 C4.00435812,11.7714969 4.41127263,13.5188357 5.19,15.11 C6.15517666,17.0237439 7.49502409,18.7240579 9.13,20.11 C9.86916736,20.7592093 10.6620019,21.3446357 11.5,21.86 L12,22.14 L12.5,21.86 C13.8750156,21.0120029 15.1296156,19.9827599 16.23,18.8 C17.2698142,17.7023203 18.1394508,16.4551671 18.81,15.1 C19.5872532,13.5118707 19.9941287,11.7681184 20,10 C20,5.581722 16.418278,2 12,2 Z M12,13 C10.3431458,13 9,11.6568542 9,10 C9,8.34314575 10.3431458,7 12,7 C13.6568542,7 15,8.34314575 15,10 C15,10.7956495 14.6839295,11.5587112 14.1213203,12.1213203 C13.5587112,12.6839295 12.7956495,13 12,13 Z' id='path-1'%3E%3C/path%3E%3C/defs%3E%3Cg id='icons/pin-filled' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cmask id='mask-2' fill='white'%3E%3Cuse xlink:href='%23path-1'%3E%3C/use%3E%3C/mask%3E%3Cuse id='Shape' stroke='%23FAFAFA' fill='%23BDBDBD' fill-rule='nonzero' xlink:href='%23path-1'%3E%3C/use%3E%3C/g%3E%3C/svg%3E\",\n offsetX: 17,\n offsetY: 32,\n};\n\nexport const labelPinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 16 24' %3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D.cls-2%7Bfill:%23616161;%7D.cls-3%7Bclip-path:url(%23clip-path);%7D%3C/style%3E%3CclipPath id='clip-path'%3E%3Ccircle cx='-576.76' cy='-107.26' r='4'/%3E%3C/clipPath%3E%3C/defs%3E%3Cpath d='M8,16H8a.48.48,0,0,1-.42-.23L5.75,13H3.51A1.5,1.5,0,0,1,2,11.5v-8A1.5,1.5,0,0,1,3.51,2h9A1.51,1.51,0,0,1,14,3.5v8a1.5,1.5,0,0,1-1.5,1.5H10.22L8.39,15.81A.5.5,0,0,1,8,16ZM3.51,3a.5.5,0,0,0-.5.5v8a.5.5,0,0,0,.5.5H6a.5.5,0,0,1,.42.23L8,14.61l1.55-2.38A.5.5,0,0,1,10,12h2.56a.5.5,0,0,0,.5-.5v-8a.51.51,0,0,0-.5-.5Z'/%3E%3Ccircle cx='8.01' cy='20' r='2'/%3E%3C/svg%3E%0A\",\n offsetX: 17,\n offsetY: 29,\n};\n\nexport const boxQueryCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-2' d='M1.25,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.33,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E %3Cpath class='cls-3' d='M9,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2.25,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3Cpath class='cls-1' d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E %3Cpath d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n"],"version":3}
@@ -9,7 +9,7 @@ const queries = require('./queries-4580caa5.js');
9
9
  const controller = require('./controller-4996f10d.js');
10
10
  const row = require('./row-7faa3fc8.js');
11
11
  const types = require('./types-a8b566ec.js');
12
- const cursors = require('./cursors-2dfb0ef3.js');
12
+ const cursors = require('./cursors-17ad74ac.js');
13
13
  const entities$1 = require('./entities-4136ef5a.js');
14
14
  const model = require('./model-46052f10.js');
15
15
  const overlays = require('./overlays-d99e0740.js');
@@ -7,7 +7,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
7
7
 
8
8
  const index = require('./index-0abd8b0b.js');
9
9
  const model = require('./model-9212645d.js');
10
- const cursors = require('./cursors-2dfb0ef3.js');
10
+ const cursors = require('./cursors-17ad74ac.js');
11
11
  const dom = require('./dom-d820f463.js');
12
12
  require('./bundle.esm-03995455.js');
13
13
  require('./bundle.esm-2509a52c.js');
@@ -7,7 +7,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
7
7
 
8
8
  const index = require('./index-0abd8b0b.js');
9
9
  const bundle_esm = require('./bundle.esm-2509a52c.js');
10
- const cursors = require('./cursors-2dfb0ef3.js');
10
+ const cursors = require('./cursors-17ad74ac.js');
11
11
  const dom = require('./dom-d820f463.js');
12
12
  require('./scene_view_api_pb-c66d549b.js');
13
13
  require('./wrappers_pb-4317baca.js');
@@ -14,7 +14,7 @@ require('./scene_view_api_pb-c66d549b.js');
14
14
  const model = require('./model-46052f10.js');
15
15
  const overlays = require('./overlays-d99e0740.js');
16
16
  const bundle_esm = require('./bundle.esm-2509a52c.js');
17
- const cursors = require('./cursors-2dfb0ef3.js');
17
+ const cursors = require('./cursors-17ad74ac.js');
18
18
  const dom = require('./dom-d820f463.js');
19
19
  const elementRectObserver = require('./elementRectObserver-3f6af753.js');
20
20
  const entities$1 = require('./entities-2b21dc38.js');
@@ -8,7 +8,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
8
8
  const index = require('./index-0abd8b0b.js');
9
9
  const bundle_esm = require('./bundle.esm-2509a52c.js');
10
10
  require('./controller-4996f10d.js');
11
- require('./cursors-2dfb0ef3.js');
11
+ require('./cursors-17ad74ac.js');
12
12
  require('./scene_view_api_pb-c66d549b.js');
13
13
  require('./wrappers_pb-4317baca.js');
14
14
  require('./mapper-81927223.js');
@@ -67,7 +67,7 @@ function getClosestCenterToPoint(boxPoint, pointToMeasure, dimensions) {
67
67
  return candidates[candidateIndex];
68
68
  }
69
69
 
70
- const viewerPinGroupCss = ":host{--viewer-annotations-pin-primary-color:var(--blue-700);--viewer-annotations-pin-accent-color:var(--blue-200);--viewer-annotations-pin-dot-color:var(--viewer-annotations-pin-primary-color);--viewer-annotations-pin-color:var(--viewer-annotations-pin-primary-color);--viewer-annotations-pin-font-size:0.75rem;--viewer-annotations-pin-selected-stroke:var(--white);--viewer-annotations-pin-selected-border:2px solid var(--white);--viewer-annotations-pin-label-border:2px solid var(--black);--viewer-annotations-pin-selected-stroke:var(--white);font-size:var(--viewer-annotations-pin-font-size);position:absolute;top:0;bottom:0;left:0;right:0;overflow:hidden;pointer-events:none}.pin-anchor{position:absolute;border-radius:50%;transform:translate(-50%, -50%);display:block;width:9px;height:9px;box-sizing:border-box;border:var(--viewer-annotations-pin-label-border);background:var(--viewer-annotations-pin-dot-color);pointer-events:auto;cursor:pointer}.selected{width:13px;height:13px;border:var(--viewer-annotations-pin-selected-border)}.pin{color:var(--viewer-annotations-pin-color);cursor:pointer;transition:opacity 0.3s ease-in}.pin-selected{stroke-width:1;stroke:var(--viewer-annotations-pin-selected-stroke)}.pin-occluded{opacity:.3;transition:opacity 0.3s ease-in}.pin-detached{visibility:hidden}";
70
+ const viewerPinGroupCss = ":host{--viewer-annotations-pin-primary-color:var(--blue-700);--viewer-annotations-pin-accent-color:var(--blue-200);--viewer-annotations-pin-dot-color:var(--viewer-annotations-pin-primary-color);--viewer-annotations-pin-color:var(--viewer-annotations-pin-primary-color);--viewer-annotations-pin-font-size:0.75rem;--viewer-annotations-pin-selected-stroke:var(--white);--viewer-annotations-pin-selected-border:2px solid var(--white);--viewer-annotations-pin-label-border:2px solid var(--black);--viewer-annotations-pin-selected-stroke:var(--white);font-size:var(--viewer-annotations-pin-font-size);position:absolute;top:0;bottom:0;left:0;right:0;overflow:hidden;pointer-events:none}.pin-anchor{position:absolute;border-radius:50%;transform:translate(-50%, -50%);display:block;width:9px;height:9px;box-sizing:border-box;border:var(--viewer-annotations-pin-label-border);background:var(--viewer-annotations-pin-dot-color);pointer-events:auto;cursor:pointer}.selected{width:13px;height:13px;border:var(--viewer-annotations-pin-selected-border)}.pin{color:var(--viewer-annotations-pin-color);cursor:pointer;transition:opacity 0.3s ease-in;transform:translate(0px, -12px)}.pin-selected{stroke-width:1;stroke:var(--viewer-annotations-pin-selected-stroke)}.pin-occluded{opacity:.3;transition:opacity 0.3s ease-in}.pin-detached{visibility:hidden}";
71
71
 
72
72
  const ViewerPinGroup = class {
73
73
  constructor(hostRef) {
@@ -1 +1 @@
1
- {"file":"vertex-viewer-pin-group.entry.cjs.js","mappings":"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","names":["getPinColors","h","Fragment","isTextPin","classNames","isIconPin","Point","Matrix4","PinModel","PinController","translatePointToScreen","Vector3","Viewport"],"sources":["./src/components/viewer-pin-group/pin-renderer.tsx","./src/components/viewer-pin-group/utils.ts","./src/components/viewer-pin-group/viewer-pin-group.css?tag=vertex-viewer-pin-group","./src/components/viewer-pin-group/viewer-pin-group.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { Fragment, FunctionalComponent, h } from '@stencil/core';\nimport classNames from 'classnames';\n\nimport { getPinColors, isIconPin, isTextPin, Pin } from '../../lib/pins/model';\n\ninterface PinRendererProps {\n pin?: Pin;\n selected: boolean;\n occluded: boolean;\n detached: boolean;\n}\n\nexport const PinRenderer: FunctionalComponent<PinRendererProps> = ({\n pin,\n selected,\n occluded,\n detached,\n}) => {\n const { primaryColor } = getPinColors(pin);\n\n return (\n <Fragment>\n {isTextPin(pin) && (\n <div\n id=\"pin-anchor\"\n class={classNames('pin-anchor', {\n selected: selected,\n 'pin-occluded': occluded,\n 'pin-detached': detached,\n })}\n style={{\n background: primaryColor,\n }}\n ></div>\n )}\n\n {isIconPin(pin) && (\n <vertex-viewer-icon\n name=\"pin-fill\"\n size=\"lg\"\n class={classNames('pin', {\n 'pin-selected': selected,\n 'pin-occluded': occluded,\n 'pin-detached': detached,\n })}\n style={{\n color: primaryColor,\n }}\n />\n )}\n </Fragment>\n );\n};\n","import { Dimensions, Point } from '@vertexvis/geometry';\n\nexport function getClosestCenterToPoint(\n boxPoint: Point.Point,\n pointToMeasure: Point.Point,\n dimensions: Dimensions.Dimensions\n): Point.Point {\n const topPoint = {\n x: boxPoint.x + dimensions.width / 2,\n y: boxPoint.y,\n };\n\n const bottomPoint = {\n x: boxPoint.x + dimensions.width / 2,\n y: boxPoint.y + dimensions.height,\n };\n\n const rightPoint = {\n x: boxPoint.x + dimensions.width,\n y: boxPoint.y + dimensions.height / 2,\n };\n\n const leftPoint = {\n x: boxPoint.x,\n y: boxPoint.y + dimensions.height / 2,\n };\n\n const candidates = [topPoint, bottomPoint, leftPoint, rightPoint];\n\n const distances = candidates.map((candidate) =>\n Point.distance(candidate, pointToMeasure)\n );\n\n const candidateIndex = distances.indexOf(Math.min(...distances));\n return candidates[candidateIndex];\n}\n",":host {\n\n /**\n * @prop --viewer-annotations-pin-primary-color: A CSS color that\n * specifies the primary color for the pins. This value gets used for the dot color \n * and borders\n */\n --viewer-annotations-pin-primary-color: var(--blue-700);\n\n /**\n * @prop --viewer-annotations-pin-accent-color: A CSS color that\n * specifies the accent color for the pins. This value gets used for background colors\n * \n */\n\n --viewer-annotations-pin-accent-color: var(--blue-200);\n /**\n * @prop viewer-annotations-pin-dot-color: A CSS color that\n * specifies the color of the anchor dot\n */\n --viewer-annotations-pin-dot-color: var(--viewer-annotations-pin-primary-color);\n\n /**\n * @prop --viewer-annotations-pin-color: A CSS color that\n * specifies the color of the pin\n */\n --viewer-annotations-pin-color: var(--viewer-annotations-pin-primary-color);\n\n /**\n * @prop --viewer-annotations-pin-font-size: A CSS property to specify\n the font size of the pin\n */\n --viewer-annotations-pin-font-size: 0.75rem;\n\n /**\n * @prop --viewer-annotations-pin-selected-stroke: A CSS color that\n * specifies the stroke color of a selected pin\n */\n --viewer-annotations-pin-selected-stroke: var(--white);\n\n /**\n * @prop --viewer-annotations-pin-selected-border: A CSS color that\n * specifies the border of a selected pin\n */\n --viewer-annotations-pin-selected-border: 2px solid var(--white);\n\n /**\n * @prop --viewer-annotations-pin-label-border: A CSS color that\n * specifies the border of a text pin anchor\n */\n --viewer-annotations-pin-label-border: 2px solid var(--black);\n\n /**\n * @prop --viewer-annotations-pin-selected-border: A CSS color that\n * specifies the stroke of a selected default pin\n */\n --viewer-annotations-pin-selected-stroke: var(--white);\n\n font-size: var(--viewer-annotations-pin-font-size);\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n overflow: hidden;\n pointer-events: none;\n}\n\n.pin-anchor {\n position: absolute;\n border-radius: 50%;\n transform: translate(-50%, -50%);\n display: block;\n width: 9px;\n height: 9px;\n box-sizing: border-box;\n border: var(--viewer-annotations-pin-label-border);\n background: var(--viewer-annotations-pin-dot-color);\n pointer-events: auto;\n cursor: pointer;\n}\n\n.selected {\n width: 13px;\n height: 13px;\n border: var(--viewer-annotations-pin-selected-border)\n}\n\n.pin {\n color: var(--viewer-annotations-pin-color);\n cursor: pointer;\n transition: opacity 0.3s ease-in;\n}\n\n.pin-selected {\n stroke-width: 1;\n stroke: var(--viewer-annotations-pin-selected-stroke);\n}\n\n.pin-occluded {\n opacity: .3;\n transition: opacity 0.3s ease-in;\n}\n\n.pin-detached {\n visibility: hidden;\n}","import {\n Component,\n Fragment,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n h,\n Listen,\n Prop,\n State,\n} from '@stencil/core';\nimport { Dimensions, Matrix4, Point, Vector3 } from '@vertexvis/geometry';\n\nimport { Viewport } from '../..';\nimport { PinController } from '../../lib/pins/controller';\nimport { isTextPin, Pin, TextPin } from '../../lib/pins/model';\nimport { PinModel } from '../../lib/pins/model';\nimport { translatePointToScreen } from '../viewer-pin-tool/utils';\nimport { PinRenderer } from './pin-renderer';\nimport { getClosestCenterToPoint } from './utils';\n\ninterface ComputedPoints {\n pinPoint: Point.Point;\n labelPoint?: Point.Point;\n}\n\n@Component({\n tag: 'vertex-viewer-pin-group',\n styleUrl: 'viewer-pin-group.css',\n shadow: false,\n})\nexport class ViewerPinGroup {\n /**\n * The pin to draw for the group\n */\n @Prop()\n public pin?: Pin;\n\n /**\n * The local matrix of this element.\n */\n @Prop({ mutable: true, attribute: null })\n public matrix: Matrix4.Matrix4 = Matrix4.makeIdentity();\n\n /**\n * Projection view matrix used for computing the position of the pin line\n */\n @Prop()\n public projectionViewMatrix: Matrix4.Matrix4 = Matrix4.makeIdentity();\n\n /**\n * The dimensions of the canvas for the pins\n */\n @Prop({ mutable: true })\n public elementBounds?: DOMRect;\n\n /**\n * The model that contains the entities and outcomes from performing pin operations\n */\n @Prop()\n public pinModel: PinModel = new PinModel();\n\n /**\n * The controller that drives behavior for pin operations\n */\n @Prop()\n public pinController?: PinController;\n\n /**\n * Whether the pin is \"selected\"\n */\n @Prop()\n public selected = false;\n\n /**\n * @internal\n * Whether the pin is occluded\n */\n @Prop({ mutable: true, reflect: true })\n public occluded = false;\n\n /**\n * @internal\n * Whether the pin is detached\n */\n @Prop({ mutable: true, reflect: true })\n public detached = false;\n\n @State()\n private invalidateStateCounter = 0;\n\n private labelEl: HTMLVertexViewerPinLabelElement | undefined;\n\n private resizeObserver?: ResizeObserver;\n\n protected componentDidLoad(): void {\n this.setLabelObserver();\n\n if (this.pinController == null) {\n this.pinController = new PinController(this.pinModel);\n }\n\n if (this.selected) {\n this.labelEl?.setFocus();\n }\n }\n\n /**\n * @ignore\n */\n @Listen('occlusionStateChanged')\n protected async handleOcclusionStateChanged(\n event: CustomEvent<boolean>\n ): Promise<void> {\n this.occluded = event.detail;\n }\n\n /**\n * @ignore\n */\n @Listen('detachedStateChanged')\n protected async handleDetachedStateChanged(\n event: CustomEvent<boolean>\n ): Promise<void> {\n this.detached = event.detail;\n }\n\n protected disconnectedCallback(): void {\n this.labelEl?.removeEventListener('labelChanged', this.invalidateState);\n this.resizeObserver?.disconnect();\n }\n\n protected render(): JSX.Element {\n if (this.pin == null) {\n throw new Error('Unable to draw pin');\n }\n\n const { pinPoint, labelPoint } = this.computePinPoints(this.pin);\n\n return (\n <Fragment>\n <vertex-viewer-dom-element\n data-testid={`drawn-pin-${this.pin.id}`}\n position={this.pin.worldPosition}\n onPointerDown={async () => {\n await this.labelEl?.submit();\n this.selectPin();\n this.handleAnchorPointerDown();\n }}\n detachedOff={false}\n >\n <PinRenderer\n pin={this.pin}\n selected={this.selected}\n occluded={this.occluded}\n detached={this.detached}\n />\n </vertex-viewer-dom-element>\n\n {isTextPin(this.pin) && !this.occluded && !this.detached && (\n <Fragment>\n <vertex-viewer-pin-label-line\n id={`pin-label-line-${this.pin?.id}`}\n pinPoint={pinPoint}\n pin={this.pin}\n labelPoint={labelPoint}\n onPointerDown={() => this.selectPin()}\n ></vertex-viewer-pin-label-line>\n\n <vertex-viewer-pin-label\n pin={this.pin}\n ref={(el) => (this.labelEl = el)}\n elementBounds={this.elementBounds}\n pinController={this.pinController}\n onPointerDown={() => this.selectPin()}\n ></vertex-viewer-pin-label>\n </Fragment>\n )}\n </Fragment>\n );\n }\n\n private invalidateState = (): void => {\n this.invalidateStateCounter = this.invalidateStateCounter + 1;\n };\n\n private setLabelObserver(): void {\n if (this.labelEl != null) {\n this.labelEl.addEventListener('labelChanged', this.invalidateState);\n\n this.resizeObserver = new ResizeObserver(() => this.invalidateState());\n this.resizeObserver.observe(this.labelEl);\n }\n }\n\n private computePinPoints(pin: Pin): ComputedPoints {\n if (this.elementBounds != null && this.pin != null) {\n return isTextPin(this.pin) && this.pin.label.point != null\n ? this.computeTextPinPoints(this.pin, this.elementBounds)\n : this.computeDefaultPinPoints(this.pin, this.elementBounds);\n }\n\n return { pinPoint: pin.worldPosition };\n }\n\n private computeDefaultPinPoints(\n pin: Pin,\n elementBounds: DOMRect\n ): ComputedPoints {\n return {\n pinPoint: this.getFromWorldPosition(\n pin.worldPosition,\n this.projectionViewMatrix,\n elementBounds\n ),\n };\n }\n\n private computeTextPinPoints(\n pin: TextPin,\n elementBounds: DOMRect\n ): ComputedPoints {\n const { pinPoint } = this.computeDefaultPinPoints(pin, elementBounds);\n\n const screenPosition = translatePointToScreen(\n pin.label.point,\n elementBounds\n );\n\n const labelWidth = this.labelEl?.firstElementChild?.clientWidth || 0;\n const labelHeight = this.labelEl?.firstElementChild?.clientHeight || 0;\n\n return {\n pinPoint,\n labelPoint: getClosestCenterToPoint(screenPosition, pinPoint, {\n width: labelWidth,\n height: labelHeight,\n }),\n };\n }\n\n private handleAnchorPointerDown(): void {\n if (\n this.elementBounds != null &&\n this.pinController?.getToolMode() === 'edit' &&\n this.pin != null\n ) {\n this.pinController?.setDraggable({ id: this.pin.id });\n }\n }\n\n private selectPin(): void {\n this.pinController?.setSelectedPinId(this.pin?.id);\n }\n\n private getFromWorldPosition(\n pt: Vector3.Vector3,\n projectionViewMatrix: Matrix4.Matrix4,\n dimensions: Dimensions.Dimensions\n ): Point.Point {\n const ndcPt = Vector3.transformMatrix(pt, projectionViewMatrix);\n return Viewport.fromDimensions(dimensions).transformVectorToViewport(ndcPt);\n }\n}\n"],"version":3}
1
+ {"file":"vertex-viewer-pin-group.entry.cjs.js","mappings":"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","names":["getPinColors","h","Fragment","isTextPin","classNames","isIconPin","Point","Matrix4","PinModel","PinController","translatePointToScreen","Vector3","Viewport"],"sources":["./src/components/viewer-pin-group/pin-renderer.tsx","./src/components/viewer-pin-group/utils.ts","./src/components/viewer-pin-group/viewer-pin-group.css?tag=vertex-viewer-pin-group","./src/components/viewer-pin-group/viewer-pin-group.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { Fragment, FunctionalComponent, h } from '@stencil/core';\nimport classNames from 'classnames';\n\nimport { getPinColors, isIconPin, isTextPin, Pin } from '../../lib/pins/model';\n\ninterface PinRendererProps {\n pin?: Pin;\n selected: boolean;\n occluded: boolean;\n detached: boolean;\n}\n\nexport const PinRenderer: FunctionalComponent<PinRendererProps> = ({\n pin,\n selected,\n occluded,\n detached,\n}) => {\n const { primaryColor } = getPinColors(pin);\n\n return (\n <Fragment>\n {isTextPin(pin) && (\n <div\n id=\"pin-anchor\"\n class={classNames('pin-anchor', {\n selected: selected,\n 'pin-occluded': occluded,\n 'pin-detached': detached,\n })}\n style={{\n background: primaryColor,\n }}\n ></div>\n )}\n\n {isIconPin(pin) && (\n <vertex-viewer-icon\n name=\"pin-fill\"\n size=\"lg\"\n class={classNames('pin', {\n 'pin-selected': selected,\n 'pin-occluded': occluded,\n 'pin-detached': detached,\n })}\n style={{\n color: primaryColor,\n }}\n />\n )}\n </Fragment>\n );\n};\n","import { Dimensions, Point } from '@vertexvis/geometry';\n\nexport function getClosestCenterToPoint(\n boxPoint: Point.Point,\n pointToMeasure: Point.Point,\n dimensions: Dimensions.Dimensions\n): Point.Point {\n const topPoint = {\n x: boxPoint.x + dimensions.width / 2,\n y: boxPoint.y,\n };\n\n const bottomPoint = {\n x: boxPoint.x + dimensions.width / 2,\n y: boxPoint.y + dimensions.height,\n };\n\n const rightPoint = {\n x: boxPoint.x + dimensions.width,\n y: boxPoint.y + dimensions.height / 2,\n };\n\n const leftPoint = {\n x: boxPoint.x,\n y: boxPoint.y + dimensions.height / 2,\n };\n\n const candidates = [topPoint, bottomPoint, leftPoint, rightPoint];\n\n const distances = candidates.map((candidate) =>\n Point.distance(candidate, pointToMeasure)\n );\n\n const candidateIndex = distances.indexOf(Math.min(...distances));\n return candidates[candidateIndex];\n}\n",":host {\n\n /**\n * @prop --viewer-annotations-pin-primary-color: A CSS color that\n * specifies the primary color for the pins. This value gets used for the dot color \n * and borders\n */\n --viewer-annotations-pin-primary-color: var(--blue-700);\n\n /**\n * @prop --viewer-annotations-pin-accent-color: A CSS color that\n * specifies the accent color for the pins. This value gets used for background colors\n * \n */\n\n --viewer-annotations-pin-accent-color: var(--blue-200);\n /**\n * @prop viewer-annotations-pin-dot-color: A CSS color that\n * specifies the color of the anchor dot\n */\n --viewer-annotations-pin-dot-color: var(--viewer-annotations-pin-primary-color);\n\n /**\n * @prop --viewer-annotations-pin-color: A CSS color that\n * specifies the color of the pin\n */\n --viewer-annotations-pin-color: var(--viewer-annotations-pin-primary-color);\n\n /**\n * @prop --viewer-annotations-pin-font-size: A CSS property to specify\n the font size of the pin\n */\n --viewer-annotations-pin-font-size: 0.75rem;\n\n /**\n * @prop --viewer-annotations-pin-selected-stroke: A CSS color that\n * specifies the stroke color of a selected pin\n */\n --viewer-annotations-pin-selected-stroke: var(--white);\n\n /**\n * @prop --viewer-annotations-pin-selected-border: A CSS color that\n * specifies the border of a selected pin\n */\n --viewer-annotations-pin-selected-border: 2px solid var(--white);\n\n /**\n * @prop --viewer-annotations-pin-label-border: A CSS color that\n * specifies the border of a text pin anchor\n */\n --viewer-annotations-pin-label-border: 2px solid var(--black);\n\n /**\n * @prop --viewer-annotations-pin-selected-border: A CSS color that\n * specifies the stroke of a selected default pin\n */\n --viewer-annotations-pin-selected-stroke: var(--white);\n\n font-size: var(--viewer-annotations-pin-font-size);\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n overflow: hidden;\n pointer-events: none;\n}\n\n.pin-anchor {\n position: absolute;\n border-radius: 50%;\n transform: translate(-50%, -50%);\n display: block;\n width: 9px;\n height: 9px;\n box-sizing: border-box;\n border: var(--viewer-annotations-pin-label-border);\n background: var(--viewer-annotations-pin-dot-color);\n pointer-events: auto;\n cursor: pointer;\n}\n\n.selected {\n width: 13px;\n height: 13px;\n border: var(--viewer-annotations-pin-selected-border)\n}\n\n.pin {\n color: var(--viewer-annotations-pin-color);\n cursor: pointer;\n transition: opacity 0.3s ease-in;\n\n /**\n * Place bottom point of the pin at the location instead of the middle of the pin\n */\n transform: translate(0px, -12px);\n}\n\n.pin-selected {\n stroke-width: 1;\n stroke: var(--viewer-annotations-pin-selected-stroke);\n}\n\n.pin-occluded {\n opacity: .3;\n transition: opacity 0.3s ease-in;\n}\n\n.pin-detached {\n visibility: hidden;\n}","import {\n Component,\n Fragment,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n h,\n Listen,\n Prop,\n State,\n} from '@stencil/core';\nimport { Dimensions, Matrix4, Point, Vector3 } from '@vertexvis/geometry';\n\nimport { Viewport } from '../..';\nimport { PinController } from '../../lib/pins/controller';\nimport { isTextPin, Pin, TextPin } from '../../lib/pins/model';\nimport { PinModel } from '../../lib/pins/model';\nimport { translatePointToScreen } from '../viewer-pin-tool/utils';\nimport { PinRenderer } from './pin-renderer';\nimport { getClosestCenterToPoint } from './utils';\n\ninterface ComputedPoints {\n pinPoint: Point.Point;\n labelPoint?: Point.Point;\n}\n\n@Component({\n tag: 'vertex-viewer-pin-group',\n styleUrl: 'viewer-pin-group.css',\n shadow: false,\n})\nexport class ViewerPinGroup {\n /**\n * The pin to draw for the group\n */\n @Prop()\n public pin?: Pin;\n\n /**\n * The local matrix of this element.\n */\n @Prop({ mutable: true, attribute: null })\n public matrix: Matrix4.Matrix4 = Matrix4.makeIdentity();\n\n /**\n * Projection view matrix used for computing the position of the pin line\n */\n @Prop()\n public projectionViewMatrix: Matrix4.Matrix4 = Matrix4.makeIdentity();\n\n /**\n * The dimensions of the canvas for the pins\n */\n @Prop({ mutable: true })\n public elementBounds?: DOMRect;\n\n /**\n * The model that contains the entities and outcomes from performing pin operations\n */\n @Prop()\n public pinModel: PinModel = new PinModel();\n\n /**\n * The controller that drives behavior for pin operations\n */\n @Prop()\n public pinController?: PinController;\n\n /**\n * Whether the pin is \"selected\"\n */\n @Prop()\n public selected = false;\n\n /**\n * @internal\n * Whether the pin is occluded\n */\n @Prop({ mutable: true, reflect: true })\n public occluded = false;\n\n /**\n * @internal\n * Whether the pin is detached\n */\n @Prop({ mutable: true, reflect: true })\n public detached = false;\n\n @State()\n private invalidateStateCounter = 0;\n\n private labelEl: HTMLVertexViewerPinLabelElement | undefined;\n\n private resizeObserver?: ResizeObserver;\n\n protected componentDidLoad(): void {\n this.setLabelObserver();\n\n if (this.pinController == null) {\n this.pinController = new PinController(this.pinModel);\n }\n\n if (this.selected) {\n this.labelEl?.setFocus();\n }\n }\n\n /**\n * @ignore\n */\n @Listen('occlusionStateChanged')\n protected async handleOcclusionStateChanged(\n event: CustomEvent<boolean>\n ): Promise<void> {\n this.occluded = event.detail;\n }\n\n /**\n * @ignore\n */\n @Listen('detachedStateChanged')\n protected async handleDetachedStateChanged(\n event: CustomEvent<boolean>\n ): Promise<void> {\n this.detached = event.detail;\n }\n\n protected disconnectedCallback(): void {\n this.labelEl?.removeEventListener('labelChanged', this.invalidateState);\n this.resizeObserver?.disconnect();\n }\n\n protected render(): JSX.Element {\n if (this.pin == null) {\n throw new Error('Unable to draw pin');\n }\n\n const { pinPoint, labelPoint } = this.computePinPoints(this.pin);\n\n return (\n <Fragment>\n <vertex-viewer-dom-element\n data-testid={`drawn-pin-${this.pin.id}`}\n position={this.pin.worldPosition}\n onPointerDown={async () => {\n await this.labelEl?.submit();\n this.selectPin();\n this.handleAnchorPointerDown();\n }}\n detachedOff={false}\n >\n <PinRenderer\n pin={this.pin}\n selected={this.selected}\n occluded={this.occluded}\n detached={this.detached}\n />\n </vertex-viewer-dom-element>\n\n {isTextPin(this.pin) && !this.occluded && !this.detached && (\n <Fragment>\n <vertex-viewer-pin-label-line\n id={`pin-label-line-${this.pin?.id}`}\n pinPoint={pinPoint}\n pin={this.pin}\n labelPoint={labelPoint}\n onPointerDown={() => this.selectPin()}\n ></vertex-viewer-pin-label-line>\n\n <vertex-viewer-pin-label\n pin={this.pin}\n ref={(el) => (this.labelEl = el)}\n elementBounds={this.elementBounds}\n pinController={this.pinController}\n onPointerDown={() => this.selectPin()}\n ></vertex-viewer-pin-label>\n </Fragment>\n )}\n </Fragment>\n );\n }\n\n private invalidateState = (): void => {\n this.invalidateStateCounter = this.invalidateStateCounter + 1;\n };\n\n private setLabelObserver(): void {\n if (this.labelEl != null) {\n this.labelEl.addEventListener('labelChanged', this.invalidateState);\n\n this.resizeObserver = new ResizeObserver(() => this.invalidateState());\n this.resizeObserver.observe(this.labelEl);\n }\n }\n\n private computePinPoints(pin: Pin): ComputedPoints {\n if (this.elementBounds != null && this.pin != null) {\n return isTextPin(this.pin) && this.pin.label.point != null\n ? this.computeTextPinPoints(this.pin, this.elementBounds)\n : this.computeDefaultPinPoints(this.pin, this.elementBounds);\n }\n\n return { pinPoint: pin.worldPosition };\n }\n\n private computeDefaultPinPoints(\n pin: Pin,\n elementBounds: DOMRect\n ): ComputedPoints {\n return {\n pinPoint: this.getFromWorldPosition(\n pin.worldPosition,\n this.projectionViewMatrix,\n elementBounds\n ),\n };\n }\n\n private computeTextPinPoints(\n pin: TextPin,\n elementBounds: DOMRect\n ): ComputedPoints {\n const { pinPoint } = this.computeDefaultPinPoints(pin, elementBounds);\n\n const screenPosition = translatePointToScreen(\n pin.label.point,\n elementBounds\n );\n\n const labelWidth = this.labelEl?.firstElementChild?.clientWidth || 0;\n const labelHeight = this.labelEl?.firstElementChild?.clientHeight || 0;\n\n return {\n pinPoint,\n labelPoint: getClosestCenterToPoint(screenPosition, pinPoint, {\n width: labelWidth,\n height: labelHeight,\n }),\n };\n }\n\n private handleAnchorPointerDown(): void {\n if (\n this.elementBounds != null &&\n this.pinController?.getToolMode() === 'edit' &&\n this.pin != null\n ) {\n this.pinController?.setDraggable({ id: this.pin.id });\n }\n }\n\n private selectPin(): void {\n this.pinController?.setSelectedPinId(this.pin?.id);\n }\n\n private getFromWorldPosition(\n pt: Vector3.Vector3,\n projectionViewMatrix: Matrix4.Matrix4,\n dimensions: Dimensions.Dimensions\n ): Point.Point {\n const ndcPt = Vector3.transformMatrix(pt, projectionViewMatrix);\n return Viewport.fromDimensions(dimensions).transformVectorToViewport(ndcPt);\n }\n}\n"],"version":3}
@@ -9,7 +9,7 @@ const index = require('./index-0abd8b0b.js');
9
9
  const model = require('./model-eab9e804.js');
10
10
  const bundle_esm = require('./bundle.esm-2509a52c.js');
11
11
  const browser_esm = require('./browser.esm-262464ed.js');
12
- const cursors = require('./cursors-2dfb0ef3.js');
12
+ const cursors = require('./cursors-17ad74ac.js');
13
13
  const dom = require('./dom-d820f463.js');
14
14
  const elementRectObserver = require('./elementRectObserver-3f6af753.js');
15
15
  const entities = require('./entities-2b21dc38.js');
@@ -17,7 +17,7 @@ const grpc = require('./grpc-799a7d35.js');
17
17
  const streamAttributes = require('./streamAttributes-9cc1133e.js');
18
18
  const queries = require('./queries-4580caa5.js');
19
19
  const config = require('./config-b0060c6f.js');
20
- const cursors = require('./cursors-2dfb0ef3.js');
20
+ const cursors = require('./cursors-17ad74ac.js');
21
21
  const dom = require('./dom-d820f463.js');
22
22
  const entities = require('./entities-2b21dc38.js');
23
23
  const viewport = require('./viewport-ab039fbb.js');
@@ -90,6 +90,11 @@
90
90
  color: var(--viewer-annotations-pin-color);
91
91
  cursor: pointer;
92
92
  transition: opacity 0.3s ease-in;
93
+
94
+ /**
95
+ * Place bottom point of the pin at the location instead of the middle of the pin
96
+ */
97
+ transform: translate(0px, -12px);
93
98
  }
94
99
 
95
100
  .pin-selected {
@@ -109,7 +109,7 @@ export const measurementWithArrowCursor = {
109
109
  export const pinCursor = {
110
110
  url: "data:image/svg+xml,%3Csvg width='36px' height='36px' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath d='M12,2 C7.581722,2 4,5.581722 4,10 C4.00435812,11.7714969 4.41127263,13.5188357 5.19,15.11 C6.15517666,17.0237439 7.49502409,18.7240579 9.13,20.11 C9.86916736,20.7592093 10.6620019,21.3446357 11.5,21.86 L12,22.14 L12.5,21.86 C13.8750156,21.0120029 15.1296156,19.9827599 16.23,18.8 C17.2698142,17.7023203 18.1394508,16.4551671 18.81,15.1 C19.5872532,13.5118707 19.9941287,11.7681184 20,10 C20,5.581722 16.418278,2 12,2 Z M12,13 C10.3431458,13 9,11.6568542 9,10 C9,8.34314575 10.3431458,7 12,7 C13.6568542,7 15,8.34314575 15,10 C15,10.7956495 14.6839295,11.5587112 14.1213203,12.1213203 C13.5587112,12.6839295 12.7956495,13 12,13 Z' id='path-1'%3E%3C/path%3E%3C/defs%3E%3Cg id='icons/pin-filled' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cmask id='mask-2' fill='white'%3E%3Cuse xlink:href='%23path-1'%3E%3C/use%3E%3C/mask%3E%3Cuse id='Shape' stroke='%23FAFAFA' fill='%23BDBDBD' fill-rule='nonzero' xlink:href='%23path-1'%3E%3C/use%3E%3C/g%3E%3C/svg%3E",
111
111
  offsetX: 17,
112
- offsetY: 22,
112
+ offsetY: 32,
113
113
  };
114
114
  export const labelPinCursor = {
115
115
  url: "data:image/svg+xml,%3Csvg width='36px' height='36px' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 16 24' %3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D.cls-2%7Bfill:%23616161;%7D.cls-3%7Bclip-path:url(%23clip-path);%7D%3C/style%3E%3CclipPath id='clip-path'%3E%3Ccircle cx='-576.76' cy='-107.26' r='4'/%3E%3C/clipPath%3E%3C/defs%3E%3Cpath d='M8,16H8a.48.48,0,0,1-.42-.23L5.75,13H3.51A1.5,1.5,0,0,1,2,11.5v-8A1.5,1.5,0,0,1,3.51,2h9A1.51,1.51,0,0,1,14,3.5v8a1.5,1.5,0,0,1-1.5,1.5H10.22L8.39,15.81A.5.5,0,0,1,8,16ZM3.51,3a.5.5,0,0,0-.5.5v8a.5.5,0,0,0,.5.5H6a.5.5,0,0,1,.42.23L8,14.61l1.55-2.38A.5.5,0,0,1,10,12h2.56a.5.5,0,0,0,.5-.5v-8a.51.51,0,0,0-.5-.5Z'/%3E%3Ccircle cx='8.01' cy='20' r='2'/%3E%3C/svg%3E%0A",
@@ -1 +1 @@
1
- {"version":3,"file":"cursors.js","sourceRoot":"","sources":["../../../../src/lib/cursors.ts"],"names":[],"mappings":"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","sourcesContent":["import { Disposable, EventDispatcher } from '@vertexvis/utils';\n\n/**\n * Represents a built-in [browser CSS\n * cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).\n */\nexport type CssCursor =\n | 'auto'\n | 'default'\n | 'none'\n | 'context-menu'\n | 'help'\n | 'pointer'\n | 'progress'\n | 'wait'\n | 'cell'\n | 'crosshair'\n | 'text'\n | 'vertical-text'\n | 'alias'\n | 'copy'\n | 'move'\n | 'no-drop'\n | 'not-allowed'\n | 'grab'\n | 'grabbing'\n | 'all-scroll'\n | 'col-resize'\n | 'row-resize'\n | 'n-resize'\n | 'e-resize'\n | 's-resize'\n | 'w-resize'\n | 'ne-resize'\n | 'nw-resize'\n | 'se-resize'\n | 'sw-resize'\n | 'ew-resize'\n | 'ns-resize'\n | 'nesw-resize'\n | 'nwse-resize'\n | 'zoom-in'\n | 'zoom-out'\n | string;\n\n/**\n * Represents a custom cursor that points to an image file and offset.\n */\nexport interface CustomCursor {\n url: string;\n offsetX?: number;\n offsetY?: number;\n}\n\n/**\n * Represents all possible cursor types.\n */\nexport type Cursor = CssCursor | CustomCursor;\n\ninterface CursorInstance extends Disposable {\n id: number;\n cursor: Cursor;\n priority: number;\n}\n\n/**\n * The cursor manager maintains a prioritized list of cursors for the viewer.\n *\n * Cursors with the highest priority will be considered active, where the most\n * recently added cursor will take precedence if there are multiple cursors with\n * the same priority.\n */\nexport class CursorManager {\n /**\n * A constant representing the lowest priority cursors.\n */\n public static readonly LOW_PRIORITY = 0;\n\n /**\n * A constant representing a priority between `LOW_PRIORITY` and\n * `HIGH_PRIORITY`.\n */\n public static readonly NORMAL_PRIORITY = 10;\n\n /**\n * A constant representing the high priority cursors.\n */\n public static readonly HIGH_PRIORITY = 20;\n\n /**\n * An event dispatcher that emits an event when a cursor is added or removed.\n *\n * @see {@link CursorManager.add} to add a cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public readonly onChanged = new EventDispatcher<void>();\n\n private cursors: CursorInstance[] = [];\n\n private nextId = 0;\n\n /**\n * Adds a cursor to the cursor manager, and returns an identifier that can be\n * used to remove the cursor.\n *\n * @param cursor The cursor to add.\n * @param priority The priority of the cursor. Higher values have higher\n * \tpriority over lower values.\n * @returns An identifier for the cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public add(\n cursor: Cursor,\n priority = CursorManager.NORMAL_PRIORITY\n ): Disposable {\n // Ensure a duplicate cursor will not be added to the cursor manager.\n // If a matching cursor exists, delete it before proceeding.\n // Note that deleting the old cursor and adding the new one results in the\n // new cursor taking precedent over other existing cursors with the same priority.\n const duplicateCursor = this.getExistingDuplicateCursor(cursor, priority);\n if (duplicateCursor != null) {\n this.remove(duplicateCursor.id);\n }\n\n const id = ++this.nextId;\n const instance = { id, cursor, priority, dispose: () => this.remove(id) };\n this.cursors.push(instance);\n this.onChanged.emit();\n return instance;\n }\n\n /**\n * Removes a cursor with the given ID, if it exists.\n *\n * @param cursorId The ID of the cursor to remove.\n */\n private remove(cursorId: number): void {\n const index = this.cursors.findIndex(({ id }) => id === cursorId);\n if (index >= 0) {\n this.cursors.splice(index, 1);\n this.onChanged.emit();\n }\n }\n\n /**\n * Checks to see if an existing cursor matches the provided cursor and priority level.\n * The matching cursor is returned if found.\n *\n * @param cursorToCheck The cursor to check for duplicates against.\n * @param priorityToCheck The priority level to check for duplicates against.\n */\n private getExistingDuplicateCursor(\n cursorToCheck: Cursor,\n priorityToCheck: number\n ): CursorInstance | undefined {\n return this.cursors.find(\n (cursor) =>\n cursor.cursor === cursorToCheck && cursor.priority === priorityToCheck\n );\n }\n\n /**\n * Returns the active cursor based on priority and insertion order.\n *\n * @see {@link CursorManager.add} to add a cursor.\n */\n public getActiveCursor(): Cursor | undefined {\n const sorted = this.cursors\n .concat()\n .reverse()\n .sort((a, b) => b.priority - a.priority);\n\n return sorted[0]?.cursor;\n }\n}\n\n// CSS SVG images need to be URL encoded: https://yoksel.github.io/url-encoder/\n\nexport const measurementCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' stroke='%23fff' stroke-width='1.25' stroke-opacity='0.5' stroke-miterlimit='10' shape-rendering='crispEdges'/%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' shape-rendering='crispEdges'/%3E%3C/svg%3E\",\n offsetX: -24,\n offsetY: -24,\n};\n\nexport const measurementWithArrowCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-1' d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath class='cls-2' d='M1,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.08,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E%3Cpath class='cls-3' d='M8.75,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n\nexport const pinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath d='M12,2 C7.581722,2 4,5.581722 4,10 C4.00435812,11.7714969 4.41127263,13.5188357 5.19,15.11 C6.15517666,17.0237439 7.49502409,18.7240579 9.13,20.11 C9.86916736,20.7592093 10.6620019,21.3446357 11.5,21.86 L12,22.14 L12.5,21.86 C13.8750156,21.0120029 15.1296156,19.9827599 16.23,18.8 C17.2698142,17.7023203 18.1394508,16.4551671 18.81,15.1 C19.5872532,13.5118707 19.9941287,11.7681184 20,10 C20,5.581722 16.418278,2 12,2 Z M12,13 C10.3431458,13 9,11.6568542 9,10 C9,8.34314575 10.3431458,7 12,7 C13.6568542,7 15,8.34314575 15,10 C15,10.7956495 14.6839295,11.5587112 14.1213203,12.1213203 C13.5587112,12.6839295 12.7956495,13 12,13 Z' id='path-1'%3E%3C/path%3E%3C/defs%3E%3Cg id='icons/pin-filled' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cmask id='mask-2' fill='white'%3E%3Cuse xlink:href='%23path-1'%3E%3C/use%3E%3C/mask%3E%3Cuse id='Shape' stroke='%23FAFAFA' fill='%23BDBDBD' fill-rule='nonzero' xlink:href='%23path-1'%3E%3C/use%3E%3C/g%3E%3C/svg%3E\",\n offsetX: 17,\n offsetY: 22,\n};\n\nexport const labelPinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 16 24' %3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D.cls-2%7Bfill:%23616161;%7D.cls-3%7Bclip-path:url(%23clip-path);%7D%3C/style%3E%3CclipPath id='clip-path'%3E%3Ccircle cx='-576.76' cy='-107.26' r='4'/%3E%3C/clipPath%3E%3C/defs%3E%3Cpath d='M8,16H8a.48.48,0,0,1-.42-.23L5.75,13H3.51A1.5,1.5,0,0,1,2,11.5v-8A1.5,1.5,0,0,1,3.51,2h9A1.51,1.51,0,0,1,14,3.5v8a1.5,1.5,0,0,1-1.5,1.5H10.22L8.39,15.81A.5.5,0,0,1,8,16ZM3.51,3a.5.5,0,0,0-.5.5v8a.5.5,0,0,0,.5.5H6a.5.5,0,0,1,.42.23L8,14.61l1.55-2.38A.5.5,0,0,1,10,12h2.56a.5.5,0,0,0,.5-.5v-8a.51.51,0,0,0-.5-.5Z'/%3E%3Ccircle cx='8.01' cy='20' r='2'/%3E%3C/svg%3E%0A\",\n offsetX: 17,\n offsetY: 29,\n};\n\nexport const boxQueryCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-2' d='M1.25,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.33,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E %3Cpath class='cls-3' d='M9,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2.25,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3Cpath class='cls-1' d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E %3Cpath d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n"]}
1
+ {"version":3,"file":"cursors.js","sourceRoot":"","sources":["../../../../src/lib/cursors.ts"],"names":[],"mappings":"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","sourcesContent":["import { Disposable, EventDispatcher } from '@vertexvis/utils';\n\n/**\n * Represents a built-in [browser CSS\n * cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).\n */\nexport type CssCursor =\n | 'auto'\n | 'default'\n | 'none'\n | 'context-menu'\n | 'help'\n | 'pointer'\n | 'progress'\n | 'wait'\n | 'cell'\n | 'crosshair'\n | 'text'\n | 'vertical-text'\n | 'alias'\n | 'copy'\n | 'move'\n | 'no-drop'\n | 'not-allowed'\n | 'grab'\n | 'grabbing'\n | 'all-scroll'\n | 'col-resize'\n | 'row-resize'\n | 'n-resize'\n | 'e-resize'\n | 's-resize'\n | 'w-resize'\n | 'ne-resize'\n | 'nw-resize'\n | 'se-resize'\n | 'sw-resize'\n | 'ew-resize'\n | 'ns-resize'\n | 'nesw-resize'\n | 'nwse-resize'\n | 'zoom-in'\n | 'zoom-out'\n | string;\n\n/**\n * Represents a custom cursor that points to an image file and offset.\n */\nexport interface CustomCursor {\n url: string;\n offsetX?: number;\n offsetY?: number;\n}\n\n/**\n * Represents all possible cursor types.\n */\nexport type Cursor = CssCursor | CustomCursor;\n\ninterface CursorInstance extends Disposable {\n id: number;\n cursor: Cursor;\n priority: number;\n}\n\n/**\n * The cursor manager maintains a prioritized list of cursors for the viewer.\n *\n * Cursors with the highest priority will be considered active, where the most\n * recently added cursor will take precedence if there are multiple cursors with\n * the same priority.\n */\nexport class CursorManager {\n /**\n * A constant representing the lowest priority cursors.\n */\n public static readonly LOW_PRIORITY = 0;\n\n /**\n * A constant representing a priority between `LOW_PRIORITY` and\n * `HIGH_PRIORITY`.\n */\n public static readonly NORMAL_PRIORITY = 10;\n\n /**\n * A constant representing the high priority cursors.\n */\n public static readonly HIGH_PRIORITY = 20;\n\n /**\n * An event dispatcher that emits an event when a cursor is added or removed.\n *\n * @see {@link CursorManager.add} to add a cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public readonly onChanged = new EventDispatcher<void>();\n\n private cursors: CursorInstance[] = [];\n\n private nextId = 0;\n\n /**\n * Adds a cursor to the cursor manager, and returns an identifier that can be\n * used to remove the cursor.\n *\n * @param cursor The cursor to add.\n * @param priority The priority of the cursor. Higher values have higher\n * \tpriority over lower values.\n * @returns An identifier for the cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public add(\n cursor: Cursor,\n priority = CursorManager.NORMAL_PRIORITY\n ): Disposable {\n // Ensure a duplicate cursor will not be added to the cursor manager.\n // If a matching cursor exists, delete it before proceeding.\n // Note that deleting the old cursor and adding the new one results in the\n // new cursor taking precedent over other existing cursors with the same priority.\n const duplicateCursor = this.getExistingDuplicateCursor(cursor, priority);\n if (duplicateCursor != null) {\n this.remove(duplicateCursor.id);\n }\n\n const id = ++this.nextId;\n const instance = { id, cursor, priority, dispose: () => this.remove(id) };\n this.cursors.push(instance);\n this.onChanged.emit();\n return instance;\n }\n\n /**\n * Removes a cursor with the given ID, if it exists.\n *\n * @param cursorId The ID of the cursor to remove.\n */\n private remove(cursorId: number): void {\n const index = this.cursors.findIndex(({ id }) => id === cursorId);\n if (index >= 0) {\n this.cursors.splice(index, 1);\n this.onChanged.emit();\n }\n }\n\n /**\n * Checks to see if an existing cursor matches the provided cursor and priority level.\n * The matching cursor is returned if found.\n *\n * @param cursorToCheck The cursor to check for duplicates against.\n * @param priorityToCheck The priority level to check for duplicates against.\n */\n private getExistingDuplicateCursor(\n cursorToCheck: Cursor,\n priorityToCheck: number\n ): CursorInstance | undefined {\n return this.cursors.find(\n (cursor) =>\n cursor.cursor === cursorToCheck && cursor.priority === priorityToCheck\n );\n }\n\n /**\n * Returns the active cursor based on priority and insertion order.\n *\n * @see {@link CursorManager.add} to add a cursor.\n */\n public getActiveCursor(): Cursor | undefined {\n const sorted = this.cursors\n .concat()\n .reverse()\n .sort((a, b) => b.priority - a.priority);\n\n return sorted[0]?.cursor;\n }\n}\n\n// CSS SVG images need to be URL encoded: https://yoksel.github.io/url-encoder/\n\nexport const measurementCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' stroke='%23fff' stroke-width='1.25' stroke-opacity='0.5' stroke-miterlimit='10' shape-rendering='crispEdges'/%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' shape-rendering='crispEdges'/%3E%3C/svg%3E\",\n offsetX: -24,\n offsetY: -24,\n};\n\nexport const measurementWithArrowCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-1' d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath class='cls-2' d='M1,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.08,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E%3Cpath class='cls-3' d='M8.75,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n\nexport const pinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath d='M12,2 C7.581722,2 4,5.581722 4,10 C4.00435812,11.7714969 4.41127263,13.5188357 5.19,15.11 C6.15517666,17.0237439 7.49502409,18.7240579 9.13,20.11 C9.86916736,20.7592093 10.6620019,21.3446357 11.5,21.86 L12,22.14 L12.5,21.86 C13.8750156,21.0120029 15.1296156,19.9827599 16.23,18.8 C17.2698142,17.7023203 18.1394508,16.4551671 18.81,15.1 C19.5872532,13.5118707 19.9941287,11.7681184 20,10 C20,5.581722 16.418278,2 12,2 Z M12,13 C10.3431458,13 9,11.6568542 9,10 C9,8.34314575 10.3431458,7 12,7 C13.6568542,7 15,8.34314575 15,10 C15,10.7956495 14.6839295,11.5587112 14.1213203,12.1213203 C13.5587112,12.6839295 12.7956495,13 12,13 Z' id='path-1'%3E%3C/path%3E%3C/defs%3E%3Cg id='icons/pin-filled' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cmask id='mask-2' fill='white'%3E%3Cuse xlink:href='%23path-1'%3E%3C/use%3E%3C/mask%3E%3Cuse id='Shape' stroke='%23FAFAFA' fill='%23BDBDBD' fill-rule='nonzero' xlink:href='%23path-1'%3E%3C/use%3E%3C/g%3E%3C/svg%3E\",\n offsetX: 17,\n offsetY: 32,\n};\n\nexport const labelPinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 16 24' %3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D.cls-2%7Bfill:%23616161;%7D.cls-3%7Bclip-path:url(%23clip-path);%7D%3C/style%3E%3CclipPath id='clip-path'%3E%3Ccircle cx='-576.76' cy='-107.26' r='4'/%3E%3C/clipPath%3E%3C/defs%3E%3Cpath d='M8,16H8a.48.48,0,0,1-.42-.23L5.75,13H3.51A1.5,1.5,0,0,1,2,11.5v-8A1.5,1.5,0,0,1,3.51,2h9A1.51,1.51,0,0,1,14,3.5v8a1.5,1.5,0,0,1-1.5,1.5H10.22L8.39,15.81A.5.5,0,0,1,8,16ZM3.51,3a.5.5,0,0,0-.5.5v8a.5.5,0,0,0,.5.5H6a.5.5,0,0,1,.42.23L8,14.61l1.55-2.38A.5.5,0,0,1,10,12h2.56a.5.5,0,0,0,.5-.5v-8a.51.51,0,0,0-.5-.5Z'/%3E%3Ccircle cx='8.01' cy='20' r='2'/%3E%3C/svg%3E%0A\",\n offsetX: 17,\n offsetY: 29,\n};\n\nexport const boxQueryCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-2' d='M1.25,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.33,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E %3Cpath class='cls-3' d='M9,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2.25,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3Cpath class='cls-1' d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E %3Cpath d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n"]}
@@ -110,7 +110,7 @@ const measurementWithArrowCursor = {
110
110
  const pinCursor = {
111
111
  url: "data:image/svg+xml,%3Csvg width='36px' height='36px' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath d='M12,2 C7.581722,2 4,5.581722 4,10 C4.00435812,11.7714969 4.41127263,13.5188357 5.19,15.11 C6.15517666,17.0237439 7.49502409,18.7240579 9.13,20.11 C9.86916736,20.7592093 10.6620019,21.3446357 11.5,21.86 L12,22.14 L12.5,21.86 C13.8750156,21.0120029 15.1296156,19.9827599 16.23,18.8 C17.2698142,17.7023203 18.1394508,16.4551671 18.81,15.1 C19.5872532,13.5118707 19.9941287,11.7681184 20,10 C20,5.581722 16.418278,2 12,2 Z M12,13 C10.3431458,13 9,11.6568542 9,10 C9,8.34314575 10.3431458,7 12,7 C13.6568542,7 15,8.34314575 15,10 C15,10.7956495 14.6839295,11.5587112 14.1213203,12.1213203 C13.5587112,12.6839295 12.7956495,13 12,13 Z' id='path-1'%3E%3C/path%3E%3C/defs%3E%3Cg id='icons/pin-filled' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cmask id='mask-2' fill='white'%3E%3Cuse xlink:href='%23path-1'%3E%3C/use%3E%3C/mask%3E%3Cuse id='Shape' stroke='%23FAFAFA' fill='%23BDBDBD' fill-rule='nonzero' xlink:href='%23path-1'%3E%3C/use%3E%3C/g%3E%3C/svg%3E",
112
112
  offsetX: 17,
113
- offsetY: 22,
113
+ offsetY: 32,
114
114
  };
115
115
  const labelPinCursor = {
116
116
  url: "data:image/svg+xml,%3Csvg width='36px' height='36px' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 16 24' %3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D.cls-2%7Bfill:%23616161;%7D.cls-3%7Bclip-path:url(%23clip-path);%7D%3C/style%3E%3CclipPath id='clip-path'%3E%3Ccircle cx='-576.76' cy='-107.26' r='4'/%3E%3C/clipPath%3E%3C/defs%3E%3Cpath d='M8,16H8a.48.48,0,0,1-.42-.23L5.75,13H3.51A1.5,1.5,0,0,1,2,11.5v-8A1.5,1.5,0,0,1,3.51,2h9A1.51,1.51,0,0,1,14,3.5v8a1.5,1.5,0,0,1-1.5,1.5H10.22L8.39,15.81A.5.5,0,0,1,8,16ZM3.51,3a.5.5,0,0,0-.5.5v8a.5.5,0,0,0,.5.5H6a.5.5,0,0,1,.42.23L8,14.61l1.55-2.38A.5.5,0,0,1,10,12h2.56a.5.5,0,0,0,.5-.5v-8a.51.51,0,0,0-.5-.5Z'/%3E%3Ccircle cx='8.01' cy='20' r='2'/%3E%3C/svg%3E%0A",
@@ -1 +1 @@
1
- {"file":"cursors.js","mappings":";;;;;AAiEA;;;;;;;MAOa,aAAa;EAA1B;;;;;;;IAuBkB,cAAS,GAAG,IAAI,eAAe,EAAQ,CAAC;IAEhD,YAAO,GAAqB,EAAE,CAAC;IAE/B,WAAM,GAAG,CAAC,CAAC;GA2EpB;;;;;;;;;;;EA/DQ,GAAG,CACR,MAAc,EACd,QAAQ,GAAG,aAAa,CAAC,eAAe;;;;;IAMxC,MAAM,eAAe,GAAG,IAAI,CAAC,0BAA0B,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1E,IAAI,eAAe,IAAI,IAAI,EAAE;MAC3B,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;KACjC;IAED,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC;IACzB,MAAM,QAAQ,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1E,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACtB,OAAO,QAAQ,CAAC;GACjB;;;;;;EAOO,MAAM,CAAC,QAAgB;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,QAAQ,CAAC,CAAC;IAClE,IAAI,KAAK,IAAI,CAAC,EAAE;MACd,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;MAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;KACvB;GACF;;;;;;;;EASO,0BAA0B,CAChC,aAAqB,EACrB,eAAuB;IAEvB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CACtB,CAAC,MAAM,KACL,MAAM,CAAC,MAAM,KAAK,aAAa,IAAI,MAAM,CAAC,QAAQ,KAAK,eAAe,CACzE,CAAC;GACH;;;;;;EAOM,eAAe;;IACpB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO;OACxB,MAAM,EAAE;OACR,OAAO,EAAE;OACT,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE3C,OAAO,MAAA,MAAM,CAAC,CAAC,CAAC,0CAAE,MAAM,CAAC;GAC1B;;AApGD;;;AAGuB,0BAAY,GAAG,CAAC,CAAC;AAExC;;;;AAIuB,6BAAe,GAAG,EAAE,CAAC;AAE5C;;;AAGuB,2BAAa,GAAG,EAAE,CAAC;AAyF5C;MAEa,iBAAiB,GAAG;EAC/B,GAAG,EAAE,irBAAirB;EACtrB,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;EACZ;MAEW,0BAA0B,GAAG;EACxC,GAAG,EAAE,siCAAsiC;EAC3iC,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;EACZ;MAEW,SAAS,GAAG;EACvB,GAAG,EAAE,2oCAA2oC;EAChpC,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,EAAE;EACX;MAEW,cAAc,GAAG;EAC5B,GAAG,EAAE,mvBAAmvB;EACxvB,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,EAAE;EACX;MAEW,cAAc,GAAG;EAC5B,GAAG,EAAE,+0BAA+0B;EACp1B,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;;;;;","names":[],"sources":["./src/lib/cursors.ts"],"sourcesContent":["import { Disposable, EventDispatcher } from '@vertexvis/utils';\n\n/**\n * Represents a built-in [browser CSS\n * cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).\n */\nexport type CssCursor =\n | 'auto'\n | 'default'\n | 'none'\n | 'context-menu'\n | 'help'\n | 'pointer'\n | 'progress'\n | 'wait'\n | 'cell'\n | 'crosshair'\n | 'text'\n | 'vertical-text'\n | 'alias'\n | 'copy'\n | 'move'\n | 'no-drop'\n | 'not-allowed'\n | 'grab'\n | 'grabbing'\n | 'all-scroll'\n | 'col-resize'\n | 'row-resize'\n | 'n-resize'\n | 'e-resize'\n | 's-resize'\n | 'w-resize'\n | 'ne-resize'\n | 'nw-resize'\n | 'se-resize'\n | 'sw-resize'\n | 'ew-resize'\n | 'ns-resize'\n | 'nesw-resize'\n | 'nwse-resize'\n | 'zoom-in'\n | 'zoom-out'\n | string;\n\n/**\n * Represents a custom cursor that points to an image file and offset.\n */\nexport interface CustomCursor {\n url: string;\n offsetX?: number;\n offsetY?: number;\n}\n\n/**\n * Represents all possible cursor types.\n */\nexport type Cursor = CssCursor | CustomCursor;\n\ninterface CursorInstance extends Disposable {\n id: number;\n cursor: Cursor;\n priority: number;\n}\n\n/**\n * The cursor manager maintains a prioritized list of cursors for the viewer.\n *\n * Cursors with the highest priority will be considered active, where the most\n * recently added cursor will take precedence if there are multiple cursors with\n * the same priority.\n */\nexport class CursorManager {\n /**\n * A constant representing the lowest priority cursors.\n */\n public static readonly LOW_PRIORITY = 0;\n\n /**\n * A constant representing a priority between `LOW_PRIORITY` and\n * `HIGH_PRIORITY`.\n */\n public static readonly NORMAL_PRIORITY = 10;\n\n /**\n * A constant representing the high priority cursors.\n */\n public static readonly HIGH_PRIORITY = 20;\n\n /**\n * An event dispatcher that emits an event when a cursor is added or removed.\n *\n * @see {@link CursorManager.add} to add a cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public readonly onChanged = new EventDispatcher<void>();\n\n private cursors: CursorInstance[] = [];\n\n private nextId = 0;\n\n /**\n * Adds a cursor to the cursor manager, and returns an identifier that can be\n * used to remove the cursor.\n *\n * @param cursor The cursor to add.\n * @param priority The priority of the cursor. Higher values have higher\n * \tpriority over lower values.\n * @returns An identifier for the cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public add(\n cursor: Cursor,\n priority = CursorManager.NORMAL_PRIORITY\n ): Disposable {\n // Ensure a duplicate cursor will not be added to the cursor manager.\n // If a matching cursor exists, delete it before proceeding.\n // Note that deleting the old cursor and adding the new one results in the\n // new cursor taking precedent over other existing cursors with the same priority.\n const duplicateCursor = this.getExistingDuplicateCursor(cursor, priority);\n if (duplicateCursor != null) {\n this.remove(duplicateCursor.id);\n }\n\n const id = ++this.nextId;\n const instance = { id, cursor, priority, dispose: () => this.remove(id) };\n this.cursors.push(instance);\n this.onChanged.emit();\n return instance;\n }\n\n /**\n * Removes a cursor with the given ID, if it exists.\n *\n * @param cursorId The ID of the cursor to remove.\n */\n private remove(cursorId: number): void {\n const index = this.cursors.findIndex(({ id }) => id === cursorId);\n if (index >= 0) {\n this.cursors.splice(index, 1);\n this.onChanged.emit();\n }\n }\n\n /**\n * Checks to see if an existing cursor matches the provided cursor and priority level.\n * The matching cursor is returned if found.\n *\n * @param cursorToCheck The cursor to check for duplicates against.\n * @param priorityToCheck The priority level to check for duplicates against.\n */\n private getExistingDuplicateCursor(\n cursorToCheck: Cursor,\n priorityToCheck: number\n ): CursorInstance | undefined {\n return this.cursors.find(\n (cursor) =>\n cursor.cursor === cursorToCheck && cursor.priority === priorityToCheck\n );\n }\n\n /**\n * Returns the active cursor based on priority and insertion order.\n *\n * @see {@link CursorManager.add} to add a cursor.\n */\n public getActiveCursor(): Cursor | undefined {\n const sorted = this.cursors\n .concat()\n .reverse()\n .sort((a, b) => b.priority - a.priority);\n\n return sorted[0]?.cursor;\n }\n}\n\n// CSS SVG images need to be URL encoded: https://yoksel.github.io/url-encoder/\n\nexport const measurementCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' stroke='%23fff' stroke-width='1.25' stroke-opacity='0.5' stroke-miterlimit='10' shape-rendering='crispEdges'/%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' shape-rendering='crispEdges'/%3E%3C/svg%3E\",\n offsetX: -24,\n offsetY: -24,\n};\n\nexport const measurementWithArrowCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-1' d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath class='cls-2' d='M1,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.08,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E%3Cpath class='cls-3' d='M8.75,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n\nexport const pinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath d='M12,2 C7.581722,2 4,5.581722 4,10 C4.00435812,11.7714969 4.41127263,13.5188357 5.19,15.11 C6.15517666,17.0237439 7.49502409,18.7240579 9.13,20.11 C9.86916736,20.7592093 10.6620019,21.3446357 11.5,21.86 L12,22.14 L12.5,21.86 C13.8750156,21.0120029 15.1296156,19.9827599 16.23,18.8 C17.2698142,17.7023203 18.1394508,16.4551671 18.81,15.1 C19.5872532,13.5118707 19.9941287,11.7681184 20,10 C20,5.581722 16.418278,2 12,2 Z M12,13 C10.3431458,13 9,11.6568542 9,10 C9,8.34314575 10.3431458,7 12,7 C13.6568542,7 15,8.34314575 15,10 C15,10.7956495 14.6839295,11.5587112 14.1213203,12.1213203 C13.5587112,12.6839295 12.7956495,13 12,13 Z' id='path-1'%3E%3C/path%3E%3C/defs%3E%3Cg id='icons/pin-filled' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cmask id='mask-2' fill='white'%3E%3Cuse xlink:href='%23path-1'%3E%3C/use%3E%3C/mask%3E%3Cuse id='Shape' stroke='%23FAFAFA' fill='%23BDBDBD' fill-rule='nonzero' xlink:href='%23path-1'%3E%3C/use%3E%3C/g%3E%3C/svg%3E\",\n offsetX: 17,\n offsetY: 22,\n};\n\nexport const labelPinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 16 24' %3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D.cls-2%7Bfill:%23616161;%7D.cls-3%7Bclip-path:url(%23clip-path);%7D%3C/style%3E%3CclipPath id='clip-path'%3E%3Ccircle cx='-576.76' cy='-107.26' r='4'/%3E%3C/clipPath%3E%3C/defs%3E%3Cpath d='M8,16H8a.48.48,0,0,1-.42-.23L5.75,13H3.51A1.5,1.5,0,0,1,2,11.5v-8A1.5,1.5,0,0,1,3.51,2h9A1.51,1.51,0,0,1,14,3.5v8a1.5,1.5,0,0,1-1.5,1.5H10.22L8.39,15.81A.5.5,0,0,1,8,16ZM3.51,3a.5.5,0,0,0-.5.5v8a.5.5,0,0,0,.5.5H6a.5.5,0,0,1,.42.23L8,14.61l1.55-2.38A.5.5,0,0,1,10,12h2.56a.5.5,0,0,0,.5-.5v-8a.51.51,0,0,0-.5-.5Z'/%3E%3Ccircle cx='8.01' cy='20' r='2'/%3E%3C/svg%3E%0A\",\n offsetX: 17,\n offsetY: 29,\n};\n\nexport const boxQueryCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-2' d='M1.25,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.33,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E %3Cpath class='cls-3' d='M9,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2.25,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3Cpath class='cls-1' d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E %3Cpath d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n"],"version":3}
1
+ {"file":"cursors.js","mappings":";;;;;AAiEA;;;;;;;MAOa,aAAa;EAA1B;;;;;;;IAuBkB,cAAS,GAAG,IAAI,eAAe,EAAQ,CAAC;IAEhD,YAAO,GAAqB,EAAE,CAAC;IAE/B,WAAM,GAAG,CAAC,CAAC;GA2EpB;;;;;;;;;;;EA/DQ,GAAG,CACR,MAAc,EACd,QAAQ,GAAG,aAAa,CAAC,eAAe;;;;;IAMxC,MAAM,eAAe,GAAG,IAAI,CAAC,0BAA0B,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1E,IAAI,eAAe,IAAI,IAAI,EAAE;MAC3B,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;KACjC;IAED,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC;IACzB,MAAM,QAAQ,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1E,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACtB,OAAO,QAAQ,CAAC;GACjB;;;;;;EAOO,MAAM,CAAC,QAAgB;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,QAAQ,CAAC,CAAC;IAClE,IAAI,KAAK,IAAI,CAAC,EAAE;MACd,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;MAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;KACvB;GACF;;;;;;;;EASO,0BAA0B,CAChC,aAAqB,EACrB,eAAuB;IAEvB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CACtB,CAAC,MAAM,KACL,MAAM,CAAC,MAAM,KAAK,aAAa,IAAI,MAAM,CAAC,QAAQ,KAAK,eAAe,CACzE,CAAC;GACH;;;;;;EAOM,eAAe;;IACpB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO;OACxB,MAAM,EAAE;OACR,OAAO,EAAE;OACT,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE3C,OAAO,MAAA,MAAM,CAAC,CAAC,CAAC,0CAAE,MAAM,CAAC;GAC1B;;AApGD;;;AAGuB,0BAAY,GAAG,CAAC,CAAC;AAExC;;;;AAIuB,6BAAe,GAAG,EAAE,CAAC;AAE5C;;;AAGuB,2BAAa,GAAG,EAAE,CAAC;AAyF5C;MAEa,iBAAiB,GAAG;EAC/B,GAAG,EAAE,irBAAirB;EACtrB,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;EACZ;MAEW,0BAA0B,GAAG;EACxC,GAAG,EAAE,siCAAsiC;EAC3iC,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;EACZ;MAEW,SAAS,GAAG;EACvB,GAAG,EAAE,2oCAA2oC;EAChpC,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,EAAE;EACX;MAEW,cAAc,GAAG;EAC5B,GAAG,EAAE,mvBAAmvB;EACxvB,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,EAAE;EACX;MAEW,cAAc,GAAG;EAC5B,GAAG,EAAE,+0BAA+0B;EACp1B,OAAO,EAAE,CAAC,EAAE;EACZ,OAAO,EAAE,CAAC,EAAE;;;;;","names":[],"sources":["./src/lib/cursors.ts"],"sourcesContent":["import { Disposable, EventDispatcher } from '@vertexvis/utils';\n\n/**\n * Represents a built-in [browser CSS\n * cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).\n */\nexport type CssCursor =\n | 'auto'\n | 'default'\n | 'none'\n | 'context-menu'\n | 'help'\n | 'pointer'\n | 'progress'\n | 'wait'\n | 'cell'\n | 'crosshair'\n | 'text'\n | 'vertical-text'\n | 'alias'\n | 'copy'\n | 'move'\n | 'no-drop'\n | 'not-allowed'\n | 'grab'\n | 'grabbing'\n | 'all-scroll'\n | 'col-resize'\n | 'row-resize'\n | 'n-resize'\n | 'e-resize'\n | 's-resize'\n | 'w-resize'\n | 'ne-resize'\n | 'nw-resize'\n | 'se-resize'\n | 'sw-resize'\n | 'ew-resize'\n | 'ns-resize'\n | 'nesw-resize'\n | 'nwse-resize'\n | 'zoom-in'\n | 'zoom-out'\n | string;\n\n/**\n * Represents a custom cursor that points to an image file and offset.\n */\nexport interface CustomCursor {\n url: string;\n offsetX?: number;\n offsetY?: number;\n}\n\n/**\n * Represents all possible cursor types.\n */\nexport type Cursor = CssCursor | CustomCursor;\n\ninterface CursorInstance extends Disposable {\n id: number;\n cursor: Cursor;\n priority: number;\n}\n\n/**\n * The cursor manager maintains a prioritized list of cursors for the viewer.\n *\n * Cursors with the highest priority will be considered active, where the most\n * recently added cursor will take precedence if there are multiple cursors with\n * the same priority.\n */\nexport class CursorManager {\n /**\n * A constant representing the lowest priority cursors.\n */\n public static readonly LOW_PRIORITY = 0;\n\n /**\n * A constant representing a priority between `LOW_PRIORITY` and\n * `HIGH_PRIORITY`.\n */\n public static readonly NORMAL_PRIORITY = 10;\n\n /**\n * A constant representing the high priority cursors.\n */\n public static readonly HIGH_PRIORITY = 20;\n\n /**\n * An event dispatcher that emits an event when a cursor is added or removed.\n *\n * @see {@link CursorManager.add} to add a cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public readonly onChanged = new EventDispatcher<void>();\n\n private cursors: CursorInstance[] = [];\n\n private nextId = 0;\n\n /**\n * Adds a cursor to the cursor manager, and returns an identifier that can be\n * used to remove the cursor.\n *\n * @param cursor The cursor to add.\n * @param priority The priority of the cursor. Higher values have higher\n * \tpriority over lower values.\n * @returns An identifier for the cursor.\n * @see {@link CursorManager.getActiveCursor} to query the current cursor.\n */\n public add(\n cursor: Cursor,\n priority = CursorManager.NORMAL_PRIORITY\n ): Disposable {\n // Ensure a duplicate cursor will not be added to the cursor manager.\n // If a matching cursor exists, delete it before proceeding.\n // Note that deleting the old cursor and adding the new one results in the\n // new cursor taking precedent over other existing cursors with the same priority.\n const duplicateCursor = this.getExistingDuplicateCursor(cursor, priority);\n if (duplicateCursor != null) {\n this.remove(duplicateCursor.id);\n }\n\n const id = ++this.nextId;\n const instance = { id, cursor, priority, dispose: () => this.remove(id) };\n this.cursors.push(instance);\n this.onChanged.emit();\n return instance;\n }\n\n /**\n * Removes a cursor with the given ID, if it exists.\n *\n * @param cursorId The ID of the cursor to remove.\n */\n private remove(cursorId: number): void {\n const index = this.cursors.findIndex(({ id }) => id === cursorId);\n if (index >= 0) {\n this.cursors.splice(index, 1);\n this.onChanged.emit();\n }\n }\n\n /**\n * Checks to see if an existing cursor matches the provided cursor and priority level.\n * The matching cursor is returned if found.\n *\n * @param cursorToCheck The cursor to check for duplicates against.\n * @param priorityToCheck The priority level to check for duplicates against.\n */\n private getExistingDuplicateCursor(\n cursorToCheck: Cursor,\n priorityToCheck: number\n ): CursorInstance | undefined {\n return this.cursors.find(\n (cursor) =>\n cursor.cursor === cursorToCheck && cursor.priority === priorityToCheck\n );\n }\n\n /**\n * Returns the active cursor based on priority and insertion order.\n *\n * @see {@link CursorManager.add} to add a cursor.\n */\n public getActiveCursor(): Cursor | undefined {\n const sorted = this.cursors\n .concat()\n .reverse()\n .sort((a, b) => b.priority - a.priority);\n\n return sorted[0]?.cursor;\n }\n}\n\n// CSS SVG images need to be URL encoded: https://yoksel.github.io/url-encoder/\n\nexport const measurementCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' stroke='%23fff' stroke-width='1.25' stroke-opacity='0.5' stroke-miterlimit='10' shape-rendering='crispEdges'/%3E%3Cpath d='M21.5 8h-19a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h19a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5zm-.5 6H3V9h3v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2v2.5a.5.5 0 001 0V9h2z' shape-rendering='crispEdges'/%3E%3C/svg%3E\",\n offsetX: -24,\n offsetY: -24,\n};\n\nexport const measurementWithArrowCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-1' d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath d='M27.46,21h-19a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h19a.5.5,0,0,0,.5-.5v-6A.5.5,0,0,0,27.46,21ZM27,27H9V22h3v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2v2.5a.5.5,0,0,0,1,0V22h2Z'/%3E%3Cpath class='cls-2' d='M1,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.08,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E%3Cpath class='cls-3' d='M8.75,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n\nexport const pinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath d='M12,2 C7.581722,2 4,5.581722 4,10 C4.00435812,11.7714969 4.41127263,13.5188357 5.19,15.11 C6.15517666,17.0237439 7.49502409,18.7240579 9.13,20.11 C9.86916736,20.7592093 10.6620019,21.3446357 11.5,21.86 L12,22.14 L12.5,21.86 C13.8750156,21.0120029 15.1296156,19.9827599 16.23,18.8 C17.2698142,17.7023203 18.1394508,16.4551671 18.81,15.1 C19.5872532,13.5118707 19.9941287,11.7681184 20,10 C20,5.581722 16.418278,2 12,2 Z M12,13 C10.3431458,13 9,11.6568542 9,10 C9,8.34314575 10.3431458,7 12,7 C13.6568542,7 15,8.34314575 15,10 C15,10.7956495 14.6839295,11.5587112 14.1213203,12.1213203 C13.5587112,12.6839295 12.7956495,13 12,13 Z' id='path-1'%3E%3C/path%3E%3C/defs%3E%3Cg id='icons/pin-filled' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cmask id='mask-2' fill='white'%3E%3Cuse xlink:href='%23path-1'%3E%3C/use%3E%3C/mask%3E%3Cuse id='Shape' stroke='%23FAFAFA' fill='%23BDBDBD' fill-rule='nonzero' xlink:href='%23path-1'%3E%3C/use%3E%3C/g%3E%3C/svg%3E\",\n offsetX: 17,\n offsetY: 32,\n};\n\nexport const labelPinCursor = {\n url: \"data:image/svg+xml,%3Csvg width='36px' height='36px' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 16 24' %3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D.cls-2%7Bfill:%23616161;%7D.cls-3%7Bclip-path:url(%23clip-path);%7D%3C/style%3E%3CclipPath id='clip-path'%3E%3Ccircle cx='-576.76' cy='-107.26' r='4'/%3E%3C/clipPath%3E%3C/defs%3E%3Cpath d='M8,16H8a.48.48,0,0,1-.42-.23L5.75,13H3.51A1.5,1.5,0,0,1,2,11.5v-8A1.5,1.5,0,0,1,3.51,2h9A1.51,1.51,0,0,1,14,3.5v8a1.5,1.5,0,0,1-1.5,1.5H10.22L8.39,15.81A.5.5,0,0,1,8,16ZM3.51,3a.5.5,0,0,0-.5.5v8a.5.5,0,0,0,.5.5H6a.5.5,0,0,1,.42.23L8,14.61l1.55-2.38A.5.5,0,0,1,10,12h2.56a.5.5,0,0,0,.5-.5v-8a.51.51,0,0,0-.5-.5Z'/%3E%3Ccircle cx='8.01' cy='20' r='2'/%3E%3C/svg%3E%0A\",\n offsetX: 17,\n offsetY: 29,\n};\n\nexport const boxQueryCursor = {\n url: \"data:image/svg+xml;utf8,%3Csvg id='icons' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bstroke:%23fff;stroke-miterlimit:10;stroke-width:2px;%7D.cls-2%7Bfill:%23fff;%7D.cls-2,.cls-3%7Bfill-rule:evenodd;%7D%3C/style%3E%3C/defs%3E%3Cpath class='cls-2' d='M1.25,17V1L12.59,12.62H5.81l-.41.12Z'/%3E%3Cpath class='cls-2' d='M10.33,17.69l-3.6,1.53L1.8,8.14,5.48,6.58Z'/%3E %3Cpath class='cls-3' d='M9,17l-1.84.77-3.1-7.37,1.84-.78Z'/%3E%3Cpath class='cls-3' d='M2.25,3.41V14.6l3-2.87.43-.14h4.76Z'/%3E%3Cpath class='cls-1' d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E %3Cpath d='M21.36,22.5H15.5V16.64a.5.5,0,0,0-1,0V22.5H8.64a.5.5,0,0,0,0,1H14.5v5.86a.5.5,0,0,0,1,0V23.5h5.86a.5.5,0,0,0,0-1Z' /%3E%3C/svg%3E\",\n offsetX: -30,\n offsetY: -30,\n};\n"],"version":3}
@@ -61,7 +61,7 @@ function getClosestCenterToPoint(boxPoint, pointToMeasure, dimensions) {
61
61
  return candidates[candidateIndex];
62
62
  }
63
63
 
64
- const viewerPinGroupCss = ":host{--viewer-annotations-pin-primary-color:var(--blue-700);--viewer-annotations-pin-accent-color:var(--blue-200);--viewer-annotations-pin-dot-color:var(--viewer-annotations-pin-primary-color);--viewer-annotations-pin-color:var(--viewer-annotations-pin-primary-color);--viewer-annotations-pin-font-size:0.75rem;--viewer-annotations-pin-selected-stroke:var(--white);--viewer-annotations-pin-selected-border:2px solid var(--white);--viewer-annotations-pin-label-border:2px solid var(--black);--viewer-annotations-pin-selected-stroke:var(--white);font-size:var(--viewer-annotations-pin-font-size);position:absolute;top:0;bottom:0;left:0;right:0;overflow:hidden;pointer-events:none}.pin-anchor{position:absolute;border-radius:50%;transform:translate(-50%, -50%);display:block;width:9px;height:9px;box-sizing:border-box;border:var(--viewer-annotations-pin-label-border);background:var(--viewer-annotations-pin-dot-color);pointer-events:auto;cursor:pointer}.selected{width:13px;height:13px;border:var(--viewer-annotations-pin-selected-border)}.pin{color:var(--viewer-annotations-pin-color);cursor:pointer;transition:opacity 0.3s ease-in}.pin-selected{stroke-width:1;stroke:var(--viewer-annotations-pin-selected-stroke)}.pin-occluded{opacity:.3;transition:opacity 0.3s ease-in}.pin-detached{visibility:hidden}";
64
+ const viewerPinGroupCss = ":host{--viewer-annotations-pin-primary-color:var(--blue-700);--viewer-annotations-pin-accent-color:var(--blue-200);--viewer-annotations-pin-dot-color:var(--viewer-annotations-pin-primary-color);--viewer-annotations-pin-color:var(--viewer-annotations-pin-primary-color);--viewer-annotations-pin-font-size:0.75rem;--viewer-annotations-pin-selected-stroke:var(--white);--viewer-annotations-pin-selected-border:2px solid var(--white);--viewer-annotations-pin-label-border:2px solid var(--black);--viewer-annotations-pin-selected-stroke:var(--white);font-size:var(--viewer-annotations-pin-font-size);position:absolute;top:0;bottom:0;left:0;right:0;overflow:hidden;pointer-events:none}.pin-anchor{position:absolute;border-radius:50%;transform:translate(-50%, -50%);display:block;width:9px;height:9px;box-sizing:border-box;border:var(--viewer-annotations-pin-label-border);background:var(--viewer-annotations-pin-dot-color);pointer-events:auto;cursor:pointer}.selected{width:13px;height:13px;border:var(--viewer-annotations-pin-selected-border)}.pin{color:var(--viewer-annotations-pin-color);cursor:pointer;transition:opacity 0.3s ease-in;transform:translate(0px, -12px)}.pin-selected{stroke-width:1;stroke:var(--viewer-annotations-pin-selected-stroke)}.pin-occluded{opacity:.3;transition:opacity 0.3s ease-in}.pin-detached{visibility:hidden}";
65
65
 
66
66
  const ViewerPinGroup = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
67
67
  constructor() {
@@ -1 +1 @@
1
- {"file":"viewer-pin-group.js","mappings":"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","names":["classNames","Point","Matrix4","Vector3"],"sources":["./src/components/viewer-pin-group/pin-renderer.tsx","./src/components/viewer-pin-group/utils.ts","./src/components/viewer-pin-group/viewer-pin-group.css?tag=vertex-viewer-pin-group","./src/components/viewer-pin-group/viewer-pin-group.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { Fragment, FunctionalComponent, h } from '@stencil/core';\nimport classNames from 'classnames';\n\nimport { getPinColors, isIconPin, isTextPin, Pin } from '../../lib/pins/model';\n\ninterface PinRendererProps {\n pin?: Pin;\n selected: boolean;\n occluded: boolean;\n detached: boolean;\n}\n\nexport const PinRenderer: FunctionalComponent<PinRendererProps> = ({\n pin,\n selected,\n occluded,\n detached,\n}) => {\n const { primaryColor } = getPinColors(pin);\n\n return (\n <Fragment>\n {isTextPin(pin) && (\n <div\n id=\"pin-anchor\"\n class={classNames('pin-anchor', {\n selected: selected,\n 'pin-occluded': occluded,\n 'pin-detached': detached,\n })}\n style={{\n background: primaryColor,\n }}\n ></div>\n )}\n\n {isIconPin(pin) && (\n <vertex-viewer-icon\n name=\"pin-fill\"\n size=\"lg\"\n class={classNames('pin', {\n 'pin-selected': selected,\n 'pin-occluded': occluded,\n 'pin-detached': detached,\n })}\n style={{\n color: primaryColor,\n }}\n />\n )}\n </Fragment>\n );\n};\n","import { Dimensions, Point } from '@vertexvis/geometry';\n\nexport function getClosestCenterToPoint(\n boxPoint: Point.Point,\n pointToMeasure: Point.Point,\n dimensions: Dimensions.Dimensions\n): Point.Point {\n const topPoint = {\n x: boxPoint.x + dimensions.width / 2,\n y: boxPoint.y,\n };\n\n const bottomPoint = {\n x: boxPoint.x + dimensions.width / 2,\n y: boxPoint.y + dimensions.height,\n };\n\n const rightPoint = {\n x: boxPoint.x + dimensions.width,\n y: boxPoint.y + dimensions.height / 2,\n };\n\n const leftPoint = {\n x: boxPoint.x,\n y: boxPoint.y + dimensions.height / 2,\n };\n\n const candidates = [topPoint, bottomPoint, leftPoint, rightPoint];\n\n const distances = candidates.map((candidate) =>\n Point.distance(candidate, pointToMeasure)\n );\n\n const candidateIndex = distances.indexOf(Math.min(...distances));\n return candidates[candidateIndex];\n}\n",":host {\n\n /**\n * @prop --viewer-annotations-pin-primary-color: A CSS color that\n * specifies the primary color for the pins. This value gets used for the dot color \n * and borders\n */\n --viewer-annotations-pin-primary-color: var(--blue-700);\n\n /**\n * @prop --viewer-annotations-pin-accent-color: A CSS color that\n * specifies the accent color for the pins. This value gets used for background colors\n * \n */\n\n --viewer-annotations-pin-accent-color: var(--blue-200);\n /**\n * @prop viewer-annotations-pin-dot-color: A CSS color that\n * specifies the color of the anchor dot\n */\n --viewer-annotations-pin-dot-color: var(--viewer-annotations-pin-primary-color);\n\n /**\n * @prop --viewer-annotations-pin-color: A CSS color that\n * specifies the color of the pin\n */\n --viewer-annotations-pin-color: var(--viewer-annotations-pin-primary-color);\n\n /**\n * @prop --viewer-annotations-pin-font-size: A CSS property to specify\n the font size of the pin\n */\n --viewer-annotations-pin-font-size: 0.75rem;\n\n /**\n * @prop --viewer-annotations-pin-selected-stroke: A CSS color that\n * specifies the stroke color of a selected pin\n */\n --viewer-annotations-pin-selected-stroke: var(--white);\n\n /**\n * @prop --viewer-annotations-pin-selected-border: A CSS color that\n * specifies the border of a selected pin\n */\n --viewer-annotations-pin-selected-border: 2px solid var(--white);\n\n /**\n * @prop --viewer-annotations-pin-label-border: A CSS color that\n * specifies the border of a text pin anchor\n */\n --viewer-annotations-pin-label-border: 2px solid var(--black);\n\n /**\n * @prop --viewer-annotations-pin-selected-border: A CSS color that\n * specifies the stroke of a selected default pin\n */\n --viewer-annotations-pin-selected-stroke: var(--white);\n\n font-size: var(--viewer-annotations-pin-font-size);\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n overflow: hidden;\n pointer-events: none;\n}\n\n.pin-anchor {\n position: absolute;\n border-radius: 50%;\n transform: translate(-50%, -50%);\n display: block;\n width: 9px;\n height: 9px;\n box-sizing: border-box;\n border: var(--viewer-annotations-pin-label-border);\n background: var(--viewer-annotations-pin-dot-color);\n pointer-events: auto;\n cursor: pointer;\n}\n\n.selected {\n width: 13px;\n height: 13px;\n border: var(--viewer-annotations-pin-selected-border)\n}\n\n.pin {\n color: var(--viewer-annotations-pin-color);\n cursor: pointer;\n transition: opacity 0.3s ease-in;\n}\n\n.pin-selected {\n stroke-width: 1;\n stroke: var(--viewer-annotations-pin-selected-stroke);\n}\n\n.pin-occluded {\n opacity: .3;\n transition: opacity 0.3s ease-in;\n}\n\n.pin-detached {\n visibility: hidden;\n}","import {\n Component,\n Fragment,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n h,\n Listen,\n Prop,\n State,\n} from '@stencil/core';\nimport { Dimensions, Matrix4, Point, Vector3 } from '@vertexvis/geometry';\n\nimport { Viewport } from '../..';\nimport { PinController } from '../../lib/pins/controller';\nimport { isTextPin, Pin, TextPin } from '../../lib/pins/model';\nimport { PinModel } from '../../lib/pins/model';\nimport { translatePointToScreen } from '../viewer-pin-tool/utils';\nimport { PinRenderer } from './pin-renderer';\nimport { getClosestCenterToPoint } from './utils';\n\ninterface ComputedPoints {\n pinPoint: Point.Point;\n labelPoint?: Point.Point;\n}\n\n@Component({\n tag: 'vertex-viewer-pin-group',\n styleUrl: 'viewer-pin-group.css',\n shadow: false,\n})\nexport class ViewerPinGroup {\n /**\n * The pin to draw for the group\n */\n @Prop()\n public pin?: Pin;\n\n /**\n * The local matrix of this element.\n */\n @Prop({ mutable: true, attribute: null })\n public matrix: Matrix4.Matrix4 = Matrix4.makeIdentity();\n\n /**\n * Projection view matrix used for computing the position of the pin line\n */\n @Prop()\n public projectionViewMatrix: Matrix4.Matrix4 = Matrix4.makeIdentity();\n\n /**\n * The dimensions of the canvas for the pins\n */\n @Prop({ mutable: true })\n public elementBounds?: DOMRect;\n\n /**\n * The model that contains the entities and outcomes from performing pin operations\n */\n @Prop()\n public pinModel: PinModel = new PinModel();\n\n /**\n * The controller that drives behavior for pin operations\n */\n @Prop()\n public pinController?: PinController;\n\n /**\n * Whether the pin is \"selected\"\n */\n @Prop()\n public selected = false;\n\n /**\n * @internal\n * Whether the pin is occluded\n */\n @Prop({ mutable: true, reflect: true })\n public occluded = false;\n\n /**\n * @internal\n * Whether the pin is detached\n */\n @Prop({ mutable: true, reflect: true })\n public detached = false;\n\n @State()\n private invalidateStateCounter = 0;\n\n private labelEl: HTMLVertexViewerPinLabelElement | undefined;\n\n private resizeObserver?: ResizeObserver;\n\n protected componentDidLoad(): void {\n this.setLabelObserver();\n\n if (this.pinController == null) {\n this.pinController = new PinController(this.pinModel);\n }\n\n if (this.selected) {\n this.labelEl?.setFocus();\n }\n }\n\n /**\n * @ignore\n */\n @Listen('occlusionStateChanged')\n protected async handleOcclusionStateChanged(\n event: CustomEvent<boolean>\n ): Promise<void> {\n this.occluded = event.detail;\n }\n\n /**\n * @ignore\n */\n @Listen('detachedStateChanged')\n protected async handleDetachedStateChanged(\n event: CustomEvent<boolean>\n ): Promise<void> {\n this.detached = event.detail;\n }\n\n protected disconnectedCallback(): void {\n this.labelEl?.removeEventListener('labelChanged', this.invalidateState);\n this.resizeObserver?.disconnect();\n }\n\n protected render(): JSX.Element {\n if (this.pin == null) {\n throw new Error('Unable to draw pin');\n }\n\n const { pinPoint, labelPoint } = this.computePinPoints(this.pin);\n\n return (\n <Fragment>\n <vertex-viewer-dom-element\n data-testid={`drawn-pin-${this.pin.id}`}\n position={this.pin.worldPosition}\n onPointerDown={async () => {\n await this.labelEl?.submit();\n this.selectPin();\n this.handleAnchorPointerDown();\n }}\n detachedOff={false}\n >\n <PinRenderer\n pin={this.pin}\n selected={this.selected}\n occluded={this.occluded}\n detached={this.detached}\n />\n </vertex-viewer-dom-element>\n\n {isTextPin(this.pin) && !this.occluded && !this.detached && (\n <Fragment>\n <vertex-viewer-pin-label-line\n id={`pin-label-line-${this.pin?.id}`}\n pinPoint={pinPoint}\n pin={this.pin}\n labelPoint={labelPoint}\n onPointerDown={() => this.selectPin()}\n ></vertex-viewer-pin-label-line>\n\n <vertex-viewer-pin-label\n pin={this.pin}\n ref={(el) => (this.labelEl = el)}\n elementBounds={this.elementBounds}\n pinController={this.pinController}\n onPointerDown={() => this.selectPin()}\n ></vertex-viewer-pin-label>\n </Fragment>\n )}\n </Fragment>\n );\n }\n\n private invalidateState = (): void => {\n this.invalidateStateCounter = this.invalidateStateCounter + 1;\n };\n\n private setLabelObserver(): void {\n if (this.labelEl != null) {\n this.labelEl.addEventListener('labelChanged', this.invalidateState);\n\n this.resizeObserver = new ResizeObserver(() => this.invalidateState());\n this.resizeObserver.observe(this.labelEl);\n }\n }\n\n private computePinPoints(pin: Pin): ComputedPoints {\n if (this.elementBounds != null && this.pin != null) {\n return isTextPin(this.pin) && this.pin.label.point != null\n ? this.computeTextPinPoints(this.pin, this.elementBounds)\n : this.computeDefaultPinPoints(this.pin, this.elementBounds);\n }\n\n return { pinPoint: pin.worldPosition };\n }\n\n private computeDefaultPinPoints(\n pin: Pin,\n elementBounds: DOMRect\n ): ComputedPoints {\n return {\n pinPoint: this.getFromWorldPosition(\n pin.worldPosition,\n this.projectionViewMatrix,\n elementBounds\n ),\n };\n }\n\n private computeTextPinPoints(\n pin: TextPin,\n elementBounds: DOMRect\n ): ComputedPoints {\n const { pinPoint } = this.computeDefaultPinPoints(pin, elementBounds);\n\n const screenPosition = translatePointToScreen(\n pin.label.point,\n elementBounds\n );\n\n const labelWidth = this.labelEl?.firstElementChild?.clientWidth || 0;\n const labelHeight = this.labelEl?.firstElementChild?.clientHeight || 0;\n\n return {\n pinPoint,\n labelPoint: getClosestCenterToPoint(screenPosition, pinPoint, {\n width: labelWidth,\n height: labelHeight,\n }),\n };\n }\n\n private handleAnchorPointerDown(): void {\n if (\n this.elementBounds != null &&\n this.pinController?.getToolMode() === 'edit' &&\n this.pin != null\n ) {\n this.pinController?.setDraggable({ id: this.pin.id });\n }\n }\n\n private selectPin(): void {\n this.pinController?.setSelectedPinId(this.pin?.id);\n }\n\n private getFromWorldPosition(\n pt: Vector3.Vector3,\n projectionViewMatrix: Matrix4.Matrix4,\n dimensions: Dimensions.Dimensions\n ): Point.Point {\n const ndcPt = Vector3.transformMatrix(pt, projectionViewMatrix);\n return Viewport.fromDimensions(dimensions).transformVectorToViewport(ndcPt);\n }\n}\n"],"version":3}
1
+ {"file":"viewer-pin-group.js","mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAaO,MAAM,WAAW,GAA0C,CAAC,EACjE,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,QAAQ,GACT;EACC,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;EAE3C,QACE,EAAC,QAAQ;IACN,SAAS,CAAC,GAAG,CAAC,KACb,WACE,EAAE,EAAC,YAAY,EACf,KAAK,EAAEA,UAAU,CAAC,YAAY,EAAE;QAC9B,QAAQ,EAAE,QAAQ;QAClB,cAAc,EAAE,QAAQ;QACxB,cAAc,EAAE,QAAQ;OACzB,CAAC,EACF,KAAK,EAAE;QACL,UAAU,EAAE,YAAY;OACzB,GACI,CACR;IAEA,SAAS,CAAC,GAAG,CAAC,KACb,0BACE,IAAI,EAAC,UAAU,EACf,IAAI,EAAC,IAAI,EACT,KAAK,EAAEA,UAAU,CAAC,KAAK,EAAE;QACvB,cAAc,EAAE,QAAQ;QACxB,cAAc,EAAE,QAAQ;QACxB,cAAc,EAAE,QAAQ;OACzB,CAAC,EACF,KAAK,EAAE;QACL,KAAK,EAAE,YAAY;OACpB,GACD,CACH,CACQ,EACX;AACJ,CAAC;;SCnDe,uBAAuB,CACrC,QAAqB,EACrB,cAA2B,EAC3B,UAAiC;EAEjC,MAAM,QAAQ,GAAG;IACf,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC;IACpC,CAAC,EAAE,QAAQ,CAAC,CAAC;GACd,CAAC;EAEF,MAAM,WAAW,GAAG;IAClB,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC;IACpC,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM;GAClC,CAAC;EAEF,MAAM,UAAU,GAAG;IACjB,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK;IAChC,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC;GACtC,CAAC;EAEF,MAAM,SAAS,GAAG;IAChB,CAAC,EAAE,QAAQ,CAAC,CAAC;IACb,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC;GACtC,CAAC;EAEF,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;EAElE,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,KACzCC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC,CAC1C,CAAC;EAEF,MAAM,cAAc,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;EACjE,OAAO,UAAU,CAAC,cAAc,CAAC,CAAC;AACpC;;ACnCA,MAAM,iBAAiB,GAAG,yzCAAyzC;;MC6Bt0C,cAAc;EAL3B;;;;;;IAgBS,WAAM,GAAoBC,OAAO,CAAC,YAAY,EAAE,CAAC;;;;IAMjD,yBAAoB,GAAoBA,OAAO,CAAC,YAAY,EAAE,CAAC;;;;IAY/D,aAAQ,GAAa,IAAI,QAAQ,EAAE,CAAC;;;;IAYpC,aAAQ,GAAG,KAAK,CAAC;;;;;IAOjB,aAAQ,GAAG,KAAK,CAAC;;;;;IAOjB,aAAQ,GAAG,KAAK,CAAC;IAGhB,2BAAsB,GAAG,CAAC,CAAC;IA6F3B,oBAAe,GAAG;MACxB,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,sBAAsB,GAAG,CAAC,CAAC;KAC/D,CAAC;GA+EH;EAxKW,gBAAgB;;IACxB,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAExB,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,EAAE;MAC9B,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;KACvD;IAED,IAAI,IAAI,CAAC,QAAQ,EAAE;MACjB,MAAA,IAAI,CAAC,OAAO,0CAAE,QAAQ,EAAE,CAAC;KAC1B;GACF;;;;EAMS,MAAM,2BAA2B,CACzC,KAA2B;IAE3B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;GAC9B;;;;EAMS,MAAM,0BAA0B,CACxC,KAA2B;IAE3B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;GAC9B;EAES,oBAAoB;;IAC5B,MAAA,IAAI,CAAC,OAAO,0CAAE,mBAAmB,CAAC,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IACxE,MAAA,IAAI,CAAC,cAAc,0CAAE,UAAU,EAAE,CAAC;GACnC;EAES,MAAM;;IACd,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,EAAE;MACpB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;KACvC;IAED,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEjE,QACE,EAAC,QAAQ,QACP,gDACe,aAAa,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EACvC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,EAChC,aAAa,EAAE;;QACb,OAAM,MAAA,IAAI,CAAC,OAAO,0CAAE,MAAM,EAAE,CAAA,CAAC;QAC7B,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,IAAI,CAAC,uBAAuB,EAAE,CAAC;OAChC,EACD,WAAW,EAAE,KAAK,IAElB,EAAC,WAAW,IACV,GAAG,EAAE,IAAI,CAAC,GAAG,EACb,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ,GACvB,CACwB,EAE3B,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,KACtD,EAAC,QAAQ,QACP,oCACE,EAAE,EAAE,kBAAkB,MAAA,IAAI,CAAC,GAAG,0CAAE,EAAE,EAAE,EACpC,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,IAAI,CAAC,GAAG,EACb,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,IAAI,CAAC,SAAS,EAAE,GACP,EAEhC,+BACE,GAAG,EAAE,IAAI,CAAC,GAAG,EACb,GAAG,EAAE,CAAC,EAAE,MAAM,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,EAChC,aAAa,EAAE,IAAI,CAAC,aAAa,EACjC,aAAa,EAAE,IAAI,CAAC,aAAa,EACjC,aAAa,EAAE,MAAM,IAAI,CAAC,SAAS,EAAE,GACZ,CAClB,CACZ,CACQ,EACX;GACH;EAMO,gBAAgB;IACtB,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE;MACxB,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;MAEpE,IAAI,CAAC,cAAc,GAAG,IAAI,cAAc,CAAC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;MACvE,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;KAC3C;GACF;EAEO,gBAAgB,CAAC,GAAQ;IAC/B,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,EAAE;MAClD,OAAO,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI;UACtD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,CAAC;UACvD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;KAChE;IAED,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC;GACxC;EAEO,uBAAuB,CAC7B,GAAQ,EACR,aAAsB;IAEtB,OAAO;MACL,QAAQ,EAAE,IAAI,CAAC,oBAAoB,CACjC,GAAG,CAAC,aAAa,EACjB,IAAI,CAAC,oBAAoB,EACzB,aAAa,CACd;KACF,CAAC;GACH;EAEO,oBAAoB,CAC1B,GAAY,EACZ,aAAsB;;IAEtB,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,uBAAuB,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAEtE,MAAM,cAAc,GAAG,sBAAsB,CAC3C,GAAG,CAAC,KAAK,CAAC,KAAK,EACf,aAAa,CACd,CAAC;IAEF,MAAM,UAAU,GAAG,CAAA,MAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,iBAAiB,0CAAE,WAAW,KAAI,CAAC,CAAC;IACrE,MAAM,WAAW,GAAG,CAAA,MAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,iBAAiB,0CAAE,YAAY,KAAI,CAAC,CAAC;IAEvE,OAAO;MACL,QAAQ;MACR,UAAU,EAAE,uBAAuB,CAAC,cAAc,EAAE,QAAQ,EAAE;QAC5D,KAAK,EAAE,UAAU;QACjB,MAAM,EAAE,WAAW;OACpB,CAAC;KACH,CAAC;GACH;EAEO,uBAAuB;;IAC7B,IACE,IAAI,CAAC,aAAa,IAAI,IAAI;MAC1B,CAAA,MAAA,IAAI,CAAC,aAAa,0CAAE,WAAW,EAAE,MAAK,MAAM;MAC5C,IAAI,CAAC,GAAG,IAAI,IAAI,EAChB;MACA,MAAA,IAAI,CAAC,aAAa,0CAAE,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;KACvD;GACF;EAEO,SAAS;;IACf,MAAA,IAAI,CAAC,aAAa,0CAAE,gBAAgB,CAAC,MAAA,IAAI,CAAC,GAAG,0CAAE,EAAE,CAAC,CAAC;GACpD;EAEO,oBAAoB,CAC1B,EAAmB,EACnB,oBAAqC,EACrC,UAAiC;IAEjC,MAAM,KAAK,GAAGC,OAAO,CAAC,eAAe,CAAC,EAAE,EAAE,oBAAoB,CAAC,CAAC;IAChE,OAAO,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC;GAC7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","names":["classNames","Point","Matrix4","Vector3"],"sources":["./src/components/viewer-pin-group/pin-renderer.tsx","./src/components/viewer-pin-group/utils.ts","./src/components/viewer-pin-group/viewer-pin-group.css?tag=vertex-viewer-pin-group","./src/components/viewer-pin-group/viewer-pin-group.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { Fragment, FunctionalComponent, h } from '@stencil/core';\nimport classNames from 'classnames';\n\nimport { getPinColors, isIconPin, isTextPin, Pin } from '../../lib/pins/model';\n\ninterface PinRendererProps {\n pin?: Pin;\n selected: boolean;\n occluded: boolean;\n detached: boolean;\n}\n\nexport const PinRenderer: FunctionalComponent<PinRendererProps> = ({\n pin,\n selected,\n occluded,\n detached,\n}) => {\n const { primaryColor } = getPinColors(pin);\n\n return (\n <Fragment>\n {isTextPin(pin) && (\n <div\n id=\"pin-anchor\"\n class={classNames('pin-anchor', {\n selected: selected,\n 'pin-occluded': occluded,\n 'pin-detached': detached,\n })}\n style={{\n background: primaryColor,\n }}\n ></div>\n )}\n\n {isIconPin(pin) && (\n <vertex-viewer-icon\n name=\"pin-fill\"\n size=\"lg\"\n class={classNames('pin', {\n 'pin-selected': selected,\n 'pin-occluded': occluded,\n 'pin-detached': detached,\n })}\n style={{\n color: primaryColor,\n }}\n />\n )}\n </Fragment>\n );\n};\n","import { Dimensions, Point } from '@vertexvis/geometry';\n\nexport function getClosestCenterToPoint(\n boxPoint: Point.Point,\n pointToMeasure: Point.Point,\n dimensions: Dimensions.Dimensions\n): Point.Point {\n const topPoint = {\n x: boxPoint.x + dimensions.width / 2,\n y: boxPoint.y,\n };\n\n const bottomPoint = {\n x: boxPoint.x + dimensions.width / 2,\n y: boxPoint.y + dimensions.height,\n };\n\n const rightPoint = {\n x: boxPoint.x + dimensions.width,\n y: boxPoint.y + dimensions.height / 2,\n };\n\n const leftPoint = {\n x: boxPoint.x,\n y: boxPoint.y + dimensions.height / 2,\n };\n\n const candidates = [topPoint, bottomPoint, leftPoint, rightPoint];\n\n const distances = candidates.map((candidate) =>\n Point.distance(candidate, pointToMeasure)\n );\n\n const candidateIndex = distances.indexOf(Math.min(...distances));\n return candidates[candidateIndex];\n}\n",":host {\n\n /**\n * @prop --viewer-annotations-pin-primary-color: A CSS color that\n * specifies the primary color for the pins. This value gets used for the dot color \n * and borders\n */\n --viewer-annotations-pin-primary-color: var(--blue-700);\n\n /**\n * @prop --viewer-annotations-pin-accent-color: A CSS color that\n * specifies the accent color for the pins. This value gets used for background colors\n * \n */\n\n --viewer-annotations-pin-accent-color: var(--blue-200);\n /**\n * @prop viewer-annotations-pin-dot-color: A CSS color that\n * specifies the color of the anchor dot\n */\n --viewer-annotations-pin-dot-color: var(--viewer-annotations-pin-primary-color);\n\n /**\n * @prop --viewer-annotations-pin-color: A CSS color that\n * specifies the color of the pin\n */\n --viewer-annotations-pin-color: var(--viewer-annotations-pin-primary-color);\n\n /**\n * @prop --viewer-annotations-pin-font-size: A CSS property to specify\n the font size of the pin\n */\n --viewer-annotations-pin-font-size: 0.75rem;\n\n /**\n * @prop --viewer-annotations-pin-selected-stroke: A CSS color that\n * specifies the stroke color of a selected pin\n */\n --viewer-annotations-pin-selected-stroke: var(--white);\n\n /**\n * @prop --viewer-annotations-pin-selected-border: A CSS color that\n * specifies the border of a selected pin\n */\n --viewer-annotations-pin-selected-border: 2px solid var(--white);\n\n /**\n * @prop --viewer-annotations-pin-label-border: A CSS color that\n * specifies the border of a text pin anchor\n */\n --viewer-annotations-pin-label-border: 2px solid var(--black);\n\n /**\n * @prop --viewer-annotations-pin-selected-border: A CSS color that\n * specifies the stroke of a selected default pin\n */\n --viewer-annotations-pin-selected-stroke: var(--white);\n\n font-size: var(--viewer-annotations-pin-font-size);\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n overflow: hidden;\n pointer-events: none;\n}\n\n.pin-anchor {\n position: absolute;\n border-radius: 50%;\n transform: translate(-50%, -50%);\n display: block;\n width: 9px;\n height: 9px;\n box-sizing: border-box;\n border: var(--viewer-annotations-pin-label-border);\n background: var(--viewer-annotations-pin-dot-color);\n pointer-events: auto;\n cursor: pointer;\n}\n\n.selected {\n width: 13px;\n height: 13px;\n border: var(--viewer-annotations-pin-selected-border)\n}\n\n.pin {\n color: var(--viewer-annotations-pin-color);\n cursor: pointer;\n transition: opacity 0.3s ease-in;\n\n /**\n * Place bottom point of the pin at the location instead of the middle of the pin\n */\n transform: translate(0px, -12px);\n}\n\n.pin-selected {\n stroke-width: 1;\n stroke: var(--viewer-annotations-pin-selected-stroke);\n}\n\n.pin-occluded {\n opacity: .3;\n transition: opacity 0.3s ease-in;\n}\n\n.pin-detached {\n visibility: hidden;\n}","import {\n Component,\n Fragment,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n h,\n Listen,\n Prop,\n State,\n} from '@stencil/core';\nimport { Dimensions, Matrix4, Point, Vector3 } from '@vertexvis/geometry';\n\nimport { Viewport } from '../..';\nimport { PinController } from '../../lib/pins/controller';\nimport { isTextPin, Pin, TextPin } from '../../lib/pins/model';\nimport { PinModel } from '../../lib/pins/model';\nimport { translatePointToScreen } from '../viewer-pin-tool/utils';\nimport { PinRenderer } from './pin-renderer';\nimport { getClosestCenterToPoint } from './utils';\n\ninterface ComputedPoints {\n pinPoint: Point.Point;\n labelPoint?: Point.Point;\n}\n\n@Component({\n tag: 'vertex-viewer-pin-group',\n styleUrl: 'viewer-pin-group.css',\n shadow: false,\n})\nexport class ViewerPinGroup {\n /**\n * The pin to draw for the group\n */\n @Prop()\n public pin?: Pin;\n\n /**\n * The local matrix of this element.\n */\n @Prop({ mutable: true, attribute: null })\n public matrix: Matrix4.Matrix4 = Matrix4.makeIdentity();\n\n /**\n * Projection view matrix used for computing the position of the pin line\n */\n @Prop()\n public projectionViewMatrix: Matrix4.Matrix4 = Matrix4.makeIdentity();\n\n /**\n * The dimensions of the canvas for the pins\n */\n @Prop({ mutable: true })\n public elementBounds?: DOMRect;\n\n /**\n * The model that contains the entities and outcomes from performing pin operations\n */\n @Prop()\n public pinModel: PinModel = new PinModel();\n\n /**\n * The controller that drives behavior for pin operations\n */\n @Prop()\n public pinController?: PinController;\n\n /**\n * Whether the pin is \"selected\"\n */\n @Prop()\n public selected = false;\n\n /**\n * @internal\n * Whether the pin is occluded\n */\n @Prop({ mutable: true, reflect: true })\n public occluded = false;\n\n /**\n * @internal\n * Whether the pin is detached\n */\n @Prop({ mutable: true, reflect: true })\n public detached = false;\n\n @State()\n private invalidateStateCounter = 0;\n\n private labelEl: HTMLVertexViewerPinLabelElement | undefined;\n\n private resizeObserver?: ResizeObserver;\n\n protected componentDidLoad(): void {\n this.setLabelObserver();\n\n if (this.pinController == null) {\n this.pinController = new PinController(this.pinModel);\n }\n\n if (this.selected) {\n this.labelEl?.setFocus();\n }\n }\n\n /**\n * @ignore\n */\n @Listen('occlusionStateChanged')\n protected async handleOcclusionStateChanged(\n event: CustomEvent<boolean>\n ): Promise<void> {\n this.occluded = event.detail;\n }\n\n /**\n * @ignore\n */\n @Listen('detachedStateChanged')\n protected async handleDetachedStateChanged(\n event: CustomEvent<boolean>\n ): Promise<void> {\n this.detached = event.detail;\n }\n\n protected disconnectedCallback(): void {\n this.labelEl?.removeEventListener('labelChanged', this.invalidateState);\n this.resizeObserver?.disconnect();\n }\n\n protected render(): JSX.Element {\n if (this.pin == null) {\n throw new Error('Unable to draw pin');\n }\n\n const { pinPoint, labelPoint } = this.computePinPoints(this.pin);\n\n return (\n <Fragment>\n <vertex-viewer-dom-element\n data-testid={`drawn-pin-${this.pin.id}`}\n position={this.pin.worldPosition}\n onPointerDown={async () => {\n await this.labelEl?.submit();\n this.selectPin();\n this.handleAnchorPointerDown();\n }}\n detachedOff={false}\n >\n <PinRenderer\n pin={this.pin}\n selected={this.selected}\n occluded={this.occluded}\n detached={this.detached}\n />\n </vertex-viewer-dom-element>\n\n {isTextPin(this.pin) && !this.occluded && !this.detached && (\n <Fragment>\n <vertex-viewer-pin-label-line\n id={`pin-label-line-${this.pin?.id}`}\n pinPoint={pinPoint}\n pin={this.pin}\n labelPoint={labelPoint}\n onPointerDown={() => this.selectPin()}\n ></vertex-viewer-pin-label-line>\n\n <vertex-viewer-pin-label\n pin={this.pin}\n ref={(el) => (this.labelEl = el)}\n elementBounds={this.elementBounds}\n pinController={this.pinController}\n onPointerDown={() => this.selectPin()}\n ></vertex-viewer-pin-label>\n </Fragment>\n )}\n </Fragment>\n );\n }\n\n private invalidateState = (): void => {\n this.invalidateStateCounter = this.invalidateStateCounter + 1;\n };\n\n private setLabelObserver(): void {\n if (this.labelEl != null) {\n this.labelEl.addEventListener('labelChanged', this.invalidateState);\n\n this.resizeObserver = new ResizeObserver(() => this.invalidateState());\n this.resizeObserver.observe(this.labelEl);\n }\n }\n\n private computePinPoints(pin: Pin): ComputedPoints {\n if (this.elementBounds != null && this.pin != null) {\n return isTextPin(this.pin) && this.pin.label.point != null\n ? this.computeTextPinPoints(this.pin, this.elementBounds)\n : this.computeDefaultPinPoints(this.pin, this.elementBounds);\n }\n\n return { pinPoint: pin.worldPosition };\n }\n\n private computeDefaultPinPoints(\n pin: Pin,\n elementBounds: DOMRect\n ): ComputedPoints {\n return {\n pinPoint: this.getFromWorldPosition(\n pin.worldPosition,\n this.projectionViewMatrix,\n elementBounds\n ),\n };\n }\n\n private computeTextPinPoints(\n pin: TextPin,\n elementBounds: DOMRect\n ): ComputedPoints {\n const { pinPoint } = this.computeDefaultPinPoints(pin, elementBounds);\n\n const screenPosition = translatePointToScreen(\n pin.label.point,\n elementBounds\n );\n\n const labelWidth = this.labelEl?.firstElementChild?.clientWidth || 0;\n const labelHeight = this.labelEl?.firstElementChild?.clientHeight || 0;\n\n return {\n pinPoint,\n labelPoint: getClosestCenterToPoint(screenPosition, pinPoint, {\n width: labelWidth,\n height: labelHeight,\n }),\n };\n }\n\n private handleAnchorPointerDown(): void {\n if (\n this.elementBounds != null &&\n this.pinController?.getToolMode() === 'edit' &&\n this.pin != null\n ) {\n this.pinController?.setDraggable({ id: this.pin.id });\n }\n }\n\n private selectPin(): void {\n this.pinController?.setSelectedPinId(this.pin?.id);\n }\n\n private getFromWorldPosition(\n pt: Vector3.Vector3,\n projectionViewMatrix: Matrix4.Matrix4,\n dimensions: Dimensions.Dimensions\n ): Point.Point {\n const ndcPt = Vector3.transformMatrix(pt, projectionViewMatrix);\n return Viewport.fromDimensions(dimensions).transformVectorToViewport(ndcPt);\n }\n}\n"],"version":3}
@@ -110,7 +110,7 @@ const measurementWithArrowCursor = {
110
110
  const pinCursor = {
111
111
  url: "data:image/svg+xml,%3Csvg width='36px' height='36px' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath d='M12,2 C7.581722,2 4,5.581722 4,10 C4.00435812,11.7714969 4.41127263,13.5188357 5.19,15.11 C6.15517666,17.0237439 7.49502409,18.7240579 9.13,20.11 C9.86916736,20.7592093 10.6620019,21.3446357 11.5,21.86 L12,22.14 L12.5,21.86 C13.8750156,21.0120029 15.1296156,19.9827599 16.23,18.8 C17.2698142,17.7023203 18.1394508,16.4551671 18.81,15.1 C19.5872532,13.5118707 19.9941287,11.7681184 20,10 C20,5.581722 16.418278,2 12,2 Z M12,13 C10.3431458,13 9,11.6568542 9,10 C9,8.34314575 10.3431458,7 12,7 C13.6568542,7 15,8.34314575 15,10 C15,10.7956495 14.6839295,11.5587112 14.1213203,12.1213203 C13.5587112,12.6839295 12.7956495,13 12,13 Z' id='path-1'%3E%3C/path%3E%3C/defs%3E%3Cg id='icons/pin-filled' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cmask id='mask-2' fill='white'%3E%3Cuse xlink:href='%23path-1'%3E%3C/use%3E%3C/mask%3E%3Cuse id='Shape' stroke='%23FAFAFA' fill='%23BDBDBD' fill-rule='nonzero' xlink:href='%23path-1'%3E%3C/use%3E%3C/g%3E%3C/svg%3E",
112
112
  offsetX: 17,
113
- offsetY: 22,
113
+ offsetY: 32,
114
114
  };
115
115
  const labelPinCursor = {
116
116
  url: "data:image/svg+xml,%3Csvg width='36px' height='36px' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 16 24' %3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D.cls-2%7Bfill:%23616161;%7D.cls-3%7Bclip-path:url(%23clip-path);%7D%3C/style%3E%3CclipPath id='clip-path'%3E%3Ccircle cx='-576.76' cy='-107.26' r='4'/%3E%3C/clipPath%3E%3C/defs%3E%3Cpath d='M8,16H8a.48.48,0,0,1-.42-.23L5.75,13H3.51A1.5,1.5,0,0,1,2,11.5v-8A1.5,1.5,0,0,1,3.51,2h9A1.51,1.51,0,0,1,14,3.5v8a1.5,1.5,0,0,1-1.5,1.5H10.22L8.39,15.81A.5.5,0,0,1,8,16ZM3.51,3a.5.5,0,0,0-.5.5v8a.5.5,0,0,0,.5.5H6a.5.5,0,0,1,.42.23L8,14.61l1.55-2.38A.5.5,0,0,1,10,12h2.56a.5.5,0,0,0,.5-.5v-8a.51.51,0,0,0-.5-.5Z'/%3E%3Ccircle cx='8.01' cy='20' r='2'/%3E%3C/svg%3E%0A",
@@ -125,4 +125,4 @@ const boxQueryCursor = {
125
125
 
126
126
  export { CursorManager as C, measurementWithArrowCursor as a, boxQueryCursor as b, labelPinCursor as l, measurementCursor as m, pinCursor as p };
127
127
 
128
- //# sourceMappingURL=cursors-9e349d61.js.map
128
+ //# sourceMappingURL=cursors-3806bc04.js.map