ol-contextmenu 5.0.1-alpha → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,24 +1,18 @@
1
1
  # OpenLayers Custom Context Menu
2
2
 
3
3
  <p align="center">
4
- <a href="https://travis-ci.org/jonataswalker/ol-contextmenu">
5
- <img src="https://travis-ci.org/jonataswalker/ol-contextmenu.svg?branch=master" alt="build status">
6
- </a>
7
- <a href="https://www.npmjs.com/package/ol-contextmenu">
8
- <img src="https://img.shields.io/npm/v/ol-contextmenu.svg"
9
- alt="npm version">
10
- </a>
11
- <a href="https://github.com/jonataswalker/ol-contextmenu/blob/master/LICENSE">
12
- <img src="https://img.shields.io/npm/l/ol-contextmenu.svg"
13
- alt="license">
14
- </a>
15
- <a href="https://david-dm.org/jonataswalker/ol-contextmenu">
16
- <img src="https://david-dm.org/jonataswalker/ol-contextmenu/status.svg"
17
- alt="dependency status">
18
- </a>
19
- <a href="https://david-dm.org/jonataswalker/ol-contextmenu">
20
- <img src="https://david-dm.org/jonataswalker/ol-contextmenu/dev-status.svg" alt="devDependency status">
21
- </a>
4
+ <a href="https://github.com/jonataswalker/ol-contextmenu/actions/workflows/test.yml">
5
+ <img src="https://github.com/jonataswalker/ol-contextmenu/actions/workflows/test.yml/badge.svg?branch=master" alt="Build Status">
6
+ </a>
7
+ <a href="https://www.npmjs.com/package/ol-contextmenu">
8
+ <img src="https://img.shields.io/npm/v/ol-contextmenu.svg" alt="npm version">
9
+ </a>
10
+ <a href="https://img.shields.io/npm/dm/ol-contextmenu">
11
+ <img alt="npm" src="https://img.shields.io/npm/dm/ol-contextmenu">
12
+ </a>
13
+ <a href="https://github.com/jonataswalker/ol-contextmenu/blob/master/LICENSE">
14
+ <img src="https://img.shields.io/npm/l/ol-contextmenu.svg" alt="license">
15
+ </a>
22
16
  </p>
23
17
 
