@operato/mini-map 2.0.0-beta.0 → 2.0.0-beta.10

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/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [2.0.0-beta.10](https://github.com/hatiolab/operato/compare/v2.0.0-beta.9...v2.0.0-beta.10) (2024-06-08)
7
+
8
+
9
+ ### :rocket: New Features
10
+
11
+ * mini-map ([a1cdac2](https://github.com/hatiolab/operato/commit/a1cdac283c57129420247c6d61b9488d2a595dc2))
12
+ * ox-zoomable-image in mini-map module ([9f23992](https://github.com/hatiolab/operato/commit/9f2399235b318cd9b90740ae19aa6d481280d61b))
13
+
14
+
15
+
6
16
  ## [2.0.0-beta.0](https://github.com/hatiolab/operato/compare/v2.0.0-alpha.158...v2.0.0-beta.0) (2024-06-01)
7
17
 
8
18
  **Note:** Version bump only for package @operato/mini-map
@@ -1,7 +1,7 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { html, css, LitElement } from 'lit';
3
3
  import { customElement, property } from 'lit/decorators.js';
4
- let OxminimapComponent = class OxminimapComponent extends LitElement {
4
+ let OxMiniMapComponent = class OxMiniMapComponent extends LitElement {
5
5
  constructor() {
6
6
  super(...arguments);
7
7
  this.target = null;
@@ -10,28 +10,50 @@ let OxminimapComponent = class OxminimapComponent extends LitElement {
10
10
  this.startY = 0;
11
11
  this.initialScrollLeft = 0;
12
12
  this.initialScrollTop = 0;
13
+ this.observer = null;
13
14
  }
14
15
  connectedCallback() {
15
16
  super.connectedCallback();
16
17
  window.addEventListener('resize', this.handleResize.bind(this));
18
+ this.addEventListener('mousemove', this.handleMouseMove.bind(this));
19
+ this.addEventListener('mouseup', this.handleMouseUp.bind(this));
20
+ if (this.target) {
21
+ this.observeTarget(this.target);
22
+ }
17
23
  }
18
24
  disconnectedCallback() {
19
25
  super.disconnectedCallback();
20
26
  window.removeEventListener('resize', this.handleResize.bind(this));
27
+ window.removeEventListener('mousemove', this.handleMouseMove.bind(this));
28
+ window.removeEventListener('mouseup', this.handleMouseUp.bind(this));
29
+ if (this.observer) {
30
+ this.observer.disconnect();
31
+ this.observer = null;
32
+ }
21
33
  }
22
34
  firstUpdated(changes) {
23
35
  super.firstUpdated(changes);
24
36
  this.updateTarget();
25
- this.checkVisibilityX();
26
37
  }
27
38
  updated(changedProperties) {
28
39
  if (changedProperties.has('target')) {
29
40
  this.updateTarget();
41
+ if (this.target) {
42
+ this.observeTarget(this.target);
43
+ }
30
44
  }
31
45
  }
32
46
  handleResize() {
33
47
  this.updateTarget();
34
- this.checkVisibilityX();
48
+ }
49
+ observeTarget(target) {
50
+ if (this.observer) {
51
+ this.observer.disconnect();
52
+ }
53
+ this.observer = new MutationObserver(() => {
54
+ this.updateTarget();
55
+ });
56
+ this.observer.observe(target, { attributes: true, attributeFilter: ['style'] });
35
57
  }
36
58
  updateTarget() {
37
59
  var _a, _b;
@@ -39,108 +61,99 @@ let OxminimapComponent = class OxminimapComponent extends LitElement {
39
61
  if (!target) {
40
62
  return;
41
63
  }
64
+ const targetStyle = window.getComputedStyle(target);
65
+ const transform = targetStyle.transform;
66
+ const scaleMatch = /scale\(([^,]+),?([^)]+)?\)/.exec(transform);
67
+ const leftMatch = /translate\(([^,]+)px, ?([^)]+)?px\)/.exec(transform);
68
+ let scale = 1;
69
+ let left = 0;
70
+ let top = 0;
71
+ if (scaleMatch) {
72
+ scale = parseFloat(scaleMatch[1]);
73
+ }
74
+ if (leftMatch) {
75
+ left = parseFloat(leftMatch[1]);
76
+ top = parseFloat(leftMatch[2] || '0');
77
+ }
42
78
  const targetRatio = target.scrollHeight / target.scrollWidth;
43
79
  const thisRatio = this.offsetHeight / this.offsetWidth;
44
- const scale = targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth;
45
- const minimapHeight = target.scrollHeight * scale;
46
- const minimapWidth = target.scrollWidth * scale;
47
- const viewportHeight = target.offsetHeight * scale;
48
- const viewportWidth = target.offsetWidth * scale;
80
+ const scaleMinimap = targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth;
81
+ const minimapHeight = target.scrollHeight * scaleMinimap;
82
+ const minimapWidth = target.scrollWidth * scaleMinimap;
83
+ const viewportHeight = target.clientHeight * scaleMinimap;
84
+ const viewportWidth = target.clientWidth * scaleMinimap;
49
85
  const minimap = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('minimap');
50
86
  const viewport = (_b = this.shadowRoot) === null || _b === void 0 ? void 0 : _b.getElementById('viewport');
51
87
  minimap.style.width = `${minimapWidth}px`;
52
88
  minimap.style.height = `${minimapHeight}px`;
53
89
  viewport.style.width = `${viewportWidth}px`;
54
90
  viewport.style.height = `${viewportHeight}px`;
55
- const viewportLeft = target.scrollLeft * scale;
56
- const viewportTop = target.scrollTop * scale;
57
- viewport.style.width = `${viewportWidth}px`;
58
- viewport.style.height = `${viewportHeight}px`;
59
- viewport.style.left = `${viewportLeft}px`;
60
- viewport.style.top = `${viewportTop}px`;
61
- }
62
- checkVisibilityX() {
63
- var _a;
64
- const parentElement = this.target || this.parentElement;
65
- if (!parentElement)
66
- return;
67
- const parentRect = parentElement.getBoundingClientRect();
68
- const minimap = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('minimap');
69
- if (parentRect.width >= minimap.offsetWidth && parentRect.height >= minimap.offsetHeight) {
70
- this.style.display = 'block';
71
- }
72
- else {
73
- this.style.display = 'none';
74
- }
91
+ this.updateViewportPosition(scale, left, top);
75
92
  }
76
- handleMouseDown(event) {
93
+ updateViewportPosition(scale, left, top) {
77
94
  var _a;
78
95
  const target = this.target || this.parentElement;
79
96
  if (!target) {
80
97
  return;
81
98
  }
82
- const minimapViewport = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('viewport');
99
+ const targetRatio = target.scrollHeight / target.scrollWidth;
100
+ const thisRatio = this.offsetHeight / this.offsetWidth;
101
+ const scaleMinimap = targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth;
102
+ const viewport = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('viewport');
103
+ viewport.style.transform = `scale(${scale}) translate(${left * scaleMinimap}px, ${top * scaleMinimap}px)`;
104
+ }
105
+ handleMouseDown(event) {
106
+ this.isDragging = true;
83
107
  this.startX = event.clientX;
84
108
  this.startY = event.clientY;
85
- this.initialScrollLeft = target.scrollLeft || 0;
86
- this.initialScrollTop = target.scrollTop || 0;
87
- this.isDragging = true;
88
- minimapViewport.classList.add('dragging');
109
+ const target = this.target || this.parentElement;
110
+ if (target) {
111
+ this.initialScrollLeft = target.scrollLeft;
112
+ this.initialScrollTop = target.scrollTop;
113
+ }
114
+ window.addEventListener('mousemove', this.handleMouseMove.bind(this));
115
+ window.addEventListener('mouseup', this.handleMouseUp.bind(this));
89
116
  event.preventDefault();
90
- event.stopPropagation();
91
117
  }
92
118
  handleMouseMove(event) {
93
- var _a;
94
119
  if (!this.isDragging)
95
120
  return;
96
121
  const deltaX = event.clientX - this.startX;
97
122
  const deltaY = event.clientY - this.startY;
98
123
  const target = this.target || this.parentElement;
99
- if (!target) {
124
+ if (!target)
100
125
  return;
101
- }
102
126
  const targetRatio = target.scrollHeight / target.scrollWidth;
103
127
  const thisRatio = this.offsetHeight / this.offsetWidth;
104
128
  const scale = targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth;
105
- const targetRect = target.getBoundingClientRect();
106
- const viewportWidth = (targetRect.width * target.clientWidth) / target.scrollWidth;
107
- const viewportHeight = (targetRect.height * target.clientHeight) / target.scrollHeight;
108
129
  const scrollX = deltaX / scale;
109
130
  const scrollY = deltaY / scale;
110
- target.scrollTo(this.initialScrollLeft + scrollX, this.initialScrollTop + scrollY);
111
- const minimapViewport = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('viewport');
112
- minimapViewport.style.left = `${Math.max(0, Math.min(event.clientX - viewportWidth / 2, target.clientWidth - viewportWidth))}px`;
113
- minimapViewport.style.top = `${Math.max(0, Math.min(event.clientY - viewportHeight / 2, target.clientHeight - viewportHeight))}px`;
114
- this.updateTarget();
131
+ target.scrollLeft = this.initialScrollLeft + scrollX;
132
+ target.scrollTop = this.initialScrollTop + scrollY;
133
+ this.updateViewportPosition(1, target.scrollLeft, target.scrollTop); // Assuming no additional transform during drag
115
134
  event.preventDefault();
116
- event.stopPropagation();
117
135
  }
118
136
  handleMouseUp(event) {
119
- var _a;
120
- const minimapViewport = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('minimap');
121
137
  this.isDragging = false;
122
- minimapViewport.classList.remove('dragging');
138
+ window.removeEventListener('mousemove', this.handleMouseMove.bind(this));
139
+ window.removeEventListener('mouseup', this.handleMouseUp.bind(this));
123
140
  event.preventDefault();
124
- event.stopPropagation();
125
141
  }
126
142
  render() {
127
143
  return html `
128
144
  <div id="minimap">
129
- <div
130
- id="viewport"
131
- @mousedown=${this.handleMouseDown}
132
- @mousemove=${this.handleMouseMove}
133
- @mouseup=${this.handleMouseUp}
134
- ></div>
145
+ <div id="viewport" @mousedown=${this.handleMouseDown}></div>
135
146
  </div>
136
147
  `;
137
148
  }
138
149
  };
139
- OxminimapComponent.styles = css `
150
+ OxMiniMapComponent.styles = css `
140
151
  :host {
141
152
  display: flex;
142
153
  position: relative;
143
154
  background-color: gray;
155
+ width: 200px; /* 기본 너비 */
156
+ height: 150px; /* 기본 높이 */
144
157
  }
145
158
 
146
159
  #minimap {
@@ -149,7 +162,8 @@ OxminimapComponent.styles = css `
149
162
  left: 50%;
150
163
  transform: translate(-50%, -50%);
151
164
  box-sizing: border-box;
152
-
165
+ width: 100%;
166
+ height: 100%;
153
167
  background-color: var(--md-sys-color-surface);
154
168
  overflow: hidden;
155
169
  }
@@ -158,16 +172,14 @@ OxminimapComponent.styles = css `
158
172
  position: absolute;
159
173
  border: 1px dashed blue;
160
174
  box-sizing: border-box;
161
- pointer-events: none;
162
- background-color: var(--md-sys-color-surface);
163
- pointer-events: auto;
164
175
  cursor: move;
176
+ background-color: rgba(255, 255, 255, 0.5);
165
177
  }
166
178
  `;
167
179
  __decorate([
168
180
  property({ type: Object })
169
- ], OxminimapComponent.prototype, "target", void 0);
170
- OxminimapComponent = __decorate([
181
+ ], OxMiniMapComponent.prototype, "target", void 0);
182
+ OxMiniMapComponent = __decorate([
171
183
  customElement('ox-mini-map')
172
- ], OxminimapComponent);
184
+ ], OxMiniMapComponent);
173
185
  //# sourceMappingURL=ox-mini-map.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ox-mini-map.js","sourceRoot":"","sources":["../../src/ox-mini-map.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css, LitElement, PropertyValueMap } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\n@customElement('ox-mini-map')\nclass OxminimapComponent extends LitElement {\n static styles = css`\n :host {\n display: flex;\n position: relative;\n background-color: gray;\n }\n\n #minimap {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n box-sizing: border-box;\n\n background-color: var(--md-sys-color-surface);\n overflow: hidden;\n }\n\n #viewport {\n position: absolute;\n border: 1px dashed blue;\n box-sizing: border-box;\n pointer-events: none;\n background-color: var(--md-sys-color-surface);\n pointer-events: auto;\n cursor: move;\n }\n `\n\n @property({ type: Object }) target: HTMLElement | null = null\n private isDragging = false\n private startX = 0\n private startY = 0\n private initialScrollLeft = 0\n private initialScrollTop = 0\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('resize', this.handleResize.bind(this))\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n window.removeEventListener('resize', this.handleResize.bind(this))\n }\n\n firstUpdated(changes: PropertyValueMap<any> | Map<PropertyKey, unknown>) {\n super.firstUpdated(changes)\n\n this.updateTarget()\n this.checkVisibilityX()\n }\n\n updated(changedProperties: Map<string, any>) {\n if (changedProperties.has('target')) {\n this.updateTarget()\n }\n }\n\n handleResize() {\n this.updateTarget()\n this.checkVisibilityX()\n }\n\n updateTarget() {\n const target = this.target || this.parentElement\n if (!target) {\n return\n }\n\n const targetRatio = target.scrollHeight / target.scrollWidth\n const thisRatio = this.offsetHeight / this.offsetWidth\n\n const scale =\n targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth\n\n const minimapHeight = target.scrollHeight * scale\n const minimapWidth = target.scrollWidth * scale\n\n const viewportHeight = target.offsetHeight * scale\n const viewportWidth = target.offsetWidth * scale\n\n const minimap = this.shadowRoot?.getElementById('minimap') as HTMLElement\n const viewport = this.shadowRoot?.getElementById('viewport') as HTMLElement\n\n minimap.style.width = `${minimapWidth}px`\n minimap.style.height = `${minimapHeight}px`\n\n viewport.style.width = `${viewportWidth}px`\n viewport.style.height = `${viewportHeight}px`\n\n const viewportLeft = target.scrollLeft * scale\n const viewportTop = target.scrollTop * scale\n\n viewport.style.width = `${viewportWidth}px`\n viewport.style.height = `${viewportHeight}px`\n viewport.style.left = `${viewportLeft}px`\n viewport.style.top = `${viewportTop}px`\n }\n\n checkVisibilityX() {\n const parentElement = this.target || this.parentElement\n if (!parentElement) return\n\n const parentRect = parentElement.getBoundingClientRect()\n const minimap = this.shadowRoot?.getElementById('minimap') as HTMLElement\n if (parentRect.width >= minimap.offsetWidth && parentRect.height >= minimap.offsetHeight) {\n this.style.display = 'block'\n } else {\n this.style.display = 'none'\n }\n }\n\n handleMouseDown(event: MouseEvent) {\n const target = this.target || this.parentElement\n\n if (!target) {\n return\n }\n\n const minimapViewport = this.shadowRoot?.getElementById('viewport') as HTMLElement\n this.startX = event.clientX\n this.startY = event.clientY\n this.initialScrollLeft = target.scrollLeft || 0\n this.initialScrollTop = target.scrollTop || 0\n this.isDragging = true\n minimapViewport.classList.add('dragging')\n event.preventDefault()\n event.stopPropagation()\n }\n\n handleMouseMove(event: MouseEvent) {\n if (!this.isDragging) return\n const deltaX = event.clientX - this.startX\n const deltaY = event.clientY - this.startY\n\n const target = this.target || this.parentElement\n\n if (!target) {\n return\n }\n\n const targetRatio = target.scrollHeight / target.scrollWidth\n const thisRatio = this.offsetHeight / this.offsetWidth\n\n const scale =\n targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth\n\n const targetRect = target.getBoundingClientRect()\n const viewportWidth = (targetRect.width * target.clientWidth) / target.scrollWidth\n const viewportHeight = (targetRect.height * target.clientHeight) / target.scrollHeight\n const scrollX = deltaX / scale\n const scrollY = deltaY / scale\n target.scrollTo(this.initialScrollLeft + scrollX, this.initialScrollTop + scrollY)\n const minimapViewport = this.shadowRoot?.getElementById('viewport') as HTMLElement\n minimapViewport.style.left = `${Math.max(\n 0,\n Math.min(event.clientX - viewportWidth / 2, target.clientWidth - viewportWidth)\n )}px`\n minimapViewport.style.top = `${Math.max(\n 0,\n Math.min(event.clientY - viewportHeight / 2, target.clientHeight - viewportHeight)\n )}px`\n\n this.updateTarget()\n event.preventDefault()\n event.stopPropagation()\n }\n\n handleMouseUp(event: MouseEvent) {\n const minimapViewport = this.shadowRoot?.getElementById('minimap') as HTMLElement\n this.isDragging = false\n minimapViewport.classList.remove('dragging')\n event.preventDefault()\n event.stopPropagation()\n }\n\n render() {\n return html`\n <div id=\"minimap\">\n <div\n id=\"viewport\"\n @mousedown=${this.handleMouseDown}\n @mousemove=${this.handleMouseMove}\n @mouseup=${this.handleMouseUp}\n ></div>\n </div>\n `\n }\n}\n"]}
1
+ {"version":3,"file":"ox-mini-map.js","sourceRoot":"","sources":["../../src/ox-mini-map.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css, LitElement, PropertyValueMap } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\n@customElement('ox-mini-map')\nclass OxMiniMapComponent extends LitElement {\n static styles = css`\n :host {\n display: flex;\n position: relative;\n background-color: gray;\n width: 200px; /* 기본 너비 */\n height: 150px; /* 기본 높이 */\n }\n\n #minimap {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n background-color: var(--md-sys-color-surface);\n overflow: hidden;\n }\n\n #viewport {\n position: absolute;\n border: 1px dashed blue;\n box-sizing: border-box;\n cursor: move;\n background-color: rgba(255, 255, 255, 0.5);\n }\n `\n\n @property({ type: Object }) target: HTMLElement | null = null\n private isDragging = false\n private startX = 0\n private startY = 0\n private initialScrollLeft = 0\n private initialScrollTop = 0\n private observer: MutationObserver | null = null\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('resize', this.handleResize.bind(this))\n this.addEventListener('mousemove', this.handleMouseMove.bind(this))\n this.addEventListener('mouseup', this.handleMouseUp.bind(this))\n if (this.target) {\n this.observeTarget(this.target)\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n window.removeEventListener('resize', this.handleResize.bind(this))\n window.removeEventListener('mousemove', this.handleMouseMove.bind(this))\n window.removeEventListener('mouseup', this.handleMouseUp.bind(this))\n if (this.observer) {\n this.observer.disconnect()\n this.observer = null\n }\n }\n\n firstUpdated(changes: PropertyValueMap<any> | Map<PropertyKey, unknown>) {\n super.firstUpdated(changes)\n this.updateTarget()\n }\n\n updated(changedProperties: Map<string, any>) {\n if (changedProperties.has('target')) {\n this.updateTarget()\n if (this.target) {\n this.observeTarget(this.target)\n }\n }\n }\n\n handleResize() {\n this.updateTarget()\n }\n\n observeTarget(target: HTMLElement) {\n if (this.observer) {\n this.observer.disconnect()\n }\n this.observer = new MutationObserver(() => {\n this.updateTarget()\n })\n this.observer.observe(target, { attributes: true, attributeFilter: ['style'] })\n }\n\n updateTarget() {\n const target = this.target || this.parentElement\n if (!target) {\n return\n }\n\n const targetStyle = window.getComputedStyle(target)\n const transform = targetStyle.transform\n const scaleMatch = /scale\\(([^,]+),?([^)]+)?\\)/.exec(transform)\n const leftMatch = /translate\\(([^,]+)px, ?([^)]+)?px\\)/.exec(transform)\n\n let scale = 1\n let left = 0\n let top = 0\n\n if (scaleMatch) {\n scale = parseFloat(scaleMatch[1])\n }\n\n if (leftMatch) {\n left = parseFloat(leftMatch[1])\n top = parseFloat(leftMatch[2] || '0')\n }\n\n const targetRatio = target.scrollHeight / target.scrollWidth\n const thisRatio = this.offsetHeight / this.offsetWidth\n\n const scaleMinimap =\n targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth\n\n const minimapHeight = target.scrollHeight * scaleMinimap\n const minimapWidth = target.scrollWidth * scaleMinimap\n\n const viewportHeight = target.clientHeight * scaleMinimap\n const viewportWidth = target.clientWidth * scaleMinimap\n\n const minimap = this.shadowRoot?.getElementById('minimap') as HTMLElement\n const viewport = this.shadowRoot?.getElementById('viewport') as HTMLElement\n\n minimap.style.width = `${minimapWidth}px`\n minimap.style.height = `${minimapHeight}px`\n\n viewport.style.width = `${viewportWidth}px`\n viewport.style.height = `${viewportHeight}px`\n\n this.updateViewportPosition(scale, left, top)\n }\n\n updateViewportPosition(scale: number, left: number, top: number) {\n const target = this.target || this.parentElement\n if (!target) {\n return\n }\n\n const targetRatio = target.scrollHeight / target.scrollWidth\n const thisRatio = this.offsetHeight / this.offsetWidth\n\n const scaleMinimap =\n targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth\n\n const viewport = this.shadowRoot?.getElementById('viewport') as HTMLElement\n viewport.style.transform = `scale(${scale}) translate(${left * scaleMinimap}px, ${top * scaleMinimap}px)`\n }\n\n handleMouseDown(event: MouseEvent) {\n this.isDragging = true\n this.startX = event.clientX\n this.startY = event.clientY\n\n const target = this.target || this.parentElement\n if (target) {\n this.initialScrollLeft = target.scrollLeft\n this.initialScrollTop = target.scrollTop\n }\n\n window.addEventListener('mousemove', this.handleMouseMove.bind(this))\n window.addEventListener('mouseup', this.handleMouseUp.bind(this))\n\n event.preventDefault()\n }\n\n handleMouseMove(event: MouseEvent) {\n if (!this.isDragging) return\n\n const deltaX = event.clientX - this.startX\n const deltaY = event.clientY - this.startY\n\n const target = this.target || this.parentElement\n if (!target) return\n\n const targetRatio = target.scrollHeight / target.scrollWidth\n const thisRatio = this.offsetHeight / this.offsetWidth\n\n const scale =\n targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth\n\n const scrollX = deltaX / scale\n const scrollY = deltaY / scale\n\n target.scrollLeft = this.initialScrollLeft + scrollX\n target.scrollTop = this.initialScrollTop + scrollY\n\n this.updateViewportPosition(1, target.scrollLeft, target.scrollTop) // Assuming no additional transform during drag\n\n event.preventDefault()\n }\n\n handleMouseUp(event: MouseEvent) {\n this.isDragging = false\n window.removeEventListener('mousemove', this.handleMouseMove.bind(this))\n window.removeEventListener('mouseup', this.handleMouseUp.bind(this))\n event.preventDefault()\n }\n\n render() {\n return html`\n <div id=\"minimap\">\n <div id=\"viewport\" @mousedown=${this.handleMouseDown}></div>\n </div>\n `\n }\n}\n"]}
@@ -0,0 +1,54 @@
1
+ import { LitElement, PropertyValues } from 'lit';
2
+ /**
3
+ * Example usage:
4
+ *
5
+ * <html>
6
+ * <head>
7
+ * <script type="module" src="path/to/ox-zoomable-image.js"></script>
8
+ * <style>
9
+ * body {
10
+ * margin: 0;
11
+ * overflow: hidden;
12
+ * display: flex;
13
+ * justify-content: center;
14
+ * align-items: center;
15
+ * height: 100vh;
16
+ * }
17
+ * ox-zoomable-image {
18
+ * width: 80%;
19
+ * height: 80%;
20
+ * }
21
+ * </style>
22
+ * </head>
23
+ * <body>
24
+ * <ox-zoomable-image src="path/to/your/image.jpg"></ox-zoomable-image>
25
+ * </body>
26
+ * </html>
27
+ */
28
+ export declare class OxZoomableImage extends LitElement {
29
+ static styles: import("lit").CSSResult;
30
+ src?: string;
31
+ private zoom;
32
+ private left;
33
+ private top;
34
+ private minZoom;
35
+ private imageWidth;
36
+ private imageHeight;
37
+ private dragStart?;
38
+ private readonly dragEndHandler;
39
+ private readonly dragMoveHandler;
40
+ private readonly dragStartHandler;
41
+ private readonly wheelEventHandler;
42
+ private readonly resetHandler;
43
+ connectedCallback(): void;
44
+ disconnectedCallback(): void;
45
+ updated(changes: PropertyValues<this>): void;
46
+ private calculateMinZoom;
47
+ private onWheelEvent;
48
+ private onDragStart;
49
+ private onDragMove;
50
+ private onDragEnd;
51
+ private onReset;
52
+ private updateTransform;
53
+ private applyBounds;
54
+ }
@@ -0,0 +1,252 @@
1
+ import { __decorate } from "tslib";
2
+ import { css, LitElement } from 'lit';
3
+ import { customElement, property, state } from 'lit/decorators.js';
4
+ // Utility function to get the point from MouseEvent or TouchEvent
5
+ function getPoint(e) {
6
+ if (e instanceof MouseEvent && e.button === 0) {
7
+ return { x: e.clientX, y: e.clientY };
8
+ }
9
+ else if (e instanceof TouchEvent && e.touches.length === 1) {
10
+ const touch = e.touches[0];
11
+ return { x: touch.clientX, y: touch.clientY };
12
+ }
13
+ return undefined;
14
+ }
15
+ /**
16
+ * Example usage:
17
+ *
18
+ * <html>
19
+ * <head>
20
+ * <script type="module" src="path/to/ox-zoomable-image.js"></script>
21
+ * <style>
22
+ * body {
23
+ * margin: 0;
24
+ * overflow: hidden;
25
+ * display: flex;
26
+ * justify-content: center;
27
+ * align-items: center;
28
+ * height: 100vh;
29
+ * }
30
+ * ox-zoomable-image {
31
+ * width: 80%;
32
+ * height: 80%;
33
+ * }
34
+ * </style>
35
+ * </head>
36
+ * <body>
37
+ * <ox-zoomable-image src="path/to/your/image.jpg"></ox-zoomable-image>
38
+ * </body>
39
+ * </html>
40
+ */
41
+ let OxZoomableImage = class OxZoomableImage extends LitElement {
42
+ constructor() {
43
+ super(...arguments);
44
+ this.zoom = 1; // Current zoom level
45
+ this.left = 0; // Horizontal position
46
+ this.top = 0; // Vertical position
47
+ this.minZoom = 1; // Minimum zoom level
48
+ this.imageWidth = 0;
49
+ this.imageHeight = 0;
50
+ // Event listeners bound to the component
51
+ this.dragEndHandler = this.onDragEnd.bind(this);
52
+ this.dragMoveHandler = this.onDragMove.bind(this);
53
+ this.dragStartHandler = this.onDragStart.bind(this);
54
+ this.wheelEventHandler = this.onWheelEvent.bind(this);
55
+ this.resetHandler = this.onReset.bind(this);
56
+ }
57
+ connectedCallback() {
58
+ super.connectedCallback();
59
+ // Register event listeners for zooming and dragging
60
+ this.addEventListener('wheel', this.wheelEventHandler);
61
+ this.addEventListener('mousedown', this.dragStartHandler);
62
+ this.addEventListener('touchstart', this.dragStartHandler);
63
+ this.addEventListener('dblclick', this.resetHandler);
64
+ document.addEventListener('mouseup', this.dragEndHandler);
65
+ document.addEventListener('touchend', this.dragEndHandler);
66
+ document.addEventListener('touchcancel', this.dragEndHandler);
67
+ document.addEventListener('mousemove', this.dragMoveHandler);
68
+ document.addEventListener('touchmove', this.dragMoveHandler);
69
+ this.calculateMinZoom(); // Calculate the minimum zoom level based on the image and container size
70
+ }
71
+ disconnectedCallback() {
72
+ // Remove event listeners when the component is disconnected
73
+ this.removeEventListener('wheel', this.wheelEventHandler);
74
+ this.removeEventListener('mousedown', this.dragStartHandler);
75
+ this.removeEventListener('touchstart', this.dragStartHandler);
76
+ this.removeEventListener('dblclick', this.resetHandler);
77
+ document.removeEventListener('mouseup', this.dragEndHandler);
78
+ document.removeEventListener('touchend', this.dragEndHandler);
79
+ document.removeEventListener('touchcancel', this.dragEndHandler);
80
+ document.removeEventListener('mousemove', this.dragMoveHandler);
81
+ document.removeEventListener('touchmove', this.dragMoveHandler);
82
+ super.disconnectedCallback();
83
+ }
84
+ updated(changes) {
85
+ // Update the background image and transform style when properties change
86
+ if (changes.has('src') && this.src) {
87
+ this.style.setProperty('--background-image', `url('${this.src}')`);
88
+ this.calculateMinZoom(); // Recalculate the minimum zoom level when the source changes
89
+ }
90
+ this.updateTransform(); // Apply the current zoom and position
91
+ }
92
+ calculateMinZoom() {
93
+ // Calculate the minimum zoom level to ensure the image always fills the container
94
+ const img = new Image();
95
+ img.src = this.src || '';
96
+ img.onload = () => {
97
+ this.imageWidth = img.width;
98
+ this.imageHeight = img.height;
99
+ const aspectRatio = img.width / img.height;
100
+ const hostAspectRatio = this.offsetWidth / this.offsetHeight;
101
+ if (aspectRatio < hostAspectRatio) {
102
+ this.minZoom = this.offsetHeight / img.height;
103
+ }
104
+ else {
105
+ this.minZoom = this.offsetWidth / img.width;
106
+ }
107
+ this.zoom = 1; // this.minZoom
108
+ this.left = 0; // Center the image
109
+ this.top = 0; // Center the image
110
+ this.updateTransform();
111
+ };
112
+ }
113
+ onWheelEvent(e) {
114
+ // Handle zoom in and out based on mouse wheel events
115
+ e.preventDefault();
116
+ const delta = Math.sign(e.deltaY);
117
+ const newZoom = Math.max(1, this.zoom * (1 - delta / 20));
118
+ const zoomFactor = newZoom / this.zoom;
119
+ const rect = this.getBoundingClientRect();
120
+ const offsetX = e.clientX - rect.left - rect.width / 2;
121
+ const offsetY = e.clientY - rect.top - rect.height / 2;
122
+ // Adjust the position to zoom in/out relative to the center of the client rect
123
+ this.left -= offsetX * (zoomFactor - 1);
124
+ this.top -= offsetY * (zoomFactor - 1);
125
+ this.zoom = newZoom;
126
+ this.applyBounds(); // Ensure the image stays within bounds
127
+ this.updateTransform(); // Apply the new zoom and position
128
+ }
129
+ onDragStart(e) {
130
+ // Start dragging the image
131
+ const point = getPoint(e);
132
+ if (point) {
133
+ this.dragStart = point;
134
+ e.stopPropagation();
135
+ }
136
+ }
137
+ onDragMove(e) {
138
+ // Move the image based on drag events
139
+ if (!this.dragStart)
140
+ return;
141
+ const point = getPoint(e);
142
+ if (!point)
143
+ return;
144
+ e.stopPropagation();
145
+ e.preventDefault();
146
+ const { x, y } = point;
147
+ this.left += x - this.dragStart.x;
148
+ this.top += y - this.dragStart.y;
149
+ this.dragStart = point;
150
+ this.applyBounds(); // Ensure the image stays within bounds
151
+ this.updateTransform(); // Apply the new position
152
+ }
153
+ onDragEnd(e) {
154
+ // End the drag operation
155
+ if (this.dragStart) {
156
+ e.stopPropagation();
157
+ e.preventDefault();
158
+ this.dragStart = undefined;
159
+ }
160
+ }
161
+ onReset(e) {
162
+ // Reset zoom and position to initial state
163
+ this.zoom = 1;
164
+ this.left = 0;
165
+ this.top = 0;
166
+ this.updateTransform();
167
+ }
168
+ updateTransform() {
169
+ // Apply the current zoom and position to the image
170
+ this.style.setProperty('--image-transform', `scale(${this.zoom}) translate(${this.left}px, ${this.top}px)`);
171
+ }
172
+ applyBounds() {
173
+ // Ensure the image stays within the bounds of the container
174
+ const hostWidth = this.offsetWidth;
175
+ const hostHeight = this.offsetHeight;
176
+ const aspectRatio = this.imageHeight / this.imageWidth;
177
+ const hostAspectRatio = hostHeight / hostWidth;
178
+ if (aspectRatio < hostAspectRatio) {
179
+ /* image ratio is wider than host */
180
+ var minX = Math.min(0, (-hostWidth * (this.zoom - 1)) / 2 / this.zoom);
181
+ var maxX = -minX;
182
+ var minY = (hostHeight - hostWidth * aspectRatio * this.zoom) / 2 / this.zoom;
183
+ minY = Math.min(minY, -minY);
184
+ var maxY = -minY;
185
+ this.left = Math.max(minX, Math.min(this.left, maxX));
186
+ this.top = Math.max(minY, Math.min(this.top, maxY));
187
+ }
188
+ else {
189
+ var minX = (hostWidth - (hostHeight / aspectRatio) * this.zoom) / 2 / this.zoom;
190
+ minX = Math.min(minX, -minX);
191
+ var maxX = -minX;
192
+ var minY = Math.min(0, (-hostHeight * (this.zoom - 1)) / 2 / this.zoom);
193
+ var maxY = -minY;
194
+ this.left = Math.max(minX, Math.min(this.left, maxX));
195
+ this.top = Math.max(minY, Math.min(this.top, maxY));
196
+ }
197
+ }
198
+ };
199
+ // Define CSS styles for the component
200
+ OxZoomableImage.styles = css `
201
+ :host {
202
+ display: block;
203
+ position: relative;
204
+ width: 100%;
205
+ height: 100%;
206
+ overflow: hidden;
207
+ }
208
+
209
+ :host::before {
210
+ content: '';
211
+ display: block;
212
+ position: absolute;
213
+ top: 0;
214
+ right: 0;
215
+ width: 100%;
216
+ height: 100%;
217
+ background-image: var(
218
+ --background-image,
219
+ linear-gradient(var(--primary-color, lightgray), var(--primary-color, lightgray))
220
+ );
221
+ transform: var(--image-transform, '');
222
+ background-repeat: no-repeat;
223
+ background-position: center;
224
+ background-size: contain;
225
+ }
226
+ `;
227
+ __decorate([
228
+ property({ type: String })
229
+ ], OxZoomableImage.prototype, "src", void 0);
230
+ __decorate([
231
+ state()
232
+ ], OxZoomableImage.prototype, "zoom", void 0);
233
+ __decorate([
234
+ state()
235
+ ], OxZoomableImage.prototype, "left", void 0);
236
+ __decorate([
237
+ state()
238
+ ], OxZoomableImage.prototype, "top", void 0);
239
+ __decorate([
240
+ state()
241
+ ], OxZoomableImage.prototype, "minZoom", void 0);
242
+ __decorate([
243
+ state()
244
+ ], OxZoomableImage.prototype, "imageWidth", void 0);
245
+ __decorate([
246
+ state()
247
+ ], OxZoomableImage.prototype, "imageHeight", void 0);
248
+ OxZoomableImage = __decorate([
249
+ customElement('ox-zoomable-image')
250
+ ], OxZoomableImage);
251
+ export { OxZoomableImage };
252
+ //# sourceMappingURL=ox-zoomable-image.js.map