@carbonorm/carbonreact 3.4.7 → 3.4.8

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;
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";
@@ -4191,16 +4187,19 @@ function isJsonString(str) {
4191
4187
  }
4192
4188
  const CarbonReact = class extends react.Component {
4193
4189
  static instance;
4190
+ static persistentState = undefined;
4194
4191
  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
4192
  // @link https://github.com/welldone-software/why-did-you-render
4199
4193
  // noinspection JSUnusedGlobalSymbols
4200
4194
  static whyDidYouRender = true;
4201
4195
  constructor(props) {
4202
4196
  super(props);
4203
- this.state = initialCarbonReactState;
4197
+ if (CarbonReact.persistentState !== undefined && this.props.shouldStatePersist !== false) {
4198
+ this.state = CarbonReact.persistentState;
4199
+ }
4200
+ else {
4201
+ this.state = initialCarbonReactState;
4202
+ }
4204
4203
  // This should only ever be done here, when the full state is being trashed.
4205
4204
  carbonnode.clearCache({
4206
4205
  ignoreWarning: true
@@ -4216,6 +4215,12 @@ const CarbonReact = class extends react.Component {
4216
4215
  return CarbonReact.instance.state;
4217
4216
  }
4218
4217
  shouldComponentUpdate(nextProps, nextState, _nextContext) {
4218
+ if (this.props.shouldStatePersist === false) {
4219
+ CarbonReact.persistentState = undefined;
4220
+ }
4221
+ else {
4222
+ CarbonReact.persistentState = nextState;
4223
+ }
4219
4224
  changed(this.constructor.name + ' (DigApi)', 'props', this.props, nextProps);
4220
4225
  changed(this.constructor.name + ' (DigApi)', 'state', this.state, nextState);
4221
4226
  return true;
@@ -4238,7 +4243,7 @@ const CarbonReact = class extends react.Component {
4238
4243
  if (this.state.backendThrowable.length > 0) {
4239
4244
  return jsxRuntime_2(jsxRuntime_3, { children: [nest, jsxRuntime_1(BackendThrowable, {})] });
4240
4245
  }
4241
- return jsxRuntime_2(reactRouterDom.BrowserRouter, { children: [jsxRuntime_1(GlobalHistory, {}), jsxRuntime_1(CarbonWebSocket, {}), this.props.children, jsxRuntime_1(reactToastify.ToastContainer, {})] });
4246
+ return jsxRuntime_2(jsxRuntime_3, { children: [jsxRuntime_1(GlobalHistory, {}), jsxRuntime_1(CarbonWebSocket, {}), this.props.children, jsxRuntime_1(reactToastify.ToastContainer, {})] });
4242
4247
  }
4243
4248
  };
4244
4249