Passed
Push — main ( 1b309e...40b6fc )
by Dylan
04:20
created

Jrid   F

Complexity

Total Complexity 75

Size/Duplication

Total Lines 30
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 75
eloc 20
dl 0
loc 30
rs 2.4
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like Jrid often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import VERSION from './version'
2
import preact, { createRef, FunctionalComponent, render } from 'preact'
3
import { useEffect } from 'preact/hooks'
4
import Canvas, { CanvasMethods } from './canvas'
5
// import style from './style.css'
6
7
const logBase = 10
8
const zoomFactor = logBase**(1/13)
9
const microZoomFactor = zoomFactor**(1/32)
10
const minimumJridSpacing = 24
11
const μ = .75
12
const translateFactor = 16
13
let free = true
14
15
export const axisLabelFormat = (coefficient: number, exponent: number): string => {
16
  if (coefficient === 0) return '0'
17
  // simple notation for small exponents
18
  if (exponent < 5) {
19
    // @todo i18n eg. toLocaleString
20
    if (exponent >= 0) {
21
      // 1...10,000
22
      return `${coefficient}${'0'.repeat(exponent)}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
23
    }
24
    if (exponent > -5) {
25
      // 0...0.0001
26
      return (coefficient*logBase**exponent).toFixed(-exponent)
27
    }
28
  }
29
  // pseudoscientific notation, eg. 5×⏨42 for 5*10^42
30
  return `${coefficient}×⏨${exponent}`
31
}
32
33
type TranslateFunction = (x: number, y: number) => void
34
35
type ScaleFunction = (x: number, y: number) => void
36
37
export interface JridOverlayProps {
38
  canvasMethodRefs?: CanvasMethods;
39
  setTranslate?: TranslateFunction;
40
  setScale?: ScaleFunction;
41
  initialScale?: number;
42
}
43
44
export const JridOverlay: FunctionalComponent<JridOverlayProps> = (props: JridOverlayProps) => {
45
  const { setTranslate, setScale, ...rest } = props
46
  const ref = createRef()
47
  const canvasCenter = [0, 0]
48
  const translate = [0, 0]
49
  const scale = [1, 1]
50
  const velocity = [0, 0]
51
  const fontSize = 12
52
  const axisLabelMargin = 4
53
  // const xLabelOffset = [-axisLabelMargin, fontSize+axisLabelMargin] // incorrect with rotation
54
  const xLabelOffset = [-2, 10]
55
  const yLabelOffset = [-axisLabelMargin, -axisLabelMargin]
56
  let contextHeight = 0
57
58
  const init = (ctx: CanvasRenderingContext2D): void => {
59
    const initialScale = rest.initialScale ?? 16/ctx.canvas.width
60
    scale[0] = scale[1] = initialScale
61
    if (setScale) {
62
      setScale(scale[0], scale[1])
63
    }
64
    draw(ctx)
65
  }
66
67
  const onResize = (ctx: CanvasRenderingContext2D): void => {
68
69
    // line styles
70
    ctx.strokeStyle = '#999'
71
    ctx.lineWidth = 1
72
    
73
    // text styles
74
    ctx.fillStyle = '#999'
75
    ctx.textAlign = 'right'
76
    ctx.font = `${fontSize}px monospace`
77
    // @todo white on white bg in unreadable
78
    // shadowBlur works ok but is too slow in Firefox
79
    // ctx.shadowColor = 'rgba(0,0,0,1)'
80
    // ctx.shadowBlur = 4
81
82
    contextHeight = ctx.canvas.height
83
    const halfWidth = ctx.canvas.width/2
84
    const halfHeight = ctx.canvas.height/2
85
    if (typeof canvasCenter[0] === 'undefined' || typeof canvasCenter[1] === 'undefined') {
86
      console.error('Not too centred there bud!')
87
    }
88
    else if (canvasCenter[0] === 0) {
89
      // initially translate (0,0) to center of canvas
90
      canvasCenter[0] = halfWidth
91
      canvasCenter[1] = halfHeight
92
      translate[0] = -canvasCenter[0]
93
      translate[1] = -canvasCenter[1]
94
    }
95
    else {
96
      // adjust translation by difference in canvas size
97
      const dx = halfWidth - canvasCenter[0]
98
      const dy = halfHeight - canvasCenter[1]
99
      translate[0] -= dx
100
      translate[1] -= dy
101
      canvasCenter[0] = halfWidth
102
      canvasCenter[1] = halfHeight
103
    }
104
    draw(ctx)
105
  }
106
107
  const render = (): void => {
108
    void(0)
109
  }
110
111
  const draw = (ctx: CanvasRenderingContext2D): void => {
112
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
113
114
    // slow down due to friction
115
    velocity[0] *= μ
116
    velocity[1] *= μ
117
118
    // glide
119
    if (free) {
120
      if (typeof velocity[0] === 'undefined' || typeof velocity[1] === 'undefined') {
121
        console.error('Not too veloed there bud!')
122
      }
123
      else {
124
        translate[0] += velocity[0]
125
        translate[1] -= velocity[1]
126
      }
127
    }
128
129
    // fu typescript
130
    if (typeof scale[0] === 'undefined' || typeof scale[1] === 'undefined') {
131
      console.error('Not too velo there bud!')
132
      return
133
    }
134
    if (typeof translate[0] === 'undefined' || typeof translate[1] === 'undefined') {
135
      console.error('Not too trans there bud!')
136
      return
137
    }
138
    if (typeof yLabelOffset[0] === 'undefined' || typeof yLabelOffset[1] === 'undefined') {
139
      console.error('Not too why offset there bud!')
140
      return
141
    }
142
    if (typeof xLabelOffset[0] === 'undefined' || typeof xLabelOffset[1] === 'undefined') {
143
      console.error('Not too X offset there bud!')
144
      return
145
    }
146
    
147
    // exponent for axis labels ⏨(n+x)
148
    const powerX = Math.ceil(Math.log10(minimumJridSpacing * scale[0]))
149
    const powerY = Math.ceil(Math.log10(minimumJridSpacing * scale[1]))
150
    const factorX = 10**powerX
151
    const factorY = 10**powerY
152
153
    // set space between lines
154
    const spaceX = factorX / scale[0]
155
    const spaceY = factorY / scale[1]
156
157
    // get first lines by rounding up
158
    const xIndexOffset = Math.ceil(translate[0] * scale[0] / factorX)
159
    const yIndexOffset = Math.ceil(translate[1] * scale[1] / factorY) 
160
    const firstXValue = xIndexOffset * factorX
161
    const firstYValue = yIndexOffset * factorY
162
    const firstXPosition = firstXValue / scale[0] - translate[0]
163
    const firstYPosition = translate[1] - firstYValue / scale[1]
164
    
165
    // lines to write labels on
166
    const xLineCount = Math.floor(ctx.canvas.width / spaceX)
167
    const yLineCount = Math.floor(ctx.canvas.height / spaceY)
168
    const xMiddleLineIndex = Math.floor(xLineCount / 2)
169
    const yMiddleLineIndex = Math.floor(yLineCount / 2)
170
171
    ctx.beginPath()
172
    // draw x-axis Jrid lines
173
    for (let i=0; i<=xLineCount; i++) {
174
      const x = firstXPosition + i * spaceX
175
      ctx.moveTo(x, 0)
176
      ctx.lineTo(x, ctx.canvas.height)
177
      // draw y-axis labels up the middle line
178
      if (i === xMiddleLineIndex) {
179
        for (let j=0; j<=yLineCount; j++) {
180
          const label = axisLabelFormat(j + yIndexOffset, powerY)
181
          const y = firstYPosition + ctx.canvas.height - j * spaceY
182
          ctx.fillText(label, x + yLabelOffset[0], y + yLabelOffset[1])
183
        }
184
      }
185
    }
186
    // draw y-axis Jrid lines
187
    for (let i=0; i<=yLineCount; i++) {
188
      const y = firstYPosition + ctx.canvas.height - i * spaceY
189
      ctx.moveTo(0, y)
190
      ctx.lineTo(ctx.canvas.width, y)
191
      // draw x-axis labels below the middle line
192
      if (i === yMiddleLineIndex) {
193
        for (let j=0; j<=xLineCount; j++) {
194
          const label = axisLabelFormat(j + xIndexOffset, powerX)
195
          const x = firstXPosition + j * spaceX
196
197
          // rotate, to avoid overlap with long labels and small Jrid
198
          ctx.save()
199
          ctx.translate(x + xLabelOffset[0], y + xLabelOffset[1])
200
          ctx.rotate(-Math.PI/6)
201
          ctx.fillText(label, 0, 0)
202
          ctx.restore()
203
204
          // without rotate:
205
          // ctx.fillText(label, x + xLabelOffset[0], y + xLabelOffset[1])
206
207
        }
208
      }
209
    }
210
    ctx.stroke()
211
212
    // update position of main canvas
213
    if (setTranslate) {
214
      setTranslate(translate[0], translate[1])
215
    }
216
  }
217
218
  useEffect(() => {
219
    // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
220
    const canvasEl = ref.current.base as HTMLCanvasElement
221
    let mouseDown = 0
222
    let renderCallbackID: number
223
    const lastMousePosition = [0, 0]
224
    const lastTouch1Position = [-1, -1]
225
    const lastTouch2Position = [-1, -1]
226
227
    const handleMouseDown = (event: MouseEvent): boolean => {
228
      mouseDown |= (1<<event.button)
229
      lastMousePosition[0] = event.clientX
230
      lastMousePosition[1] = event.clientY
231
      velocity[0] = velocity[1] = 0
232
      free = !(mouseDown&1)
233
      event.preventDefault()
234
      return false
235
    }
236
    canvasEl.addEventListener('mousedown', handleMouseDown)
237
238
    const handleMouseUp = (event: MouseEvent): boolean => {
239
      mouseDown ^= (1<<event.button)
240
      event.preventDefault()
241
      free = !(mouseDown&1)
242
      return false
243
    }
244
    canvasEl.addEventListener('mouseup', handleMouseUp)
245
246
    const handleContextMenu = (event: MouseEvent): boolean => {
247
      event.preventDefault()
248
      return false
249
    }
250
    canvasEl.addEventListener('contextmenu', handleContextMenu)
251
252
    const handleMouseMove = (event: MouseEvent): void => {
253
      if (typeof lastMousePosition[0] === 'undefined' || typeof lastMousePosition[1] === 'undefined') return
254
      if (typeof translate[0] === 'undefined' || typeof translate[1] === 'undefined') return
255
      if (typeof scale[0] === 'undefined' || typeof scale[1] === 'undefined') return
256
      const dx = lastMousePosition[0] - event.clientX
257
      const dy = lastMousePosition[1] - event.clientY
258
      const flingFactor = 4
259
      // left-clicked, translate
260
      if (mouseDown&1) {
261
        velocity[0] = dx * flingFactor
262
        velocity[1] = dy * flingFactor
263
        translate[0] += dx
264
        translate[1] -= dy
265
        if (setTranslate) {
266
          setTranslate(translate[0], translate[1])
267
          render()
268
        }
269
      }
270
      // middle-clicked, scale all axes
271
      if (mouseDown&2) {
272
        const f = microZoomFactor**-dy
273
        scale[0] *= f
274
        scale[1] *= f
275
        if (setScale) {
276
          setScale(scale[0], scale[1])
277
          render()
278
        } 
279
      }
280
      // right-clicked, scale individual axes
281
      if (mouseDown&4) {
282
        const zoomTo = [
283
          (lastMousePosition[0] + translate[0]) * scale[0],
284
          (contextHeight - lastMousePosition[1] + translate[1]) * scale[1]
285
        ]
286
        if (typeof zoomTo[0] === 'undefined' || typeof zoomTo[1] === 'undefined') return
287
        const zoomLastPosition = [
288
          zoomTo[0] / scale[0] - translate[0],
289
          zoomTo[1] / scale[1] - translate[1]
290
        ]
291
        if (typeof zoomLastPosition[0] === 'undefined' || typeof zoomLastPosition[1] === 'undefined') return
292
        scale[0] *= microZoomFactor**dx
293
        scale[1] *= microZoomFactor**-dy
294
        if (setScale) {
295
          setScale(scale[0], scale[1])
296
        }
297
        const zoomToPosition = [
298
          zoomTo[0] / scale[0] - translate[0],
299
          zoomTo[1] / scale[1] - translate[1]
300
        ]
301
        if (typeof zoomToPosition[0] === 'undefined' || typeof zoomToPosition[1] === 'undefined') return
302
        translate[0] -= zoomLastPosition[0] - zoomToPosition[0] - dx
303
        translate[1] += zoomToPosition[1] - zoomLastPosition[1] - dy
304
        if (setTranslate) {
305
          setTranslate(translate[0], translate[1])
306
        }
307
        render()
308
      }
309
      lastMousePosition[0] = event.clientX
310
      lastMousePosition[1] = event.clientY
311
    }
312
    canvasEl.addEventListener('mousemove', handleMouseMove)
313
314
    const handleTouchDown = (event: TouchEvent): boolean => {
315
      if (typeof event.touches[0] === 'undefined') return false
316
      lastTouch1Position[0] = event.touches[0].pageX
317
      lastTouch1Position[1] = event.touches[0].pageY
318
      velocity[0] = velocity[1] = 0
319
      free = false
320
      return false
321
    }
322
    canvasEl.addEventListener('touchstart', handleTouchDown)
323
324
    const handleTouchUp = (event: TouchEvent): boolean => {
325
      void(event)
326
      lastTouch1Position[0] = lastTouch1Position[1] = -1
327
      free = true
328
      return false
329
    }
330
    canvasEl.addEventListener('touchend', handleTouchUp)
331
332
    const handleTouchMove = (event: TouchEvent): void => {
333
      if (typeof lastTouch1Position[0] === 'undefined' || typeof lastTouch1Position[1] === 'undefined') return
334
      if (typeof lastTouch2Position[0] === 'undefined' || typeof lastTouch2Position[1] === 'undefined') return
335
      if (typeof translate[0] === 'undefined' || typeof translate[1] === 'undefined') return
336
      if (typeof scale[0] === 'undefined' || typeof scale[1] === 'undefined') return
337
      if (typeof event.touches[0] === 'undefined' || typeof event.touches[1] === 'undefined') return
338
      if (lastTouch1Position[0] > -1) {
339
        if (event.touches.length===1) {
340
          const dx = lastTouch1Position[0] - event.touches[0].pageX
341
          const dy = lastTouch1Position[1] - event.touches[0].pageY
342
          velocity[0] = dx
343
          velocity[1] = dy
344
          translate[0] += dx
345
          translate[1] -= dy
346
          lastTouch2Position[0] = lastTouch2Position[1] = -1
347
          if (setTranslate) {
348
            setTranslate(translate[0], translate[1])
349
            render()
350
          }
351
        }
352
        else {
353
          if (lastTouch2Position[0] > -1) {
354
            const x1 = event.touches[0].pageX
355
            const y1 = event.touches[0].pageY
356
            const x2 = event.touches[1].pageX
357
            const y2 = event.touches[1].pageY
358
            const q1 = (lastTouch1Position[0] - lastTouch2Position[0])**2 + (lastTouch1Position[1] - lastTouch2Position[1])**2
359
            const q2 = (x1 - x2)**2 + (y1 - y2)**2
360
            const zoomModifier = q1 / q2
361
            const touchMidpoint = [
362
              (x1 + x2) / 2,
363
              (y1 + y2) / 2
364
            ]
365
            if (typeof touchMidpoint[0] === 'undefined' || typeof touchMidpoint[1] === 'undefined') return
366
            const zoomTo = [
367
              (touchMidpoint[0] + translate[0]) * scale[0],
368
              (contextHeight - touchMidpoint[1] + translate[1]) * scale[1]
369
            ]
370
            if (typeof zoomTo[0] === 'undefined' || typeof zoomTo[1] === 'undefined') return
371
            const zoomLastPosition = [
372
              zoomTo[0] / scale[0] - translate[0],
373
              zoomTo[1] / scale[1] - translate[1]
374
            ]
375
            if (typeof zoomLastPosition[0] === 'undefined' || typeof zoomLastPosition[1] === 'undefined') return
376
            scale[0] *= zoomModifier
377
            scale[1] *= zoomModifier
378
            if (setScale) {
379
              setScale(scale[0], scale[1])
380
            }
381
            const zoomToPosition = [
382
              zoomTo[0] / scale[0] - translate[0],
383
              zoomTo[1] / scale[1] - translate[1]
384
            ]
385
            if (typeof zoomToPosition[0] === 'undefined' || typeof zoomToPosition[1] === 'undefined') return
386
            translate[0] -= zoomLastPosition[0] - zoomToPosition[0]
387
            translate[1] += zoomToPosition[1] - zoomLastPosition[1]
388
            if (setTranslate) {
389
              setTranslate(translate[0], translate[1])
390
            }
391
            render()
392
          }
393
          lastTouch2Position[0] = event.touches[1].pageX
394
          lastTouch2Position[1] = event.touches[1].pageY
395
        }
396
      }
397
      lastTouch1Position[0] = event.touches[0].pageX
398
      lastTouch1Position[1] = event.touches[0].pageY
399
    }
400
    canvasEl.addEventListener('touchmove', handleTouchMove)
401
402
    const handleWheel = (event: WheelEvent): void => {
403
      const zoomModifier = event.deltaY > 0 ? zoomFactor : 1/zoomFactor
404
      if (typeof lastMousePosition[0] === 'undefined' || typeof lastMousePosition[1] === 'undefined') return
405
      if (typeof translate[0] === 'undefined' || typeof translate[1] === 'undefined') return
406
      if (typeof scale[0] === 'undefined' || typeof scale[1] === 'undefined') return
407
      const zoomTo = [
408
        (lastMousePosition[0] + translate[0]) * scale[0],
409
        (contextHeight - lastMousePosition[1] + translate[1]) * scale[1]
410
      ]
411
      if (typeof zoomTo[0] === 'undefined' || typeof zoomTo[1] === 'undefined') return
412
      const zoomLastPosition = [
413
        zoomTo[0] / scale[0] - translate[0],
414
        zoomTo[1] / scale[1] - translate[1]
415
      ]
416
      if (typeof zoomLastPosition[0] === 'undefined' || typeof zoomLastPosition[1] === 'undefined') return
417
      scale[0] *= zoomModifier
418
      scale[1] *= zoomModifier
419
      if (setScale) {
420
        setScale(scale[0], scale[1])
421
      }
422
      const zoomToPosition = [
423
        zoomTo[0] / scale[0] - translate[0],
424
        zoomTo[1] / scale[1] - translate[1]
425
      ]
426
      if (typeof zoomToPosition[0] === 'undefined' || typeof zoomToPosition[1] === 'undefined') return
427
      translate[0] -= zoomLastPosition[0] - zoomToPosition[0]
428
      translate[1] += zoomToPosition[1] - zoomLastPosition[1]
429
      if (setTranslate) {
430
        setTranslate(translate[0], translate[1])
431
      }
432
      render()
433
    }
434
    canvasEl.addEventListener('wheel', handleWheel)
435
436
    const handleKeyDown = (event: KeyboardEvent): void => {
437
      if (typeof canvasCenter[0] === 'undefined' || typeof canvasCenter[1] === 'undefined') return
438
      if (typeof scale[0] === 'undefined' || typeof scale[1] === 'undefined') return
439
      switch (event.code) {
440
  
441
      case 'KeyW':
442
      case 'ArrowUp':
443
      case 'Numpad8':
444
        translate[1] -= translateFactor * zoomFactor
445
        break
446
            
447
      case 'KeyS':
448
      case 'ArrowDown':
449
      case 'Numpad2':
450
        translate[1] += translateFactor * zoomFactor
451
        break
452
             
453
      case 'KeyA':
454
      case 'ArrowLeft':
455
      case 'Numpad4':
456
        translate[0] += translateFactor * zoomFactor
457
        break
458
            
459
      case 'KeyD':
460
      case 'ArrowRight':
461
      case 'Numpad6':
462
        translate[0] -= translateFactor * zoomFactor
463
        break
464
465
      case 'KeyE':
466
      case 'Numpad9':
467
        translate[1] -= translateFactor * zoomFactor
468
        translate[0] -= translateFactor * zoomFactor
469
        break
470
            
471
      case 'KeyC':
472
      case 'Numpad3':
473
        translate[1] += translateFactor * zoomFactor
474
        translate[0] -= translateFactor * zoomFactor
475
        break
476
              
477
      case 'KeyZ':
478
      case 'Numpad1':
479
        translate[0] += translateFactor * zoomFactor
480
        translate[1] += translateFactor * zoomFactor
481
        break
482
            
483
      case 'KeyQ':
484
      case 'Numpad7':
485
        translate[0] += translateFactor * zoomFactor
486
        translate[1] -= translateFactor * zoomFactor
487
        break
488
489
      case 'Space':
490
      case 'KeyO':
491
      case 'Numpad5':
492
        translate[0] = -canvasCenter[0]
493
        translate[1] = -canvasCenter[1]
494
        break
495
    
496
      case 'KeyX':
497
      case 'Numpad0':
498
        translate[0] = translate[1] = 0
499
        break
500
501
      case 'NumpadSubtract':
502
      case 'Minus':
503
        scale[0] *= zoomFactor
504
        scale[1] *= zoomFactor
505
        if (setScale) {
506
          setScale(scale[0], scale[1])
507
          render()
508
        } 
509
        break
510
 
511
      case 'NumpadAdd':
512
      case 'Equal':
513
        scale[0] /= zoomFactor
514
        scale[1] /= zoomFactor
515
        if (setScale) {
516
          setScale(scale[0], scale[1])
517
          render()
518
        } 
519
        break
520
521
      case 'NumpadDivide':
522
      case 'BracketRight':
523
        scale[0] /= logBase
524
        scale[1] /= logBase
525
        if (setScale) {
526
          setScale(scale[0], scale[1])
527
          render()
528
        }
529
        break
530
    
531
      case 'NumpadMultiply':
532
      case 'BracketLeft':
533
        scale[0] *= logBase
534
        scale[1] *= logBase
535
        if (setScale) {
536
          setScale(scale[0], scale[1])
537
          render()
538
        } 
539
        break
540
  
541
      case 'Period':
542
      case 'NumpadDecimal':
543
        {
544
          const initialScale = rest.initialScale ?? 8/ ( canvasCenter[0] ?? 1 )
545
          scale[0] = scale[1] = initialScale
546
          if (setScale) {
547
            setScale(scale[0], scale[1])
548
          }
549
        }
550
        break
551
        
552
553
      case 'Escape':
554
      case 'Backspace':
555
        window.location.reload()
556
        break
557
                
558
      }
559
    }
560
    window.addEventListener('keydown', handleKeyDown)
561
562
    return (): void => {
563
      window.cancelAnimationFrame(renderCallbackID)
564
      canvasEl.removeEventListener('mousedown', handleMouseDown)
565
      canvasEl.removeEventListener('mouseup', handleMouseUp)
566
      canvasEl.removeEventListener('contextmenu', handleContextMenu)
567
      canvasEl.removeEventListener('mousemove', handleMouseMove)
568
      canvasEl.removeEventListener('touchstart', handleTouchDown)
569
      canvasEl.removeEventListener('touchend', handleTouchUp)
570
      canvasEl.removeEventListener('touchmove', handleTouchMove)
571
      window.removeEventListener('keydown', handleKeyDown)
572
    }
573
574
  }, [ref])
575
576
  return (
577
    <Canvas 
578
      ref={ref}
579
      className="jrid"
580
      init={init}
581
      onResize={onResize}
582
      draw={draw}
583
      animate={true}
584
      {...rest}
585
    />
586
  )
587
}
588
589
interface JridState {
590
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
591
  [index: string]: any;
592
  locale: string;
593
  setTranslate?: TranslateFunction;
594
  setScale?: ScaleFunction;
595
}
596
597
const JridDefaultState: JridState = {
598
  locale: 'en-CA',
599
  setTranslate: function() {alert('t!')},
600
  setScale: function() {alert('s!')}
601
}
602
603
export interface JridSettings {
604
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
605
  [index: string]: any;
606
  locale?: string;
607
  setTranslate?: TranslateFunction;
608
  setScale?: ScaleFunction;
609
}
610
611
/**
612
 * @class Jrid
613
 * @name Jrid
614
 */
615
class Jrid {
616
  el: HTMLElement
617
  state: JridSettings = JridDefaultState
618
619
  constructor(el: HTMLElement, settings: JridSettings = {}) {
620
    // super()
621
    this.el = el
622
    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
623
    for (const k in settings) this.state[k] = settings[k]
624
    if (typeof this.state.setTranslate === 'undefined') {
625
      render(<div>no trans!?</div>, el)
626
    }
627
    else if (typeof this.state.setScale === 'undefined') {
628
      render(<div>no scale!?</div>, el)
629
    }
630
    else {
631
      render(
632
        <JridOverlay setTranslate={this.state.setTranslate} setScale={this.state.setScale} />,
633
        this.el
634
    )
635
    }
636
  }
637
638
  static get version(): string {
639
    return VERSION
640
  }
641
642
}
643
644
export default Jrid
645