swoop-common 1.0.8 → 1.0.9

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,10 +1 @@
1
- import React from 'react';
2
- import { Address } from '../types/address';
3
- import { CustomType } from '../router/router';
4
- interface Props {
5
- address: Address;
6
- submit: (address: Address) => void;
7
- }
8
- export declare const FormAddress: React.FC<Props>;
9
- export declare const TypeAddress: CustomType;
10
1
  export {};
@@ -1,41 +1,47 @@
1
- import React from 'react';
1
+ import React, { useMemo, useState } from 'react';
2
2
  import { getXType } from '../util/type';
3
- import { Box, TextField } from '@mui/material';
3
+ import { Box, debounce, MenuItem, Paper, TextField, Typography } from '@mui/material';
4
+ import { registerComponent, registerExport } from '../router/router';
5
+ import { FormMode } from '../router/types';
6
+ import { useLocalErrors } from '../hooks/errors';
4
7
  const tester = (uischema, schema, ctx) => {
5
- const type = getXType(schema);
6
- if (!type)
7
- return -1;
8
- else
8
+ if (getXType(schema) === "address")
9
9
  return 10;
10
+ return -1;
10
11
  };
11
- export const FormAddress = ({ address, submit }) => {
12
- console.log("THIS IS ADDRESS", address);
13
- const fallback = {
14
- line1: '',
15
- line2: '',
16
- city: '',
17
- county: '',
18
- postcode: '',
19
- number: 0,
20
- };
21
- const safeAddress = Object.assign(Object.assign({}, fallback), (address !== null && address !== void 0 ? address : {}));
22
- // Typescript is great
12
+ const FormAddress = ({ address, submit, getError }) => {
13
+ var _a, _b, _c, _d, _e;
14
+ if (!getError)
15
+ getError = () => undefined;
16
+ const [val, setVal] = useState(address);
17
+ // Errors, stored to reduce num of calls for performance
18
+ const line1Error = (_a = getError("line1")) === null || _a === void 0 ? void 0 : _a.message;
19
+ const line2Error = (_b = getError("line2")) === null || _b === void 0 ? void 0 : _b.message;
20
+ const cityError = (_c = getError("city")) === null || _c === void 0 ? void 0 : _c.message;
21
+ const postcodeError = (_d = getError("postcode")) === null || _d === void 0 ? void 0 : _d.message;
22
+ const numberError = (_e = getError("number")) === null || _e === void 0 ? void 0 : _e.message;
23
+ const submitDebounced = useMemo(() => debounce(submit, 300), [submit]);
23
24
  const update = (field, value) => {
24
- submit(Object.assign(Object.assign({}, address), { [field]: value }));
25
+ const newVal = Object.assign(Object.assign({}, val), { [field]: value });
26
+ setVal(newVal);
27
+ submitDebounced(newVal);
25
28
  };
26
- return (React.createElement(Box, { component: "form", sx: { display: 'flex', flexDirection: 'column', gap: 2, width: 400 }, noValidate: true, autoComplete: "off" },
27
- React.createElement(TextField, { label: "Line 1", value: safeAddress.line1, onChange: (e) => update('line1', e.target.value), required: true }),
28
- React.createElement(TextField, { label: "Line 2", value: safeAddress.line2, onChange: (e) => update('line2', e.target.value) }),
29
- React.createElement(TextField, { label: "City", value: safeAddress.city, onChange: (e) => update('city', e.target.value), required: true }),
30
- React.createElement(TextField, { label: "Postcode", value: safeAddress.postcode, onChange: (e) => update('postcode', e.target.value), required: true }),
31
- React.createElement(TextField, { label: "Number", value: safeAddress.postcode, onChange: (e) => update('number', +e.target.value), required: true })));
29
+ return (React.createElement(Paper, { component: "form", sx: { display: 'flex', flexDirection: 'column', gap: 1, p: 2 }, noValidate: true, autoComplete: "off" },
30
+ React.createElement(Typography, { variant: 'h5' }, "Custom Address"),
31
+ React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 } },
32
+ React.createElement(TextField, { label: "Line 1", value: val.line1, onChange: (e) => update('line1', e.target.value), required: true, error: !!line1Error, helperText: line1Error }),
33
+ React.createElement(TextField, { label: "Line 2", value: val.line2, onChange: (e) => update('line2', e.target.value), error: !!line2Error, helperText: line2Error })),
34
+ React.createElement(TextField, { select: true, label: "City", value: val.city, onChange: (e) => update('city', e.target.value), required: true, fullWidth: true, error: !!cityError, helperText: cityError },
35
+ React.createElement(MenuItem, { value: "London" }, "London"),
36
+ React.createElement(MenuItem, { value: "Newcastle" }, "Newcastle"),
37
+ React.createElement(MenuItem, { value: "Bristol" }, "Bristol")),
38
+ React.createElement(Box, { sx: { display: 'flex', gap: 2 } },
39
+ React.createElement(TextField, { label: "Postcode", value: val.postcode, onChange: (e) => update('postcode', e.target.value), required: true, error: !!postcodeError, helperText: postcodeError, fullWidth: true }),
40
+ React.createElement(TextField, { label: "Number", type: "number", value: val.number, onChange: (e) => update('number', +e.target.value), required: true, error: !!numberError, helperText: numberError, fullWidth: true }))));
32
41
  };
