@pihanga2/core 0.3.1 → 0.3.3

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
- import equal from "deep-equal"
2
- import { getLogger } from "./logger"
1
+ import equal from "deep-equal";
2
+ import { getLogger } from "./logger";
3
3
  import {
4
4
  CSSModuleClasses,
5
5
  CardAction,
@@ -17,200 +17,223 @@ import {
17
17
  RegisterCardF,
18
18
  StateMapper,
19
19
  StateMapperContext,
20
- } from "./types"
21
- import { Action, AnyAction, Dispatch } from "@reduxjs/toolkit"
20
+ } from "./types";
21
+ import { Action, AnyAction, Dispatch } from "@reduxjs/toolkit";
22
22
 
23
- const logger = getLogger("card-register")
23
+ const logger = getLogger("card-register");
24
24
 
25
25
  export function isCardRef(p: any): boolean {
26
- return (typeof p === "object" && p.cardType !== undefined)
26
+ return typeof p === "object" && p.cardType !== undefined;
27
27
  }
28
28
 
29
29
  export type Mapping = {
30
- cardType: string
31
- props: { [k: string]: unknown }
32
- eventMappers: { [k: string]: (ev: Action) => Action | null }
33
- cardEvents: { [key: string]: string }
34
- parameters: PiCardDef // original
35
- }
30
+ cardType: string;
31
+ props: { [k: string]: unknown };
32
+ eventMappers: {
33
+ [k: string]: (ev: Action, ctxtProps: CardProp) => Action | null;
34
+ };
35
+ cardEvents: { [key: string]: string };
36
+ parameters: PiCardDef; // original
37
+ };
36
38
 
37
39
  export type MetaCard = {
38
- type: string
39
- registerCard: RegisterCardF
40
- mapper: MetaCardMapperF
41
- events?: { [key: string]: string }
42
- }
40
+ type: string;
41
+ registerCard: RegisterCardF;
42
+ mapper: MetaCardMapperF;
43
+ events?: { [key: string]: string };
44
+ };
43
45
 
44
- export const cardTypes: { [k: string]: PiRegisterComponent } = {}
45
- export const metacardTypes: { [k: string]: MetaCard } = {}
46
-
47
- export let framework: string // name of active UI framework
48
- export const cardMappings: { [k: string]: Mapping } = {}
49
- export const dispatch2registerReducer: [React.Dispatch<any>, PiRegisterReducerF][] = []
46
+ export const cardTypes: { [k: string]: PiRegisterComponent } = {};
47
+ export const metacardTypes: { [k: string]: MetaCard } = {};
50
48
 
49
+ export let framework: string; // name of active UI framework
50
+ export const cardMappings: { [k: string]: Mapping } = {};
51
+ export const dispatch2registerReducer: [
52
+ React.Dispatch<any>,
53
+ PiRegisterReducerF
54
+ ][] = [];
51
55
 
52
56
  export function registerCardComponent(card: PiRegisterComponent): void {
53
57
  if (cardTypes[card.name]) {
54
- logger.warn(`Overwriting definition for card type "${card.name}"`)
58
+ logger.warn(`Overwriting definition for card type "${card.name}"`);
55
59
  }
56
- logger.info(`Register card type "${card.name}"`)
60
+ logger.info(`Register card type "${card.name}"`);
57
61
  if (!framework) {
58
62
  // set default framework
59
- const na = card.name.split("/")
63
+ const na = card.name.split("/");
60
64
  if (na.length >= 2) {
61
- framework = na[0]
62
- logger.info(`Setting UI framework to "${framework}"`)
65
+ framework = na[0];
66
+ logger.info(`Setting UI framework to "${framework}"`);
63
67
  }
64
68
  }
65
- cardTypes[card.name] = card
69
+ cardTypes[card.name] = card;
66
70
  }
67
71
 
68
72
  export function registerMetacard(registerCard: RegisterCardF) {
69
73
  function f<C>(declaration: PiRegisterMetaCard) {
70
- const { type, mapper, events } = declaration
74
+ const { type, mapper, events } = declaration;
71
75
  if (metacardTypes[type]) {
72
- logger.warn(`Overwriting definition for meta card type "${type}"`)
76
+ logger.warn(`Overwriting definition for meta card type "${type}"`);
73
77
  }
74
- logger.info(`Register meta card type "${type}"`)
75
- metacardTypes[type] = { type, registerCard, mapper, events }
78
+ logger.info(`Register meta card type "${type}"`);
79
+ metacardTypes[type] = { type, registerCard, mapper, events };
76
80
  }
77
- return f
81
+ return f;
78
82
  }
79
83
 
