@twintag/twintag-form 1.6.2-beta.1 → 1.7.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 (57) hide show
  1. package/.turbo/turbo-build.log +16 -16
  2. package/CHANGELOG.md +241 -221
  3. package/README.md +407 -407
  4. package/dev/index.css +32 -32
  5. package/dev/main.tsx +461 -460
  6. package/dist/common/button.d.ts +0 -1
  7. package/dist/common/form.d.ts +0 -1
  8. package/dist/common/icon.d.ts +0 -1
  9. package/dist/common/input.d.ts +0 -1
  10. package/dist/common/label.d.ts +0 -1
  11. package/dist/common/textarea.d.ts +0 -1
  12. package/dist/components/config.d.ts +0 -1
  13. package/dist/components/containers/accordion.d.ts +1 -2
  14. package/dist/components/containers/category.d.ts +0 -1
  15. package/dist/components/fields/checkbox.d.ts +0 -1
  16. package/dist/components/fields/file.d.ts +0 -1
  17. package/dist/components/fields/input.d.ts +0 -1
  18. package/dist/components/fields/radiogroup.d.ts +0 -1
  19. package/dist/components/fields/submit.d.ts +0 -1
  20. package/dist/components/fields/textarea.d.ts +0 -1
  21. package/dist/components/fields/toggle.d.ts +0 -1
  22. package/dist/components/fields/tri-toggle.d.ts +0 -1
  23. package/dist/components/form.d.ts +0 -1
  24. package/dist/components/input.d.ts +0 -1
  25. package/dist/components/label.d.ts +0 -1
  26. package/dist/components/provider.d.ts +1 -2
  27. package/dist/index.cjs +1 -1
  28. package/dist/index.d.ts +0 -1
  29. package/dist/index.js +1437 -1601
  30. package/dist/types/index.d.ts +0 -1
  31. package/dist/utils/data.d.ts +0 -1
  32. package/dist/utils/style.d.ts +0 -1
  33. package/dist/webcomponent.cjs +1 -1
  34. package/dist/webcomponent.js +1118 -1104
  35. package/lib/common/icon.tsx +2 -1
  36. package/lib/components/config.tsx +1 -0
  37. package/lib/components/containers/accordion.tsx +3 -2
  38. package/lib/components/containers/category.tsx +1 -1
  39. package/lib/components/fields/checkbox.tsx +3 -6
  40. package/lib/components/fields/date-picker.tsx +151 -154
  41. package/lib/components/fields/file.tsx +81 -84
  42. package/lib/components/fields/input.tsx +67 -70
  43. package/lib/components/fields/radiogroup.tsx +3 -6
  44. package/lib/components/fields/submit.tsx +1 -0
  45. package/lib/components/fields/textarea.tsx +69 -72
  46. package/lib/components/fields/toggle.tsx +3 -6
  47. package/lib/components/fields/tri-toggle.tsx +3 -4
  48. package/lib/components/input.tsx +2 -1
  49. package/lib/components/label.tsx +1 -0
  50. package/lib/components/provider.tsx +163 -162
  51. package/lib/components/renderer.tsx +2 -1
  52. package/lib/index.tsx +46 -45
  53. package/lib/types/index.ts +102 -102
  54. package/lib/webcomponent.ts +1 -2
  55. package/package.json +9 -10
  56. package/prettier.config.mjs +1 -17
  57. package/vite.config.ts +2 -1
