@3t-transform/threeteeui 0.0.10 → 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.
Files changed (78) hide show
  1. package/dist/cjs/{index-8a4cb9bc.js → index-bf39be87.js} +41 -0
  2. package/dist/cjs/loader.cjs.js +2 -2
  3. package/dist/cjs/tttx-button.cjs.entry.js +2 -2
  4. package/dist/cjs/tttx-checkbox.cjs.entry.js +3 -3
  5. package/dist/cjs/tttx-form.cjs.entry.js +169 -41
  6. package/dist/cjs/tttx-icon.cjs.entry.js +2 -2
  7. package/dist/cjs/tttx-loading-spinner.cjs.entry.js +4 -4
  8. package/dist/cjs/tttx-popover-content.cjs.entry.js +2 -2
  9. package/dist/cjs/tttx-standalone-input.cjs.entry.js +134 -0
  10. package/dist/cjs/tttx.cjs.js +2 -2
  11. package/dist/collection/collection-manifest.json +2 -2
  12. package/dist/collection/components/atoms/tttx-button/tttx-button.css +1 -0
  13. package/dist/collection/components/atoms/tttx-button/tttx-button.stories.js +3 -3
  14. package/dist/collection/components/atoms/tttx-icon/tttx-icon.css +3 -3
  15. package/dist/collection/components/atoms/tttx-icon/tttx-icon.stories.js +15 -15
  16. package/dist/collection/components/atoms/tttx-loading-spinner/tttx-loading-spinner.css +1 -1
  17. package/dist/collection/components/atoms/tttx-loading-spinner/tttx-loading-spinner.js +2 -2
  18. package/dist/collection/components/atoms/tttx-loading-spinner/tttx-loading-spinner.stories.js +1 -1
  19. package/dist/collection/components/atoms/tttx-popover-content/tttx-popover-content.js +1 -1
  20. package/dist/collection/components/atoms/tttx-popover-content/tttx-popover-content.stories.js +3 -3
  21. package/dist/collection/components/atoms/ttx-checkbox/tttx-checkbox.css +85 -39
  22. package/dist/collection/components/atoms/ttx-checkbox/tttx-checkbox.js +1 -1
  23. package/dist/collection/components/atoms/ttx-checkbox/tttx-checkbox.stories.js +5 -5
  24. package/dist/collection/components/molecules/tttx-form/tttx-form.css +230 -0
  25. package/dist/collection/components/molecules/tttx-form/tttx-form.js +195 -55
  26. package/dist/collection/components/molecules/tttx-form/tttx-form.stories.js +97 -28
  27. package/dist/collection/components/molecules/{tttx-input/tttx-input.css → tttx-standalone-input/tttx-standalone-input.css} +77 -49
  28. package/dist/collection/components/molecules/tttx-standalone-input/tttx-standalone-input.js +561 -0
  29. package/dist/collection/components/molecules/tttx-standalone-input/tttx-standalone-input.stories.js +156 -0
  30. package/dist/collection/components/palette.stories.js +81 -81
  31. package/dist/collection/docs/gettingstarted-developer.stories.js +4 -4
  32. package/dist/components/index.d.ts +1 -1
  33. package/dist/components/index.js +1 -1
  34. package/dist/components/tttx-button.js +1 -1
  35. package/dist/components/tttx-checkbox.js +2 -2
  36. package/dist/components/tttx-form.js +167 -39
  37. package/dist/components/tttx-icon2.js +1 -1
  38. package/dist/components/tttx-loading-spinner.js +3 -3
  39. package/dist/components/tttx-popover-content.js +1 -1
  40. package/dist/components/{tttx-input.d.ts → tttx-standalone-input.d.ts} +4 -4
  41. package/dist/components/tttx-standalone-input.js +178 -0
  42. package/dist/esm/{index-9654537d.js → index-63c4d25e.js} +41 -0
  43. package/dist/esm/loader.js +3 -3
  44. package/dist/esm/tttx-button.entry.js +2 -2
  45. package/dist/esm/tttx-checkbox.entry.js +3 -3
  46. package/dist/esm/tttx-form.entry.js +169 -41
  47. package/dist/esm/tttx-icon.entry.js +2 -2
  48. package/dist/esm/tttx-loading-spinner.entry.js +4 -4
  49. package/dist/esm/tttx-popover-content.entry.js +2 -2
  50. package/dist/esm/tttx-standalone-input.entry.js +130 -0
  51. package/dist/esm/tttx.js +3 -3
  52. package/dist/tttx/{p-3cb692d6.entry.js → p-1a4eb1f3.entry.js} +1 -1
  53. package/dist/tttx/p-2d54f8aa.entry.js +1 -0
  54. package/dist/tttx/p-338b3976.entry.js +1 -0
  55. package/dist/tttx/{p-674e2f18.entry.js → p-4c57bcbd.entry.js} +1 -1
  56. package/dist/tttx/{p-f4855113.entry.js → p-709246f5.entry.js} +1 -1
  57. package/dist/tttx/p-95a29e09.entry.js +1 -0
  58. package/dist/tttx/{p-1884203f.entry.js → p-ad0c3fe4.entry.js} +1 -1
  59. package/dist/tttx/p-bec472d8.js +2 -0
  60. package/dist/tttx/tttx.esm.js +1 -1
  61. package/dist/types/components/molecules/tttx-form/tttx-form.d.ts +14 -7
  62. package/dist/types/components/molecules/tttx-form/tttx-form.stories.d.ts +1 -8
  63. package/dist/types/components/molecules/tttx-standalone-input/tttx-standalone-input.d.ts +38 -0
  64. package/dist/types/components/molecules/tttx-standalone-input/tttx-standalone-input.stories.d.ts +106 -0
  65. package/dist/types/components.d.ts +66 -41
  66. package/package.json +67 -65
  67. package/readme.md +89 -86
  68. package/dist/cjs/tttx-input.cjs.entry.js +0 -44
  69. package/dist/collection/components/molecules/tttx-input/tttx-input.js +0 -259
  70. package/dist/collection/components/molecules/tttx-input/tttx-input.stories.js +0 -106
  71. package/dist/components/tttx-input.js +0 -77
  72. package/dist/esm/tttx-input.entry.js +0 -40
  73. package/dist/tttx/p-317b13d3.entry.js +0 -1
  74. package/dist/tttx/p-3cd7ad04.entry.js +0 -1
  75. package/dist/tttx/p-b6cc2780.js +0 -2
  76. package/dist/tttx/p-f30a0e84.entry.js +0 -1
  77. package/dist/types/components/molecules/tttx-input/tttx-input.d.ts +0 -20
  78. package/dist/types/components/molecules/tttx-input/tttx-input.stories.d.ts +0 -60
