superglue 0.53.2 → 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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/superglue/install/install_generator.rb +119 -0
  3. data/lib/{install/templates/web → generators/superglue/install/templates}/application.json.props +2 -2
  4. data/lib/generators/superglue/install/templates/js/application.jsx +35 -0
  5. data/lib/generators/superglue/install/templates/js/application_visit.js +113 -0
  6. data/lib/generators/superglue/install/templates/js/components.js +2 -0
  7. data/lib/generators/superglue/install/templates/js/flash.js +44 -0
  8. data/lib/generators/superglue/install/templates/js/inputs.jsx +302 -0
  9. data/lib/generators/superglue/install/templates/js/jsconfig.json +9 -0
  10. data/lib/generators/superglue/install/templates/js/layout.jsx +16 -0
  11. data/lib/generators/superglue/install/templates/js/page_to_page_mapping.js +35 -0
  12. data/lib/generators/superglue/install/templates/js/store.js +30 -0
  13. data/lib/{install/templates/web/application.js → generators/superglue/install/templates/ts/application.tsx} +10 -16
  14. data/lib/generators/superglue/install/templates/ts/application_visit.ts +122 -0
  15. data/lib/generators/superglue/install/templates/ts/components.ts +2 -0
  16. data/lib/generators/superglue/install/templates/ts/flash.ts +46 -0
  17. data/lib/generators/superglue/install/templates/ts/inputs.tsx +547 -0
  18. data/lib/generators/superglue/install/templates/ts/layout.tsx +16 -0
  19. data/lib/generators/superglue/install/templates/ts/page_to_page_mapping.ts +34 -0
  20. data/lib/generators/superglue/install/templates/ts/store.ts +34 -0
  21. data/lib/generators/superglue/install/templates/ts/tsconfig.json +27 -0
  22. data/lib/generators/superglue/scaffold/scaffold_generator.rb +16 -0
  23. data/lib/generators/superglue/scaffold_controller/scaffold_controller_generator.rb +61 -0
  24. data/lib/generators/{rails/templates/web → superglue/view_collection/templates/erb}/edit.html.erb +1 -1
  25. data/lib/generators/{rails/templates/web → superglue/view_collection/templates/erb}/index.html.erb +1 -1
  26. data/lib/generators/{rails/templates/web → superglue/view_collection/templates/erb}/new.html.erb +1 -1
  27. data/lib/generators/{rails/templates/web → superglue/view_collection/templates/erb}/show.html.erb +1 -1
  28. data/lib/generators/superglue/view_collection/templates/js/edit.jsx +40 -0
  29. data/lib/generators/superglue/view_collection/templates/js/index.jsx +62 -0
  30. data/lib/generators/superglue/view_collection/templates/js/new.jsx +38 -0
  31. data/lib/generators/superglue/view_collection/templates/js/show.jsx +26 -0
  32. data/lib/generators/superglue/view_collection/templates/props/edit.json.props +9 -0
  33. data/lib/generators/superglue/view_collection/templates/props/index.json.props +14 -0
  34. data/lib/generators/superglue/view_collection/templates/props/new.json.props +10 -0
  35. data/lib/generators/superglue/view_collection/templates/props/show.json.props +6 -0
  36. data/lib/generators/superglue/view_collection/templates/ts/edit.tsx +54 -0
  37. data/lib/generators/superglue/view_collection/templates/ts/index.tsx +77 -0
  38. data/lib/generators/superglue/view_collection/templates/ts/new.tsx +50 -0
  39. data/lib/generators/superglue/view_collection/templates/ts/show.tsx +37 -0
  40. data/lib/generators/superglue/view_collection/view_collection_generator.rb +180 -0
  41. data/lib/superglue/helpers.rb +1 -1
  42. data/lib/superglue.rb +2 -1
  43. metadata +60 -43
  44. data/lib/generators/rails/scaffold_controller_generator.rb +0 -12
  45. data/lib/generators/rails/superglue_generator.rb +0 -98
  46. data/lib/generators/rails/templates/controller.rb.tt +0 -82
  47. data/lib/generators/rails/templates/edit.json.props +0 -12
  48. data/lib/generators/rails/templates/index.json.props +0 -14
  49. data/lib/generators/rails/templates/new.json.props +0 -13
  50. data/lib/generators/rails/templates/show.json.props +0 -6
  51. data/lib/generators/rails/templates/web/edit.js +0 -35
  52. data/lib/generators/rails/templates/web/index.js +0 -56
  53. data/lib/generators/rails/templates/web/new.js +0 -33
  54. data/lib/generators/rails/templates/web/show.js +0 -28
  55. data/lib/install/templates/web/actions.js +0 -6
  56. data/lib/install/templates/web/application_visit.js +0 -65
  57. data/lib/install/templates/web/flash.js +0 -19
  58. data/lib/install/templates/web/page_to_page_mapping.js +0 -12
  59. data/lib/install/templates/web/pages.js +0 -15
  60. data/lib/install/templates/web/store.js +0 -32
  61. data/lib/install/web.rb +0 -55
  62. data/lib/tasks/install.rake +0 -9
  63. /data/lib/{install/templates/web → generators/superglue/install/templates}/initializer.rb +0 -0
  64. /data/lib/generators/{rails/templates → superglue/view_collection/templates/props}/_form.json.props +0 -0