24
18
  A `contextmenu` extension for [OpenLayers](http://openlayers.org/). **Requires** OpenLayers **v3.11.0** or higher.
@@ -26,48 +20,58 @@ A `contextmenu` extension for [OpenLayers](http://openlayers.org/). **Requires**
26
20
  ![contextmenu anim](https://raw.githubusercontent.com/jonataswalker/ol-contextmenu/screenshot/images/anim.gif)
27
21
 
28
22
  ## Demo
23
+
29
24
  You can see [here a demo](http://rawgit.com/jonataswalker/ol-contextmenu/master/examples/contextmenu.html) or [JSFiddle](https://jsfiddle.net/jonataswalker/ooxs1w5d/).
30
25
 
31
26
  ## How to use it?
27
+
32
28
  ##### NPM
29
+
33
30
  `npm install ol-contextmenu`
34
31
 
35
32
  ##### CDN Hosted - [jsDelivr](https://www.jsdelivr.com/package/npm/ol-contextmenu)
33
+
36
34
  Load CSS and Javascript:
35
+
37
36
  ```HTML
38
- <link href="https://cdn.jsdelivr.net/npm/ol-contextmenu@latest/dist/ol-contextmenu.min.css" rel="stylesheet">
37
+ <link href="https://cdn.jsdelivr.net/npm/ol-contextmenu@latest/dist/ol-contextmenu.css" rel="stylesheet">
39
38
  <script src="https://cdn.jsdelivr.net/npm/ol-contextmenu"></script>
40
39
  ```
41
40
 
42
41
  ##### CDN Hosted - UNPKG
42
+
43
43
  Load CSS and Javascript:
44
+
44
45
  ```HTML
45
- <link href="https://unpkg.com/ol-contextmenu/dist/ol-contextmenu.min.css" rel="stylesheet">
46
+ <link href="https://unpkg.com/ol-contextmenu/dist/ol-contextmenu.css" rel="stylesheet">
46
47
  <script src="https://unpkg.com/ol-contextmenu"></script>
47
48
  ```
49
+
48
50
  ##### Self hosted
51
+
49
52
  Download [latest release](https://github.com/jonataswalker/ol-contextmenu/releases/latest) and (obviously) load CSS and Javascript.
50
53
 
51
54
  ##### Instantiate with some options and add the Control
55
+
52
56
  ```javascript
53
57
  var contextmenu = new ContextMenu({
54
- width: 170,
55
- defaultItems: true, // defaultItems are (for now) Zoom In/Zoom Out
56
- items: [
57
- {
58
- text: 'Center map here',
59
- classname: 'some-style-class', // add some CSS rules
60
- callback: center // `center` is your callback function
61
- },
62
- {
63
- text: 'Add a Marker',
64
- classname: 'some-style-class', // you can add this icon with a CSS class
65
- // instead of `icon` property (see next line)
66
- icon: 'img/marker.png', // this can be relative or absolute
67
- callback: marker
68
- },
69
- '-' // this is a separator
70
- ]
58
+ width: 170,
59
+ defaultItems: true, // defaultItems are (for now) Zoom In/Zoom Out
60
+ items: [
61
+ {
62
+ text: 'Center map here',
63
+ classname: 'some-style-class', // add some CSS rules
64
+ callback: center, // `center` is your callback function
65
+ },
66
+ {
67
+ text: 'Add a Marker',
68
+ classname: 'some-style-class', // you can add this icon with a CSS class
69
+ // instead of `icon` property (see next line)
70
+ icon: 'img/marker.png', // this can be relative or absolute
71
+ callback: marker,
72
+ },
73
+ '-', // this is a separator
74
+ ],
71
75
  });
72
76
  map.addControl(contextmenu);
73
77
  ```
@@ -78,55 +82,57 @@ If you provide `items {Array}` a submenu will be created as a child of the curre
78
82
 
79
83
  ```javascript
80
84
  var all_items = [
81
- {
82
- text: 'Some Actions',
83
- items: [ // <== this is a submenu
84
- {
85
- text: 'Action 1',
86
- callback: action
87
- },
88
- {
89
- text: 'Other action',
90
- callback: action2
91
- }
92
- ]
93
- },
94
- {
95
- text: 'Add a Marker',
96
- icon: 'img/marker.png',
97
- callback: marker
98
- },
99
- '-' // this is a separator
85
+ {
86
+ text: 'Some Actions',
87
+ items: [
88
+ // <== this is a submenu
89
+ {
90
+ text: 'Action 1',
91
+ callback: action,
92
+ },
93
+ {
94
+ text: 'Other action',
95
+ callback: action2,
96
+ },
97
+ ],
98
+ },
99
+ {
100
+ text: 'Add a Marker',
101
+ icon: 'img/marker.png',
102
+ callback: marker,
103
+ },
104
+ '-', // this is a separator
100
105
  ];
101
106
  ```
102
107
 
103
108
  ##### Would you like to propagate custom data to the callback handler?
109
+
104
110
  ```javascript
105
111
  var removeMarker = function (obj) {
106
- vectorLayer.getSource().removeFeature(obj.data.marker);
112
+ vectorLayer.getSource().removeFeature(obj.data.marker);
107
113
  };
108
114
  var removeMarkerItem = {
109
- text: 'Remove this Marker',
110
- icon: 'img/marker.png',
111
- callback: removeMarker
115
+ text: 'Remove this Marker',
116
+ icon: 'img/marker.png',
117
+ callback: removeMarker,
112
118
  };
113
119
 
114
120
  var restore = false;
115
121
  contextmenu.on('open', function (evt) {
116
- var feature = map.forEachFeatureAtPixel(evt.pixel, function (ft, l) {
117
- return ft;
118
- });
119
- if (feature) {
120
- contextmenu.clear();
121
- removeMarkerItem.data = { marker: feature };
122
- contextmenu.push(removeMarkerItem);
123
- restore = true;
124
- } else if (restore) {
125
- contextmenu.clear();
126
- contextmenu.extend(contextmenu_items);
127
- contextmenu.extend(contextmenu.getDefaultItems());
128
- restore = false;
129
- }
122
+ var feature = map.forEachFeatureAtPixel(evt.pixel, function (ft, l) {
123
+ return ft;
124
+ });
125
+ if (feature) {
126
+ contextmenu.clear();
127
+ removeMarkerItem.data = { marker: feature };
128
+ contextmenu.push(removeMarkerItem);
129
+ restore = true;
130
+ } else if (restore) {
131
+ contextmenu.clear();
132
+ contextmenu.extend(contextmenu_items);
133
+ contextmenu.extend(contextmenu.getDefaultItems());
134
+ restore = false;
135
+ }
130
136
  });
131
137
  ```
132
138
 
@@ -137,10 +143,11 @@ contextmenu.on('open', function (evt) {
137
143
  #### `new ContextMenu(options)`
138
144
 
139
145
  ###### `options` is an object with the following possible properties:
140
- * `eventType`: `contextmenu`; The listening event type (You could use `'click'`, `'dblclick'`)
141
- * `defaultItems`: `true`; Whether the default items (which are: Zoom In/Out) are enabled
142
- * `width`: `150`; The menu's width
143
- * `items`: `[]`; An array of object|string
146
+
147
+ - `eventType`: `contextmenu`; The listening event type (You could use `'click'`, `'dblclick'`)
148
+ - `defaultItems`: `true`; Whether the default items (which are: Zoom In/Out) are enabled
149
+ - `width`: `150`; The menu's width
150
+ - `items`: `[]`; An array of object|string
144
151
 
145
152
  ## Methods
146
153
 
@@ -159,17 +166,18 @@ Close the menu programmatically.
159
166
  Add items to the menu. This pushes each item in the provided array to the end of the menu.
160
167
 
161
168
  Example:
169
+
162
170
  ```js
163
171
  var contextmenu = new ContextMenu();
164
172
  map.addControl(contextmenu);
165
173
 
166
174
  var add_later = [
167
- '-', // this is a separator
168
- {
169
- text: 'Add a Marker',
170
- icon: 'img/marker.png',
171
- callback: marker
172
- }
175
+ '-', // this is a separator
176
+ {
177
+ text: 'Add a Marker',
178
+ icon: 'img/marker.png',
179
+ callback: marker,
180
+ },
173
181
  ];
174
182
  contextmenu.extend(add_later);
175
183
  ```
@@ -202,36 +210,36 @@ Whether the menu is open.
202
210
 
203
211
  Update menu's position.
204
212
 
205
-
206
213
  ## Events
207
214
 
208
215
  #### If you want to disable this plugin under certain circumstances, listen to `beforeopen`
209
216
 
210
217
  ```javascript
211
218
  contextmenu.on('beforeopen', function (evt) {
212
- var feature = map.forEachFeatureAtPixel(evt.pixel, function (ft, l) {
213
- return ft;
214
- });
215
-
216
- if (feature) { // open only on features
217
- contextmenu.enable();
218
- } else {
219
- contextmenu.disable();
220
- }
219
+ var feature = map.forEachFeatureAtPixel(evt.pixel, function (ft, l) {
220
+ return ft;
221
+ });
222
+
223
+ if (feature) {
224
+ // open only on features
225
+ contextmenu.enable();
226
+ } else {
227
+ contextmenu.disable();
228
+ }
221
229
  });
222
230
  ```
223
231
 
224
232
  #### Listen and make some changes when context menu opens
225
233
 
226
234
  ```javascript
227
- contextmenu.on('open', function(evt){
228
- var feature = map.forEachFeatureAtPixel(evt.pixel, function (ft, l) {
229
- return ft;
230
- });
231
-
232
- if (feature) {
233
- // add some other items to the menu
234
- }
235
+ contextmenu.on('open', function (evt) {
236
+ var feature = map.forEachFeatureAtPixel(evt.pixel, function (ft, l) {
237
+ return ft;
238
+ });
239
+
240
+ if (feature) {
241
+ // add some other items to the menu
242
+ }
235
243
  });
236
244
  ```
237
245
 
@@ -239,6 +247,6 @@ contextmenu.on('open', function(evt){
239
247
 
240
248
  ```javascript
241
249
  contextmenu.on('close', function (evt) {
242
- // it's upon you
250
+ // it's upon you
243
251
  });
244
252
  ```
@@ -0,0 +1,14 @@
1
+ import { SingleItem, Options } from './types';
2
+ export declare const DEFAULT_OPTIONS: Options;
3
+ export declare const CSS_CLASSES: {
4
+ namespace: string;
5
+ container: string;
6
+ separator: string;
7
+ submenu: string;
8
+ hidden: string;
9
+ icon: string;
10
+ zoomIn: string;
11
+ zoomOut: string;
12
+ unselectable: string;
13
+ };
14
+ export declare const DEFAULT_ITEMS: SingleItem[];
@@ -0,0 +1,3 @@
1
+ import { TinyEmitter } from 'tiny-emitter';
2
+ declare const emitter: TinyEmitter;
3
+ export default emitter;
@@ -0,0 +1,5 @@
1
+ import { Item } from '../types';
2
+ export declare function createFragment(html: string): DocumentFragment;
3
+ export declare function getLineHeight(container: HTMLDivElement): number;
4
+ export declare function addMenuEntry(parentNode: HTMLUListElement, item: Item, isSubmenu?: boolean): HTMLLIElement;
5
+ export declare function addMenuEntries(container: HTMLUListElement, items: Item[], menuWidth: number): void;
package/dist/main.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ import type { Pixel } from 'ol/pixel';
2
+ import type { Coordinate } from 'ol/coordinate';
3
+ import OlMap from 'ol/Map';
4
+ import Control from 'ol/control/Control';
5
+ import { Item, MenuEntry, Options } from './types';
6
+ export default class ContextMenu extends Control {
7
+ protected map: OlMap;
8
+ protected container: HTMLDivElement;
9
+ protected coordinate: Coordinate;
10
+ protected pixel: Pixel;
11
+ protected contextMenuEventListener: (evt: MouseEvent) => void;
12
+ protected entryCallbackEventListener: (evt: MouseEvent) => void;
13
+ protected mapMoveListener: () => void;
14
+ protected lineHeight: number;
15
+ protected disabled: boolean;
16
+ protected opened: boolean;
17
+ protected items: Item[];
18
+ protected menuEntries: Map<string, MenuEntry>;
19
+ options: Options;
20
+ constructor(opts?: Partial<Options>);
21
+ clear(): void;
22
+ enable(): void;
23
+ disable(): void;
24
+ getDefaultItems(): import("./types").SingleItem[];
25
+ countItems(): number;
26
+ extend(items: Item[]): void;
27
+ closeMenu(): void;
28
+ isOpen(): boolean;
29
+ updatePosition(pixel: Pixel): void;
30
+ pop(): void;
31
+ shift(): void;
32
+ push(item: Item): void;
33
+ setMap(map: OlMap): void;
34
+ protected removeListeners(): void;
35
+ protected removeMenuEntry(id: string): void;
36
+ protected handleContextMenu(evt: MouseEvent): void;
37
+ protected openMenu(): void;
38
+ protected getMenuEntriesLength(): number;
39
+ protected positionContainer(): void;
40
+ protected handleMapMove(): void;
41
+ protected handleEntryCallback(evt: MouseEvent): void;
42
+ protected handleAddMenuEntry(item: MenuEntry, element: HTMLLIElement): void;
43
+ }
@@ -0,0 +1,3 @@
1
+ export * from './main'
2
+ import ContextMenu from './main'
3
+ export default ContextMenu
@@ -1,6 +1,6 @@
1
1
  var S = Object.defineProperty;
2
2
  var k = (s, t, e) => t in s ? S(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
3
- var a = (s, t, e) => (k(s, typeof t != "symbol" ? t + "" : t, e), e);
3
+ var r = (s, t, e) => (k(s, typeof t != "symbol" ? t + "" : t, e), e);
4
4
  import T from "ol/control/Control";
5
5
  var M = /* @__PURE__ */ ((s) => (s.CONTEXTMENU = "contextmenu", s.CLICK = "click", s.DBLCLICK = "dblclick", s))(M || {}), p = /* @__PURE__ */ ((s) => (s.BEFOREOPEN = "beforeopen", s.OPEN = "open", s.CLOSE = "close", s.ADD_MENU_ENTRY = "add-menu-entry", s))(p || {});
6
6
  const O = {
@@ -9,7 +9,7 @@ const O = {
9
9
  eventType: M.CONTEXTMENU,
10
10
  defaultItems: !0,
11
11
  items: []
12
- }, d = "ol-ctx-menu", r = {
12
+ }, d = "ol-ctx-menu", a = {
13
13
  namespace: d,
14
14
  container: `${d}-container`,
15
15
  separator: `${d}-separator`,
@@ -22,7 +22,7 @@ const O = {
22
22
  }, x = [
23
23
  {
24
24
  text: "Zoom In",
25
- classname: `${r.zoomIn} ${r.icon}`,
25
+ classname: `${a.zoomIn} ${a.icon}`,
26
26
  callback: (s, t) => {
27
27
  const e = t.getView();
28
28
  e.animate({
@@ -34,7 +34,7 @@ const O = {
34
34
  },
35
35
  {
36
36
  text: "Zoom Out",
37
- classname: `${r.zoomOut} ${r.icon}`,
37
+ classname: `${a.zoomOut} ${a.icon}`,
38
38
  callback: (s, t) => {
39
39
  const e = t.getView();
40
40
  e.animate({
@@ -98,7 +98,7 @@ function L(s, t, e = !1) {
98
98
  const n = `_${Math.random().toString(36).slice(2, 11)}`;
99
99
  if (typeof t != "string" && "text" in t) {
100
100
  const u = `<span>${t.text}</span>`, f = E(u), c = document.createElement("li");
101
- return t.classname = t.classname || "", t.icon && (t.classname === "" ? t.classname = r.icon : t.classname.includes(r.icon) === !1 && (t.classname += ` ${r.icon}`), c.setAttribute("style", `background-image:url(${t.icon})`)), c.id = n, c.className = t.classname, c.append(f), s.append(c), y.emit(
101
+ return t.classname = t.classname || "", t.icon && (t.classname === "" ? t.classname = a.icon : t.classname.includes(a.icon) === !1 && (t.classname += ` ${a.icon}`), c.setAttribute("style", `background-image:url(${t.icon})`)), c.id = n, c.className = t.classname, c.append(f), s.append(c), y.emit(
102
102
  p.ADD_MENU_ENTRY,
103
103
  {
104
104
  id: n,
@@ -110,7 +110,7 @@ function L(s, t, e = !1) {
110
110
  c
111
111
  ), c;
112
112
  }
113
- const i = `<li id="${n}" class="${r.separator}"><hr></li>`, o = E(i);
113
+ const i = `<li id="${n}" class="${a.separator}"><hr></li>`, o = E(i);
114
114
  s.append(o);
115
115
  const l = s.lastChild;
116
116
  return y.emit(
@@ -129,9 +129,9 @@ function v(s, t, e) {
129
129
  t.forEach((n) => {
130
130
  if (typeof n != "string" && "items" in n && Array.isArray(n.items)) {
131
131
  const i = L(s, n, !0);
132
- i.classList.add(r.submenu);
132
+ i.classList.add(a.submenu);
133
133
  const o = document.createElement("ul");
134
- o.classList.add(r.container), o.style.width = `${e}px`, i.append(o), v(o, n.items, e);
134
+ o.classList.add(a.container), o.style.width = `${e}px`, i.append(o), v(o, n.items, e);
135
135
  } else
136
136
  L(s, n);
137
137
  });
@@ -140,30 +140,30 @@ function g(s, t) {
140
140
  if (!s)
141
141
  throw new Error(t);
142
142
  }
143
- class z extends T {
143
+ class P extends T {
144
144
  constructor(e = {}) {
145
145
  g(typeof e == "object", "@param `opts` should be object type!");
146
146
  const n = document.createElement("div");
147
147
  super({ element: n });
148
- a(this, "map");
149
- a(this, "container");
150
- a(this, "coordinate", []);
151
- a(this, "pixel", []);
152
- a(this, "contextMenuEventListener");
153
- a(this, "entryCallbackEventListener");
154
- a(this, "mapMoveListener");
155
- a(this, "lineHeight", 0);
156
- a(this, "disabled");
157
- a(this, "opened");
158
- a(this, "items", []);
159
- a(this, "menuEntries", /* @__PURE__ */ new Map());
160
- a(this, "options");
148
+ r(this, "map");
149
+ r(this, "container");
150
+ r(this, "coordinate", []);
151
+ r(this, "pixel", []);
152
+ r(this, "contextMenuEventListener");
153
+ r(this, "entryCallbackEventListener");
154
+ r(this, "mapMoveListener");
155
+ r(this, "lineHeight", 0);
156
+ r(this, "disabled");
157
+ r(this, "opened");
158
+ r(this, "items", []);
159
+ r(this, "menuEntries", /* @__PURE__ */ new Map());
160
+ r(this, "options");
161
161
  this.options = { ...O, ...e };
162
162
  const i = document.createElement("ul");
163
163
  n.append(i), n.style.width = `${this.options.width}px`, n.classList.add(
164
- r.container,
165
- r.unselectable,
166
- r.hidden
164
+ a.container,
165
+ a.unselectable,
166
+ a.hidden
167
167
  ), this.container = n, this.contextMenuEventListener = (o) => {
168
168
  this.handleContextMenu(o);
169
169
  }, this.entryCallbackEventListener = (o) => {
@@ -181,7 +181,7 @@ class z extends T {
181
181
  clear() {
182
182
  for (const e of this.menuEntries.keys())
183
183
  this.removeMenuEntry(e);
184
- this.container.replaceChildren();
184
+ this.container.replaceChildren(), this.container.append(document.createElement("ul"));
185
185
  }
186
186
  enable() {
187
187
  this.disabled = !1;
@@ -203,7 +203,7 @@ class z extends T {
203
203
  );
204
204
  }
205
205
  closeMenu() {
206
- this.opened = !1, this.container.classList.add(r.hidden), this.dispatchEvent(p.CLOSE);
206
+ this.opened = !1, this.container.classList.add(a.hidden), this.dispatchEvent(p.CLOSE);
207
207
  }
208
208
  isOpen() {
209
209
  return this.opened;
@@ -257,7 +257,7 @@ class z extends T {
257
257
  ));
258
258
  }
259
259
  openMenu() {
260
- this.menuEntries.size !== 0 && (this.opened = !0, this.positionContainer(), this.container.classList.remove(r.hidden));
260
+ this.menuEntries.size !== 0 && (this.opened = !0, this.positionContainer(), this.container.classList.remove(a.hidden));
261
261
  }
262
262
  getMenuEntriesLength() {
263
263
  return Array.from(this.menuEntries).filter(
@@ -274,13 +274,13 @@ class z extends T {
274
274
  }, o = n.w >= i.w ? this.pixel[0] + 5 : this.pixel[0] - i.w;
275
275
  this.container.style.left = `${o}px`, this.container.style.top = n.h >= i.h ? `${this.pixel[1] - 10}px` : `${this.pixel[1] - i.h}px`, this.container.style.right = "auto", this.container.style.bottom = "auto", n.w -= i.w;
276
276
  const l = (c) => Array.from(c.children).filter(
277
- (m) => m.tagName === "LI" && m.classList.contains(r.submenu)
277
+ (m) => m.tagName === "LI" && m.classList.contains(a.submenu)
278
278
  );
279
279
  let u = 0;
280
280
  const f = (c, m) => {
281
281
  u += 1, l(c).forEach((C) => {
282
282
  const A = m >= i.w ? i.w - 8 : (i.w + 8) * -1, h = C.querySelector(
283
- `ul.${r.container}`
283
+ `ul.${a.container}`
284
284
  ), $ = Math.round(
285
285
  this.lineHeight * Array.from(h.children).filter((N) => N.tagName === "LI").length
286
286
  );
@@ -307,7 +307,6 @@ class z extends T {
307
307
  this.menuEntries.set(e.id, e), "callback" in e && typeof e.callback == "function" && n.addEventListener("click", this.entryCallbackEventListener, !1);
308
308
  }
309
309
  }
310
- window.ol?.control && (window.ol.control.ContextMenu = z);
311
310
  export {
312
- z as default
311
+ P as default
313
312
  };
@@ -1 +1 @@
1
- (function(l,c){typeof exports=="object"&&typeof module<"u"?module.exports=c(require("ol/control/Control")):typeof define=="function"&&define.amd?define(["ol/control/Control"],c):(l=typeof globalThis<"u"?globalThis:l||self,l.ContextMenu=c(l.ol.control.Control))})(this,function(l){"use strict";var z=Object.defineProperty;var H=(l,c,f)=>c in l?z(l,c,{enumerable:!0,configurable:!0,writable:!0,value:f}):l[c]=f;var a=(l,c,f)=>(H(l,typeof c!="symbol"?c+"":c,f),f);const f=(n=>n&&typeof n=="object"&&"default"in n?n:{default:n})(l);var M=(n=>(n.CONTEXTMENU="contextmenu",n.CLICK="click",n.DBLCLICK="dblclick",n))(M||{}),m=(n=>(n.BEFOREOPEN="beforeopen",n.OPEN="open",n.CLOSE="close",n.ADD_MENU_ENTRY="add-menu-entry",n))(m||{});const S={width:150,scrollAt:4,eventType:M.CONTEXTMENU,defaultItems:!0,items:[]},p="ol-ctx-menu",r={namespace:p,container:`${p}-container`,separator:`${p}-separator`,submenu:`${p}-submenu`,hidden:`${p}-hidden`,icon:`${p}-icon`,zoomIn:`${p}-zoom-in`,zoomOut:`${p}-zoom-out`,unselectable:"ol-unselectable"},C=[{text:"Zoom In",classname:`${r.zoomIn} ${r.icon}`,callback:(n,i)=>{const e=i.getView();e.animate({zoom:Number(e.getZoom())+1,duration:700,center:n.coordinate})}},{text:"Zoom Out",classname:`${r.zoomOut} ${r.icon}`,callback:(n,i)=>{const e=i.getView();e.animate({zoom:Number(e.getZoom())-1,duration:700,center:n.coordinate})}}];var A={exports:{}};function x(){}x.prototype={on:function(n,i,e){var t=this.e||(this.e={});return(t[n]||(t[n]=[])).push({fn:i,ctx:e}),this},once:function(n,i,e){var t=this;function s(){t.off(n,s),i.apply(e,arguments)}return s._=i,this.on(n,s,e)},emit:function(n){var i=[].slice.call(arguments,1),e=((this.e||(this.e={}))[n]||[]).slice(),t=0,s=e.length;for(t;t<s;t++)e[t].fn.apply(e[t].ctx,i);return this},off:function(n,i){var e=this.e||(this.e={}),t=e[n],s=[];if(t&&i)for(var o=0,h=t.length;o<h;o++)t[o].fn!==i&&t[o].fn._!==i&&s.push(t[o]);return s.length?e[n]=s:delete e[n],this}},A.exports=x;var k=A.exports.TinyEmitter=x;const b=new k;function y(n){const i=document.createDocumentFragment(),e=document.createElement("div");for(e.innerHTML=n;e.firstChild;)i.append(e.firstChild);return i}function T(n){const i=document.importNode(n),e=n.offsetWidth;i.style.cssText=`position: fixed; top: 0; left: 0; overflow: auto; visibility: hidden; pointer-events: none; height: unset; max-height: unset; width: ${e}px`;const t=y("<span>Foo</span>"),s=y("<span>Foo</span>"),o=document.createElement("li"),h=document.createElement("li");o.append(t),h.append(s),i.append(o),i.append(h),n.parentNode?.append(i);const E=i.offsetHeight/2;return n.parentNode?.removeChild(i),E}function $(n,i,e=!1){const t=`_${Math.random().toString(36).slice(2,11)}`;if(typeof i!="string"&&"text"in i){const E=`<span>${i.text}</span>`,v=y(E),u=document.createElement("li");return i.classname=i.classname||"",i.icon&&(i.classname===""?i.classname=r.icon:i.classname.includes(r.icon)===!1&&(i.classname+=` ${r.icon}`),u.setAttribute("style",`background-image:url(${i.icon})`)),u.id=t,u.className=i.classname,u.append(v),n.append(u),b.emit(m.ADD_MENU_ENTRY,{id:t,isSubmenu:e,isSeparator:!1,callback:"callback"in i?i.callback:null,data:"data"in i?i.data:null},u),u}const s=`<li id="${t}" class="${r.separator}"><hr></li>`,o=y(s);n.append(o);const h=n.lastChild;return b.emit(m.ADD_MENU_ENTRY,{id:t,isSubmenu:e,isSeparator:!0,callback:null,data:null},h),h}function L(n,i,e){i.forEach(t=>{if(typeof t!="string"&&"items"in t&&Array.isArray(t.items)){const s=$(n,t,!0);s.classList.add(r.submenu);const o=document.createElement("ul");o.classList.add(r.container),o.style.width=`${e}px`,s.append(o),L(o,t.items,e)}else $(n,t)})}const P="";function w(n,i){if(!n)throw new Error(i)}class N extends f.default{constructor(e={}){w(typeof e=="object","@param `opts` should be object type!");const t=document.createElement("div");super({element:t});a(this,"map");a(this,"container");a(this,"coordinate",[]);a(this,"pixel",[]);a(this,"contextMenuEventListener");a(this,"entryCallbackEventListener");a(this,"mapMoveListener");a(this,"lineHeight",0);a(this,"disabled");a(this,"opened");a(this,"items",[]);a(this,"menuEntries",new Map);a(this,"options");this.options={...S,...e};const s=document.createElement("ul");t.append(s),t.style.width=`${this.options.width}px`,t.classList.add(r.container,r.unselectable,r.hidden),this.container=t,this.contextMenuEventListener=o=>{this.handleContextMenu(o)},this.entryCallbackEventListener=o=>{this.handleEntryCallback(o)},this.mapMoveListener=()=>{this.handleMapMove()},this.disabled=!1,this.opened=!1,b.on(m.ADD_MENU_ENTRY,(o,h)=>{this.handleAddMenuEntry(o,h)},this)}clear(){for(const e of this.menuEntries.keys())this.removeMenuEntry(e);this.container.replaceChildren()}enable(){this.disabled=!1}disable(){this.disabled=!0}getDefaultItems(){return C}countItems(){return this.menuEntries.size}extend(e){w(Array.isArray(e),"@param `items` should be an Array."),L(this.container.firstElementChild,e,this.options.width)}closeMenu(){this.opened=!1,this.container.classList.add(r.hidden),this.dispatchEvent(m.CLOSE)}isOpen(){return this.opened}updatePosition(e){w(Array.isArray(e),"@param `pixel` should be an Array."),this.isOpen()&&(this.pixel=e,this.positionContainer())}pop(){const e=Array.from(this.menuEntries.keys()).pop();e&&this.removeMenuEntry(e)}shift(){const e=Array.from(this.menuEntries.keys()).shift();e&&this.removeMenuEntry(e)}push(e){e&&this.extend([e])}setMap(e){if(super.setMap(e),e){this.map=e,this.map.getViewport().addEventListener(this.options.eventType,this.contextMenuEventListener,!1),this.map.on("movestart",()=>{this.handleMapMove()}),this.items=this.options.defaultItems?this.options.items.concat(C):this.options.items,L(this.container.firstElementChild,this.items,this.options.width);const t=this.getMenuEntriesLength();this.lineHeight=t>0?this.container.offsetHeight/t:T(this.container)}else this.removeListeners(),this.clear()}removeListeners(){this.map.getViewport().removeEventListener(this.options.eventType,this.contextMenuEventListener,!1)}removeMenuEntry(e){const t=document.getElementById(e);t?.remove(),t?.removeEventListener("click",this.entryCallbackEventListener),this.menuEntries.delete(e)}handleContextMenu(e){this.coordinate=this.map.getEventCoordinate(e),this.pixel=this.map.getEventPixel(e),this.dispatchEvent({type:m.BEFOREOPEN,pixel:this.pixel,coordinate:this.coordinate}),!this.disabled&&(this.options.eventType===M.CONTEXTMENU&&(e.stopPropagation(),e.preventDefault()),this.openMenu(),e.target?.addEventListener("pointerdown",t=>{this.opened&&(t.stopPropagation(),this.closeMenu())},{once:!0}))}openMenu(){this.menuEntries.size!==0&&(this.opened=!0,this.positionContainer(),this.container.classList.remove(r.hidden))}getMenuEntriesLength(){return Array.from(this.menuEntries).filter(([,e])=>e.isSeparator===!1||e.isSubmenu===!1).length}positionContainer(){const e=this.map.getSize()||[0,0],t={w:e[0]-this.pixel[0],h:e[1]-this.pixel[1]},s={w:this.container.offsetWidth,h:Math.round(this.lineHeight*this.getMenuEntriesLength())},o=t.w>=s.w?this.pixel[0]+5:this.pixel[0]-s.w;this.container.style.left=`${o}px`,this.container.style.top=t.h>=s.h?`${this.pixel[1]-10}px`:`${this.pixel[1]-s.h}px`,this.container.style.right="auto",this.container.style.bottom="auto",t.w-=s.w;const h=u=>Array.from(u.children).filter(g=>g.tagName==="LI"&&g.classList.contains(r.submenu));let E=0;const v=(u,g)=>{E+=1,h(u).forEach(_=>{const D=g>=s.w?s.w-8:(s.w+8)*-1,d=_.querySelector(`ul.${r.container}`),O=Math.round(this.lineHeight*Array.from(d.children).filter(I=>I.tagName==="LI").length);d.style.left=`${D}px`,d.style.right="auto",d.style.top=t.h>=O+s.h?"0":`-${d.offsetHeight-25}px`,d.style.bottom="auto",d.style.zIndex=String(E),h(d).length>0&&v(d,g-s.w)})};v(this.container.firstElementChild,t.w)}handleMapMove(){this.closeMenu()}handleEntryCallback(e){e.preventDefault(),e.stopPropagation();const t=e.currentTarget,s=this.menuEntries.get(t.id);if(!s)return;const o={coordinate:this.coordinate,data:s.data};this.closeMenu(),s.callback?.(o,this.map)}handleAddMenuEntry(e,t){this.menuEntries.set(e.id,e),"callback"in e&&typeof e.callback=="function"&&t.addEventListener("click",this.entryCallbackEventListener,!1)}}return window.ol?.control&&(window.ol.control.ContextMenu=N),N});
1
+ (function(l,c){typeof exports=="object"&&typeof module<"u"?module.exports=c(require("ol/control/Control")):typeof define=="function"&&define.amd?define(["ol/control/Control"],c):(l=typeof globalThis<"u"?globalThis:l||self,l.ContextMenu=c(l.ol.control.Control))})(this,function(l){"use strict";var z=Object.defineProperty;var H=(l,c,f)=>c in l?z(l,c,{enumerable:!0,configurable:!0,writable:!0,value:f}):l[c]=f;var a=(l,c,f)=>(H(l,typeof c!="symbol"?c+"":c,f),f);const f=(n=>n&&typeof n=="object"&&"default"in n?n:{default:n})(l);var M=(n=>(n.CONTEXTMENU="contextmenu",n.CLICK="click",n.DBLCLICK="dblclick",n))(M||{}),m=(n=>(n.BEFOREOPEN="beforeopen",n.OPEN="open",n.CLOSE="close",n.ADD_MENU_ENTRY="add-menu-entry",n))(m||{});const N={width:150,scrollAt:4,eventType:M.CONTEXTMENU,defaultItems:!0,items:[]},p="ol-ctx-menu",r={namespace:p,container:`${p}-container`,separator:`${p}-separator`,submenu:`${p}-submenu`,hidden:`${p}-hidden`,icon:`${p}-icon`,zoomIn:`${p}-zoom-in`,zoomOut:`${p}-zoom-out`,unselectable:"ol-unselectable"},w=[{text:"Zoom In",classname:`${r.zoomIn} ${r.icon}`,callback:(n,i)=>{const e=i.getView();e.animate({zoom:Number(e.getZoom())+1,duration:700,center:n.coordinate})}},{text:"Zoom Out",classname:`${r.zoomOut} ${r.icon}`,callback:(n,i)=>{const e=i.getView();e.animate({zoom:Number(e.getZoom())-1,duration:700,center:n.coordinate})}}];var A={exports:{}};function b(){}b.prototype={on:function(n,i,e){var t=this.e||(this.e={});return(t[n]||(t[n]=[])).push({fn:i,ctx:e}),this},once:function(n,i,e){var t=this;function s(){t.off(n,s),i.apply(e,arguments)}return s._=i,this.on(n,s,e)},emit:function(n){var i=[].slice.call(arguments,1),e=((this.e||(this.e={}))[n]||[]).slice(),t=0,s=e.length;for(t;t<s;t++)e[t].fn.apply(e[t].ctx,i);return this},off:function(n,i){var e=this.e||(this.e={}),t=e[n],s=[];if(t&&i)for(var o=0,h=t.length;o<h;o++)t[o].fn!==i&&t[o].fn._!==i&&s.push(t[o]);return s.length?e[n]=s:delete e[n],this}},A.exports=b;var S=A.exports.TinyEmitter=b;const x=new S;function y(n){const i=document.createDocumentFragment(),e=document.createElement("div");for(e.innerHTML=n;e.firstChild;)i.append(e.firstChild);return i}function k(n){const i=document.importNode(n),e=n.offsetWidth;i.style.cssText=`position: fixed; top: 0; left: 0; overflow: auto; visibility: hidden; pointer-events: none; height: unset; max-height: unset; width: ${e}px`;const t=y("<span>Foo</span>"),s=y("<span>Foo</span>"),o=document.createElement("li"),h=document.createElement("li");o.append(t),h.append(s),i.append(o),i.append(h),n.parentNode?.append(i);const E=i.offsetHeight/2;return n.parentNode?.removeChild(i),E}function $(n,i,e=!1){const t=`_${Math.random().toString(36).slice(2,11)}`;if(typeof i!="string"&&"text"in i){const E=`<span>${i.text}</span>`,v=y(E),u=document.createElement("li");return i.classname=i.classname||"",i.icon&&(i.classname===""?i.classname=r.icon:i.classname.includes(r.icon)===!1&&(i.classname+=` ${r.icon}`),u.setAttribute("style",`background-image:url(${i.icon})`)),u.id=t,u.className=i.classname,u.append(v),n.append(u),x.emit(m.ADD_MENU_ENTRY,{id:t,isSubmenu:e,isSeparator:!1,callback:"callback"in i?i.callback:null,data:"data"in i?i.data:null},u),u}const s=`<li id="${t}" class="${r.separator}"><hr></li>`,o=y(s);n.append(o);const h=n.lastChild;return x.emit(m.ADD_MENU_ENTRY,{id:t,isSubmenu:e,isSeparator:!0,callback:null,data:null},h),h}function L(n,i,e){i.forEach(t=>{if(typeof t!="string"&&"items"in t&&Array.isArray(t.items)){const s=$(n,t,!0);s.classList.add(r.submenu);const o=document.createElement("ul");o.classList.add(r.container),o.style.width=`${e}px`,s.append(o),L(o,t.items,e)}else $(n,t)})}const P="";function C(n,i){if(!n)throw new Error(i)}class T extends f.default{constructor(e={}){C(typeof e=="object","@param `opts` should be object type!");const t=document.createElement("div");super({element:t});a(this,"map");a(this,"container");a(this,"coordinate",[]);a(this,"pixel",[]);a(this,"contextMenuEventListener");a(this,"entryCallbackEventListener");a(this,"mapMoveListener");a(this,"lineHeight",0);a(this,"disabled");a(this,"opened");a(this,"items",[]);a(this,"menuEntries",new Map);a(this,"options");this.options={...N,...e};const s=document.createElement("ul");t.append(s),t.style.width=`${this.options.width}px`,t.classList.add(r.container,r.unselectable,r.hidden),this.container=t,this.contextMenuEventListener=o=>{this.handleContextMenu(o)},this.entryCallbackEventListener=o=>{this.handleEntryCallback(o)},this.mapMoveListener=()=>{this.handleMapMove()},this.disabled=!1,this.opened=!1,x.on(m.ADD_MENU_ENTRY,(o,h)=>{this.handleAddMenuEntry(o,h)},this)}clear(){for(const e of this.menuEntries.keys())this.removeMenuEntry(e);this.container.replaceChildren(),this.container.append(document.createElement("ul"))}enable(){this.disabled=!1}disable(){this.disabled=!0}getDefaultItems(){return w}countItems(){return this.menuEntries.size}extend(e){C(Array.isArray(e),"@param `items` should be an Array."),L(this.container.firstElementChild,e,this.options.width)}closeMenu(){this.opened=!1,this.container.classList.add(r.hidden),this.dispatchEvent(m.CLOSE)}isOpen(){return this.opened}updatePosition(e){C(Array.isArray(e),"@param `pixel` should be an Array."),this.isOpen()&&(this.pixel=e,this.positionContainer())}pop(){const e=Array.from(this.menuEntries.keys()).pop();e&&this.removeMenuEntry(e)}shift(){const e=Array.from(this.menuEntries.keys()).shift();e&&this.removeMenuEntry(e)}push(e){e&&this.extend([e])}setMap(e){if(super.setMap(e),e){this.map=e,this.map.getViewport().addEventListener(this.options.eventType,this.contextMenuEventListener,!1),this.map.on("movestart",()=>{this.handleMapMove()}),this.items=this.options.defaultItems?this.options.items.concat(w):this.options.items,L(this.container.firstElementChild,this.items,this.options.width);const t=this.getMenuEntriesLength();this.lineHeight=t>0?this.container.offsetHeight/t:k(this.container)}else this.removeListeners(),this.clear()}removeListeners(){this.map.getViewport().removeEventListener(this.options.eventType,this.contextMenuEventListener,!1)}removeMenuEntry(e){const t=document.getElementById(e);t?.remove(),t?.removeEventListener("click",this.entryCallbackEventListener),this.menuEntries.delete(e)}handleContextMenu(e){this.coordinate=this.map.getEventCoordinate(e),this.pixel=this.map.getEventPixel(e),this.dispatchEvent({type:m.BEFOREOPEN,pixel:this.pixel,coordinate:this.coordinate}),!this.disabled&&(this.options.eventType===M.CONTEXTMENU&&(e.stopPropagation(),e.preventDefault()),this.openMenu(),e.target?.addEventListener("pointerdown",t=>{this.opened&&(t.stopPropagation(),this.closeMenu())},{once:!0}))}openMenu(){this.menuEntries.size!==0&&(this.opened=!0,this.positionContainer(),this.container.classList.remove(r.hidden))}getMenuEntriesLength(){return Array.from(this.menuEntries).filter(([,e])=>e.isSeparator===!1||e.isSubmenu===!1).length}positionContainer(){const e=this.map.getSize()||[0,0],t={w:e[0]-this.pixel[0],h:e[1]-this.pixel[1]},s={w:this.container.offsetWidth,h:Math.round(this.lineHeight*this.getMenuEntriesLength())},o=t.w>=s.w?this.pixel[0]+5:this.pixel[0]-s.w;this.container.style.left=`${o}px`,this.container.style.top=t.h>=s.h?`${this.pixel[1]-10}px`:`${this.pixel[1]-s.h}px`,this.container.style.right="auto",this.container.style.bottom="auto",t.w-=s.w;const h=u=>Array.from(u.children).filter(g=>g.tagName==="LI"&&g.classList.contains(r.submenu));let E=0;const v=(u,g)=>{E+=1,h(u).forEach(_=>{const D=g>=s.w?s.w-8:(s.w+8)*-1,d=_.querySelector(`ul.${r.container}`),O=Math.round(this.lineHeight*Array.from(d.children).filter(I=>I.tagName==="LI").length);d.style.left=`${D}px`,d.style.right="auto",d.style.top=t.h>=O+s.h?"0":`-${d.offsetHeight-25}px`,d.style.bottom="auto",d.style.zIndex=String(E),h(d).length>0&&v(d,g-s.w)})};v(this.container.firstElementChild,t.w)}handleMapMove(){this.closeMenu()}handleEntryCallback(e){e.preventDefault(),e.stopPropagation();const t=e.currentTarget,s=this.menuEntries.get(t.id);if(!s)return;const o={coordinate:this.coordinate,data:s.data};this.closeMenu(),s.callback?.(o,this.map)}handleAddMenuEntry(e,t){this.menuEntries.set(e.id,e),"callback"in e&&typeof e.callback=="function"&&t.addEventListener("click",this.entryCallbackEventListener,!1)}}return T});
@@ -0,0 +1,52 @@
1
+ import type { Coordinate } from 'ol/coordinate';
2
+ import type { Pixel } from 'ol/pixel';
3
+ import { Map as OlMap } from 'ol';
4
+ import BaseEvent from 'ol/events/Event';
5
+ export declare enum EventTypes {
6
+ CONTEXTMENU = "contextmenu",
7
+ CLICK = "click",
8
+ DBLCLICK = "dblclick"
9
+ }
10
+ export declare enum CustomEventTypes {
11
+ BEFOREOPEN = "beforeopen",
12
+ OPEN = "open",
13
+ CLOSE = "close",
14
+ ADD_MENU_ENTRY = "add-menu-entry"
15
+ }
16
+ export interface ContextMenuEvent extends BaseEvent {
17
+ coordinate: Coordinate;
18
+ pixel: Pixel;
19
+ }
20
+ export declare type CallbackObject = {
21
+ coordinate: Coordinate;
22
+ data: unknown;
23
+ };
24
+ export declare type ItemSeparator = '-';
25
+ export declare type SingleItem = {
26
+ text: string;
27
+ classname?: string;
28
+ icon?: string;
29
+ callback: (object: CallbackObject, map: OlMap) => void;
30
+ data?: unknown;
31
+ };
32
+ export declare type MenuEntry = {
33
+ id: string;
34
+ isSubmenu: boolean;
35
+ isSeparator: boolean;
36
+ callback: SingleItem['callback'] | null;
37
+ data: unknown;
38
+ };
39
+ export declare type ItemWithNested = {
40
+ text: string;
41
+ classname?: string;
42
+ icon?: string;
43
+ items: Item[];
44
+ };
45
+ export declare type Item = SingleItem | ItemSeparator | ItemWithNested;
46
+ export declare type Options = {
47
+ width: number;
48
+ scrollAt: number;
49
+ eventType: `${EventTypes}`;
50
+ defaultItems: boolean;
51
+ items: Item[];
52
+ };
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ol-contextmenu",
3
- "version": "5.0.1-alpha",
3
+ "version": "5.0.1",
4
4
  "description": "Custom Context Menu for Openlayers",
5
5
  "type": "module",
6
6
  "main": "./dist/ol-contextmenu.umd.cjs",
@@ -8,9 +8,17 @@
8
8
  "exports": {
9
9
  ".": {
10
10
  "import": "./dist/ol-contextmenu.js",
11
- "require": "./dist/ol-contextmenu.umd.cjs"
11
+ "require": "./dist/ol-contextmenu.umd.cjs",
12
+ "types": "./dist/ol-contextmenu.d.ts"
13
+ },
14
+ "./ol-contextmenu.css": {
15
+ "import": "./dist/ol-contextmenu.css",
16
+ "require": "./dist/ol-contextmenu.css"
12
17
  }
13
18
  },
19
+ "files": [
20
+ "./dist"
21
+ ],
14
22
  "types": "./dist/ol-contextmenu.d.ts",
15
23
  "author": "Jonatas Walker",
16
24
  "homepage": "https://github.com/jonataswalker/ol-contextmenu",
@@ -26,24 +34,19 @@
26
34
  "node": "^16 || ^18",
27
35
  "npm": ">=8"
28
36
  },
29
- "files": [
30
- "dist/"
31
- ],
32
37
  "scripts": {
33
38
  "dev": "vite",
34
- "build": "npm run generate-types && tsc && vite build",
39
+ "build": "rimraf ./dist && vite build",
35
40
  "preview": "vite preview",
36
41
  "lint": "eslint --cache --ext .js .",
37
42
  "lint:fix": "npm run lint -- --fix",
38
- "generate-types": "tsc src/**/*.ts --declaration --declarationMap --emitDeclarationOnly --outdir dist",
39
- "test": "jest"
43
+ "test": "jest",
44
+ "prepublishOnly": "npm run lint && npm test && npm run build"
40
45
  },
41
46
  "devDependencies": {
42
- "@swc/core": "^1.3.0",
47
+ "@swc/core": "^1.3.2",
43
48
  "@swc/jest": "^0.2.22",
44
- "@types/jest": "^29.0.2",
45
- "@vitejs/plugin-legacy": "^2.1.0",
46
- "canvas": "^2.10.1",
49
+ "@types/jest": "^29.0.3",
47
50
  "eslint": "^8.23.1",
48
51
  "eslint-config-jwalker": "^7.9.2",
49
52
  "eslint-config-prettier": "^8.5.0",
@@ -54,8 +57,10 @@
54
57
  "jest-environment-jsdom": "^29.0.3",
55
58
  "ol": "^7.1.0",
56
59
  "prettier": "^2.7.1",
60
+ "rimraf": "^3.0.2",
57
61
  "typescript": "^4.8.3",
58
- "vite": "^3.1.0"
62
+ "vite": "^3.1.3",
63
+ "vite-plugin-dts": "^1.5.0"
59
64
  },
60
65
  "peerDependencies": {
61
66
  "ol": "^7.1.0"