anu-verzum 2.2.9 → 2.3.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
@@ -9,7 +9,7 @@
9
9
 
10
10
  A lightweight React-inspired UI library for building component-based web applications in JavaScript and TypeScript.
11
11
 
12
- - Fiber-based virtual DOM with time-sliced rendering (`requestIdleCallback`)
12
+ - Fiber-based virtual DOM with time-sliced rendering (MessageChannel scheduler)
13
13
  - Class components with full lifecycle support and function components
14
14
  - JSX via a custom Babel preset — no separate TypeScript preset needed
15
15
  - Redux-compatible state management with thunk middleware and memoized selectors
@@ -1,5 +1,5 @@
1
1
  import { Component } from './Component';
2
- import { AnuElement, Props } from '../elements';
2
+ import { AnuChild, Props } from '../elements';
3
3
  type UserActionEvent = {
4
4
  type: string;
5
5
  keyCode?: number | null;
@@ -26,7 +26,7 @@ declare class AnulyticsProvider extends Component<AnulyticsProviderProps> {
26
26
  componentDidMount(): void;
27
27
  componentWillUnmount(): void;
28
28
  handleVisibilityChange(): void;
29
- render(): AnuElement | AnuElement[] | null;
29
+ render(): AnuChild[] | null;
30
30
  }
31
31
  export default AnulyticsProvider;
32
32
  export declare const __testing: {
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.trackStateChange = exports.trackRouteChange = exports.trackEvent = exports.default = exports.__testing = void 0;
7
7
  var _Component = require("./Component");
8
+ var _elements = require("../elements");
8
9
  var _serverApi = _interopRequireDefault(require("../../server-api/server-api"));
9
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
11
  const EventTypes = {
@@ -206,9 +207,9 @@ class AnulyticsProvider extends _Component.Component {
206
207
  }
207
208
  }
208
209
  render() {
209
- const children = this.props.children;
210
+ const children = (0, _elements.toChildArray)(this.props.children);
210
211
  try {
211
- if (!children || children.length !== 1) {
212
+ if (children.length !== 1) {
212
213
  throw new Error('Provider must have one child element!');
213
214
  }
214
215
  return children;
@@ -1,4 +1,4 @@
1
- import { AnuElement, Props } from '../elements';
1
+ import { AnuNode, Props } from '../elements';
2
2
  export declare abstract class Component<P extends Record<string, any> = Props, S extends Record<string, any> = Record<string, any>> {
3
3
  props: P;
4
4
  state: S;
@@ -7,7 +7,7 @@ export declare abstract class Component<P extends Record<string, any> = Props, S
7
7
  static isAnuComponent: boolean;
8
8
  constructor(props: P, context?: Record<string, any>);
9
9
  setState(partialState?: Partial<S> | ((prevState: S, prevProps: P) => Partial<S>)): void;
10
- abstract render(): AnuElement | AnuElement[] | string | number | boolean | null | undefined;
10
+ abstract render(): AnuNode;
11
11
  componentDidMount(): void;
12
12
  componentDidUpdate(_prevProps: P, _prevState: S): void;
13
13
  componentWillUnmount(): void;
@@ -1,5 +1,5 @@
1
1
  import { Component } from './Component';
2
- import { AnuElement, Props, ComponentConstructor } from '../elements';
2
+ import { AnuChild, Props, ComponentConstructor } from '../elements';
3
3
  type StoreShape = {
4
4
  getState: () => any;
5
5
  dispatch: (action: any) => any;
@@ -14,7 +14,7 @@ export interface ConnectorProviderProps extends Props {
14
14
  declare class Provider extends Component<ConnectorProviderProps> {
15
15
  store: StoreShape;
16
16
  constructor(props: ConnectorProviderProps, context?: Record<string, any>);
17
- render(): AnuElement | AnuElement[] | null;
17
+ render(): AnuChild[] | null;
18
18
  }
19
19
  declare const Connector: {
20
20
  connect: <TState = any, TOwnProps extends Record<string, any> = Record<string, any>, TStateProps extends Record<string, any> = Record<string, any>, TDispatchProps extends Record<string, any> = Record<string, any>>(mapStateToProps?: MapStateToProps<TState, TOwnProps, TStateProps> | null, mapDispatchToProps?: MapDispatchToProps<any, TOwnProps, TDispatchProps> | null) => (WrappedComponent: ComponentConstructor<TStateProps & TDispatchProps & TOwnProps>) => ComponentConstructor;
@@ -40,9 +40,9 @@ class Provider extends _Component.Component {
40
40
  });
41
41
  }
42
42
  render() {
43
- const children = this.props.children;
43
+ const children = (0, _elements.toChildArray)(this.props.children);
44
44
  try {
45
- if (!children || children.length !== 1) {
45
+ if (children.length !== 1) {
46
46
  throw new Error('Provider must have one child element!');
47
47
  }
48
48
  return children;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.createContext = void 0;
7
7
  var _utils = require("../../misc/utils");
8
8
  var _Component = require("./Component");
9
+ var _elements = require("../elements");
9
10
  const createContext = context => {
10
11
  const defaultContext = {
11
12
  value: context
@@ -37,9 +38,9 @@ const createContext = context => {
37
38
  }
38
39
  }
39
40
  render() {
40
- const children = this.props.children;
41
+ const children = (0, _elements.toChildArray)(this.props.children);
41
42
  try {
42
- if (!children || children.length !== 1) {
43
+ if (children.length !== 1) {
43
44
  throw new Error('Context Component must have exactly one child element!');
44
45
  }
45
46
  return children;
@@ -80,23 +81,21 @@ const createContext = context => {
80
81
  }
81
82
  }
82
83
  render() {
83
- const children = this.props.children;
84
+ const children = (0, _elements.toChildArray)(this.props.children);
84
85
  try {
85
- if (!children || children.length !== 1) {
86
+ if (children.length !== 1) {
86
87
  throw new Error('Context Component must have exactly one child element!');
87
88
  }
88
89
  const provider = resolveProvider(this);
89
90
  this.subscribeTo(provider);
90
91
  const value = provider ? provider.value : defaultContext.value;
91
- const {
92
- type
93
- } = children[0];
92
+ const renderChild = children[0];
94
93
  const childProps = {
95
94
  value,
96
95
  defaultContext
97
96
  };
98
- if (typeof type === 'function') {
99
- return type(childProps);
97
+ if (typeof renderChild === 'function') {
98
+ return renderChild(childProps);
100
99
  } else {
101
100
  throw new Error('Context component child element must be a function!');
102
101
  }
@@ -12,7 +12,7 @@ const defaultFeatures = {};
12
12
  const FeaturesContext = (0, _Context.createContext)(defaultFeatures);
13
13
  const resolveDefault = defaultComponent => {
14
14
  if (defaultComponent && !Array.isArray(defaultComponent) && defaultComponent.type === _Fragment.Fragment) {
15
- return defaultComponent.props.children ?? null;
15
+ return (0, _elements.toChildArray)(defaultComponent.props.children);
16
16
  }
17
17
  return defaultComponent;
18
18
  };
@@ -1,5 +1,5 @@
1
1
  import { Component } from './Component';
2
- import { AnuElement } from '../elements';
2
+ import { AnuChild } from '../elements';
3
3
  export declare class Fragment extends Component {
4
- render(): AnuElement[];
4
+ render(): AnuChild[];
5
5
  }
@@ -5,11 +5,12 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.Fragment = void 0;
7
7
  var _Component = require("./Component");
8
+ var _elements = require("../elements");
8
9
  class Fragment extends _Component.Component {
9
10
  render() {
10
- const children = this.props.children;
11
+ const children = (0, _elements.toChildArray)(this.props.children);
11
12
  try {
12
- if (!children || !children.length) {
13
+ if (!children.length) {
13
14
  throw new Error('Fragment must have at least one child element!');
14
15
  }
15
16
  return children;
@@ -22,3 +22,5 @@ export type AnuElement<P = Props, T extends ElementType = ElementType> = {
22
22
  ref: Ref<any> | null;
23
23
  };
24
24
  export declare const createElement: (type: ElementType, config: Props | null, ...args: any[]) => AnuElement;
25
+ export declare const toChildArray: (children: AnuNode) => AnuChild[];
26
+ export declare const normalizeChildren: (children: AnuNode) => AnuElement[];
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.createElement = exports.TEXT_ELEMENT = exports.PORTAL_ELEMENT = void 0;
6
+ exports.toChildArray = exports.normalizeChildren = exports.createElement = exports.TEXT_ELEMENT = exports.PORTAL_ELEMENT = void 0;
7
7
  const TEXT_ELEMENT = exports.TEXT_ELEMENT = 'TEXT_ELEMENT';
8
8
  const PORTAL_ELEMENT = exports.PORTAL_ELEMENT = Symbol('portal');
9
9
  const createTextElement = value => ({
@@ -20,13 +20,10 @@ const createElement = (type, config, ...args) => {
20
20
  const props = Object.assign({}, config);
21
21
  delete props.key;
22
22
  delete props.ref;
23
- if (args.length > 0) {
24
- const rawChildren = [].concat(...args);
25
- props.children = rawChildren.filter(c => c !== null && c !== undefined && typeof c !== 'boolean').map(c => typeof c === 'function' ? createElement(c, {
26
- ...(c.props || {})
27
- }) : c instanceof Object ? c : createTextElement(c));
28
- } else {
29
- props.children = props.children ?? [];
23
+ if (args.length === 1) {
24
+ props.children = args[0];
25
+ } else if (args.length > 1) {
26
+ props.children = args;
30
27
  }
31
28
  return {
32
29
  type,
@@ -35,4 +32,20 @@ const createElement = (type, config, ...args) => {
35
32
  ref
36
33
  };
37
34
  };
38
- exports.createElement = createElement;
35
+ exports.createElement = createElement;
36
+ const flattenChildren = (children, acc = []) => {
37
+ if (Array.isArray(children)) {
38
+ for (const child of children) {
39
+ flattenChildren(child, acc);
40
+ }
41
+ } else if (children !== null && children !== undefined && typeof children !== 'boolean') {
42
+ acc.push(children);
43
+ }
44
+ return acc;
45
+ };
46
+ const toChildArray = children => flattenChildren(children);
47
+ exports.toChildArray = toChildArray;
48
+ const normalizeChildren = children => flattenChildren(children).map(c => typeof c === 'function' ? createElement(c, {
49
+ ...(c.props || {})
50
+ }) : c instanceof Object ? c : createTextElement(c));
51
+ exports.normalizeChildren = normalizeChildren;
@@ -6,5 +6,7 @@ export declare const render: (elements: AnuElement | AnuElement[], containerDom:
6
6
  export declare const unmountComponentAtNode: (containerDom: Element) => void;
7
7
  export declare const __testing: {
8
8
  flushSync(): void;
9
+ installSyncScheduler(): void;
10
+ uninstallSyncScheduler(): void;
9
11
  resetGlobals(): void;
10
12
  };
@@ -61,9 +61,50 @@ const workLoop = deadline => {
61
61
  const performWork = deadline => {
62
62
  workLoop(deadline);
63
63
  if (nextUnitOfWork || updateQueue.length > 0) {
64
- requestIdleCallback(performWork);
64
+ scheduleWork();
65
65
  }
66
66
  };
67
+ const FRAME_BUDGET = 5;
68
+ const now = () => typeof performance !== 'undefined' && typeof performance.now === 'function' ? performance.now() : Date.now();
69
+ let frameDeadline = 0;
70
+ const FRAME_DEADLINE = {
71
+ didTimeout: false,
72
+ timeRemaining: () => Math.max(0, frameDeadline - now())
73
+ };
74
+ const SYNC_DEADLINE = {
75
+ didTimeout: false,
76
+ timeRemaining: () => 999
77
+ };
78
+ const createMacroTaskScheduler = () => {
79
+ let scheduled = false;
80
+ const flush = () => {
81
+ scheduled = false;
82
+ frameDeadline = now() + FRAME_BUDGET;
83
+ performWork(FRAME_DEADLINE);
84
+ };
85
+ let post;
86
+ if (typeof MessageChannel !== 'undefined') {
87
+ const channel = new MessageChannel();
88
+ channel.port1.onmessage = flush;
89
+ post = () => channel.port2.postMessage(null);
90
+ } else {
91
+ post = () => {
92
+ setTimeout(flush, 0);
93
+ };
94
+ }
95
+ return () => {
96
+ if (scheduled) {
97
+ return;
98
+ }
99
+ scheduled = true;
100
+ post();
101
+ };
102
+ };
103
+ const defaultScheduleWork = createMacroTaskScheduler();
104
+ const syncScheduleWork = () => {
105
+ performWork(SYNC_DEADLINE);
106
+ };
107
+ let scheduleWork = defaultScheduleWork;
67
108
  const performUnitOfWork = wipFiber => {
68
109
  beginWork(wipFiber);
69
110
  if (wipFiber.child) {
@@ -163,7 +204,6 @@ const updateClassComponent = wipFiber => {
163
204
  const newChildElements = wipFiber.stateNode.render();
164
205
  reconcileChildrenArray(wipFiber, newChildElements);
165
206
  };
166
- const arrify = val => !val ? [] : Array.isArray(val) ? val : [val];
167
207
  const getTag = element => {
168
208
  if (element.type === _elements.PORTAL_ELEMENT) {
169
209
  return PORTAL;
@@ -177,7 +217,7 @@ const getTag = element => {
177
217
  return CLASS_COMPONENT;
178
218
  };
179
219
  const reconcileChildrenArray = (wipFiber, newChildElements) => {
180
- const elements = arrify(newChildElements);
220
+ const elements = (0, _elements.normalizeChildren)(newChildElements);
181
221
  const oldFiberMap = new Map();
182
222
  let oldFiber = wipFiber.alternate ? wipFiber.alternate.child : undefined;
183
223
  let oldIndex = 0;
@@ -467,7 +507,7 @@ const scheduleUpdate = (instance, partialState, partialStateCallback) => {
467
507
  updateFiber.partialStateCallback = partialStateCallback;
468
508
  }
469
509
  updateQueue.push(updateFiber);
470
- requestIdleCallback(performWork);
510
+ scheduleWork();
471
511
  };
472
512
  exports.scheduleUpdate = scheduleUpdate;
473
513
  const render = (elements, containerDom) => {
@@ -478,7 +518,7 @@ const render = (elements, containerDom) => {
478
518
  children: Array.isArray(elements) ? elements : [elements]
479
519
  }
480
520
  });
481
- requestIdleCallback(performWork);
521
+ scheduleWork();
482
522
  };
483
523
  exports.render = render;
484
524
  const unmountComponentAtNode = containerDom => {
@@ -492,7 +532,7 @@ const unmountComponentAtNode = containerDom => {
492
532
  children: []
493
533
  }
494
534
  });
495
- requestIdleCallback(performWork);
535
+ scheduleWork();
496
536
  };
497
537
  exports.unmountComponentAtNode = unmountComponentAtNode;
498
538
  const __testing = exports.__testing = {
@@ -500,16 +540,24 @@ const __testing = exports.__testing = {
500
540
  if (process.env.NODE_ENV !== 'test') {
501
541
  return;
502
542
  }
503
- const syncDeadline = {
504
- didTimeout: false,
505
- timeRemaining: () => 999
506
- };
507
543
  while (updateQueue.length > 0 || nextUnitOfWork != null) {
508
- workLoop(syncDeadline);
544
+ workLoop(SYNC_DEADLINE);
509
545
  }
510
546
  nextUnitOfWork = null;
511
547
  pendingCommit = null;
512
548
  },
549
+ installSyncScheduler() {
550
+ if (process.env.NODE_ENV !== 'test') {
551
+ return;
552
+ }
553
+ scheduleWork = syncScheduleWork;
554
+ },
555
+ uninstallSyncScheduler() {
556
+ if (process.env.NODE_ENV !== 'test') {
557
+ return;
558
+ }
559
+ scheduleWork = defaultScheduleWork;
560
+ },
513
561
  resetGlobals() {
514
562
  if (process.env.NODE_ENV !== 'test') {
515
563
  return;
package/dist/index.d.ts CHANGED
@@ -118,7 +118,7 @@ declare const Anu: {
118
118
  subscribe: (listener: () => void) => void;
119
119
  unsubscribe: (listener: () => void) => void;
120
120
  };
121
- render(): AnuElement | AnuElement[] | null;
121
+ render(): import(".").AnuChild[] | null;
122
122
  props: import("./core/components/Connector").ConnectorProviderProps;
123
123
  state: Record<string, any>;
124
124
  context: Record<string, any>;
package/dist/index.js CHANGED
@@ -121,22 +121,6 @@ var _Intl = _interopRequireDefault(require("./core/components/Intl"));
121
121
  var _AnulyticsProvider = _interopRequireWildcard(require("./core/components/AnulyticsProvider"));
122
122
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
123
123
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
124
- if (!window.requestIdleCallback) {
125
- window.requestIdleCallback = callback => {
126
- const start = Date.now();
127
- return setTimeout(() => {
128
- callback({
129
- didTimeout: false,
130
- timeRemaining: () => Math.max(0, 50 - (Date.now() - start))
131
- });
132
- }, 1);
133
- };
134
- }
135
- if (!window.cancelIdleCallback) {
136
- window.cancelIdleCallback = id => {
137
- clearTimeout(id);
138
- };
139
- }
140
124
  const Anu = {
141
125
  Anulytics: {
142
126
  Provider: _AnulyticsProvider.default,
@@ -5,25 +5,18 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.uninstallSyncScheduler = exports.installSyncScheduler = exports.flushEffects = exports.act = void 0;
7
7
  var _reconciler = require("../core/reconciler");
8
- const FAKE_DEADLINE = {
9
- didTimeout: false,
10
- timeRemaining: () => 999
11
- };
12
8
  let _installed = false;
13
9
  const installSyncScheduler = () => {
14
10
  if (_installed) {
15
11
  return;
16
12
  }
17
13
  _installed = true;
18
- window.requestIdleCallback = cb => {
19
- cb(FAKE_DEADLINE);
20
- return 0;
21
- };
22
- window.cancelIdleCallback = () => {};
14
+ _reconciler.__testing.installSyncScheduler();
23
15
  };
24
16
  exports.installSyncScheduler = installSyncScheduler;
25
17
  const uninstallSyncScheduler = () => {
26
18
  _installed = false;
19
+ _reconciler.__testing.uninstallSyncScheduler();
27
20
  };
28
21
  exports.uninstallSyncScheduler = uninstallSyncScheduler;
29
22
  const flushEffects = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anu-verzum",
3
- "version": "2.2.9",
3
+ "version": "2.3.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",