@@ -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.fetchFormData = () => {
5
- let validForm = true;
6
- const formData = {};
7
- const elements = this.el.querySelectorAll(`[${this.dataAttribute}]`);
8
- elements.forEach((element) => {
9
- const inputElement = element;
10
- validForm = validForm ? this.validateFormField(inputElement) : false;
11
- formData[inputElement.getAttribute(this.dataAttribute)] = inputElement.value;
12
- });
13
- return validForm ? formData : null;
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
- validateFormField(element) {
19
- let isValid = true;
20
- const isRequired = element.hasAttribute("required");
21
- if (isRequired && !element.value) {
22
- // required and not set, show error
23
- element.setAttribute("showerrormsg", "true");
24
- isValid = false;
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
- // required and set, ensure error does not show
28
- element.removeAttribute("showerrormsg");
66
+ target.className = '';
67
+ target.parentElement.querySelector('.errorBubble').replaceChildren();
29
68
  }
30
- return isValid;
31
69
  }
32
- componentDidLoad() {
33
- const elements = this.el.querySelectorAll(`[${this.functionAttribute}]`);
34
- elements.forEach((element) => {
35
- element.addEventListener('click', event => {
36
- event.preventDefault();
37
- const formData = this.fetchFormData();
38
- if (formData) {
39
- // only emit event if form data is valid
40
- this.formSubmit.emit(this.fetchFormData());
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("div", null, h("slot", null)));
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
- "dataAttribute": {
53
- "type": "string",
185
+ "formschema": {
186
+ "type": "any",
54
187
  "mutable": false,
55
188
  "complexType": {
56
- "original": "string",
57
- "resolved": "string",
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": "data-attribute",
67
- "reflect": false,
68
- "defaultValue": "'form-data'"
199
+ "attribute": "formschema",
200
+ "reflect": false
69
201
  },
70
- "functionAttribute": {
71
- "type": "string",
202
+ "submitValue": {
203
+ "type": "any",
72
204
  "mutable": false,
73
205
  "complexType": {
74
- "original": "string",
75
- "resolved": "string",
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": "function-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": "formSubmit",
93
- "name": "formSubmit",
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": "any",
103
- "resolved": "any",
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 elementRef() { return "el"; }
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/TTTX Form',
2
+ title: 'molecules/tttx Form',
3
3
  component: 'tttx-form',
4
- parameters: {
5
- actions: {
6
- handles: ['formSubmit'],
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
- export const CreateUserTemplate = () => `
11
- <tttx-form>
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>`;
@@ -19,19 +19,6 @@
19
19
  color: #9e9e9e;
20
20
  }
21
21
 
22
- .field {
23
- clear: both;
24
- }
25
-
26
- .container {
27
- display: flex;
28
- flex-wrap: wrap;
29
- box-sizing: border-box;
30
- height: 36px;
31
- border: 1px solid #c8c8c8;
32
- border-radius: 4px;
33
- }
34
-
35
22
  .icon-left,
36
23
  .icon-right {
37
24
  flex-basis: 24px;
@@ -56,13 +43,14 @@
56
43
  margin-right: 4px;
57
44
  }
58
45
 
59
- .input {
60
- flex-grow: 1;
61
- border: none;
62
- outline: none;
63
- font-size: 16px;
64
- padding: 8px 16px;
65
- background-color: transparent;
46
+ .icon-right {
47
+ margin-top: 5px;
48
+ margin-right: 4px;
49
+ }
50
+
51
+ .icon-left {
52
+ margin-top: 5px;
53
+ margin-left: 4px;
66
54
  }
67
55
 
68
56
  .iconleft .input {
@@ -73,22 +61,6 @@
73
61
  padding-right: 4px;
74
62
  }
75
63
 
76
- .label {
77
- display: block;
78
- height: 18px;
79
- font-weight: 600;
80
- color: #212121;
81
- font-size: 16px;
82
- margin-bottom: 4px;
83
- z-index: 1;
84
- }
85
-
86
- .disabled {
87
- background: #f0f0f0;
88
- color: #9e9e9e;
89
- border-color: #c8c8c8;
90
- }
91
-
92
64
  .focused {
93
65
  border-color: #1479c6;
94
66
  }
@@ -105,7 +77,7 @@
105
77
  font-size: 14px;
106
78
  border-radius: none;
107
79
  z-index: 2;
108
- color: #DC0000;
80
+ color: #dc0000;
109
81
  }
110
82
 
111
83
  .errormsg .validationicon {
@@ -114,11 +86,11 @@
114
86
  font-size: 16px;
115
87
  margin-right: 4px;
116
88
  vertical-align: middle;
117
- color: #DC0000;
89
+ color: #dc0000;
118
90
  }
119
91
 
120
92
  .danger {
121
- color: #DC0000;
93
+ color: #dc0000;
122
94
  }
123
95
 
124
96
  .optional {
@@ -126,24 +98,80 @@
126
98
  font-weight: normal;
127
99
  }
128
100
 
129
- :host {
101
+ label.inputBlock {
130
102
  display: block;
103
+ position: relative;
104
+ line-height: 21px;
131
105
  }
132
106
 
133
- .spacing {
134
- margin-bottom: 16px;
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;
135
122
  }
136
123
 
137
- .errorstate {
138
- border-color: #DC0000;
124
+ /* iPhone OS fix */
125
+ input[type=date] {
126
+ background: white;
127
+ display: block;
128
+ min-width: calc(100% - 18px);
129
+ line-height: 37px;
139
130
  }
140
131
 
141
- .icon-right {
142
- margin-top: 5px;
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;
143
157
  margin-right: 4px;
158
+ height: 16px;
144
159
  }
145
160
 
146
- .icon-left {
147
- margin-top: 5px;
148
- margin-left: 4px;
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
+ :host {
176
+ display: block;
149
177
  }