80
-
81
84
  export function registerCard(
82
85
  registerReducer: PiRegisterReducerF,
83
- dispatchF: React.Dispatch<any>,
86
+ dispatchF: React.Dispatch<any>
84
87
  ) {
85
88
  // to be used by dynamically registered cards
86
- dispatch2registerReducer.push([dispatchF, registerReducer])
89
+ dispatch2registerReducer.push([dispatchF, registerReducer]);
87
90
  return (name: string, parameters: PiCardDef): PiCardRef => {
88
- return _registerCard(name, parameters, registerReducer)
89
- }
91
+ return _registerCard(name, parameters, registerReducer);
92
+ };
90
93
  }
91
94
 
92
95
  export function updateOrRegisterCard(
93
96
  registerReducer: PiRegisterReducerF,
94
- dispatchF: React.Dispatch<any>,
97
+ dispatchF: React.Dispatch<any>
95
98
  ) {
96
99
  // to be used by dynamically registered cards
97
- dispatch2registerReducer.push([dispatchF, registerReducer])
98
- return (name: string, parameters: { [key: string]: GenericCardParameterT }): PiCardRef => {
99
- return _updateCard(name, parameters, registerReducer)
100
- }
100
+ dispatch2registerReducer.push([dispatchF, registerReducer]);
101
+ return (
102
+ name: string,
103
+ parameters: { [key: string]: GenericCardParameterT }
104
+ ): PiCardRef => {
105
+ return _updateCard(name, parameters, registerReducer);
106
+ };
101
107
  }
102
108
 
103
109
  export function _registerCard(
104
110
  name: string,
105
111
  parameters: PiCardDef,
106
112
  registerReducer: PiRegisterReducerF,
107
- overrideEvents?: { [key: string]: string },
113
+ overrideEvents?: { [key: string]: string }
108
114
  ): PiCardRef {
109
115
  if (cardMappings[name]) {
110
- logger.warn(`Overwriting definition for card "${name}"`)
116
+ logger.warn(`Overwriting definition for card "${name}"`);
111
117
  }
112
- let cardType = cardTypes[parameters.cardType]
118
+ let cardType = cardTypes[parameters.cardType];
113
119
  if (!cardType) {
114
120
  if (framework) {
115
- cardType = cardTypes[`${framework}/${parameters.cardType}`]
121
+ cardType = cardTypes[`${framework}/${parameters.cardType}`];
116
122
  }
117
123
  if (!cardType) {
118
124
  // maybe it's a metadata card
119
125
  if (_registerMetadataCard(name, parameters, registerReducer)) {
120
- return name
126
+ return name;
121
127
  }
122
- logger.warn("unknown card type", parameters.cardType)
123
- return name
128
+ logger.warn("unknown card type", parameters.cardType);
129
+ return name;
124
130
  }
125
131
  }
126
132
 
127
- const events = overrideEvents || cardType.events || {}
128
- _createCardMapping(name, parameters, registerReducer, events)
129
- return name
133
+ const events = overrideEvents || cardType.events || {};
134
+ _createCardMapping(name, parameters, registerReducer, events);
135
+ return name;
130
136
  }
131
137
 
132
138
  export function _updateCard(
133
139
  name: string,
134
140
  parameters: { [key: string]: GenericCardParameterT },
135
141
  registerReducer: PiRegisterReducerF,
136
- overrideEvents?: { [key: string]: string },
142
+ overrideEvents?: { [key: string]: string }
137
143
  ): PiCardRef {
138
- const mappings = cardMappings[name]
144
+ const mappings = cardMappings[name];
139
145
  if (!mappings) {
140
146
  // first time
141
147
  if (!parameters.cardType) {
142
- logger.warn("missing 'cardType'", name)
143
- return name
148
+ logger.warn("missing 'cardType'", name);
149
+ return name;
144
150
  }
145
- const p: any = parameters
146
- return _registerCard(name, p, registerReducer, overrideEvents)
151
+ const p: any = parameters;
152
+ return _registerCard(name, p, registerReducer, overrideEvents);
147
153
  }
148
154
 
149
- const p = { ...mappings.parameters, ...parameters }
150
- _createCardMapping(name, p, registerReducer, mappings.cardEvents)
151
- return name
152
-
155
+ const p = { ...mappings.parameters, ...parameters };
156
+ _createCardMapping(name, p, registerReducer, mappings.cardEvents);
157
+ return name;
153
158
  }
154
159
 
