anu-verzum 1.6.0 → 1.8.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
@@ -4,7 +4,6 @@
4
4
 
5
5
  <h3>@author: <strong>Anubis-programmer</strong></h3>
6
6
  <h3>@license: <strong>MIT</strong></h3>
7
- <h3>@version: <strong>1.6.0</strong></h3>
8
7
 
9
8
  <br>
10
9
 
@@ -117,11 +116,14 @@ The following types are exported from `anu-verzum` for use in consumer projects:
117
116
  | Type | Description |
118
117
  |------|-------------|
119
118
  | `AnuElement` | The virtual-DOM element descriptor (return type of `createElement`) |
119
+ | `AnuChild` | Union of all valid JSX child types: `AnuElement \| string \| number \| boolean \| null \| undefined` |
120
120
  | `Props` | Base props type — all component prop objects should extend this |
121
121
  | `Ref<T>` | Reference object created by `Anu.createRef<T>()` |
122
122
  | `Component<P, S>` | Abstract base class for class components |
123
123
  | `FunctionComponent<P>` | Function component signature |
124
124
  | `ElementType` | String tag, function component, or class component constructor |
125
+ | `ContextValue<T>` | Context value passed to a `Consumer` render-prop: `{ value: Partial<T>; defaultContext: { value: T } }` |
126
+ | `ConsumerProps<T>` | Props for a typed context `Consumer` — `children` is the render-prop `(ctx: ContextValue<T>) => AnuElement \| null` |
125
127
  | `Store<S, A>` | Store instance returned by `Anu.store.createStore` |
126
128
  | `Reducer<S, A>` | Reducer function signature |
127
129
  | `Middleware<S, A>` | Middleware function signature |
@@ -129,6 +131,7 @@ The following types are exported from `anu-verzum` for use in consumer projects:
129
131
  | `Action` | Base action type `{ type: string; [key: string]: any }` |
130
132
  | `ThunkAction<S>` | Thunk action `(dispatch, getState) => any` |
131
133
  | `SelectorFn<TInput, TOutput>` | Selector function signature for `createSelector` |
134
+ | `CreateSelectorFn` | Overloaded interface for `Anu.store.createSelector` — enables full type inference on transformation parameters |
132
135
  | `ApiSuccessResponse<T>` | Successful HTTP response `{ status: number; response: T \| null }` |
133
136
  | `ApiErrorResponse` | Error HTTP response `{ status: number; response: null }` |
134
137
 
@@ -1626,45 +1629,37 @@ It takes a <code>context</code> argument which can be reached later as <code>con
1626
1629
 
1627
1630
  <h3 id="usage-of-context-provider-and-consumers">Usage of the context provider and its consumer(s)</h3>
1628
1631
 
1629
- - Context props defined on <code>&lt;ThemedContext.ContextProvider /&gt;</code> can be accessed from within the function child of the <code>&lt;ThemedContext.ContextConsumer /&gt;</code> as <code>context.value</code>.
1632
+ - Context props defined on <code>&lt;ThemedContext.Provider /&gt;</code> can be accessed from within the function child of the <code>&lt;ThemedContext.Consumer /&gt;</code> as <code>context.value</code>.
1630
1633
  - Context providers can have multiple context consumer descendents.
1631
1634
  - Context consumers can have one function-as-a-child (which takes the <code>context</code> as argument) which must return a valid HTML, inline-SVG element, component (either class-based or function) or <code>null</code>.
1632
1635
  - You can have as many elements between the context provider and consumer(s), as you want.<br>
1633
1636
  No need to pass the <code>context</code> all the way down within the "props flow"; the function child of the context consumer will have access to it by default.<br>
