@bloom-housing/ui-components 4.0.1-alpha.49 → 4.0.1-alpha.53

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.
@@ -18,6 +18,14 @@ window.matchMedia = jest.fn().mockImplementation((query) => {
18
18
  }
19
19
  })
20
20
 
21
+ window.IntersectionObserver = class {
22
+ constructor(root, options) {
23
+ // no-op
24
+ }
25
+ observe = jest.fn()
26
+ disconnect = jest.fn()
27
+ }
28
+
21
29
  addTranslation(general)
22
30
 
23
31
  configure({ testIdAttribute: "data-test-id" })
package/CHANGELOG.md CHANGED
@@ -3,6 +3,41 @@
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
+ ## [4.0.1-alpha.53](https://github.com/bloom-housing/bloom/compare/@bloom-housing/ui-components@4.0.1-alpha.52...@bloom-housing/ui-components@4.0.1-alpha.53) (2022-02-10)
7
+
8
+
9
+ ### Features
10
+
11
+ * only show MapBox map when it's in the viewport ([#2470](https://github.com/bloom-housing/bloom/issues/2470)) ([86f9d6c](https://github.com/bloom-housing/bloom/commit/86f9d6cccd7de7e635ae4eab5b1e1358faf834e4))
12
+
13
+
14
+
15
+
16
+
17
+ ## [4.0.1-alpha.52](https://github.com/bloom-housing/bloom/compare/@bloom-housing/ui-components@4.0.1-alpha.51...@bloom-housing/ui-components@4.0.1-alpha.52) (2022-02-10)
18
+
19
+ **Note:** Version bump only for package @bloom-housing/ui-components
20
+
21
+
22
+
23
+
24
+
25
+ ## [4.0.1-alpha.51](https://github.com/bloom-housing/bloom/compare/@bloom-housing/ui-components@4.0.1-alpha.50...@bloom-housing/ui-components@4.0.1-alpha.51) (2022-02-09)
26
+
27
+ **Note:** Version bump only for package @bloom-housing/ui-components
28
+
29
+
30
+
31
+
32
+
33
+ ## [4.0.1-alpha.50](https://github.com/bloom-housing/bloom/compare/@bloom-housing/ui-components@4.0.1-alpha.49...@bloom-housing/ui-components@4.0.1-alpha.50) (2022-02-09)
34
+
35
+ **Note:** Version bump only for package @bloom-housing/ui-components
36
+
37
+
38
+
39
+
40
+
6
41
  ## [4.0.1-alpha.49](https://github.com/bloom-housing/bloom/compare/@bloom-housing/ui-components@4.0.1-alpha.48...@bloom-housing/ui-components@4.0.1-alpha.49) (2022-02-09)
7
42
 
8
43
  **Note:** Version bump only for package @bloom-housing/ui-components
package/index.ts CHANGED
@@ -66,6 +66,7 @@ export * from "./src/helpers/formatYesNoLabel"
66
66
  export * from "./src/helpers/getTranslationWithArguments"
67
67
  export * from "./src/helpers/preferences"
68
68
  export * from "./src/helpers/resolveObject"
69
+ export * from "./src/helpers/useIntersect"
69
70
  export * from "./src/helpers/useMutate"
70
71
  export * from "./src/helpers/tableSummaries"
71
72
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bloom-housing/ui-components",
3
- "version": "4.0.1-alpha.49",
3
+ "version": "4.0.1-alpha.53",
4
4
  "author": "Sean Albert <sean.albert@exygy.com>",
5
5
  "description": "Shared user interface components for Bloom affordable housing system",
6
6
  "homepage": "https://github.com/bloom-housing/bloom/tree/master/shared/ui-components",
@@ -69,7 +69,7 @@
69
69
  "webpack": "^4.44.2"
70
70
  },
