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