@tsed/react-formio 3.0.0-alpha.10 → 3.0.0-alpha.11

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 (115) hide show
  1. package/dist/hooks/keyboard.constants.d.ts +38 -0
  2. package/dist/hooks/keyboard.constants.js +7 -0
  3. package/dist/hooks/keyboard.constants.js.map +1 -0
  4. package/dist/hooks/useKeyboardControls.d.ts +12 -0
  5. package/dist/hooks/useKeyboardControls.js +35 -0
  6. package/dist/hooks/useKeyboardControls.js.map +1 -0
  7. package/dist/interfaces/Operation.d.ts +12 -2
  8. package/dist/molecules/button/Button.d.ts +18 -5
  9. package/dist/molecules/button/Button.js +29 -30
  10. package/dist/molecules/button/Button.js.map +1 -1
  11. package/dist/molecules/card/Card.js +7 -5
  12. package/dist/molecules/card/Card.js.map +1 -1
  13. package/dist/molecules/forms/input-tags/InputTags.js +14 -14
  14. package/dist/molecules/forms/input-tags/InputTags.js.map +1 -1
  15. package/dist/molecules/table/Table.d.ts +11 -3
  16. package/dist/molecules/table/Table.js +8 -3
  17. package/dist/molecules/table/Table.js.map +1 -1
  18. package/dist/molecules/table/components/DefaultCellOperations.d.ts +12 -4
  19. package/dist/molecules/table/components/DefaultCellOperations.js +12 -6
  20. package/dist/molecules/table/components/DefaultCellOperations.js.map +1 -1
  21. package/dist/molecules/table/components/DefaultOperationButton.d.ts +12 -4
  22. package/dist/molecules/table/components/DefaultOperationButton.js.map +1 -1
  23. package/dist/molecules/table/hooks/useTable.d.ts +12 -4
  24. package/dist/molecules/table/hooks/useTable.js.map +1 -1
  25. package/dist/molecules/tabs/Tab.d.ts +13 -0
  26. package/dist/molecules/tabs/Tab.js +67 -0
  27. package/dist/molecules/tabs/Tab.js.map +1 -0
  28. package/dist/molecules/tabs/TabList.d.ts +2 -0
  29. package/dist/molecules/tabs/TabList.js +24 -0
  30. package/dist/molecules/tabs/TabList.js.map +1 -0
  31. package/dist/molecules/tabs/TabPanel.d.ts +9 -0
  32. package/dist/molecules/tabs/TabPanel.js +27 -0
  33. package/dist/molecules/tabs/TabPanel.js.map +1 -0
  34. package/dist/molecules/tabs/Tabs.d.ts +4 -16
  35. package/dist/molecules/tabs/Tabs.js +7 -67
  36. package/dist/molecules/tabs/Tabs.js.map +1 -1
  37. package/dist/molecules/tabs/TabsBody.d.ts +1 -0
  38. package/dist/molecules/tabs/TabsBody.js +10 -0
  39. package/dist/molecules/tabs/TabsBody.js.map +1 -0
  40. package/dist/molecules/tabs/TabsLegacy.d.ts +17 -0
  41. package/dist/molecules/tabs/TabsLegacy.js +49 -0
  42. package/dist/molecules/tabs/TabsLegacy.js.map +1 -0
  43. package/dist/molecules/tabs/all.d.ts +5 -0
  44. package/dist/molecules/tabs/all.js +13 -0
  45. package/dist/molecules/tabs/all.js.map +1 -0
  46. package/dist/molecules/tabs/context/TabControl.d.ts +52 -0
  47. package/dist/molecules/tabs/context/TabControl.js +85 -0
  48. package/dist/molecules/tabs/context/TabControl.js.map +1 -0
  49. package/dist/molecules/tabs/hooks/tabControl.d.ts +44 -0
  50. package/dist/molecules/tabs/hooks/tabControl.js +34 -0
  51. package/dist/molecules/tabs/hooks/tabControl.js.map +1 -0
  52. package/dist/organisms/form/actions/FormAction.js.map +1 -0
  53. package/dist/organisms/form/builder/FormEdit.d.ts +3 -1
  54. package/dist/organisms/form/builder/FormEdit.js +38 -35
  55. package/dist/organisms/form/builder/FormEdit.js.map +1 -1
  56. package/dist/organisms/form/builder/useFormEdit.js +17 -17
  57. package/dist/organisms/form/builder/useFormEdit.js.map +1 -1
  58. package/dist/organisms/form/exports/FormExport.d.ts +5 -0
  59. package/dist/organisms/form/exports/FormExport.js +55 -0
  60. package/dist/organisms/form/exports/FormExport.js.map +1 -0
  61. package/dist/organisms/form/preview/FormPreview.d.ts +6 -0
  62. package/dist/organisms/form/preview/FormPreview.js +11 -0
  63. package/dist/organisms/form/preview/FormPreview.js.map +1 -0
  64. package/dist/organisms/table/submissions/SubmissionsTable.d.ts +11 -3
  65. package/dist/organisms/table/submissions/SubmissionsTable.js +4 -1
  66. package/dist/organisms/table/submissions/SubmissionsTable.js.map +1 -1
  67. package/dist/organisms/views/FormViews.d.ts +24 -0
  68. package/dist/organisms/views/FormViews.js +96 -0
  69. package/dist/organisms/views/FormViews.js.map +1 -0
  70. package/package.json +3 -3
  71. package/src/hooks/keyboard.constants.ts +40 -0
  72. package/src/hooks/useKeyboardControls.spec.tsx +208 -0
  73. package/src/hooks/useKeyboardControls.ts +84 -0
  74. package/src/interfaces/Operation.ts +9 -3
  75. package/src/molecules/button/Button.tsx +43 -24
  76. package/src/molecules/card/Card.tsx +4 -0
  77. package/src/molecules/forms/input-tags/InputTags.tsx +1 -1
  78. package/src/molecules/pagination/Pagination.stories.tsx +0 -7
  79. package/src/molecules/table/Table.stories.tsx +34 -1
  80. package/src/molecules/table/Table.tsx +12 -6
  81. package/src/molecules/table/components/DefaultCellOperations.tsx +13 -7
  82. package/src/molecules/table/components/DefaultOperationButton.tsx +5 -4
  83. package/src/molecules/table/hooks/useTable.tsx +5 -5
  84. package/src/molecules/tabs/Tab.tsx +106 -0
  85. package/src/molecules/tabs/TabList.tsx +37 -0
  86. package/src/molecules/tabs/TabPanel.tsx +37 -0
  87. package/src/molecules/tabs/Tabs.spec.tsx +126 -73
  88. package/src/molecules/tabs/Tabs.stories.tsx +298 -65
  89. package/src/molecules/tabs/Tabs.tsx +10 -81
  90. package/src/molecules/tabs/TabsBody.tsx +11 -0
  91. package/src/molecules/tabs/TabsLegacy.stories.tsx +103 -0
  92. package/src/molecules/tabs/TabsLegacy.tsx +84 -0
  93. package/src/molecules/tabs/all.ts +5 -0
  94. package/src/molecules/tabs/context/TabControl.tsx +166 -0
  95. package/src/molecules/tabs/hooks/tabControl.spec.tsx +388 -0
  96. package/src/molecules/tabs/hooks/tabControl.ts +52 -0
  97. package/src/organisms/__fixtures__/form-firstname.fixture.json +1 -0
  98. package/src/organisms/__fixtures__/form.fixture.json +1 -0
  99. package/src/organisms/form/actions/FormAction.stories.tsx +422 -0
  100. package/src/organisms/form/builder/FormEdit.tsx +7 -1
  101. package/src/organisms/form/builder/useFormEdit.ts +1 -1
  102. package/src/organisms/form/exports/FormExport.stories.tsx +71 -0
  103. package/src/organisms/form/exports/FormExport.tsx +58 -0
  104. package/src/organisms/form/preview/FormPreview.stories.tsx +61 -0
  105. package/src/organisms/form/preview/FormPreview.tsx +21 -0
  106. package/src/organisms/table/actions/ActionsTable.stories.tsx +36 -34
  107. package/src/organisms/table/submissions/SubmissionsTable.stories.tsx +103 -57
  108. package/src/organisms/table/submissions/SubmissionsTable.tsx +10 -4
  109. package/src/organisms/views/FormViews.stories.tsx +224 -0
  110. package/src/organisms/views/FormViews.tsx +146 -0
  111. package/dist/organisms/form/action/FormAction.js.map +0 -1
  112. package/src/organisms/form/action/FormAction.stories.tsx +0 -364
  113. /package/dist/organisms/form/{action → actions}/FormAction.d.ts +0 -0
  114. /package/dist/organisms/form/{action → actions}/FormAction.js +0 -0
  115. /package/src/organisms/form/{action → actions}/FormAction.tsx +0 -0
