center-center 0.0.1 → 0.0.3

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/index.mjs CHANGED
@@ -2,80 +2,62 @@ import debug from 'debug'
2
2
 
3
3
  const log = debug('center-center')
4
4
 
5
- export function getViewportRect () {
6
- const {
7
- innerWidth: viewportW,
8
- innerHeight: viewportH
9
- } = window
10
-
11
- const {
12
- scrollingElement: {
13
- scrollLeft: viewportL,
14
- scrollTop: viewportT
15
- }
16
- } = document
17
-
18
- const viewportR = (viewportL + viewportW)
19
- const viewportB = (viewportT + viewportH)
5
+ export function getScrollingElement (document) {
6
+ if (Reflect.has(document, 'scrollingElement')) {
7
+ const scrollingElement = Reflect.get(document, 'scrollingElement')
8
+ if (scrollingElement) return scrollingElement
9
+ }
20
10
 
21
11
  return {
22
- top: viewportT,
23
- right: viewportR,
24
- bottom: viewportB,
25
- left: viewportL,
26
- width: viewportW,
27
- height: viewportH
12
+ scrollLeft: 0,
13
+ scrollTop: 0
28
14
  }
29
15
  }
30
16
 
31
- export function getContainerRect (container) {
17
+ export function getViewportRect () {
32
18
  const {
33
- offsetLeft: containerL,
34
- offsetTop: containerT
35
- } = container
19
+ innerWidth: width,
20
+ innerHeight: height
21
+ } = window
36
22
 
37
- /**
38
- * x/top is relative to the viewport
39
- */
40
23
  const {
41
- x: containerX,
42
- y: containerY,
43
- width: containerW,
44
- height: containerH
45
- } = container.getBoundingClientRect()
46
-
47
- const containerR = (containerL + containerW)
48
- const containerB = (containerT + containerH)
24
+ scrollLeft: left,
25
+ scrollTop: top
26
+ } = getScrollingElement(document)
49
27
 
50
28
  return {
51
- x: containerX,
52
- y: containerY,
53
- top: containerT,
54
- right: containerR,
55
- bottom: containerB,
56
- left: containerL,
57
- width: containerW,
58
- height: containerH
29
+ width,
30
+ height,
31
+ left,
32
+ top,
33
+ right: (left + width),
34
+ bottom: (top + height)
59
35
  }
60
36
  }
61
37
 
62
- export function getTargetRect (target) {
38
+ export function getElementRect (element) {
63
39
  const {
64
- offsetWidth: targetW,
65
- offsetHeight: targetH
66
- } = target
40
+ offsetWidth: width,
41
+ offsetHeight: height,
42
+ offsetLeft: left,
43
+ offsetTop: top
44
+ } = element
67
45
 
68
46
  return {
69
- width: targetW,
70
- height: targetH
47
+ width,
48
+ height,
49
+ left,
50
+ top,
51
+ right: (left + width),
52
+ bottom: (top + height)
71
53
  }
72
54
  }
73
55
 
74
56
  export function getRects (container, target) {
75
57
  return {
76
58
  viewport: getViewportRect(),
77
- container: getContainerRect(container),
78
- target: getTargetRect(target)
59
+ container: getElementRect(container),
60
+ target: getElementRect(target)
79
61
  }
80
62
  }
81
63
 