71
71
  "dependencies": {
72
- "@bloom-housing/backend-core": "^3.0.2-alpha.32",
72
+ "@bloom-housing/backend-core": "^3.0.2-alpha.34",
73
73
  "@mapbox/mapbox-sdk": "^0.13.0",
74
74
  "@types/body-scroll-lock": "^2.6.1",
75
75
  "@types/jwt-decode": "^2.2.1",
@@ -100,5 +100,5 @@
100
100
  "tailwindcss": "2.2.10",
101
101
  "typesafe-actions": "^5.1.0"
102
102
  },
103
- "gitHead": "b5b98f42d3e863c6eea930b2be4f26ad841c6c30"
103
+ "gitHead": "1af623f3a35874c50f50b28f9231412026835cc8"
104
104
  }
@@ -0,0 +1,48 @@
1
+ import { useEffect, useRef, useState } from "react"
2
+
3
+ interface useIntersectProps {
4
+ root?: Element | null
5
+ rootMargin?: string
6
+ threshold?: number
7
+ }
8
+
9
+ /**
10
+ * Use this hook to obtain state when an element is visible or not relative to
11
+ * an ancestor element (or by default the browser viewport)
12
+ */
13
+ export const useIntersect = ({
14
+ root = null,
15
+ rootMargin = "0px",
16
+ threshold = 0,
17
+ }: useIntersectProps) => {
18
+ // broadly based on this source code:
19
+ // https://non-traditional.dev/how-to-use-an-intersectionobserver-in-a-react-hook-9fb061ac6cb5
20
+
21
+ const [intersecting, setIntersecting] = useState(false)
22
+ const [element, setIntersectingElement] = useState<Element | null>(null)
23
+
24
+ const observer = useRef<IntersectionObserver | null>(null)
25
+
26
+ // Instantiate the observer upon element mount
27
+ useEffect(() => {
28
+ if (observer.current) observer.current.disconnect()
29
+
30
+ if (element) {
31
+ observer.current = new IntersectionObserver(
32
+ ([entry]) => setIntersecting(entry.isIntersecting),
33
+ {
34
+ root,
35
+ rootMargin,
36
+ threshold,
37
+ }
38
+ )
39
+
40
+ observer.current.observe(element)
41
+ }
42
+
43
+ // Unmount callback
44
+ return () => observer?.current?.disconnect()
45
+ }, [element, root, rootMargin, threshold])
46
+
47
+ return { setIntersectingElement, intersecting }
48
+ }
@@ -268,6 +268,29 @@
268
268
  "description": "Al menos un miembro de mi hogar es empleado del Distrito Escolar Unificado de Alameda"
269
269
  }
270
270
  },
271
+ "dublinHousing": {
272
+ "liveInDublin": {
273
+ "label": "Al menos un miembro de mi hogar vive en Dublín (3 puntos)"
274
+ },
275
+ "immediateFamily": {
276
+ "label": "Al menos un miembro de mi hogar tiene un familiar directo en Dublín (1 punto)"
277
+ },
278
+ "displacedResident": {
279
+ "label": "Se requirió que al menos un miembro de mi hogar se mudara de la residencia actual de Dublín debido a la demolición de la vivienda o la conversión de la vivienda de alquiler a unidad de venta (1 punto)"
280
+ },
281
+ "worksInDublin": {
282
+ "label": "Al menos un miembro de mi hogar trabaja a tiempo completo en Dublín (3 puntos)"
283
+ },
284
+ "publicServiceEmployee": {
285
+ "label": "Al menos un miembro de mi hogar es un empleado del servicio público en Dublín (1 punto adicional)"
286
+ },
287
+ "permanentlyDisabled": {
288
+ "label": "Al menos un miembro de mi hogar tiene una discapacidad permanente (1 punto)"
289
+ },
290
+ "senior": {
291
+ "label": "Al menos un miembro de mi hogar es una persona mayor, definida como de 62 años o más (1 punto)"
292
+ }
293
+ },
271
294
  "terminationOfAffordability": {
272
295
  "atLeastOne": {
273
296
  "label": "Al menos un miembro de mi hogar está sujeto a la terminación de las restricciones de asequibilidad"
@@ -672,6 +672,30 @@
672
672
  "description": "At least one member of my household is an Alameda Unified School District employee."
673
673
  }
674
674
  },