@@ -0,0 +1,422 @@
1
+ import "../../../molecules/card/Card.js";
2
+ import "../Form.js";
3
+
4
+ import { Meta, StoryObj } from "@storybook/react";
5
+
6
+ import { FormAction } from "./FormAction.js";
7
+
8
+ /**
9
+ * FormAction component displays a form for configuring form action
10
+ *
11
+ * ```tsx
12
+ * import {FormAction} from "@tsed/react-formio/organisms/form/action/FormAction";
13
+ * ```
14
+ */
15
+ export default {
16
+ title: "form/action/FormAction",
17
+ component: FormAction,
18
+ argTypes: {
19
+ actionInfo: {
20
+ description: "Information about the action including defaults and settings form",
21
+ control: "object"
22
+ },
23
+ submission: {
24
+ description: "Submission data to fill the form",
25
+ control: "object"
26
+ },
27
+ onSubmit: {
28
+ action: "onSubmit",
29
+ description: "Callback when the form is submitted"
30
+ },
31
+ options: {
32
+ description: "Form options",
33
+ control: "object"
34
+ }
35
+ },
36
+ parameters: {
37
+ docs: {
38
+ description: {
39
+ component: "Component that displays a form for configuring form actions such as save, email, webhook, etc."
40
+ }
41
+ }
42
+ }
43
+ } satisfies Meta<typeof FormAction>;
44
+
45
+ type Story = StoryObj<typeof FormAction>;
46
+
47
+ /**
48
+ * Basic save action configuration
49
+ */
50
+ export const SaveAction: Story = {
51
+ args: {
52
+ actionInfo: {
53
+ name: "save",
54
+ title: "Save Submission",
55
+ description: "Saves the submission into the database.",
56
+ priority: 10,
57
+ defaults: {
58
+ handler: ["before"],
59
+ method: ["create", "update"],
60
+ priority: 10,
61
+ name: "save",
62
+ title: "Save Submission"
63
+ },
64
+ access: {
65
+ handler: false,
66
+ method: false
67
+ },
68
+ settingsForm: {
69
+ components: [
70
+ {
71
+ type: "hidden",
72
+ input: true,
73
+ key: "priority"
74
+ },
75
+ {
76
+ type: "hidden",
77
+ input: true,
78
+ key: "name"
79
+ },
80
+ {
81
+ type: "textfield",
82
+ input: true,
83
+ label: "Title",
84
+ key: "title"
85
+ },
86
+ {
87
+ type: "fieldset",
88
+ input: false,
89
+ tree: true,
90
+ legend: "Action Settings",
91
+ components: [
92
+ {
93
+ input: false,
94
+ type: "container",
95
+ key: "settings",
96
+ components: [
97
+ {
98
+ type: "resourcefields",
99
+ key: "resource",
100
+ title: "Save submission to",
101
+ placeholder: "This form",
102
+ basePath: "/project/5d0797bc872fc7d140559857/form",
103
+ form: "62b18b10fbbba513555c6c5e",
104
+ required: false
105
+ }
106
+ ]
107
+ }
108
+ ]
109
+ },
110
+ {
111
+ type: "fieldset",
112
+ input: false,
113
+ tree: false,
114
+ key: "conditions",
115
+ legend: "Action Execution",
116
+ components: [
117
+ {
118
+ type: "select",
119
+ input: true,
120
+ key: "handler",
121
+ label: "Handler",
122
+ placeholder: "Select which handler(s) you would like to trigger",
123
+ dataSrc: "json",
124
+ data: {
125
+ json: '[{"name":"before","title":"Before"},{"name":"after","title":"After"}]'
126
+ },
127
+ template: "<span>{{ item.title }}</span>",
128
+ valueProperty: "name",
129
+ multiple: true
130
+ },
131
+ {
132
+ type: "select",
133
+ input: true,
134
+ label: "Methods",
135
+ key: "method",
136
+ placeholder: "Trigger action on method(s)",
137
+ dataSrc: "json",
138
+ data: {
139
+ json: '[{"name":"create","title":"Create"},{"name":"update","title":"Update"},{"name":"read","title":"Read"},{"name":"delete","title":"Delete"},{"name":"index","title":"Index"}]'
140
+ },
141
+ template: "<span>{{ item.title }}</span>",
142
+ valueProperty: "name",
143
+ multiple: true
144
+ }
145
+ ]
146
+ },
147
+ {
148
+ type: "button",
149
+ input: true,
150
+ label: "Save Action",
151
+ key: "submit",
152
+ size: "md",
153
+ action: "submit",
154
+ disableOnInvalid: true,
155
+ theme: "primary"
156
+ }
157
+ ]
158
+ }
159
+ },
160
+ options: { template: "tailwind", iconset: "bx" }
161
+ }
162
+ };
163
+
164
+ /**
165
+ * Email action configuration
166
+ */
167
+ export const EmailAction: Story = {
168
+ args: {
169
+ actionInfo: {
170
+ name: "email",
171
+ title: "Email",
172
+ description: "Sends an email when a form is submitted.",
173
+ priority: 0,
174
+ defaults: {
175
+ handler: ["after"],
176
+ method: ["create"],
177
+ priority: 0,
178
+ name: "email",
179
+ title: "Email"
180
+ },
181
+ access: {
182
+ handler: false,
183
+ method: false
184
+ },
185
+ settingsForm: {
186
+ components: [
187
+ {
188
+ type: "hidden",
189
+ input: true,
190
+ key: "priority"
191
+ },
192
+ {
193
+ type: "hidden",
194
+ input: true,
195
+ key: "name"
196
+ },
197
+ {
198
+ type: "textfield",
199
+ input: true,
200
+ label: "Title",
201
+ key: "title"
202
+ },
203
+ {
204
+ type: "fieldset",
205
+ input: false,
206
+ tree: true,
207
+ legend: "Email Settings",
208
+ components: [
209
+ {
210
+ type: "textfield",
211
+ input: true,
212
+ label: "From",
213
+ key: "from",
214
+ placeholder: "no-reply@example.com",
215
+ defaultValue: "no-reply@example.com",
216
+ multiple: false
217
+ },
218
+ {
219
+ type: "textfield",
220
+ input: true,
221
+ label: "To",
222
+ key: "to",
223
+ placeholder: "user@example.com",
224
+ multiple: true
225
+ },
226
+ {
227
+ type: "textfield",
228
+ input: true,
229
+ label: "Subject",
230
+ key: "subject",
231
+ placeholder: "New submission for {{ form.title }}",
232
+ defaultValue: "New submission for {{ form.title }}"
233
+ },
234
+ {
235
+ type: "textarea",
236
+ input: true,
237
+ label: "Message",
238
+ key: "message",
239
+ placeholder: "{{ submission.data }}",
240
+ defaultValue: "{{ submission.data }}",
241
+ rows: 5
242
+ }
243
+ ]
244
+ },
245
+ {
246
+ type: "fieldset",
247
+ input: false,
248
+ tree: false,
249
+ key: "conditions",
250
+ legend: "Action Execution",
251
+ components: [
252
+ {
253
+ type: "select",
254
+ input: true,
255
+ key: "handler",
256
+ label: "Handler",
257
+ placeholder: "Select which handler(s) you would like to trigger",
258
+ dataSrc: "json",
259
+ data: {
260
+ json: '[{"name":"before","title":"Before"},{"name":"after","title":"After"}]'
261
+ },
262
+ template: "<span>{{ item.title }}</span>",
263
+ valueProperty: "name",
264
+ multiple: true
265
+ },
266
+ {
267
+ type: "select",
268
+ input: true,
269
+ label: "Methods",
270
+ key: "method",
271
+ placeholder: "Trigger action on method(s)",
272
+ dataSrc: "json",
273
+ data: {
274
+ json: '[{"name":"create","title":"Create"},{"name":"update","title":"Update"},{"name":"read","title":"Read"},{"name":"delete","title":"Delete"},{"name":"index","title":"Index"}]'
275
+ },
276
+ template: "<span>{{ item.title }}</span>",
277
+ valueProperty: "name",
278
+ multiple: true
279
+ }
280
+ ]
281
+ },
282
+ {
283
+ type: "button",
284
+ input: true,
285
+ label: "Save Action",
286
+ key: "submit",
287
+ size: "md",
288
+ action: "submit",
289
+ disableOnInvalid: true,
290
+ theme: "primary"
291
+ }
292
+ ]
293
+ }
294
+ },
295
+ options: { template: "tailwind", iconset: "bx" }
296
+ }
297
+ };
298
+
299
+ /**
300
+ * Webhook action configuration
301
+ */
302
+ export const WebhookAction: Story = {
303
+ args: {
304
+ actionInfo: {
305
+ name: "webhook",
306
+ title: "Webhook",
307
+ description: "Sends a submission to a URL.",
308
+ priority: 0,
309
+ defaults: {
310
+ handler: ["after"],
311
+ method: ["create", "update"],
312
+ priority: 0,
313
+ name: "webhook",
314
+ title: "Webhook"
315
+ },
316
+ access: {
317
+ handler: false,
318
+ method: false
319
+ },
320
+ settingsForm: {
321
+ components: [
322
+ {
323
+ type: "hidden",
324
+ input: true,
325
+ key: "priority"
326
+ },
327
+ {
328
+ type: "hidden",
329
+ input: true,
330
+ key: "name"
331
+ },
332
+ {
333
+ type: "textfield",
334
+ input: true,
335
+ label: "Title",
336
+ key: "title"
337
+ },
338
+ {
339
+ type: "fieldset",
340
+ input: false,
341
+ tree: true,
342
+ legend: "Webhook Settings",
343
+ components: [
344
+ {
345
+ type: "textfield",
346
+ input: true,
347
+ label: "URL",
348
+ key: "url",
349
+ placeholder: "https://example.com/webhook",
350
+ multiple: false
351
+ },
352
+ {
353
+ type: "select",
354
+ input: true,
355
+ label: "Method",
356
+ key: "webhookMethod",
357
+ placeholder: "Select HTTP method",
358
+ dataSrc: "values",
359
+ data: {
360
+ values: [
361
+ { label: "POST", value: "post" },
362
+ { label: "PUT", value: "put" },
363
+ { label: "PATCH", value: "patch" }
364
+ ]
365
+ },
366
+ defaultValue: "post"
367
+ }
368
+ ]
369
+ },
370
+ {
371
+ type: "fieldset",
372
+ input: false,
373
+ tree: false,
374
+ key: "conditions",
375
+ legend: "Action Execution",
376
+ components: [
377
+ {
378
+ type: "select",
379
+ input: true,
380
+ key: "handler",
381
+ label: "Handler",
382
+ placeholder: "Select which handler(s) you would like to trigger",
383
+ dataSrc: "json",
384
+ data: {
385
+ json: '[{"name":"before","title":"Before"},{"name":"after","title":"After"}]'
386
+ },
387
+ template: "<span>{{ item.title }}</span>",
388
+ valueProperty: "name",
389
+ multiple: true
390
+ },
391
+ {
392
+ type: "select",
393
+ input: true,
394
+ label: "Methods",
395
+ key: "method",
396
+ placeholder: "Trigger action on method(s)",
397
+ dataSrc: "json",
398
+ data: {
399
+ json: '[{"name":"create","title":"Create"},{"name":"update","title":"Update"},{"name":"read","title":"Read"},{"name":"delete","title":"Delete"},{"name":"index","title":"Index"}]'
400
+ },
401
+ template: "<span>{{ item.title }}</span>",
402
+ valueProperty: "name",
403
+ multiple: true
404
+ }
405
+ ]
406
+ },
407
+ {
408
+ type: "button",
409
+ input: true,
410
+ label: "Save Action",
411
+ key: "submit",
412
+ size: "md",
413
+ action: "submit",
414
+ disableOnInvalid: true,
415
+ theme: "primary"
416
+ }
417
+ ]
418
+ }
419
+ },
420
+ options: { template: "tailwind", iconset: "bx" }
421
+ }
422
+ };
@@ -1,3 +1,5 @@
1
+ import classnames from "classnames";
2
+
1
3
  import type { FormOptions } from "../../../interfaces";
