universal-test-renderer 0.3.0-react19.0 → 0.4.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/dist/index.js CHANGED
@@ -32,7 +32,10 @@ var __objRest = (source, exclude) => {
32
32
 
33
33
  // src/reconciler.ts
34
34
  import ReactReconciler from "react-reconciler";
35
- import { DefaultEventPriority } from "react-reconciler/constants";
35
+ import {
36
+ DefaultEventPriority,
37
+ NoEventPriority
38
+ } from "react-reconciler/constants";
36
39
 
37
40
  // src/utils.ts
38
41
  function formatComponentList(names) {
@@ -51,8 +54,6 @@ function formatComponentList(names) {
51
54
  }
52
55
 
53
56
  // src/reconciler.ts
54
- var NoEventPriority = 0;
55
- var UPDATE_SIGNAL = {};
56
57
  var nodeToInstanceMap = /* @__PURE__ */ new WeakMap();
57
58
  var currentUpdatePriority = NoEventPriority;
58
59
  var hostConfig = {
@@ -95,6 +96,8 @@ var hostConfig = {
95
96
  */
96
97
  supportsPersistence: false,
97
98
  /**
99
+ * #### `createInstance(type, props, rootContainer, hostContext, internalHandle)`
100
+ *
98
101
  * This method should return a newly created node. For example, the DOM renderer would call
99
102
  * `document.createElement(type)` here and then set the properties from `props`.
100
103
  *
@@ -127,14 +130,16 @@ var hostConfig = {
127
130
  };
128
131
  },
129
132
  /**
133
+ * #### `createTextInstance(text, rootContainer, hostContext, internalHandle)`
134
+ *
130
135
  * Same as `createInstance`, but for text nodes. If your renderer doesn't support text nodes, you can
131
136
  * throw here.
132
137
  */
133
138
  createTextInstance(text, rootContainer, hostContext, _internalHandle) {
134
- if (rootContainer.textComponents && !hostContext.isInsideText) {
139
+ if (rootContainer.config.textComponents && !hostContext.isInsideText) {
135
140
  throw new Error(
136
141
  `Invariant Violation: Text strings must be rendered within a ${formatComponentList(
137
- rootContainer.textComponents
142
+ rootContainer.config.textComponents
138
143
  )} component. Detected attempt to render "${text}" string within a <${hostContext.type}> component.`
139
144
  );
140
145
  }
@@ -145,8 +150,20 @@ var hostConfig = {
145
150
  isHidden: false
146
151
  };
147
152
  },
153
+ /**
154
+ * #### `appendInitialChild(parentInstance, child)`
155
+ *
156
+ * This method should mutate the `parentInstance` and add the child to its list of children.
157
+ * For example, in the DOM this would translate to a `parentInstance.appendChild(child)` call.
158
+ *
159
+ * This method happens **in the render phase**. It can mutate `parentInstance` and `child`, but it
160
+ * must not modify any other nodes. It's called while the tree is still being built up and not connected
161
+ * to the actual tree on the screen.
162
+ */
148
163
  appendInitialChild: appendChild,
149
164
  /**
165
+ * #### `finalizeInitialChildren(instance, type, props, rootContainer, hostContext)`
166
+ *
150
167
  * In this method, you can perform some final mutations on the `instance`. Unlike with `createInstance`,
151
168
  * by the time `finalizeInitialChildren` is called, all the initial children have already been added to
152
169
  * the `instance`, but the instance itself has not yet been connected to the tree on the screen.
@@ -164,22 +181,8 @@ var hostConfig = {
164
181
  return false;
165
182
  },
166
183
  /**
167
- * React calls this method so that you can compare the previous and the next props, and decide whether you
168
- * need to update the underlying instance or not. If you don't need to update it, return `null`. If you
169
- * need to update it, you can return an arbitrary object representing the changes that need to happen.
170
- * Then in `commitUpdate` you would need to apply those changes to the instance.
171
- *
172
- * This method happens **in the render phase**. It should only *calculate* the update — but not apply it!
173
- * For example, the DOM renderer returns an array that looks like `[prop1, value1, prop2, value2, ...]`
174
- * for all props that have actually changed. And only in `commitUpdate` it applies those changes. You should
175
- * calculate as much as you can in `prepareUpdate` so that `commitUpdate` can be very fast and straightforward.
184
+ * #### `shouldSetTextContent(type, props)`
176
185
  *
177
- * See the meaning of `rootContainer` and `hostContext` in the `createInstance` documentation.
178
- */
179
- prepareUpdate(_instance, _type, _oldProps, _newProps, _rootContainer, _hostContext) {
180
- return UPDATE_SIGNAL;
181
- },
182
- /**
183
186
  * Some target platforms support setting an instance's text content without manually creating a text node.
184
187
  * For example, in the DOM, you can set `node.textContent` instead of creating a text node and appending it.
185
188
  *
@@ -195,7 +198,21 @@ var hostConfig = {
195
198
  shouldSetTextContent(_type, _props) {
196
199
  return false;
197
200
  },
201
+ setCurrentUpdatePriority(newPriority) {
202
+ currentUpdatePriority = newPriority;
203
+ },
204
+ getCurrentUpdatePriority() {
205
+ return currentUpdatePriority;
206
+ },
207
+ resolveUpdatePriority() {
208
+ return currentUpdatePriority || DefaultEventPriority;
209
+ },
210
+ shouldAttemptEagerTransition() {
211
+ return false;
212
+ },
198
213
  /**
214
+ * #### `getRootHostContext(rootContainer)`
215
+ *
199
216
  * This method lets you return the initial host context from the root of the tree. See `getChildHostContext`
200
217
  * for the explanation of host context.
201
218
  *
@@ -205,11 +222,13 @@ var hostConfig = {
205
222
  getRootHostContext(rootContainer) {
206
223
  return {
207
224
  type: "ROOT",
208
- isInsideText: false,
209
- textComponents: rootContainer.textComponents
225
+ config: rootContainer.config,
226
+ isInsideText: false
210
227
  };
211
228
  },
212
229
  /**
230
+ * #### `getChildHostContext(parentHostContext, type, rootContainer)`
231
+ *
213
232
  * Host context lets you track some information about where you are in the tree so that it's available
214
233
  * inside `createInstance` as the `hostContext` parameter. For example, the DOM renderer uses it to track
215
234
  * whether it's inside an HTML or an SVG tree, because `createInstance` implementation needs to be
@@ -226,11 +245,13 @@ var hostConfig = {
226
245
  getChildHostContext(parentHostContext, type) {
227
246
  var _a;
228
247
  const isInsideText = Boolean(
229
- (_a = parentHostContext.textComponents) == null ? void 0 : _a.includes(type)
248
+ (_a = parentHostContext.config.textComponents) == null ? void 0 : _a.includes(type)
230
249
  );
231
250
  return __spreadProps(__spreadValues({}, parentHostContext), { type, isInsideText });
232
251
  },
233
252
  /**
253
+ * #### `getPublicInstance(instance)`
254
+ *
234
255
  * Determines what object gets exposed as a ref. You'll likely want to return the `instance` itself. But
235
256
  * in some cases it might make sense to only expose some part of it.
236
257
  *
@@ -239,7 +260,7 @@ var hostConfig = {
239
260
  getPublicInstance(instance) {
240
261
  switch (instance.tag) {
241
262
  case "INSTANCE": {
242
- const createNodeMock = instance.rootContainer.createNodeMock;
263
+ const createNodeMock = instance.rootContainer.config.createNodeMock;
243
264
  const mockNode = createNodeMock({
244
265
  type: instance.type,
245
266
  props: instance.props,
@@ -253,6 +274,8 @@ var hostConfig = {
253
274
  }
254
275
  },
255
276
  /**
277
+ * #### `prepareForCommit(containerInfo)`
278
+ *
256
279
  * This method lets you store some information before React starts making changes to the tree on
257
280
  * the screen. For example, the DOM renderer stores the current text selection so that it can later
258
281
  * restore it. This method is mirrored by `resetAfterCommit`.
@@ -263,6 +286,8 @@ var hostConfig = {
263
286
  return null;
264
287
  },
265
288
  /**
289
+ * #### `resetAfterCommit(containerInfo)`
290
+ *
266
291
  * This method is called right after React has performed the tree mutations. You can use it to restore
267
292
  * something you've stored in `prepareForCommit` — for example, text selection.
268
293
  *
@@ -271,21 +296,34 @@ var hostConfig = {
271
296
  resetAfterCommit(_containerInfo) {
272
297
  },
273
298
  /**
299
+ * #### `preparePortalMount(containerInfo)`
300
+ *
274
301
  * This method is called for a container that's used as a portal target. Usually you can leave it empty.
275
302
  */
276
303
  preparePortalMount(_containerInfo) {
277
304
  },
278
305
  /**
306
+ * #### `scheduleTimeout(fn, delay)`
307
+ *
279
308
  * You can proxy this to `setTimeout` or its equivalent in your environment.
280
309
  */
281
310
  scheduleTimeout: setTimeout,
311
+ /**
312
+ * #### `cancelTimeout(id)`
313
+ *
314
+ * You can proxy this to `clearTimeout` or its equivalent in your environment.
315
+ */
282
316
  cancelTimeout: clearTimeout,
283
317
  /**
318
+ * #### `noTimeout`
319
+ *
284
320
  * This is a property (not a function) that should be set to something that can never be a valid timeout ID.
285
321
  * For example, you can set it to `-1`.
286
322
  */
287
323
  noTimeout: -1,
288
324
  /**
325
+ * #### `supportsMicrotasks`
326
+ *
289
327
  * Set this to `true` to indicate that your renderer supports `scheduleMicrotask`. We use microtasks as part
290
328
  * of our discrete event implementation in React DOM. If you're not sure if your renderer should support this,
291
329
  * you probably should. The option to not implement `scheduleMicrotask` exists so that platforms with more control
@@ -293,10 +331,14 @@ var hostConfig = {
293
331
  */
294
332
  supportsMicrotasks: true,
295
333
  /**
334
+ * #### `scheduleMicrotask(fn)`
335
+ *
296
336
  * Optional. You can proxy this to `queueMicrotask` or its equivalent in your environment.
297
337
  */
298
338
  scheduleMicrotask: queueMicrotask,
299
339
  /**
340
+ * #### `isPrimaryRenderer`
341
+ *
300
342
  * This is a property (not a function) that should be set to `true` if your renderer is the main one on the
301
343
  * page. For example, if you're writing a renderer for the Terminal, it makes sense to set it to `true`, but
302
344
  * if your renderer is used *on top of* React DOM or some other existing renderer, set it to `false`.
@@ -306,47 +348,6 @@ var hostConfig = {
306
348
  * Whether the renderer shouldn't trigger missing `act()` warnings
307
349
  */
308
350
  warnsIfNotActing: true,
309
- /**
310
- * To implement this method, you'll need some constants available on the special `react-reconciler/constants` entry point:
311
- *
312
- * ```
313
- * import {
314
- * DiscreteEventPriority,
315
- * ContinuousEventPriority,
316
- * DefaultEventPriority,
317
- * } from 'react-reconciler/constants';
318
- *
319
- * const HostConfig = {
320
- * // ...
321
- * getCurrentEventPriority() {
322
- * return DefaultEventPriority;
323
- * },
324
- * // ...
325
- * }
326
- *
327
- * const MyRenderer = Reconciler(HostConfig);
328
- * ```
329
- *
330
- * The constant you return depends on which event, if any, is being handled right now. (In the browser, you can
331
- * check this using `window.event && window.event.type`).
332
- *
333
- * - **Discrete events**: If the active event is directly caused by the user (such as mouse and keyboard events)
334
- * and each event in a sequence is intentional (e.g. click), return DiscreteEventPriority. This tells React that
335
- * they should interrupt any background work and cannot be batched across time.
336
- *
337
- * - **Continuous events**: If the active event is directly caused by the user but the user can't distinguish between
338
- * individual events in a sequence (e.g. mouseover), return ContinuousEventPriority. This tells React they
339
- * should interrupt any background work but can be batched across time.
340
- *
341
- * - **Other events / No active event**: In all other cases, return DefaultEventPriority. This tells React that
342
- * this event is considered background work, and interactive events will be prioritized over it.
343
- *
344
- * You can consult the `getCurrentEventPriority()` implementation in `ReactDOMHostConfig.js` for a reference implementation.
345
- */
346
- // Removed in React 19
347
- // getCurrentEventPriority() {
348
- // return DefaultEventPriority;
349
- // },
350
351
  getInstanceFromNode(node) {
351
352
  const instance = nodeToInstanceMap.get(node);
352
353
  if (instance !== void 0) {
@@ -368,6 +369,8 @@ var hostConfig = {
368
369
  detachDeletedInstance(_node) {
369
370
  },
370
371
  /**
372
+ * #### `appendChild(parentInstance, child)`
373
+ *
371
374
  * This method should mutate the `parentInstance` and add the child to its list of children. For example,
372
375
  * in the DOM this would translate to a `parentInstance.appendChild(child)` call.
373
376
  *
@@ -376,12 +379,16 @@ var hostConfig = {
376
379
  */
377
380
  appendChild,
378
381
  /**
382
+ * #### `appendChildToContainer(container, child)`
383
+ *
379
384
  * Same as `appendChild`, but for when a node is attached to the root container. This is useful if attaching
380
385
  * to the root has a slightly different implementation, or if the root container nodes are of a different
381
386
  * type than the rest of the tree.
382
387
  */
383
388
  appendChildToContainer: appendChild,
384
389
  /**
390
+ * #### `insertBefore(parentInstance, child, beforeChild)`
391
+ *
385
392
  * This method should mutate the `parentInstance` and place the `child` before `beforeChild` in the list of
386
393
  * its children. For example, in the DOM this would translate to a `parentInstance.insertBefore(child, beforeChild)` call.
387
394
  *
@@ -390,12 +397,16 @@ var hostConfig = {
390
397
  */
391
398
  insertBefore,
392
399
  /**
400
+ * #### `insertInContainerBefore(container, child, beforeChild)
401
+ *
393
402
  * Same as `insertBefore`, but for when a node is attached to the root container. This is useful if attaching
394
403
  * to the root has a slightly different implementation, or if the root container nodes are of a different type
395
404
  * than the rest of the tree.
396
405
  */
397
406
  insertInContainerBefore: insertBefore,
398
407
  /**
408
+ * #### `removeChild(parentInstance, child)`
409
+ *
399
410
  * This method should mutate the `parentInstance` to remove the `child` from the list of its children.
400
411
  *
401
412
  * React will only call it for the top-level node that is being removed. It is expected that garbage collection
@@ -403,12 +414,16 @@ var hostConfig = {
403
414
  */
404
415
  removeChild,
405
416
  /**
417
+ * #### `removeChildFromContainer(container, child)`
418
+ *
406
419
  * Same as `removeChild`, but for when a node is detached from the root container. This is useful if attaching
407
420
  * to the root has a slightly different implementation, or if the root container nodes are of a different type
408
421
  * than the rest of the tree.
409
422
  */
410
423
  removeChildFromContainer: removeChild,
411
424
  /**
425
+ * #### `resetTextContent(instance)`
426
+ *
412
427
  * If you returned `true` from `shouldSetTextContent` for the previous props, but returned `false` from
413
428
  * `shouldSetTextContent` for the next props, React will call this method so that you can clear the text
414
429
  * content you were managing manually. For example, in the DOM you could set `node.textContent = ''`.
@@ -418,6 +433,8 @@ var hostConfig = {
418
433
  resetTextContent(_instance) {
419
434
  },
420
435
  /**
436
+ * #### `commitTextUpdate(textInstance, prevText, nextText)`
437
+ *
421
438
  * This method should mutate the `textInstance` and update its text content to `nextText`.
422
439
  *
423
440
  * Here, `textInstance` is a node created by `createTextInstance`.
@@ -426,6 +443,8 @@ var hostConfig = {
426
443
  textInstance.text = newText;
427
444
  },
428
445
  /**
446
+ * #### `commitMount(instance, type, props, internalHandle)`
447
+ *
429
448
  * This method is only called if you returned `true` from `finalizeInitialChildren` for this instance.
430
449
  *
431
450
  * It lets you do some additional work after the node is actually attached to the tree on the screen for
@@ -445,6 +464,8 @@ var hostConfig = {
445
464
  commitMount(_instance, _type, _props, _internalHandle) {
446
465
  },
447
466
  /**
467
+ * #### `commitUpdate(instance, type, prevProps, nextProps, internalHandle)`
468
+ *
448
469
  * This method should mutate the `instance` according to the set of changes in `updatePayload`. Here, `updatePayload`
449
470
  * is the object that you've returned from `prepareUpdate` and has an arbitrary structure that makes sense for your
450
471
  * renderer. For example, the DOM renderer returns an update payload like `[prop1, value1, prop2, value2, ...]` from
@@ -455,12 +476,15 @@ var hostConfig = {
455
476
  * be aware that it may change significantly between versions. You're taking on additional maintenance risk by
456
477
  * reading from it, and giving up all guarantees if you write something to it.
457
478
  */
458
- commitUpdate(instance, _updatePayload, type, _prevProps, nextProps, internalHandle) {
479
+ // @ts-expect-error types are not updated
480
+ commitUpdate(instance, type, _prevProps, nextProps, internalHandle) {
459
481
  instance.type = type;
460
482
  instance.props = nextProps;
461
483
  instance.internalHandle = internalHandle;
462
484
  },
463
485
  /**
486
+ * #### `hideInstance(instance)`
487
+ *
464
488
  * This method should make the `instance` invisible without removing it from the tree. For example, it can apply
465
489
  * visual styling to hide it. It is used by Suspense to hide the tree while the fallback is visible.
466
490
  */
@@ -468,24 +492,32 @@ var hostConfig = {
468
492
  instance.isHidden = true;
469
493
  },
470
494
  /**
495
+ * #### `hideTextInstance(textInstance)`
496
+ *
471
497
  * Same as `hideInstance`, but for nodes created by `createTextInstance`.
472
498
  */
473
499
  hideTextInstance(textInstance) {
474
500
  textInstance.isHidden = true;
475
501
  },
476
502
  /**
503
+ * #### `unhideInstance(instance, props)`
504
+ *
477
505
  * This method should make the `instance` visible, undoing what `hideInstance` did.
478
506
  */
479
507
  unhideInstance(instance, _props) {
480
508
  instance.isHidden = false;
481
509
  },
482
510
  /**
511
+ * #### `unhideTextInstance(textInstance, text)`
512
+ *
483
513
  * Same as `unhideInstance`, but for nodes created by `createTextInstance`.
484
514
  */
485
515
  unhideTextInstance(textInstance, _text) {
486
516
  textInstance.isHidden = false;
487
517
  },
488
518
  /**
519
+ * #### `clearContainer(container)`
520
+ *
489
521
  * This method should mutate the `container` root node and remove all children from it.
490
522
  */
491
523
  clearContainer(container) {
@@ -494,62 +526,68 @@ var hostConfig = {
494
526
  });
495
527
  container.children.splice(0);
496
528
  },
497
- // -------------------
498
- // Hydration Methods
499
- // (optional)
500
- // You can optionally implement hydration to "attach" to the existing tree during the initial render instead
501
- // of creating it from scratch. For example, the DOM renderer uses this to attach to an HTML markup.
502
- //
503
- // To support hydration, you need to declare `supportsHydration: true` and then implement the methods in
504
- // the "Hydration" section [listed in this file](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js).
505
- // File an issue if you need help.
506
- // -------------------
507
- supportsHydration: false,
508
- // React 19
509
- // @ts-expect-error missing types
510
- setCurrentUpdatePriority(newPriority) {
511
- currentUpdatePriority = newPriority;
512
- },
513
- getCurrentUpdatePriority() {
514
- return currentUpdatePriority;
515
- },
516
- resolveUpdatePriority() {
517
- return currentUpdatePriority || DefaultEventPriority;
518
- },
519
- shouldAttemptEagerTransition() {
520
- return false;
521
- },
522
- // #### `maySuspendCommit(type, props)`
523
- // This method is called during render to determine if the Host Component type and props require
524
- // some kind of loading process to complete before committing an update.
525
- maySuspendCommit() {
529
+ /**
530
+ * #### `maySuspendCommit(type, props)`
531
+ *
532
+ * This method is called during render to determine if the Host Component type and props require
533
+ * some kind of loading process to complete before committing an update.
534
+ */
535
+ maySuspendCommit(_type, _props) {
526
536
  return false;
527
537
  },
528
- // #### `preloadInstance(type, props)`
529
- // This method may be called during render if the Host Component type and props might suspend a commit.
530
- // It can be used to initiate any work that might shorten the duration of a suspended commit.
531
- preloadInstance() {
538
+ /**
539
+ * #### `preloadInstance(type, props)`
540
+ *
541
+ * This method may be called during render if the Host Component type and props might suspend a commit.
542
+ * It can be used to initiate any work that might shorten the duration of a suspended commit.
543
+ */
544
+ preloadInstance(_type, _props) {
532
545
  return true;
533
546
  },
534
- // #### `startSuspendingCommit()`
535
- // This method is called just before the commit phase. Use it to set up any necessary state while any Host
536
- // Components that might suspend this commit are evaluated to determine if the commit must be suspended.
547
+ /**
548
+ * #### `startSuspendingCommit()`
549
+ *
550
+ * This method is called just before the commit phase. Use it to set up any necessary state while any Host
551
+ * Components that might suspend this commit are evaluated to determine if the commit must be suspended.
552
+ */
537
553
  startSuspendingCommit() {
538
554
  },
539
- // #### `suspendInstance(type, props)`
540
- // This method is called after `startSuspendingCommit` for each Host Component that indicated it might
541
- // suspend a commit.
555
+ /**
556
+ * #### `suspendInstance(type, props)`
557
+ *
558
+ * This method is called after `startSuspendingCommit` for each Host Component that indicated it might
559
+ * suspend a commit.
560
+ */
542
561
  suspendInstance() {
543
562
  },
544
- // #### `waitForCommitToBeReady()`
545
- // This method is called after all `suspendInstance` calls are complete.
563
+ /**
564
+ * #### `waitForCommitToBeReady()`
565
+ *
566
+ * This method is called after all `suspendInstance` calls are complete.
567
+ *
568
+ * Return `null` if the commit can happen immediately.
569
+ * Return `(initiateCommit: Function) => Function` if the commit must be suspended. The argument to this
570
+ * callback will initiate the commit when called. The return value is a cancellation function that the
571
+ * Reconciler can use to abort the commit.
572
+ */
546
573
  waitForCommitToBeReady() {
547
574
  return null;
548
575
  },
576
+ // -------------------
577
+ // Hydration Methods
578
+ // (optional)
579
+ // You can optionally implement hydration to "attach" to the existing tree during the initial render instead
580
+ // of creating it from scratch. For example, the DOM renderer uses this to attach to an HTML markup.
581
+ //
582
+ // To support hydration, you need to declare `supportsHydration: true` and then implement the methods in
583
+ // the "Hydration" section [listed in this file](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js).
584
+ // File an issue if you need help.
585
+ // -------------------
586
+ supportsHydration: false,
549
587
  NotPendingTransition: null,
550
- resetFormInstance() {
588
+ resetFormInstance(_form) {
551
589
  },
552
- requestPostPaintCallback() {
590
+ requestPostPaintCallback(_callback) {
553
591
  }
554
592
  };
555
593
  var TestReconciler = ReactReconciler(hostConfig);
@@ -709,14 +747,16 @@ var HostElement = class _HostElement {
709
747
 
710
748
  // src/renderer.ts
711
749
  import { ConcurrentRoot, LegacyRoot } from "react-reconciler/constants";
712
- function createRenderer(options) {
750
+ function createRoot(options) {
713
751
  var _a;
714
752
  let container = {
715
753
  tag: "CONTAINER",
716
754
  children: [],
717
755
  parent: null,
718
- textComponents: options == null ? void 0 : options.textComponents,
719
- createNodeMock: (_a = options == null ? void 0 : options.createNodeMock) != null ? _a : () => ({})
756
+ config: {
757
+ textComponents: options == null ? void 0 : options.textComponents,
758
+ createNodeMock: (_a = options == null ? void 0 : options.createNodeMock) != null ? _a : () => ({})
759
+ }
720
760
  };
721
761
  let containerFiber = TestReconciler.createContainer(
722
762
  container,
@@ -779,6 +819,6 @@ function createRenderer(options) {
779
819
  }
780
820
  export {
781
821
  CONTAINER_TYPE,
782
- createRenderer
822
+ createRoot
783
823
  };
784
824
  //# sourceMappingURL=index.js.map