675
+ "dublinHousing": {
676
+ "title": "Alameda Unified School District (AUSD) employee",
677
+ "liveInDublin": {
678
+ "label": "At least one member of my household lives in Dublin (3 points)"
679
+ },
680
+ "immediateFamily": {
681
+ "label": "At least one member of my household has an immediate family member in Dublin (1 point)"
682
+ },
683
+ "displacedResident": {
684
+ "label": "At least one member of my household was required to relocate from current Dublin residence due to demolition of dwelling or conversation of dwelling from rental to for-sale unit (1 point)"
685
+ },
686
+ "worksInDublin": {
687
+ "label": "At least one member of my household works full-time in Dublin (3 points)"
688
+ },
689
+ "publicServiceEmployee": {
690
+ "label": "At least one member of my household is a public service employee in Dublin (1 additional point)"
691
+ },
692
+ "permanentlyDisabled": {
693
+ "label": "At least one member of my household is permanently disabled (1 point)"
694
+ },
695
+ "senior": {
696
+ "label": "At least one member of my household is a senior, defined as age 62 and older (1 point)"
697
+ }
698
+ },
675
699
  "terminationOfAffordability": {
676
700
  "title": "Persons subject to termination of affordability restrictions",
677
701
  "atLeastOne": {
@@ -265,9 +265,32 @@
265
265
  "description": "Ít nhất một thành viên trong gia đình tôi là nhân viên của Học khu Thống nhất Alameda"
266
266
  }
267
267
  },
268
+ "dublinHousing": {
269
+ "liveInDublin": {
270
+ "label": "Ít nhất một thành viên trong gia đình tôi sống ở Dublin (3 điểm)"
271
+ },
272
+ "immediateFamily": {
273
+ "label": "Ít nhất một thành viên trong gia đình của tôi có người thân trong gia đình ở Dublin (1 điểm)"
274
+ },
275
+ "displacedResident": {
276
+ "label": "Ít nhất một thành viên trong gia đình tôi đã phải di dời khỏi nơi ở hiện tại ở Dublin do việc phá dỡ nhà ở hoặc chuyển nhà từ cho thuê sang bán (1 điểm)"
277
+ },
278
+ "worksInDublin": {
279
+ "label": "Ít nhất một thành viên trong gia đình tôi làm việc toàn thời gian ở Dublin (3 điểm)"
280
+ },
281
+ "publicServiceEmployee": {
282
+ "label": "Ít nhất một thành viên trong gia đình tôi là nhân viên dịch vụ công cộng ở Dublin (1 điểm bổ sung)"
283
+ },
284
+ "permanentlyDisabled": {
285
+ "label": "Ít nhất một thành viên trong gia đình tôi bị tàn tật vĩnh viễn (1 điểm)"
286
+ },
287
+ "senior": {
288
+ "label": "Ít nhất một thành viên trong gia đình tôi là người cao tuổi, được xác định là từ 62 tuổi trở lên (1 điểm)"
289
+ }
290
+ },
268
291
  "terminationOfAffordability": {
269
292
  "atLeastOne": {
270
- "label": "Ít nhất một thành viên trong gia đình tôi phải chấm dứt các hạn chế về khả năng chi trả"
293
+ "label": "Ít nhất một thành viên trong gia đình, tôi phải sử dụng các hạn chế về chi trả khả năng"
271
294
  }
272
295
  },
273
296
  "liveWorkFosterCity": {
@@ -265,6 +265,29 @@
265
265
  "description": "我的至少一名家庭成员是阿拉米达联合学区的雇员"
266
266
  }