155
160
  export function _createCardMapping(
156
161
  name: string,
157
162
  parameters: PiCardDef,
158
163
  registerReducer: PiRegisterReducerF,
159
- cardEvents: { [key: string]: string },
164
+ cardEvents: { [key: string]: string }
160
165
  ) {
161
- const props = {} as { [k: string]: unknown }
162
- const eventMappers = {} as { [k: string]: (ev: Action) => Action }
166
+ const props = {} as { [k: string]: unknown };
167
+ const eventMappers = {} as { [k: string]: (ev: Action) => Action };
163
168
 
164
169
  Object.entries(parameters).forEach(([k, v]) => {
165
- if (k === "cardType") return
170
+ if (k === "cardType") return;
166
171
  if (typeof v === "object") {
167
- const cd = v as PiCardDef // speculative
172
+ const cd = v as PiCardDef; // speculative
168
173
  if (cd.cardType) {
169
- const cardName = `${name}/${k}`
170
- v = _registerCard(cardName, cd, registerReducer)
174
+ const cardName = `${name}/${k}`;
175
+ v = _registerCard(cardName, cd, registerReducer);
171
176
  }
172
177
  }
173
178
  if (
174
179
  k.startsWith("on") &&
175
- processEventParameter(k, v, cardEvents, eventMappers, registerReducer, name)
180
+ processEventParameter(
181
+ k,
182
+ v,
183
+ cardEvents,
184
+ eventMappers,
185
+ registerReducer,
186
+ name
187
+ )
176
188
  ) {
177
- return
189
+ return;
178
190
  }
179
- props[k] = v
180
- })
181
- cardMappings[name] = { cardType: parameters.cardType, props, eventMappers, cardEvents, parameters }
191
+ props[k] = v;
192
+ });
193
+ cardMappings[name] = {
194
+ cardType: parameters.cardType,
195
+ props,
196
+ eventMappers,
197
+ cardEvents,
198
+ parameters,
199
+ };
182
200
  }
183
201
 
184
202
  export function _updateCardMapping(
185
203
  name: string,
186
204
  parameters: PiCardDef,
187
205
  registerReducer: PiRegisterReducerF,
188
- mappings: Mapping,
206
+ mappings: Mapping
189
207
  ) {
190
- return _createCardMapping(name, parameters, registerReducer, mappings.cardEvents)
208
+ return _createCardMapping(
209
+ name,
210
+ parameters,
211
+ registerReducer,
212
+ mappings.cardEvents
213
+ );
191
214
  }
192
215
 
193
216
  function _registerMetadataCard(
194
217
  metaName: string,
195
218
  parameters: PiCardDef,
196
- registerReducer: PiRegisterReducerF,
219
+ registerReducer: PiRegisterReducerF
197
220
  ): boolean {
198
- let mc = metacardTypes[parameters.cardType]
221
+ let mc = metacardTypes[parameters.cardType];
199
222
  if (!mc) {
200
223
  if (framework) {
201
- mc = metacardTypes[`${framework}/${parameters.cardType}`]
224
+ mc = metacardTypes[`${framework}/${parameters.cardType}`];
202
225
  }
203
226
  if (!mc) {
204
- return false
227
+ return false;
205
228
  }
206
229
  }
207
230
  function registerCard(name: string, parameters: PiCardDef): PiCardRef {
208
- const n = `${metaName}/${name}`
209
- return mc.registerCard(n, parameters)
231
+ const n = `${metaName}/${name}`;
232
+ return mc.registerCard(n, parameters);
210
233
  }
211
- const top = mc.mapper(metaName, parameters, registerCard)
212
- _registerCard(metaName, top, registerReducer, mc.events)
213
- return true
234
+ const top = mc.mapper(metaName, parameters, registerCard);
235
+ _registerCard(metaName, top, registerReducer, mc.events);
236
+ return true;
214
237
  }
215
238
 
216
239
  // NOT IMPLEMENTED YET
@@ -238,12 +261,12 @@ function _registerMetadataCard(
238
261
  // }
239
262
 
240
263
  export function createCardDeclaration<Props = {}, Events = {}>(
241
- cardType: string,
264
+ cardType: string
242
265
  ): <S extends ReduxState>(p: PiMapProps<Props, S, Events>) => PiCardDef {
243
266
  return (p) => ({
244
267
  ...p,
245
268
  cardType,
246
- })
269
+ });
247
270
  }
248
271
 
249
272
  function processEventParameter(
@@ -252,57 +275,96 @@ function processEventParameter(
252
275
  events: { [key: string]: string },
253
276
  eventMappers: { [k: string]: (ev: Action) => Action },
254
277
  registerReducer: PiRegisterReducerF,
255
- cardName: string,
278
+ cardName: string
256
279
  ): boolean {
257
280
  const eva = Object.entries(events).find(([n, _]) => {
258
- return propName === n || propName === `${n}Mapper`
259
- })
281
+ return propName === n || propName === `${n}Mapper`;
282
+ });
260
283
  if (!eva) {
261
284
  logger.warn(
262
- `encountered property '${propName}' for card '${cardName}' which looks like an even but is not defined`,
263
- )
264
- return false
285
+ `encountered property '${propName}' for card '${cardName}' which looks like an even but is not defined`
286
+ );
287
+ return false;
265
288
  }
