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 +1 -1
- package/dist/core/elements.d.ts +3 -1
- package/dist/core/elements.js +2 -1
- package/dist/core/reconciler.d.ts +2 -1
- package/dist/core/reconciler.js +38 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +7 -0
- package/dist/testing/__tests__/smoke.test.js +52 -0
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +6 -0
- package/dist/testing/queries/index.d.ts +1 -0
- package/dist/testing/queries/index.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/core/elements.d.ts
CHANGED
|
@@ -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
|
|
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;
|
package/dist/core/elements.js
CHANGED
|
@@ -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;
|
package/dist/core/reconciler.js
CHANGED
|
@@ -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 {
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -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';
|
package/dist/testing/index.js
CHANGED
|
@@ -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");
|
|
@@ -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