267
267
  },
268
+ "dublinHousing": {
269
+ "liveInDublin": {
270
+ "label": "我的至少一名家庭成员住在都柏林 (3 分)"
271
+ },
272
+ "immediateFamily": {
273
+ "label": "我的至少一名家庭成员在都柏林有直系亲属 (1 分)"
274
+ },
275
+ "displacedResident": {
276
+ "label": "由于住宅被拆除或住宅从出租转为出售单位的谈话, 我的至少一名家庭成员需要从目前都柏林的住宅搬迁 (1 分)"
277
+ },
278
+ "worksInDublin": {
279
+ "label": "我的至少一名家庭成员在都柏林全职工作 (3 分)"
280
+ },
281
+ "publicServiceEmployee": {
282
+ "label": "我的至少一名家庭成员是都柏林的公共服务人员 (加分)"
283
+ },
284
+ "permanentlyDisabled": {
285
+ "label": "我的家庭中至少有一名成员永久残疾 (1 分)"
286
+ },
287
+ "senior": {
288
+ "label": "我的家庭中至少一名成员是老年人, 定义为 62 岁及以上 (1 分)"
289
+ }
290
+ },
268
291
  "terminationOfAffordability": {
269
292
  "atLeastOne": {
270
293
  "label": "我的至少一名家庭成员受到终止负担能力限制"
@@ -1,3 +1,7 @@
1
+ .listing-map {
2
+ min-height: 12rem;
3
+ }
4
+
1
5
  .pin {
2
6
  @apply absolute;
3
7
  width: 30px;
@@ -1,9 +1,10 @@
1
- import React, { useState, useCallback, useEffect } from "react"
1
+ import React, { useState, useCallback, useEffect, useMemo } from "react"
2
2
  import "mapbox-gl/dist/mapbox-gl.css"
3
3
  import MapGL, { Marker } from "react-map-gl"
4
4
 
5
5
  import "./ListingMap.scss"
6
6
  import { MultiLineAddress, Address } from "../../helpers/address"
7
+ import { useIntersect } from "../../.."
7
8
 
8
9
  export interface ListingMapProps {
9
10
  address?: Address
@@ -35,6 +36,15 @@ const isValidLongitude = (longitude: number) => {
35
36
  }
36
37
 
37
38
  const ListingMap = (props: ListingMapProps) => {
39
+ // Lazy load the map component only when it will become visible on screen
40
+ const { setIntersectingElement, intersecting } = useIntersect({
41
+ // `window` isn't set for SSR, so we'll use `global` instead—doesn't really
42
+ // matter because the map won't ever get rendered in SSR anyway
43
+ rootMargin: `${global.innerHeight || 0}px`,
44
+ })
45
+ const [hasIntersected, setHasIntersected] = useState(false)
46
+ if (intersecting && !hasIntersected) setHasIntersected(true)
47
+
38
48
  const [marker, setMarker] = useState({
39
49
  latitude: props.address?.latitude,
40
50
  longitude: props.address?.longitude,
@@ -95,12 +105,12 @@ const ListingMap = (props: ListingMapProps) => {
95
105
  return null
96
106
 
97
107
  return (
98
- <div className="listing-map">
108
+ <div className="listing-map" ref={setIntersectingElement}>
99
109
  <div className="addressPopup">
100
110
  {props.listingName && <h3 className="text-caps-tiny">{props.listingName}</h3>}
101
111
  <MultiLineAddress address={props.address} />
102
112
  </div>
103
- {(process.env.mapBoxToken || process.env.MAPBOX_TOKEN) && (
113
+ {(process.env.mapBoxToken || process.env.MAPBOX_TOKEN) && hasIntersected && (
104
114
  <MapGL
105
115
  mapboxApiAccessToken={process.env.mapBoxToken || process.env.MAPBOX_TOKEN}
106
116
  mapStyle="mapbox://styles/mapbox/streets-v11"