1 | import deepEqual from '@rahazad/deep-equal';
|
2 | import { graphReducer } from '@rahazad/graph-reducer';
|
3 | import React, { useReducer, useEffect, useContext } from 'react';
|
4 |
|
5 | var defaultLogger = function defaultLogger(state, action, newState) {
|
6 | var _newState;
|
7 |
|
8 | if (newState === void 0) {
|
9 | newState = null;
|
10 | }
|
11 |
|
12 | console.group('%c%s %c%s %c%s %s', 'font-weight:normal;color:#888', 'action', 'color:#222', action.type, 'font-weight:normal;color:#888', '@', new Date().toLocaleTimeString());
|
13 | console.log('%c%s\t%o', 'font-weight:bold;color:#9E9E9E', 'prev-state', state);
|
14 | console.log('%c%s\t', 'font-weight:bold;color:#03A9E4', 'action', action);
|
15 | console.log('%c%s\t%o', 'font-weight:bold;color:#4CAF50', 'new-state', newState === state ? 'PREV-STATE' : (_newState = newState) != null ? _newState : 'NO-TRANSFORM');
|
16 | console.groupEnd();
|
17 | };
|
18 |
|
19 | var stateManager = {};
|
20 | var StoreProvider = React.memo(function (_ref) {
|
21 | var children = _ref.children;
|
22 | var rootReducer = stateManager.rootReducer,
|
23 | defaultInitialState = stateManager.defaultInitialState,
|
24 | initializer = stateManager.initializer,
|
25 | payloadCreators = stateManager.payloadCreators,
|
26 | AppContext = stateManager.AppContext;
|
27 |
|
28 | var _useReducer = useReducer(rootReducer, defaultInitialState, initializer),
|
29 | state = _useReducer[0],
|
30 | dispatch = _useReducer[1];
|
31 |
|
32 | var popStateListener = function popStateListener(_ref2) {
|
33 | var state = _ref2.state;
|
34 | return dispatch({
|
35 | type: 'POP-',
|
36 | state: state
|
37 | });
|
38 | };
|
39 |
|
40 | useEffect(function () {
|
41 | window.addEventListener('popstate', popStateListener);
|
42 | return function () {
|
43 | return window.removeEventListener('popstate', popStateListener);
|
44 | };
|
45 | }, []);
|
46 | var dp = Object.fromEntries(Object.entries(payloadCreators).map(function (_ref3) {
|
47 | var type = _ref3[0],
|
48 | payloadCreator = _ref3[1];
|
49 | return [type, function () {
|
50 | return dispatch({
|
51 | type: type,
|
52 | payload: payloadCreator.apply(void 0, arguments)
|
53 | });
|
54 | }];
|
55 | }));
|
56 | return React.createElement(AppContext.Provider, {
|
57 | value: {
|
58 | state: state,
|
59 | dp: dp,
|
60 | dispatch: dispatch
|
61 | }
|
62 | }, children);
|
63 | });
|
64 |
|
65 | var useStore = function useStore() {
|
66 | return useContext(stateManager.AppContext);
|
67 | };
|
68 |
|
69 | var roudexInitializer = function roudexInitializer(initialState, payloadCreators, createPayloadFromUrl, createPathFromState, _temp) {
|
70 | var _ref4 = _temp === void 0 ? {} : _temp,
|
71 | _ref4$logger = _ref4.logger,
|
72 | logger = _ref4$logger === void 0 ? process.env.NODE_ENV === 'production' ? null : defaultLogger : _ref4$logger;
|
73 |
|
74 | if ('_serial' in initialState) throw new Error('The `_serial` property in `initialState` is managed automatically.\n' + ("You shouldn't provide it.\ninitialState:\n" + initialState));
|
75 | stateManager.defaultInitialState = initialState;
|
76 | initialState._serial = 0;
|
77 | stateManager.AppContext = React.createContext({
|
78 | state: {},
|
79 | dp: {},
|
80 | dispatch: null
|
81 | });
|
82 | stateManager.payloadCreators = payloadCreators;
|
83 |
|
84 | stateManager.rootReducer = function (state, action) {
|
85 | if (action.state) {
|
86 | if (action.payload) console.warn('The action provides both `payload` and `state`!\n' + 'Provided `payload` will be ignored.\naction:\n', action);
|
87 | var _newState = action.state;
|
88 | action.type += _newState._serial > state._serial ? 'FWD' : 'BACK';
|
89 | logger === null || logger === void 0 ? void 0 : logger(state, action, _newState);
|
90 | return _newState;
|
91 | }
|
92 |
|
93 | if (action.url) {
|
94 | if (action.payload) console.warn('The action provides both `payload` and `url`!\n' + 'Provided `payload` will be ignored and overridden.\naction:\n', action);
|
95 | action.payload = createPayloadFromUrl(action.url);
|
96 | }
|
97 |
|
98 | var payload = action.payload;
|
99 |
|
100 | if (!payload) {
|
101 | console.warn('No payload detected (directly or indirectly)!', {
|
102 | action: action
|
103 | });
|
104 | return state;
|
105 | }
|
106 |
|
107 | var _graphReducer = graphReducer(state, payload),
|
108 | noTransform = _graphReducer.noTransform,
|
109 | newState = _graphReducer.newState;
|
110 |
|
111 | var url0 = window.location.href;
|
112 | var newUrl = new URL(url0).origin + createPathFromState(newState);
|
113 |
|
114 | if (noTransform) {
|
115 | if (newUrl === url0 && deepEqual(window.history.state, state)) logger === null || logger === void 0 ? void 0 : logger(state, action);else {
|
116 | logger === null || logger === void 0 ? void 0 : logger(state, action, state);
|
117 | window.history.replaceState(state, '', newUrl);
|
118 | }
|
119 | return state;
|
120 | }
|
121 |
|
122 | newState._serial++;
|
123 | logger === null || logger === void 0 ? void 0 : logger(state, action, newState);
|
124 | var replaceOrPushState = action.url || newUrl === url0 ? 'replaceState' : 'pushState';
|
125 | window.history[replaceOrPushState](newState, '', newUrl);
|
126 | return newState;
|
127 | };
|
128 |
|
129 | stateManager.initializer = function (defaultInitialState) {
|
130 | var _window$history$state;
|
131 |
|
132 | return stateManager.rootReducer((_window$history$state = window.history.state) != null ? _window$history$state : defaultInitialState, {
|
133 | type: 'INIT',
|
134 | url: window.location.href
|
135 | });
|
136 | };
|
137 |
|
138 | var rootReducer = stateManager.rootReducer,
|
139 | defaultInitialState = stateManager.defaultInitialState;
|
140 | return {
|
141 | StoreProvider: StoreProvider,
|
142 | useStore: useStore,
|
143 | rootReducer: rootReducer,
|
144 | defaultInitialState: defaultInitialState
|
145 | };
|
146 | };
|
147 |
|
148 | export { roudexInitializer };
|
149 |
|