package/README.md CHANGED
@@ -1,407 +1,407 @@
1
- # **Twintag Form**
2
-
3
- ## **Content**
4
-
5
- - [Introduction](#introduction)
6
- - [Framework Agnostic](#framework-agnostic)
7
- - [Parameters](#parameters)
8
- - [Config](#config)
9
- - [Options](#options)
10
- - [Inputs](#inputs)
11
- - [Options](#input-options)
12
- - [Subtypes](#subtypes)
13
- - [Event Handling](#event-handling)
14
- - [CSS](#css)
15
-
16
- ## **Introduction**
17
-
18
- Twintag Form provides a web component that allows you to create a form based on a JSON object, leaving the actions to the developer.
19
-
20
- ## **Framework Agnostic**
21
-
22
- Twintag Form exposes a web component that can be used in any framework or vanilla JS.
23
-
24
- ```html
25
- <twintag-form options="..." config="[...]"></twintag-form>
26
- ```
27
-
28
- ## **Parameters**
29
-
30
- The form component receives the following parameters:
31
-
32
- | Parameter | Type | Description |
33
- | --------- | -------- | --------------------------------------- |
34
- | `config` | `array` | Array that contains the form structure. |
35
- | `options` | `object` | Options to customize the form |
36
-
37
- ### **Config**
38
-
39
- The `config` object contains the form structure. It is organized by the index of the items, where each item is an `Input` field represented by an object with the following properties:
40
-
41
- | Property | Type | Description |
42
- | --------- | -------- | -------------------------------------------------------------------------------- |
43
- | `type` | `string` | Component type. The subtype is optional as part of the string: `input:<subtype>` |
44
- | `subtype` | `string` | Component subtype |
45
- | `label` | `string` | Field label. |
46
- | `bind` | `string` | Field name. |
47
-
48
- ```json
49
- [
50
- {
51
- "type": "input",
52
- "props": {
53
- "subtype": "simple",
54
- "label": "Email",
55
- "bind": "email"
56
- }
57
- },
58
- {
59
- "type": "input:textarea",
60
- "props": {
61
- "label": "Message",
62
- "bind": "message"
63
- }
64
- },
65
- {
66
- "type": "input",
67
- "props": {
68
- "subtype": "submit",
69
- "label": "Submit"
70
- }
71
- }
72
- ]
73
- ```
74
-
75
- ### **Options**
76
-
77
- Twintag Form provides some options to customize the form:
78
-
79
- | Option | Type | Description |
80
- | ---------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------- |
81
- | `variant` | `default / outline` | Variant of the form. |
82
- | `size` | `base / sm` | Default: `base` (font-size set to 16px). |
83
- | `resetOnSubmit` | `boolean` | If `true`, the form will be reset after submitting. (`false` per default) |
84
- | `defaultValues` | `object` | The properties are the same as the bind values in your config. |
85
- | `acceptFileType` | `string` | Accept file type. ([ref](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/file#accept)) |
86
-
87
- ### **Inputs**
88
-
89
- #### **Input options**
90
-
91
- Each input can be customized with the following optional options:
92
-
93
- | Option | Type | Description |
94
- | --------------- | --------- | ----------------------------------------------------------------------------------------------------------------- |
95
- | `description` | `string` | Description of the input. |
96
- | `error` | `string` | Error message. |
97
- | `placeholder` | `string` | Placeholder of the input. |
98
- | `optionalField` | `boolean` | If `true`, the field will be optional. (`false` per default) |
99
- | `accept` | `string` | Accept file type. ([ref](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/file#accept)) |
100
-
101
- ```json
102
- {
103
- "type": "input",
104
- "props": {
105
- "subtype": "simple",
106
- "label": "Email",
107
- "bind": "email",
108
- "options": {
109
- ...
110
- }
111
- }
112
- }
113
- ```
114
-
115
- ### **Subtypes**
116
-
117
- - Simple
118
-
119
- ```json
120
- {
121
- "type": "input",
122
- "props": {
123
- "subtype": "simple",
124
- "label": "Email",
125
- "bind": "email",
126
- "options": {
127
- "description": "Please enter you email",
128
- "error": "The field is empty."
129
- "placeholder": "Write here...",
130
- "optionalField": false
131
- }
132
- }
133
- }
134
- ```
135
-
136
- - Textarea
137
-
138
- ```json
139
- {
140
- "type": "input",
141
- "props": {
142
- "subtype": "textarea",
143
- "label": "Message",
144
- "bind": "message",
145
- "options": {
146
- "description": "Please enter you message",
147
- "error": "The field is empty."
148
- "placeholder": "Write here...",
149
- "optionalField": false
150
- }
151
- }
152
- }
153
- ```
154
-
155
- - File
156
-
157
- ```json
158
- {
159
- "type": "input",
160
- "props": {
161
- "subtype": "file",
162
- "label": "File",
163
- "bind": "file",
164
- "options": {
165
- "description": "Please upload an image",
166
- "error": "The field is empty.",
167
- "accept": "image/*",
168
- "optionalField": true
169
- }
170
- }
171
- }
172
- ```
173
-
174
- - Checkbox
175
-
176
- ```json
177
- {
178
- "type": "input",
179
- "props": {
180
- "subtype": "checkbox",
181
- "label": "Checkbox",
182
- "bind": "checkbox",
183
- "options": {
184
- "description": "Please enter you email",
185
- "error": "The field is empty."
186
- "optionalField": false
187
- }
188
- }
189
- }
190
- ```
191
-
192
- - Toggle
193
-
194
- ```json
195
- {
196
- "type": "input",
197
- "props": {
198
- "subtype": "toggle",
199
- "label": "Toggle",
200
- "bind": "toggle",
201
- "options": {
202
- "description": "Please enter you email",
203
- "error": "The field is empty."
204
- "optionalField": false
205
- }
206
- }
207
- }
208
- ```
209
-
210
- - Tri-Toggle
211
-
212
- ```json
213
- {
214
- "type": "input",
215
- "props": {
216
- "subtype": "tri-toggle",
217
- "label": "Toggle with 3 states",
218
- "bind": "tri-states",
219
- "options": {
220
- "description": "Please enter you email",
221
- "error": "The field is empty."
222
- "optionalField": false
223
- }
224
- }
225
- }
226
- ```
227
-
228
- - Radiogroup
229
-
230
- ```json
231
- {
232
- "type": "input",
233
- "props": {
234
- "subtype": "radiogroup",
235
- "label": "Radio Group",
236
- "bind": "radiogroup",
237
- "options": {
238
- "description": "Please enter you email",
239
- "error": "The field is empty."
240
- "optionalField": false
241
- }
242
- },
243
- "children": [
244
- {
245
- "type": "item",
246
- "props": {
247
- "label": "First item",
248
- "bind": "first-item"
249
- }
250
- },
251
- ...
252
- ]
253
- }
254
- ```
255
-
256
- - Submit
257
-
258
- ```json
259
- {
260
- "type": "input",
261
- "props": {
262
- "subtype": "submit",
263
- "label": "Submit"
264
- }
265
- }
266
- ```
267
-
268
- - Date picker
269
-
270
- ```json
271
- {
272
- "type": "input",
273
- "props": {
274
- "subtype": "datepicker",
275
- "label": "Pick a date"
276
- }
277
- }
278
- ```
279
-
280
- ## **Containers**
281
-
282
- - Accordion
283
-
284
- ```json
285
- {
286
- "type": "accordion",
287
- "props": {
288
- "defaultValue": "first-item" // optional: default expanded item
289
- },
290
- "children": [
291
- {
292
- "type": "accordion",
293
- "props": {
294
- "subtype": "item",
295
- "value": "first-item", // optional
296
- "label": "Your label",
297
- "icon": "archive-box-x-mark"
298
- },
299
- "children": [
300
- {
301
- "type": "input",
302
- "props": {
303
- "subtype": "simple",
304
- "bind": "first-item"
305
- }
306
- },
307
- ...
308
- ]
309
- },
310
- ...
311
- ]
312
- }
313
- ```
314
-
315
- - Category
316
-
317
- ```json
318
- {
319
- "type": "category",
320
- "props": {
321
- "label": "Category"
322
- },
323
- "children": [
324
- {
325
- "type": "input",
326
- "props": {
327
- "subtype": "simple",
328
- "label": "Your label"
329
- }
330
- },
331
- ...
332
- ]
333
- }
334
- ```
335
-
336
- ## **Event Handling**
337
-
338
- ```html
339
- <twintag-form
340
- id="yourform"
341
- options='{"variant":"beta","resetOnSubmit":true}'
342
- config='[{"type":"input:toggle","label":"Test","bind":"test","options":{"optionalField":true}},{"type":"input:submit","label":"Submit"}]'
343
- ></twintag-form>
344
-
345
- <button id="submit-btn">Submit</button>
346
- <button id="get-values-btn">Submit</button>
347
-
348
- <script>
349
- const form = document.getElementById('yourform');
350
- const submit = document.getElementById('submit-btn');
351
- const getValues = document.getElementById('get-values-btn');
352
-
353
- // You can validate the form outside the component:
354
- submit.addEventListener('click', () => {
355
- const submitEvent = new Event('twintag-form-validate');
356
- form.shadowRoot.querySelector('form').dispatchEvent(submitEvent);
357
- });
358
-
359
- // If there are no errors, the form will emit a custom event with the data on submit
360
- form.addEventListener('twintag-form-valid', (e) => {
361
- console.log(e.detail); // { test: true }
362
- });
363
-
364
- // If there are errors, the form will emit a custom event with the errors
365
- form.addEventListener('twintag-form-invalid', (e) => {
366
- console.log(e.detail); // { test: 'Test is required' }
367
- });
368
-
369
- // You can get the values of the form outside the component:
370
- form.addEventListener('twintag-form-values', (e) => {
371
- console.log(e.detail);
372
- });
373
- getValues.addEventListener('click', () => {
374
- const getValuesEvent = new Event('twintag-form-get_values');
375
- form.shadowRoot.querySelector('form').dispatchEvent(getValuesEvent);
376
- });
377
- </script>
378
- ```
379
-
380
- ## **CSS**
381
-
382
- The form component exposes the following CSS variables:
383
-
384
- | Variable | Description |
385
- | ----------------------- | ----------------------------------------------------------------------------------------- |
386
- | --tf-label | Color used for the inputs `label`. |
387
- | --tf-category | Color used for the `category` labels. |
388
- | | |
389
- | --tf-background | Background color for the input fields. |
390
- | --tf-foreground | Text color for the input fields. |
391
- | | |
392
- | --tf-muted | Used for `toggle` and `tri-toggle` background when value is false. |
393
- | --tf-muted-foreground | Color used for `placeholder` text (inputs) and description text. |
394
- | | |
395
- | --tf-primary | This color complements `primary-foreground`: `submit` button text |
396
- | --tf-primary-foreground | This color is used for, `submit` background, `label` text and input value. |
397
- | | |
398
- | --tf-accent | The accent color is used for `toggle`, `tri-toggle`, `checkbox` and `radiogroup` inputs. |
399
- | --tf-accent-foreground | This color complements `accent` to show contrast between elements: `checkbox` check icon. |
400
- | | |
401
- | --tf-destructive | This color is used for `error` messages and the asterisk to mark a required input. |
402
- | --tf-input | This color is used by the input borders. |
403
- | --tf-ring | This color highlights a focused input. |
404
- | | |
405
- | --tf-radius | This value is used for input rounded corners. |
406
- | | |
407
- | --tf-font | Font family for all the form. |
1
+ # **Twintag Form**
2
+
3
+ ## **Content**
4
+
5
+ - [Introduction](#introduction)
6
+ - [Framework Agnostic](#framework-agnostic)
7
+ - [Parameters](#parameters)
8
+ - [Config](#config)
9
+ - [Options](#options)
10
+ - [Inputs](#inputs)
11
+ - [Options](#input-options)
12
+ - [Subtypes](#subtypes)
13
+ - [Event Handling](#event-handling)
14
+ - [CSS](#css)
15
+
16
+ ## **Introduction**
17
+
18
+ Twintag Form provides a web component that allows you to create a form based on a JSON object, leaving the actions to the developer.
19
+
20
+ ## **Framework Agnostic**
21
+
22
+ Twintag Form exposes a web component that can be used in any framework or vanilla JS.
23
+
24
+ ```html
25
+ <twintag-form options="..." config="[...]"></twintag-form>
26
+ ```
27
+
28
+ ## **Parameters**
29
+
30
+ The form component receives the following parameters:
31
+
32
+ | Parameter | Type | Description |
33
+ | --------- | -------- | --------------------------------------- |
34
+ | `config` | `array` | Array that contains the form structure. |
35
+ | `options` | `object` | Options to customize the form |
36
+
37
+ ### **Config**
38
+
39
+ The `config` object contains the form structure. It is organized by the index of the items, where each item is an `Input` field represented by an object with the following properties:
40
+
41
+ | Property | Type | Description |
42
+ | --------- | -------- | -------------------------------------------------------------------------------- |
43
+ | `type` | `string` | Component type. The subtype is optional as part of the string: `input:<subtype>` |
44
+ | `subtype` | `string` | Component subtype |
45
+ | `label` | `string` | Field label. |
46
+ | `bind` | `string` | Field name. |
47
+
48
+ ```json
49
+ [
50
+ {
51
+ "type": "input",
52
+ "props": {
53
+ "subtype": "simple",
54
+ "label": "Email",
55
+ "bind": "email"
56
+ }
57
+ },
58
+ {
59
+ "type": "input:textarea",
60
+ "props": {
61
+ "label": "Message",
62
+ "bind": "message"
63
+ }
64
+ },
65
+ {
66
+ "type": "input",
67
+ "props": {
68
+ "subtype": "submit",
69
+ "label": "Submit"
70
+ }
71
+ }
72
+ ]
73
+ ```
74
+
75
+ ### **Options**
76
+
77
+ Twintag Form provides some options to customize the form:
78
+
79
+ | Option | Type | Description |
80
+ | ---------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------- |
81
+ | `variant` | `default / outline` | Variant of the form. |
82
+ | `size` | `base / sm` | Default: `base` (font-size set to 16px). |
83
+ | `resetOnSubmit` | `boolean` | If `true`, the form will be reset after submitting. (`false` per default) |
84
+ | `defaultValues` | `object` | The properties are the same as the bind values in your config. |
85
+ | `acceptFileType` | `string` | Accept file type. ([ref](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/file#accept)) |
86
+
87
+ ### **Inputs**
88
+
89
+ #### **Input options**
90
+
91
+ Each input can be customized with the following optional options:
92
+
93
+ | Option | Type | Description |
94
+ | --------------- | --------- | ----------------------------------------------------------------------------------------------------------------- |
95
+ | `description` | `string` | Description of the input. |
96
+ | `error` | `string` | Error message. |
97
+ | `placeholder` | `string` | Placeholder of the input. |
98
+ | `optionalField` | `boolean` | If `true`, the field will be optional. (`false` per default) |
99
+ | `accept` | `string` | Accept file type. ([ref](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/file#accept)) |
100
+
101
+ ```json
102
+ {
103
+ "type": "input",
104
+ "props": {
105
+ "subtype": "simple",
106
+ "label": "Email",
107
+ "bind": "email",
108
+ "options": {
109
+ ...
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ ### **Subtypes**
116
+
117
+ - Simple
118
+
119
+ ```json
120
+ {
121
+ "type": "input",
122
+ "props": {
123
+ "subtype": "simple",
124
+ "label": "Email",
125
+ "bind": "email",
126
+ "options": {
127
+ "description": "Please enter you email",
128
+ "error": "The field is empty."
129
+ "placeholder": "Write here...",
130
+ "optionalField": false
131
+ }
132
+ }
133
+ }
134
+ ```
135
+
136
+ - Textarea
137
+
138
+ ```json
139
+ {
140
+ "type": "input",
141
+ "props": {
142
+ "subtype": "textarea",
143
+ "label": "Message",
144
+ "bind": "message",
145
+ "options": {
146
+ "description": "Please enter you message",
147
+ "error": "The field is empty."
148
+ "placeholder": "Write here...",
149
+ "optionalField": false
150
+ }
151
+ }
152
+ }
153
+ ```
154
+
155
+ - File
156
+
157
+ ```json
158
+ {
159
+ "type": "input",
160
+ "props": {
161
+ "subtype": "file",
162
+ "label": "File",
163
+ "bind": "file",
164
+ "options": {
165
+ "description": "Please upload an image",
166
+ "error": "The field is empty.",
167
+ "accept": "image/*",
168
+ "optionalField": true
169
+ }
170
+ }
171
+ }
172
+ ```
173
+
174
+ - Checkbox
175
+
176
+ ```json
177
+ {
178
+ "type": "input",
179
+ "props": {
180
+ "subtype": "checkbox",
181
+ "label": "Checkbox",
182
+ "bind": "checkbox",
183
+ "options": {
184
+ "description": "Please enter you email",
185
+ "error": "The field is empty."
186
+ "optionalField": false
187
+ }
188
+ }
189
+ }
190
+ ```
191
+
192
+ - Toggle
193
+
194
+ ```json
195
+ {
196
+ "type": "input",
197
+ "props": {
198
+ "subtype": "toggle",
199
+ "label": "Toggle",
200
+ "bind": "toggle",
201
+ "options": {
202
+ "description": "Please enter you email",
203
+ "error": "The field is empty."
204
+ "optionalField": false
205
+ }
206
+ }
207
+ }
208
+ ```
209
+
210
+ - Tri-Toggle
211
+
212
+ ```json
213
+ {
214
+ "type": "input",
215
+ "props": {
216
+ "subtype": "tri-toggle",
217
+ "label": "Toggle with 3 states",
218
+ "bind": "tri-states",
219
+ "options": {
220
+ "description": "Please enter you email",
221
+ "error": "The field is empty."
222
+ "optionalField": false
223
+ }
224
+ }
225
+ }
226
+ ```
227
+
228
+ - Radiogroup
229
+
230
+ ```json
231
+ {
232
+ "type": "input",
233
+ "props": {
234
+ "subtype": "radiogroup",
235
+ "label": "Radio Group",
236
+ "bind": "radiogroup",
237
+ "options": {
238
+ "description": "Please enter you email",
239
+ "error": "The field is empty."
240
+ "optionalField": false
241
+ }
242
+ },
243
+ "children": [
244
+ {
245
+ "type": "item",
246
+ "props": {
247
+ "label": "First item",
248
+ "bind": "first-item"
249
+ }
250
+ },
251
+ ...
252
+ ]
253
+ }
254
+ ```
255
+
256
+ - Submit
257
+
258
+ ```json
259
+ {
260
+ "type": "input",
261
+ "props": {
262
+ "subtype": "submit",
263
+ "label": "Submit"
264
+ }
265
+ }
266
+ ```
267
+
268
+ - Date picker
269
+
270
+ ```json
271
+ {
272
+ "type": "input",
273
+ "props": {
274
+ "subtype": "datepicker",
275
+ "label": "Pick a date"
276
+ }
277
+ }
278
+ ```
279
+
280
+ ## **Containers**
281
+
282
+ - Accordion
283
+
284
+ ```json
285
+ {
286
+ "type": "accordion",
287
+ "props": {
288
+ "defaultValue": "first-item" // optional: default expanded item
289
+ },
290
+ "children": [
291
+ {
292
+ "type": "accordion",
293
+ "props": {
294
+ "subtype": "item",
295
+ "value": "first-item", // optional
296
+ "label": "Your label",
297
+ "icon": "archive-box-x-mark"
298
+ },
299
+ "children": [
300
+ {
301
+ "type": "input",
302
+ "props": {
303
+ "subtype": "simple",
304
+ "bind": "first-item"
305
+ }
306
+ },
307
+ ...
308
+ ]
309
+ },
310
+ ...
311
+ ]
312
+ }
313
+ ```
314
+
315
+ - Category
316
+
317
+ ```json
318
+ {
319
+ "type": "category",
320
+ "props": {
321
+ "label": "Category"
322
+ },
323
+ "children": [
324
+ {
325
+ "type": "input",
326
+ "props": {
327
+ "subtype": "simple",
328
+ "label": "Your label"
329
+ }
330
+ },
331
+ ...
332
+ ]
333
+ }
334
+ ```
335
+
336
+ ## **Event Handling**
337
+
338
+ ```html
339
+ <twintag-form
340
+ id="yourform"
341
+ options='{"variant":"beta","resetOnSubmit":true}'
342
+ config='[{"type":"input:toggle","label":"Test","bind":"test","options":{"optionalField":true}},{"type":"input:submit","label":"Submit"}]'
343
+ ></twintag-form>
344
+
345
+ <button id="submit-btn">Submit</button>
346
+ <button id="get-values-btn">Submit</button>
347
+
348
+ <script>
349
+ const form = document.getElementById('yourform');
350
+ const submit = document.getElementById('submit-btn');
351
+ const getValues = document.getElementById('get-values-btn');
352
+
353
+ // You can validate the form outside the component:
354
+ submit.addEventListener('click', () => {
355
+ const submitEvent = new Event('twintag-form-validate');
356
+ form.shadowRoot.querySelector('form').dispatchEvent(submitEvent);
357
+ });
358
+
359
+ // If there are no errors, the form will emit a custom event with the data on submit
360
+ form.addEventListener('twintag-form-valid', (e) => {
361
+ console.log(e.detail); // { test: true }
362
+ });
363
+
364
+ // If there are errors, the form will emit a custom event with the errors
365
+ form.addEventListener('twintag-form-invalid', (e) => {
366
+ console.log(e.detail); // { test: 'Test is required' }
367
+ });
368
+
369
+ // You can get the values of the form outside the component:
370
+ form.addEventListener('twintag-form-values', (e) => {
371
+ console.log(e.detail);
372
+ });
373
+ getValues.addEventListener('click', () => {
374
+ const getValuesEvent = new Event('twintag-form-get_values');
375
+ form.shadowRoot.querySelector('form').dispatchEvent(getValuesEvent);
376
+ });
377
+ </script>
378
+ ```
379
+
380
+ ## **CSS**
381
+
382
+ The form component exposes the following CSS variables:
383
+
384
+ | Variable | Description |
385
+ | ----------------------- | ----------------------------------------------------------------------------------------- |
386
+ | --tf-label | Color used for the inputs `label`. |
387
+ | --tf-category | Color used for the `category` labels. |
388
+ | | |
389
+ | --tf-background | Background color for the input fields. |
390
+ | --tf-foreground | Text color for the input fields. |
391
+ | | |
392
+ | --tf-muted | Used for `toggle` and `tri-toggle` background when value is false. |
393
+ | --tf-muted-foreground | Color used for `placeholder` text (inputs) and description text. |
394
+ | | |
395
+ | --tf-primary | This color complements `primary-foreground`: `submit` button text |
396
+ | --tf-primary-foreground | This color is used for, `submit` background, `label` text and input value. |
397
+ | | |
398
+ | --tf-accent | The accent color is used for `toggle`, `tri-toggle`, `checkbox` and `radiogroup` inputs. |
399
+ | --tf-accent-foreground | This color complements `accent` to show contrast between elements: `checkbox` check icon. |
400
+ | | |
401
+ | --tf-destructive | This color is used for `error` messages and the asterisk to mark a required input. |
402
+ | --tf-input | This color is used by the input borders. |
403
+ | --tf-ring | This color highlights a focused input. |
404
+ | | |
405
+ | --tf-radius | This value is used for input rounded corners. |
406
+ | | |
407
+ | --tf-font | Font family for all the form. |