@archvisioninc/canvas 2.8.7 → 3.0.0

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/README.md CHANGED
@@ -1,2 +1,2 @@
1
- ## GET STARTED
1
+ ## GET STARTED
2
2
  Please see [developer documentation](https://github.com/ArchvisionInc/archvision-canvas/blob/main/README_DEV.md), in the repository.
@@ -139,6 +139,102 @@ const applyUVSettings = args => {
139
139
  texture.vScale = uvYScale;
140
140
  }
141
141
  };
142
+
143
+ // TODO: Future uses should support red, green, blue, and alpha channels with defaults for each
144
+ const combineMetallicRoughnessTextures = (metallicImage, roughnessImage) => {
145
+ const roughnessHeight = roughnessImage.naturalHeight;
146
+ const roughnessWidth = roughnessImage.naturalWidth;
147
+ const metallicHeight = metallicImage.naturalHeight;
148
+ const metallicWidth = metallicImage.naturalWidth;
149
+ const maxHeight = Math.max(roughnessHeight, metallicHeight);
150
+ const maxWidth = Math.max(roughnessWidth, metallicWidth);
151
+ const canvas = document.createElement('canvas');
152
+ const ctx = canvas.getContext('2d');
153
+ canvas.width = maxWidth;
154
+ canvas.height = maxHeight;
155
+ ctx.drawImage(roughnessImage, 0, 0, maxWidth, maxHeight);
156
+ const roughnessData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
157
+ ctx.drawImage(metallicImage, 0, 0, maxWidth, maxHeight);
158
+ const metallicData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
159
+ const combinedImageData = ctx.createImageData(maxWidth, maxHeight);
160
+ const combinedData = combinedImageData.data;
161
+ for (let i = 0; i < combinedData.length; i += 4) {
162
+ combinedData[i] = 255;
163
+ combinedData[i + 1] = roughnessData[i + 1];
164
+ combinedData[i + 2] = metallicData[i + 2];
165
+ combinedData[i + 3] = 255;
166
+ }
167
+ ctx.putImageData(combinedImageData, 0, 0);
168
+ return canvas.toDataURL('image/png');
169
+ };
170
+
171
+ // eslint-disable-next-line
172
+ const loadImage = async file => {
173
+ return new Promise((resolve, reject) => {
174
+ const reader = new FileReader();
175
+ reader.onload = event => {
176
+ const img = new Image();
177
+ img.onload = () => {
178
+ resolve(img);
179
+ };
180
+ img.onerror = reject;
181
+ img.src = event.target.result;
182
+ };
183
+ reader.onerror = reject;
184
+ reader.readAsDataURL(file);
185
+ });
186
+ };
187
+ const textureToImage = (texture, textureName) => {
188
+ return new Promise((resolve, reject) => {
189
+ texture.readPixels().then(pixels => {
190
+ const canvas = document.createElement('canvas');
191
+ const ctx = canvas.getContext('2d');
192
+ const {
193
+ width,
194
+ height
195
+ } = texture.getSize();
196
+ canvas.width = width;
197
+ canvas.height = height;
198
+ const img = new Image();
199
+ const imageData = ctx.createImageData(width, height);
200
+ imageData.data.set(new Uint8ClampedArray(pixels));
201
+ ctx.putImageData(imageData, 0, 0);
202
+ img.onload = () => {
203
+ resolve(img);
204
+ };
205
+ img.onerror = event => {
206
+ console.log(`Error loading image: ${textureName}`);
207
+ reject(event);
208
+ };
209
+ img.src = canvas.toDataURL();
210
+ });
211
+ });
212
+ };
213
+ const dataUrlToBlob = dataURI => {
214
+ // convert base64 to raw binary data held in a string
215
+ // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
216
+ const byteString = atob(dataURI.split(',')[1]);
217
+
218
+ // separate out the mime component
219
+ const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
220
+
221
+ // write the bytes of the string to an ArrayBuffer
222
+ const ab = new ArrayBuffer(byteString.length);
223
+
224
+ // create a view into the buffer
225
+ const ia = new Uint8Array(ab);
226
+
227
+ // set the bytes of the buffer to the correct values
228
+ for (let i = 0; i < byteString.length; i++) {
229
+ ia[i] = byteString.charCodeAt(i);
230
+ }
231
+
232
+ // write the ArrayBuffer to a blob, and you're done
233
+ const blob = new Blob([ab], {
234
+ type: mimeString
235
+ });
236
+ return blob;
237
+ };
142
238
  export const updateMaterial = inboundData => {
143
239
  const {
144
240
  payload
@@ -158,6 +254,7 @@ export const updateMaterial = inboundData => {
158
254
  metallic,
159
255
  metallicTexture,
160
256
  roughness,
257
+ roughnessTexture,
161
258
  microSurfaceTexture,
162
259
  emissiveColor,
163
260
  emissiveIntensity,
@@ -261,12 +358,24 @@ export const updateMaterial = inboundData => {
261
358
  // Metallic
262
359
  if (metallic !== undefined) material.metallic = metallic;
263
360
  if (!_.isEmpty(metallicTexture?.src || metallicTexture?.url)) {
264
- material.metallicTexture = newTexture(metallicTexture?.src || metallicTexture?.url);
265
- material.metallicTexture.name = metallicTexture.name;
266
- applyUVSettings({
267
- texture: material.metallicTexture,
268
- material
269
- });
361
+ // Metallic Texture uses the B channel of the metallicTexture for a PBRMaterial
362
+ const texture = newTexture(metallicTexture?.src || metallicTexture?.url);
363
+ let currentTexture = material.metallicTexture;
364
+ if (!currentTexture) {
365
+ material.metallicTexture = newTexture();
366
+ currentTexture = material.metallicTexture;
367
+ }
368
+ const metallicBlob = dataUrlToBlob(texture.url);
369
+ Promise.all([loadImage(metallicBlob), textureToImage(currentTexture, 'metallic')]).then(data => {
370
+ const [metallicImage, currentImage] = data;
371
+ const combinedTexture = combineMetallicRoughnessTextures(metallicImage, currentImage);
372
+ currentTexture.updateURL(combinedTexture);
373
+ texture.dispose();
374
+ applyUVSettings({
375
+ texture: material.metallicTexture,
376
+ material
377
+ });
378
+ }).catch(() => console.log(`Error updating the metallic texture of material: ${material.name}`));
270
379
  }
271
380
 
272
381
  // Roughness
@@ -279,6 +388,26 @@ export const updateMaterial = inboundData => {
279
388
  material
280
389
  });
281
390
  }
391
+ if (!_.isEmpty(roughnessTexture?.src || roughnessTexture?.url)) {
392
+ // Roughness Texture uses the G channel of the metallicTexture for a PBRMaterial
393
+ const texture = newTexture(roughnessTexture?.src || roughnessTexture?.url);
394
+ let currentTexture = material.metallicTexture;
395
+ if (!currentTexture) {
396
+ material.metallicTexture = newTexture();
397
+ currentTexture = material.metallicTexture;
398
+ }
399
+ const roughnessBlob = dataUrlToBlob(texture.url);
400
+ Promise.all([loadImage(roughnessBlob), textureToImage(currentTexture, 'metallic')]).then(data => {
401
+ const [roughnessImage, metallicImage] = data;
402
+ const combinedTexture = combineMetallicRoughnessTextures(metallicImage, roughnessImage);
403
+ currentTexture.updateURL(combinedTexture);
404
+ texture.dispose();
405
+ applyUVSettings({
406
+ texture: material.metallicTexture,
407
+ material
408
+ });
409
+ }).catch(() => console.log(`Error updating the roughness texture of material: ${material.name}`));
410
+ }
282
411
 
283
412
  // Emissive
284
413
  if (emissiveColor) material.emissiveColor = newColor(emissiveColor);
package/jsconfig.json CHANGED
@@ -1,6 +1,6 @@
1
- {
2
- "compilerOptions": {
3
- "baseUrl": "src"
4
- },
5
- "include": ["src"]
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": "src"
4
+ },
5
+ "include": ["src"]
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archvisioninc/canvas",
3
- "version": "2.8.7",
3
+ "version": "3.0.0",
4
4
  "private": false,
5
5
  "main": "dist/Canvas.js",
6
6
  "module": "dist/Canvas.js",
package/public/index.html CHANGED
@@ -1,21 +1,21 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8" />
5
- <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6
- <meta name="viewport" content="width=device-width, initial-scale=1" />
7
- <meta name="theme-color" content="#000000" />
8
- <meta
9
- name="description"
10
- content="Web site created using create-react-app"
11
- />
12
- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
13
- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
14
- <title>React App</title>
15
- </head>
16
-
17
- <body>
18
- <noscript>You need to enable JavaScript to run this app.</noscript>
19
- <div id="root"></div>
20
- </body>
21
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <meta name="theme-color" content="#000000" />
8
+ <meta
9
+ name="description"
10
+ content="Web site created using create-react-app"
11
+ />
12
+ <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
13
+ <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
14
+ <title>React App</title>
15
+ </head>
16
+
17
+ <body>
18
+ <noscript>You need to enable JavaScript to run this app.</noscript>
19
+ <div id="root"></div>
20
+ </body>
21
+ </html>
@@ -1,25 +1,25 @@
1
- {
2
- "short_name": "React App",
3
- "name": "Create React App Sample",
4
- "icons": [
5
- {
6
- "src": "favicon.ico",
7
- "sizes": "64x64 32x32 24x24 16x16",
8
- "type": "image/x-icon"
9
- },
10
- {
11
- "src": "logo192.png",
12
- "type": "image/png",
13
- "sizes": "192x192"
14
- },
15
- {
16
- "src": "logo512.png",
17
- "type": "image/png",
18
- "sizes": "512x512"
19
- }
20
- ],
21
- "start_url": ".",
22
- "display": "standalone",
23
- "theme_color": "#000000",
24
- "background_color": "#ffffff"
25
- }
1
+ {
2
+ "short_name": "React App",
3
+ "name": "Create React App Sample",
4
+ "icons": [
5
+ {
6
+ "src": "favicon.ico",
7
+ "sizes": "64x64 32x32 24x24 16x16",
8
+ "type": "image/x-icon"
9
+ },
10
+ {
11
+ "src": "logo192.png",
12
+ "type": "image/png",
13
+ "sizes": "192x192"
14
+ },
15
+ {
16
+ "src": "logo512.png",
17
+ "type": "image/png",
18
+ "sizes": "512x512"
19
+ }
20
+ ],
21
+ "start_url": ".",
22
+ "display": "standalone",
23
+ "theme_color": "#000000",
24
+ "background_color": "#ffffff"
25
+ }
package/public/robots.txt CHANGED
@@ -1,3 +1,3 @@
1
- # https://www.robotstxt.org/robotstxt.html
2
- User-agent: *
3
- Disallow:
1
+ # https://www.robotstxt.org/robotstxt.html
2
+ User-agent: *
3
+ Disallow:
@@ -14,7 +14,7 @@ export const fetchDownloadURL = async args => {
14
14
  if (!_.isEmpty(rpcGuid)) {
15
15
  const servicesURL = `https://api.archvision.services/rpc/v1/integration/${rpcGuid}/download/${format}`;
16
16
  // eslint-disable-next-line
17
- const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FyY2h2aXNpb24uY29tIiwic3ViIjozOTUxNTcsInRva2VuX3R5cGUiOiJiZWFyZXIiLCJzY29wZSI6ImJhc2ljIiwiYXVkIjoiNDVFUnF3SEV5SWRqbXhkaUU4MUxMbDlFYTN2SzZZQ3dLNWE2R2xEMyIsImlhdCI6MTcwOTY1MDM5OSwiZXhwIjoxNzE0ODM0Mzk5fQ.aCtOw3h-BTTiIEcvb0FeA_XhRpEmzQTfyerRUu4JGuU';
17
+ const token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjE2MDAyMDc3ODQifQ.eyJpZCI6ImowbzVobDJkdXc5ZXZ4bXJubGIxZWh6a3lhYmJmN3d6ZzN3Z2g3c2kiLCJqdGkiOiJqMG81aGwyZHV3OWV2eG1ybmxiMWVoemt5YWJiZjd3emczd2doN3NpIiwiaXNzIjoiaHR0cHM6XC9cL2FyY2h2aXNpb24uY29tIiwiYXVkIjoiNDVFUnF3SEV5SWRqbXhkaUU4MUxMbDlFYTN2SzZZQ3dLNWE2R2xEMyIsInN1YiI6IjM5MDQxOSIsImV4cCI6MTc0ODI3ODEwNiwiaWF0IjoxNzE3MTc4MTA2LCJ0b2tlbl90eXBlIjoiYmVhcmVyIiwic2NvcGUiOiJiYXNpYyJ9.xKpX0xCEdoVpn-GGdmRWcMPp3pEa7PUbMxlhuAsNjL1ZoFIbxwTrAoXDnvozxjdxomxM7nFw05I1caGtfJARPipOSLFgzD1ANYvogmAImg1zXUV8RsHEVaApxhdwUS7IPO13K3QJMGmn-NgqpYly9ZF9XYxZ7twT4JneGmc_WzeairT9qqGLhKXuU_tkJ49tKAXfCSHAFFBkb93nnsrpd-RlsIeQnc7puTqxlKTREzvmW3_RdqO_1X9ohlnn3wWBEFo_a0W770lfWoF1JlJIqd9NIPrgVRG5inRmYNEz6gw5yLHcDDG-Z5DrQExVUJkYV81wBK2krr0AgX45CWTEdQ';
18
18
  const options = {
19
19
  method: 'GET',
20
20
  headers: {
@@ -42,4 +42,4 @@ export const fetchDownloadURL = async args => {
42
42
  clearExisting,
43
43
  );
44
44
  }
45
- };
45
+ };
@@ -177,6 +177,119 @@ const applyUVSettings = args => {
177
177
  }
178
178
  };
179
179
 
180
+ // TODO: Future uses should support red, green, blue, and alpha channels with defaults for each
181
+ const combineMetallicRoughnessTextures = (metallicImage, roughnessImage) => {
182
+ const roughnessHeight = roughnessImage.naturalHeight;
183
+ const roughnessWidth = roughnessImage.naturalWidth;
184
+ const metallicHeight = metallicImage.naturalHeight;
185
+ const metallicWidth = metallicImage.naturalWidth;
186
+
187
+ const maxHeight = Math.max(roughnessHeight, metallicHeight);
188
+ const maxWidth = Math.max(roughnessWidth, metallicWidth);
189
+
190
+ const canvas = document.createElement('canvas');
191
+
192
+ const ctx = canvas.getContext('2d');
193
+
194
+ canvas.width = maxWidth;
195
+ canvas.height = maxHeight;
196
+
197
+ ctx.drawImage(roughnessImage, 0, 0, maxWidth, maxHeight);
198
+ const roughnessData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
199
+
200
+ ctx.drawImage(metallicImage, 0, 0, maxWidth, maxHeight);
201
+ const metallicData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
202
+
203
+ const combinedImageData = ctx.createImageData(maxWidth, maxHeight);
204
+ const combinedData = combinedImageData.data;
205
+
206
+ for (let i = 0; i < combinedData.length; i += 4) {
207
+ combinedData[i] = 255;
208
+ combinedData[i + 1] = roughnessData[i + 1];
209
+ combinedData[i + 2] = metallicData[i + 2];
210
+ combinedData[i + 3] = 255;
211
+ }
212
+
213
+ ctx.putImageData(combinedImageData, 0, 0);
214
+
215
+ return canvas.toDataURL('image/png');
216
+
217
+ };
218
+
219
+ // eslint-disable-next-line
220
+ const loadImage = async file => {
221
+ return new Promise((resolve, reject) => {
222
+ const reader = new FileReader();
223
+ reader.onload = event => {
224
+ const img = new Image();
225
+ img.onload = () => {
226
+ resolve(img);
227
+ };
228
+ img.onerror = reject;
229
+ img.src = event.target.result;
230
+ };
231
+ reader.onerror = reject;
232
+ reader.readAsDataURL(file);
233
+ });
234
+ };
235
+
236
+ const textureToImage = (texture, textureName) => {
237
+ return new Promise((resolve, reject) => {
238
+ texture.readPixels()
239
+ .then(pixels => {
240
+ const canvas = document.createElement('canvas');
241
+ const ctx = canvas.getContext('2d');
242
+ const { width, height } = texture.getSize();
243
+
244
+ canvas.width = width;
245
+ canvas.height = height;
246
+
247
+ const img = new Image();
248
+ const imageData = ctx.createImageData(width, height);
249
+ imageData.data.set(new Uint8ClampedArray(pixels));
250
+
251
+ ctx.putImageData(imageData, 0, 0);
252
+
253
+ img.onload = () => {
254
+ resolve(img);
255
+ };
256
+
257
+ img.onerror = event => {
258
+ console.log(`Error loading image: ${textureName}`);
259
+ reject(event);
260
+ };
261
+
262
+
263
+ img.src = canvas.toDataURL();
264
+ });
265
+
266
+ });
267
+ };
268
+
269
+ const dataUrlToBlob = dataURI => {
270
+ // convert base64 to raw binary data held in a string
271
+ // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
272
+ const byteString = atob(dataURI.split(',')[1]);
273
+
274
+ // separate out the mime component
275
+ const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
276
+
277
+ // write the bytes of the string to an ArrayBuffer
278
+ const ab = new ArrayBuffer(byteString.length);
279
+
280
+ // create a view into the buffer
281
+ const ia = new Uint8Array(ab);
282
+
283
+ // set the bytes of the buffer to the correct values
284
+ for (let i = 0; i < byteString.length; i++) {
285
+ ia[i] = byteString.charCodeAt(i);
286
+ }
287
+
288
+ // write the ArrayBuffer to a blob, and you're done
289
+ const blob = new Blob([ ab ], { type: mimeString });
290
+ return blob;
291
+ };
292
+
180
293
  export const updateMaterial = inboundData => {
181
294
  const { payload } = inboundData;
182
295
  const {
@@ -194,6 +307,7 @@ export const updateMaterial = inboundData => {
194
307
  metallic,
195
308
  metallicTexture,
196
309
  roughness,
310
+ roughnessTexture,
197
311
  microSurfaceTexture,
198
312
  emissiveColor,
199
313
  emissiveIntensity,
@@ -293,10 +407,26 @@ export const updateMaterial = inboundData => {
293
407
  // Metallic
294
408
  if (metallic !== undefined) material.metallic = metallic;
295
409
  if (!_.isEmpty(metallicTexture?.src || metallicTexture?.url)) {
296
- material.metallicTexture = newTexture(metallicTexture?.src || metallicTexture?.url);
297
- material.metallicTexture.name = metallicTexture.name;
410
+ // Metallic Texture uses the B channel of the metallicTexture for a PBRMaterial
411
+ const texture = newTexture(metallicTexture?.src || metallicTexture?.url);
412
+ let currentTexture = material.metallicTexture;
413
+ if (!currentTexture) {
414
+ material.metallicTexture = newTexture();
415
+ currentTexture = material.metallicTexture;
416
+ }
417
+
418
+ const metallicBlob = dataUrlToBlob(texture.url);
298
419
 
299
- applyUVSettings({ texture: material.metallicTexture, material });
420
+ Promise.all([ loadImage(metallicBlob), textureToImage(currentTexture, 'metallic') ])
421
+ .then(data => {
422
+ const [ metallicImage, currentImage ] = data;
423
+ const combinedTexture = combineMetallicRoughnessTextures(metallicImage, currentImage);
424
+ currentTexture.updateURL(combinedTexture);
425
+
426
+ texture.dispose();
427
+ applyUVSettings({ texture: material.metallicTexture, material });
428
+ })
429
+ .catch(() => console.log(`Error updating the metallic texture of material: ${material.name}`));
300
430
  }
301
431
 
302
432
  // Roughness
@@ -308,6 +438,30 @@ export const updateMaterial = inboundData => {
308
438
  applyUVSettings({ texture: material.microSurfaceTexture, material });
309
439
  }
310
440
 
441
+ if (!_.isEmpty(roughnessTexture?.src || roughnessTexture?.url)) {
442
+ // Roughness Texture uses the G channel of the metallicTexture for a PBRMaterial
443
+ const texture = newTexture(roughnessTexture?.src || roughnessTexture?.url);
444
+ let currentTexture = material.metallicTexture;
445
+ if (!currentTexture) {
446
+ material.metallicTexture = newTexture();
447
+ currentTexture = material.metallicTexture;
448
+ }
449
+
450
+ const roughnessBlob = dataUrlToBlob(texture.url);
451
+
452
+ Promise.all([ loadImage(roughnessBlob), textureToImage(currentTexture, 'metallic') ])
453
+ .then(data => {
454
+ const [ roughnessImage, metallicImage ] = data;
455
+ const combinedTexture = combineMetallicRoughnessTextures(metallicImage, roughnessImage);
456
+ currentTexture.updateURL(combinedTexture);
457
+
458
+ texture.dispose();
459
+ applyUVSettings({ texture: material.metallicTexture, material });
460
+ })
461
+ .catch(() => console.log(`Error updating the roughness texture of material: ${material.name}`));
462
+
463
+ }
464
+
311
465
  // Emissive
312
466
  if (emissiveColor) material.emissiveColor = newColor(emissiveColor);
313
467
  if (emissiveIntensity !== undefined) material.emissiveIntensity = emissiveIntensity;
@@ -948,4 +1102,4 @@ export const updatePublish = inboundData => {
948
1102
  };
949
1103
 
950
1104
  newMetaDataEntry('publish', withOptimizationValues);
951
- };
1105
+ };
@@ -9,7 +9,7 @@ import { updateMaterial, scene } from 'package/helpers';
9
9
  import Canvas from 'package/Canvas';
10
10
  import _ from 'lodash';
11
11
 
12
- const materialMode = true;
12
+ const materialMode = false;
13
13
  const previewMode = false;
14
14
  const demoScene = false;
15
15
  const shaderballGuid = '21-791A-0D8D-F8A0-63F7-5086-471F-69A7-7AB0-00';
@@ -127,6 +127,24 @@ const App = () => {
127
127
  const updatedArray = notifications.filter((item, i) => index !== i);
128
128
  setNotifications(updatedArray);
129
129
  };
130
+ const onImageLoad = args => {
131
+ const inboundData = {
132
+ payload: {
133
+ id: 'Material Metal PBR Rich',
134
+ metallicTexture: args,
135
+ },
136
+ };
137
+
138
+ updateMaterial(inboundData);
139
+
140
+ };
141
+
142
+ const handleUpload = e => {
143
+ const file = e.currentTarget.files[0];
144
+ const reader = new FileReader();
145
+ reader.readAsDataURL(file);
146
+ reader.onload = () => onImageLoad({ name: file.name, src: reader.result });
147
+ };
130
148
 
131
149
  useEffect(() => {
132
150
  getPreviewURL();
@@ -189,6 +207,8 @@ const App = () => {
189
207
  Import material
190
208
  </Button>
191
209
 
210
+ <input type={'file'} onChange={handleUpload} accept={'image/*'} />
211
+
192
212
  <Button
193
213
  theme={theme}
194
214
  $selectedTheme={selectedTheme}
@@ -249,4 +269,4 @@ const App = () => {
249
269
  );
250
270
  };
251
271
 
252
- export default App;
272
+ export default App;
@@ -1,8 +1,8 @@
1
- import { render, screen } from '@testing-library/react';
2
- import App from './App';
3
-
4
- test('renders learn react link', () => {
5
- render(<App />);
6
- const linkElement = screen.getByText(/learn react/i);
7
- expect(linkElement).toBeInTheDocument();
8
- });
1
+ import { render, screen } from '@testing-library/react';
2
+ import App from './App';
3
+
4
+ test('renders learn react link', () => {
5
+ render(<App />);
6
+ const linkElement = screen.getByText(/learn react/i);
7
+ expect(linkElement).toBeInTheDocument();
8
+ });
package/src/setupTests.js CHANGED
@@ -1,5 +1,5 @@
1
- // jest-dom adds custom jest matchers for asserting on DOM nodes.
2
- // allows you to do things like:
3
- // expect(element).toHaveTextContent(/react/i)
4
- // learn more: https://github.com/testing-library/jest-dom
5
- import '@testing-library/jest-dom';
1
+ // jest-dom adds custom jest matchers for asserting on DOM nodes.
2
+ // allows you to do things like:
3
+ // expect(element).toHaveTextContent(/react/i)
4
+ // learn more: https://github.com/testing-library/jest-dom
5
+ import '@testing-library/jest-dom';