Skip to content

Commit 3886f9e

Browse files
author
Kristján Oddsson
authored
Merge pull request #16 from github/add-flow-checking
Add flow type checking
2 parents bd47d5b + 6a82da8 commit 3886f9e

File tree

7 files changed

+91
-29
lines changed

7 files changed

+91
-29
lines changed

.eslintrc.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
{
22
"extends": [
33
"plugin:github/es6",
4-
"plugin:github/browser"
4+
"plugin:github/browser",
5+
"plugin:github/flow"
56
],
67
"overrides": [
78
{
89
"files": "test/**/*.js",
10+
"rules": {
11+
"flowtype/require-valid-file-annotation": "off"
12+
},
913
"env": {
1014
"mocha": true
1115
},

.flowconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[ignore]
2+
3+
[include]
4+
5+
[libs]
6+
7+
[lints]
8+
9+
[options]
10+
11+
[strict]

examples/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
</style>
1515
<meta charset="utf-8">
1616
<link href="../index.css" rel="stylesheet">
17-
<script type="module" src="../index.js"></script>
17+
<script type="module" src="../dist/index.esm.js"></script>
1818
<title>image-crop-element demo</title>
1919
</head>
2020
<body>

index.js

Lines changed: 64 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* @flow strict */
2+
13
const tmpl = document.createElement('template')
24
tmpl.innerHTML = `
35
<div class="crop-wrapper">
@@ -14,8 +16,10 @@ tmpl.innerHTML = `
1416
</div>
1517
`
1618

17-
function moveCropArea(event) {
19+
function moveCropArea(event: MouseEvent | KeyboardEvent) {
1820
const el = event.currentTarget
21+
if (!(el instanceof ImageCropElement)) return
22+
1923
let deltaX = 0
2024
let deltaY = 0
2125
if (event.type === 'keydown') {
@@ -28,7 +32,7 @@ function moveCropArea(event) {
2832
} else if (event.key === 'ArrowRight') {
2933
deltaX = 1
3034
}
31-
} else if (el.dragStartX && el.dragStartY) {
35+
} else if (el.dragStartX && el.dragStartY && event instanceof MouseEvent) {
3236
deltaX = event.pageX - el.dragStartX
3337
deltaY = event.pageY - el.dragStartY
3438
}
@@ -42,12 +46,19 @@ function moveCropArea(event) {
4246
fireChangeEvent(el, {x, y, width: el.box.offsetWidth, height: el.box.offsetHeight})
4347
}
4448

45-
el.dragStartX = event.pageX
46-
el.dragStartY = event.pageY
49+
if (event instanceof MouseEvent) {
50+
el.dragStartX = event.pageX
51+
el.dragStartY = event.pageY
52+
}
4753
}
4854

49-
function updateCropArea(event) {
50-
const el = event.target.closest('image-crop')
55+
function updateCropArea(event: MouseEvent | KeyboardEvent) {
56+
const target = event.target
57+
if (!(target instanceof HTMLElement)) return
58+
59+
const el = target.closest('image-crop')
60+
if (!(el instanceof ImageCropElement)) return
61+
5162
const rect = el.getBoundingClientRect()
5263
let deltaX, deltaY, delta
5364
if (event.key) {
@@ -59,18 +70,26 @@ function updateCropArea(event) {
5970
deltaY = el.box.offsetHeight + delta
6071
el.startX = el.box.offsetLeft
6172
el.startY = el.box.offsetTop
62-
} else {
73+
} else if (event instanceof MouseEvent) {
6374
deltaX = event.pageX - el.startX - rect.left - window.pageXOffset
6475
deltaY = event.pageY - el.startY - rect.top - window.pageYOffset
6576
}
6677

67-
if (deltaX && deltaY) updateDimensions(el, deltaX, deltaY, !event.key)
78+
if (deltaX && deltaY) updateDimensions(el, deltaX, deltaY, !(event instanceof KeyboardEvent))
6879
}
6980

70-
function startUpdate(event) {
71-
const el = event.currentTarget.closest('image-crop')
72-
if (event.target.hasAttribute('data-direction')) {
73-
const direction = event.target.getAttribute('data-direction')
81+
function startUpdate(event: MouseEvent) {
82+
const currentTarget = event.currentTarget
83+
if (!(currentTarget instanceof HTMLElement)) return
84+
85+
const el = currentTarget.closest('image-crop')
86+
if (!(el instanceof ImageCropElement)) return
87+
88+
const target = event.target
89+
if (!(target instanceof HTMLElement)) return
90+
91+
if (target.hasAttribute('data-direction')) {
92+
const direction = target.getAttribute('data-direction')
7493
// Change crop area
7594
el.addEventListener('mousemove', updateCropArea)
7695
if (['nw', 'se'].indexOf(direction) >= 0) el.classList.add('nwse')
@@ -107,8 +126,13 @@ function updateDimensions(target, deltaX, deltaY, reposition = true) {
107126
fireChangeEvent(target, {x, y, width: newSide, height: newSide})
108127
}
109128

110-
function imageReady(event) {
111-
const el = event.currentTarget.closest('image-crop')
129+
function imageReady(event: Event) {
130+
const currentTarget = event.currentTarget
131+
if (!(currentTarget instanceof HTMLElement)) return
132+
133+
const el = currentTarget.closest('image-crop')
134+
if (!(el instanceof ImageCropElement)) return
135+
112136
el.loaded = true
113137
setInitialPosition(el)
114138
}
@@ -121,31 +145,40 @@ function setInitialPosition(el) {
121145
updateDimensions(el, side, side)
122146
}
123147

124-
function stopUpdate(event) {
148+
function stopUpdate(event: MouseEvent) {
125149
const el = event.currentTarget
150+
if (!(el instanceof ImageCropElement)) return
151+
126152
el.dragStartX = el.dragStartY = null
127153
el.classList.remove('nwse', 'nesw')
128154
el.removeEventListener('mousemove', updateCropArea)
129155
el.removeEventListener('mousemove', moveCropArea)
130156
}
131157

132-
function fireChangeEvent(target, result) {
158+
function fireChangeEvent(target: ImageCropElement, result: {x: number, y: number, width: number, height: number}) {
133159
const ratio = target.image.naturalWidth / target.image.width
134160
for (const key in result) {
135161
const value = Math.round(result[key] * ratio)
136162
result[key] = value
137163
const slottedInput = target.querySelector(`[data-image-crop-input='${key}']`)
138-
if (slottedInput) slottedInput.value = value
164+
if (slottedInput instanceof HTMLInputElement) slottedInput.value = value.toString()
139165
}
140166

141167
target.dispatchEvent(new CustomEvent('image-crop-change', {bubbles: true, detail: result}))
142168
}
143169

144170
export class ImageCropElement extends HTMLElement {
171+
image: HTMLImageElement
172+
box: HTMLElement
173+
constructed: boolean
174+
minWidth: number
175+
dragStartX: ?number
176+
dragStartY: ?number
177+
startX: number
178+
startY: number
179+
145180
constructor() {
146181
super()
147-
this.startX = null
148-
this.startY = null
149182
this.minWidth = 10
150183
}
151184

@@ -154,8 +187,13 @@ export class ImageCropElement extends HTMLElement {
154187
this.constructed = true
155188

156189
this.appendChild(document.importNode(tmpl.content, true))
157-
this.image = this.querySelector('img')
158-
this.box = this.querySelector('[data-crop-box]')
190+
const image = this.querySelector('img')
191+
if (!(image instanceof HTMLImageElement)) return
192+
this.image = image
193+
194+
const box = this.querySelector('[data-crop-box]')
195+
if (!(box instanceof HTMLElement)) return
196+
this.box = box
159197

160198
this.image.addEventListener('load', imageReady)
161199
this.addEventListener('mouseleave', stopUpdate)
@@ -171,31 +209,31 @@ export class ImageCropElement extends HTMLElement {
171209
return ['src']
172210
}
173211

174-
get src() {
212+
get src(): ?string {
175213
return this.getAttribute('src')
176214
}
177215

178-
set src(val) {
216+
set src(val: ?string) {
179217
if (val) {
180218
this.setAttribute('src', val)
181219
} else {
182220
this.removeAttribute('src')
183221
}
184222
}
185223

186-
get loaded() {
224+
get loaded(): boolean {
187225
return this.hasAttribute('loaded')
188226
}
189227

190-
set loaded(val) {
228+
set loaded(val: boolean) {
191229
if (val) {
192230
this.setAttribute('loaded', '')
193231
} else {
194232
this.removeAttribute('loaded')
195233
}
196234
}
197235

198-
attributeChangedCallback(attribute, oldValue, newValue) {
236+
attributeChangedCallback(attribute: string, oldValue: string, newValue: string) {
199237
if (attribute === 'src') {
200238
this.loaded = false
201239
if (this.image) this.image.src = newValue

package-lock.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
],
1111
"scripts": {
1212
"clean": "rm -rf dist",
13-
"lint": "eslint index.js",
13+
"lint": "github-lint",
1414
"prebuild": "npm run clean && npm run lint && mkdir dist",
1515
"build-umd": "BABEL_ENV=umd babel index.js -o dist/index.umd.js",
1616
"build-esm": "BABEL_ENV=esm babel index.js -o dist/index.esm.js",
@@ -34,6 +34,7 @@
3434
"chai": "^4.2.0",
3535
"eslint": "^5.14.1",
3636
"eslint-plugin-github": "^1.10.0",
37+
"flow-bin": "^0.98.1",
3738
"karma": "^4.0.0",
3839
"karma-chai": "^0.1.0",
3940
"karma-chrome-launcher": "^2.2.0",

prettier.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
/* @flow strict */
2+
13
module.exports = require('eslint-plugin-github/prettier.config')

0 commit comments

Comments
 (0)