266
289
 
267
- const [evName, actionType] = eva
290
+ const [evName, actionType] = eva;
268
291
  if (propName === evName) {
269
- const r = value as (state: ReduxState, action: CardAction, dispatch: DispatchF) => ReduxState
270
- registerReducer(actionType, (s, a, d) => {
271
- const ca = a as CardAction
272
- if (ca.cardID === cardName) {
273
- s = r(s, ca, d)
274
- }
275
- return s
276
- }, 0, `${cardName}|${propName}`)
292
+ const r = value as (
293
+ state: ReduxState,
294
+ action: CardAction,
295
+ dispatch: DispatchF
296
+ ) => ReduxState;
297
+ registerReducer(
298
+ actionType,
299
+ (s, a, d) => {
300
+ const ca = a as CardAction;
301
+ if (ca.cardID === cardName) {
302
+ s = r(s, ca, d);
303
+ }
304
+ return s;
305
+ },
306
+ 0,
307
+ `${cardName}|${propName}`
308
+ );
277
309
  }
278
310
  if (propName === `${evName}Mapper`) {
279
- logger.debug("processEventParameter", cardName)
311
+ logger.debug("processEventParameter", cardName);
280
312
 
281
- const m = value as (ev: Action) => Action
282
- eventMappers[evName] = m
313
+ const m = value as (ev: Action) => Action;
314
+ eventMappers[evName] = m;
283
315
  }
284
- return true
316
+ return true;
285
317
  }
286
318
 
287
- export function memo<P, T, S extends ReduxState, C>(
319
+ /**
320
+ * Memorises a calculation as long as a certain "part"
321
+ * of the ReduxState is not changing. The `filterF` function
322
+ * is always called with the current ReduxState.
323
+ *
324
+ * If `memo` has been called previously, the return value of
325
+ * `filterF` is compared with the last previous call. If it has
326
+ * changed, `mapF` is called. Both return values are internally
327
+ * stored and the most recent result of `mapF` is returned.
328
+ *
329
+ * If `filterF` is returning the same result as in the most recent
330
+ * call, `mapF` will NOT be called, but the result of the most recent
331
+ * `mapF` is returned.
332
+ *
333
+ * @example
334
+ * ```typescript
335
+ * options: memo<CatalogItemtT[], SelectOptionT[], AppState>(
336
+ * (s) => s.catalog,
337
+ * (items) => items.map(...),
338
+ * ),
339
+ * ```
340
+ *
341
+ * @param filterF Function to return the part [P] of the ReduxState of interests.
342
+ * @param mapF Function to map the result of `mapF` to the return value of type T
343
+ * @typeparam P The type of a section of the ReduxState S.
344
+ * @typeparam T The return type of this function call.
345
+ * @typeparam S The type of the ReduxState which is being passed to `filterF`.
346
+ * @typeparam C They type of specific context this card is being used StateMapperContext<C> (Primarily relevant for tables)
347
+ * @returns The result of `mapF` if the result of `filterF` has changed, otherwise returns a previous result of `mapF`
348
+ */
349
+ export function memo<P, T, S extends ReduxState, C = any>(
288
350
  filterF: (state: S, context: StateMapperContext<C>) => P,
289
- mapperF: (partial: P, context: StateMapperContext<C>, state: S) => T,
351
+ mapperF: (partial: P, context: StateMapperContext<C>, state: S) => T
290
352
  ): (state: S, context: StateMapperContext<C>) => T {
291
- const lastFilter: { [k: string]: P } = {}
292
- const lastValue: { [k: string]: T } = {}
293
- const isNotFirst: { [k: string]: boolean } = {}
353
+ const lastFilter: { [k: string]: P } = {};
354
+ const lastValue: { [k: string]: T } = {};
355
+ const isNotFirst: { [k: string]: boolean } = {};
294
356
 
295
357
  return (state: S, context: StateMapperContext<C>): T => {
296
- const k = context.cardKey || "-"
297
- const fv = filterF(state, context)
358
+ const k = context.cardKey || "-";
359
+ const fv = filterF(state, context);
298
360
  if (isNotFirst[k] && equal(fv, lastFilter[k])) {
299
361
  // nothing changed
300
- return lastValue[k]
362
+ return lastValue[k];
301
363
  }
302
- lastFilter[k] = fv
303
- const v = mapperF(fv, context, state)
304
- lastValue[k] = v
305
- isNotFirst[k] = true
306
- return v
307
- }
308
- }
364
+ lastFilter[k] = fv;
365
+ const v = mapperF(fv, context, state);
366
+ lastValue[k] = v;
367
+ isNotFirst[k] = true;
368
+ return v;
369
+ };
370
+ }