@carbonorm/carbonreact 3.4.7 → 3.5.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
@@ -1,15 +1,232 @@
1
- # CarbonNode
2
- Initially this repository will host the node bindings for the Carbon API.
3
- The Carbon API is a Cross Language ORM Syntax for querying SQL databases.
4
- The Carbon Node is currently under development and is not yet ready for use.
1
+ ![npm](https://img.shields.io/npm/v/%40carbonorm%2Fcarbonreact)
2
+ ![License](https://img.shields.io/npm/l/%40carbonorm%2Fcarbonreact)
3
+ ![Size](https://img.shields.io/github/languages/code-size/carbonorm/carbonreact)
4
+ ![Documentation](https://img.shields.io/website?down_color=lightgrey&down_message=Offline&up_color=green&up_message=Online&url=https%3A%2F%2Fcarbonorm.dev)
5
+ ![Monthly Downloads](https://img.shields.io/npm/dm/%40carbonorm%2Fcarbonreact)
6
+ ![All Downloads](https://img.shields.io/npm/dt/%40carbonorm%2Fcarbonreact)
7
+ ![Star](https://img.shields.io/github/stars/carbonorm/carbonreact?style=social)
5
8
 
9
+ # CarbonReact
6
10
 
11
+ CarbonReact is a part of the CarbonORM series. It is a React MySQL ORM that is designed to generate all your boilerplate
12
+ code.
7
13
 
8
14
 
9
- ## Links
10
- https://saturncloud.io/blog/whats-the-difference-between-dependencies-devdependencies-and-peerdependencies-in-npm-packagejson-file/
15
+ ## Installation
11
16
 
12
- ## @notes
13
- https://fontawesome.com/v4/icons/
17
+ CarbonReact is available on [NPM](https://www.npmjs.com/). You'll need to have [NodeJS](https://nodejs.org/en/) installed
18
+ which comes prepackaged with npm (node package manager).
14
19
 
20
+ ```bash
21
+ npm install @carbonorm/carbonreact
22
+ ```
15
23
 
24
+ ## Generate Models
25
+
26
+ The command below will generate the models for the database. The models will be generated in the output directory. We do
27
+ recommend you keep this folder separate from other work. It is also best to track the output directory in your version
28
+ control system. All arguments are optional. If you do not provide them the defaults will be used. The example arguments
29
+ below are the defaults.
30
+
31
+ ```bash
32
+ npx generateRestBindings --user root --pass password --host 127.0.0.1 --port 3306 --dbname carbonPHP --prefix carbon_ --output /src/api/rest
33
+ ```
34
+
35
+ You can view the [code generated](https://github.com/CarbonORM/CarbonORM.dev/blob/www/src/api/rest/Users.tsx) by
36
+ [this command](https://github.com/CarbonORM/CarbonNode/blob/main/scripts/generateRestBindings.ts) in
37
+ [this repository](git@github.com:CarbonORM/CarbonNode.git). We use [Handlebars templates](https://mustache.github.io/)
38
+ to generate the code.
39
+
40
+ For more information on CarbonNode and the generations please see the [CarbonNode](https://github.com/CarbonORM/CarbonNode).
41
+
42
+
43
+ ## QuickStart Implementation
44
+
45
+ CarbonReact is designed to be the Bootstrap of your application. It is in charge of managing the state of your application.
46
+ ideally once it has mounted it never gets unmounted. In application where this is not possible, you can provide the
47
+ `shouldStatePersist` property to the CarbonReact React Component. This will allow you to persist the state of your
48
+ application even if the component is unmounted. The behavior of accessing or updating state while the component is
49
+ unknown (undefined) and should be avoided. The example below shows a simple implementation of CarbonReact. Our user
50
+ defined component is in `CarbonORM` which is written to extend the `CarbonReact` class. Your implementation must also
51
+ extend `CarbonORM`.
52
+
53
+
54
+ [index.tsx](https://github.com/CarbonORM/CarbonORM.dev/blob/www/src/index.tsx)
55
+
56
+ ```typescript jsx
57
+
58
+ import 'react-toastify/dist/ReactToastify.min.css'; // This is required for alerts to work and not break styling
59
+
60
+ const container = document.getElementById('root');
61
+
62
+ const root = createRoot(container!);
63
+
64
+ root.render(<React.StrictMode><CarbonORM /></React.StrictMode>);
65
+ ```
66
+
67
+ CarbonReact should be loaded as soon as the page loads. There are plans to allow other alerting systems to be used, but
68
+ for now we use [React Toastify](https://www.npmjs.com/package/react-toastify). It must be required in one of your files
69
+ and typically can be done the root of your project.
70
+
71
+
72
+ [CarbonORM.tsx](https://github.com/CarbonORM/CarbonORM.dev/blob/www/src/CarbonORM.tsx)
73
+
74
+ ```typescript jsx
75
+
76
+
77
+ export const initialCarbonORMState: typeof initialRestfulObjectsState
78
+ & typeof initialRequiredCarbonORMState
79
+ & iAuthenticate
80
+ & iVersions
81
+ & iUi
82
+ & {} = {
83
+ ...initialVersionsState,
84
+ ...initialRestfulObjectsState,
85
+ ...initialRequiredCarbonORMState,
86
+ ...initialAuthenticateState,
87
+ ...initialUiState,
88
+ }
89
+
90
+ export default class CarbonORM extends CarbonReact<{ browserRouter?: boolean }, typeof initialCarbonORMState> {
91
+
92
+ static instance: CarbonORM;
93
+
94
+ state = initialCarbonORMState;
95
+
96
+ constructor(props) {
97
+ super(props);
98
+ CarbonORM.instance = this;
99
+ CarbonReact.instance = this;
100
+ }
101
+
102
+ componentDidMount() {
103
+ Carbons.Get()
104
+ authenticateUser()
105
+ }
106
+
107
+ render() {
108
+ console.log("CarbonORM TSX RENDER");
109
+
110
+ const {isLoaded, backendThrowable} = this.state;
111
+
112
+
113
+ if (backendThrowable.length > 0) {
114
+
115
+ return <BackendThrowable />
116
+
117
+ }
118
+
119
+ const reactRouterContext = (children: any) => {
120
+
121
+ if (isTest) {
122
+
123
+ return <MemoryRouter initialEntries={['/']}>{children}</MemoryRouter>
124
+
125
+ }
126
+
127
+ return <HashRouter>{children}</HashRouter>
128
+
129
+ }
130
+
131
+ return reactRouterContext(<>
132
+ <CarbonWebSocket url={'ws://localhost:8888/ws'}/>
133
+ <Routes>
134
+ <Route path={UI + "*"}>
135
+ <Route path={MATERIAL_DASHBOARD + "*"} element={ppr(Dashboard, {})}>
136
+ <Route path={DASHBOARD + '*'} element={ppr(DashboardPage, {})}/>
137
+ <Route path={USER_PROFILE + '*'} element={ppr(UserProfile, {})}/>
138
+ <Route path={TABLES + '*'} element={ppr(TableList, {})}/>
139
+ <Route path={TYPOGRAPHY + '*'} element={ppr(Typography, {})}/>
140
+ <Route path={ICONS + '*'} element={ppr(Icons, {})}/>
141
+ <Route path={MAPS + '*'} element={ppr(Maps, {})}/>
142
+ <Route path={NOTIFICATIONS + '*'} element={ppr(Notifications, {})}/>
143
+ <Route path={UPGRADE_TO_PRO + '*'} element={ppr(UpgradeToPro, {})}/>
144
+ <Route path={'*'} element={<Navigate to={'/' + UI + MATERIAL_DASHBOARD + DASHBOARD}/>}/>
145
+ </Route>
146
+ <Route path={MATERIAL_KIT + "*"} element={ppr(MaterialKit, {})}>
147
+ <Route path={SECTION_NAVBARS + '*'} element={ppr(SectionNavbars, {})}/>
148
+ <Route path={SECTION_BASICS + '*'} element={ppr(SectionBasics, {})}/>
149
+ <Route path={SECTION_TABS + '*'} element={ppr(SectionTabs, {})}/>
150
+ <Route path={SECTION_PILLS + '*'} element={ppr(SectionPills, {})}/>
151
+ <Route path={SECTION_NOTIFICATIONS + '*'} element={ppr(SectionNotifications, {})}/>
152
+ <Route path={SECTION_TYPOGRAPHY + '*'} element={ppr(SectionTypography, {})}/>
153
+ <Route path={SECTION_JAVASCRIPT + '*'} element={ppr(SectionJavascript, {})}/>
154
+ <Route path={SECTION_COMPLETED_EXAMPLES + '*'} element={ppr(SectionCompletedExamples, {})}/>
155
+ <Route path={SECTION_LOGIN + '*'} element={ppr(SectionLogin, {})}/>
156
+ <Route path={LANDING_PAGE + '*'} element={ppr(LandingPage, {})}/>
157
+ <Route path={SECTION_DOWNLOAD + '*'} element={ppr(SectionDownload, {})}/>
158
+ <Route path={'*'} element={<Navigate to={'/' + UI + MATERIAL_KIT + SECTION_NAVBARS}/>}/>
159
+ </Route>
160
+ <Route path={'*'} element={<Navigate to={'/' + UI + MATERIAL_DASHBOARD}/>}/>
161
+ </Route>
162
+ <Route path={DOCUMENTATION + '*'} element={ppr(Documentation, {})}>
163
+ <Route path={CARBON_ORM_INTRODUCTION + '*'} element={ppr(CarbonORMIntroduction, {})}/>
164
+ <Route path={SUPPORT + '*'} element={ppr(Support, {})}/>
165
+ <Route path={CARBONPHP + '*'} element={ppr(CarbonPHP, {})}/>
166
+ <Route path={DEPENDENCIES + '*'} element={ppr(Dependencies, {})}/>
167
+ <Route path={CHANGELOG + "*"} element={ppr(Changelog, {})}/>
168
+ <Route path={IMPLEMENTATIONS + "*"} element={ppr(Implementations, {})}/>
169
+ <Route path={LICENSE + "*"} element={ppr(License, {})}/>
170
+ <Route path={'*'} element={<Navigate to={'/' + DOCUMENTATION + CARBON_ORM_INTRODUCTION}/>}/>
171
+ </Route>
172
+ <Route path="/landing-page" element={ppr(LandingPage, {})}/>
173
+ <Route path={'*'} element={<Navigate to={'/documentation'}/>}/>
174
+ </Routes>
175
+ <ToastContainer
176
+ autoClose={3000}
177
+ draggable={false}
178
+ position="top-right"
179
+ hideProgressBar={false}
180
+ newestOnTop
181
+ closeOnClick
182
+ rtl={false}
183
+ pauseOnHover
184
+ />
185
+ </>)
186
+
187
+ }
188
+ }
189
+ ```
190
+
191
+
192
+ Our testing tool [Jest](https://www.npmjs.com/package/jest) requires [React Router Dom](https://www.npmjs.com/package/react-router-dom)
193
+ to be in `MemoryRouter` mode. This is because Jest does not have a DOM and therefore cannot render the `HashRouter` or
194
+ `BrowserRouter` component. CarbonReact does not require `React Router Dom` to be installed. You can use any router you
195
+ like. The example above uses `HashRouter` which is [necessary as this website](https://stackoverflow.com/questions/71984401/react-router-not-working-with-github-pages)
196
+ hosted for free using [GitHub Pages](https://pages.github.com/).
197
+
198
+ A folder named [state](https://github.com/CarbonORM/CarbonORM.dev/tree/www/src/state) in the root of your project
199
+ `src/state/` should contain all your state files. These files should be written with the intention of being imported
200
+ into your CarbonReact extended component. The example below shows a simple state file that is implemented above. Helper
201
+ functions are also included in the state files. These functions are designed to be used in your React Components. React
202
+ stateful operations must be wrapped in a function and thus must not be run during the initial page load.
203
+
204
+ Updating state is as simple as calling `CarbonORM.instance.setState({})`. The class name `CarbonORM` can be replaced with
205
+ any name of your liking. Typically, you will want to use the name of your project.
206
+
207
+ [ui.tsx](https://github.com/CarbonORM/CarbonORM.dev/blob/www/src/state/ui.tsx)
208
+ ```typescript jsx
209
+ import CarbonORM from "CarbonORM";
210
+
211
+
212
+ export interface iUi {
213
+ pureWordpressPluginConfigured?: boolean,
214
+ documentationVersionURI: string,
215
+ isLoaded: boolean,
216
+ darkMode: boolean,
217
+ }
218
+
219
+ export const initialUiState: iUi = {
220
+ pureWordpressPluginConfigured: false,
221
+ documentationVersionURI: '0.0.0',
222
+ isLoaded: false,
223
+ darkMode: true,
224
+ }
225
+
226
+
227
+ export const switchDarkAndLightTheme = () => {
228
+ CarbonORM.instance.setState({
229
+ darkMode: !CarbonORM.instance.state.darkMode
230
+ });
231
+ };
232
+ ```
@@ -19,10 +19,12 @@ declare const CarbonReact: {
19
19
  context: unknown;
20
20
  setState<K extends keyof iCarbonReactState | keyof S>(state: (S & iCarbonReactState) | ((prevState: Readonly<S & iCarbonReactState>, props: Readonly<{
21
21
  children?: ReactNode | ReactNode[];
22
+ shouldStatePersist?: boolean | undefined;
22
23
  } & P>) => (S & iCarbonReactState) | Pick<S & iCarbonReactState, K> | null) | Pick<S & iCarbonReactState, K> | null, callback?: (() => void) | undefined): void;
23
24
  forceUpdate(callback?: (() => void) | undefined): void;
24
25
  readonly props: Readonly<{
25
26
  children?: ReactNode | ReactNode[];
27
+ shouldStatePersist?: boolean | undefined;
26
28
  } & P>;
27
29
  state: Readonly<S & iCarbonReactState>;
28
30
  refs: {
@@ -33,29 +35,32 @@ declare const CarbonReact: {
33
35
  componentDidCatch?(error: Error, errorInfo: import("react").ErrorInfo): void;
34
36
  getSnapshotBeforeUpdate?(prevProps: Readonly<{
35
37
  children?: ReactNode | ReactNode[];
38
+ shouldStatePersist?: boolean | undefined;
36
39
  } & P>, prevState: Readonly<S & iCarbonReactState>): any;
37
40
  componentWillMount?(): void;
38
41
  UNSAFE_componentWillMount?(): void;
39
42
  componentWillReceiveProps?(nextProps: Readonly<{
40
43
  children?: ReactNode | ReactNode[];
44
+ shouldStatePersist?: boolean | undefined;
41
45
  } & P>, nextContext: any): void;
42
46
  UNSAFE_componentWillReceiveProps?(nextProps: Readonly<{
43
47
  children?: ReactNode | ReactNode[];
48
+ shouldStatePersist?: boolean | undefined;
44
49
  } & P>, nextContext: any): void;
45
50
  componentWillUpdate?(nextProps: Readonly<{
46
51
  children?: ReactNode | ReactNode[];
52
+ shouldStatePersist?: boolean | undefined;
47
53
  } & P>, nextState: Readonly<S & iCarbonReactState>, nextContext: any): void;
48
54
  UNSAFE_componentWillUpdate?(nextProps: Readonly<{
49
55
  children?: ReactNode | ReactNode[];
56
+ shouldStatePersist?: boolean | undefined;
50
57
  } & P>, nextState: Readonly<S & iCarbonReactState>, nextContext: any): void;
51
58
  };
52
59
  instance: Component<{
53
60
  children?: ReactNode | ReactNode[];
54
61
  } & any, any & iCarbonReactState>;
62
+ persistentState?: iCarbonReactState | undefined;
55
63
  lastLocation: string;
56
- websocketUrl: string;
57
- websocketTimeoutSeconds: number;
58
- websocketHeartbeatSeconds: number;
59
64
  whyDidYouRender: boolean;
60
65
  getState<S_1>(): S_1;
61
66
  contextType?: import("react").Context<any> | undefined;
@@ -1,13 +1,14 @@
1
- import { tC6Tables } from "@carbonorm/carbonnode";
1
+ import { tC6Tables, tWsLiveUpdate } from "@carbonorm/carbonnode";
2
2
  export interface iCarbonWebSocketProps {
3
3
  url?: string;
4
4
  timeoutSeconds?: number;
5
5
  heartbeatSeconds?: number;
6
6
  TABLES?: tC6Tables;
7
+ WsLiveUpdates?: tWsLiveUpdate;
7
8
  }
8
9
  /**
9
10
  * @function connect
10
11
  * This function establishes a connection with the websocket and also ensures constant reconnection if connection closes
11
12
  **/
12
- export declare function initiateWebsocket({ TABLES, url, timeoutSeconds, heartbeatSeconds }?: iCarbonWebSocketProps): void;
13
+ export declare function initiateWebsocket({ TABLES, WsLiveUpdates, url, timeoutSeconds, heartbeatSeconds }?: iCarbonWebSocketProps): void;
13
14
  export default function (props: iCarbonWebSocketProps): null;
package/dist/index.cjs.js CHANGED
@@ -3898,12 +3898,8 @@ function getStyles(overrides = {}) {
3898
3898
 
3899
3899
  // @link https://stackoverflow.com/questions/58399637/include-modal-functionality-in-react-higher-order-component
3900
3900
  function Popup({ open = true, handleClose, children, maxWidth, }) {
3901
- if (false === open) {
3902
- // @link https://legacy.reactjs.org/docs/conditional-rendering.html#preventing-component-from-rendering
3903
- return jsxRuntime_1(jsxRuntime_3, {});
3904
- }
3905
3901
  const dig = getStyles();
3906
- return jsxRuntime_1("div", { className: classNames(dig.modal, dig.fade, dig.show, dig.dBlock), style: { backgroundColor: "rgba(0,0,0,0.8)" }, id: "exampleModalCenter", tabIndex: -1, "aria-labelledby": "exampleModalCenterTitle", "aria-modal": "true", role: "dialog", children: jsxRuntime_1("div", { style: { maxWidth: maxWidth }, className: classNames(dig.modalDialog, dig.modalDialogCentered), children: jsxRuntime_1(OutsideClickHandler, { onOutsideClick: () => handleClose(), children: jsxRuntime_1("div", { className: classNames(dig.modalContent, dig.bgTransparent, dig.modalDialogScrollable), children: children }) }) }) });
3902
+ return jsxRuntime_1("div", { className: classNames(dig.modal, dig.fade, { [dig.show]: open }, dig.dBlock), style: { backgroundColor: "rgba(0,0,0,0.8)" }, id: "exampleModalCenter", tabIndex: -1, "aria-labelledby": "exampleModalCenterTitle", "aria-modal": "true", role: "dialog", children: jsxRuntime_1("div", { style: { maxWidth: maxWidth }, className: classNames(dig.modalDialog, dig.modalDialogCentered), children: jsxRuntime_1(OutsideClickHandler, { onOutsideClick: () => handleClose(), children: jsxRuntime_1("div", { className: classNames(dig.modalContent, dig.bgTransparent, dig.modalDialogScrollable), children: children }) }) }) });
3907
3903
  }
3908
3904
 
3909
3905
  const isProduction = window.location.host.split(".")[0] === "www";
@@ -4049,7 +4045,7 @@ const useEffectOnce = (effect) => {
4049
4045
  * @function connect
4050
4046
  * This function establishes a connection with the websocket and also ensures constant reconnection if connection closes
4051
4047
  **/
4052
- function initiateWebsocket({ TABLES = undefined, url = 'ws://localhost:8080/ws', timeoutSeconds = 250, heartbeatSeconds = 60 } = {}) {
4048
+ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url = 'ws://localhost:8080/ws', timeoutSeconds = 250, heartbeatSeconds = 60 } = {}) {
4053
4049
  const { websocket } = CarbonReact.instance.state;
4054
4050
  if (!("WebSocket" in window)) {
4055
4051
  // todo - store that this has been shown in the state
@@ -4084,17 +4080,59 @@ function initiateWebsocket({ TABLES = undefined, url = 'ws://localhost:8080/ws',
4084
4080
  };
4085
4081
  connection.onmessage = (message) => {
4086
4082
  const parsedData = isJsonString(message?.data) ? JSON.parse(message?.data) : message?.data;
4083
+ if (message.data === 'pong') {
4084
+ return;
4085
+ }
4087
4086
  CarbonReact.instance.setState((prevState) => ({
4088
4087
  websocketEvents: prevState.websocketEvents.concat(message),
4089
4088
  websocketData: prevState.websocketData.concat(parsedData), // JSON.parse no good - base64?
4090
- }));
4091
- console.info('todo - going to impl TABLES', TABLES);
4092
- /*if (undefined !== TABLES) {
4093
-
4094
- TABLES.
4095
-
4096
-
4097
- }*/
4089
+ }), () => {
4090
+ if (undefined === TABLES) {
4091
+ console.log('WebSocket updates without the TABLES property passed will not automatically update the state.');
4092
+ return;
4093
+ }
4094
+ if (undefined === WsLiveUpdates) {
4095
+ console.log('WebSocket updates without the WsLiveUpdates property passed will not automatically update the state.');
4096
+ return;
4097
+ }
4098
+ if (parsedData?.REST) {
4099
+ const TABLE_NAME = parsedData?.REST?.TABLE_NAME;
4100
+ const TABLE_PREFIX = parsedData?.REST?.TABLE_PREFIX;
4101
+ const METHOD = parsedData?.REST?.METHOD;
4102
+ const REQUEST = parsedData?.REST?.REQUEST;
4103
+ const REQUEST_PRIMARY_KEY = parsedData?.REST?.REQUEST_PRIMARY_KEY ?? null;
4104
+ if (null === REQUEST_PRIMARY_KEY) {
4105
+ console.log('WebSocket updates without a primary key are not yet supported.');
4106
+ return;
4107
+ }
4108
+ console.log('todo - going to impl REST', TABLE_NAME, METHOD, REQUEST_PRIMARY_KEY, parsedData?.REST);
4109
+ const TABLE_NAME_SHORT = TABLE_NAME.substring(TABLE_PREFIX.length);
4110
+ const currentCache = CarbonReact.instance.state[TABLE_NAME_SHORT];
4111
+ // just because we have a websocket update, doesn't mean we need the update
4112
+ // check to see if the primary key is in the current cache
4113
+ const c6Table = TABLES[TABLE_NAME_SHORT] ?? null;
4114
+ if (null === c6Table) {
4115
+ console.error('WebSocket update could not find (' + TABLE_NAME_SHORT + ') in the TABLES property passed.', TABLES);
4116
+ return;
4117
+ }
4118
+ const primaryKeyKeys = Object.keys(REQUEST_PRIMARY_KEY);
4119
+ const elementsToUpdate = currentCache.filter((row) => {
4120
+ for (const element of primaryKeyKeys) {
4121
+ if (REQUEST_PRIMARY_KEY[element] !== row[element]) {
4122
+ return false;
4123
+ }
4124
+ }
4125
+ return true;
4126
+ });
4127
+ const updatedElements = elementsToUpdate.map((row) => {
4128
+ return {
4129
+ ...row,
4130
+ ...REQUEST
4131
+ };
4132
+ });
4133
+ WsLiveUpdates[TABLE_NAME_SHORT][METHOD]({}, updatedElements);
4134
+ }
4135
+ });
4098
4136
  };
4099
4137
  window.addEventListener("focus", () => initiateWebsocket());
4100
4138
  // websocket onclose event listener
@@ -4191,16 +4229,19 @@ function isJsonString(str) {
4191
4229
  }
4192
4230
  const CarbonReact = class extends react.Component {
4193
4231
  static instance;
4232
+ static persistentState = undefined;
4194
4233
  static lastLocation = window.location.pathname;
4195
- static websocketUrl = (window.location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host + ':8888/ws';
4196
- static websocketTimeoutSeconds = 250;
4197
- static websocketHeartbeatSeconds = 250;
4198
4234
  // @link https://github.com/welldone-software/why-did-you-render
4199
4235
  // noinspection JSUnusedGlobalSymbols
4200
4236
  static whyDidYouRender = true;
4201
4237
  constructor(props) {
4202
4238
  super(props);
4203
- this.state = initialCarbonReactState;
4239
+ if (CarbonReact.persistentState !== undefined && this.props.shouldStatePersist !== false) {
4240
+ this.state = CarbonReact.persistentState;
4241
+ }
4242
+ else {
4243
+ this.state = initialCarbonReactState;
4244
+ }
4204
4245
  // This should only ever be done here, when the full state is being trashed.
4205
4246
  carbonnode.clearCache({
4206
4247
  ignoreWarning: true
@@ -4216,6 +4257,12 @@ const CarbonReact = class extends react.Component {
4216
4257
  return CarbonReact.instance.state;
4217
4258
  }
4218
4259
  shouldComponentUpdate(nextProps, nextState, _nextContext) {
4260
+ if (this.props.shouldStatePersist === false) {
4261
+ CarbonReact.persistentState = undefined;
4262
+ }
4263
+ else {
4264
+ CarbonReact.persistentState = nextState;
4265
+ }
4219
4266
  changed(this.constructor.name + ' (DigApi)', 'props', this.props, nextProps);
4220
4267
  changed(this.constructor.name + ' (DigApi)', 'state', this.state, nextState);
4221
4268
  return true;
@@ -4238,7 +4285,7 @@ const CarbonReact = class extends react.Component {
4238
4285
  if (this.state.backendThrowable.length > 0) {
4239
4286
  return jsxRuntime_2(jsxRuntime_3, { children: [nest, jsxRuntime_1(BackendThrowable, {})] });
4240
4287
  }
4241
- return jsxRuntime_2(reactRouterDom.BrowserRouter, { children: [jsxRuntime_1(GlobalHistory, {}), jsxRuntime_1(CarbonWebSocket, {}), this.props.children, jsxRuntime_1(reactToastify.ToastContainer, {})] });
4288
+ return jsxRuntime_2(jsxRuntime_3, { children: [jsxRuntime_1(GlobalHistory, {}), jsxRuntime_1(CarbonWebSocket, {}), this.props.children, jsxRuntime_1(reactToastify.ToastContainer, {})] });
4242
4289
  }
4243
4290
  };
4244
4291