33
42
  const FormRendererAddress = ({ data, handleChange, path }) => {
34
- console.log("DATA", data);
35
- data = {};
36
- return React.createElement(FormAddress, { address: data, submit: (addr) => handleChange(path, addr) });
37
- };
38
- export const TypeAddress = {
39
- renderer: FormRendererAddress,
40
- tester
43
+ const getError = useLocalErrors(path);
44
+ return React.createElement(FormAddress, { address: data, submit: (addr) => handleChange(path, addr), getError: getError });
41
45
  };
46
+ registerExport(FormAddress);
47
+ registerComponent(tester, FormRendererAddress, [FormMode.FORM]);
@@ -0,0 +1 @@
1
+ export declare const useLocalErrors: (path: string) => (field: string) => import("ajv").ErrorObject<string, Record<string, any>, unknown> | undefined;
@@ -0,0 +1,11 @@
1
+ import { useJsonForms } from "@jsonforms/react";
2
+ import React from "react";
3
+ export const useLocalErrors = (path) => {
4
+ const { core } = useJsonForms();
5
+ // Filters out errors for the current scope
6
+ const local = React.useMemo(() => {
7
+ var _a;
8
+ return ((_a = core === null || core === void 0 ? void 0 : core.errors) === null || _a === void 0 ? void 0 : _a.filter(e => e.instancePath.startsWith("/" + path.replace(/\./g, "/") + "/"))) || [];
9
+ }, [core === null || core === void 0 ? void 0 : core.errors, path]);
10
+ return React.useCallback((field) => local.find(e => e.instancePath.endsWith("/" + field)), [local]);
11
+ };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./test";
2
2
  export * from "./render/StyledFormView";
3
+ export * from "./router/types";
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./test";
2
2
  export * from "./render/StyledFormView";
3
+ export * from "./router/types";
@@ -1,9 +1,25 @@
1
1
  import { JsonSchema, UISchemaElement } from '@jsonforms/core';
2
2
  import React from 'react';
3
+ import { FormMode } from '../router/types';
4
+ import "../components/Address";
3
5
  interface Props {
4
- data: any;
6
+ /**
7
+ * This should only be used for the initial values, as this is not truly a controlled component.
8
+ * Frequent updates of this can cause significant perfomance dips.
9
+ */
10
+ initialData: any;
5
11
  schema: JsonSchema;
6
12
  uischema: UISchemaElement;
13
+ /**
14
+ * This should not be fed back into the form.
15
+ * Instead store it as a ref.
16
+ */
17
+ onChange?: (value: any) => void;
18
+ /**
19
+ * Dictates which mode the form will display in.
20
+ * Each mode has a different pool of renderers.
21
+ */
22
+ mode: FormMode;
7
23
  }
