|
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 | object; |
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 | | - } else if ( |
141 | | - typeof loaderOptions?.width === "number" && |
142 | | - typeof options?.width !== "number" |
| 139 | + widthResize = loaderOptions.width |
| 140 | + } |
| 141 | + else if ( |
| 142 | + typeof loaderOptions?.width === 'number' |
| 143 | + && typeof options?.width !== 'number' |
143 | 144 | ) { |
144 | | - widthResize = loaderOptions.width; |
145 | | - options.width = widthResize; |
| 145 | + widthResize = loaderOptions.width |
| 146 | + options.width = widthResize |
146 | 147 | } |
147 | 148 |
|
148 | 149 | // If we have a resize width that's smaller than the user-defined width, we want to give the |
149 | 150 | // ability to perform a final resize on the image without impacting any of the effects like text |
150 | 151 | // overlays that may depend on the size to work properly |
151 | 152 |
|
152 | 153 | if (options.width && widthResize && widthResize < options.width) { |
153 | | - options.widthResize = loaderOptions?.width; |
| 154 | + options.widthResize = loaderOptions?.width |
154 | 155 | } |
155 | 156 |
|
156 | | - const { url } = useCldImageUrl({ options, config } as ConstructUrlProps); |
| 157 | + const { url } = useCldImageUrl({ options, config } as ConstructUrlProps) |
157 | 158 |
|
158 | | - return url; |
159 | | -}; |
| 159 | + return url |
| 160 | +} |
160 | 161 |
|
161 | | -const imgKey = ref("image-key"); |
| 162 | +const imgKey = ref('image-key') |
162 | 163 |
|
163 | 164 | const handleError = async (payload: Event) => { |
164 | | - const result = await pollForProcessingImage(payload); |
| 165 | + const result = await pollForProcessingImage(payload) |
165 | 166 |
|
166 | | - if (result) imgKey.value = `${imgKey.value}-${Math.random()}`; |
167 | | -}; |
| 167 | + if (result) imgKey.value = `${imgKey.value}-${Math.random()}` |
| 168 | +} |
168 | 169 |
|
169 | 170 | const pollForProcessingImage = async (options: Event): Promise<boolean> => { |
170 | | - const { src } = options.target as EventTarget & { src: string }; |
| 171 | + const { src } = options.target as EventTarget & { src: string } |
171 | 172 | try { |
172 | 173 | await new Promise((resolve, reject) => { |
173 | 174 | fetch(src).then((res) => { |
174 | 175 | if (!res.ok) { |
175 | | - reject(res); |
176 | | - return; |
| 176 | + reject(res) |
| 177 | + return |
177 | 178 | } |
178 | | - resolve(res); |
179 | | - }); |
180 | | - }); |
181 | | - } catch (e: any) { |
| 179 | + resolve(res) |
| 180 | + }) |
| 181 | + }) |
| 182 | + } |
| 183 | + catch (e: any) { |
182 | 184 | if (e.status === 423) { |
183 | | - return await pollForProcessingImage(options); |
| 185 | + return await pollForProcessingImage(options) |
184 | 186 | } |
185 | | - return false; |
| 187 | + return false |
186 | 188 | } |
187 | | - return true; |
188 | | -}; |
| 189 | + return true |
| 190 | +} |
189 | 191 | </script> |
190 | 192 |
|
191 | 193 | <template> |
|
0 commit comments