@muonic/muon 0.0.2-beta.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 (124) hide show
  1. package/.nycrc +17 -0
  2. package/.versionrc +3 -0
  3. package/CHANGELOG.md +389 -0
  4. package/components/card/index.js +1 -0
  5. package/components/card/src/card-component.js +43 -0
  6. package/components/card/src/card-styles.css +25 -0
  7. package/components/card/src/config-tokens.json +11 -0
  8. package/components/card/src/design-tokens.json +34 -0
  9. package/components/card/story.js +52 -0
  10. package/components/cta/index.js +1 -0
  11. package/components/cta/src/config-tokens.json +11 -0
  12. package/components/cta/src/cta-component.js +174 -0
  13. package/components/cta/src/cta-styles.css +105 -0
  14. package/components/cta/src/design-tokens.json +132 -0
  15. package/components/cta/story.js +99 -0
  16. package/components/detail/index.js +1 -0
  17. package/components/detail/src/config-tokens.json +11 -0
  18. package/components/detail/src/design-tokens.json +102 -0
  19. package/components/detail/src/detail-component.js +27 -0
  20. package/components/detail/src/detail-styles.css +83 -0
  21. package/components/detail/story.js +33 -0
  22. package/components/form/index.js +1 -0
  23. package/components/form/src/config-tokens.json +11 -0
  24. package/components/form/src/design-tokens.json +9 -0
  25. package/components/form/src/form-component.js +197 -0
  26. package/components/form/src/form-styles.css +10 -0
  27. package/components/form/story.js +71 -0
  28. package/components/icon/index.js +1 -0
  29. package/components/icon/src/config-tokens.json +31 -0
  30. package/components/icon/src/design-tokens.json +8 -0
  31. package/components/icon/src/icon-component.js +91 -0
  32. package/components/icon/src/icon-styles.css +26 -0
  33. package/components/icon/story.js +26 -0
  34. package/components/image/index.js +1 -0
  35. package/components/image/src/config-tokens.json +26 -0
  36. package/components/image/src/image-component.js +96 -0
  37. package/components/image/src/image-styles.css +71 -0
  38. package/components/image/story.js +31 -0
  39. package/components/inputter/index.js +1 -0
  40. package/components/inputter/src/config-tokens.json +14 -0
  41. package/components/inputter/src/design-tokens.json +308 -0
  42. package/components/inputter/src/inputter-component.js +227 -0
  43. package/components/inputter/src/inputter-styles-detail.css +59 -0
  44. package/components/inputter/src/inputter-styles.css +305 -0
  45. package/components/inputter/src/inputter-styles.slotted.css +64 -0
  46. package/components/inputter/story.js +243 -0
  47. package/css/accessibility.css +3 -0
  48. package/css/default.css +9 -0
  49. package/css/global.css +8 -0
  50. package/directives/image-loader-directive.js +116 -0
  51. package/directives/svg-loader-directive.js +94 -0
  52. package/index.js +52 -0
  53. package/mixins/card-mixin.js +27 -0
  54. package/mixins/detail-mixin.js +128 -0
  55. package/mixins/form-associate-mixin.js +36 -0
  56. package/mixins/form-element-mixin.js +378 -0
  57. package/mixins/image-holder-mixin.js +20 -0
  58. package/mixins/mask-mixin.js +159 -0
  59. package/mixins/validation-mixin.js +272 -0
  60. package/muon-element/index.js +97 -0
  61. package/package.json +72 -0
  62. package/rollup.config.mjs +30 -0
  63. package/scripts/build/storybook/index.mjs +11 -0
  64. package/scripts/build/storybook/run.mjs +47 -0
  65. package/scripts/rollup-plugins.mjs +116 -0
  66. package/scripts/serve/index.mjs +11 -0
  67. package/scripts/serve/run.mjs +27 -0
  68. package/scripts/style-dictionary.mjs +64 -0
  69. package/scripts/utils/config.mjs +30 -0
  70. package/scripts/utils/index.mjs +283 -0
  71. package/storybook/find-stories.js +36 -0
  72. package/storybook/server.config.mjs +19 -0
  73. package/storybook/stories.js +86 -0
  74. package/storybook/tokens/color.js +87 -0
  75. package/storybook/tokens/font.js +52 -0
  76. package/storybook/tokens/spacer.js +48 -0
  77. package/tests/README.md +3 -0
  78. package/tests/components/card/__snapshots__/card.test.snap.js +70 -0
  79. package/tests/components/card/card.test.js +81 -0
  80. package/tests/components/cta/__snapshots__/cta.test.snap.js +246 -0
  81. package/tests/components/cta/cta.test.js +212 -0
  82. package/tests/components/form/__snapshots__/form.test.snap.js +115 -0
  83. package/tests/components/form/form.test.js +336 -0
  84. package/tests/components/icon/__snapshots__/icon.test.snap.js +95 -0
  85. package/tests/components/icon/icon.test.js +197 -0
  86. package/tests/components/image/__snapshots__/image.test.snap.js +205 -0
  87. package/tests/components/image/image.test.js +314 -0
  88. package/tests/components/image/images/15.png +0 -0
  89. package/tests/components/image/images/150.png +0 -0
  90. package/tests/components/inputter/__snapshots__/inputter.test.snap.js +357 -0
  91. package/tests/components/inputter/inputter.test.js +427 -0
  92. package/tests/helpers/index.js +30 -0
  93. package/tests/mixins/__snapshots__/card.test.snap.js +35 -0
  94. package/tests/mixins/__snapshots__/detail.test.snap.js +237 -0
  95. package/tests/mixins/__snapshots__/form-element.test.snap.js +137 -0
  96. package/tests/mixins/__snapshots__/mask.test.snap.js +53 -0
  97. package/tests/mixins/__snapshots__/validation.test.snap.js +297 -0
  98. package/tests/mixins/card.test.js +63 -0
  99. package/tests/mixins/detail.test.js +223 -0
  100. package/tests/mixins/form-element.test.js +473 -0
  101. package/tests/mixins/mask.test.js +261 -0
  102. package/tests/mixins/muon-element.test.js +52 -0
  103. package/tests/mixins/validation.test.js +423 -0
  104. package/tests/runner/commands.mjs +19 -0
  105. package/tests/scripts/utils/card-component.js +26 -0
  106. package/tests/scripts/utils/muon.config.test.json +13 -0
  107. package/tests/scripts/utils/single.component.config.json +5 -0
  108. package/tests/scripts/utils/test-runner.mjs +1 -0
  109. package/tests/scripts/utils/utils-test.mjs +284 -0
  110. package/tests/utils/validation.functions.test.js +199 -0
  111. package/tokens/theme/color.json +482 -0
  112. package/tokens/theme/font.json +61 -0
  113. package/tokens/theme/size.json +27 -0
  114. package/tokens/theme/spacer.json +73 -0
  115. package/tokens/utils/formats/reference.js +17 -0
  116. package/tokens/utils/modular-scale.js +33 -0
  117. package/tokens/utils/templates/font-face.css.template +30 -0
  118. package/tokens/utils/transforms/color.js +27 -0
  119. package/tokens/utils/transforms/string.js +6 -0
  120. package/tokens/utils/validation.json +76 -0
  121. package/utils/scroll/index.js +31 -0
  122. package/utils/validation/index.js +205 -0
  123. package/web-test-runner.browserstack.config.mjs +123 -0
  124. package/web-test-runner.config.mjs +44 -0
