@pihanga2/core 0.2.1 → 0.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/dist/card.d.ts +2 -8
- package/dist/card.d.ts.map +1 -1
- package/dist/card.js +24 -192
- package/dist/card.js.map +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -9
- package/dist/index.js.map +1 -1
- package/dist/reducer.d.ts.map +1 -1
- package/dist/reducer.js +52 -32
- package/dist/reducer.js.map +1 -1
- package/dist/register_cards.d.ts +56 -0
- package/dist/register_cards.d.ts.map +1 -0
- package/dist/register_cards.js +204 -0
- package/dist/register_cards.js.map +1 -0
- package/dist/rest/types.d.ts +1 -1
- package/dist/rest/types.d.ts.map +1 -1
- package/dist/root.d.ts +3 -0
- package/dist/root.d.ts.map +1 -0
- package/dist/root.js +9 -0
- package/dist/root.js.map +1 -0
- package/dist/router.d.ts.map +1 -1
- package/dist/types.d.ts +9 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -10
- package/src/card.tsx +237 -437
- package/src/{index.tsx → index.ts} +25 -14
- package/src/reducer.ts +67 -32
- package/src/register_cards.ts +308 -0
- package/src/rest/types.ts +1 -1
- package/src/root.tsx +14 -0
- package/src/types.ts +14 -5
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import React from "react"
|
|
2
1
|
import ReactDOM from "react-dom/client"
|
|
3
|
-
import { Provider } from "react-redux"
|
|
4
2
|
import { Dispatch } from "react"
|
|
5
3
|
|
|
6
4
|
import {
|
|
@@ -13,8 +11,11 @@ import {
|
|
|
13
11
|
RegisterCardF,
|
|
14
12
|
MetaCardMapperF,
|
|
15
13
|
PiRegisterMetaCard,
|
|
14
|
+
PiMapProps,
|
|
15
|
+
WindowProps,
|
|
16
|
+
GenericCardParameterT,
|
|
16
17
|
} from "./types"
|
|
17
|
-
import {
|
|
18
|
+
import { createCardDeclaration, registerCard, registerCardComponent, registerMetacard, updateOrRegisterCard } from "./register_cards"
|
|
18
19
|
import { createReducer } from "./reducer"
|
|
19
20
|
import { ON_INIT_ACTION, currentRoute, init as routerInit } from "./router"
|
|
20
21
|
|
|
@@ -32,6 +33,7 @@ import {
|
|
|
32
33
|
registerPOST,
|
|
33
34
|
registerPUT,
|
|
34
35
|
} from "./rest"
|
|
36
|
+
import { RootComponent } from "./root"
|
|
35
37
|
const logger = getLogger("root")
|
|
36
38
|
|
|
37
39
|
export type {
|
|
@@ -47,9 +49,11 @@ export type {
|
|
|
47
49
|
StateMapper,
|
|
48
50
|
PiReducer,
|
|
49
51
|
PiRegisterMetaCard,
|
|
52
|
+
WindowProps,
|
|
50
53
|
} from "./types"
|
|
51
54
|
export { registerActions, actionTypesToEvents, createOnAction } from "./redux"
|
|
52
|
-
export { Card,
|
|
55
|
+
export { Card, usePiReducer } from "./card"
|
|
56
|
+
export { memo, createCardDeclaration, isCardRef } from "./register_cards"
|
|
53
57
|
export { getLogger } from "./logger"
|
|
54
58
|
export type { PiCardProps, PiCardRef } from "./types"
|
|
55
59
|
export type { ErrorAction as RestErrorAction } from "./rest"
|
|
@@ -59,7 +63,12 @@ export { showPage, onInit, onShowPage, createShowPageAction, onNavigateToPage }
|
|
|
59
63
|
export type { ShowPageEvent, NavigateToPageEvent } from "./router"
|
|
60
64
|
|
|
61
65
|
export interface PiRegister {
|
|
66
|
+
//window(parameters: PiCardDef): PiCardRef
|
|
67
|
+
|
|
68
|
+
window<S extends ReduxState>(parameters: PiMapProps<WindowProps, S, {}>): PiCardRef
|
|
69
|
+
|
|
62
70
|
card(name: string, parameters: PiCardDef): PiCardRef
|
|
71
|
+
updateCard(name: string, parameters: { [key: string]: GenericCardParameterT }): PiCardRef
|
|
63
72
|
|
|
64
73
|
cardComponent(declaration: PiRegisterComponent): void
|
|
65
74
|
|
|
@@ -157,11 +166,23 @@ export function start<S extends Partial<ReduxState>>(
|
|
|
157
166
|
}
|
|
158
167
|
})
|
|
159
168
|
})
|
|
169
|
+
// make pihanga's reducer interface available to cards
|
|
170
|
+
const anyStore: any = store
|
|
171
|
+
anyStore.piReducer = piReducer
|
|
172
|
+
|
|
160
173
|
dispatchF = store.dispatch
|
|
161
174
|
|
|
162
175
|
const card = registerCard(piReducer.register, dispatchF)
|
|
176
|
+
const updateCard = updateOrRegisterCard(piReducer.register, dispatchF)
|
|
177
|
+
const window = <S extends ReduxState>(p: PiMapProps<WindowProps, S, {}>): PiCardRef => {
|
|
178
|
+
return card("_window", { cardType: "framework", ...p })
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
163
182
|
const register: PiRegister = {
|
|
183
|
+
window,
|
|
164
184
|
card,
|
|
185
|
+
updateCard,
|
|
165
186
|
cardComponent: registerCardComponent,
|
|
166
187
|
metaCard: registerMetacard(card),
|
|
167
188
|
reducer: piReducer,
|
|
@@ -181,13 +202,3 @@ export function start<S extends Partial<ReduxState>>(
|
|
|
181
202
|
|
|
182
203
|
return register
|
|
183
204
|
}
|
|
184
|
-
|
|
185
|
-
function RootComponent(store: any) {
|
|
186
|
-
return (
|
|
187
|
-
<React.StrictMode>
|
|
188
|
-
<Provider store={store}>
|
|
189
|
-
<Card cardName="page" parentCard="" />
|
|
190
|
-
</Provider>
|
|
191
|
-
</React.StrictMode>
|
|
192
|
-
)
|
|
193
|
-
}
|
package/src/reducer.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Action, Reducer } from "@reduxjs/toolkit"
|
|
|
2
2
|
import {
|
|
3
3
|
DispatchF,
|
|
4
4
|
PiReducer,
|
|
5
|
+
PiReducerCancelF,
|
|
5
6
|
PiRegisterOneShotReducerF,
|
|
6
7
|
PiRegisterReducerF,
|
|
7
8
|
ReduceF,
|
|
@@ -14,6 +15,7 @@ import { RegisterCardState, UPDATE_STATE_ACTION } from "./card"
|
|
|
14
15
|
import StackTrace from "stacktrace-js"
|
|
15
16
|
import { getLogger } from "./logger"
|
|
16
17
|
import { Dispatch } from "react"
|
|
18
|
+
import { currentRoute } from "./router"
|
|
17
19
|
|
|
18
20
|
const logger = getLogger("reducer")
|
|
19
21
|
|
|
@@ -21,6 +23,7 @@ type ReducerDef<S extends ReduxState, A extends ReduxAction> = {
|
|
|
21
23
|
mapperMany?: ReduceF<S, A>
|
|
22
24
|
mapperOnce?: ReduceOnceF<S, A>
|
|
23
25
|
priority?: number
|
|
26
|
+
key?: string
|
|
24
27
|
definedIn?: StackTrace.StackFrame
|
|
25
28
|
}
|
|
26
29
|
|
|
@@ -40,34 +43,21 @@ export function createReducer(
|
|
|
40
43
|
): ReduxState => {
|
|
41
44
|
const s = state || initialState
|
|
42
45
|
const ra = mappings[action.type]
|
|
43
|
-
|
|
46
|
+
const rany = mappings["*"]
|
|
47
|
+
if ((!ra || ra.length === 0) && (!rany || rany.length === 0)) {
|
|
44
48
|
return s
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
const nextState = produce<ReduxState, ReduxState>(s, (draft) => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (!flag) {
|
|
58
|
-
rout.push(m)
|
|
59
|
-
}
|
|
60
|
-
return s
|
|
61
|
-
} else {
|
|
62
|
-
return d
|
|
63
|
-
}
|
|
64
|
-
} catch (err: any) {
|
|
65
|
-
logger.error(err.message, m.definedIn)
|
|
66
|
-
return d
|
|
67
|
-
}
|
|
68
|
-
}, draft)
|
|
69
|
-
mappings[action.type] = rout
|
|
70
|
-
return outDraft
|
|
52
|
+
if (ra) {
|
|
53
|
+
const rout = _reduce(ra, draft, action, delayedDispatcher)
|
|
54
|
+
mappings[action.type] = rout
|
|
55
|
+
}
|
|
56
|
+
if (rany) {
|
|
57
|
+
const rout2 = _reduce(rany, draft, action, delayedDispatcher)
|
|
58
|
+
mappings["*"] = rout2
|
|
59
|
+
}
|
|
60
|
+
return
|
|
71
61
|
})
|
|
72
62
|
return nextState
|
|
73
63
|
}
|
|
@@ -79,8 +69,9 @@ export function createReducer(
|
|
|
79
69
|
eventType: string,
|
|
80
70
|
mapper: ReduceF<S, A>,
|
|
81
71
|
priority: number = 0,
|
|
82
|
-
|
|
83
|
-
|
|
72
|
+
key: string | undefined = undefined
|
|
73
|
+
): PiReducerCancelF => {
|
|
74
|
+
return addReducer(eventType, { mapperMany: mapper, priority, key })
|
|
84
75
|
}
|
|
85
76
|
|
|
86
77
|
const registerOneShot: PiRegisterOneShotReducerF = <
|
|
@@ -88,18 +79,22 @@ export function createReducer(
|
|
|
88
79
|
A extends ReduxAction,
|
|
89
80
|
>(
|
|
90
81
|
eventType: string,
|
|
91
|
-
mapper: (state: S, action: A, dispatch: DispatchF) =>
|
|
82
|
+
mapper: (state: S, action: A, dispatch: DispatchF) => boolean,
|
|
92
83
|
priority: number = 0,
|
|
93
|
-
|
|
94
|
-
|
|
84
|
+
key: string | undefined = undefined
|
|
85
|
+
): PiReducerCancelF => {
|
|
86
|
+
return addReducer(eventType, { mapperOnce: mapper, priority, key })
|
|
95
87
|
}
|
|
96
88
|
|
|
89
|
+
const nonCancelF = () => {}
|
|
90
|
+
|
|
97
91
|
function addReducer<S extends ReduxState, A extends ReduxAction>(
|
|
98
92
|
eventType: string,
|
|
99
93
|
reducerDef: ReducerDef<S, A>,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
94
|
+
): PiReducerCancelF {
|
|
95
|
+
let m = mappings[eventType] || []
|
|
96
|
+
const key = reducerDef.key
|
|
97
|
+
m = removeReducer(key, m)
|
|
103
98
|
m.push(reducerDef as any as ReducerDef<ReduxState, Action<any>>) // keep typing happy
|
|
104
99
|
m.sort((a, b) => (b.priority || 0) - (a.priority || 0))
|
|
105
100
|
mappings[eventType] = m
|
|
@@ -114,6 +109,10 @@ export function createReducer(
|
|
|
114
109
|
logger.warn(err.message)
|
|
115
110
|
}
|
|
116
111
|
StackTrace.get().then(callback).catch(errback)
|
|
112
|
+
return key ? () => {
|
|
113
|
+
let m = mappings[eventType] || []
|
|
114
|
+
mappings[eventType] = removeReducer(key, m)
|
|
115
|
+
} : nonCancelF
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
const piReducer: PiReducer = {
|
|
@@ -125,3 +124,39 @@ export function createReducer(
|
|
|
125
124
|
|
|
126
125
|
return [reducer, piReducer]
|
|
127
126
|
}
|
|
127
|
+
|
|
128
|
+
function removeReducer(
|
|
129
|
+
key: string | undefined,
|
|
130
|
+
m: ReducerDef<ReduxState, Action>[]
|
|
131
|
+
) {
|
|
132
|
+
if (key) {
|
|
133
|
+
return m.filter((r) => r.key !== key)
|
|
134
|
+
} else {
|
|
135
|
+
return m
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function _reduce(
|
|
140
|
+
ra: ReducerDef<ReduxState, Action>[],
|
|
141
|
+
draft: ReduxState,
|
|
142
|
+
action: Action,
|
|
143
|
+
delayedDispatcher: (a: any) => void,
|
|
144
|
+
): ReducerDef<ReduxState, Action<any>>[] {
|
|
145
|
+
const rout: ReducerDef<ReduxState, Action<any>>[] = []
|
|
146
|
+
ra.forEach((m) => {
|
|
147
|
+
try {
|
|
148
|
+
if (m.mapperMany) {
|
|
149
|
+
m.mapperMany(draft, action, delayedDispatcher)
|
|
150
|
+
rout.push(m)
|
|
151
|
+
} else if (m.mapperOnce) {
|
|
152
|
+
const flag = m.mapperOnce(draft, action, delayedDispatcher)
|
|
153
|
+
if (!flag) {
|
|
154
|
+
rout.push(m)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
} catch (err: any) {
|
|
158
|
+
logger.error(err.message, m.definedIn)
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
return rout
|
|
162
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import equal from "deep-equal"
|
|
2
|
+
import { getLogger } from "./logger"
|
|
3
|
+
import {
|
|
4
|
+
CSSModuleClasses,
|
|
5
|
+
CardAction,
|
|
6
|
+
CardProp,
|
|
7
|
+
DispatchF,
|
|
8
|
+
GenericCardParameterT,
|
|
9
|
+
MetaCardMapperF,
|
|
10
|
+
PiCardDef,
|
|
11
|
+
PiCardRef,
|
|
12
|
+
PiMapProps,
|
|
13
|
+
PiRegisterComponent,
|
|
14
|
+
PiRegisterMetaCard,
|
|
15
|
+
PiRegisterReducerF,
|
|
16
|
+
ReduxState,
|
|
17
|
+
RegisterCardF,
|
|
18
|
+
StateMapper,
|
|
19
|
+
StateMapperContext,
|
|
20
|
+
} from "./types"
|
|
21
|
+
import { Action, AnyAction, Dispatch } from "@reduxjs/toolkit"
|
|
22
|
+
|
|
23
|
+
const logger = getLogger("card-register")
|
|
24
|
+
|
|
25
|
+
export function isCardRef(p: any): boolean {
|
|
26
|
+
return (typeof p === "object" && p.cardType !== undefined)
|
|
27
|
+
}
|
|
28
|
+
|
|
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
|
+
}
|
|
36
|
+
|
|
37
|
+
export type MetaCard = {
|
|
38
|
+
type: string
|
|
39
|
+
registerCard: RegisterCardF
|
|
40
|
+
mapper: MetaCardMapperF
|
|
41
|
+
events?: { [key: string]: string }
|
|
42
|
+
}
|
|
43
|
+
|
|
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][] = []
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
export function registerCardComponent(card: PiRegisterComponent): void {
|
|
53
|
+
if (cardTypes[card.name]) {
|
|
54
|
+
logger.warn(`Overwriting definition for card type "${card.name}"`)
|
|
55
|
+
}
|
|
56
|
+
logger.info(`Register card type "${card.name}"`)
|
|
57
|
+
if (!framework) {
|
|
58
|
+
// set default framework
|
|
59
|
+
const na = card.name.split("/")
|
|
60
|
+
if (na.length >= 2) {
|
|
61
|
+
framework = na[0]
|
|
62
|
+
logger.info(`Setting UI framework to "${framework}"`)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
cardTypes[card.name] = card
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function registerMetacard(registerCard: RegisterCardF) {
|
|
69
|
+
function f<C>(declaration: PiRegisterMetaCard) {
|
|
70
|
+
const { type, mapper, events } = declaration
|
|
71
|
+
if (metacardTypes[type]) {
|
|
72
|
+
logger.warn(`Overwriting definition for meta card type "${type}"`)
|
|
73
|
+
}
|
|
74
|
+
logger.info(`Register meta card type "${type}"`)
|
|
75
|
+
metacardTypes[type] = { type, registerCard, mapper, events }
|
|
76
|
+
}
|
|
77
|
+
return f
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
export function registerCard(
|
|
82
|
+
registerReducer: PiRegisterReducerF,
|
|
83
|
+
dispatchF: React.Dispatch<any>,
|
|
84
|
+
) {
|
|
85
|
+
// to be used by dynamically registered cards
|
|
86
|
+
dispatch2registerReducer.push([dispatchF, registerReducer])
|
|
87
|
+
return (name: string, parameters: PiCardDef): PiCardRef => {
|
|
88
|
+
return _registerCard(name, parameters, registerReducer)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function updateOrRegisterCard(
|
|
93
|
+
registerReducer: PiRegisterReducerF,
|
|
94
|
+
dispatchF: React.Dispatch<any>,
|
|
95
|
+
) {
|
|
96
|
+
// 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
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function _registerCard(
|
|
104
|
+
name: string,
|
|
105
|
+
parameters: PiCardDef,
|
|
106
|
+
registerReducer: PiRegisterReducerF,
|
|
107
|
+
overrideEvents?: { [key: string]: string },
|
|
108
|
+
): PiCardRef {
|
|
109
|
+
if (cardMappings[name]) {
|
|
110
|
+
logger.warn(`Overwriting definition for card "${name}"`)
|
|
111
|
+
}
|
|
112
|
+
let cardType = cardTypes[parameters.cardType]
|
|
113
|
+
if (!cardType) {
|
|
114
|
+
if (framework) {
|
|
115
|
+
cardType = cardTypes[`${framework}/${parameters.cardType}`]
|
|
116
|
+
}
|
|
117
|
+
if (!cardType) {
|
|
118
|
+
// maybe it's a metadata card
|
|
119
|
+
if (_registerMetadataCard(name, parameters, registerReducer)) {
|
|
120
|
+
return name
|
|
121
|
+
}
|
|
122
|
+
logger.warn("unknown card type", parameters.cardType)
|
|
123
|
+
return name
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const events = overrideEvents || cardType.events || {}
|
|
128
|
+
_createCardMapping(name, parameters, registerReducer, events)
|
|
129
|
+
return name
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function _updateCard(
|
|
133
|
+
name: string,
|
|
134
|
+
parameters: { [key: string]: GenericCardParameterT },
|
|
135
|
+
registerReducer: PiRegisterReducerF,
|
|
136
|
+
overrideEvents?: { [key: string]: string },
|
|
137
|
+
): PiCardRef {
|
|
138
|
+
const mappings = cardMappings[name]
|
|
139
|
+
if (!mappings) {
|
|
140
|
+
// first time
|
|
141
|
+
if (!parameters.cardType) {
|
|
142
|
+
logger.warn("missing 'cardType'", name)
|
|
143
|
+
return name
|
|
144
|
+
}
|
|
145
|
+
const p: any = parameters
|
|
146
|
+
return _registerCard(name, p, registerReducer, overrideEvents)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const p = { ...mappings.parameters, ...parameters }
|
|
150
|
+
_createCardMapping(name, p, registerReducer, mappings.cardEvents)
|
|
151
|
+
return name
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function _createCardMapping(
|
|
156
|
+
name: string,
|
|
157
|
+
parameters: PiCardDef,
|
|
158
|
+
registerReducer: PiRegisterReducerF,
|
|
159
|
+
cardEvents: { [key: string]: string },
|
|
160
|
+
) {
|
|
161
|
+
const props = {} as { [k: string]: unknown }
|
|
162
|
+
const eventMappers = {} as { [k: string]: (ev: Action) => Action }
|
|
163
|
+
|
|
164
|
+
Object.entries(parameters).forEach(([k, v]) => {
|
|
165
|
+
if (k === "cardType") return
|
|
166
|
+
if (typeof v === "object") {
|
|
167
|
+
const cd = v as PiCardDef // speculative
|
|
168
|
+
if (cd.cardType) {
|
|
169
|
+
const cardName = `${name}/${k}`
|
|
170
|
+
v = _registerCard(cardName, cd, registerReducer)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (
|
|
174
|
+
k.startsWith("on") &&
|
|
175
|
+
processEventParameter(k, v, cardEvents, eventMappers, registerReducer, name)
|
|
176
|
+
) {
|
|
177
|
+
return
|
|
178
|
+
}
|
|
179
|
+
props[k] = v
|
|
180
|
+
})
|
|
181
|
+
cardMappings[name] = { cardType: parameters.cardType, props, eventMappers, cardEvents, parameters }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function _updateCardMapping(
|
|
185
|
+
name: string,
|
|
186
|
+
parameters: PiCardDef,
|
|
187
|
+
registerReducer: PiRegisterReducerF,
|
|
188
|
+
mappings: Mapping,
|
|
189
|
+
) {
|
|
190
|
+
return _createCardMapping(name, parameters, registerReducer, mappings.cardEvents)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function _registerMetadataCard(
|
|
194
|
+
metaName: string,
|
|
195
|
+
parameters: PiCardDef,
|
|
196
|
+
registerReducer: PiRegisterReducerF,
|
|
197
|
+
): boolean {
|
|
198
|
+
let mc = metacardTypes[parameters.cardType]
|
|
199
|
+
if (!mc) {
|
|
200
|
+
if (framework) {
|
|
201
|
+
mc = metacardTypes[`${framework}/${parameters.cardType}`]
|
|
202
|
+
}
|
|
203
|
+
if (!mc) {
|
|
204
|
+
return false
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function registerCard(name: string, parameters: PiCardDef): PiCardRef {
|
|
208
|
+
const n = `${metaName}/${name}`
|
|
209
|
+
return mc.registerCard(n, parameters)
|
|
210
|
+
}
|
|
211
|
+
const top = mc.mapper(metaName, parameters, registerCard)
|
|
212
|
+
_registerCard(metaName, top, registerReducer, mc.events)
|
|
213
|
+
return true
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// NOT IMPLEMENTED YET
|
|
217
|
+
// function _updateMetadataCard(
|
|
218
|
+
// metaName: string,
|
|
219
|
+
// parameters: PiCardDef,
|
|
220
|
+
// registerReducer: PiRegisterReducerF,
|
|
221
|
+
// ): boolean {
|
|
222
|
+
// let mc = metacardTypes[parameters.cardType]
|
|
223
|
+
// if (!mc) {
|
|
224
|
+
// if (framework) {
|
|
225
|
+
// mc = metacardTypes[`${framework}/${parameters.cardType}`]
|
|
226
|
+
// }
|
|
227
|
+
// if (!mc) {
|
|
228
|
+
// return false
|
|
229
|
+
// }
|
|
230
|
+
// }
|
|
231
|
+
// function updateCard(name: string, parameters: PiCardDef): PiCardRef {
|
|
232
|
+
// const n = `${metaName}/${name}`
|
|
233
|
+
// return mc.updateCard(n, parameters)
|
|
234
|
+
// }
|
|
235
|
+
// const top = mc.mapper(metaName, parameters, updateCard)
|
|
236
|
+
// _updateCard(metaName, top, registerReducer, mc.events)
|
|
237
|
+
// return true
|
|
238
|
+
// }
|
|
239
|
+
|
|
240
|
+
export function createCardDeclaration<Props = {}, Events = {}>(
|
|
241
|
+
cardType: string,
|
|
242
|
+
): <S extends ReduxState>(p: PiMapProps<Props, S, Events>) => PiCardDef {
|
|
243
|
+
return (p) => ({
|
|
244
|
+
...p,
|
|
245
|
+
cardType,
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function processEventParameter(
|
|
250
|
+
propName: string,
|
|
251
|
+
value: unknown,
|
|
252
|
+
events: { [key: string]: string },
|
|
253
|
+
eventMappers: { [k: string]: (ev: Action) => Action },
|
|
254
|
+
registerReducer: PiRegisterReducerF,
|
|
255
|
+
cardName: string,
|
|
256
|
+
): boolean {
|
|
257
|
+
const eva = Object.entries(events).find(([n, _]) => {
|
|
258
|
+
return propName === n || propName === `${n}Mapper`
|
|
259
|
+
})
|
|
260
|
+
if (!eva) {
|
|
261
|
+
logger.warn(
|
|
262
|
+
`encountered property '${propName}' for card '${cardName}' which looks like an even but is not defined`,
|
|
263
|
+
)
|
|
264
|
+
return false
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const [evName, actionType] = eva
|
|
268
|
+
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}`)
|
|
277
|
+
}
|
|
278
|
+
if (propName === `${evName}Mapper`) {
|
|
279
|
+
logger.debug("processEventParameter", cardName)
|
|
280
|
+
|
|
281
|
+
const m = value as (ev: Action) => Action
|
|
282
|
+
eventMappers[evName] = m
|
|
283
|
+
}
|
|
284
|
+
return true
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export function memo<P, T, S extends ReduxState, C>(
|
|
288
|
+
filterF: (state: S, context: StateMapperContext<C>) => P,
|
|
289
|
+
mapperF: (partial: P, context: StateMapperContext<C>, state: S) => T,
|
|
290
|
+
): (state: S, context: StateMapperContext<C>) => T {
|
|
291
|
+
const lastFilter: { [k: string]: P } = {}
|
|
292
|
+
const lastValue: { [k: string]: T } = {}
|
|
293
|
+
const isNotFirst: { [k: string]: boolean } = {}
|
|
294
|
+
|
|
295
|
+
return (state: S, context: StateMapperContext<C>): T => {
|
|
296
|
+
const k = context.cardKey || "-"
|
|
297
|
+
const fv = filterF(state, context)
|
|
298
|
+
if (isNotFirst[k] && equal(fv, lastFilter[k])) {
|
|
299
|
+
// nothing changed
|
|
300
|
+
return lastValue[k]
|
|
301
|
+
}
|
|
302
|
+
lastFilter[k] = fv
|
|
303
|
+
const v = mapperF(fv, context, state)
|
|
304
|
+
lastValue[k] = v
|
|
305
|
+
isNotFirst[k] = true
|
|
306
|
+
return v
|
|
307
|
+
}
|
|
308
|
+
}
|
package/src/rest/types.ts
CHANGED
package/src/root.tsx
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { Provider } from "react-redux"
|
|
3
|
+
|
|
4
|
+
import { Card } from "./card"
|
|
5
|
+
|
|
6
|
+
export function RootComponent(store: any) {
|
|
7
|
+
return (
|
|
8
|
+
<React.StrictMode>
|
|
9
|
+
<Provider store={store}>
|
|
10
|
+
<Card cardName="_window" parentCard="" />
|
|
11
|
+
</Provider>
|
|
12
|
+
</React.StrictMode>
|
|
13
|
+
)
|
|
14
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -31,13 +31,13 @@ export type ReduceF<S extends ReduxState, A extends ReduxAction> = (
|
|
|
31
31
|
state: S,
|
|
32
32
|
action: A,
|
|
33
33
|
dispatch: DispatchF,
|
|
34
|
-
) => S
|
|
34
|
+
) => void // S
|
|
35
35
|
|
|
36
36
|
export type ReduceOnceF<S extends ReduxState, A extends ReduxAction> = (
|
|
37
37
|
state: S,
|
|
38
38
|
action: A,
|
|
39
39
|
dispatch: DispatchF,
|
|
40
|
-
) => [S, boolean]
|
|
40
|
+
) => boolean // [S, boolean]
|
|
41
41
|
|
|
42
42
|
export type DispatchF = <T extends ReduxAction>(a: T) => void
|
|
43
43
|
|
|
@@ -52,7 +52,10 @@ export type PiRegisterReducerF = <S extends ReduxState, A extends ReduxAction>(
|
|
|
52
52
|
eventType: string,
|
|
53
53
|
mapper: ReduceF<S, A>, // (state: S, action: A, dispatch: DispatchF) => S,
|
|
54
54
|
priority?: number,
|
|
55
|
-
|
|
55
|
+
key?: string,
|
|
56
|
+
) => PiReducerCancelF
|
|
57
|
+
|
|
58
|
+
export type PiReducerCancelF = () => void
|
|
56
59
|
|
|
57
60
|
export type PiRegisterOneShotReducerF = <
|
|
58
61
|
S extends ReduxState,
|
|
@@ -76,6 +79,12 @@ export type CardProp = {
|
|
|
76
79
|
parentCard: string
|
|
77
80
|
} & PiDefCtxtProps
|
|
78
81
|
|
|
82
|
+
// props for the 'root' of all cards
|
|
83
|
+
export type WindowProps = {
|
|
84
|
+
page: PiCardRef
|
|
85
|
+
framework?: string // select framework to render window
|
|
86
|
+
theme?: any // depends on framework
|
|
87
|
+
}
|
|
79
88
|
|
|
80
89
|
// type which needs to be implemented by card components
|
|
81
90
|
export type PiCardProps<P, E = {}> = P & {
|
|
@@ -84,8 +93,8 @@ export type PiCardProps<P, E = {}> = P & {
|
|
|
84
93
|
_cls: (elName: string | string[], styles?: CSSModuleClasses) => string
|
|
85
94
|
_dispatch: DispatchF
|
|
86
95
|
} & {
|
|
87
|
-
|
|
88
|
-
|
|
96
|
+
[Key in keyof E]: (ev: E[Key]) => void
|
|
97
|
+
}
|
|
89
98
|
|
|
90
99
|
export type CSSModuleClasses = { readonly [key: string]: string }
|
|
91
100
|
|