2
4
  import { getComponent } from "../../../registries/components";
3
5
  import { FormBuilder as DefaultFormBuilder } from "./FormBuilder";
@@ -9,6 +11,8 @@ import { useFormEdit, UseFormEditHookProps } from "./useFormEdit";
9
11
  export interface FormEditProps extends UseFormEditHookProps, FormBuilderEvents {
10
12
  options?: FormOptions;
11
13
  layout?: "html5" | "choicesjs" | "react";
14
+ className?: string;
15
+ style?: React.CSSProperties;
12
16
  }
13
17
 
14
18
  export function FormEdit({
@@ -18,6 +22,8 @@ export function FormEdit({
18
22
  enableTags,
19
23
  onSubmit: initialOnSubmit,
20
24
  onCopy: initialOnCopy,
25
+ className,
26
+ style,
21
27
  ...props
22
28
  }: FormEditProps) {
23
29
  const { form, isValid, setChange, hasRedo, hasChanged, hasUndo, redo, undo, reset, onSubmit, onCopy } = useFormEdit({
@@ -35,7 +41,7 @@ export function FormEdit({
35
41
  const FormEditCTAs = getComponent<typeof DefaultFormEditCTAs>("FormEditCTAs");
36
42
 
37
43
  return (
38
- <div className='form-edit-container'>
44
+ <div className={classnames("form-edit-container", className)} style={style}>
39
45
  <div className='form-edit'>
40
46
  <FormParameters
41
47
  enableTags={enableTags}
@@ -28,7 +28,7 @@ export function useFormEdit(props: UseFormEditHookProps) {
28
28
  };
29
29
 
30
30
  useEffect(() => {
31
- if (props.form && (current._id !== props.form._id || current.modified !== props.form.modified)) {
31
+ if (props.form && (current?._id !== props.form._id || current.modified !== props.form.modified)) {
32
32
  dispatchFormAction({ type: "replaceForm", value: props.form });
33
33
  }
34
34
  }, [props.form]);
@@ -0,0 +1,71 @@
1
+ import "../../../molecules/card/Card.js";
2
+ import "../../../atoms/icon/Icon.js";
3
+
4
+ import { Meta, StoryObj } from "@storybook/react";
5
+
6
+ import { FormExport } from "./FormExport.js";
7
+
8
+ /**
9
+ * FormExport component displays options to export form schema and submissions
10
+ */
11
+ export default {
12
+ title: "form/export/FormExport",
13
+ component: FormExport,
14
+ argTypes: {
15
+ i18n: {
16
+ description: "Internationalization function"
17
+ },
18
+ onClick: {
19
+ action: "clicked",
20
+ description: "Callback when an export button is clicked"
21
+ }
22
+ },
23
+ parameters: {
24
+ docs: {
25
+ description: {
26
+ component: "Component that displays options to export form schema as JSON and form submissions as JSON or CSV."
27
+ }
28
+ }
29
+ }
30
+ } satisfies Meta<typeof FormExport>;
31
+
32
+ type Story = StoryObj<typeof FormExport>;
33
+
34
+ /**
35
+ * Default view with form type set to "form"
36
+ */
37
+ export const Usage: Story = {
38
+ args: {
39
+ i18n: (key: string) => key,
40
+ onClick: (action: string, format: string) => console.log(`Action: ${action}, Format: ${format}`)
41
+ }
42
+ };
43
+
44
+ /**
45
+ * View with form type set to "resource"
46
+ */
47
+ export const Resource: Story = {
48
+ args: {
49
+ i18n: (key: string) => key,
50
+ onClick: (action: string, format: string) => console.log(`Action: ${action}, Format: ${format}`)
51
+ }
52
+ };
53
+
54
+ /**
55
+ * View with custom i18n function
56
+ */
57
+ export const Translated: Story = {
58
+ args: {
59
+ i18n: (key: string) => {
60
+ const translations: Record<string, string> = {
61
+ "Export schema": "Exporter le schéma",
62
+ "Export the formIO schema:": "Exporter le schéma formIO :",
63
+ Json: "Json",
64
+ Csv: "Csv",
65
+ "Export form submissions": "Exporter les soumissions du formulaire"
66
+ };
67
+ return translations[key] || key;
68
+ },
69
+ onClick: (action: string, format: string) => console.log(`Action: ${action}, Format: ${format}`)
70
+ }
71
+ };
@@ -0,0 +1,58 @@
1
+ import { Icon } from "../../../atoms/icon/Icon.js";
2
+ import type { Card } from "../../../molecules/card/Card.js";
3
+ import { getComponent } from "../../../registries/components.js";
4
+
5
+ export interface FormExportProps {
6
+ i18n?: (key: string) => string;
7
+ onClick?: (action: "export:form" | "export:submissions", format: "json" | "csv") => void;
8
+ }
9
+
10
+ export function FormExport({ i18n = (f: string) => f, onClick }: FormExportProps) {
11
+ const FCard = getComponent<typeof Card>("Card");
12
+
13
+ return (
14
+ <div>
15
+ <div className={"flex gap-3"}>
16
+ <div className={"sm:w-1/2"}>
17
+ <FCard
18
+ label={
19
+ (
20
+ <span className={"flex items-center"}>
21
+ <Icon name={"detail"} className={"mr-1 text-secondary"} /> {i18n(`Export schema`)}
22
+ </span>
23
+ ) as any
24
+ }
25
+ >
26
+ <p className={"mb-5"}>{i18n("Export the formIO schema:")}</p>
27
+ <div className={"flex items-center justify-center"}>
28
+ <button className={"btn btn-primary"} onClick={() => onClick?.("export:form", "json")}>
29
+ <Icon name={"code"} className={"mr-1"} /> {i18n(`Json`)}
30
+ </button>
31
+ </div>
32
+ </FCard>
33
+ </div>
34
+ <div className={"sm:w-1/2"}>
35
+ <FCard
36
+ label={
37
+ (
38
+ <span className={"flex items-center"}>
39
+ <Icon name={"data"} className={"mr-1 text-secondary"} /> {i18n(`Export submissions`)}
40
+ </span>
41
+ ) as any
42
+ }
43
+ >
44
+ <p className={"mb-5"}>{i18n("Export all submission as JSON or CSV:")}</p>
45
+ <div className={"flex items-center justify-center"}>
46
+ <button className={"btn btn-primary mr-4"} onClick={() => onClick?.("export:submissions", "json")}>
47
+ <Icon name={"code"} className={"mr-1"} /> {i18n(`Json`)}
48
+ </button>
49
+ <button className={"btn btn-primary"} onClick={() => onClick?.("export:submissions", "csv")}>
50
+ <Icon name={"spreadsheet"} className={"mr-1"} /> {i18n(`Csv`)}
51
+ </button>
52
+ </div>
53
+ </FCard>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ );
58
+ }
@@ -0,0 +1,61 @@
1
+ import "../../../molecules/card/Card.js";
2
+ import "../Form.js";
3
+
4
+ import { Meta, StoryObj } from "@storybook/react";
5
+
6
+ import formFirstname from "../../__fixtures__/form-firstname.fixture.json";
7
+ import { FormPreview } from "./FormPreview.js";
8
+
9
+ /**
10
+ * FormPreview component displays a form preview inside a card with a background
11
+ */
12
+ export default {
13
+ title: "form/preview/FormPreview",
14
+ component: FormPreview,
15
+ argTypes: {
16
+ form: {
17
+ description: "The form object to preview",
18
+ control: "object"
19
+ },
20
+ i18n: {
21
+ description: "Internationalization function"
22
+ }
23
+ },
24
+ parameters: {
25
+ docs: {
26
+ description: {
27
+ component: "Component that displays a form preview inside a card with a background."
28
+ }
29
+ }
30
+ }
31
+ } satisfies Meta<typeof FormPreview>;
32
+
33
+ type Story = StoryObj<typeof FormPreview>;
34
+
35
+ /**
36
+ * Basic form preview with a simple form
37
+ */
38
+ export const Usage: Story = {
39
+ args: {
40
+ form: formFirstname as any,
41
+ i18n: (key: string) => key
42
+ }
43
+ };
44
+
45
+ /**
46
+ * Form preview with custom translations
47
+ */
48
+ export const Translated: Story = {
49
+ args: {
50
+ form: formFirstname as any,
51
+ i18n: (key: string) => {
52
+ const translations: Record<string, string> = {
53
+ "Form with First Name": "Formulaire avec prénom",
54
+ "First name": "Prénom",
55
+ "Last name": "Nom de famille",
56
+ Submit: "Soumettre"
57
+ };
58
+ return translations[key] || key;
59
+ }
60
+ }
61
+ };
@@ -0,0 +1,21 @@
1
+ import type { FormType } from "../../../interfaces/index.js";
2
+ import type { Card } from "../../../molecules/card/Card.js";
3
+ import { getComponent } from "../../../registries/components.js";
4
+ import { Form } from "../Form.js";
5
+
6
+ export interface FormPreviewProps {
7
+ form: FormType;
8
+ i18n?: (key: string) => string;
9
+ }
10
+
11
+ export function FormPreview({ form, i18n = (f) => f }: FormPreviewProps) {
12
+ const FCard = getComponent<typeof Card>("Card");
13
+
14
+ return (
15
+ <div className='p-10 bg-gray-500'>
16
+ <FCard label={i18n(form.title || "")} className={"shadow"}>
17
+ <Form form={form} options={{ i18n }} />
18
+ </FCard>
19
+ </div>
20
+ );
21
+ }