@3t-transform/threeteeui 0.0.9 → 0.0.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.
- package/dist/cjs/{index-8a4cb9bc.js → index-bf39be87.js} +41 -0
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/tttx-button.cjs.entry.js +2 -2
- package/dist/cjs/tttx-checkbox.cjs.entry.js +3 -3
- package/dist/cjs/tttx-form.cjs.entry.js +169 -41
- package/dist/cjs/tttx-icon.cjs.entry.js +2 -2
- package/dist/cjs/tttx-loading-spinner.cjs.entry.js +26 -0
- package/dist/cjs/tttx-popover-content.cjs.entry.js +2 -2
- package/dist/cjs/tttx-standalone-input.cjs.entry.js +134 -0
- package/dist/cjs/tttx.cjs.js +2 -2
- package/dist/collection/collection-manifest.json +3 -2
- package/dist/collection/components/atoms/tttx-button/tttx-button.css +1 -0
- package/dist/collection/components/atoms/tttx-button/tttx-button.stories.js +3 -3
- package/dist/collection/components/atoms/tttx-icon/tttx-icon.css +8 -4
- package/dist/collection/components/atoms/tttx-icon/tttx-icon.stories.js +15 -15
- package/dist/collection/components/atoms/tttx-loading-spinner/tttx-loading-spinner.css +48 -0
- package/dist/collection/components/atoms/tttx-loading-spinner/tttx-loading-spinner.js +66 -0
- package/dist/collection/components/atoms/tttx-loading-spinner/tttx-loading-spinner.stories.js +17 -0
- package/dist/collection/components/atoms/tttx-popover-content/tttx-popover-content.js +1 -1
- package/dist/collection/components/atoms/tttx-popover-content/tttx-popover-content.stories.js +3 -3
- package/dist/collection/components/atoms/ttx-checkbox/tttx-checkbox.css +86 -43
- package/dist/collection/components/atoms/ttx-checkbox/tttx-checkbox.js +1 -1
- package/dist/collection/components/atoms/ttx-checkbox/tttx-checkbox.stories.js +5 -5
- package/dist/collection/components/molecules/tttx-form/tttx-form.css +230 -0
- package/dist/collection/components/molecules/tttx-form/tttx-form.js +195 -55
- package/dist/collection/components/molecules/tttx-form/tttx-form.stories.js +97 -28
- package/dist/collection/components/molecules/{tttx-input/tttx-input.css → tttx-standalone-input/tttx-standalone-input.css} +78 -53
- package/dist/collection/components/molecules/tttx-standalone-input/tttx-standalone-input.js +561 -0
- package/dist/collection/components/molecules/tttx-standalone-input/tttx-standalone-input.stories.js +156 -0
- package/dist/collection/components/palette.stories.js +81 -81
- package/dist/collection/docs/gettingstarted-developer.stories.js +4 -4
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.js +2 -1
- package/dist/components/tttx-button.js +1 -1
- package/dist/components/tttx-checkbox.js +2 -2
- package/dist/components/tttx-form.js +167 -39
- package/dist/components/tttx-icon2.js +1 -1
- package/dist/components/{tttx-input.d.ts → tttx-loading-spinner.d.ts} +4 -4
- package/dist/components/tttx-loading-spinner.js +43 -0
- package/dist/components/tttx-popover-content.js +1 -1
- package/dist/components/tttx-standalone-input.d.ts +11 -0
- package/dist/components/tttx-standalone-input.js +178 -0
- package/dist/esm/{index-9654537d.js → index-63c4d25e.js} +41 -0
- package/dist/esm/loader.js +3 -3
- package/dist/esm/tttx-button.entry.js +2 -2
- package/dist/esm/tttx-checkbox.entry.js +3 -3
- package/dist/esm/tttx-form.entry.js +169 -41
- package/dist/esm/tttx-icon.entry.js +2 -2
- package/dist/esm/tttx-loading-spinner.entry.js +22 -0
- package/dist/esm/tttx-popover-content.entry.js +2 -2
- package/dist/esm/tttx-standalone-input.entry.js +130 -0
- package/dist/esm/tttx.js +3 -3
- package/dist/tttx/{p-3cb692d6.entry.js → p-1a4eb1f3.entry.js} +1 -1
- package/dist/tttx/p-2d54f8aa.entry.js +1 -0
- package/dist/tttx/p-338b3976.entry.js +1 -0
- package/dist/tttx/p-4c57bcbd.entry.js +1 -0
- package/dist/tttx/p-709246f5.entry.js +1 -0
- package/dist/tttx/p-95a29e09.entry.js +1 -0
- package/dist/tttx/{p-1884203f.entry.js → p-ad0c3fe4.entry.js} +1 -1
- package/dist/tttx/p-bec472d8.js +2 -0
- package/dist/tttx/tttx.esm.js +1 -1
- package/dist/types/components/atoms/tttx-loading-spinner/tttx-loading-spinner.d.ts +6 -0
- package/dist/types/components/atoms/tttx-loading-spinner/tttx-loading-spinner.stories.d.ts +17 -0
- package/dist/types/components/molecules/tttx-form/tttx-form.d.ts +14 -7
- package/dist/types/components/molecules/tttx-form/tttx-form.stories.d.ts +1 -8
- package/dist/types/components/molecules/tttx-standalone-input/tttx-standalone-input.d.ts +38 -0
- package/dist/types/components/molecules/tttx-standalone-input/tttx-standalone-input.stories.d.ts +106 -0
- package/dist/types/components.d.ts +73 -31
- package/package.json +67 -65
- package/readme.md +89 -86
- package/dist/cjs/tttx-input.cjs.entry.js +0 -44
- package/dist/collection/components/molecules/tttx-input/tttx-input.js +0 -259
- package/dist/collection/components/molecules/tttx-input/tttx-input.stories.js +0 -106
- package/dist/components/tttx-input.js +0 -77
- package/dist/esm/tttx-input.entry.js +0 -40
- package/dist/tttx/p-8e977b49.entry.js +0 -1
- package/dist/tttx/p-b6cc2780.js +0 -2
- package/dist/tttx/p-beb8e3fc.entry.js +0 -1
- package/dist/tttx/p-ece1c722.entry.js +0 -1
- package/dist/tttx/p-f30a0e84.entry.js +0 -1
- package/dist/types/components/molecules/tttx-input/tttx-input.d.ts +0 -20
- package/dist/types/components/molecules/tttx-input/tttx-input.stories.d.ts +0 -60
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
.material-symbols-rounded {
|
|
2
|
+
font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 24;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.material-symbols-rounded {
|
|
6
|
+
font-family: "Material Symbols Rounded", sans-serif;
|
|
7
|
+
font-weight: 400;
|
|
8
|
+
font-style: normal;
|
|
9
|
+
font-size: 24px;
|
|
10
|
+
line-height: 1;
|
|
11
|
+
letter-spacing: normal;
|
|
12
|
+
text-transform: none;
|
|
13
|
+
display: inline-block;
|
|
14
|
+
white-space: nowrap;
|
|
15
|
+
word-wrap: normal;
|
|
16
|
+
direction: ltr;
|
|
17
|
+
text-rendering: optimizeLegibility;
|
|
18
|
+
-webkit-font-smoothing: antialiased;
|
|
19
|
+
color: #9e9e9e;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.icon-left,
|
|
23
|
+
.icon-right {
|
|
24
|
+
flex-basis: 24px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.icon-left span,
|
|
28
|
+
.icon-right span {
|
|
29
|
+
font-size: 24px;
|
|
30
|
+
line-height: 24px;
|
|
31
|
+
text-align: center;
|
|
32
|
+
display: block;
|
|
33
|
+
width: 24px;
|
|
34
|
+
height: 24px;
|
|
35
|
+
margin-top: 4px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.icon-left span {
|
|
39
|
+
margin-left: 4px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.icon-right span {
|
|
43
|
+
margin-right: 4px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.icon-right {
|
|
47
|
+
margin-top: 5px;
|
|
48
|
+
margin-right: 4px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.icon-left {
|
|
52
|
+
margin-top: 5px;
|
|
53
|
+
margin-left: 4px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.iconleft .input {
|
|
57
|
+
padding-left: 4px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.iconright .input {
|
|
61
|
+
padding-right: 4px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.focused {
|
|
65
|
+
border-color: #1479c6;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.errormsg {
|
|
69
|
+
display: flex;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
align-items: center;
|
|
72
|
+
float: left;
|
|
73
|
+
margin-bottom: 16px;
|
|
74
|
+
box-sizing: border-box;
|
|
75
|
+
background-color: transparent;
|
|
76
|
+
height: 26px;
|
|
77
|
+
font-size: 14px;
|
|
78
|
+
border-radius: none;
|
|
79
|
+
z-index: 2;
|
|
80
|
+
color: #dc0000;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.errormsg .validationicon {
|
|
84
|
+
width: 16px;
|
|
85
|
+
height: 16px;
|
|
86
|
+
font-size: 16px;
|
|
87
|
+
margin-right: 4px;
|
|
88
|
+
vertical-align: middle;
|
|
89
|
+
color: #dc0000;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.danger {
|
|
93
|
+
color: #dc0000;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.optional {
|
|
97
|
+
color: #757575;
|
|
98
|
+
font-weight: normal;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
label.inputBlock {
|
|
102
|
+
display: block;
|
|
103
|
+
position: relative;
|
|
104
|
+
line-height: 21px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
label {
|
|
108
|
+
font-weight: 500;
|
|
109
|
+
font-size: 16px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
input:not([type=submit]) {
|
|
113
|
+
font-family: "Roboto", serif;
|
|
114
|
+
box-sizing: border-box;
|
|
115
|
+
width: 100%;
|
|
116
|
+
height: 36px;
|
|
117
|
+
padding: 0 16px;
|
|
118
|
+
font-size: 16px;
|
|
119
|
+
border: 1px solid #d5d5d5;
|
|
120
|
+
border-radius: 4px;
|
|
121
|
+
margin-top: 4px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* iPhone OS fix */
|
|
125
|
+
input[type=date] {
|
|
126
|
+
background: white;
|
|
127
|
+
display: block;
|
|
128
|
+
min-width: calc(100% - 18px);
|
|
129
|
+
line-height: 37px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
input.invalid:invalid, input.standalone.invalid {
|
|
133
|
+
border: 1px solid #dc0000;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
input ~ .errorBubble {
|
|
137
|
+
min-height: 27px;
|
|
138
|
+
position: relative;
|
|
139
|
+
font-size: 14px;
|
|
140
|
+
font-weight: normal;
|
|
141
|
+
width: 100%;
|
|
142
|
+
font-family: "Roboto", sans-serif;
|
|
143
|
+
color: #dc0000;
|
|
144
|
+
display: flex;
|
|
145
|
+
align-content: center;
|
|
146
|
+
align-items: center;
|
|
147
|
+
justify-items: center;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
input ~ .errorBubble:not(.visible) {
|
|
151
|
+
visibility: hidden;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
input ~ .errorBubble span {
|
|
155
|
+
color: #dc0000;
|
|
156
|
+
font-size: 16px;
|
|
157
|
+
margin-right: 4px;
|
|
158
|
+
height: 16px;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
input.invalid:invalid ~ .errorBubble {
|
|
162
|
+
position: relative;
|
|
163
|
+
font-size: 14px;
|
|
164
|
+
font-weight: normal;
|
|
165
|
+
width: 100%;
|
|
166
|
+
font-family: "Roboto", sans-serif;
|
|
167
|
+
color: #dc0000;
|
|
168
|
+
visibility: visible;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
input:focus {
|
|
172
|
+
border-color: #1479c6;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.button {
|
|
176
|
+
height: 36px;
|
|
177
|
+
padding: 8px 16px;
|
|
178
|
+
margin: 0;
|
|
179
|
+
background: transparent;
|
|
180
|
+
color: #212121;
|
|
181
|
+
border: 1px solid #c8c8c8;
|
|
182
|
+
border-radius: 4px;
|
|
183
|
+
text-transform: uppercase;
|
|
184
|
+
display: flex;
|
|
185
|
+
justify-content: left;
|
|
186
|
+
align-items: center;
|
|
187
|
+
font-size: 14px;
|
|
188
|
+
font-weight: 400;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.button:hover {
|
|
192
|
+
background: #f0f0f0;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.button:active {
|
|
196
|
+
background: #e3e3e3;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.primary-blue {
|
|
200
|
+
background: #1479c6;
|
|
201
|
+
border: 1px solid #1479c6;
|
|
202
|
+
color: white;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.primary-blue:hover {
|
|
206
|
+
background: #1169ba;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.primary-blue:active {
|
|
210
|
+
background: #0951a8;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.secondary-white {
|
|
214
|
+
background: white;
|
|
215
|
+
border: 1px solid #212121;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
:host {
|
|
219
|
+
display: block;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
fieldset {
|
|
223
|
+
margin: 0;
|
|
224
|
+
padding: 0;
|
|
225
|
+
border: none;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
input[type=submit] {
|
|
229
|
+
margin-left: auto;
|
|
230
|
+
}
|
|
@@ -1,60 +1,193 @@
|
|
|
1
|
-
import { h } from '@stencil/core';
|
|
1
|
+
import { h, Host } from '@stencil/core';
|
|
2
2
|
export class TttxForm {
|
|
3
3
|
constructor() {
|
|
4
|
-
this.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
this.dataAttribute = 'form-data';
|
|
16
|
-
this.functionAttribute = 'function-data';
|
|
4
|
+
this.template = document.createElement('template');
|
|
5
|
+
this.formschema = undefined;
|
|
6
|
+
this.submitValue = undefined;
|
|
7
|
+
}
|
|
8
|
+
onFormSchemaChange(newValue) {
|
|
9
|
+
if (typeof newValue === 'string') {
|
|
10
|
+
this._formSchema = JSON.parse(newValue);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
this._formSchema = newValue;
|
|
14
|
+
}
|
|
17
15
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
validityCheck(event) {
|
|
17
|
+
var _a, _b, _c, _d;
|
|
18
|
+
event.preventDefault();
|
|
19
|
+
const target = event.target;
|
|
20
|
+
let hasError = true;
|
|
21
|
+
let errorMessage = '';
|
|
22
|
+
// validity object on HTML5 inputs has the following options
|
|
23
|
+
// badInput
|
|
24
|
+
// customError
|
|
25
|
+
// patternMismatch
|
|
26
|
+
// rangeOverflow
|
|
27
|
+
// rangeUnderflow
|
|
28
|
+
// stepMismatch
|
|
29
|
+
// tooLong
|
|
30
|
+
// tooShort
|
|
31
|
+
// typeMismatch
|
|
32
|
+
// valid
|
|
33
|
+
// valueMissing
|
|
34
|
+
// customErrors can be set with
|
|
35
|
+
// target.setCustomValidity('custom error!');
|
|
36
|
+
// and cleared with
|
|
37
|
+
// target.setCustomValidity('');
|
|
38
|
+
if (target.validity.valueMissing) {
|
|
39
|
+
errorMessage = (_a = target.dataset.required) !== null && _a !== void 0 ? _a : 'This field is required';
|
|
40
|
+
}
|
|
41
|
+
else if (target.validity.patternMismatch) {
|
|
42
|
+
errorMessage = (_b = target.dataset.pattern) !== null && _b !== void 0 ? _b : 'Incorrect format';
|
|
43
|
+
}
|
|
44
|
+
else if (target.validity.badInput) {
|
|
45
|
+
// IE string in a number field
|
|
46
|
+
errorMessage = (_c = target.dataset.badinput) !== null && _c !== void 0 ? _c : 'Wrong input type';
|
|
47
|
+
}
|
|
48
|
+
else if (target.validity.rangeOverflow || target.validity.rangeUnderflow) {
|
|
49
|
+
// IE date or number is above or below value set in min or max tags
|
|
50
|
+
errorMessage = (_d = target.dataset.range) !== null && _d !== void 0 ? _d : 'Invalid value';
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// no error
|
|
54
|
+
hasError = false;
|
|
55
|
+
}
|
|
56
|
+
if (hasError) {
|
|
57
|
+
target.className = 'invalid';
|
|
58
|
+
const errorIcon = document.createElement('span');
|
|
59
|
+
errorIcon.className = 'material-symbols-rounded';
|
|
60
|
+
errorIcon.textContent = 'warning';
|
|
61
|
+
target.parentElement.querySelector('.errorBubble').replaceChildren();
|
|
62
|
+
target.parentElement.querySelector('.errorBubble').append(errorIcon);
|
|
63
|
+
target.parentElement.querySelector('.errorBubble').append(errorMessage);
|
|
25
64
|
}
|
|
26
65
|
else {
|
|
27
|
-
|
|
28
|
-
|
|
66
|
+
target.className = '';
|
|
67
|
+
target.parentElement.querySelector('.errorBubble').replaceChildren();
|
|
29
68
|
}
|
|
30
|
-
return isValid;
|
|
31
69
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
70
|
+
doSubmit(event) {
|
|
71
|
+
event.preventDefault();
|
|
72
|
+
const formData = new FormData(event.target);
|
|
73
|
+
// Key value pair matching the key names given by the JSON schema will be output line by line
|
|
74
|
+
// TODO: Emit an event so external components can handle the resulting form data
|
|
75
|
+
// let output = "";
|
|
76
|
+
// for (var [key, value] of formData.entries()) {
|
|
77
|
+
// output += `${key} -> ${value}\n`;
|
|
78
|
+
// }
|
|
79
|
+
// console.log(output);
|
|
80
|
+
this.submitEvent.emit(formData);
|
|
81
|
+
}
|
|
82
|
+
fieldsetChange(event) {
|
|
83
|
+
console.log(event.target.name + ' has changed');
|
|
84
|
+
// The correct input box will always be the target of the incoming event
|
|
85
|
+
// TODO: Emit an event so external components can change based on form values input
|
|
86
|
+
}
|
|
87
|
+
componentWillLoad() {
|
|
88
|
+
// set proper on initial render
|
|
89
|
+
this.onFormSchemaChange(this.formschema);
|
|
90
|
+
}
|
|
91
|
+
componentWillRender() {
|
|
92
|
+
this.template.content.replaceChildren(); // clear the template to account for a potential re-render scenario
|
|
93
|
+
this.populateFormFromSchema();
|
|
94
|
+
}
|
|
95
|
+
populateFormFromSchema() {
|
|
96
|
+
if (!this._formSchema)
|
|
97
|
+
return;
|
|
98
|
+
const properties = this._formSchema.properties;
|
|
99
|
+
const propertyKeys = Object.keys(properties);
|
|
100
|
+
propertyKeys.forEach(formKey => {
|
|
101
|
+
var _a, _b, _c;
|
|
102
|
+
const formItem = properties[formKey];
|
|
103
|
+
const formProperties = formItem.form;
|
|
104
|
+
const input = document.createElement('input');
|
|
105
|
+
input.name = formKey;
|
|
106
|
+
input.type = formProperties.type;
|
|
107
|
+
input.placeholder = (_a = formProperties.placeholder) !== null && _a !== void 0 ? _a : '';
|
|
108
|
+
input.autocomplete = 'off';
|
|
109
|
+
input.autocapitalize = 'off';
|
|
110
|
+
if (formProperties.validation) {
|
|
111
|
+
const validation = formProperties.validation;
|
|
112
|
+
if (validation.required) {
|
|
113
|
+
input.setAttribute('required', '');
|
|
114
|
+
input.setAttribute('data-required', (_b = validation.required.message) !== null && _b !== void 0 ? _b : '');
|
|
41
115
|
}
|
|
42
|
-
|
|
116
|
+
if (validation.pattern) {
|
|
117
|
+
input.setAttribute('pattern', validation.pattern.pattern);
|
|
118
|
+
input.setAttribute('data-pattern', (_c = validation.pattern.message) !== null && _c !== void 0 ? _c : '');
|
|
119
|
+
}
|
|
120
|
+
if (validation.badInput) {
|
|
121
|
+
input.setAttribute('data-badinput', validation.badInput.message);
|
|
122
|
+
}
|
|
123
|
+
if (validation.minmax) {
|
|
124
|
+
input.setAttribute('min', validation.minmax.min);
|
|
125
|
+
input.setAttribute('max', validation.minmax.max);
|
|
126
|
+
input.setAttribute('data-range', validation.minmax.message);
|
|
127
|
+
}
|
|
128
|
+
if (validation.maxlength) {
|
|
129
|
+
input.setAttribute('maxlength', validation.maxlength);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const errorBubble = document.createElement('div');
|
|
133
|
+
errorBubble.className = 'errorBubble';
|
|
134
|
+
const label = document.createElement('label');
|
|
135
|
+
label.className = 'inputBlock';
|
|
136
|
+
label.innerText = formProperties.label;
|
|
137
|
+
if (!formProperties.validation) {
|
|
138
|
+
const optionalSpan = document.createElement('span');
|
|
139
|
+
optionalSpan.className = 'optional';
|
|
140
|
+
optionalSpan.innerHTML = ' (optional)';
|
|
141
|
+
label.appendChild(optionalSpan);
|
|
142
|
+
}
|
|
143
|
+
label.appendChild(input);
|
|
144
|
+
label.appendChild(errorBubble);
|
|
145
|
+
this.template.content.append(label);
|
|
146
|
+
});
|
|
147
|
+
const submitButton = document.createElement('input');
|
|
148
|
+
submitButton.type = 'submit';
|
|
149
|
+
submitButton.className = 'button primary-blue';
|
|
150
|
+
console.log(this.submitValue);
|
|
151
|
+
submitButton.value = 'Save';
|
|
152
|
+
this.template.content.append(submitButton);
|
|
153
|
+
}
|
|
154
|
+
componentDidRender() {
|
|
155
|
+
if (!this._formSchema)
|
|
156
|
+
return;
|
|
157
|
+
const formItems = this.template.content.cloneNode(true);
|
|
158
|
+
// bind to events here as you can't do it in a template in stencil
|
|
159
|
+
const properties = this._formSchema.properties;
|
|
160
|
+
const propertyKeys = Object.keys(properties);
|
|
161
|
+
propertyKeys.forEach(formKey => {
|
|
162
|
+
formItems.querySelector(`[name=${formKey}]`).oninvalid = this.validityCheck.bind(this);
|
|
163
|
+
formItems.querySelector(`[name=${formKey}]`).onblur = this.validityCheck.bind(this);
|
|
43
164
|
});
|
|
165
|
+
// append to the fieldset
|
|
166
|
+
this.fieldset.appendChild(formItems);
|
|
44
167
|
}
|
|
45
168
|
render() {
|
|
46
|
-
return (h("
|
|
169
|
+
return (h(Host, null, h("form", { onSubmit: this.doSubmit.bind(this) }, h("fieldset", { onChange: this.fieldsetChange, ref: el => (this.fieldset = el) }))));
|
|
47
170
|
}
|
|
48
171
|
static get is() { return "tttx-form"; }
|
|
49
172
|
static get encapsulation() { return "shadow"; }
|
|
173
|
+
static get originalStyleUrls() {
|
|
174
|
+
return {
|
|
175
|
+
"$": ["tttx-form.scss"]
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
static get styleUrls() {
|
|
179
|
+
return {
|
|
180
|
+
"$": ["tttx-form.css"]
|
|
181
|
+
};
|
|
182
|
+
}
|
|
50
183
|
static get properties() {
|
|
51
184
|
return {
|
|
52
|
-
"
|
|
53
|
-
"type": "
|
|
185
|
+
"formschema": {
|
|
186
|
+
"type": "any",
|
|
54
187
|
"mutable": false,
|
|
55
188
|
"complexType": {
|
|
56
|
-
"original": "
|
|
57
|
-
"resolved": "
|
|
189
|
+
"original": "any",
|
|
190
|
+
"resolved": "any",
|
|
58
191
|
"references": {}
|
|
59
192
|
},
|
|
60
193
|
"required": false,
|
|
@@ -63,16 +196,15 @@ export class TttxForm {
|
|
|
63
196
|
"tags": [],
|
|
64
197
|
"text": ""
|
|
65
198
|
},
|
|
66
|
-
"attribute": "
|
|
67
|
-
"reflect": false
|
|
68
|
-
"defaultValue": "'form-data'"
|
|
199
|
+
"attribute": "formschema",
|
|
200
|
+
"reflect": false
|
|
69
201
|
},
|
|
70
|
-
"
|
|
71
|
-
"type": "
|
|
202
|
+
"submitValue": {
|
|
203
|
+
"type": "any",
|
|
72
204
|
"mutable": false,
|
|
73
205
|
"complexType": {
|
|
74
|
-
"original": "
|
|
75
|
-
"resolved": "
|
|
206
|
+
"original": "any",
|
|
207
|
+
"resolved": "any",
|
|
76
208
|
"references": {}
|
|
77
209
|
},
|
|
78
210
|
"required": false,
|
|
@@ -81,16 +213,15 @@ export class TttxForm {
|
|
|
81
213
|
"tags": [],
|
|
82
214
|
"text": ""
|
|
83
215
|
},
|
|
84
|
-
"attribute": "
|
|
85
|
-
"reflect": false
|
|
86
|
-
"defaultValue": "'function-data'"
|
|
216
|
+
"attribute": "submit-value",
|
|
217
|
+
"reflect": false
|
|
87
218
|
}
|
|
88
219
|
};
|
|
89
220
|
}
|
|
90
221
|
static get events() {
|
|
91
222
|
return [{
|
|
92
|
-
"method": "
|
|
93
|
-
"name": "
|
|
223
|
+
"method": "submitEvent",
|
|
224
|
+
"name": "submitEvent",
|
|
94
225
|
"bubbles": true,
|
|
95
226
|
"cancelable": true,
|
|
96
227
|
"composed": true,
|
|
@@ -99,11 +230,20 @@ export class TttxForm {
|
|
|
99
230
|
"text": ""
|
|
100
231
|
},
|
|
101
232
|
"complexType": {
|
|
102
|
-
"original": "
|
|
103
|
-
"resolved": "
|
|
104
|
-
"references": {
|
|
233
|
+
"original": "FormData",
|
|
234
|
+
"resolved": "FormData",
|
|
235
|
+
"references": {
|
|
236
|
+
"FormData": {
|
|
237
|
+
"location": "global"
|
|
238
|
+
}
|
|
239
|
+
}
|
|
105
240
|
}
|
|
106
241
|
}];
|
|
107
242
|
}
|
|
108
|
-
static get
|
|
243
|
+
static get watchers() {
|
|
244
|
+
return [{
|
|
245
|
+
"propName": "formschema",
|
|
246
|
+
"methodName": "onFormSchemaChange"
|
|
247
|
+
}];
|
|
248
|
+
}
|
|
109
249
|
}
|
|
@@ -1,33 +1,102 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
title: 'molecules/
|
|
2
|
+
title: 'molecules/tttx Form',
|
|
3
3
|
component: 'tttx-form',
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
};
|
|
5
|
+
const formSchema = {
|
|
6
|
+
properties: {
|
|
7
|
+
Title: {
|
|
8
|
+
type: 'string',
|
|
9
|
+
format: 'string',
|
|
10
|
+
form: {
|
|
11
|
+
type: 'text',
|
|
12
|
+
placeholder: 'Mr, Mrs, Dr, Hon Rev',
|
|
13
|
+
label: 'Title',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
forename: {
|
|
17
|
+
type: 'string',
|
|
18
|
+
format: 'string',
|
|
19
|
+
form: {
|
|
20
|
+
type: 'text',
|
|
21
|
+
placeholder: 'John',
|
|
22
|
+
label: 'Forename',
|
|
23
|
+
validation: {
|
|
24
|
+
required: {
|
|
25
|
+
message: 'Please enter your forename',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
surname: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
format: 'string',
|
|
33
|
+
form: {
|
|
34
|
+
type: 'text',
|
|
35
|
+
placeholder: 'Doe',
|
|
36
|
+
label: 'Surname',
|
|
37
|
+
validation: {
|
|
38
|
+
required: {
|
|
39
|
+
message: 'Please enter your surname',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
postcode: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
format: 'string',
|
|
47
|
+
form: {
|
|
48
|
+
type: 'text',
|
|
49
|
+
placeholder: 'AB10',
|
|
50
|
+
label: 'Start of postcode',
|
|
51
|
+
validation: {
|
|
52
|
+
required: {
|
|
53
|
+
message: 'Please enter the beginning of your postcode',
|
|
54
|
+
},
|
|
55
|
+
pattern: {
|
|
56
|
+
pattern: '^([A-Za-z][0-9])$|^([A-Za-z][0-9]{2})$|^([A-Za-z]{2}[0-9])$|^([A-Za-z]{2}[0-9]{2})$|^([A-Za-z][0-9][A-Za-z])$|^([A-Za-z]{2}[0-9][A-Za-z])$|^(GIR|BF|BX|XX)$',
|
|
57
|
+
message: 'Please enter the first half of your postcode. EG: ZZ99',
|
|
58
|
+
},
|
|
59
|
+
maxlength: 4,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
age: {
|
|
64
|
+
type: 'number',
|
|
65
|
+
format: 'number',
|
|
66
|
+
form: {
|
|
67
|
+
type: 'number',
|
|
68
|
+
placeholder: '',
|
|
69
|
+
label: 'Age',
|
|
70
|
+
validation: {
|
|
71
|
+
required: {
|
|
72
|
+
message: 'Please enter your age',
|
|
73
|
+
},
|
|
74
|
+
badInput: {
|
|
75
|
+
message: 'Please enter a number',
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
dob: {
|
|
81
|
+
type: 'string',
|
|
82
|
+
format: 'date-time',
|
|
83
|
+
form: {
|
|
84
|
+
type: 'date',
|
|
85
|
+
placeholder: '',
|
|
86
|
+
label: 'Date of birth',
|
|
87
|
+
validation: {
|
|
88
|
+
required: {
|
|
89
|
+
message: 'Please enter your date of birth',
|
|
90
|
+
},
|
|
91
|
+
minmax: {
|
|
92
|
+
min: '1900-01-01',
|
|
93
|
+
max: '2100-12-31',
|
|
94
|
+
message: 'Please enter a date between 1900 and 2100',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
7
98
|
},
|
|
8
99
|
},
|
|
9
100
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<tttx-input label="Email Address" form-data="email" errormsg="Email is required" required showerrormsg></tttx-input>
|
|
13
|
-
<tttx-input label="Password" form-data="password" type="password" errormsg="Enter a password" required showerrormsg></tttx-input>
|
|
14
|
-
<tttx-input label="Repeat Password" form-data="repeatpassword" type="password" errormsg="Repeat your password" required showerrormsg></tttx-input>
|
|
15
|
-
<tttx-checkbox label="Has Signed GDPR" form-data="gdpr" required></tttx-checkbox>
|
|
16
|
-
<tttx-button font-color="font-white" button-style="primary-blue" function-data="submit">Create User</tttx-button>
|
|
17
|
-
</tttx-form>
|
|
18
|
-
`;
|
|
19
|
-
export const LoginTemplate = () => `
|
|
20
|
-
<tttx-form>
|
|
21
|
-
<tttx-input label="Email" form-data="email" errormsg="email is required" required></tttx-input>
|
|
22
|
-
<tttx-input label="Password" form-data="password" type="password" errormsg="password is required" required></tttx-input>
|
|
23
|
-
<tttx-checkbox label="Remember my Password" form-data="rememberpassword" required></tttx-checkbox>
|
|
24
|
-
<tttx-button font-color="font-white" button-style="primary-blue" function-data="submit">Log In</tttx-button>
|
|
25
|
-
</tttx-form>
|
|
26
|
-
`;
|
|
27
|
-
export const TextBoxExample = () => `
|
|
28
|
-
<tttx-form>
|
|
29
|
-
<tttx-text-box form-data="firstname" label="First Name" errormsg="Field is required" required></tttx-text-box>
|
|
30
|
-
<tttx-text-box form-data="lastname" label="Last Name"></tttx-text-box>
|
|
31
|
-
<tttx-button font-color="font-white" button-style="primary-blue" function-data="submit">Submit</tttx-button>
|
|
32
|
-
</tttx-form>
|
|
33
|
-
`;
|
|
101
|
+
const jsonFormSchema = JSON.stringify(formSchema);
|
|
102
|
+
export const ExampleFormFromJSON = () => `<tttx-form formSchema='${jsonFormSchema}'></tttx-form>`;
|