@@ -0,0 +1,227 @@
1
+ import { html, MuonElement, ScopedElementsMixin, classMap, styleMap, ifDefined } from '@muonic/muon';
2
+ import {
3
+ INPUTTER_CONFIG_TYPE,
4
+ INPUTTER_CONFIG_DISABLED,
5
+ INPUTTER_DETAIL_TOGGLE_OPEN,
6
+ INPUTTER_DETAIL_TOGGLE_CLOSE,
7
+ INPUTTER_DETAIL_TOGGLE_POSITION,
8
+ INPUTTER_VALIDATION_WARNING_ICON,
9
+ INPUTTER_FIELD_DATE_ICON,
10
+ INPUTTER_FIELD_SELECT_ICON,
11
+ INPUTTER_FIELD_SEARCH_ICON
12
+ } from '@muon/tokens';
13
+ import { ValidationMixin } from '@muon/mixins/validation-mixin';
14
+ import { MaskMixin } from '@muon/mixins/mask-mixin';
15
+ import { DetailMixin } from '@muon/mixins/detail-mixin';
16
+ import { Icon } from '@muon/components/icon';
17
+ import styles from './inputter-styles.css';
18
+ import detailStyles from './inputter-styles-detail.css';
19
+ import slottedStyles from './inputter-styles.slotted.css';
20
+
21
+ /**
22
+ * A component to allow for user inputs of type text, radio, checkbox, select,
23
+ * date, tel, number, textarea, search.
24
+ *
25
+ * @element inputter
26
+ */
27
+
28
+ export class Inputter extends ScopedElementsMixin(ValidationMixin(MaskMixin(MuonElement))) {
29
+
30
+ static get properties() {
31
+ return {
32
+ helper: { type: String },
33
+ isHelperOpen: { type: Boolean }
34
+ };
35
+ }
36
+
37
+ /* eslint-disable no-use-before-define */
38
+ static get scopedElements() {
39
+ return {
40
+ 'inputter-detail': InputterDetail,
41
+ 'inputter-icon': Icon
42
+ };
43
+ }
44
+ /* eslint-enable no-use-before-define */
45
+
46
+ static get styles() {
47
+ return styles;
48
+ }
49
+
50
+ get slottedStyles() {
51
+ return slottedStyles;
52
+ }
53
+
54
+ constructor() {
55
+ super();
56
+
57
+ this.type = INPUTTER_CONFIG_TYPE;
58
+ this.isHelperOpen = false;
59
+ }
60
+
61
+ _onChange(changeEvent) {
62
+ this._pristine = false;
63
+ changeEvent.stopPropagation();
64
+ let value = this._processFormChangeValue(this._slottedValue);
65
+ if (ifDefined(this.mask)) {
66
+ value = this._processMaskChangeValue(value);
67
+ }
68
+ if (value !== this.value) {
69
+ this.value = value;
70
+ this._fireChangeEvent();
71
+ }
72
+ if (this.validation) {
73
+ this.validate();
74
+ }
75
+ }
76
+
77
+ _onBlur(blurEvent) {
78
+ this._pristine = false;
79
+ super._onBlur(blurEvent);
80
+ if (this.validation) {
81
+ this.validate();
82
+ }
83
+ }
84
+
85
+ _onInput(inputEvent) {
86
+ this._pristine = false;
87
+ inputEvent.stopPropagation();
88
+ let value = this._slottedValue;
89
+ if (ifDefined(this.mask)) {
90
+ value = this._processMaskInputValue(value);
91
+ }
92
+
93
+ if (this.mask || this.validation) {
94
+ if (value !== this.value) {
95
+ this.value = value;
96
+ this._fireChangeEvent();
97
+ }
98
+ }
99
+ if (this.validation) {
100
+ this.validate();
101
+ }
102
+ }
103
+
104
+ get _addValidationIcon() {
105
+ return html`
106
+ <inputter-icon name="${INPUTTER_VALIDATION_WARNING_ICON}" class="icon"></inputter-icon>
107
+ `;
108
+ }
109
+
110
+ /**
111
+ * A method to check availability of tip details slot.
112
+ *
113
+ * @returns {boolean} - Availability of tip details slot.
114
+ * @private
115
+ */
116
+ get __isTipDetailAvailable() {
117
+ return !!this.querySelector('[slot="tip-details"]');
118
+ }
119
+
120
+ /**
121
+ * A method to get helper template.
122
+ *
123
+ * @returns {object} TemplateResult - helper template.
124
+ * @protected
125
+ * @override
126
+ */
127
+ get _addHelper() {
128
+ if (this.helper) {
129
+ if (this.__isTipDetailAvailable) {
130
+ return html`
131
+ <inputter-detail ?open="${this.isHelperOpen}">
132
+ <div slot="heading">${this.helper}</div>
133
+ <slot name="tip-details"></slot>
134
+ </inputter-detail>
135
+ `;
136
+ } else {
137
+ return html`
138
+ <div class="helper">${this.helper}</div>
139
+ `;
140
+ }
141
+ }
142
+
143
+ return undefined;
144
+ }
145
+
146
+ get _inputTypeIcon() {
147
+ if (this._isSelect) {
148
+ return INPUTTER_FIELD_SELECT_ICON;
149
+ } else if (this._inputType === this._inputTypes.SEARCH) {
150
+ return INPUTTER_FIELD_SEARCH_ICON;
151
+ } else if (this._inputType === this._inputTypes.DATE) {
152
+ return INPUTTER_FIELD_DATE_ICON;
153
+ }
154
+
155
+ return undefined;
156
+ }
157
+
158
+ get _addInputTypeIcon() {
159
+ const icon = this._inputTypeIcon;
160
+ return icon ? html`<inputter-icon name="${icon}"></inputter-icon>` : undefined;
161
+ }
162
+
163
+ get _hasDisabled() {
164
+ if (INPUTTER_CONFIG_DISABLED) {
165
+ for (let i = 0; i < this._slottedInputs?.length; i++) {
166
+ if (this._slottedInputs[i].disabled) {
167
+ return true;
168
+ }
169
+ }
170
+ }
171
+ return false;
172
+ }
173
+
174
+ get standardTemplate() {
175
+ const classes = {
176
+ inputter: true,
177
+ select: this._isSelect,
178
+ 'has-mask': this.mask,
179
+ radio: this._inputType === this._inputTypes.RADIO,
180
+ checkbox: this._inputType === this._inputTypes.CHECKBOX,
181
+ search: this._inputType === this._inputTypes.SEARCH,
182
+ date: this._inputType === this._inputTypes.DATE,
183
+ 'has-disabled': this._hasDisabled
184
+ };
185
+
186
+ let styles = {};
187
+ if (this.mask) {
188
+ styles = {
189
+ '--maxlength': this.mask.length
190
+ };
191
+ }
192
+
193
+ return html`
194
+ <div class="${classMap(classes)}" style="${styleMap(styles)}">
195
+ ${this._isMultiple ? this._addHeading : this._addLabel}
196
+ ${this._addHelper}
197
+ <div class="wrapper">
198
+ ${super.standardTemplate}
199
+ ${this._addMask}
200
+ ${this._addInputTypeIcon}
201
+ </div>
202
+ </div>
203
+ ${this._addValidationMessage}
204
+ `;
205
+ }
206
+ }
207
+
208
+ /**
209
+ * InputterDetail component to handle helper text.
210
+ *
211
+ * @element inputter-detail
212
+ * @private
213
+ */
214
+
215
+ class InputterDetail extends DetailMixin(MuonElement) {
216
+
217
+ static get styles() {
218
+ return detailStyles;
219
+ }
220
+
221
+ constructor() {
222
+ super();
223
+ this._toggleOpen = INPUTTER_DETAIL_TOGGLE_OPEN;
224
+ this._toggleClose = INPUTTER_DETAIL_TOGGLE_CLOSE;
225
+ this._togglePosition = INPUTTER_DETAIL_TOGGLE_POSITION;
226
+ }
227
+ }
@@ -0,0 +1,59 @@
1
+ @import "@muonic/muon/css/default.css";
2
+
3
+ :host {
4
+ & summary {
5
+ &::-webkit-details-marker {
6
+ display: none;
7
+ }
8
+ }
9
+
10
+ & .details {
11
+ color: $INPUTTER_DETAIL_COLOR;
12
+ margin-block-start: $INPUTTER_DETAIL_MARGIN_BLOCK;
13
+ }
14
+
15
+ & .toggle {
16
+ width: $INPUTTER_DETAIL_ICON_SIZE;
17
+ height: $INPUTTER_DETAIL_ICON_SIZE;
18
+ flex-shrink: 0;
19
+ }
20
+
21
+ & .heading {
22
+ display: flex;
23
+ align-items: center;
24
+ column-gap: $INPUTTER_DETAIL_HEADING_GAP;
25
+ width: fit-content;
26
+ cursor: pointer;
27
+ font-size: 14px;
28
+ margin-block-start: $INPUTTER_DETAIL_HEADING_MARGIN_BLOCK;
29
+
30
+ &:hover {
31
+ text-decoration: underline;
32
+ color: $INPUTTER_DETAIL_HOVER_COLOR;
33
+ }
34
+
35
+ & :focus:not(:focus-visible) {
36
+ /*
37
+ https://matthiasott.com/notes/focus-visible-is-here and
38
+ https://www.tpgi.com/focus-visible-and-backwards-compatibility/
39
+ */
40
+ outline-style: none;
41
+ }
42
+
43
+ &:focus-visible {
44
+ outline-color: $INPUTTER_DETAIL_FOCUS_OUTLINE_COLOR;
45
+ outline-style: solid;
46
+ outline-width: 3px;
47
+ outline-offset: 0;
48
+ }
49
+ }
50
+
51
+ & .content {
52
+ margin-block-start: $INPUTTER_DETAIL_CONTENT_MARGIN_BLOCK;
53
+ padding-inline-start: $INPUTTER_DETAIL_CONTENT_PADDING_INLINE;
54
+ font-size: 12px;
55
+ border-inline-start-style: solid;
56
+ border-inline-start-width: 3px;
57
+ border-inline-start-color: $INPUTTER_DETAIL_BORDER_COLOR;
58
+ }
59
+ }
@@ -0,0 +1,305 @@
1
+ @import "@muonic/muon/css/default.css";
2
+
3
+ :host {
4
+ display: block;
5
+
6
+ & ::slotted(label) {
7
+ color: $INPUTTER_LABEL_COLOR;
8
+ }
9
+
10
+ & ::slotted(*)::placeholder {
11
+ color: $INPUTTER_PLACEHOLDER_COLOR;
12
+ opacity: 1; /* NOTE: This overrides the Firefox user agent style of `opacity: 0.54;` */
13
+ }
14
+
15
+ & ::slotted(:is(
16
+ input[type="date"],
17
+ input[type="email"],
18
+ input[type="number"],
19
+ input[type="password"],
20
+ input[type="search"],
21
+ input[type="tel"],
22
+ input[type="text"],
23
+ select,
24
+ textarea)) {
25
+ margin: 0; /* NOTE: remove `margin: 2px` Safari user agent */
26
+ padding-block-start: $INPUTTER_FIELD_PADDING_BLOCK;
27
+ padding-block-end: $INPUTTER_FIELD_PADDING_BLOCK;
28
+ padding-inline-start: $INPUTTER_FIELD_PADDING_INLINE;
29
+ padding-inline-end: $INPUTTER_FIELD_PADDING_INLINE;
30
+ color: $INPUTTER_FIELD_COLOR;
31
+ background-color: $INPUTTER_FIELD_BACKGROUND_COLOR;
32
+ border-width: 2px;
33
+ border-style: solid;
34
+ border-color: $INPUTTER_FIELD_BORDER_COLOR;
35
+ border-radius: 0;
36
+ font-family: $INPUTTER_FIELD_FONT_FAMILY;
37
+ font-size: $INPUTTER_FIELD_FONT_SIZE;
38
+ }
39
+
40
+ & ::slotted(:is(
41
+ input[type="date"]:hover,
42
+ input[type="email"]:hover,
43
+ input[type="number"]:hover,
44
+ input[type="password"]:hover,
45
+ input[type="search"]:hover,
46
+ input[type="tel"]:hover,
47
+ input[type="text"]:hover,
48
+ select:hover,
49
+ textarea:hover)) {
50
+ border-color: $INPUTTER_HOVER_BORDER_COLOR;
51
+ color: $INPUTTER_HOVER_COLOR;
52
+ }
53
+
54
+ & ::slotted(:is(
55
+ input[type="date"]:focus,
56
+ input[type="email"]:focus,
57
+ input[type="number"]:focus,
58
+ input[type="password"]:focus,
59
+ input[type="search"]:focus,
60
+ input[type="tel"]:focus,
61
+ input[type="text"]:focus,
62
+ select:focus,
63
+ textarea:focus)) {
64
+ border-color: $INPUTTER_FOCUS_BORDER_COLOR;
65
+ color: $INPUTTER_FOCUS_COLOR;
66
+ outline-color: $INPUTTER_FOCUS_OUTLINE_COLOR;
67
+ outline-offset: 0;
68
+ outline-style: solid;
69
+ outline-width: 3px;
70
+ }
71
+
72
+ & .has-disabled {
73
+ & ::slotted(:is(
74
+ input[type="date"]:disabled,
75
+ input[type="email"]:disabled,
76
+ input[type="number"]:disabled,
77
+ input[type="password"]:disabled,
78
+ input[type="search"]:disabled,
79
+ input[type="tel"]:disabled,
80
+ input[type="text"]:disabled,
81
+ select:disabled,
82
+ textarea:disabled)) {
83
+ pointer-events: none;
84
+ color: $INPUTTER_DISABLED_COLOR;
85
+ background-color: $INPUTTER_DISABLED_BACKGROUND_COLOR;
86
+ border-color: $INPUTTER_DISABLED_BORDER_COLOR;
87
+ }
88
+
89
+ & ::slotted(*:disabled)::placeholder {
90
+ color: $INPUTTER_DISABLED_PLACEHOLDER_COLOR;
91
+ }
92
+ }
93
+
94
+ & .wrapper {
95
+ margin-block-start: $INPUTTER_FIELD_MARGIN_BLOCK;
96
+ max-width: fit-content;
97
+ position: relative;
98
+ }
99
+
100
+ & .checkbox,
101
+ & .radio {
102
+ & .wrapper {
103
+ display: grid; /* NOTE: using `grid` to control the layout of `<input>` and `<label>` */
104
+ line-height: 1.2; /* NOTE: setting `line-height` here to control the position of the checkbox and radio input */
105
+ grid-template-columns: $INPUTTER_MULTIPLE_SIZE auto;
106
+ column-gap: $INPUTTER_MULTIPLE_GAP;
107
+ row-gap: $INPUTTER_MULTIPLE_GAP;
108
+ }
109
+
110
+ & ::slotted(:is(
111
+ input[type="checkbox"],
112
+ input[type="radio"])) {
113
+ margin: 0; /* NOTE: remove user agent default margin */
114
+ appearance: none; /* NOTE: remove the user agent visual styles for checkbox and radio */
115
+ background-color: $INPUTTER_MULTIPLE_BACKGROUND_COLOR;
116
+ font: inherit; /* NOTE: inheiting font to ensure the use of `em` produces the desired outcome */
117
+ width: $INPUTTER_MULTIPLE_SIZE;
118
+ height: $INPUTTER_MULTIPLE_SIZE;
119
+ border-width: 0.125em; /* NOTE: equal to 2px when font-size is 16px */
120
+ border-style: solid;
121
+ border-color: $INPUTTER_MULTIPLE_BORDER_COLOR;
122
+ display: grid; /* NOTE: setting `display: grid` to position the `::before` */
123
+ place-content: center; /* NOTE: placing the content of grid in the centre */
124
+ }
125
+
126
+ & ::slotted(:is(
127
+ input[type="checkbox"]:hover,
128
+ input[type="radio"]:hover)) {
129
+ border-color: $INPUTTER_HOVER_BORDER_COLOR;
130
+ }
131
+
132
+ & ::slotted(:is(
133
+ input[type="checkbox"]:focus-visible,
134
+ input[type="radio"]:focus-visible)) {
135
+ border-color: $INPUTTER_FOCUS_BORDER_COLOR;
136
+ outline-color: $INPUTTER_FOCUS_OUTLINE_COLOR;
137
+ outline-offset: 0;
138
+ outline-style: solid;
139
+ outline-width: 3px;
140
+ }
141
+
142
+ &.has-disabled {
143
+ & ::slotted(:is(
144
+ input[type="checkbox"]:disabled,
145
+ input[type="radio"]:disabled)) {
146
+ pointer-events: none;
147
+ background-color: $INPUTTER_DISABLED_BACKGROUND_COLOR;
148
+ border-color: $INPUTTER_DISABLED_BORDER_COLOR;
149
+ }
150
+ }
151
+
152
+ & ::slotted(input[type="checkbox"]) {
153
+ border-radius: 0.1875em; /* NOTE: equal to 3px when font-size is 16px */
154
+ }
155
+
156
+ & ::slotted(input[type="radio"]) {
157
+ border-radius: 50%;
158
+ }
159
+
160
+ & ::slotted(input[type="radio"]:checked)::before {
161
+ display: block;
162
+ content: "";
163
+ width: 0;
164
+ height: 0;
165
+ border-width: 0.25em;
166
+ border-style: solid;
167
+ border-color: $INPUTTER_MULTIPLE_BORDER_COLOR;
168
+ border-radius: 50%;
169
+ }
170
+
171
+ & ::slotted(input[type="checkbox"]:checked)::before {
172
+ display: block;
173
+ content: "";
174
+ width: 0.25em;
175
+ height: 0.5em;
176
+ border-width: 0.125em;
177
+ border-style: solid;
178
+ border-color: $INPUTTER_MULTIPLE_BORDER_COLOR;
179
+ border-top: unset;
180
+ border-right-style: solid;
181
+ border-bottom-style: solid;
182
+ border-left: unset;
183
+ transform: translateY(-10%) rotate(45deg);
184
+ }
185
+
186
+ & ::slotted(label) {
187
+ display: block;
188
+ width: fit-content;
189
+ }
190
+
191
+ & ::slotted(label:hover) {
192
+ color: $INPUTTER_HOVER_COLOR;
193
+ }
194
+ }
195
+
196
+ /* stylelint-disable no-descending-specificity */
197
+ & ::slotted(:is(
198
+ select,
199
+ input[type="date"])) {
200
+ appearance: none; /* NOTE: remove the user agent visual styles */
201
+ padding-inline-end: $INPUTTER_FIELD_ICON_SPACER;
202
+ }
203
+
204
+ & ::slotted(input[type="search"]) {
205
+ padding-inline-start: $INPUTTER_FIELD_ICON_SPACER;
206
+ }
207
+
208
+ & ::slotted(textarea) {
209
+ display: block; /* NOTE: this is to remove the additional space at the bottom of `textarea` */
210
+ }
211
+ /* stylelint-enable no-descending-specificity */
212
+
213
+ & .date,
214
+ & .search,
215
+ & .select {
216
+ & .wrapper {
217
+ & inputter-icon {
218
+ pointer-events: none;
219
+ position: absolute;
220
+ top: 50%;
221
+ transform: translateY(-50%);
222
+ width: $INPUTTER_FIELD_ICON_SIZE;
223
+ height: $INPUTTER_FIELD_ICON_SIZE;
224
+ }
225
+ }
226
+ }
227
+
228
+ & .date,
229
+ & .select {
230
+ & .wrapper {
231
+ & inputter-icon {
232
+ right: calc($INPUTTER_FIELD_PADDING_INLINE + 2px); /* NOTE: the 2px is the width of the border */
233
+ }
234
+ }
235
+ }
236
+
237
+ & .search {
238
+ & .wrapper {
239
+ & inputter-icon {
240
+ left: calc($INPUTTER_FIELD_PADDING_INLINE + 2px); /* NOTE: the 2px is the width of the border */
241
+ }
242
+ }
243
+ }
244
+
245
+ & .has-mask {
246
+ position: relative;
247
+
248
+ & .input-mask,
249
+ & ::slotted(:is(
250
+ input[type="email"],
251
+ input[type="number"],
252
+ input[type="search"],
253
+ input[type="tel"],
254
+ input[type="text"])) {
255
+ width: calc((var(--maxlength)) * 1ch);
256
+ font-family: $INPUTTER_MASK_FONT_FAMILY;
257
+ }
258
+
259
+ & .input-mask {
260
+ padding-block-start: $INPUTTER_FIELD_PADDING_BLOCK;
261
+ padding-block-end: $INPUTTER_FIELD_PADDING_BLOCK;
262
+ padding-inline-start: $INPUTTER_FIELD_PADDING_INLINE;
263
+ padding-inline-end: $INPUTTER_FIELD_PADDING_INLINE;
264
+ border-width: 2px;
265
+ border-style: solid;
266
+ border-color: transparent;
267
+ border-radius: 0;
268
+ position: absolute;
269
+ top: 0;
270
+ right: 0;
271
+ bottom: 0;
272
+ left: 0;
273
+ color: $INPUTTER_MASK_COLOR;
274
+ pointer-events: none;
275
+ white-space: pre;
276
+ line-height: normal;
277
+ text-align: start;
278
+ }
279
+
280
+ & ::slotted(input[type="text"]) {
281
+ font-weight: $INPUTTER_MASK_FONT_WEIGHT;
282
+ }
283
+ }
284
+
285
+ & .validation {
286
+ display: flex;
287
+ align-items: center;
288
+ column-gap: $INPUTTER_VALIDATION_GAP;
289
+ width: fit-content;
290
+ margin-block-start: $INPUTTER_VALIDATION_MARGIN_BLOCK;
291
+ color: $INPUTTER_VALIDATION_WARNING_COLOR;
292
+ font-size: 14px;
293
+
294
+ & .icon {
295
+ width: $INPUTTER_VALIDATION_ICON_SIZE;
296
+ flex-shrink: 0;
297
+ }
298
+ }
299
+
300
+ & .helper {
301
+ margin-block-start: $INPUTTER_DETAIL_HEADING_MARGIN_BLOCK;
302
+ color: $INPUTTER_DETAIL_COLOR;
303
+ font-size: 14px;
304
+ }
305
+ }
@@ -0,0 +1,64 @@
1
+ :host {
2
+ /* NOTE: targeting Safari only */
3
+ @media not all and (min-resolution: 0.001dpcm) {
4
+ /*
5
+ NOTE: These styles are duplicated from inputter-styles.css
6
+ due to this bug in Webkit: https://bugs.webkit.org/show_bug.cgi?id=223814
7
+ */
8
+ & input[type="radio"] {
9
+ &:checked {
10
+ &::before {
11
+ display: block;
12
+ content: "";
13
+ width: 0;
14
+ height: 0;
15
+ border-width: 0.25em;
16
+ border-style: solid;
17
+ border-color: $INPUTTER_MULTIPLE_BORDER_COLOR;
18
+ border-radius: 50%;
19
+ }
20
+ }
21
+ }
22
+
23
+ & input[type="checkbox"] {
24
+ &:checked {
25
+ &::before {
26
+ display: block;
27
+ content: "";
28
+ width: 0.25em;
29
+ height: 0.5em;
30
+ border-width: 0.125em;
31
+ border-style: solid;
32
+ border-color: $INPUTTER_MULTIPLE_BORDER_COLOR;
33
+ border-top: unset;
34
+ border-right-style: solid;
35
+ border-bottom-style: solid;
36
+ border-left: unset;
37
+ transform: translateY(-10%) rotate(45deg);
38
+ }
39
+ }
40
+ }
41
+ }
42
+
43
+ & input[type="date"] {
44
+ &::-webkit-datetime-edit,
45
+ &::-webkit-datetime-edit-fields-wrapper,
46
+ &::-webkit-datetime-edit-day-field,
47
+ &::-webkit-datetime-edit-month-field,
48
+ &::-webkit-datetime-edit-year-field {
49
+ padding-block-start: 0; /* NOTE: these pseudo elements have padding applied by the user agent */
50
+ padding-block-end: 0;
51
+ }
52
+
53
+ &::-webkit-calendar-picker-indicator {
54
+ opacity: 0; /* NOTE: icon defined: `$INPUTTER_FIELD_DATE` `display: none` removes the clickable element Chrome */
55
+ margin-inline-start: 0; /* NOTE: margin and position styles, increase the clickable area of this element Chrome */
56
+ position: absolute;
57
+ top: 0;
58
+ right: 0;
59
+ bottom: 0;
60
+ height: auto;
61
+ width: 2rem;
62
+ }
63
+ }
64
+ }