anu-verzum 1.22.1 → 1.23.1

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
@@ -4,7 +4,7 @@
4
4
 
5
5
  <h3>@author: <strong>Anubis-programmer</strong></h3>
6
6
  <h3>@license: <strong>MIT</strong></h3>
7
- <h3>@version: <strong>1.22.1</strong></h3>
7
+ <h3>@version: <strong>1.23.1</strong></h3>
8
8
 
9
9
  <br>
10
10
 
@@ -12,7 +12,9 @@ export type Ref<T> = {
12
12
  };
13
13
  export type FunctionComponent<P extends Props = Props> = (props: P) => AnuElement<any, any> | AnuElement<any, any>[] | string | number | boolean | null | undefined;
14
14
  export type ComponentConstructor<P extends Props = Props> = new (props: P, context?: Record<string, any>) => any;
15
- export type ElementType = string | FunctionComponent<any> | ComponentConstructor<any>;
15
+ export declare const PORTAL_ELEMENT: unique symbol;
16
+ export type PortalElementType = typeof PORTAL_ELEMENT;
17
+ export type ElementType = string | FunctionComponent<any> | ComponentConstructor<any> | PortalElementType;
16
18
  export type AnuElement<P = Props, T extends ElementType = ElementType> = {
17
19
  type: T;
18
20
  props: P;
@@ -3,8 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.createElement = exports.TEXT_ELEMENT = void 0;
6
+ exports.createElement = exports.TEXT_ELEMENT = exports.PORTAL_ELEMENT = void 0;
7
7
  const TEXT_ELEMENT = exports.TEXT_ELEMENT = 'TEXT_ELEMENT';
8
+ const PORTAL_ELEMENT = exports.PORTAL_ELEMENT = Symbol('portal');
8
9
  const createTextElement = value => ({
9
10
  type: TEXT_ELEMENT,
10
11
  props: {
@@ -1,5 +1,6 @@
1
- import { AnuElement, Ref } from './elements';
1
+ import { AnuElement, AnuNode, Ref } from './elements';
2
2
  export declare const createRef: <T = any>() => Ref<T>;
3
+ export declare const createPortal: (children: AnuNode, container: Element) => AnuElement;
3
4
  export declare const scheduleUpdate: (instance: any, partialState: Record<string, any>, partialStateCallback?: (prevState: any, prevProps: any) => any) => void;
4
5
  export declare const render: (elements: AnuElement | AnuElement[], containerDom: Element) => void;
5
6
  export declare const unmountComponentAtNode: (containerDom: Element) => void;
@@ -3,12 +3,14 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.unmountComponentAtNode = exports.scheduleUpdate = exports.render = exports.createRef = exports.__testing = void 0;
6
+ exports.unmountComponentAtNode = exports.scheduleUpdate = exports.render = exports.createRef = exports.createPortal = exports.__testing = void 0;
7
7
  var _domUtils = require("./domUtils");
8
+ var _elements = require("./elements");
8
9
  const HOST_COMPONENT = 'host';
9
10
  const CLASS_COMPONENT = 'class';
10
11
  const FUNCTION_COMPONENT = 'function';
11
12
  const HOST_ROOT = 'root';
13
+ const PORTAL = 'portal';
12
14
  const PLACEMENT = 1;
13
15
  const DELETION = 2;
14
16
  const UPDATE = 3;
@@ -82,10 +84,16 @@ const beginWork = wipFiber => {
82
84
  updateClassComponent(wipFiber);
83
85
  } else if (wipFiber.tag === FUNCTION_COMPONENT) {
84
86
  updateFunctionComponent(wipFiber);
87
+ } else if (wipFiber.tag === PORTAL) {
88
+ updatePortalComponent(wipFiber);
85
89
  } else {
86
90
  updateHostComponent(wipFiber);
87
91
  }
88
92
  };
93
+ const updatePortalComponent = wipFiber => {
94
+ wipFiber.stateNode = wipFiber.props.container;
95
+ reconcileChildrenArray(wipFiber, wipFiber.props.children);
96
+ };
89
97
  const updateHostComponent = wipFiber => {
90
98
  if (!wipFiber.stateNode) {
91
99
  wipFiber.stateNode = (0, _domUtils.createDomElement)(wipFiber);
@@ -157,6 +165,9 @@ const updateClassComponent = wipFiber => {
157
165
  };
158
166
  const arrify = val => !val ? [] : Array.isArray(val) ? val : [val];
159
167
  const getTag = element => {
168
+ if (element.type === _elements.PORTAL_ELEMENT) {
169
+ return PORTAL;
170
+ }
160
171
  if (typeof element.type === 'string') {
161
172
  return HOST_COMPONENT;
162
173
  }
@@ -231,6 +242,9 @@ const reconcileChildrenArray = (wipFiber, newChildElements) => {
231
242
  });
232
243
  };
233
244
  const getFirstHostNode = fiber => {
245
+ if (fiber.tag === PORTAL) {
246
+ return null;
247
+ }
234
248
  if (fiber.tag === HOST_COMPONENT) {
235
249
  return fiber.stateNode ? fiber.stateNode : null;
236
250
  }
@@ -407,6 +421,19 @@ const commitDeletion = (fiber, domParent) => {
407
421
  node = node.child;
408
422
  continue;
409
423
  }
424
+ if (node.tag === PORTAL) {
425
+ if (node.child) {
426
+ commitDeletion(node.child, node.stateNode);
427
+ }
428
+ while (node !== fiber && !node.sibling) {
429
+ node = node.parent;
430
+ }
431
+ if (node === fiber) {
432
+ return;
433
+ }
434
+ node = node.sibling;
435
+ continue;
436
+ }
410
437
  if (domParent.contains(node.stateNode)) {
411
438
  domParent.removeChild(node.stateNode);
412
439
  }
@@ -423,6 +450,16 @@ const createRef = () => ({
423
450
  current: null
424
451
  });
425
452
  exports.createRef = createRef;
453
+ const createPortal = (children, container) => ({
454
+ type: _elements.PORTAL_ELEMENT,
455
+ props: {
456
+ children,
457
+ container
458
+ },
459
+ key: null,
460
+ ref: null
461
+ });
462
+ exports.createPortal = createPortal;
426
463
  const scheduleUpdate = (instance, partialState, partialStateCallback) => {
427
464
  const updateFiber = {
428
465
  from: CLASS_COMPONENT,
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import Utils from './misc/utils';
2
2
  import ServerAPI from './server-api/server-api';
3
3
  import { createElement, AnuElement, Props, Ref } from './core/elements';
4
- import { createRef, render } from './core/reconciler';
4
+ import { createRef, render, createPortal } from './core/reconciler';
5
5
  import store from './store/store';
6
6
  import { createContext } from './core/components/Context';
7
7
  import { Component } from './core/components/Component';
@@ -29,6 +29,7 @@ declare const Anu: {
29
29
  };
30
30
  createContext: <T extends Record<string, any> = Record<string, any>>(context: T) => import("./core/components/Context").Context<T>;
31
31
  createElement: (type: import(".").ElementType, config: Props | null, ...args: any[]) => AnuElement;
32
+ createPortal: (children: import(".").AnuNode, container: Element) => AnuElement;
32
33
  createRef: <T = any>() => Ref<T>;
33
34
  Component: typeof Component;
34
35
  Fragment: typeof Fragment;
@@ -156,7 +157,7 @@ export type { AnuElement, AnuChild, AnuNode, AnuCSSProperties, Props, Ref, Funct
156
157
  export type { ContextValue, ConsumerProps } from './core/components/Context';
157
158
  export type { Action, ThunkAction, Dispatch, Reducer, MiddlewareAPI, Middleware, Store, SelectorFn, CreateSelectorFn } from './store/store';
158
159
  export type { ApiSuccessResponse, ApiErrorResponse } from './server-api/server-api';
159
- export { Component, Fragment, createElement, createRef, createContext, render, goTo };
160
+ export { Component, Fragment, createElement, createRef, createPortal, createContext, render, goTo };
160
161
  export { AnulyticsProvider, trackEvent };
161
162
  export { store, ServerAPI, Utils, Connector, Feature, History, Intl };
162
163
  export type { AbbreviateNumberOptions } from './core/components/Intl';
package/dist/index.js CHANGED
@@ -69,6 +69,12 @@ Object.defineProperty(exports, "createElement", {
69
69
  return _elements.createElement;
70
70
  }
71
71
  });
72
+ Object.defineProperty(exports, "createPortal", {
73
+ enumerable: true,
74
+ get: function () {
75
+ return _reconciler.createPortal;
76
+ }
77
+ });
72
78
  Object.defineProperty(exports, "createRef", {
73
79
  enumerable: true,
74
80
  get: function () {
@@ -138,6 +144,7 @@ const Anu = {
138
144
  },
139
145
  createContext: _Context.createContext,
140
146
  createElement: _elements.createElement,
147
+ createPortal: _reconciler.createPortal,
141
148
  createRef: _reconciler.createRef,
142
149
  Component: _Component.Component,
143
150
  Fragment: _Fragment.Fragment,
@@ -157,6 +157,58 @@ describe('waitFor', () => {
157
157
  })).rejects.toThrow();
158
158
  });
159
159
  });
160
+ describe('createPortal', () => {
161
+ let portalContainer;
162
+ beforeEach(() => {
163
+ portalContainer = document.createElement('div');
164
+ document.body.appendChild(portalContainer);
165
+ });
166
+ afterEach(() => {
167
+ if (portalContainer.parentNode) {
168
+ portalContainer.parentNode.removeChild(portalContainer);
169
+ }
170
+ });
171
+ const Portal = () => (0, _index.createPortal)(_index.default.createElement('p', {}, 'Portal content'), portalContainer);
172
+ test('renders content into the portal container, not the render container', () => {
173
+ const {
174
+ queryByText
175
+ } = (0, _index2.render)(_index.default.createElement(Portal, {}));
176
+ expect(portalContainer.textContent).toBe('Portal content');
177
+ expect(queryByText('Portal content')).toBeNull();
178
+ });
179
+ test('within() finds portal content', () => {
180
+ (0, _index2.render)(_index.default.createElement(Portal, {}));
181
+ expect((0, _index2.within)(portalContainer).getByText('Portal content')).toBeDefined();
182
+ });
183
+ test('portal content is removed from the container on unmount', () => {
184
+ const {
185
+ unmount
186
+ } = (0, _index2.render)(_index.default.createElement(Portal, {}));
187
+ expect(portalContainer.textContent).toBe('Portal content');
188
+ unmount();
189
+ expect(portalContainer.textContent).toBe('');
190
+ });
191
+ test('portal content updates when parent state changes', () => {
192
+ class PortalParent extends _index.Component {
193
+ state = {
194
+ label: 'before'
195
+ };
196
+ render() {
197
+ return _index.default.createElement('div', {}, _index.default.createElement('button', {
198
+ onClick: () => this.setState({
199
+ label: 'after'
200
+ })
201
+ }, 'update'), (0, _index.createPortal)(_index.default.createElement('p', {}, this.state.label), portalContainer));
202
+ }
203
+ }
204
+ const {
205
+ getByRole
206
+ } = (0, _index2.render)(_index.default.createElement(PortalParent, {}));
207
+ expect((0, _index2.within)(portalContainer).getByText('before')).toBeDefined();
208
+ _index2.fireEvent.click(getByRole('button'));
209
+ expect((0, _index2.within)(portalContainer).getByText('after')).toBeDefined();
210
+ });
211
+ });
160
212
  describe('act', () => {
161
213
  test('flushes state updates synchronously', () => {
162
214
  const {
@@ -5,5 +5,5 @@ export { waitFor, waitForElementToBeRemoved } from './waitFor';
5
5
  export { fireEvent } from './events/fireEvent';
6
6
  export { userEvent } from './events/userEvent';
7
7
  export { renderWithStore, renderWithRouter, renderWithIntl, renderWithContext } from './wrappers';
8
- export { buildQueries } from './queries/index';
8
+ export { buildQueries, within } from './queries/index';
9
9
  export type { RenderOptions, RenderResult, BoundQueries, BoundQuery, ByRoleOptions, TextMatch, WaitForOptions, } from './types';
@@ -99,6 +99,12 @@ Object.defineProperty(exports, "waitForElementToBeRemoved", {
99
99
  return _waitFor.waitForElementToBeRemoved;
100
100
  }
101
101
  });
102
+ Object.defineProperty(exports, "within", {
103
+ enumerable: true,
104
+ get: function () {
105
+ return _index.within;
106
+ }
107
+ });
102
108
  var _render = require("./render");
103
109
  var _act = require("./act");
104
110
  var _cleanup = require("./cleanup");
@@ -1,2 +1,3 @@
1
1
  import type { BoundQueries } from '../types';
2
+ export declare const within: (element: Element) => BoundQueries;
2
3
  export declare const buildQueries: (container: Element) => BoundQueries;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.buildQueries = void 0;
6
+ exports.within = exports.buildQueries = void 0;
7
7
  var _byText = require("./byText");
8
8
  var _byRole = require("./byRole");
9
9
  var _byLabelText = require("./byLabelText");
@@ -11,6 +11,8 @@ var _byPlaceholderText = require("./byPlaceholderText");
11
11
  var _byTestId = require("./byTestId");
12
12
  var _byTitle = require("./byTitle");
13
13
  var _byAltText = require("./byAltText");
14
+ const within = element => buildQueries(element);
15
+ exports.within = within;
14
16
  const buildQueries = container => ({
15
17
  getByText: text => (0, _byText.createByTextQueries)(container, text).get(),
16
18
  queryByText: text => (0, _byText.createByTextQueries)(container, text).query(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anu-verzum",
3
- "version": "1.22.1",
3
+ "version": "1.23.1",
4
4
  "description": "A \"React-like\" UI library that supports JSX syntax, Redux-like state management, array-rendering, i18n, routing and many more.",
5
5
  "keywords": [
6
6
  "anu-verzum",