reactivated 0.25.0 → 1.0.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/{babel.config.d.ts → dist/babel.config.d.ts} +0 -0
- package/{babel.config.js → dist/babel.config.js} +0 -0
- package/dist/babel.config.js.map +1 -0
- package/dist/build.client.d.ts +2 -0
- package/{build.client.js → dist/build.client.js} +14 -13
- package/dist/build.client.js.map +1 -0
- package/dist/build.renderer.d.ts +2 -0
- package/{build.renderer.js → dist/build.renderer.js} +21 -14
- package/dist/build.renderer.js.map +1 -0
- package/{client.d.ts → dist/client.d.ts} +0 -0
- package/dist/client.js +19 -0
- package/dist/client.js.map +1 -0
- package/{components → dist/components}/Form.d.ts +1 -0
- package/{components → dist/components}/Form.js +4 -5
- package/dist/components/Form.js.map +1 -0
- package/{components → dist/components}/Widget.d.ts +0 -0
- package/{components → dist/components}/Widget.js +5 -7
- package/dist/components/Widget.js.map +1 -0
- package/{context.d.ts → dist/context.d.ts} +0 -0
- package/dist/context.js +20 -0
- package/dist/context.js.map +1 -0
- package/{eslintrc.d.ts → dist/eslintrc.d.ts} +0 -0
- package/{eslintrc.js → dist/eslintrc.js} +0 -0
- package/dist/eslintrc.js.map +1 -0
- package/{forms → dist/forms}/index.d.ts +0 -0
- package/dist/forms/index.js +377 -0
- package/dist/forms/index.js.map +1 -0
- package/{forms → dist/forms}/widgets.d.ts +1 -0
- package/{forms → dist/forms}/widgets.js +11 -11
- package/dist/forms/widgets.js.map +1 -0
- package/{generated.d.ts → dist/generated.d.ts} +0 -0
- package/{generated.js → dist/generated.js} +0 -0
- package/dist/generated.js.map +1 -0
- package/dist/generator/constants.d.ts +2 -0
- package/{generator → dist/generator}/constants.js +11 -11
- package/dist/generator/constants.js.map +1 -0
- package/dist/generator.d.ts +2 -0
- package/dist/generator.js +155 -0
- package/dist/generator.js.map +1 -0
- package/{index.d.ts → dist/index.d.ts} +0 -0
- package/{index.js → dist/index.js} +0 -0
- package/dist/index.js.map +1 -0
- package/{models.d.ts → dist/models.d.ts} +0 -0
- package/{models.js → dist/models.js} +0 -0
- package/dist/models.js.map +1 -0
- package/{renderer.d.ts → dist/renderer.d.ts} +0 -0
- package/dist/renderer.js +117 -0
- package/dist/renderer.js.map +1 -0
- package/{types.d.ts → dist/types.d.ts} +0 -0
- package/{types.js → dist/types.js} +0 -0
- package/dist/types.js.map +1 -0
- package/package.json +23 -19
- package/scripts/setup_environment.sh +39 -0
- package/{README.md → src/README.md} +0 -0
- package/src/babel.config.tsx +14 -0
- package/src/build.client.tsx +59 -0
- package/src/build.renderer.tsx +69 -0
- package/src/client.tsx +15 -0
- package/src/components/Form.tsx +73 -0
- package/src/components/Widget.tsx +202 -0
- package/src/context.tsx +28 -0
- package/src/eslintrc.tsx +117 -0
- package/src/forms/index.tsx +769 -0
- package/src/forms/widgets.tsx +85 -0
- package/src/generated.tsx +267 -0
- package/src/generator/constants.tsx +40 -0
- package/src/generator.tsx +181 -0
- package/src/index.tsx +4 -0
- package/src/models.tsx +12 -0
- package/src/renderer.tsx +165 -0
- package/src/types.tsx +6 -0
- package/tsconfig.json +10 -20
- package/babel.config.js.map +0 -1
- package/build.client.d.ts +0 -1
- package/build.client.js.map +0 -1
- package/build.renderer.d.ts +0 -1
- package/build.renderer.js.map +0 -1
- package/client.js +0 -30
- package/client.js.map +0 -1
- package/components/Form.js.map +0 -1
- package/components/Widget.js.map +0 -1
- package/context.js +0 -31
- package/context.js.map +0 -1
- package/eslintrc.js.map +0 -1
- package/forms/index.js +0 -401
- package/forms/index.js.map +0 -1
- package/forms/widgets.js.map +0 -1
- package/generated.js.map +0 -1
- package/generator/constants.d.ts +0 -1
- package/generator/constants.js.map +0 -1
- package/generator.d.ts +0 -1
- package/generator.js +0 -109
- package/generator.js.map +0 -1
- package/index.js.map +0 -1
- package/models.js.map +0 -1
- package/renderer.js +0 -108
- package/renderer.js.map +0 -1
- package/types.js.map +0 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
const TEXTAREA_ROWS = 10;
|
|
4
|
+
|
|
5
|
+
interface BaseWidget {
|
|
6
|
+
name: string;
|
|
7
|
+
is_hidden: boolean;
|
|
8
|
+
required: boolean;
|
|
9
|
+
attrs: {
|
|
10
|
+
id: string;
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
required?: boolean;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Note: maxlength isn't actually part of the widget. Rather, it is added at
|
|
18
|
+
// runtime by forms.CharField (and children, like URLField)
|
|
19
|
+
//
|
|
20
|
+
// Kind of messy.
|
|
21
|
+
//
|
|
22
|
+
// Also, not sure why we need type instead of just using template_name.
|
|
23
|
+
|
|
24
|
+
export interface TextInput extends BaseWidget {
|
|
25
|
+
type: "text";
|
|
26
|
+
template_name: "django/forms/widgets/text.html";
|
|
27
|
+
value: string | null;
|
|
28
|
+
attrs: BaseWidget["attrs"] & {
|
|
29
|
+
maxlength?: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface URLInput extends BaseWidget {
|
|
34
|
+
type: "url";
|
|
35
|
+
template_name: "django/forms/widgets/url.html";
|
|
36
|
+
value: string | null;
|
|
37
|
+
attrs: BaseWidget["attrs"] & {
|
|
38
|
+
maxlength?: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface NumberInput extends BaseWidget {
|
|
43
|
+
type: "number";
|
|
44
|
+
template_name: "django/forms/widgets/number.html";
|
|
45
|
+
value: string | null;
|
|
46
|
+
attrs: BaseWidget["attrs"] & {
|
|
47
|
+
step: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface CheckboxInput extends BaseWidget {
|
|
52
|
+
type: "checkbox";
|
|
53
|
+
template_name: "django/forms/widgets/checkbox.html";
|
|
54
|
+
value: string | null;
|
|
55
|
+
attrs: BaseWidget["attrs"] & {
|
|
56
|
+
checked?: true;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface PasswordInput extends BaseWidget {
|
|
61
|
+
type: "password";
|
|
62
|
+
template_name: "django/forms/widgets/password.html";
|
|
63
|
+
value: string | null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface EmailInput extends BaseWidget {
|
|
67
|
+
type: "email";
|
|
68
|
+
template_name: "django/forms/widgets/email.html";
|
|
69
|
+
value: string | null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface HiddenInput extends BaseWidget {
|
|
73
|
+
type: "hidden";
|
|
74
|
+
template_name: "django/forms/widgets/hidden.html";
|
|
75
|
+
value: string | null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface Textarea extends BaseWidget {
|
|
79
|
+
template_name: "django/forms/widgets/textarea.html";
|
|
80
|
+
value: string | null;
|
|
81
|
+
attrs: BaseWidget["attrs"] & {
|
|
82
|
+
cols: string;
|
|
83
|
+
rows: string;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface DateInput extends BaseWidget {
|
|
88
|
+
template_name: "django/forms/widgets/date.html";
|
|
89
|
+
type: "date";
|
|
90
|
+
value: string | null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface ClearableFileInput extends BaseWidget {
|
|
94
|
+
template_name: "django/forms/widgets/clearable_file_input.html";
|
|
95
|
+
type: "file";
|
|
96
|
+
value: string | null;
|
|
97
|
+
checkbox_name: string;
|
|
98
|
+
checkbox_id: string;
|
|
99
|
+
is_initial: boolean;
|
|
100
|
+
input_text: string;
|
|
101
|
+
initial_text: string;
|
|
102
|
+
clear_checkbox_label: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
type Optgroup = [
|
|
106
|
+
null,
|
|
107
|
+
[
|
|
108
|
+
{
|
|
109
|
+
name: string;
|
|
110
|
+
// value: string|number|boolean|null;
|
|
111
|
+
value: string | number | boolean | null;
|
|
112
|
+
label: string;
|
|
113
|
+
selected: boolean;
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
number,
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
interface IsMultiple {
|
|
120
|
+
attrs: {multiple: "multiple"};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
interface IsSingle {
|
|
124
|
+
attrs: {};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function isMultiple<T extends IsMultiple, U extends IsSingle>(
|
|
128
|
+
widget: T | U,
|
|
129
|
+
): widget is T {
|
|
130
|
+
return "multiple" in widget.attrs;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface Select<T extends string = string> extends BaseWidget {
|
|
134
|
+
value: T[];
|
|
135
|
+
template_name: "django/forms/widgets/select.html";
|
|
136
|
+
optgroups: Optgroup[];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface Autocomplete extends BaseWidget {
|
|
140
|
+
value: string[];
|
|
141
|
+
template_name: "reactivated/autocomplete";
|
|
142
|
+
selected: {
|
|
143
|
+
value: string | number;
|
|
144
|
+
label: string;
|
|
145
|
+
} | null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface SelectMultiple<T extends string = string> extends Select<T> {
|
|
149
|
+
attrs: BaseWidget["attrs"] & {
|
|
150
|
+
multiple: "multiple";
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export interface SelectDateWidget extends BaseWidget {
|
|
155
|
+
value: {
|
|
156
|
+
year: string | null;
|
|
157
|
+
month: string | null;
|
|
158
|
+
day: string | null;
|
|
159
|
+
};
|
|
160
|
+
subwidgets: [Select, Select, Select];
|
|
161
|
+
template_name: "django/forms/widgets/select_date.html";
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export type WidgetType =
|
|
165
|
+
| TextInput
|
|
166
|
+
| URLInput
|
|
167
|
+
| NumberInput
|
|
168
|
+
| CheckboxInput
|
|
169
|
+
| PasswordInput
|
|
170
|
+
| EmailInput
|
|
171
|
+
| HiddenInput
|
|
172
|
+
| Textarea
|
|
173
|
+
| Select
|
|
174
|
+
| Autocomplete
|
|
175
|
+
| SelectMultiple
|
|
176
|
+
| DateInput
|
|
177
|
+
| SelectDateWidget
|
|
178
|
+
| ClearableFileInput;
|
|
179
|
+
|
|
180
|
+
export const getValue = (optgroup: Optgroup) => {
|
|
181
|
+
const rawValue = optgroup[1][0].value;
|
|
182
|
+
|
|
183
|
+
if (rawValue == null) {
|
|
184
|
+
return "";
|
|
185
|
+
} else if (rawValue === true) {
|
|
186
|
+
return "True";
|
|
187
|
+
} else if (rawValue === false) {
|
|
188
|
+
return "False";
|
|
189
|
+
}
|
|
190
|
+
return rawValue;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export const getValueForSelect = (widget: Select | Autocomplete | SelectMultiple) => {
|
|
194
|
+
if (isMultiple(widget)) {
|
|
195
|
+
return widget.value;
|
|
196
|
+
} else {
|
|
197
|
+
return widget.value == null ? "" : widget.value[0];
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
export const isHidden = (widget: WidgetType) =>
|
|
202
|
+
"type" in widget && widget.type === "hidden";
|
package/src/context.tsx
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export default <TContext extends {}>() => {
|
|
4
|
+
type TMutableContext = TContext & {
|
|
5
|
+
setValue: React.Dispatch<React.SetStateAction<TContext>>;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const Context = React.createContext<TMutableContext>(null!);
|
|
9
|
+
|
|
10
|
+
const Provider = (props: {value: TContext; children: React.ReactNode}) => {
|
|
11
|
+
const [value, setValue] = React.useState(props.value);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<Context.Provider value={{...value, setValue}}>
|
|
15
|
+
{props.children}
|
|
16
|
+
</Context.Provider>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getServerData = () => {
|
|
21
|
+
const props: Record<string, unknown> = (window as any).__PRELOADED_PROPS__;
|
|
22
|
+
const context: TContext = (window as any).__PRELOADED_CONTEXT__;
|
|
23
|
+
|
|
24
|
+
return {props, context};
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return {Context, Provider, getServerData};
|
|
28
|
+
};
|
package/src/eslintrc.tsx
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
root: true,
|
|
3
|
+
parser: "@typescript-eslint/parser",
|
|
4
|
+
parserOptions: {
|
|
5
|
+
project: ["./tsconfig.json"],
|
|
6
|
+
},
|
|
7
|
+
plugins: ["@typescript-eslint"],
|
|
8
|
+
settings: {
|
|
9
|
+
react: {
|
|
10
|
+
version: "detect",
|
|
11
|
+
},
|
|
12
|
+
"import/resolver": "typescript",
|
|
13
|
+
},
|
|
14
|
+
rules: {
|
|
15
|
+
"sort-imports": ["error", {ignoreDeclarationSort: true}],
|
|
16
|
+
|
|
17
|
+
// TypeScript handles this for us.
|
|
18
|
+
"import/namespace": 0,
|
|
19
|
+
"import/named": 0,
|
|
20
|
+
"import/no-unresolved": 0,
|
|
21
|
+
|
|
22
|
+
// immer's default export is produce, not matching the filename.
|
|
23
|
+
// TODO: I think immer can be specifically imported now.
|
|
24
|
+
"import/no-named-as-default": 0,
|
|
25
|
+
"import/no-named-as-default-member": 0,
|
|
26
|
+
|
|
27
|
+
"import/newline-after-import": ["error"],
|
|
28
|
+
"import/first": ["error"],
|
|
29
|
+
"import/order": [
|
|
30
|
+
"error",
|
|
31
|
+
{
|
|
32
|
+
alphabetize: {order: "asc"},
|
|
33
|
+
"newlines-between": "always",
|
|
34
|
+
pathGroups: [
|
|
35
|
+
{
|
|
36
|
+
group: "builtin",
|
|
37
|
+
pattern: "{react,react-dom}",
|
|
38
|
+
position: "before",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
group: "builtin",
|
|
42
|
+
pattern: "{@reactivated,react-*}",
|
|
43
|
+
position: "after",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
group: "builtin",
|
|
47
|
+
pattern: "@linaria/*",
|
|
48
|
+
position: "after",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
group: "internal",
|
|
52
|
+
pattern: "@client/actions/*",
|
|
53
|
+
position: "before",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
group: "internal",
|
|
57
|
+
pattern:
|
|
58
|
+
"@client/{app/graphics,shared/analytics,dates,utils,routes,models,style,shared/typography,constants}",
|
|
59
|
+
position: "before",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
groups: [
|
|
63
|
+
"builtin",
|
|
64
|
+
"external",
|
|
65
|
+
"internal",
|
|
66
|
+
"parent",
|
|
67
|
+
"sibling",
|
|
68
|
+
"index",
|
|
69
|
+
],
|
|
70
|
+
pathGroupsExcludedImportTypes: ["builtin"],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
// React overrides
|
|
74
|
+
"react/prop-types": "off",
|
|
75
|
+
// We create way too many components dynamically.
|
|
76
|
+
"react/display-name": "off",
|
|
77
|
+
// We use empty arrays to run once, etc.
|
|
78
|
+
"react-hooks/exhaustive-deps": "off",
|
|
79
|
+
|
|
80
|
+
// Typescript overrides from recommended
|
|
81
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
82
|
+
|
|
83
|
+
"@typescript-eslint/explicit-module-boundary-types": "off",
|
|
84
|
+
"@typescript-eslint/no-non-null-assertion": "off",
|
|
85
|
+
|
|
86
|
+
// We use empty callbacks that are no-ops sometimes.
|
|
87
|
+
"@typescript-eslint/no-empty-function": ["error", {allow: ["arrowFunctions"]}],
|
|
88
|
+
|
|
89
|
+
// Typescript additions
|
|
90
|
+
"@typescript-eslint/strict-boolean-expressions": "error",
|
|
91
|
+
|
|
92
|
+
// See: https://github.com/typescript-eslint/typescript-eslint/issues/4619#issuecomment-1057096238
|
|
93
|
+
// We want async callbacks to React event handlers
|
|
94
|
+
"@typescript-eslint/no-misused-promises": [
|
|
95
|
+
"error",
|
|
96
|
+
{
|
|
97
|
+
checksVoidReturn: {
|
|
98
|
+
attributes: false,
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
|
|
103
|
+
// https://www.reddit.com/r/typescript/comments/uiil9k/am_i_crazy_for_expecting_typescript_to_catch_this/
|
|
104
|
+
"@typescript-eslint/no-use-before-define": ["error"],
|
|
105
|
+
},
|
|
106
|
+
extends: [
|
|
107
|
+
"eslint:recommended",
|
|
108
|
+
"plugin:react/recommended",
|
|
109
|
+
"plugin:react-hooks/recommended",
|
|
110
|
+
"plugin:@typescript-eslint/recommended",
|
|
111
|
+
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
|
112
|
+
"prettier",
|
|
113
|
+
"plugin:import/typescript",
|
|
114
|
+
"plugin:import/errors",
|
|
115
|
+
"plugin:import/warnings",
|
|
116
|
+
],
|
|
117
|
+
};
|