8
- declare const StyledFormView: React.FC<Props>;
9
- export default StyledFormView;
24
+ export declare const StyledFormView: React.FC<Props>;
25
+ export {};
@@ -1,7 +1,8 @@
1
1
  import { JsonForms } from '@jsonforms/react';
2
2
  import React from 'react';
3
- import { FormTypes } from '../router/router';
4
- const StyledFormView = ({ data, schema, uischema }) => {
5
- return (React.createElement(JsonForms, { data: data, schema: schema, uischema: uischema, renderers: FormTypes }));
3
+ import { materialRenderers } from '@jsonforms/material-renderers';
4
+ import { getComponents } from '../router/router';
5
+ import "../components/Address";
6
+ export const StyledFormView = ({ initialData, schema, uischema, onChange, mode }) => {
7
+ return (React.createElement(JsonForms, { onChange: onChange, data: initialData, schema: schema, uischema: uischema, renderers: [...materialRenderers, ...getComponents(mode)] }));
6
8
  };
7
- export default StyledFormView;
@@ -1,6 +1,10 @@
1
- import { ControlProps, RankedTester } from "@jsonforms/core";
1
+ import { ControlProps, OwnPropsOfControl, RankedTester } from "@jsonforms/core";
2
+ import { ComponentType } from "react";
3
+ import { FormMode } from "./types";
2
4
  export interface CustomType {
3
5
  tester: RankedTester;
4
- renderer: React.FC<ControlProps>;
6
+ renderer: ComponentType<OwnPropsOfControl>;
5
7
  }
6
- export declare const FormTypes: Array<CustomType>;
8
+ export declare const registerComponent: (tester: RankedTester, renderer: ComponentType<ControlProps>, modes: Array<FormMode>) => void;
9
+ export declare const getComponents: (mode: FormMode) => Readonly<Array<CustomType>>;
10
+ export declare const registerExport: (component: React.FC<any>) => void;
@@ -1,4 +1,17 @@
1
- import { TypeAddress } from "../components/Address";
2
- export const FormTypes = [
3
- TypeAddress
4
- ];
1
+ import { withJsonFormsControlProps } from "@jsonforms/react";
2
+ import { FormMode } from "./types";
3
+ // Stored seperately to avoid lookups
4
+ const customComponents = {
5
+ [FormMode.FORM]: [],
6
+ [FormMode.PRESENTATION]: [],
7
+ [FormMode.READONLY]: [],
8
+ };
9
+ export const registerComponent = (tester, renderer, modes) => {
10
+ modes.forEach((mode) => customComponents[mode].push({ tester, renderer: withJsonFormsControlProps(renderer) }));
11
+ };
12
+ export const getComponents = (mode) => {
13
+ return customComponents[mode];
14
+ };
15
+ export const registerExport = (component) => {
16
+ component;
17
+ };
@@ -0,0 +1,5 @@
1
+ export declare enum FormMode {
2
+ PRESENTATION = 0,
3
+ READONLY = 1,
4
+ FORM = 2
5
+ }
@@ -0,0 +1,6 @@
1
+ export var FormMode;
2
+ (function (FormMode) {
3
+ FormMode[FormMode["PRESENTATION"] = 0] = "PRESENTATION";
4
+ FormMode[FormMode["READONLY"] = 1] = "READONLY";
5
+ FormMode[FormMode["FORM"] = 2] = "FORM";
6
+ })(FormMode || (FormMode = {}));
@@ -0,0 +1 @@
1
+ export type Updator<T extends object> = <Field extends keyof T>(field: Field, value: T[Field]) => void;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swoop-common",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [