|
3 | 3 | // Come back to this after https://github.com/nuxt/nuxt/issues/20936 is fixed |
4 | 4 | // import type { AssetOptions } from "@cloudinary-util/url-loader"; |
5 | 5 | // import type { ConfigOptions } from "@cloudinary-util/url-loader"; |
6 | | -import { ref } from 'vue' |
7 | | -import { Image } from '@unpic/vue' |
8 | | -import type { ConstructUrlProps } from '@cloudinary-util/url-loader' |
9 | | -import { useCldImageUrl } from '../composables/useCldImageUrl' |
| 6 | +import { ref } from "vue"; |
| 7 | +import { Image } from "@unpic/vue"; |
| 8 | +import type { ConstructUrlProps } from "@cloudinary-util/url-loader"; |
| 9 | +import { useCldImageUrl } from "../composables/useCldImageUrl"; |
10 | 10 |
|
11 | 11 | interface AssetOptionsResize { |
12 | | - crop?: string |
13 | | - width?: number | string |
| 12 | + crop?: string | object; |
| 13 | + width?: number | string; |
14 | 14 | } |
15 | 15 |
|
16 | 16 | interface ImageOptionsFillBackground { |
17 | | - crop?: string |
18 | | - gravity?: string |
19 | | - prompt?: string |
| 17 | + crop?: string; |
| 18 | + gravity?: string; |
| 19 | + prompt?: string; |
20 | 20 | } |
21 | 21 |
|
22 | 22 | interface AssetOptions { |
23 | | - assetType?: string |
24 | | - crop?: string |
25 | | - deliveryType?: string |
26 | | - effects?: Array<any> |
27 | | - flags?: Array<string> | object |
28 | | - format?: string |
29 | | - gravity?: string |
30 | | - height?: string | number |
31 | | - overlays?: Array<any> |
32 | | - quality?: number | string |
33 | | - rawTransformations?: string[] |
34 | | - removeBackground?: boolean |
35 | | - sanitize?: boolean |
36 | | - resize?: AssetOptionsResize |
37 | | - seoSuffix?: string |
38 | | - src: string |
39 | | - text?: any |
40 | | - namedTransformations?: Array<string> |
41 | | - underlay?: string |
42 | | - underlays?: Array<any> |
43 | | - version?: number | string |
44 | | - width?: string | number |
45 | | - widthResize?: string | number |
46 | | - zoom?: string |
| 23 | + assetType?: string; |
| 24 | + crop?: string; |
| 25 | + deliveryType?: string; |
| 26 | + effects?: Array<any>; |
| 27 | + flags?: Array<string> | object; |
| 28 | + format?: string; |
| 29 | + gravity?: string; |
| 30 | + height?: string | number; |
| 31 | + overlays?: Array<any>; |
| 32 | + quality?: number | string; |
| 33 | + rawTransformations?: string[]; |
| 34 | + removeBackground?: boolean; |
| 35 | + sanitize?: boolean; |
| 36 | + resize?: AssetOptionsResize; |
| 37 | + seoSuffix?: string; |
| 38 | + src: string; |
| 39 | + text?: any; |
| 40 | + namedTransformations?: Array<string>; |
| 41 | + underlay?: string; |
| 42 | + underlays?: Array<any>; |
| 43 | + version?: number | string; |
| 44 | + width?: string | number; |
| 45 | + widthResize?: string | number; |
| 46 | + zoom?: string; |
47 | 47 | } |
48 | 48 |
|
49 | | -type ImageOptionsRecolorPrompt = string | Array<string> |
| 49 | +type ImageOptionsRecolorPrompt = string | Array<string>; |
50 | 50 |
|
51 | 51 | interface ImageOptionsRecolor { |
52 | | - prompt?: ImageOptionsRecolorPrompt |
53 | | - to?: string |
54 | | - multiple?: boolean |
| 52 | + prompt?: ImageOptionsRecolorPrompt; |
| 53 | + to?: string; |
| 54 | + multiple?: boolean; |
55 | 55 | } |
56 | 56 |
|
57 | 57 | interface ImageOptionsZoomPan { |
58 | | - loop: string | boolean |
59 | | - options: string |
| 58 | + loop: string | boolean; |
| 59 | + options: string; |
60 | 60 | } |
61 | 61 |
|
62 | | -type ImageOptionsRemovePrompt = string | Array<string> |
| 62 | +type ImageOptionsRemovePrompt = string | Array<string>; |
63 | 63 |
|
64 | 64 | interface ImageOptionsRemove { |
65 | | - prompt?: ImageOptionsRemovePrompt |
66 | | - region?: [300, 200, 1900, 3500] |
67 | | - multiple?: boolean |
68 | | - removeShadow?: boolean |
| 65 | + prompt?: ImageOptionsRemovePrompt; |
| 66 | + region?: [300, 200, 1900, 3500]; |
| 67 | + multiple?: boolean; |
| 68 | + removeShadow?: boolean; |
69 | 69 | } |
70 | 70 |
|
71 | 71 | interface ImageOptionsGenerativeReplace { |
72 | | - to: string |
73 | | - from: string |
74 | | - preserveGeometry?: boolean |
| 72 | + to: string; |
| 73 | + from: string; |
| 74 | + preserveGeometry?: boolean; |
75 | 75 | } |
76 | 76 | interface ImageOptions extends AssetOptions { |
77 | | - zoompan?: string | boolean | ImageOptionsZoomPan |
78 | | - fillBackground?: boolean | ImageOptionsFillBackground |
79 | | - recolor?: ImageOptionsRecolorPrompt | ImageOptionsRecolor |
80 | | - remove?: ImageOptionsRemovePrompt | ImageOptionsRemove |
81 | | - replace?: Array<string | boolean> | ImageOptionsGenerativeReplace |
82 | | - restore?: boolean |
| 77 | + zoompan?: string | boolean | ImageOptionsZoomPan; |
| 78 | + fillBackground?: boolean | ImageOptionsFillBackground; |
| 79 | + recolor?: ImageOptionsRecolorPrompt | ImageOptionsRecolor; |
| 80 | + remove?: ImageOptionsRemovePrompt | ImageOptionsRemove; |
| 81 | + replace?: Array<string | boolean> | ImageOptionsGenerativeReplace; |
| 82 | + restore?: boolean; |
83 | 83 | } |
84 | 84 |
|
85 | 85 | export interface CldImageProps extends ImageOptions { |
86 | | - loading?: 'eager' | 'lazy' |
87 | | - fetchPriority?: 'high' | 'low' | 'auto' |
| 86 | + loading?: "eager" | "lazy"; |
| 87 | + fetchPriority?: "high" | "low" | "auto"; |
88 | 88 | // Adding below as required props to promote good patterns in developing images |
89 | | - alt: string |
90 | | - width: string | number |
91 | | - height: string | number |
| 89 | + alt: string; |
| 90 | + width: string | number; |
| 91 | + height: string | number; |
92 | 92 | // Cloudinary URL Loader props |
93 | 93 | // Cannot use `ConfigOptions` due to the same issue as mentioned at the top |
94 | | - config?: any |
| 94 | + config?: any; |
95 | 95 | // Unpic props |
96 | | - layout?: 'constrained' | 'fullWidth' | 'fixed' |
97 | | - priority?: boolean |
98 | | - background?: 'auto' | string |
| 96 | + layout?: "constrained" | "fullWidth" | "fixed"; |
| 97 | + priority?: boolean; |
| 98 | + background?: "auto" | string; |
99 | 99 | // Cloudinary missing effect props |
100 | | - blur?: string | number |
101 | | - pixelate?: boolean |
102 | | - grayscale?: boolean |
103 | | - tint?: string | number |
104 | | - opacity?: string | number |
105 | | - shear?: string |
106 | | - border?: string |
| 100 | + blur?: string | number; |
| 101 | + pixelate?: boolean; |
| 102 | + grayscale?: boolean; |
| 103 | + tint?: string | number; |
| 104 | + opacity?: string | number; |
| 105 | + shear?: string; |
| 106 | + border?: string; |
107 | 107 | loaderOptions?: { |
108 | | - width: number | string |
109 | | - } |
| 108 | + width: number | string; |
| 109 | + }; |
110 | 110 | } |
111 | 111 |
|
112 | | -const props = defineProps<CldImageProps>() |
| 112 | +const props = defineProps<CldImageProps>(); |
113 | 113 |
|
114 | | -const { config, loaderOptions, ...options } = props |
| 114 | +const { config, loaderOptions, ...options } = props; |
115 | 115 |
|
116 | | -const { url } = useCldImageUrl({ options, config } as ConstructUrlProps) |
| 116 | +const { url } = useCldImageUrl({ options, config } as ConstructUrlProps); |
117 | 117 |
|
118 | 118 | const transformUrl = () => { |
119 | 119 | const options = { |
120 | 120 | ...props, |
121 | | - } |
| 121 | + }; |
122 | 122 |
|
123 | | - options.width |
124 | | - = typeof options.width === 'string' |
| 123 | + options.width = |
| 124 | + typeof options.width === "string" |
125 | 125 | ? Number.parseInt(options.width) |
126 | | - : options.width |
127 | | - options.height |
128 | | - = typeof options.height === 'string' |
| 126 | + : options.width; |
| 127 | + options.height = |
| 128 | + typeof options.height === "string" |
129 | 129 | ? Number.parseInt(options.height) |
130 | | - : options.height |
| 130 | + : options.height; |
131 | 131 |
|
132 | | - let widthResize |
| 132 | + let widthResize; |
133 | 133 |
|
134 | 134 | if ( |
135 | | - typeof loaderOptions?.width === 'number' |
136 | | - && typeof options.width === 'number' |
137 | | - && loaderOptions.width !== options.width |
| 135 | + typeof loaderOptions?.width === "number" && |
| 136 | + typeof options.width === "number" && |
| 137 | + loaderOptions.width !== options.width |
138 | 138 | ) { |
139 | | - widthResize = loaderOptions.width |
140 | | - } |
141 | | - else if ( |
142 | | - typeof loaderOptions?.width === 'number' |
143 | | - && typeof options?.width !== 'number' |
| 139 | + widthResize = loaderOptions.width; |
| 140 | + } else if ( |
| 141 | + typeof loaderOptions?.width === "number" && |
| 142 | + typeof options?.width !== "number" |
144 | 143 | ) { |
145 | | - widthResize = loaderOptions.width |
146 | | - options.width = widthResize |
| 144 | + widthResize = loaderOptions.width; |
| 145 | + options.width = widthResize; |
147 | 146 | } |
148 | 147 |
|
149 | 148 | // If we have a resize width that's smaller than the user-defined width, we want to give the |
150 | 149 | // ability to perform a final resize on the image without impacting any of the effects like text |
151 | 150 | // overlays that may depend on the size to work properly |
152 | 151 |
|
153 | 152 | if (options.width && widthResize && widthResize < options.width) { |
154 | | - options.widthResize = loaderOptions?.width |
| 153 | + options.widthResize = loaderOptions?.width; |
155 | 154 | } |
156 | 155 |
|
157 | | - const { url } = useCldImageUrl({ options, config } as ConstructUrlProps) |
| 156 | + const { url } = useCldImageUrl({ options, config } as ConstructUrlProps); |
158 | 157 |
|
159 | | - return url |
160 | | -} |
| 158 | + return url; |
| 159 | +}; |
161 | 160 |
|
162 | | -const imgKey = ref('image-key') |
| 161 | +const imgKey = ref("image-key"); |
163 | 162 |
|
164 | 163 | const handleError = async (payload: Event) => { |
165 | | - const result = await pollForProcessingImage(payload) |
| 164 | + const result = await pollForProcessingImage(payload); |
166 | 165 |
|
167 | | - if (result) imgKey.value = `${imgKey.value}-${Math.random()}` |
168 | | -} |
| 166 | + if (result) imgKey.value = `${imgKey.value}-${Math.random()}`; |
| 167 | +}; |
169 | 168 |
|
170 | 169 | const pollForProcessingImage = async (options: Event): Promise<boolean> => { |
171 | | - const { src } = options.target as EventTarget & { src: string } |
| 170 | + const { src } = options.target as EventTarget & { src: string }; |
172 | 171 | try { |
173 | 172 | await new Promise((resolve, reject) => { |
174 | 173 | fetch(src).then((res) => { |
175 | 174 | if (!res.ok) { |
176 | | - reject(res) |
177 | | - return |
| 175 | + reject(res); |
| 176 | + return; |
178 | 177 | } |
179 | | - resolve(res) |
180 | | - }) |
181 | | - }) |
182 | | - } |
183 | | - catch (e: any) { |
| 178 | + resolve(res); |
| 179 | + }); |
| 180 | + }); |
| 181 | + } catch (e: any) { |
184 | 182 | if (e.status === 423) { |
185 | | - return await pollForProcessingImage(options) |
| 183 | + return await pollForProcessingImage(options); |
186 | 184 | } |
187 | | - return false |
| 185 | + return false; |
188 | 186 | } |
189 | | - return true |
190 | | -} |
| 187 | + return true; |
| 188 | +}; |
191 | 189 | </script> |
192 | 190 |
|
193 | 191 | <template> |
|
0 commit comments