1634
1637
  It allows you to create your "intermediate" components without depending from the <code>context</code> (they don't need to be aware of it if they have nothing to do with it...).
1638
+ - In TypeScript projects use <code>Provider</code> / <code>Consumer</code> — the callback argument type is inferred from the `createContext<T>()` type parameter, so no manual annotation is needed.
1639
+ - **Avoid** <code>ContextProvider</code> / <code>ContextConsumer</code> in TypeScript projects. These aliases exist for internal use (e.g. by `Intl` and `Feature` modules) but carry looser types: the consumer callback argument is typed as `Props` instead of `ContextValue<T>`, so you lose type inference on `context.value` and `context.defaultContext`.
1635
1640
 
1636
1641
  ```typescript
1637
- import Anu, { AnuElement, ContextValue } from 'anu-verzum';
1642
+ import Anu, { AnuElement } from 'anu-verzum';
1638
1643
 
1639
1644
  const ComponentWithContext = (): AnuElement => {
1640
1645
  const theme2 = 'Theme-2';
1641
1646
  return (
1642
- <ThemedContext.ContextProvider theme={theme2}>
1647
+ <ThemedContext.Provider theme={theme2}>
1643
1648
  <MyComponent1>
1644
1649
  <MyComponentN>
1645
- <ThemedContext.ContextConsumer>
1646
- {(context: ContextValue<ThemeContextValue>) => {
1647
- const {
1648
- value: {
1649
- theme // "Theme-2"
1650
- },
1651
- defaultContext: {
1652
- value: {
1653
- theme: defaultTheme // "Theme-1"
1654
- }
1655
- }
1656
- } = context;
1657
- return (
1658
- <Anu.Fragment>
1659
- <span>{theme}</span>
1660
- <span>{defaultTheme}</span>
1661
- </Anu.Fragment>
1662
- );
1663
- }}
1664
- </ThemedContext.ContextConsumer>
1650
+ <ThemedContext.Consumer>
1651
+ {({ value: { theme }, defaultContext: { value: { theme: defaultTheme } } }) => (
1652
+ // context type is inferred as ContextValue<ThemeContextValue>
1653
+ // theme → "Theme-2", defaultTheme → "Theme-1"
1654
+ <Anu.Fragment>
1655
+ <span>{theme}</span>
1656
+ <span>{defaultTheme}</span>
1657
+ </Anu.Fragment>
1658
+ )}
1659
+ </ThemedContext.Consumer>
1665
1660
  </MyComponentN>
1666
1661
  </MyComponent1>
1667
- </ThemedContext.ContextProvider>
1662
+ </ThemedContext.Provider>
1668
1663
  );
1669
1664
  };
1670
1665
  ```
@@ -1821,10 +1816,11 @@ it should return that part, with the updated desired values:
1821
1816
 
1822
1817
  - Selectors are memoized functions which come handy if you need to do expensive calculations or conversions on the global state.
1823
1818
  - To create selector, use the <code>Anu.store.createSelector()</code> (it comes handy in <code>mapStateToProps()</code> - see <a href="#connector-api">Connecting components to the global state - The Connector API</a> section):
1824
- - Its first argument is an array of "getter" functions which will return the desired slice of the global state object.
1819
+ - Its first argument is either a single "getter" function or an array of up to four "getter" functions, each returning a desired slice of the global state object.
1825
1820
  These functions must always return something.
1826
- - The second argument is a "handler" function which take as many arguments as many "getter" functions you defined; these arguments are the return values of the "getter" functions.
1827
- Their number and order is the same as of the "getters" within the first (array) argument of the <code>Anu.store.createSelector()</code>.
1821
+ - The second argument is a "handler" function which takes as many arguments as "getter" functions you defined; these arguments are the return values of the "getter" functions.
1822
+ Their number and order is the same as of the "getters" within the first argument of the <code>Anu.store.createSelector()</code>.
1823
+ - In TypeScript, when you pass the getter array inline, the handler's parameter types are inferred automatically — no manual annotations needed.
1828
1824
 
1829
1825
  ```typescript
1830
1826
  import Anu, { SelectorFn } from 'anu-verzum';
@@ -1838,17 +1834,18 @@ it should return that part, with the updated desired values:
1838
1834
  const getStatePart1: SelectorFn<MyGlobalState, string> = state => state.myStatePart1;
1839
1835
  const getStatePart2: SelectorFn<MyGlobalState, number[]> = state => state.myStatePart2;
1840
1836
 
1841
- // Store the getters within an array:
1842
- const getters = [getStatePart1, getStatePart2];
1843
-
1844
- // Define the transformation function:
1845
- const handler = (part1: string, part2: number[]): string => {
1846
- // Do something with the state-parts and return the result:
1847
- return `${part1}: ${part2.join(', ')}`;
1848
- };
1837
+ // Single getter — transformation receives the getter's return type directly:
1838
+ const mySimpleSelector = Anu.store.createSelector(
1839
+ getStatePart1,
1840
+ (part1) => part1.toUpperCase() // part1 inferred as string
1841
+ );
1849
1842
 
1850
- // Selector:
1851
- const mySelector: SelectorFn<MyGlobalState, string> = Anu.store.createSelector(getters, handler);
1843
+ // Multiple getters — pass the array inline so TypeScript can infer a tuple:
1844
+ const mySelector = Anu.store.createSelector(
1845
+ [getStatePart1, getStatePart2],
1846
+ (part1, part2) => `${part1}: ${part2.join(', ')}`
1847
+ // part1 inferred as string, part2 as number[]
1848
+ );
1852
1849
  ```
1853
1850
 
1854
1851
  <h3 id="combining-reducers">Combining reducers</h3>
@@ -206,9 +206,7 @@ class AnulyticsProvider extends _Component.Component {
206
206
  }
207
207
  }