@@ -83,7 +65,7 @@ export function calculateLeft ({
83
65
  viewport: {
84
66
  left: viewportL,
85
67
  right: viewportR,
86
- height: viewportH
68
+ width: viewportW
87
69
  },
88
70
  container: {
89
71
  left: containerL,
@@ -94,6 +76,20 @@ export function calculateLeft ({
94
76
  width: targetW
95
77
  }
96
78
  }) {
79
+ if (viewportL === containerL) {
80
+ if (viewportW === containerW) {
81
+ const availableW = Math.max(targetW, containerW)
82
+
83
+ return ((availableW / 2) - (targetW / 2))
84
+ }
85
+
86
+ if (viewportW > containerW) {
87
+ const availableW = Math.max(targetW, (containerL + containerW))
88
+
89
+ return ((availableW / 2) - (targetW / 2))
90
+ }
91
+ }
92
+
97
93
  if (viewportL > containerL) {
98
94
  if (containerR > viewportL) {
99
95
  if (viewportR > containerR) {
@@ -107,7 +103,7 @@ export function calculateLeft ({
107
103
  if (containerR > viewportR) {
108
104
  log('calculate viewportL to viewportR')
109
105
 
110
- const availableW = Math.max(targetW, viewportH)
106
+ const availableW = Math.max(targetW, viewportW)
111
107
 
112
108
  return (viewportL - containerL) + ((availableW / 2) - (targetW / 2))
113
109
  }
@@ -138,11 +134,19 @@ export function calculateLeft ({
138
134
  }
139
135
 
140
136
  if (viewportR > containerL) {
141
- log('calculate containerL to viewportR')
137
+ if (viewportR > containerR) {
138
+ log('calculate containerL to containerR')
142
139
 
143
- const availableW = Math.max(targetW, (viewportR - containerL))
140
+ const availableW = Math.max(targetW, (containerR - containerL))
144
141
 
145
- return ((availableW / 2) - (targetW / 2))
142
+ return ((availableW / 2) - (targetW / 2))
143
+ } else {
144
+ log('calculate containerL to viewportR')
145
+
146
+ const availableW = Math.max(targetW, (viewportR - containerL))
147
+
148
+ return ((availableW / 2) - (targetW / 2))
149
+ }
146
150
  }
147
151
  }
148
152
  }
@@ -162,6 +166,20 @@ export function calculateTop ({
162
166
  height: targetH
163
167
  }
164
168
  }) {
169
+ if (viewportT === containerT) {
170
+ if (viewportH === containerH) {
171
+ const availableH = Math.max(targetH, containerH)
172
+
173
+ return ((availableH / 2) - (targetH / 2))
174
+ }
175
+
176
+ if (viewportB > containerB) {
177
+ const availableH = Math.max(targetH, (containerT + containerB))
178
+
179
+ return ((availableH / 2) - (targetH / 2))
180
+ }
181
+ }
182
+
165
183
  if (viewportT > containerT) {
166
184
  if (containerB > viewportT) {
167
185
  if (viewportB > containerB) {
@@ -206,11 +224,19 @@ export function calculateTop ({
206
224
  }
207
225
 
208
226
  if (viewportB > containerT) {
209
- log('calculate containerT to viewportB')
227
+ if (viewportB > containerB) {
228
+ log('calculate containerT to containerB')
210
229
 
211
- const availableH = Math.max(targetH, (viewportB - containerT))
230
+ const availableH = Math.max(targetH, (containerB - containerT))
212
231
 
213
- return ((availableH / 2) - (targetH / 2))
232
+ return ((availableH / 2) - (targetH / 2))
233
+ } else {
234
+ log('calculate containerT to viewportB')
235
+
236
+ const availableH = Math.max(targetH, (viewportB - containerT))
237
+
238
+ return ((availableH / 2) - (targetH / 2))
239
+ }
214
240
  }
215
241
  }
216
242
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "center-center",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Position an element at the center center of a container",
5
5
  "main": "./index.mjs",
6
6
  "type": "module",
@@ -11,7 +11,8 @@
11
11
  },
12
12
  "scripts": {
13
13
  "lint": "cross-env NODE_ENV=production eslint . --ext .mjs,.cjs",
14
- "lint:fix": "npm run lint -- --fix"
14
+ "lint:fix": "npm run lint -- --fix",
15
+ "test": "cross-env NODE_ENV=test mocha test --recursive"
15
16
  },
16
17
  "dependencies": {
17
18
  "debug": "^4.3.4"
@@ -21,9 +22,14 @@
21
22
  "@babel/core": "^7.22.17",
22
23
  "@babel/eslint-parser": "^7.22.15",
23
24
  "@babel/preset-env": "^7.22.15",
25
+ "chai": "^5.0.0",
24
26
  "core-js": "^3.32.2",
25
27
  "cross-env": "^7.0.3",
26
28
  "eslint": "^8.49.0",
27
- "eslint-config-standard": "^17.1.0"
29
+ "eslint-config-standard": "^17.1.0",
30
+ "mocha": "^10.2.0"
31
+ },
32
+ "imports": {
33
+ "#center-center": "./index.mjs"
28
34
  }
29
35
  }
@@ -0,0 +1,316 @@
1
+ import {
2
+ expect
3
+ } from 'chai'
4
+
5
+ import {
6
+ getScrollingElement,
7
+ getViewportRect,
8
+ getElementRect,
9
+ getRects,
10
+ calculateLeft,
11
+ calculateTop
12
+ } from '#center-center'
13
+
14
+ describe('`center-center`', () => {
15
+ it('exports `getScrollingElement`', () => expect(getScrollingElement).to.be.a('function'))
16
+
17
+ it('exports `getViewportRect`', () => expect(getViewportRect).to.be.a('function'))
18
+
19
+ it('exports `getElementRect`', () => expect(getElementRect).to.be.a('function'))
20
+
21
+ it('exports `getRects`', () => expect(getRects).to.be.a('function'))
22
+
23
+ it('exports `calculateLeft`', () => expect(calculateLeft).to.be.a('function'))
24
+
25
+ it('exports `calculateTop`', () => expect(calculateTop).to.be.a('function'))
26
+
27
+ describe('`getScrollingElement()`', () => {
28
+ describe('`scrollingElement` is defined', () => {
29
+ describe('`scrollingElement` is null', () => {
30
+ it('returns an object', () => {
31
+ return (
32
+ expect(getScrollingElement({ scrollingElement: null }))
33
+ .to.eql({
34
+ scrollLeft: 0,
35
+ scrollTop: 0
36
+ })
37
+ )
38
+ })
39
+ })
40
+
41
+ describe('`scrollingElement` is an object', () => {
42
+ it('returns an object', () => {
43
+ return (
44
+ expect(getScrollingElement({ scrollingElement: { scrollLeft: 'MOCK SCROLL LEFT', scrollTop: 'MOCK SCROLL TOP' } }))
45
+ .to.eql({
46
+ scrollLeft: 'MOCK SCROLL LEFT',
47
+ scrollTop: 'MOCK SCROLL TOP'
48
+ })
49
+ )
50
+ })
51
+ })
52
+ })
53
+
54
+ describe('`scrollingElement` is not defined', () => {
55
+ it('returns an object', () => {
56
+ return (
57
+ expect(getScrollingElement({}))
58
+ .to.eql({
59
+ scrollLeft: 0,
60
+ scrollTop: 0
61
+ })
62
+ )
63
+ })
64
+ })
65
+ })
66
+
67
+ describe('`getViewportRect()`', () => {
68
+ beforeEach(() => {
69
+ global.window = {
70
+ innerWidth: 'MOCK INNER WIDTH',
71
+ innerHeight: 'MOCK INNER HEIGHT'
72
+ }
73
+
74
+ global.document = {
75
+ scrollingElement: {
76
+ scrollLeft: 'MOCK SCROLL LEFT',
77
+ scrollTop: 'MOCK SCROLL TOP'
78
+ }
79
+ }
80
+ })
81
+
82
+ afterEach(() => {
83
+ delete global.window
84
+ delete global.document
85
+ })
86
+
87
+ it('returns an object', () => expect(getViewportRect()).to.eql({
88
+ top: 'MOCK SCROLL TOP',
89
+ right: 'MOCK SCROLL LEFTMOCK INNER WIDTH',
90
+ bottom: 'MOCK SCROLL TOPMOCK INNER HEIGHT',
91
+ left: 'MOCK SCROLL LEFT',
92
+ width: 'MOCK INNER WIDTH',
93
+ height: 'MOCK INNER HEIGHT'
94
+ }))
95
+ })
96
+
97
+ describe('`getElementRect()`', () => {
98
+ const mockElement = {
99
+ offsetLeft: 'MOCK OFFSET LEFT',
100
+ offsetTop: 'MOCK OFFSET TOP',
101
+ offsetWidth: 'MOCK OFFSET WIDTH',
102
+ offsetHeight: 'MOCK OFFSET HEIGHT'
103
+ }
104
+
105
+ it('returns an object', () => {
106
+ return (
107
+ expect(getElementRect(mockElement))
108
+ .to.eql({
109
+ left: 'MOCK OFFSET LEFT',
110
+ top: 'MOCK OFFSET TOP',
111
+ width: 'MOCK OFFSET WIDTH',
112
+ height: 'MOCK OFFSET HEIGHT',
113
+ right: 'MOCK OFFSET LEFTMOCK OFFSET WIDTH',
114
+ bottom: 'MOCK OFFSET TOPMOCK OFFSET HEIGHT'
115
+ })
116
+ )
117
+ })
118
+ })
119
+
120
+ describe('`getRects()`', () => {
121
+ const mockContainer = {
122
+ offsetLeft: 'MOCK OFFSET LEFT',
123
+ offsetTop: 'MOCK OFFSET TOP',
124
+ offsetWidth: 'MOCK OFFSET WIDTH',
125
+ offsetHeight: 'MOCK OFFSET HEIGHT'
126
+ }
127
+
128
+ const mockTarget = {
129
+ offsetLeft: 'MOCK OFFSET LEFT',
130
+ offsetTop: 'MOCK OFFSET TOP',
131
+ offsetWidth: 'MOCK OFFSET WIDTH',
132
+ offsetHeight: 'MOCK OFFSET HEIGHT'
133
+ }
134
+
135
+ beforeEach(() => {
136
+ global.window = {
137
+ innerWidth: 'MOCK INNER WIDTH',
138
+ innerHeight: 'MOCK INNER HEIGHT'
139
+ }
140
+
141
+ global.document = {
142
+ scrollingElement: {
143
+ scrollLeft: 'MOCK SCROLL LEFT',
144
+ scrollTop: 'MOCK SCROLL TOP'
145
+ }
146
+ }
147
+ })
148
+
149
+ afterEach(() => {
150
+ delete global.window
151
+ delete global.document
152
+ })
153
+
154
+ it('returns an object', () => {
155
+ return (
156
+ expect(getRects(mockContainer, mockTarget))
157
+ .to.eql({
158
+ viewport: {
159
+ top: 'MOCK SCROLL TOP',
160
+ right: 'MOCK SCROLL LEFTMOCK INNER WIDTH',
161
+ bottom: 'MOCK SCROLL TOPMOCK INNER HEIGHT',
162
+ left: 'MOCK SCROLL LEFT',
163
+ width: 'MOCK INNER WIDTH',
164
+ height: 'MOCK INNER HEIGHT'
165
+ },
166
+ container: {
167
+ left: 'MOCK OFFSET LEFT',
168
+ top: 'MOCK OFFSET TOP',
169
+ width: 'MOCK OFFSET WIDTH',
170
+ height: 'MOCK OFFSET HEIGHT',
171
+ right: 'MOCK OFFSET LEFTMOCK OFFSET WIDTH',
172
+ bottom: 'MOCK OFFSET TOPMOCK OFFSET HEIGHT'
173
+ },
174
+ target: {
175
+ left: 'MOCK OFFSET LEFT',
176
+ top: 'MOCK OFFSET TOP',
177
+ width: 'MOCK OFFSET WIDTH',
178
+ height: 'MOCK OFFSET HEIGHT',
179
+ right: 'MOCK OFFSET LEFTMOCK OFFSET WIDTH',
180
+ bottom: 'MOCK OFFSET TOPMOCK OFFSET HEIGHT'
181
+ }
182
+ })
183
+ )
184
+ })
185
+ })
186
+
187
+ describe('Container is shorter than the Window', () => {
188
+ const rects = {
189
+ viewport: {
190
+ top: 0,
191
+ right: 1440,
192
+ bottom: 900,
193
+ left: 0,
194
+ width: 1440,
195
+ height: 900
196
+ },
197
+ container: {
198
+ x: 0,
199
+ y: 90,
200
+ top: 90,
201
+ right: 1440,
202
+ bottom: 810,
203
+ left: 0,
204
+ width: 1440,
205
+ height: 720
206
+ },
207
+ target: {
208
+ width: 50,
209
+ height: 50
210
+ }
211
+ }
212
+
213
+ describe('`calculateLeft()`', () => {
214
+ /**
215
+ * Window is 1440 x 900
216
+ * Header is 1440 x 90
217
+ * Container is 1440 x 720
218
+ * Footer is 1440 x 90
219
+ * Target is 50 x 50
220
+ */
221
+ it('returns an object', () => {
222
+ /**
223
+ * (1440 / 2) - (50 / 2)
224
+ */
225
+ return (
226
+ expect(calculateLeft(rects))
227
+ .to.equal(695)
228
+ )
229
+ })
230
+ })
231
+
232
+ describe('`calculateTop()`', () => {
233
+ /**
234
+ * Window is 1440 x 900
235
+ * Header is 1440 x 90
236
+ * Container is 1440 x 720
237
+ * Footer is 1440 x 90
238
+ * Target is 50 x 50
239
+ */
240
+ it('returns an object', () => {
241
+ /**
242
+ * (720 / 2) - (50 / 2)
243
+ */
244
+ return (
245
+ expect(calculateTop(rects))
246
+ .to.equal(335)
247
+ )
248
+ })
249
+ })
250
+ })
251
+
252
+ describe('Container is taller than the Window', () => {
253
+ const rects = {
254
+ viewport: {
255
+ top: 0,
256
+ right: 1440,
257
+ bottom: 900,
258
+ left: 0,
259
+ width: 1440,
260
+ height: 900
261
+ },
262
+ container: {
263
+ x: 0,
264
+ y: 90,
265
+ top: 90,
266
+ right: 1440,
267
+ bottom: 1080,
268
+ left: 0,
269
+ width: 1440,
270
+ height: 990
271
+ },
272
+ target: {
273
+ width: 50,
274
+ height: 50
275
+ }
276
+ }
277
+
278
+ describe('`calculateLeft()`', () => {
279
+ /**
280
+ * Window is 1440 x 900
281
+ * Header is 1440 x 90
282
+ * Container is 1440 x 990
283
+ * Footer is 1440 x 90
284
+ * Target is 50 x 50
285
+ */
286
+ it('returns an object', () => {
287
+ /**
288
+ * (1440 / 2) - (50 / 2)
289
+ */
290
+ return (
291
+ expect(calculateLeft(rects))
292
+ .to.equal(695)
293
+ )
294
+ })
295
+ })
296
+
297
+ describe('`calculateTop()`', () => {
298
+ /**
299
+ * Window is 1440 x 900
300
+ * Header is 1440 x 90
301
+ * Container is 1440 x 990
302
+ * Footer is 1440 x 90
303
+ * Target is 50 x 50
304
+ */
305
+ it('returns an object', () => {
306
+ /**
307
+ * (810 / 2) - (50 / 2)
308
+ */
309
+ return (
310
+ expect(calculateTop(rects))
311
+ .to.equal(380)
312
+ )
313
+ })
314
+ })
315
+ })
316
+ })