@operato/board 0.2.15

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 (69) hide show
  1. package/.storybook/main.js +3 -0
  2. package/.storybook/server.mjs +8 -0
  3. package/CHANGELOG.md +22 -0
  4. package/LICENSE +21 -0
  5. package/README.md +95 -0
  6. package/custom-elements.json +1377 -0
  7. package/demo/index-player.html +101 -0
  8. package/demo/index-viewer.html +101 -0
  9. package/demo/index.html +101 -0
  10. package/dist/src/index.d.ts +2 -0
  11. package/dist/src/index.js +3 -0
  12. package/dist/src/index.js.map +1 -0
  13. package/dist/src/ox-board-player copy.d.ts +39 -0
  14. package/dist/src/ox-board-player copy.js +258 -0
  15. package/dist/src/ox-board-player copy.js.map +1 -0
  16. package/dist/src/ox-board-player-control.d.ts +39 -0
  17. package/dist/src/ox-board-player-control.js +390 -0
  18. package/dist/src/ox-board-player-control.js.map +1 -0
  19. package/dist/src/ox-board-player-style.d.ts +1 -0
  20. package/dist/src/ox-board-player-style.js +200 -0
  21. package/dist/src/ox-board-player-style.js.map +1 -0
  22. package/dist/src/ox-board-player.d.ts +39 -0
  23. package/dist/src/ox-board-player.js +284 -0
  24. package/dist/src/ox-board-player.js.map +1 -0
  25. package/dist/src/ox-board-viewer.d.ts +45 -0
  26. package/dist/src/ox-board-viewer.js +491 -0
  27. package/dist/src/ox-board-viewer.js.map +1 -0
  28. package/dist/src/ox-board-wrapper.d.ts +1 -0
  29. package/dist/src/ox-board-wrapper.js +88 -0
  30. package/dist/src/ox-board-wrapper.js.map +1 -0
  31. package/dist/src/player/board-player-carousel.d.ts +1 -0
  32. package/dist/src/player/board-player-carousel.js +205 -0
  33. package/dist/src/player/board-player-carousel.js.map +1 -0
  34. package/dist/src/player/board-player-grid.d.ts +1 -0
  35. package/dist/src/player/board-player-grid.js +78 -0
  36. package/dist/src/player/board-player-grid.js.map +1 -0
  37. package/dist/src/utils/fullscreen.d.ts +14 -0
  38. package/dist/src/utils/fullscreen.js +69 -0
  39. package/dist/src/utils/fullscreen.js.map +1 -0
  40. package/dist/src/utils/os.d.ts +20 -0
  41. package/dist/src/utils/os.js +41 -0
  42. package/dist/src/utils/os.js.map +1 -0
  43. package/dist/src/utils/swipe-listener.d.ts +10 -0
  44. package/dist/src/utils/swipe-listener.js +257 -0
  45. package/dist/src/utils/swipe-listener.js.map +1 -0
  46. package/dist/stories/index.stories.d.ts +33 -0
  47. package/dist/stories/index.stories.js +33 -0
  48. package/dist/stories/index.stories.js.map +1 -0
  49. package/dist/test/board-viewer.test.d.ts +1 -0
  50. package/dist/test/board-viewer.test.js +24 -0
  51. package/dist/test/board-viewer.test.js.map +1 -0
  52. package/dist/tsconfig.tsbuildinfo +1 -0
  53. package/package.json +76 -0
  54. package/src/index.ts +2 -0
  55. package/src/ox-board-player-style.ts +200 -0
  56. package/src/ox-board-player.ts +292 -0
  57. package/src/ox-board-viewer.ts +534 -0
  58. package/src/ox-board-wrapper.ts +93 -0
  59. package/src/player/board-player-carousel.ts +197 -0
  60. package/src/player/board-player-grid.ts +78 -0
  61. package/src/utils/fullscreen.ts +82 -0
  62. package/src/utils/os.ts +41 -0
  63. package/src/utils/swipe-listener.ts +290 -0
  64. package/src/utils/things-scene.d.ts +1 -0
  65. package/stories/index.stories.ts +52 -0
  66. package/test/board-viewer.test.ts +35 -0
  67. package/tsconfig.json +22 -0
  68. package/web-dev-server.config.mjs +28 -0
  69. package/web-test-runner.config.mjs +29 -0
