@pihanga2/core 0.3.2 → 0.3.4

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.
@@ -1,5 +1,5 @@
1
1
  import equal from "deep-equal";
2
- import { getLogger } from "./logger";
2
+ import {getLogger} from "./logger";
3
3
  import {
4
4
  CSSModuleClasses,
5
5
  CardAction,
@@ -18,7 +18,7 @@ import {
18
18
  StateMapper,
19
19
  StateMapperContext,
20
20
  } from "./types";
21
- import { Action, AnyAction, Dispatch } from "@reduxjs/toolkit";
21
+ import {Action, AnyAction, Dispatch} from "@reduxjs/toolkit";
22
22
 
23
23
  const logger = getLogger("card-register");
24
24
 
@@ -28,9 +28,11 @@ export function isCardRef(p: any): boolean {
28
28
 
29
29
  export type Mapping = {
30
30
  cardType: string;
31
- props: { [k: string]: unknown };
32
- eventMappers: { [k: string]: (ev: Action) => Action | null };
33
- cardEvents: { [key: string]: string };
31
+ props: {[k: string]: unknown};
32
+ eventMappers: {
33
+ [k: string]: (ev: Action, ctxtProps: CardProp) => Action | null;
34
+ };
35
+ cardEvents: {[key: string]: string};
34
36
  parameters: PiCardDef; // original
35
37
  };
36
38
 
@@ -38,14 +40,14 @@ export type MetaCard = {
38
40
  type: string;
39
41
  registerCard: RegisterCardF;
40
42
  mapper: MetaCardMapperF;
41
- events?: { [key: string]: string };
43
+ events?: {[key: string]: string};
42
44
  };
43
45
 
44
- export const cardTypes: { [k: string]: PiRegisterComponent } = {};
45
- export const metacardTypes: { [k: string]: MetaCard } = {};
46
+ export const cardTypes: {[k: string]: PiRegisterComponent} = {};
47
+ export const metacardTypes: {[k: string]: MetaCard} = {};
46
48
 
47
49
  export let framework: string; // name of active UI framework
48
- export const cardMappings: { [k: string]: Mapping } = {};
50
+ export const cardMappings: {[k: string]: Mapping} = {};
49
51
  export const dispatch2registerReducer: [
50
52
  React.Dispatch<any>,
51
53
  PiRegisterReducerF
@@ -69,12 +71,12 @@ export function registerCardComponent(card: PiRegisterComponent): void {
69
71
 
70
72
  export function registerMetacard(registerCard: RegisterCardF) {
71
73
  function f<C>(declaration: PiRegisterMetaCard) {
72
- const { type, mapper, events } = declaration;
74
+ const {type, mapper, events} = declaration;
73
75
  if (metacardTypes[type]) {
74
76
  logger.warn(`Overwriting definition for meta card type "${type}"`);
75
77
  }
76
78
  logger.info(`Register meta card type "${type}"`);
77
- metacardTypes[type] = { type, registerCard, mapper, events };
79
+ metacardTypes[type] = {type, registerCard, mapper, events};
78
80
  }
79
81
  return f;
80
82
  }
@@ -98,7 +100,7 @@ export function updateOrRegisterCard(
98
100
  dispatch2registerReducer.push([dispatchF, registerReducer]);
99
101
  return (
100
102
  name: string,
101
- parameters: { [key: string]: GenericCardParameterT }
103
+ parameters: {[key: string]: GenericCardParameterT}
102
104
  ): PiCardRef => {
103
105
  return _updateCard(name, parameters, registerReducer);
104
106
  };
@@ -108,7 +110,7 @@ export function _registerCard(
108
110
  name: string,
109
111
  parameters: PiCardDef,
110
112
  registerReducer: PiRegisterReducerF,
111
- overrideEvents?: { [key: string]: string }
113
+ overrideEvents?: {[key: string]: string}
112
114
  ): PiCardRef {
113
115
  if (cardMappings[name]) {
114
116
  logger.warn(`Overwriting definition for card "${name}"`);
@@ -135,9 +137,9 @@ export function _registerCard(
135
137
 
136
138
  export function _updateCard(
137
139
  name: string,
138
- parameters: { [key: string]: GenericCardParameterT },
140
+ parameters: {[key: string]: GenericCardParameterT},
139
141
  registerReducer: PiRegisterReducerF,
140
- overrideEvents?: { [key: string]: string }
142
+ overrideEvents?: {[key: string]: string}
141
143
  ): PiCardRef {
142
144
  const mappings = cardMappings[name];
143
145
  if (!mappings) {
@@ -150,7 +152,7 @@ export function _updateCard(
150
152
  return _registerCard(name, p, registerReducer, overrideEvents);
151
153
  }
152
154
 
153
- const p = { ...mappings.parameters, ...parameters };
155
+ const p = {...mappings.parameters, ...parameters};
154
156
  _createCardMapping(name, p, registerReducer, mappings.cardEvents);
155
157
  return name;
156
158
  }
@@ -159,10 +161,10 @@ export function _createCardMapping(
159
161
  name: string,
160
162
  parameters: PiCardDef,
161
163
  registerReducer: PiRegisterReducerF,
162
- cardEvents: { [key: string]: string }
164
+ cardEvents: {[key: string]: string}
163
165
  ) {
164
- const props = {} as { [k: string]: unknown };
165
- const eventMappers = {} as { [k: string]: (ev: Action) => Action };
166
+ const props = {} as {[k: string]: unknown};
167
+ const eventMappers = {} as {[k: string]: (ev: Action) => Action};
166
168
 
167
169
  Object.entries(parameters).forEach(([k, v]) => {
168
170
  if (k === "cardType") return;
@@ -270,8 +272,8 @@ export function createCardDeclaration<Props = {}, Events = {}>(
270
272
  function processEventParameter(
271
273
  propName: string,
272
274
  value: unknown,
273
- events: { [key: string]: string },
274
- eventMappers: { [k: string]: (ev: Action) => Action },
275
+ events: {[key: string]: string},
276
+ eventMappers: {[k: string]: (ev: Action) => Action},
275
277
  registerReducer: PiRegisterReducerF,
276
278
  cardName: string
277
279
  ): boolean {
@@ -302,7 +304,8 @@ function processEventParameter(
302
304
  return s;
303
305
  },
304
306
  0,
305
- `${cardName}|${propName}`
307
+ `on card ${cardName} for ${propName}`,
308
+ r
306
309
  );
307
310
  }
308
311
  if (propName === `${evName}Mapper`) {
@@ -348,9 +351,9 @@ export function memo<P, T, S extends ReduxState, C = any>(
348
351
  filterF: (state: S, context: StateMapperContext<C>) => P,
349
352
  mapperF: (partial: P, context: StateMapperContext<C>, state: S) => T
350
353
  ): (state: S, context: StateMapperContext<C>) => T {
351
- const lastFilter: { [k: string]: P } = {};
352
- const lastValue: { [k: string]: T } = {};
353
- const isNotFirst: { [k: string]: boolean } = {};
354
+ const lastFilter: {[k: string]: P} = {};
355
+ const lastValue: {[k: string]: T} = {};
356
+ const isNotFirst: {[k: string]: boolean} = {};
354
357
 
355
358
  return (state: S, context: StateMapperContext<C>): T => {
356
359
  const k = context.cardKey || "-";
package/src/router.ts CHANGED
@@ -1,10 +1,19 @@
1
- import { Update, createBrowserHistory, Location } from 'history';
2
- import { getLogger } from './logger';
3
- import { registerActions } from './redux';
4
- import { DispatchF, PathQuery, PiReducer, ReduceF, ReduxAction, ReduxState, Route } from './types';
5
- import { PiRegister } from '.';
6
-
7
- const logger = getLogger("router")
1
+ import {Update, createBrowserHistory, Location} from "history";
2
+ import {getLogger} from "./logger";
3
+ import {createOnAction, registerActions} from "./redux";
4
+ import {
5
+ DEF_REDUCER_PRIORITY,
6
+ DispatchF,
7
+ PathQuery,
8
+ PiReducer,
9
+ ReduceF,
10
+ ReduxAction,
11
+ ReduxState,
12
+ Route,
13
+ } from "./types";
14
+ import {PiRegister} from ".";
15
+
16
+ const logger = getLogger("router");
8
17
  export const browserHistory = createBrowserHistory();
9
18
 
10
19
  // type Route = {
@@ -14,56 +23,69 @@ export const browserHistory = createBrowserHistory();
14
23
  // fromBrowser?: boolean
15
24
  // }
16
25
 
17
- export const ACTION_TYPES = registerActions('pi/router', ['show_page', 'navigate_to_page']);
26
+ export const ACTION_TYPES = registerActions("pi/router", [
27
+ "show_page",
28
+ "navigate_to_page",
29
+ ]);
18
30
 
19
31
  export type ShowPageEvent = {
20
- path: string[]
21
- query?: PathQuery
22
- fromBrowser?: boolean
23
- }
24
- export const onShowPage = createOnAction<ShowPageEvent>(ACTION_TYPES.SHOW_PAGE)
32
+ path: string[];
33
+ query?: PathQuery;
34
+ fromBrowser?: boolean;
35
+ };
36
+ export const onShowPage = createOnAction<ShowPageEvent>(ACTION_TYPES.SHOW_PAGE);
25
37
 
26
- export const showPage = (dispatch: DispatchF, path: string[], query?: PathQuery) => {
27
- dispatch(createShowPageAction(path, query))
28
- }
38
+ export const showPage = (
39
+ dispatch: DispatchF,
40
+ path: string[],
41
+ query?: PathQuery
42
+ ) => {
43
+ dispatch(createShowPageAction(path, query));
44
+ };
29
45
 
30
- export const createShowPageAction = (path: string[], query?: PathQuery): ReduxAction & ShowPageEvent => ({
46
+ export const createShowPageAction = (
47
+ path: string[],
48
+ query?: PathQuery
49
+ ): ReduxAction & ShowPageEvent => ({
31
50
  type: ACTION_TYPES.SHOW_PAGE,
32
- path, query, fromBrowser: false
33
- })
51
+ path,
52
+ query,
53
+ fromBrowser: false,
54
+ });
34
55
 
35
56
  export type NavigateToPageEvent = {
36
- url: string
37
- fromBrowser: boolean
38
- }
39
- export const onNavigateToPage = createOnAction<NavigateToPageEvent>(ACTION_TYPES.NAVIGATE_TO_PAGE)
40
-
41
- export const ON_INIT_ACTION = "pi/start"
42
- export const onInit = createOnAction<{}>(ON_INIT_ACTION)
43
-
44
- export function currentRoute(pathPrefix = ''): Route {
45
- const f = route_functions(pathPrefix)
46
- const r2 = f.url2route(window.location.href)
47
- const r = f.location2route(browserHistory.location)
48
- return r
49
-
57
+ url: string;
58
+ fromBrowser: boolean;
59
+ };
60
+ export const onNavigateToPage = createOnAction<NavigateToPageEvent>(
61
+ ACTION_TYPES.NAVIGATE_TO_PAGE
62
+ );
63
+
64
+ export const ON_INIT_ACTION = "pi/start";
65
+ export const onInit = createOnAction<{}>(ON_INIT_ACTION);
66
+
67
+ export function currentRoute(pathPrefix = ""): Route {
68
+ const f = route_functions(pathPrefix);
69
+ const r2 = f.url2route(window.location.href);
70
+ const r = f.location2route(browserHistory.location);
71
+ return r;
50
72
  }
51
73
 
52
- export function init(reducer: PiReducer, pathPrefix = ''): Route {
53
- let workingURL: string
54
- const f = route_functions(pathPrefix)
74
+ export function init(reducer: PiReducer, pathPrefix = ""): Route {
75
+ let workingURL: string;
76
+ const f = route_functions(pathPrefix);
55
77
 
56
- browserHistory.listen(({ action, location }: Update) => {
78
+ browserHistory.listen(({action, location}: Update) => {
57
79
  // location is an object like window.location
58
- const { url } = f.location2route(location)
80
+ const {url} = f.location2route(location);
59
81
  if (workingURL !== url) {
60
- logger.info('browser history:', url, action)
61
- setTimeout(() => navigateToPage(url, action === 'POP'))
82
+ logger.info("browser history:", url, action);
83
+ setTimeout(() => navigateToPage(url, action === "POP"));
62
84
  }
63
85
  });
64
86
 
65
87
  function browserPath(): Route {
66
- return f.location2route(browserHistory.location)
88
+ return f.location2route(browserHistory.location);
67
89
  }
68
90
 
69
91
  function navigateToPage(url: string, fromBrowser = false) {
@@ -76,9 +98,9 @@ export function init(reducer: PiReducer, pathPrefix = ''): Route {
76
98
 
77
99
  reducer.register<ReduxState, ReduxAction & NavigateToPageEvent>(
78
100
  ACTION_TYPES.NAVIGATE_TO_PAGE,
79
- (state, { url, fromBrowser }, dispatch) => {
80
- const r = f.url2route(url)
81
- r.fromBrowser = fromBrowser
101
+ (state, {url, fromBrowser}, dispatch) => {
102
+ const r = f.url2route(url);
103
+ r.fromBrowser = fromBrowser;
82
104
  if (workingURL && state.route?.url === r.url) {
83
105
  return state;
84
106
  }
@@ -86,16 +108,19 @@ export function init(reducer: PiReducer, pathPrefix = ''): Route {
86
108
  type: ACTION_TYPES.SHOW_PAGE,
87
109
  ...r,
88
110
  });
89
- return state
90
- });
111
+ return state;
112
+ },
113
+ DEF_REDUCER_PRIORITY,
114
+ "@builtin:router:NAVIGATE_TO_PAGE"
115
+ );
91
116
 
92
117
  reducer.register<ReduxState, ReduxAction & ShowPageEvent>(
93
118
  ACTION_TYPES.SHOW_PAGE,
94
- (state, { path, query = {}, fromBrowser = false }) => {
95
- const route = f.pathl2route(path, query)
96
- workingURL = route.url
119
+ (state, {path, query = {}, fromBrowser = false}) => {
120
+ const route = f.pathl2route(path, query);
121
+ workingURL = route.url;
97
122
  if (!fromBrowser) {
98
- const hp = browserPath()
123
+ const hp = browserPath();
99
124
  if (route.url !== hp.url) {
100
125
  browserHistory.push(route.url);
101
126
  }
@@ -103,69 +128,73 @@ export function init(reducer: PiReducer, pathPrefix = ''): Route {
103
128
  state.route = {
104
129
  ...route,
105
130
  fromBrowser,
106
- }
107
- return state
108
- });
109
-
110
- reducer.register('@@INIT', (state) => {
111
- const url = browserPath().url
112
- logger.info(`Request navigation to '${url}'`);
113
- setTimeout(() => navigateToPage(url, true));
114
- return state;
115
- });
116
- return f.location2route(browserHistory.location)
117
- };
131
+ };
132
+ return state;
133
+ },
134
+ DEF_REDUCER_PRIORITY,
135
+ "@builtin:router:SHOW_PAGE"
136
+ );
137
+
138
+ reducer.register(
139
+ "@@INIT",
140
+ (state) => {
141
+ const url = browserPath().url;
142
+ logger.info(`Request navigation to '${url}'`);
143
+ setTimeout(() => navigateToPage(url, true));
144
+ return state;
145
+ },
146
+ DEF_REDUCER_PRIORITY,
147
+ "@builtin:router:@@INIT"
148
+ );
149
+ return f.location2route(browserHistory.location);
150
+ }
118
151
 
119
- function route_functions(pathPrefix = '') {
152
+ function route_functions(pathPrefix = "") {
120
153
  const location2route = (location: Location): Route => {
121
- const [p, s] = [location.pathname, location.search]
122
- const url = s ? `${p}${s}` : p
123
- return url2route(url)
124
- }
154
+ const [p, s] = [location.pathname, location.search];
155
+ const url = s ? `${p}${s}` : p;
156
+ return url2route(url);
157
+ };
125
158
 
126
159
  const url2route = (url: string): Route => {
127
- const [pn, search] = url.split("?")
128
-
129
- const path = pn.substring(pathPrefix.length).split('/').filter(s => s !== '');
130
- const query = {} as PathQuery
131
- const s = search
160
+ const [pn, search] = url.split("?");
161
+
162
+ const path = pn
163
+ .substring(pathPrefix.length)
164
+ .split("/")
165
+ .filter((s) => s !== "");
166
+ const query = {} as PathQuery;
167
+ const s = search;
132
168
  if (s && s.length > 0) {
133
- s.split('&').forEach((el) => {
134
- const [k, v] = el.split('=');
169
+ s.split("&").forEach((el) => {
170
+ const [k, v] = el.split("=");
135
171
  query[decodeURI(k)] = v ? decodeURI(v) : true;
136
172
  });
137
173
  }
138
- return { url, path, query }
139
- }
174
+ return {url, path, query};
175
+ };
140
176
 
141
177
  const pathl2route = (path: string[], query: PathQuery): Route => {
142
- let url = `${pathPrefix}/${path.join('/')}`
178
+ let url = `${pathPrefix}/${path.join("/")}`;
143
179
  if (query) {
144
180
  const qa = Object.entries(query);
145
181
  if (qa.length > 0) {
146
- const s = qa.map(([k, v]) => {
147
- const n = encodeURI(k)
148
- if (typeof v === 'boolean') {
149
- return n
150
- } else if (typeof v === 'number') {
151
- return `${n}=${v}`
152
- } else {
153
- return `${n}=${encodeURI(v)}`
154
- }
155
- }).join('&')
156
- url = `${url}?${s}`
182
+ const s = qa
183
+ .map(([k, v]) => {
184
+ const n = encodeURI(k);
185
+ if (typeof v === "boolean") {
186
+ return n;
187
+ } else if (typeof v === "number") {
188
+ return `${n}=${v}`;
189
+ } else {
190
+ return `${n}=${encodeURI(v)}`;
191
+ }
192
+ })
193
+ .join("&");
194
+ url = `${url}?${s}`;
157
195
  }
158
196
  }
159
- return { url, path, query }
160
- }
161
- return { location2route, url2route, pathl2route }
197
+ return {url, path, query};
198
+ };
199
+ return {location2route, url2route, pathl2route};
162
200
  }
163
-
164
- function createOnAction<E>(actionType: string): <S extends ReduxState>(
165
- register: PiRegister,
166
- f: ReduceF<S, ReduxAction & E>,
167
- ) => void {
168
- return (register, f) => {
169
- register.reducer.register(actionType, f)
170
- }
171
- }
package/src/types.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export type ReduxState = {
2
2
  route: Route;
3
3
 
4
- pihanga?: { [key: string]: any };
4
+ pihanga?: {[key: string]: any};
5
5
  };
6
6
 
7
7
  export type Route = {
@@ -10,7 +10,7 @@ export type Route = {
10
10
  url: string;
11
11
  fromBrowser?: boolean;
12
12
  };
13
- export type PathQuery = { [k: string]: string | number | boolean };
13
+ export type PathQuery = {[k: string]: string | number | boolean};
14
14
 
15
15
  export type ReduxAction = {
16
16
  type: string;
@@ -23,7 +23,7 @@ export type CardAction = ReduxAction & {
23
23
  export type PiRegisterComponent = {
24
24
  name: string;
25
25
  component: any; // ReactComponent
26
- events?: { [key: string]: string };
26
+ events?: {[key: string]: string};
27
27
  // defaults?: { [key: string]: any }
28
28
  };
29
29
 
@@ -48,11 +48,14 @@ export interface PiReducer {
48
48
  dispatchFromReducer: DispatchF;
49
49
  }
50
50
 
51
+ export const DEF_REDUCER_PRIORITY = 0;
52
+
51
53
  export type PiRegisterReducerF = <S extends ReduxState, A extends ReduxAction>(
52
54
  eventType: string,
53
55
  mapper: ReduceF<S, A>, // (state: S, action: A, dispatch: DispatchF) => S,
54
56
  priority?: number,
55
- key?: string
57
+ key?: string,
58
+ targetMapper?: ReduceF<S, A>
56
59
  ) => PiReducerCancelF;
57
60
 
58
61
  export type PiReducerCancelF = () => void;
@@ -69,7 +72,7 @@ export type PiRegisterOneShotReducerF = <
69
72
  // CARDS
70
73
 
71
74
  // context props given to <Card> in parent card
72
- export type PiDefCtxtProps = { [k: string]: any };
75
+ export type PiDefCtxtProps = {[k: string]: any};
73
76
 
74
77
  // type for <Card .../>
75
78
  export type CardProp = {
@@ -95,7 +98,7 @@ export type PiCardProps<P, E = {}> = P & {
95
98
  [Key in keyof E]: (ev: E[Key]) => void;
96
99
  };
97
100
 
98
- export type CSSModuleClasses = { readonly [key: string]: string };
101
+ export type CSSModuleClasses = {readonly [key: string]: string};
99
102
 
100
103
  export type PiCardRef = string | PiCardDef;
101
104
 
@@ -122,15 +125,16 @@ export type PiMapProps<
122
125
  | CType[Property]
123
126
  | StateMapper<CType[Property], S, C>;
124
127
  } & EventHandler<EType, S> &
125
- EventMapper<EType>;
128
+ EventMapper<EType, C>;
126
129
 
127
130
  export type EventHandler<T, S extends ReduxState> = {
128
131
  [Key in keyof T]?: ReduceF<S, T[Key] & ReduxAction>;
129
132
  };
130
133
 
131
- export type EventMapper<T> = {
134
+ export type EventMapper<T, C = PiDefCtxtProps> = {
132
135
  [Key in keyof T as `${Key & string}Mapper`]?: (
133
- ev: T[Key]
136
+ ev: T[Key],
137
+ ctxt: C
134
138
  ) => ReduxAction | null;
135
139
  };
136
140
 
@@ -149,7 +153,7 @@ export type PiCardDef = {
149
153
  export type PiRegisterMetaCard = {
150
154
  type: string;
151
155
  mapper: MetaCardMapperF;
152
- events?: { [key: string]: string };
156
+ events?: {[key: string]: string};
153
157
  };
154
158
 
155
159
  export type RegisterCardF = (name: string, parameters: PiCardDef) => PiCardRef;