dce-reactkit 3.3.6 → 3.4.0-beta.1
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/dist/cjs/index.js +37520 -379
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/DBEntryManagerPanel/AddOrEditDBEntry/CreatableMultiselect.d.ts +10 -0
- package/dist/cjs/types/components/DBEntryManagerPanel/AddOrEditDBEntry/index.d.ts +33 -0
- package/dist/cjs/types/components/DBEntryManagerPanel/helpers/generateEndpointPath.d.ts +8 -0
- package/dist/cjs/types/components/DBEntryManagerPanel/index.d.ts +25 -0
- package/dist/cjs/types/components/DBEntryManagerPanel/types/DBEntry.d.ts +8 -0
- package/dist/cjs/types/components/DBEntryManagerPanel/types/DBEntryField.d.ts +49 -0
- package/dist/cjs/types/components/DBEntryManagerPanel/types/DBEntryFieldType.d.ts +12 -0
- package/dist/cjs/types/helpers/addDBEditorEndpoints.d.ts +40 -0
- package/dist/cjs/types/index.d.ts +6 -1
- package/dist/esm/index.js +37694 -574
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/DBEntryManagerPanel/AddOrEditDBEntry/CreatableMultiselect.d.ts +10 -0
- package/dist/esm/types/components/DBEntryManagerPanel/AddOrEditDBEntry/index.d.ts +33 -0
- package/dist/esm/types/components/DBEntryManagerPanel/helpers/generateEndpointPath.d.ts +8 -0
- package/dist/esm/types/components/DBEntryManagerPanel/index.d.ts +25 -0
- package/dist/esm/types/components/DBEntryManagerPanel/types/DBEntry.d.ts +8 -0
- package/dist/esm/types/components/DBEntryManagerPanel/types/DBEntryField.d.ts +49 -0
- package/dist/esm/types/components/DBEntryManagerPanel/types/DBEntryFieldType.d.ts +12 -0
- package/dist/esm/types/helpers/addDBEditorEndpoints.d.ts +40 -0
- package/dist/esm/types/index.d.ts +6 -1
- package/dist/index.d.ts +166 -35
- package/package.json +8 -3
- package/src/components/DBEntryManagerPanel/AddOrEditDBEntry/CreatableMultiselect.tsx +290 -0
- package/src/components/DBEntryManagerPanel/AddOrEditDBEntry/index.tsx +699 -0
- package/src/components/DBEntryManagerPanel/helpers/generateEndpointPath.ts +15 -0
- package/src/components/DBEntryManagerPanel/index.tsx +511 -0
- package/src/components/DBEntryManagerPanel/types/DBEntry.ts +7 -0
- package/src/components/DBEntryManagerPanel/types/DBEntryField.ts +94 -0
- package/src/components/DBEntryManagerPanel/types/DBEntryFieldType.ts +18 -0
- package/src/helpers/addDBEditorEndpoints.ts +121 -0
- package/src/index.ts +11 -1
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
// Import React
|
|
2
|
+
import React, { KeyboardEventHandler, useReducer } from 'react';
|
|
3
|
+
|
|
4
|
+
// Import React Select
|
|
5
|
+
import CreatableSelect from 'react-select/creatable';
|
|
6
|
+
import { MultiValue } from 'react-select';
|
|
7
|
+
|
|
8
|
+
// Import other types
|
|
9
|
+
import DBEntryFieldType from '../types/DBEntryFieldType';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/*------------------------------------------------------------------------*/
|
|
13
|
+
/* -------------------------------- Types ------------------------------- */
|
|
14
|
+
/*------------------------------------------------------------------------*/
|
|
15
|
+
|
|
16
|
+
// Props definition
|
|
17
|
+
type Props = {
|
|
18
|
+
// Type of the field
|
|
19
|
+
type: DBEntryFieldType.StringArray | DBEntryFieldType.NumberArray;
|
|
20
|
+
// The values entered by the user
|
|
21
|
+
values: string[] | number[];
|
|
22
|
+
// Function to call when the values change
|
|
23
|
+
onChange: (values: string[] | number[]) => void;
|
|
24
|
+
// True if the field is disabled
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// An option for the multiselect component
|
|
29
|
+
type Option = {
|
|
30
|
+
// What the user sees and types in for the option
|
|
31
|
+
label: string;
|
|
32
|
+
// Lowercase, no spaces, no special characters of the label
|
|
33
|
+
value: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/*------------------------------------------------------------------------*/
|
|
37
|
+
/* -------------------------------- State ------------------------------- */
|
|
38
|
+
/*------------------------------------------------------------------------*/
|
|
39
|
+
|
|
40
|
+
/* -------- State Definition -------- */
|
|
41
|
+
|
|
42
|
+
type State = {
|
|
43
|
+
// what the user has typed in so far(before pressing enter or tab)
|
|
44
|
+
inputValue: string,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/* ------------- Actions ------------ */
|
|
48
|
+
|
|
49
|
+
// Types of actions
|
|
50
|
+
enum ActionType {
|
|
51
|
+
// Update the input value
|
|
52
|
+
SetInputValue = 'SetInputValue',
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Action definitions
|
|
56
|
+
type Action = (
|
|
57
|
+
| {
|
|
58
|
+
// Action type
|
|
59
|
+
type: ActionType.SetInputValue;
|
|
60
|
+
// New value
|
|
61
|
+
value: string
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Reducer that executes actions
|
|
67
|
+
* @author Yuen Ler Chow
|
|
68
|
+
* @param state current state
|
|
69
|
+
* @param action action to execute
|
|
70
|
+
*/
|
|
71
|
+
const reducer = (state: State, action: Action): State => {
|
|
72
|
+
switch (action.type) {
|
|
73
|
+
case ActionType.SetInputValue: {
|
|
74
|
+
return {
|
|
75
|
+
...state,
|
|
76
|
+
inputValue: action.value,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
default: {
|
|
80
|
+
return state;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/*------------------------------------------------------------------------*/
|
|
86
|
+
/* -------------------------------- State ------------------------------- */
|
|
87
|
+
/*------------------------------------------------------------------------*/
|
|
88
|
+
|
|
89
|
+
const CreatableMultiselect: React.FC<Props> = (props) => {
|
|
90
|
+
|
|
91
|
+
// Destructure all props
|
|
92
|
+
const {
|
|
93
|
+
type,
|
|
94
|
+
values,
|
|
95
|
+
onChange,
|
|
96
|
+
disabled,
|
|
97
|
+
} = props;
|
|
98
|
+
|
|
99
|
+
/* -------------- State ------------- */
|
|
100
|
+
|
|
101
|
+
// Initial state
|
|
102
|
+
const initialState: State = {
|
|
103
|
+
inputValue: '',
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Initialize state
|
|
107
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
108
|
+
|
|
109
|
+
// Destructure common state
|
|
110
|
+
const { inputValue } = state;
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
/*------------------------------------------------------------------------*/
|
|
114
|
+
/* ------------------------- Component Functions ------------------------ */
|
|
115
|
+
/*------------------------------------------------------------------------*/
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Creates an option for the multiselect component
|
|
119
|
+
* @author Yuen Ler Chow
|
|
120
|
+
* @param label label of the option
|
|
121
|
+
*/
|
|
122
|
+
const createOption = (label: string): Option => {
|
|
123
|
+
// set the value to the label without special characters and spaces, and lowercase
|
|
124
|
+
return {
|
|
125
|
+
label,
|
|
126
|
+
value: (
|
|
127
|
+
label
|
|
128
|
+
.toLowerCase()
|
|
129
|
+
.replace(/\W/g, '')
|
|
130
|
+
.replace(' ', '-')
|
|
131
|
+
),
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Adds the values to the multiselect component
|
|
137
|
+
* @author Yuen Ler Chow
|
|
138
|
+
* @param newValue new value to add
|
|
139
|
+
*/
|
|
140
|
+
const addValues = (newValue: string) => {
|
|
141
|
+
if (type === DBEntryFieldType.NumberArray) {
|
|
142
|
+
const newValues = (
|
|
143
|
+
newValue
|
|
144
|
+
// Split into items
|
|
145
|
+
.split(',')
|
|
146
|
+
// Trim strings
|
|
147
|
+
.map((val) => {
|
|
148
|
+
return val.trim();
|
|
149
|
+
})
|
|
150
|
+
// Filter zero length
|
|
151
|
+
.filter((trimmedVal) => {
|
|
152
|
+
return trimmedVal.length > 0;
|
|
153
|
+
})
|
|
154
|
+
// Parse to number
|
|
155
|
+
.map(Number.parseFloat)
|
|
156
|
+
// Filter out existing values
|
|
157
|
+
.filter((numberVal) => {
|
|
158
|
+
return !values.some((value) => {
|
|
159
|
+
return value === numberVal;
|
|
160
|
+
});
|
|
161
|
+
})
|
|
162
|
+
);
|
|
163
|
+
onChange([...values, ...newValues] as number[]);
|
|
164
|
+
} else {
|
|
165
|
+
const newValues = (
|
|
166
|
+
newValue
|
|
167
|
+
// Split into items
|
|
168
|
+
.split(',')
|
|
169
|
+
// Trim strings
|
|
170
|
+
.map((val) => {
|
|
171
|
+
return val.trim();
|
|
172
|
+
})
|
|
173
|
+
// Filter zero length
|
|
174
|
+
.filter((trimmedVal) => {
|
|
175
|
+
return (trimmedVal.length > 0);
|
|
176
|
+
})
|
|
177
|
+
// Filter out existing values
|
|
178
|
+
.filter((val) => {
|
|
179
|
+
return !values.some((value) => {
|
|
180
|
+
return value === val;
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
);
|
|
184
|
+
onChange([...values, ...newValues] as string[]);
|
|
185
|
+
}
|
|
186
|
+
// resets text field to empty because the values have been added
|
|
187
|
+
dispatch({
|
|
188
|
+
type: ActionType.SetInputValue,
|
|
189
|
+
value: '',
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Adds the values to the multiselect component when enter or tab is pressed
|
|
195
|
+
* @author Yuen Ler Chow
|
|
196
|
+
* @param event keyboard event
|
|
197
|
+
*/
|
|
198
|
+
const handleKeyDown: KeyboardEventHandler = (event) => {
|
|
199
|
+
event.preventDefault();
|
|
200
|
+
|
|
201
|
+
// Skip if no input value
|
|
202
|
+
if (!inputValue) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Add values if enter or tab is pressed
|
|
207
|
+
if (['Enter', 'Tab'].includes(event.key)) {
|
|
208
|
+
addValues(inputValue);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Handles the input change of the multiselect component
|
|
214
|
+
* @author Yuen Ler Chow
|
|
215
|
+
* @param input input value
|
|
216
|
+
*/
|
|
217
|
+
const handleInputChange = (input: string) => {
|
|
218
|
+
// Create copy of input value so we can modify it
|
|
219
|
+
let newValue = input;
|
|
220
|
+
|
|
221
|
+
// Don't allow user to type in non numbers
|
|
222
|
+
if (type === DBEntryFieldType.NumberArray) {
|
|
223
|
+
newValue = input.replace(/[^0-9,]/g, '');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (input.includes(',')) {
|
|
227
|
+
// if the input has a comma, add the values separated by commas
|
|
228
|
+
addValues(newValue);
|
|
229
|
+
} else {
|
|
230
|
+
// simply update the input value to the new input value
|
|
231
|
+
dispatch({
|
|
232
|
+
type: ActionType.SetInputValue,
|
|
233
|
+
value: newValue,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Handles the value change of the multiselect component
|
|
240
|
+
* @author Yuen Ler Chow
|
|
241
|
+
* @param newValue new values
|
|
242
|
+
*/
|
|
243
|
+
const handleValueChange = (newValues: MultiValue<Option>) => {
|
|
244
|
+
// Skip if no new values
|
|
245
|
+
if (!newValues) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Update values based on type
|
|
250
|
+
if (type === DBEntryFieldType.NumberArray) {
|
|
251
|
+
const numberValues: number[] = newValues.map((val) => {
|
|
252
|
+
return Number(val.value);
|
|
253
|
+
});
|
|
254
|
+
onChange(numberValues);
|
|
255
|
+
} else {
|
|
256
|
+
const stringValues: string[] = newValues.map((val) => {
|
|
257
|
+
return val.value;
|
|
258
|
+
});
|
|
259
|
+
onChange(stringValues);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
/*----------------------------------------*/
|
|
264
|
+
/* --------------- Main UI -------------- */
|
|
265
|
+
/*----------------------------------------*/
|
|
266
|
+
|
|
267
|
+
return (
|
|
268
|
+
<CreatableSelect
|
|
269
|
+
isDisabled={!!disabled}
|
|
270
|
+
components={{ DropdownIndicator: null }}
|
|
271
|
+
inputValue={inputValue}
|
|
272
|
+
isClearable
|
|
273
|
+
isMulti
|
|
274
|
+
menuIsOpen={false}
|
|
275
|
+
onChange={handleValueChange}
|
|
276
|
+
onInputChange={handleInputChange}
|
|
277
|
+
onKeyDown={handleKeyDown}
|
|
278
|
+
placeholder="Type/paste value and press enter..."
|
|
279
|
+
value={values.map((val) => {
|
|
280
|
+
return createOption(String(val));
|
|
281
|
+
})}
|
|
282
|
+
/>
|
|
283
|
+
);
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
/*------------------------------------------------------------------------*/
|
|
287
|
+
/* ------------------------------- Wrap Up ------------------------------ */
|
|
288
|
+
/*------------------------------------------------------------------------*/
|
|
289
|
+
|
|
290
|
+
export default CreatableMultiselect;
|