@@ -0,0 +1,491 @@
1
+ import { __decorate } from "tslib";
2
+ import '@material/mwc-fab';
3
+ import '@material/mwc-icon';
4
+ import { LitElement, css, html } from 'lit';
5
+ import { customElement, property, query, state } from 'lit/decorators.js';
6
+ import { create } from '@hatiolab/things-scene';
7
+ import { isIOS } from './utils/os';
8
+ import { togglefullscreen } from './utils/fullscreen';
9
+ let BoardViewer = class BoardViewer extends LitElement {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.baseUrl = '';
13
+ this.board = {};
14
+ this.provider = null;
15
+ this.data = {};
16
+ this.hideFullscreen = false;
17
+ this.hideNavigation = false;
18
+ this.scene = null;
19
+ this.forward = [];
20
+ this.backward = [];
21
+ }
22
+ render() {
23
+ var fullscreen = !isIOS() && !this.hideFullscreen
24
+ ? html `
25
+ <mwc-fab
26
+ id="fullscreen"
27
+ .icon=${document.fullscreenElement ? 'fullscreen_exit' : 'fullscreen'}
28
+ @click=${(e) => this.onTapFullscreen()}
29
+ @mouseover=${(e) => this.transientShowButtons(true)}
30
+ @mouseout=${(e) => this.transientShowButtons()}
31
+ title="fullscreen"
32
+ ></mwc-fab>
33
+ `
34
+ : html ``;
35
+ var prev = !this.hideNavigation
36
+ ? html `
37
+ <mwc-icon
38
+ id="prev"
39
+ @click=${(e) => this.onTapPrev()}
40
+ @mouseover=${(e) => this.transientShowButtons(true)}
41
+ @mouseout=${(e) => this.transientShowButtons()}
42
+ hidden
43
+ >keyboard_arrow_left</mwc-icon
44
+ >
45
+ `
46
+ : html ``;
47
+ var next = !this.hideNavigation
48
+ ? html `
49
+ <mwc-icon
50
+ id="next"
51
+ @click=${(e) => this.onTapNext()}
52
+ @mouseover=${(e) => this.transientShowButtons(true)}
53
+ @mouseout=${(e) => this.transientShowButtons()}
54
+ hidden
55
+ >keyboard_arrow_right</mwc-icon
56
+ >
57
+ `
58
+ : html ``;
59
+ return html `
60
+ ${prev}
61
+
62
+ <div
63
+ id="target"
64
+ @touchstart=${(e) => this.transientShowButtons()}
65
+ @mousemove=${(e) => this.transientShowButtons()}
66
+ ></div>
67
+
68
+ ${next} ${fullscreen}
69
+ `;
70
+ }
71
+ firstUpdated() {
72
+ window.addEventListener('resize', () => {
73
+ this.scene && this.scene.fit();
74
+ });
75
+ this.renderRoot.addEventListener('close-scene', e => {
76
+ e.preventDefault();
77
+ this.onTapPrev();
78
+ }, false);
79
+ }
80
+ updated(changes) {
81
+ if (changes.has('board')) {
82
+ if (this.board && this.board.id) {
83
+ this.initScene();
84
+ }
85
+ else {
86
+ this.closeScene();
87
+ }
88
+ }
89
+ if (changes.has('data') && this.scene && this.data) {
90
+ this.scene.data = this.data;
91
+ }
92
+ }
93
+ initScene() {
94
+ if (!this.board || !this.board.id)
95
+ return;
96
+ var scene = create({
97
+ model: {
98
+ ...this.board.model
99
+ },
100
+ mode: 0,
101
+ refProvider: this.provider
102
+ });
103
+ if (this.baseUrl) {
104
+ scene.baseUrl = this.baseUrl;
105
+ }
106
+ this.provider.add(this.board.id, scene);
107
+ this.showScene(this.board.id);
108
+ /* provider.add 시에 추가된 레퍼런스 카운트를 다운시켜주어야 함 */
109
+ scene.release();
110
+ }
111
+ closeScene() {
112
+ if (this.scene) {
113
+ this.unbindSceneEvents(this.scene);
114
+ this.scene.target = null;
115
+ this.scene.release();
116
+ delete this.scene;
117
+ }
118
+ // delete queued scenes
119
+ this.forward.forEach(scene => scene.release());
120
+ this.forward = [];
121
+ this.backward.forEach(scene => scene.release());
122
+ this.backward = [];
123
+ }
124
+ releaseScene() {
125
+ if (this.scene) {
126
+ this.unbindSceneEvents(this.scene);
127
+ this.scene.target = null;
128
+ this.scene.release();
129
+ delete this.scene;
130
+ // delete queued scenes
131
+ this.forward.forEach(scene => {
132
+ scene.release();
133
+ });
134
+ this.forward = [];
135
+ this.backward.forEach(scene => {
136
+ scene.release();
137
+ });
138
+ this.backward = [];
139
+ this.transientShowButtons();
140
+ }
141
+ }
142
+ setupScene(scene) {
143
+ this.scene = scene;
144
+ /* scene의 기존 target을 보관한다. */
145
+ this._oldtarget = this.scene.target;
146
+ this.scene.fit(this.board.model.fitMode);
147
+ this.scene.target = this.target;
148
+ if (this.data) {
149
+ this.scene.data = this.data;
150
+ }
151
+ this.bindSceneEvents();
152
+ this.transientShowButtons();
153
+ }
154
+ async showScene(boardId, bindingData) {
155
+ if (!boardId)
156
+ return;
157
+ try {
158
+ var scene = await this.provider.get(boardId, true);
159
+ var old_scene = this.scene;
160
+ this.scene = scene;
161
+ if (scene.target === this.target) {
162
+ scene.release();
163
+ return;
164
+ }
165
+ if (old_scene) {
166
+ /* old scene을 backward에 보관한다. */
167
+ this.unbindSceneEvents(old_scene);
168
+ /* 원래의 target에 되돌린다. */
169
+ old_scene.target = this._oldtarget;
170
+ this.backward.push(old_scene);
171
+ }
172
+ this.forward.forEach(scene => {
173
+ scene.release();
174
+ });
175
+ /* forward를 비운다. */
176
+ this.forward = [];
177
+ this.setupScene(scene);
178
+ if (bindingData) {
179
+ scene.data = bindingData;
180
+ }
181
+ }
182
+ catch (e) {
183
+ console.error(e);
184
+ }
185
+ }
186
+ bindSceneEvents() {
187
+ this.scene.on('goto', this.onLinkGoto, this);
188
+ this.scene.on('link-open', this.onLinkOpen, this);
189
+ this.scene.on('link-move', this.onLinkMove, this);
190
+ this.scene.on('route-page', this.onRoutePage, this);
191
+ }
192
+ unbindSceneEvents(scene) {
193
+ scene.off('goto', this.onLinkGoto, this);
194
+ scene.off('link-open', this.onLinkOpen, this);
195
+ scene.off('link-move', this.onLinkMove, this);
196
+ scene.off('route-page', this.onRoutePage, this);
197
+ }
198
+ transientShowButtons(stop) {
199
+ var buttons = [];
200
+ !this.hideNavigation && buttons.push(this.next, this.prev);
201
+ !this.hideFullscreen && buttons.push(this.fullscreen);
202
+ if (buttons.length == 0) {
203
+ return;
204
+ }
205
+ if (!this._fade_animations) {
206
+ this._fade_animations = buttons
207
+ .filter(button => button)
208
+ .map(button => {
209
+ let animation = button.animate([
210
+ {
211
+ opacity: 1,
212
+ easing: 'ease-in'
213
+ },
214
+ { opacity: 0 }
215
+ ], { delay: 1000, duration: 2000 });
216
+ animation.onfinish = () => {
217
+ button.setAttribute('hidden', '');
218
+ };
219
+ return animation;
220
+ });
221
+ }
222
+ this.forward.length <= 0 ? this.next.setAttribute('hidden', '') : this.next.removeAttribute('hidden');
223
+ this.backward.length <= 0 ? this.prev.setAttribute('hidden', '') : this.prev.removeAttribute('hidden');
224
+ this.fullscreen && this.fullscreen.removeAttribute('hidden');
225
+ this._fade_animations.forEach(animation => {
226
+ animation.cancel();
227
+ if (stop)
228
+ return;
229
+ animation.play();
230
+ });
231
+ }
232
+ /* event handlers */
233
+ onTapNext() {
234
+ var scene = this.forward.pop();
235
+ if (!scene)
236
+ return;
237
+ if (this.scene) {
238
+ this.scene.target = null;
239
+ /* 원래의 target에 되돌린다. */
240
+ this.scene.target = this._oldtarget;
241
+ this.unbindSceneEvents(this.scene);
242
+ this.backward.push(this.scene);
243
+ }
244
+ this.setupScene(scene);
245
+ }
246
+ onTapPrev() {
247
+ var scene = this.backward.pop();
248
+ if (!scene)
249
+ return;
250
+ if (this.scene) {
251
+ this.scene.target = null;
252
+ /* 원래의 target에 되돌린다. */
253
+ this.scene.target = this._oldtarget;
254
+ this.unbindSceneEvents(this.scene);
255
+ this.forward.push(this.scene);
256
+ }
257
+ this.setupScene(scene);
258
+ }
259
+ onTapFullscreen() {
260
+ togglefullscreen(this, () => {
261
+ this.requestUpdate();
262
+ }, () => {
263
+ this.requestUpdate();
264
+ });
265
+ }
266
+ onLinkGoto(targetBoardId, value, fromComponent) {
267
+ this.showScene(targetBoardId, fromComponent.data);
268
+ }
269
+ onLinkOpen(url, value, fromComponent) {
270
+ if (!url)
271
+ return;
272
+ try {
273
+ window.open(url);
274
+ }
275
+ catch (ex) {
276
+ document.dispatchEvent(new CustomEvent('notify', {
277
+ detail: {
278
+ level: 'error',
279
+ message: ex,
280
+ ex
281
+ }
282
+ }));
283
+ }
284
+ }
285
+ onLinkMove(url, value, fromComponent) {
286
+ if (!url)
287
+ return;
288
+ location.href = url;
289
+ }
290
+ onRoutePage(page) {
291
+ if (!page) {
292
+ return;
293
+ }
294
+ history.pushState({}, '', page);
295
+ window.dispatchEvent(new Event('popstate'));
296
+ }
297
+ async getSceneImageData(base64 = false) {
298
+ if (!this.scene) {
299
+ return;
300
+ }
301
+ var { width, height } = this.scene.model;
302
+ var pixelRatio = window.devicePixelRatio;
303
+ // 1. Scene의 바운드에 근거하여, 오프스크린 캔바스를 만든다.
304
+ var canvas = document.createElement('canvas');
305
+ canvas.width = Number(width);
306
+ canvas.height = Number(height);
307
+ var root = this.scene.root;
308
+ // 2. 모델레이어의 원래 위치와 스케일을 저장한다.
309
+ var translate = root.get('translate');
310
+ var scale = root.get('scale');
311
+ // 3. 위치와 스케일 기본 설정.
312
+ root.set('translate', { x: 0, y: 0 });
313
+ root.set('scale', { x: 1 / pixelRatio, y: 1 / pixelRatio });
314
+ // 4. 오프스크린 캔바스의 Context2D를 구한뒤, 모델레이어를 그 위에 그린다.
315
+ var context = canvas.getContext('2d');
316
+ root.draw(context);
317
+ root.set('translate', translate);
318
+ root.set('scale', scale);
319
+ var data = base64 ? canvas.toDataURL() : context.getImageData(0, 0, width, height).data;
320
+ return {
321
+ width,
322
+ height,
323
+ data
324
+ };
325
+ }
326
+ async printTrick(image) {
327
+ var _a;
328
+ var viewTarget = null;
329
+ var printTarget = null;
330
+ if (!image) {
331
+ image = (_a = (await this.getSceneImageData(true))) === null || _a === void 0 ? void 0 : _a.data;
332
+ }
333
+ printTarget = document.createElement('img');
334
+ printTarget.id = 'target';
335
+ printTarget.src = image;
336
+ printTarget.style.width = '100%';
337
+ printTarget.style.height = '100%';
338
+ const x = (mql) => {
339
+ if (mql.matches) {
340
+ if (!viewTarget) {
341
+ viewTarget = this.shadowRoot.getElementById('target');
342
+ this.renderRoot.replaceChild(printTarget, viewTarget);
343
+ }
344
+ }
345
+ else {
346
+ this.renderRoot.replaceChild(viewTarget, printTarget);
347
+ printTarget.remove();
348
+ mediaQueryList.removeEventListener('change', x);
349
+ }
350
+ };
351
+ if (window.matchMedia) {
352
+ var mediaQueryList = window.matchMedia('print');
353
+ mediaQueryList.addEventListener('change', x);
354
+ }
355
+ }
356
+ };
357
+ BoardViewer.styles = css `
358
+ :host {
359
+ display: flex;
360
+ flex-direction: column;
361
+
362
+ position: relative;
363
+
364
+ width: 100%; /* 전체화면보기를 위해서 필요함. */
365
+ overflow: hidden;
366
+ }
367
+
368
+ #target {
369
+ flex: 1;
370
+
371
+ width: 100%; /* 전체화면보기를 위해서 필요함. */
372
+ height: 100%;
373
+
374
+ outline: 0;
375
+ }
376
+
377
+ /* navigation buttons */
378
+ mwc-icon {
379
+ z-index: 10;
380
+ position: absolute;
381
+ top: 45%;
382
+ min-width: 50px;
383
+ width: 50px;
384
+ height: 50px;
385
+ margin: 0;
386
+ padding: 0;
387
+ color: #fff;
388
+ user-select: none;
389
+
390
+ --mdc-icon-size: 3em;
391
+ }
392
+
393
+ mwc-icon[hidden] {
394
+ display: none;
395
+ }
396
+
397
+ mwc-icon:hover {
398
+ background-color: rgba(0, 0, 0, 0.2);
399
+ border-radius: 50%;
400
+ }
401
+
402
+ #prev {
403
+ left: 5px;
404
+ }
405
+
406
+ #next {
407
+ right: 5px;
408
+ }
409
+
410
+ #fullscreen {
411
+ position: absolute;
412
+ bottom: 15px;
413
+ right: 16px;
414
+ }
415
+
416
+ /* for scroller */
417
+ ::-webkit-scrollbar {
418
+ width: 5px;
419
+ height: 5px;
420
+ }
421
+ ::-webkit-scrollbar-track {
422
+ background-color: transparent;
423
+ }
424
+ ::-webkit-scrollbar-thumb {
425
+ background-color: rgba(0, 0, 0, 0.2);
426
+ }
427
+ ::-webkit-scrollbar-thumb:hover {
428
+ background-color: #aa866a;
429
+ }
430
+
431
+ [hidden] {
432
+ display: none;
433
+ }
434
+
435
+ @media print {
436
+ mwc-fab,
437
+ mwc-icon {
438
+ display: none;
439
+ }
440
+ }
441
+ `;
442
+ __decorate([
443
+ property({ type: String })
444
+ ], BoardViewer.prototype, "baseUrl", void 0);
445
+ __decorate([
446
+ property({ type: Object })
447
+ ], BoardViewer.prototype, "board", void 0);
448
+ __decorate([
449
+ property({ type: Object })
450
+ ], BoardViewer.prototype, "provider", void 0);
451
+ __decorate([
452
+ property({ type: Object })
453
+ ], BoardViewer.prototype, "data", void 0);
454
+ __decorate([
455
+ property({ type: Boolean, reflect: true, attribute: 'hide-fullscreen' })
456
+ ], BoardViewer.prototype, "hideFullscreen", void 0);
457
+ __decorate([
458
+ property({ type: Boolean, reflect: true, attribute: 'hide-navigation' })
459
+ ], BoardViewer.prototype, "hideNavigation", void 0);
460
+ __decorate([
461
+ state()
462
+ ], BoardViewer.prototype, "scene", void 0);
463
+ __decorate([
464
+ state()
465
+ ], BoardViewer.prototype, "forward", void 0);
466
+ __decorate([
467
+ state()
468
+ ], BoardViewer.prototype, "backward", void 0);
469
+ __decorate([
470
+ state()
471
+ ], BoardViewer.prototype, "_oldtarget", void 0);
472
+ __decorate([
473
+ state()
474
+ ], BoardViewer.prototype, "_fade_animations", void 0);
475
+ __decorate([
476
+ query('#target')
477
+ ], BoardViewer.prototype, "target", void 0);
478
+ __decorate([
479
+ query('#prev')
480
+ ], BoardViewer.prototype, "prev", void 0);
481
+ __decorate([
482
+ query('#next')
483
+ ], BoardViewer.prototype, "next", void 0);
484
+ __decorate([
485
+ query('#fullscreen')
486
+ ], BoardViewer.prototype, "fullscreen", void 0);
487
+ BoardViewer = __decorate([
488
+ customElement('ox-board-viewer')
489
+ ], BoardViewer);
490
+ export { BoardViewer };
491
+ //# sourceMappingURL=ox-board-viewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ox-board-viewer.js","sourceRoot":"","sources":["../../src/ox-board-viewer.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/mwc-fab'\nimport '@material/mwc-icon'\n\nimport { LitElement, PropertyValues, css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { create } from '@hatiolab/things-scene'\nimport { isIOS } from './utils/os'\nimport { togglefullscreen } from './utils/fullscreen'\n\n@customElement('ox-board-viewer')\nexport class BoardViewer extends LitElement {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n\n position: relative;\n\n width: 100%; /* 전체화면보기를 위해서 필요함. */\n overflow: hidden;\n }\n\n #target {\n flex: 1;\n\n width: 100%; /* 전체화면보기를 위해서 필요함. */\n height: 100%;\n\n outline: 0;\n }\n\n /* navigation buttons */\n mwc-icon {\n z-index: 10;\n position: absolute;\n top: 45%;\n min-width: 50px;\n width: 50px;\n height: 50px;\n margin: 0;\n padding: 0;\n color: #fff;\n user-select: none;\n\n --mdc-icon-size: 3em;\n }\n\n mwc-icon[hidden] {\n display: none;\n }\n\n mwc-icon:hover {\n background-color: rgba(0, 0, 0, 0.2);\n border-radius: 50%;\n }\n\n #prev {\n left: 5px;\n }\n\n #next {\n right: 5px;\n }\n\n #fullscreen {\n position: absolute;\n bottom: 15px;\n right: 16px;\n }\n\n /* for scroller */\n ::-webkit-scrollbar {\n width: 5px;\n height: 5px;\n }\n ::-webkit-scrollbar-track {\n background-color: transparent;\n }\n ::-webkit-scrollbar-thumb {\n background-color: rgba(0, 0, 0, 0.2);\n }\n ::-webkit-scrollbar-thumb:hover {\n background-color: #aa866a;\n }\n\n [hidden] {\n display: none;\n }\n\n @media print {\n mwc-fab,\n mwc-icon {\n display: none;\n }\n }\n `\n\n @property({ type: String }) baseUrl = ''\n @property({ type: Object }) board: any = {}\n @property({ type: Object }) provider: any = null\n @property({ type: Object }) data = {}\n\n @property({ type: Boolean, reflect: true, attribute: 'hide-fullscreen' }) hideFullscreen = false\n @property({ type: Boolean, reflect: true, attribute: 'hide-navigation' }) hideNavigation = false\n\n @state() scene: any = null\n @state() forward: Array<any> = []\n @state() backward: Array<any> = []\n\n @state() _oldtarget?: HTMLElement\n @state() _fade_animations?: Array<Animation>\n\n @query('#target') target!: HTMLElement\n @query('#prev') prev!: HTMLElement\n @query('#next') next!: HTMLElement\n @query('#fullscreen') fullscreen!: HTMLElement\n\n render() {\n var fullscreen =\n !isIOS() && !this.hideFullscreen\n ? html`\n <mwc-fab\n id=\"fullscreen\"\n .icon=${document.fullscreenElement ? 'fullscreen_exit' : 'fullscreen'}\n @click=${(e: Event) => this.onTapFullscreen()}\n @mouseover=${(e: Event) => this.transientShowButtons(true)}\n @mouseout=${(e: Event) => this.transientShowButtons()}\n title=\"fullscreen\"\n ></mwc-fab>\n `\n : html``\n\n var prev = !this.hideNavigation\n ? html`\n <mwc-icon\n id=\"prev\"\n @click=${(e: Event) => this.onTapPrev()}\n @mouseover=${(e: Event) => this.transientShowButtons(true)}\n @mouseout=${(e: Event) => this.transientShowButtons()}\n hidden\n >keyboard_arrow_left</mwc-icon\n >\n `\n : html``\n\n var next = !this.hideNavigation\n ? html`\n <mwc-icon\n id=\"next\"\n @click=${(e: Event) => this.onTapNext()}\n @mouseover=${(e: Event) => this.transientShowButtons(true)}\n @mouseout=${(e: Event) => this.transientShowButtons()}\n hidden\n >keyboard_arrow_right</mwc-icon\n >\n `\n : html``\n\n return html`\n ${prev}\n\n <div\n id=\"target\"\n @touchstart=${(e: Event) => this.transientShowButtons()}\n @mousemove=${(e: Event) => this.transientShowButtons()}\n ></div>\n\n ${next} ${fullscreen}\n `\n }\n\n firstUpdated() {\n window.addEventListener('resize', () => {\n this.scene && this.scene.fit()\n })\n\n this.renderRoot.addEventListener(\n 'close-scene',\n e => {\n e.preventDefault()\n this.onTapPrev()\n },\n false\n )\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('board')) {\n if (this.board && this.board.id) {\n this.initScene()\n } else {\n this.closeScene()\n }\n }\n\n if (changes.has('data') && this.scene && this.data) {\n this.scene.data = this.data\n }\n }\n\n initScene() {\n if (!this.board || !this.board.id) return\n\n var scene = create({\n model: {\n ...this.board.model\n },\n mode: 0,\n refProvider: this.provider\n })\n\n if (this.baseUrl) {\n scene.baseUrl = this.baseUrl\n }\n\n this.provider.add(this.board.id, scene)\n\n this.showScene(this.board.id)\n\n /* provider.add 시에 추가된 레퍼런스 카운트를 다운시켜주어야 함 */\n scene.release()\n }\n\n closeScene() {\n if (this.scene) {\n this.unbindSceneEvents(this.scene)\n\n this.scene.target = null\n this.scene.release()\n\n delete this.scene\n }\n\n // delete queued scenes\n this.forward.forEach(scene => scene.release())\n this.forward = []\n\n this.backward.forEach(scene => scene.release())\n this.backward = []\n }\n\n releaseScene() {\n if (this.scene) {\n this.unbindSceneEvents(this.scene)\n\n this.scene.target = null\n this.scene.release()\n\n delete this.scene\n\n // delete queued scenes\n this.forward.forEach(scene => {\n scene.release()\n })\n this.forward = []\n\n this.backward.forEach(scene => {\n scene.release()\n })\n this.backward = []\n\n this.transientShowButtons()\n }\n }\n\n setupScene(scene: any) {\n this.scene = scene\n\n /* scene의 기존 target을 보관한다. */\n this._oldtarget = this.scene.target\n\n this.scene.fit(this.board.model.fitMode)\n this.scene.target = this.target\n\n if (this.data) {\n this.scene.data = this.data\n }\n\n this.bindSceneEvents()\n\n this.transientShowButtons()\n }\n\n async showScene(boardId: string, bindingData?: any) {\n if (!boardId) return\n\n try {\n var scene = await this.provider.get(boardId, true)\n\n var old_scene = this.scene\n this.scene = scene\n\n if (scene.target === this.target) {\n scene.release()\n return\n }\n\n if (old_scene) {\n /* old scene을 backward에 보관한다. */\n this.unbindSceneEvents(old_scene)\n /* 원래의 target에 되돌린다. */\n old_scene.target = this._oldtarget\n this.backward.push(old_scene)\n }\n\n this.forward.forEach(scene => {\n scene.release()\n })\n\n /* forward를 비운다. */\n this.forward = []\n\n this.setupScene(scene)\n\n if (bindingData) {\n scene.data = bindingData\n }\n } catch (e) {\n console.error(e)\n }\n }\n\n bindSceneEvents() {\n this.scene.on('goto', this.onLinkGoto, this)\n this.scene.on('link-open', this.onLinkOpen, this)\n this.scene.on('link-move', this.onLinkMove, this)\n this.scene.on('route-page', this.onRoutePage, this)\n }\n\n unbindSceneEvents(scene: any) {\n scene.off('goto', this.onLinkGoto, this)\n scene.off('link-open', this.onLinkOpen, this)\n scene.off('link-move', this.onLinkMove, this)\n scene.off('route-page', this.onRoutePage, this)\n }\n\n transientShowButtons(stop?: boolean) {\n var buttons = []\n !this.hideNavigation && buttons.push(this.next, this.prev)\n !this.hideFullscreen && buttons.push(this.fullscreen)\n\n if (buttons.length == 0) {\n return\n }\n\n if (!this._fade_animations) {\n this._fade_animations = buttons\n .filter(button => button)\n .map(button => {\n let animation = button.animate(\n [\n {\n opacity: 1,\n easing: 'ease-in'\n },\n { opacity: 0 }\n ],\n { delay: 1000, duration: 2000 }\n )\n\n animation.onfinish = () => {\n button.setAttribute('hidden', '')\n }\n\n return animation\n })\n }\n\n this.forward.length <= 0 ? this.next.setAttribute('hidden', '') : this.next.removeAttribute('hidden')\n this.backward.length <= 0 ? this.prev.setAttribute('hidden', '') : this.prev.removeAttribute('hidden')\n this.fullscreen && this.fullscreen.removeAttribute('hidden')\n\n this._fade_animations.forEach(animation => {\n animation.cancel()\n if (stop) return\n\n animation.play()\n })\n }\n\n /* event handlers */\n\n onTapNext() {\n var scene = this.forward.pop()\n if (!scene) return\n\n if (this.scene) {\n this.scene.target = null\n /* 원래의 target에 되돌린다. */\n this.scene.target = this._oldtarget\n this.unbindSceneEvents(this.scene)\n this.backward.push(this.scene)\n }\n\n this.setupScene(scene)\n }\n\n onTapPrev() {\n var scene = this.backward.pop()\n if (!scene) return\n\n if (this.scene) {\n this.scene.target = null\n /* 원래의 target에 되돌린다. */\n this.scene.target = this._oldtarget\n this.unbindSceneEvents(this.scene)\n this.forward.push(this.scene)\n }\n\n this.setupScene(scene)\n }\n\n onTapFullscreen() {\n togglefullscreen(\n this,\n () => {\n this.requestUpdate()\n },\n () => {\n this.requestUpdate()\n }\n )\n }\n\n onLinkGoto(targetBoardId: string, value: any, fromComponent: any) {\n this.showScene(targetBoardId, fromComponent.data)\n }\n\n onLinkOpen(url: string, value: any, fromComponent: any) {\n if (!url) return\n\n try {\n window.open(url)\n } catch (ex) {\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n level: 'error',\n message: ex,\n ex\n }\n })\n )\n }\n }\n\n onLinkMove(url: string, value: any, fromComponent: any) {\n if (!url) return\n\n location.href = url\n }\n\n onRoutePage(page: string) {\n if (!page) {\n return\n }\n\n history.pushState({}, '', page)\n window.dispatchEvent(new Event('popstate'))\n }\n\n async getSceneImageData(base64 = false) {\n if (!this.scene) {\n return\n }\n\n var { width, height } = this.scene.model\n var pixelRatio = window.devicePixelRatio\n\n // 1. Scene의 바운드에 근거하여, 오프스크린 캔바스를 만든다.\n var canvas = document.createElement('canvas')\n canvas.width = Number(width)\n canvas.height = Number(height)\n\n var root = this.scene.root\n // 2. 모델레이어의 원래 위치와 스케일을 저장한다.\n var translate = root.get('translate')\n var scale = root.get('scale')\n\n // 3. 위치와 스케일 기본 설정.\n root.set('translate', { x: 0, y: 0 })\n root.set('scale', { x: 1 / pixelRatio, y: 1 / pixelRatio })\n\n // 4. 오프스크린 캔바스의 Context2D를 구한뒤, 모델레이어를 그 위에 그린다.\n var context = canvas.getContext('2d')\n\n root.draw(context)\n\n root.set('translate', translate)\n root.set('scale', scale)\n\n var data = base64 ? canvas.toDataURL() : context!.getImageData(0, 0, width, height).data\n\n return {\n width,\n height,\n data\n }\n }\n\n async printTrick(image: string) {\n var viewTarget: HTMLElement | null = null\n var printTarget: HTMLImageElement | null = null\n\n if (!image) {\n image = (await this.getSceneImageData(true))?.data as string\n }\n\n printTarget = document.createElement('img')\n printTarget.id = 'target'\n printTarget.src = image\n printTarget.style.width = '100%'\n printTarget.style.height = '100%'\n\n const x = (mql: MediaQueryListEvent) => {\n if (mql.matches) {\n if (!viewTarget) {\n viewTarget = this.shadowRoot!.getElementById('target')\n this.renderRoot.replaceChild(printTarget!, viewTarget!)\n }\n } else {\n this.renderRoot.replaceChild(viewTarget!, printTarget!)\n printTarget!.remove()\n mediaQueryList.removeEventListener('change', x)\n }\n }\n\n if (window.matchMedia) {\n var mediaQueryList = window.matchMedia('print')\n mediaQueryList.addEventListener('change', x)\n }\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,88 @@
1
+ import { __decorate } from "tslib";
2
+ import { LitElement, css, html } from 'lit';
3
+ import { customElement, property, query, state } from 'lit/decorators.js';
4
+ /**
5
+ * @class BoardWrapper
6
+ *
7
+ * @description scene provider로부터 제공받은 scene의 reference count control을 담당하며, resize 이벤트 발생시 scene의 사이즈를 fit 시키는 역할을 담당한다.
8
+ */
9
+ let BoardWrapper = class BoardWrapper extends LitElement {
10
+ render() {
11
+ return html ` <div id="target"></div> `;
12
+ }
13
+ connectedCallback() {
14
+ super.connectedCallback();
15
+ window.addEventListener('resize', () => {
16
+ requestAnimationFrame(() => {
17
+ if (this._scene) {
18
+ this._scene.resize();
19
+ if (this.offsetWidth) {
20
+ this._scene.fit();
21
+ }
22
+ }
23
+ });
24
+ });
25
+ }
26
+ disconnectedCallback() {
27
+ super.disconnectedCallback();
28
+ this._releaseRef();
29
+ }
30
+ updated(changes) {
31
+ changes.has('sceneId') && this._onSceneIdChanged();
32
+ }
33
+ _releaseRef() {
34
+ if (this._scene) {
35
+ this._scene.target = null;
36
+ this._scene.release();
37
+ delete this._scene;
38
+ }
39
+ }
40
+ _onSceneIdChanged() {
41
+ if (!this.provider)
42
+ return;
43
+ this._releaseRef();
44
+ if (!this.sceneId)
45
+ return;
46
+ this.provider.get(this.sceneId, true).then((scene) => {
47
+ this._scene = scene;
48
+ this._scene.target = this._targetEl;
49
+ /* 이 컴포넌트의 폭이 값을 가지고 있으면 - 화면상에 자리를 잡고 보여지고 있음을 의미한다.
50
+ * 이 때는 정상적으로 그려주고,
51
+ * 그렇지 않으면, 다음 Resize Handling시에 처리하도록 한다.
52
+ */
53
+ if (this._scene.target.offsetWidth) {
54
+ this._scene.fit();
55
+ }
56
+ }, (e) => { });
57
+ }
58
+ };
59
+ BoardWrapper.styles = [
60
+ css `
61
+ :host {
62
+ position: relative;
63
+ }
64
+
65
+ #target {
66
+ display: block;
67
+ width: 100%;
68
+ height: 100%;
69
+ outline: 0;
70
+ }
71
+ `
72
+ ];
73
+ __decorate([
74
+ property({ type: String })
75
+ ], BoardWrapper.prototype, "sceneId", void 0);
76
+ __decorate([
77
+ property({ type: Object })
78
+ ], BoardWrapper.prototype, "provider", void 0);
79
+ __decorate([
80
+ state()
81
+ ], BoardWrapper.prototype, "_scene", void 0);
82
+ __decorate([
83
+ query('#target')
84
+ ], BoardWrapper.prototype, "_targetEl", void 0);
85
+ BoardWrapper = __decorate([
86
+ customElement('ox-board-wrapper')
87
+ ], BoardWrapper);
88
+ //# sourceMappingURL=ox-board-wrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ox-board-wrapper.js","sourceRoot":"","sources":["../../src/ox-board-wrapper.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAkB,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEzE;;;;GAIG;AAEH,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,UAAU;IAuBnC,MAAM;QACJ,OAAO,IAAI,CAAA,2BAA2B,CAAA;IACxC,CAAC;IAED,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEzB,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;YACrC,qBAAqB,CAAC,GAAG,EAAE;gBACzB,IAAI,IAAI,CAAC,MAAM,EAAE;oBACf,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;oBAEpB,IAAI,IAAI,CAAC,WAAW,EAAE;wBACpB,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAA;qBAClB;iBACF;YACH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,oBAAoB;QAClB,KAAK,CAAC,oBAAoB,EAAE,CAAA;QAE5B,IAAI,CAAC,WAAW,EAAE,CAAA;IACpB,CAAC;IAED,OAAO,CAAC,OAA6B;QACnC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAA;IACpD,CAAC;IAED,WAAW;QACT,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAA;YACzB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;YACrB,OAAO,IAAI,CAAC,MAAM,CAAA;SACnB;IACH,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAM;QAC1B,IAAI,CAAC,WAAW,EAAE,CAAA;QAElB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QAEzB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,CACxC,CAAC,KAAU,EAAE,EAAE;YACb,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;YACnB,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAA;YAEnC;;;eAGG;YACH,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE;gBAClC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAA;aAClB;QACH,CAAC,EACD,CAAC,CAAM,EAAE,EAAE,GAAE,CAAC,CACf,CAAA;IACH,CAAC;CACF,CAAA;AAlFQ,mBAAM,GAAG;IACd,GAAG,CAAA;;;;;;;;;;;KAWF;CACF,CAAA;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;6CAAiB;AAChB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CAAe;AAEjC;IAAR,KAAK,EAAE;4CAAY;AAEF;IAAjB,KAAK,CAAC,SAAS,CAAC;+CAAwB;AArBrC,YAAY;IADjB,aAAa,CAAC,kBAAkB,CAAC;GAC5B,YAAY,CAmFjB","sourcesContent":["import { LitElement, PropertyValues, css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\n/**\n * @class BoardWrapper\n *\n * @description scene provider로부터 제공받은 scene의 reference count control을 담당하며, resize 이벤트 발생시 scene의 사이즈를 fit 시키는 역할을 담당한다.\n */\n@customElement('ox-board-wrapper')\nclass BoardWrapper extends LitElement {\n static styles = [\n css`\n :host {\n position: relative;\n }\n\n #target {\n display: block;\n width: 100%;\n height: 100%;\n outline: 0;\n }\n `\n ]\n\n @property({ type: String }) sceneId!: string\n @property({ type: Object }) provider!: any\n\n @state() _scene: any\n\n @query('#target') _targetEl!: HTMLElement\n\n render() {\n return html` <div id=\"target\"></div> `\n }\n\n connectedCallback() {\n super.connectedCallback()\n\n window.addEventListener('resize', () => {\n requestAnimationFrame(() => {\n if (this._scene) {\n this._scene.resize()\n\n if (this.offsetWidth) {\n this._scene.fit()\n }\n }\n })\n })\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n\n this._releaseRef()\n }\n\n updated(changes: PropertyValues<this>) {\n changes.has('sceneId') && this._onSceneIdChanged()\n }\n\n _releaseRef() {\n if (this._scene) {\n this._scene.target = null\n this._scene.release()\n delete this._scene\n }\n }\n\n _onSceneIdChanged() {\n if (!this.provider) return\n this._releaseRef()\n\n if (!this.sceneId) return\n\n this.provider.get(this.sceneId, true).then(\n (scene: any) => {\n this._scene = scene\n this._scene.target = this._targetEl\n\n /* 이 컴포넌트의 폭이 값을 가지고 있으면 - 화면상에 자리를 잡고 보여지고 있음을 의미한다.\n * 이 때는 정상적으로 그려주고,\n * 그렇지 않으면, 다음 Resize Handling시에 처리하도록 한다.\n */\n if (this._scene.target.offsetWidth) {\n this._scene.fit()\n }\n },\n (e: any) => {}\n )\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ import './board-player-grid';