208
208
  render() {
209
- const {
210
- children
211
- } = this.props;
209
+ const children = this.props.children;
212
210
  try {
213
211
  if (!children || children.length !== 1) {
214
212
  throw new Error('Provider must have one child element!');
@@ -32,9 +32,7 @@ class Provider extends _Component.Component {
32
32
  });
33
33
  }
34
34
  render() {
35
- const {
36
- children
37
- } = this.props;
35
+ const children = this.props.children;
38
36
  try {
39
37
  if (!children || children.length !== 1) {
40
38
  throw new Error('Provider must have one child element!');
@@ -1,15 +1,18 @@
1
1
  import { Component } from './Component';
2
- import { Props } from '../elements';
2
+ import { AnuElement, Props } from '../elements';
3
3
  export type ContextValue<T> = {
4
4
  value: Partial<T>;
5
5
  defaultContext: {
6
6
  value: T;
7
7
  };
8
8
  };
9
- export type Context = {
10
- Provider: new (props: Props) => Component;
11
- Consumer: new (props: Props) => Component;
9
+ export type ConsumerProps<T> = {
10
+ children: (ctx: ContextValue<T>) => AnuElement | null;
11
+ };
12
+ export type Context<T extends Record<string, any> = Record<string, any>> = {
13
+ Provider: new (props: Props & Partial<T>) => Component;
14
+ Consumer: new (props: ConsumerProps<T>) => Component;
12
15
  ContextProvider: new (props: Props) => Component;
13
16
  ContextConsumer: new (props: Props) => Component;
14
17
  };
15
- export declare const createContext: <T extends Record<string, any> = Record<string, any>>(context: T) => Context;
18
+ export declare const createContext: <T extends Record<string, any> = Record<string, any>>(context: T) => Context<T>;
@@ -40,9 +40,7 @@ const createContext = context => {
40
40
  }
41
41
  }
42
42
  render() {
43
- const {
44
- children
45
- } = this.props;
43
+ const children = this.props.children;
46
44
  try {
47
45
  if (!children || children.length !== 1) {
48
46
  throw new Error('Context Component must have exactly one child element!');
@@ -62,9 +60,7 @@ const createContext = context => {
62
60
  }
63
61
  }
64
62
  render() {
65
- const {
66
- children
67
- } = this.props;
63
+ const children = this.props.children;
68
64
  const {
69
65
  value,
70
66
  defaultContext
@@ -7,9 +7,7 @@ exports.Fragment = void 0;
7
7
  var _Component = require("./Component");
8
8
  class Fragment extends _Component.Component {
9
9
  render() {
10
- const {
11
- children
12
- } = this.props;
10
+ const children = this.props.children;
13
11
  try {
14
12
  if (!children || !children.length) {
15
13
  throw new Error('Fragment must have at least one child element!');
@@ -17,8 +17,8 @@ export interface AbbreviateNumberOptions {
17
17
  }
18
18
  declare const Intl: {
19
19
  abbreviateNumber: (value: number, options?: AbbreviateNumberOptions) => string | number;
20
- FormattedMessage: ({ id, values, defaultMessage }: FormattedMessageProps) => AnuElement | undefined;
20
+ FormattedMessage: ({ id, values, defaultMessage }: FormattedMessageProps) => AnuElement;
21
21
  formatMessage: (id: string, values?: Record<string, string | number>, defaultMessage?: string) => string;
22
- Provider: ({ locale, messages, defaultLocale, children }: IntlProviderProps) => AnuElement | undefined;
22
+ Provider: ({ locale, messages, defaultLocale, children }: IntlProviderProps) => AnuElement | null;
23
23
  };
24
24
  export default Intl;
@@ -46,7 +46,7 @@ const IntlProvider = ({
46
46
  }
47
47
  } catch (err) {
48
48
  console.error(err);
49
- return undefined;
49
+ return null;
50
50
  }
51
51
  };
52
52
  const interpolateValues = (text, values) => {
@@ -89,7 +89,7 @@ const FormattedMessage = ({
89
89
  }
90
90
  } catch (err) {
91
91
  console.error(err);
92
- return undefined;
92
+ return null;
93
93
  }
94
94
  });
95
95
  const formatMessage = (id, values, defaultMessage) => {
@@ -1,6 +1,7 @@
1
1
  export declare const TEXT_ELEMENT: "TEXT_ELEMENT";
2
+ export type AnuChild = AnuElement | string | number | boolean | null | undefined;
2
3
  export type Props = {
3
- children?: AnuElement[];
4
+ children?: AnuChild | AnuChild[];
4
5
  ref?: Ref<any>;
5
6
  key?: string | number;
6
7
  style?: Partial<CSSStyleDeclaration & Record<string, string>>;
@@ -13,11 +13,14 @@ const createTextElement = value => ({
13
13
  });
14
14
  const createElement = (type, config, ...args) => {
15
15
  const props = Object.assign({}, config);
16
- const hasChildren = args.length > 0;
17
- const rawChildren = hasChildren ? [].concat(...args) : [];
18
- props.children = rawChildren.filter(c => c !== null && c !== false).map(c => typeof c === 'function' ? createElement(c, {
19
- ...(c.props || {})
20
- }) : c instanceof Object ? c : createTextElement(c));
16
+ if (args.length > 0) {
17
+ const rawChildren = [].concat(...args);
18
+ props.children = rawChildren.filter(c => c !== null && c !== false).map(c => typeof c === 'function' ? createElement(c, {
19
+ ...(c.props || {})
20
+ }) : c instanceof Object ? c : createTextElement(c));
21
+ } else {
22
+ props.children = props.children ?? [];
23
+ }
21
24
  return {
22
25
  type,
23
26
  props
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@ declare const Anu: {
27
27
  };
28
28
  }, props?: unknown) => void;
29
29
  };
30
- createContext: <T extends Record<string, any> = Record<string, any>>(context: T) => import("./core/components/Context").Context;
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
32
  createRef: <T = any>() => import("./core/reconciler").Ref<T>;
33
33
  Component: typeof Component;
@@ -88,9 +88,9 @@ declare const Anu: {
88
88
  };
89
89
  Intl: {
90
90
  abbreviateNumber: (value: number, options?: import(".").AbbreviateNumberOptions) => string | number;
91
- FormattedMessage: ({ id, values, defaultMessage }: import("./core/components/Intl").FormattedMessageProps) => AnuElement | undefined;
91
+ FormattedMessage: ({ id, values, defaultMessage }: import("./core/components/Intl").FormattedMessageProps) => AnuElement;
92
92
  formatMessage: (id: string, values?: Record<string, string | number>, defaultMessage?: string) => string;
93
- Provider: ({ locale, messages, defaultLocale, children }: import("./core/components/Intl").IntlProviderProps) => AnuElement | undefined;
93
+ Provider: ({ locale, messages, defaultLocale, children }: import("./core/components/Intl").IntlProviderProps) => AnuElement | null;
94
94
  };
95
95
  Connector: {
96
96
  connect: <TState = any, TOwnProps extends Props = Props, TStateProps extends Props = Props, TDispatchProps extends Props = Props>(mapStateToProps?: ((state: TState, ownProps: TOwnProps) => TStateProps) | null, mapDispatchToProps?: ((dispatch: any, ownProps: TOwnProps) => TDispatchProps) | null) => (WrappedComponent: import("./core/elements").ComponentConstructor<TStateProps & TDispatchProps & TOwnProps>) => import("./core/elements").ComponentConstructor;
@@ -124,7 +124,7 @@ declare const Anu: {
124
124
  };
125
125
  store: {
126
126
  combineReducers: <S extends Record<string, any> = Record<string, any>>(reducers: { [K in keyof S]: import(".").Reducer<S[K]>; }) => import(".").Reducer<S>;
127
- createSelector: <TInput = any, TOutput = any>(dependenciesInput: import(".").SelectorFn<TInput> | Array<import(".").SelectorFn<TInput>>, transformation: (...args: any[]) => TOutput) => import(".").SelectorFn<TInput, TOutput>;
127
+ createSelector: import(".").CreateSelectorFn;
128
128
  createStore: <S = any, A extends import(".").Action = import(".").Action>(reducer: import(".").Reducer<S, A>, initialState: S, middleware?: import(".").Middleware<S, A>) => import(".").Store<S, A>;
129
129
  middleware: {
130
130
  applyMiddleware: <S = any, A extends import(".").Action = import(".").Action>(...middlewares: Array<import(".").Middleware<S, A>>) => (store: import(".").MiddlewareAPI<S, A>) => ((next: import(".").Dispatch<A>) => import(".").Dispatch<A>);
@@ -136,9 +136,9 @@ declare const Anu: {
136
136
  deepEqual: (object1: Record<string, any>, object2: Record<string, any>) => boolean;
137
137
  };
138
138
  };
139
- export type { AnuElement, Props, Ref, FunctionComponent, ElementType } from './core/elements';
140
- export type { ContextValue } from './core/components/Context';
141
- export type { Action, ThunkAction, Dispatch, Reducer, MiddlewareAPI, Middleware, Store, SelectorFn } from './store/store';
139
+ export type { AnuElement, AnuChild, Props, Ref, FunctionComponent, ElementType } from './core/elements';
140
+ export type { ContextValue, ConsumerProps } from './core/components/Context';
141
+ export type { Action, ThunkAction, Dispatch, Reducer, MiddlewareAPI, Middleware, Store, SelectorFn, CreateSelectorFn } from './store/store';
142
142
  export type { ApiSuccessResponse, ApiErrorResponse } from './server-api/server-api';
143
143
  export { Component, Fragment, createElement, createRef, createContext, render, goTo };
144
144
  export { AnulyticsProvider, trackEvent };
@@ -17,9 +17,16 @@ export type Store<S = any, A extends Action = Action> = {
17
17
  unsubscribe: (listener: () => void) => void;
18
18
  };
19
19
  export type SelectorFn<TInput = any, TOutput = any> = (input: TInput) => TOutput;
20
+ export interface CreateSelectorFn {
21
+ <TInput, TI, TOutput>(dep: SelectorFn<TInput, TI>, fn: (r: TI) => TOutput): SelectorFn<TInput, TOutput>;
22
+ <TInput, T1, TOutput>(deps: [SelectorFn<TInput, T1>], fn: (r1: T1) => TOutput): SelectorFn<TInput, TOutput>;
23
+ <TInput, T1, T2, TOutput>(deps: [SelectorFn<TInput, T1>, SelectorFn<TInput, T2>], fn: (r1: T1, r2: T2) => TOutput): SelectorFn<TInput, TOutput>;
24
+ <TInput, T1, T2, T3, TOutput>(deps: [SelectorFn<TInput, T1>, SelectorFn<TInput, T2>, SelectorFn<TInput, T3>], fn: (r1: T1, r2: T2, r3: T3) => TOutput): SelectorFn<TInput, TOutput>;
25
+ <TInput, T1, T2, T3, T4, TOutput>(deps: [SelectorFn<TInput, T1>, SelectorFn<TInput, T2>, SelectorFn<TInput, T3>, SelectorFn<TInput, T4>], fn: (r1: T1, r2: T2, r3: T3, r4: T4) => TOutput): SelectorFn<TInput, TOutput>;
26
+ }
20
27
  declare const store: {
21
28
  combineReducers: <S extends Record<string, any> = Record<string, any>>(reducers: { [K in keyof S]: Reducer<S[K]>; }) => Reducer<S>;
22
- createSelector: <TInput = any, TOutput = any>(dependenciesInput: SelectorFn<TInput> | Array<SelectorFn<TInput>>, transformation: (...args: any[]) => TOutput) => SelectorFn<TInput, TOutput>;
29
+ createSelector: CreateSelectorFn;
23
30
  createStore: <S = any, A extends Action = Action>(reducer: Reducer<S, A>, initialState: S, middleware?: Middleware<S, A>) => Store<S, A>;
24
31
  middleware: {
25
32
  applyMiddleware: <S = any, A extends Action = Action>(...middlewares: Array<Middleware<S, A>>) => (store: MiddlewareAPI<S, A>) => ((next: Dispatch<A>) => Dispatch<A>);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anu-verzum",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
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",