@bloom-housing/ui-components 12.0.15 → 12.0.16

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.
@@ -33,6 +33,8 @@ export interface ImageCardProps {
33
33
  imageUrl?: string;
34
34
  /** Alternatively, a number of images can be passed in */
35
35
  images?: ImageItem[];
36
+ /** A fallback image URL that will be displayed on error for all images */
37
+ fallbackImageUrl?: string;
36
38
  /** A list of status indicators, an ApplicationStatus component is rendered for each item at the bottom of the card */
37
39
  statuses?: StatusBarType[];
38
40
  /** A list of image tags, a Tag component is rendered for each over the image */
@@ -20,6 +20,7 @@ import { Icon, IconFillColors } from "../icons/Icon";
20
20
  import { Modal } from "../overlays/Modal";
21
21
  import { Button } from "../actions/Button";
22
22
  import { t } from "../helpers/translator";
23
+ import { useFallbackImage } from "../helpers/useFallbackImage";
23
24
  /**
24
25
  * @component ImageCard
25
26
  *
@@ -28,6 +29,7 @@ import { t } from "../helpers/translator";
28
29
  var ImageCard = function (props) {
29
30
  var _a, _b, _c, _d, _e;
30
31
  var _f = useState(false), showModal = _f[0], setShowModal = _f[1];
32
+ var _g = useFallbackImage(props === null || props === void 0 ? void 0 : props.fallbackImageUrl), imgParentRef = _g.imgParentRef, imgRefs = _g.imgRefs, onError = _g.onError;
31
33
  var getStatuses = function () {
32
34
  var _a;
33
35
  var statuses = (_a = props.statuses) === null || _a === void 0 ? void 0 : _a.map(function (status, index) {
@@ -60,8 +62,8 @@ var ImageCard = function (props) {
60
62
  };
61
63
  var image = (React.createElement(React.Fragment, null,
62
64
  React.createElement("div", { className: "image-card" },
63
- React.createElement("figure", { className: innerClasses.join(" ") },
64
- props.imageUrl ? (React.createElement("img", { src: props.imageUrl, alt: (_c = (_a = props.description) !== null && _a !== void 0 ? _a : (_b = props.strings) === null || _b === void 0 ? void 0 : _b.defaultImageAltText) !== null && _c !== void 0 ? _c : t("listings.buildingImageAltText") })) : props.images && displayedImages ? (displayedImages.map(function (image, index) { return (React.createElement("img", { key: index, src: image.thumbnailUrl || image.mobileUrl || image.url, alt: getAltText(index, displayedImages, image.description) })); })) : (React.createElement("div", { className: "image-card__placeholder" })),
65
+ React.createElement("figure", { className: innerClasses.join(" "), ref: imgParentRef },
66
+ props.imageUrl ? (React.createElement("img", { src: props.imageUrl, alt: (_c = (_a = props.description) !== null && _a !== void 0 ? _a : (_b = props.strings) === null || _b === void 0 ? void 0 : _b.defaultImageAltText) !== null && _c !== void 0 ? _c : t("listings.buildingImageAltText"), ref: function (el) { return (imgRefs.current[0] = el); }, onError: onError })) : props.images && displayedImages ? (displayedImages.map(function (image, index) { return (React.createElement("img", { key: index, src: image.thumbnailUrl || image.mobileUrl || image.url, alt: getAltText(index, displayedImages, image.description), ref: function (el) { return (imgRefs.current[index] = el); }, onError: onError })); })) : (React.createElement("div", { className: "image-card__placeholder" })),
65
67
  props.images && props.images.length > 1 && (React.createElement(React.Fragment, null,
66
68
  props.images && props.images.length > 3 && (React.createElement("div", { className: "image-card__more-images" },
67
69
  React.createElement(Icon, { symbol: "plus", size: "xlarge" }),
@@ -90,7 +92,7 @@ var ImageCard = function (props) {
90
92
  ], actionsInContent: props.modalCloseInContent }, (_e = props.images) === null || _e === void 0 ? void 0 : _e.map(function (image, index) { return (React.createElement("p", { key: index, className: "md:mb-8" },
91
93
  React.createElement("picture", null,
92
94
  image.mobileUrl && React.createElement("source", { media: "(max-width: 767px)", srcSet: image.mobileUrl }),
93
- React.createElement("img", { src: image.url, alt: getAltText(index, props.images, image.description) })))); })))));
95
+ React.createElement("img", { src: image.url, alt: getAltText(index, props.images, image.description), onError: onError })))); })))));
94
96
  var card = image;
95
97
  if (props.href) {
96
98
  card = (React.createElement(LocalizedLink, { className: "block", href: props.href }, image));
@@ -1 +1 @@
1
- {"version":3,"file":"ImageCard.js","sourceRoot":"","sources":["../../../src/blocks/ImageCard.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ImageCard.js","sourceRoot":"","sources":["../../../src/blocks/ImageCard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { SyntheticEvent } from "react";
2
+ export declare function useFallbackImage(fallbackSrc?: string): {
3
+ imgParentRef: import("react").RefObject<HTMLDivElement>;
4
+ imgRefs: import("react").MutableRefObject<(HTMLImageElement | null)[]>;
5
+ onError: (e: SyntheticEvent<HTMLImageElement>) => void;
6
+ };
@@ -0,0 +1,31 @@
1
+ import { useCallback, useEffect, useRef } from "react";
2
+ export function useFallbackImage(fallbackSrc) {
3
+ var imgParentRef = useRef(null);
4
+ var imgRefs = useRef([]);
5
+ var onError = useCallback(function (e) {
6
+ if (fallbackSrc) {
7
+ e.currentTarget.src = fallbackSrc;
8
+ }
9
+ }, [fallbackSrc]);
10
+ useEffect(function () {
11
+ if (imgParentRef && imgParentRef.current && fallbackSrc) {
12
+ var numberOfImages = imgParentRef.current.children.length;
13
+ for (var i = 0; i < numberOfImages; i++) {
14
+ var imgRef = imgRefs.current[i];
15
+ if (imgRef) {
16
+ var complete = imgRef.complete, naturalHeight = imgRef.naturalHeight;
17
+ var errorLoadingImgBeforeHydration = complete && naturalHeight === 0;
18
+ if (errorLoadingImgBeforeHydration) {
19
+ imgRef.src = fallbackSrc;
20
+ }
21
+ }
22
+ }
23
+ }
24
+ }, [fallbackSrc]);
25
+ return {
26
+ imgParentRef: imgParentRef,
27
+ imgRefs: imgRefs,
28
+ onError: onError,
29
+ };
30
+ }
31
+ //# sourceMappingURL=useFallbackImage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFallbackImage.js","sourceRoot":"","sources":["../../../src/helpers/useFallbackImage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAEtE,MAAM,UAAU,gBAAgB,CAAC,WAAoB;IACnD,IAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IACjD,IAAM,OAAO,GAAG,MAAM,CAA8B,EAAE,CAAC,CAAA;IAEvD,IAAM,OAAO,GAAG,WAAW,CACzB,UAAC,CAAmC;QAClC,IAAI,WAAW,EAAE;YACf,CAAC,CAAC,aAAa,CAAC,GAAG,GAAG,WAAW,CAAA;SAClC;IACH,CAAC,EACD,CAAC,WAAW,CAAC,CACd,CAAA;IAED,SAAS,CAAC;QACR,IAAI,YAAY,IAAI,YAAY,CAAC,OAAO,IAAI,WAAW,EAAE;YACvD,IAAM,cAAc,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAA;YAC3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,EAAE,CAAC,EAAE,EAAE;gBACvC,IAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;gBACjC,IAAI,MAAM,EAAE;oBACF,IAAA,QAAQ,GAAoB,MAAM,SAA1B,EAAE,aAAa,GAAK,MAAM,cAAX,CAAW;oBAC1C,IAAM,8BAA8B,GAAG,QAAQ,IAAI,aAAa,KAAK,CAAC,CAAA;oBACtE,IAAI,8BAA8B,EAAE;wBAClC,MAAM,CAAC,GAAG,GAAG,WAAW,CAAA;qBACzB;iBACF;aACF;SACF;IACH,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;IAEjB,OAAO;QACL,YAAY,cAAA;QACZ,OAAO,SAAA;QACP,OAAO,SAAA;KACR,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bloom-housing/ui-components",
3
- "version": "12.0.15",
3
+ "version": "12.0.16",
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/ui-components",
@@ -10,6 +10,7 @@ import { Icon, IconFillColors, UniversalIconType } from "../icons/Icon"
10
10
  import { Modal } from "../overlays/Modal"
11
11
  import { Button } from "../actions/Button"
12
12
  import { t } from "../helpers/translator"
13
+ import { useFallbackImage } from "../helpers/useFallbackImage"
13
14
 
14
15
  export interface StatusBarType {
15
16
  status?: ApplicationStatusType
@@ -45,6 +46,8 @@ export interface ImageCardProps {
45
46
  imageUrl?: string
46
47
  /** Alternatively, a number of images can be passed in */
47
48
  images?: ImageItem[]
49
+ /** A fallback image URL that will be displayed on error for all images */
50
+ fallbackImageUrl?: string
48
51
  /** A list of status indicators, an ApplicationStatus component is rendered for each item at the bottom of the card */
49
52
  statuses?: StatusBarType[]
50
53
  /** A list of image tags, a Tag component is rendered for each over the image */
@@ -71,6 +74,7 @@ export interface ImageCardProps {
71
74
  */
72
75
  const ImageCard = (props: ImageCardProps) => {
73
76
  const [showModal, setShowModal] = useState(false)
77
+ const { imgParentRef, imgRefs, onError } = useFallbackImage(props?.fallbackImageUrl)
74
78
 
75
79
  const getStatuses = () => {
76
80
  const statuses = props.statuses?.map((status, index) => {
@@ -116,7 +120,7 @@ const ImageCard = (props: ImageCardProps) => {
116
120
  const image = (
117
121
  <>
118
122
  <div className="image-card">
119
- <figure className={innerClasses.join(" ")}>
123
+ <figure className={innerClasses.join(" ")} ref={imgParentRef}>
120
124
  {props.imageUrl ? (
121
125
  <img
122
126
  src={props.imageUrl}
@@ -125,6 +129,8 @@ const ImageCard = (props: ImageCardProps) => {
125
129
  props.strings?.defaultImageAltText ??
126
130
  t("listings.buildingImageAltText")
127
131
  }
132
+ ref={(el) => (imgRefs.current[0] = el)}
133
+ onError={onError}
128
134
  />
129
135
  ) : props.images && displayedImages ? (
130
136
  displayedImages.map((image, index) => (
@@ -132,6 +138,8 @@ const ImageCard = (props: ImageCardProps) => {
132
138
  key={index}
133
139
  src={image.thumbnailUrl || image.mobileUrl || image.url}
134
140
  alt={getAltText(index, displayedImages, image.description)}
141
+ ref={(el) => (imgRefs.current[index] = el)}
142
+ onError={onError}
135
143
  />
136
144
  ))
137
145
  ) : (
@@ -219,7 +227,11 @@ const ImageCard = (props: ImageCardProps) => {
219
227
  <p key={index} className="md:mb-8">
220
228
  <picture>
221
229
  {image.mobileUrl && <source media="(max-width: 767px)" srcSet={image.mobileUrl} />}
222
- <img src={image.url} alt={getAltText(index, props.images, image.description)} />
230
+ <img
231
+ src={image.url}
232
+ alt={getAltText(index, props.images, image.description)}
233
+ onError={onError}
234
+ />
223
235
  </picture>
224
236
  </p>
225
237
  ))}
@@ -0,0 +1,37 @@
1
+ import { SyntheticEvent, useCallback, useEffect, useRef } from "react"
2
+
3
+ export function useFallbackImage(fallbackSrc?: string) {
4
+ const imgParentRef = useRef<HTMLDivElement>(null)
5
+ const imgRefs = useRef<(HTMLImageElement | null)[]>([])
6
+
7
+ const onError = useCallback(
8
+ (e: SyntheticEvent<HTMLImageElement>) => {
9
+ if (fallbackSrc) {
10
+ e.currentTarget.src = fallbackSrc
11
+ }
12
+ },
13
+ [fallbackSrc]
14
+ )
15
+
16
+ useEffect(() => {
17
+ if (imgParentRef && imgParentRef.current && fallbackSrc) {
18
+ const numberOfImages = imgParentRef.current.children.length
19
+ for (let i = 0; i < numberOfImages; i++) {
20
+ const imgRef = imgRefs.current[i]
21
+ if (imgRef) {
22
+ const { complete, naturalHeight } = imgRef
23
+ const errorLoadingImgBeforeHydration = complete && naturalHeight === 0
24
+ if (errorLoadingImgBeforeHydration) {
25
+ imgRef.src = fallbackSrc
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }, [fallbackSrc])
31
+
32
+ return {
33
+ imgParentRef,
34
+ imgRefs,
35
+ onError,
36
+ }
37
+ }