@@ -0,0 +1,547 @@
1
+ /**
2
+ * Vanilla is a minimum set of
3
+ * [candy_wrappers](https://github.com/thoughtbot/candy_wrapper) around react
4
+ * HTML tags. It works with the output from
5
+ * [FormProps](https://github.com/thoughtbot/form_props).
6
+ *
7
+ * There is no style and structured with bare necessities. You should modify
8
+ * these components to fit your design needs.
9
+ */
10
+
11
+ import React, { ReactNode, useContext, createContext, useMemo } from "react";
12
+ import {
13
+ CheckboxField as RailsCheckboxField,
14
+ CollectionCheckboxesField as RailsCollectionCheckboxesField,
15
+ HiddenField as RailsHiddenField,
16
+ CollectionRadioButtonsField as RailsCollectionRadioButtonsField,
17
+ ColorField as RailsColorField,
18
+ DateField as RailsDateField,
19
+ DateTimeLocalField as RailsDateTimeLocalField,
20
+ EmailField as RailsEmailField,
21
+ MonthField as RailsMonthField,
22
+ NumberField as RailsNumberField,
23
+ PasswordField as RailsPasswordField,
24
+ RangeField as RailsRangeField,
25
+ SearchField as RailsSearchField,
26
+ Select as RailsSelect,
27
+ TelField as RailsTelField,
28
+ FileField as RailsFileField,
29
+ TextField as RailsTextField,
30
+ TimeField as RailsTimeField,
31
+ UrlField as RailsUrlField,
32
+ TextArea as RailsTextArea,
33
+ ValidationErrors,
34
+ SubmitProps as RailsSubmitButton
35
+ } from '@thoughtbot/candy_wrapper'
36
+
37
+ export const ValidationContext = createContext<ValidationErrors>({});
38
+
39
+ export const useErrorKeyValidation = ({
40
+ errorKey,
41
+ }: {
42
+ errorKey: string;
43
+ name: string;
44
+ }) => {
45
+ const errors = useContext(ValidationContext);
46
+
47
+ return useMemo(() => {
48
+ return errors[errorKey];
49
+ }, [errors, errorKey]);
50
+ };
51
+
52
+ export type ExtrasProps = Record<string, RailsHiddenField>;
53
+
54
+ /**
55
+ * Extras renders the hidden inputs generated by form_props.
56
+ *
57
+ * Its meant to be used with a form component and renders hidden values for
58
+ * utf8, crsf_token, _method
59
+ */
60
+ export const Extras = (hiddenInputAttributes: ExtrasProps) => {
61
+ const hiddenProps = Object.values(hiddenInputAttributes);
62
+ const hiddenInputs = hiddenProps.map((props: RailsHiddenField) => (
63
+ <input {...props} type="hidden" key={props.name} />
64
+ ));
65
+
66
+ return <>{hiddenInputs}</>;
67
+ };
68
+
69
+ // TODO: Add this as a form props props??
70
+ export interface FormProps<T={}> {
71
+ extras: ExtrasProps;
72
+ inputs: T;
73
+ form: React.FormHTMLAttributes<HTMLFormElement>;
74
+ }
75
+
76
+ type FormElementProps = React.FormHTMLAttributes<HTMLFormElement> & {
77
+ extras: ExtrasProps;
78
+ validationErrors?: ValidationErrors;
79
+ };
80
+ /**
81
+ * A basic form component that supports inline errors.
82
+ *
83
+ * It's meant to be used with FormProps and mimics the ways that
84
+ * Rails forms are generated.
85
+ */
86
+ export const Form = ({
87
+ extras,
88
+ validationErrors = {},
89
+ children,
90
+ ...props
91
+ }: FormElementProps) => {
92
+ return (
93
+ <form {...props}>
94
+ <ValidationContext.Provider value={validationErrors}>
95
+ <Extras {...extras}></Extras>
96
+ {children}
97
+ </ValidationContext.Provider>
98
+ </form>
99
+ );
100
+ };
101
+
102
+ /**
103
+ * An inline error component.
104
+ *
105
+ * When a Field has an error, this will show below the label and input.
106
+ * Please modify this to your liking.
107
+ */
108
+ export const FieldError = ({ errorKey }: { errorKey: string | undefined }) => {
109
+ const errors = useContext(ValidationContext);
110
+ if (!errorKey || !errors) {
111
+ return null;
112
+ }
113
+
114
+ const validationError = errors[errorKey];
115
+ const hasErrors = errorKey && validationError;
116
+
117
+ if (!hasErrors) {
118
+ return null;
119
+ }
120
+
121
+ const errorMessages = Array.isArray(validationError)
122
+ ? validationError
123
+ : [validationError];
124
+
125
+ return <span>{errorMessages.join(" ")}</span>;
126
+ };
127
+
128
+ export type FieldBaseProps = React.InputHTMLAttributes<HTMLInputElement> & {
129
+ id?: string;
130
+ label: string;
131
+ errorKey?: string;
132
+ children?: ReactNode;
133
+ };
134
+
135
+ /**
136
+ * A Field component.
137
+ *
138
+ * Combines a label, input and a FieldError. Please modify this to your liking.
139
+ */
140
+ export const FieldBase = ({
141
+ label,
142
+ errorKey,
143
+ children,
144
+ ...props
145
+ }: FieldBaseProps) => {
146
+ return (
147
+ <>
148
+ <label htmlFor={props.id}>{label}</label>
149
+ {children || <input {...props} />}
150
+ <FieldError errorKey={errorKey} />
151
+ </>
152
+ );
153
+ };
154
+
155
+ type InputProps = {
156
+ label: string;
157
+ errorKey?: string;
158
+ };
159
+
160
+ /**
161
+ * A checkbox component.
162
+ *
163
+ * Designed to work with a payload form_props's [checkbox helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#checkbox-helper).
164
+ * Mimics the rails equivalent. Please modify to your liking.
165
+ */
166
+ type CheckboxProps = RailsCheckboxField & InputProps;
167
+ export const Checkbox = ({
168
+ type: _type,
169
+ includeHidden,
170
+ uncheckedValue,
171
+ errorKey,
172
+ ...rest
173
+ }: CheckboxProps) => {
174
+ const { name } = rest;
175
+ return (
176
+ <FieldBase {...rest} errorKey={errorKey}>
177
+ {includeHidden && (
178
+ <input
179
+ type="hidden"
180
+ name={name}
181
+ defaultValue={uncheckedValue}
182
+ autoComplete="off"
183
+ />
184
+ )}
185
+ <input type="checkbox" {...rest}></input>
186
+ </FieldBase>
187
+ );
188
+ };
189
+
190
+ type CollectionCheckboxesFieldProps = RailsCollectionCheckboxesField &
191
+ InputProps;
192
+
193
+ /**
194
+ * A collection checkbox component.
195
+ *
196
+ * Designed to work with a payload form_props's [collection_check_boxes helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#collection-select).
197
+ * Mimics the rails equivalent. Please modify to your liking.
198
+ */
199
+ export const CollectionCheckboxes = ({
200
+ includeHidden,
201
+ collection,
202
+ label,
203
+ errorKey,
204
+ }: CollectionCheckboxesFieldProps) => {
205
+ if (collection.length == 0) {
206
+ return null;
207
+ }
208
+
209
+ const checkboxes = collection.map((options) => {
210
+ return <Checkbox {...options} key={options.id} />;
211
+ });
212
+
213
+ const { name } = collection[0];
214
+
215
+ return (
216
+ <>
217
+ {includeHidden && (
218
+ <input type="hidden" name={name} defaultValue={""} autoComplete="off" />
219
+ )}
220
+ <label>{label}</label>
221
+ {checkboxes}
222
+ <FieldError errorKey={errorKey} />
223
+ </>
224
+ );
225
+ };
226
+
227
+ type CollectionRadioButtonsFieldProps = RailsCollectionRadioButtonsField &
228
+ InputProps;
229
+
230
+ /**
231
+ * A collection radio button component.
232
+ *
233
+ * Designed to work with a payload form_props's [collection_radio_buttons helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#collection-select).
234
+ * Mimics the rails equivalent. Please modify to your liking.
235
+ */
236
+ export const CollectionRadioButtons = ({
237
+ includeHidden,
238
+ collection,
239
+ label,
240
+ errorKey,
241
+ }: CollectionRadioButtonsFieldProps) => {
242
+ if (collection.length == 0) {
243
+ return null;
244
+ }
245
+
246
+ const radioButtons = collection.map((options) => {
247
+ return (
248
+ <div key={options.value}>
249
+ <input {...options} type="radio" />
250
+ <label htmlFor={options.id}>{options.label}</label>
251
+ </div>
252
+ );
253
+ });
254
+
255
+ const { name } = collection[0];
256
+
257
+ return (
258
+ <>
259
+ {includeHidden && (
260
+ <input type="hidden" name={name} defaultValue={""} autoComplete="off" />
261
+ )}
262
+ <label>{label}</label>
263
+ {radioButtons}
264
+ <FieldError errorKey={errorKey} />
265
+ </>
266
+ );
267
+ };
268
+
269
+ export type TextFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
270
+ RailsTextField &
271
+ InputProps;
272
+
273
+ /**
274
+ * A text field component.
275
+ *
276
+ * Designed to work with a payload form_props's [text_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#text-helpers).
277
+ * Mimics the rails equivalent. Please modify to your liking.
278
+ */
279
+ export const TextField = ({ type: _type, ...rest }: TextFieldProps) => {
280
+ return <FieldBase {...rest} type="text" />;
281
+ };
282
+
283
+ export type EmailFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
284
+ RailsEmailField &
285
+ InputProps;
286
+
287
+ /**
288
+ * A email field component.
289
+ *
290
+ * Designed to work with a payload form_props's [email_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#text-helpers).
291
+ * Mimics the rails equivalent. Please modify to your liking.
292
+ */
293
+ export const EmailField = ({ type: _type, ...rest }: EmailFieldProps) => {
294
+ return <FieldBase {...rest} type="email" />;
295
+ };
296
+
297
+ export type ColorFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
298
+ RailsColorField &
299
+ InputProps;
300
+
301
+ /**
302
+ * A color field component.
303
+ *
304
+ * Designed to work with a payload form_props's [color_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#text-helpers).
305
+ * Mimics the rails equivalent. Please modify to your liking.
306
+ */
307
+ export const ColorField = ({ type: _type, ...rest }: ColorFieldProps) => {
308
+ return <FieldBase {...rest} type="color" />;
309
+ };
310
+
311
+ export type DateFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
312
+ RailsDateField &
313
+ InputProps;
314
+
315
+ /**
316
+ * A date field component.
317
+ *
318
+ * Designed to work with a payload form_props's [date_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#date-helpers).
319
+ * Mimics the rails equivalent. Please modify to your liking.
320
+ */
321
+ export const DateField = ({ type: _type, ...rest }: DateFieldProps) => {
322
+ return <FieldBase {...rest} type="date" />;
323
+ };
324
+
325
+ export type DateTimeLocalFieldProps =
326
+ React.InputHTMLAttributes<HTMLInputElement> &
327
+ RailsDateTimeLocalField &
328
+ InputProps;
329
+
330
+ /**
331
+ * A date field component.
332
+ *
333
+ * Designed to work with a payload form_props's [date_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#date-helpers).
334
+ * Mimics the rails equivalent. Please modify to your liking.
335
+ */
336
+ export const DateTimeLocalField = ({
337
+ type: _type,
338
+ ...rest
339
+ }: DateTimeLocalFieldProps) => {
340
+ return <FieldBase {...rest} type="datetime-local" />;
341
+ };
342
+
343
+ export type SearchFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
344
+ RailsSearchField &
345
+ InputProps;
346
+
347
+ /**
348
+ * A search field component.
349
+ *
350
+ * Designed to work with a payload form_props's [search_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#text-helpers).
351
+ * Mimics the rails equivalent. Please modify to your liking.
352
+ */
353
+ export const SearchField = ({ type: _type, ...rest }: SearchFieldProps) => {
354
+ return <FieldBase {...rest} type="search" />;
355
+ };
356
+
357
+ export type TelFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
358
+ RailsTelField &
359
+ InputProps;
360
+
361
+ /**
362
+ * A tel field component.
363
+ *
364
+ * Designed to work with a payload form_props's [tel_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#text-helpers).
365
+ * Mimics the rails equivalent. Please modify to your liking.
366
+ */
367
+ export const TelField = ({ type: _type, ...rest }: TelFieldProps) => {
368
+ return <FieldBase {...rest} type="tel" />;
369
+ };
370
+
371
+ export type UrlFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
372
+ RailsUrlField &
373
+ InputProps;
374
+
375
+ /**
376
+ * A url field component.
377
+ *
378
+ * Designed to work with a payload form_props's [tel_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#text-helpers).
379
+ * Mimics the rails equivalent. Please modify to your liking.
380
+ */
381
+ export const UrlField = ({ type: _type, ...rest }: UrlFieldProps) => {
382
+ return <FieldBase {...rest} type="url" />;
383
+ };
384
+
385
+ export type MonthFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
386
+ RailsMonthField &
387
+ InputProps;
388
+
389
+ /**
390
+ * A month field component.
391
+ *
392
+ * Designed to work with a payload form_props's [month_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#date-helpers).
393
+ * Mimics the rails equivalent. Please modify to your liking.
394
+ */
395
+ export const MonthField = ({ type: _type, ...rest }: MonthFieldProps) => {
396
+ return <FieldBase {...rest} type="month" />;
397
+ };
398
+
399
+ export type TimeFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
400
+ RailsTimeField &
401
+ InputProps;
402
+
403
+ /**
404
+ * A month field component.
405
+ *
406
+ * Designed to work with a payload form_props's [month_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#date-helpers).
407
+ * Mimics the rails equivalent. Please modify to your liking.
408
+ */
409
+ export const TimeField = ({ type: _type, ...rest }: TimeFieldProps) => {
410
+ return <FieldBase {...rest} type="time" />;
411
+ };
412
+
413
+ export type NumberFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
414
+ RailsNumberField &
415
+ InputProps;
416
+ /**
417
+ * A number field component.
418
+ *
419
+ * Designed to work with a payload form_props's [month_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#number-helpers).
420
+ * Mimics the rails equivalent. Please modify to your liking.
421
+ */
422
+ export const NumberField = ({ type: _type, ...rest }: NumberFieldProps) => {
423
+ return <FieldBase {...rest} type="number" />;
424
+ };
425
+
426
+ export type RangeFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
427
+ RailsRangeField &
428
+ InputProps;
429
+ /**
430
+ * A range field component.
431
+ *
432
+ * Designed to work with a payload form_props's [range_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#number-helpers).
433
+ * Mimics the rails equivalent. Please modify to your liking.
434
+ */
435
+ export const RangeField = ({ type: _type, ...rest }: RangeFieldProps) => {
436
+ return <FieldBase {...rest} type="range" />;
437
+ };
438
+
439
+ export type PasswordFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
440
+ RailsPasswordField &
441
+ InputProps;
442
+ /**
443
+ * A password field component.
444
+ *
445
+ * Designed to work with a payload form_props's [password_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#text-helpers).
446
+ * Mimics the rails equivalent. Please modify to your liking.
447
+ */
448
+ export const PasswordField = ({ type: _type, ...rest }: PasswordFieldProps) => {
449
+ return <FieldBase {...rest} type="password" />;
450
+ };
451
+
452
+ export type SelectProps = React.SelectHTMLAttributes<HTMLSelectElement> &
453
+ RailsSelect & {
454
+ label?: string;
455
+ errorKey?: string;
456
+ };
457
+ /**
458
+ * A select component.
459
+ *
460
+ * Designed to work with a payload form_props's [select helpers](https://github.com/thoughtbot/form_props?tab=readme-ov-file#select-helpers),
461
+ * [collection_select helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#collection-select), and [grouped_collection_select helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#group-collection-select).
462
+ *
463
+ * Please modify to your liking.
464
+ */
465
+ export const Select = ({
466
+ includeHidden,
467
+ name,
468
+ id,
469
+ children,
470
+ options,
471
+ multiple,
472
+ type: _type,
473
+ ...rest
474
+ }: SelectProps) => {
475
+ const addHidden = includeHidden && multiple;
476
+
477
+ const optionElements = options.map((item) => {
478
+ if ("options" in item) {
479
+ return (
480
+ <optgroup label={item.label} key={item.label}>
481
+ {item.options.map((opt) => (
482
+ <option key={opt.label} {...opt} />
483
+ ))}
484
+ </optgroup>
485
+ );
486
+ } else {
487
+ return <option key={item.label} {...item} />;
488
+ }
489
+ });
490
+
491
+ return (
492
+ <>
493
+ {addHidden && (
494
+ <input type="hidden" name={name} value={""} autoComplete="off" />
495
+ )}
496
+ <select name={name} id={id} multiple={multiple} {...rest}>
497
+ {children}
498
+ {optionElements}
499
+ </select>
500
+ </>
501
+ );
502
+ };
503
+
504
+ export type TextAreaProps = React.InputHTMLAttributes<HTMLTextAreaElement> &
505
+ RailsTextArea &
506
+ InputProps;
507
+ /**
508
+ * A text area component.
509
+ *
510
+ * Designed to work with a payload form_props's text_area helper.
511
+ * Mimics the rails equivalent. Please modify to your liking.
512
+ */
513
+ export const TextArea = ({ type: _type, errorKey, ...rest }: TextAreaProps) => {
514
+ const { label } = rest;
515
+
516
+ return (
517
+ <FieldBase label={label} errorKey={errorKey} id={rest.id}>
518
+ <textarea {...rest} />
519
+ </FieldBase>
520
+ );
521
+ };
522
+
523
+ export type FileFieldProps = React.InputHTMLAttributes<HTMLInputElement> &
524
+ RailsFileField &
525
+ InputProps;
526
+
527
+ /**
528
+ * A file field component.
529
+ *
530
+ * Designed to work with a payload form_props's [file_field helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#text-helpers).
531
+ * Mimics the rails equivalent. Please modify to your liking.
532
+ */
533
+ export const FileField = ({ type: _type, ...rest }: FileFieldProps) => {
534
+ return <FieldBase {...rest} type="file" />;
535
+ };
536
+
537
+ export type SubmitButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
538
+ RailsSubmitButton
539
+ /**
540
+ * A SubmitButton component.
541
+ *
542
+ * Designed to work with a payload form_props's [submit helper](https://github.com/thoughtbot/form_props?tab=readme-ov-file#form-helpers).
543
+ * Mimics the rails equivalent. Please modify to your liking.
544
+ */
545
+ export const SubmitButton = ({ type: _type, text, ...rest }: SubmitButtonProps) => {
546
+ return <button {...rest} type="submit"> {text} </button>
547
+ };
@@ -0,0 +1,16 @@
1
+ import React, {ReactNode} from 'react'
2
+ import { useAppSelector } from '@javascript/store'
3
+
4
+ export const Layout = ({children}: {children: ReactNode}) => {
5
+ const flash = useAppSelector((state) => state.flash)
6
+
7
+ return (
8
+ <div>
9
+ {flash.success && <p>{flash.success}</p>}
10
+ {flash.notice && <p>{flash.notice}</p>}
11
+ {flash.error && <p>{flash.error}</p>}
12
+
13
+ {children}
14
+ </div>
15
+ )
16
+ }
@@ -0,0 +1,34 @@
1
+ // import your page component #todo fix output of new lines
2
+ // e.g import PostsEdit from '../views/posts/edit'
3
+
4
+ // Mapping between your props template to Component, you must add to this
5
+ // to register any new page level component you create. If you are using the
6
+ // scaffold, it will auto append the identifers for you.
7
+ //
8
+ // For example:
9
+ //
10
+ // const pageIdentifierToPageComponent = {
11
+ // 'posts/new': PostNew
12
+ // };
13
+ //
14
+ //
15
+ // If you are using a build tool that supports globbing, you can automatically
16
+ // populate `pageIdentiferToPageComponent`. For example, if you are using vite,
17
+ // you can use the following snippet instead of manually importing.
18
+ //
19
+ // ```
20
+ // const pageIdentifierToPageComponent = {}
21
+ // const pages = import.meta.glob('../views/**/*.tsx', {eager: true})
22
+ //
23
+ // for (const key in pages) {
24
+ // if (pages.hasOwnProperty(key)) {
25
+ // const identifier = key.replace("../views/", "").split('.')[0];
26
+ // pageIdentifierToPageComponent[identifier] = pages[key].default;
27
+ // }
28
+ // }
29
+ // ```
30
+ //
31
+ const pageIdentifierToPageComponent = {
32
+ };
33
+
34
+ export { pageIdentifierToPageComponent }
@@ -0,0 +1,34 @@
1
+ import { configureStore } from "@reduxjs/toolkit";
2
+ import { useDispatch, useSelector, useStore } from "react-redux";
3
+ import { flashSlice } from "./slices/flash";
4
+ import {
5
+ beforeVisit,
6
+ beforeFetch,
7
+ beforeRemote,
8
+ rootReducer,
9
+ } from "@thoughtbot/superglue";
10
+
11
+ const { pages, superglue } = rootReducer;
12
+
13
+ export const store = configureStore({
14
+ devTools: process.env.NODE_ENV !== "production",
15
+ middleware: (getDefaultMiddleware) =>
16
+ getDefaultMiddleware({
17
+ serializableCheck: {
18
+ ignoredActions: [beforeFetch.type, beforeVisit.type, beforeRemote.type],
19
+ },
20
+ }),
21
+ reducer: {
22
+ superglue,
23
+ pages,
24
+ flash: flashSlice.reducer,
25
+ },
26
+ });
27
+
28
+ export type AppDispatch = typeof store.dispatch;
29
+ export type RootState = ReturnType<typeof store.getState>;
30
+ export type AppStore = typeof store;
31
+
32
+ export const useAppDispatch = useDispatch.withTypes<AppDispatch>();
33
+ export const useAppSelector = useSelector.withTypes<RootState>();
34
+ export const useAppStore = useStore.withTypes<AppStore>();
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "removeComments": true,
4
+ "isolatedModules": true,
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "strictPropertyInitialization": false,
8
+ "noUnusedLocals": true,
9
+ "noUnusedParameters": true,
10
+ "jsx": "react",
11
+ "allowJs": false,
12
+ "target": "ES2021",
13
+ "allowSyntheticDefaultImports": true,
14
+ "esModuleInterop": true,
15
+ "noEmit": true,
16
+ "baseUrl": ".", // Usually the root of your project
17
+ "paths": {
18
+ "@javascript/*": ["app/javascript/*"],
19
+ "@views/*": ["app/views/*"]
20
+ },
21
+ "types": ["node"]
22
+ },
23
+ "include": [
24
+ "app/javascript/**/*",
25
+ "app/views/**/*"
26
+ ],
27
+ }
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/rails/resource/resource_generator"
4
+
5
+ module Superglue
6
+ module Generators
7
+ class ScaffoldGenerator < Rails::Generators::ResourceGenerator # :nodoc:
8
+ remove_hook_for :resource_controller
9
+ remove_class_option :actions
10
+
11
+ class_option :resource_route, type: :boolean
12
+
13
+ hook_for :scaffold_controller, required: true
14
+ end
15
+ end
16
+ end