7 |
10 |
15 |
16 |
20 | 🐟
21 |
22 | NEAR protocol is a new blockchain focused on developer productivity and useability!
23 |
27 | 🐟
28 |
29 |
30 |
31 |
35 | ⛓
36 |
37 | This little react app is connected to blockchain right now.
38 |
42 | ⛓
43 |
44 |
45 |
54 |
55 |
56 |
57 |
60 | Log out
61 |
62 |
65 | Change greeting
66 |
67 |
68 |
69 |
143 |
144 | `;
145 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/BOUNTY.yml:
--------------------------------------------------------------------------------
1 | name: "Simple Bounty"
2 | description: "Use this template to create a HEROES Simple Bounty via Github bot"
3 | title: "Bounty: "
4 | labels: ["bounty"]
5 | assignees: heroes-bot-test
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Hi! Let's set up your bounty! Please don't change the template - @heroes-bot-test won't be able to help you.
11 |
12 | - type: dropdown
13 | id: type
14 | attributes:
15 | label: What talent are you looking for?
16 | options:
17 | - Marketing
18 | - Development
19 | - Design
20 | - Other
21 | - Content
22 | - Research
23 | - Audit
24 |
25 | - type: textarea
26 | id: description
27 | attributes:
28 | label: What you need to be done?
29 |
30 | - type: dropdown
31 | id: tags
32 | attributes:
33 | label: Tags
34 | description: Add tags that match the topic of the work
35 | multiple: true
36 | options:
37 | - API
38 | - Blockchain
39 | - Community
40 | - CSS
41 | - DAO
42 | - dApp
43 | - DeFi
44 | - Design
45 | - Documentation
46 | - HTML
47 | - Javascript
48 | - NFT
49 | - React
50 | - Rust
51 | - Smart contract
52 | - Typescript
53 | - UI/UX
54 | - web3
55 | - Translation
56 | - Illustration
57 | - Branding
58 | - Copywriting
59 | - Blogging
60 | - Editing
61 | - Video Creation
62 | - Social Media
63 | - Graphic Design
64 | - Transcription
65 | - Product Design
66 | - Artificial Intelligence
67 | - Quality Assurance
68 | - Risk Assessment
69 | - Security Audit
70 | - Bug Bounty
71 | - Code Review
72 | - Blockchain Security
73 | - Smart Contract Testing
74 | - Penetration Testing
75 | - Vulnerability Assessment
76 | - BOS
77 | - News
78 | - Hackathon
79 | - NEARCON2023
80 | - NEARWEEK
81 |
82 | - type: input
83 | id: deadline
84 | attributes:
85 | label: Deadline
86 | description: "Set a deadline for your bounty. Please enter the date in format: DD.MM.YYYY"
87 | placeholder: "19.05.2027"
88 |
89 | - type: dropdown
90 | id: currencyType
91 | attributes:
92 | label: Currency
93 | description: What is the currency you want to pay?
94 | options:
95 | - USDC.e
96 | - USDT.e
97 | - DAI
98 | - wNEAR
99 | - USDt
100 | - XP
101 | - marmaj
102 | - NEKO
103 | - JUMP
104 | - USDC
105 | - NEARVIDIA
106 | default: 0
107 | validations:
108 | required: true
109 |
110 | - type: input
111 | id: currencyAmount
112 | attributes:
113 | label: Amount
114 | description: How much it will be cost?
115 |
116 | - type: markdown
117 | attributes:
118 | value: "## Advanced settings"
119 |
120 | - type: checkboxes
121 | id: kyc
122 | attributes:
123 | label: KYC
124 | description: "Use HEROES' KYC Verification, only applicants who passed HEROES' KYC can apply and work on this bounty!"
125 | options:
126 | - label: Use KYC Verification
127 |
128 | - type: markdown
129 | attributes:
130 | value: |
131 | ### This cannot be changed once the bounty is live!
132 |
--------------------------------------------------------------------------------
/src/scss/_parallax.scss:
--------------------------------------------------------------------------------
1 | // Parallax
2 | $parallax-deg: 3deg !default;
3 | $parallax-offset: 4.5px !default;
4 | $parallax-offset-z: 50px !default;
5 | $parallax-perspective: 1000px !default;
6 | $parallax-scale: .95 !default;
7 | $parallax-fade-color: rgba(255, 255, 255, .35) !default;
8 |
9 | // Mixin: Parallax direction
10 | @mixin parallax-dir() {
11 | height: 50%;
12 | outline: none;
13 | position: absolute;
14 | width: 50%;
15 | z-index: $zindex-1;
16 | }
17 |
18 | .parallax {
19 | display: block;
20 | height: auto;
21 | position: relative;
22 | width: auto;
23 |
24 | .parallax-content {
25 | @include shadow-variant(1rem);
26 | height: auto;
27 | transform: perspective($parallax-perspective);
28 | transform-style: preserve-3d;
29 | transition: all .4s ease;
30 | width: 100%;
31 |
32 | &::before {
33 | content: "";
34 | display: block;
35 | height: 100%;
36 | left: 0;
37 | position: absolute;
38 | top: 0;
39 | width: 100%;
40 | }
41 | }
42 |
43 | .parallax-front {
44 | align-items: center;
45 | color: $light-color;
46 | display: flex;
47 | height: 100%;
48 | justify-content: center;
49 | left: 0;
50 | position: absolute;
51 | text-align: center;
52 | text-shadow: 0 0 20px rgba($dark-color, .75);
53 | top: 0;
54 | transform: translateZ($parallax-offset-z) scale($parallax-scale);
55 | transition: transform .4s;
56 | width: 100%;
57 | z-index: $zindex-0;
58 | }
59 |
60 | .parallax-top-left {
61 | @include parallax-dir();
62 | left: 0;
63 | top: 0;
64 |
65 | &:focus ~ .parallax-content,
66 | &:hover ~ .parallax-content {
67 | transform: perspective($parallax-perspective) rotateX($parallax-deg) rotateY(-$parallax-deg);
68 |
69 | &::before {
70 | background: linear-gradient(135deg, $parallax-fade-color 0%, transparent 50%);
71 | }
72 |
73 | .parallax-front {
74 | transform: translate3d($parallax-offset, $parallax-offset, $parallax-offset-z) scale($parallax-scale);
75 | }
76 | }
77 | }
78 |
79 | .parallax-top-right {
80 | @include parallax-dir();
81 | right: 0;
82 | top: 0;
83 |
84 | &:focus ~ .parallax-content,
85 | &:hover ~ .parallax-content {
86 | transform: perspective($parallax-perspective) rotateX($parallax-deg) rotateY($parallax-deg);
87 |
88 | &::before {
89 | background: linear-gradient(-135deg, $parallax-fade-color 0%, transparent 50%);
90 | }
91 |
92 | .parallax-front {
93 | transform: translate3d(-$parallax-offset, $parallax-offset, $parallax-offset-z) scale($parallax-scale);
94 | }
95 | }
96 | }
97 |
98 | .parallax-bottom-left {
99 | @include parallax-dir();
100 | bottom: 0;
101 | left: 0;
102 |
103 | &:focus ~ .parallax-content,
104 | &:hover ~ .parallax-content {
105 | transform: perspective($parallax-perspective) rotateX(-$parallax-deg) rotateY(-$parallax-deg);
106 |
107 | &::before {
108 | background: linear-gradient(45deg, $parallax-fade-color 0%, transparent 50%);
109 | }
110 |
111 | .parallax-front {
112 | transform: translate3d($parallax-offset, -$parallax-offset, $parallax-offset-z) scale($parallax-scale);
113 | }
114 | }
115 | }
116 |
117 | .parallax-bottom-right {
118 | @include parallax-dir();
119 | bottom: 0;
120 | right: 0;
121 |
122 | &:focus ~ .parallax-content,
123 | &:hover ~ .parallax-content {
124 | transform: perspective($parallax-perspective) rotateX(-$parallax-deg) rotateY($parallax-deg);
125 |
126 | &::before {
127 | background: linear-gradient(-45deg, $parallax-fade-color 0%, transparent 50%);
128 | }
129 |
130 | .parallax-front {
131 | transform: translate3d(-$parallax-offset, -$parallax-offset, $parallax-offset-z) scale($parallax-scale);
132 | }
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/scss/_markdown.scss:
--------------------------------------------------------------------------------
1 | .markdown {
2 | font-size: .8rem;
3 | font-weight: 400;
4 | line-height: 1.4rem;
5 | text-align: justify;
6 | word-break: break-word;
7 |
8 | // Reset
9 | & > :first-child {
10 | margin-top: 0;
11 | }
12 |
13 | // Headings
14 | h1,
15 | h2,
16 | h3,
17 | h4,
18 | h5,
19 | h6 {
20 | font-weight: 700;
21 | line-height: 1.5;
22 | margin-bottom: $unit-6;
23 | margin-top: $unit-2;
24 |
25 | & + hr {
26 | margin-top: -$unit-2;
27 | }
28 | }
29 | h1 {
30 | font-size: 28px;
31 | }
32 | h2 {
33 | font-size: 24px;
34 | }
35 | h3 {
36 | font-size: 22px;
37 | }
38 | h4 {
39 | font-size: 20px;
40 | }
41 | h5 {
42 | font-size: 18px;
43 | }
44 | h6 {
45 | font-size: 16px;
46 | }
47 |
48 | // Paragraphs
49 | p {
50 | hyphens: auto;
51 | margin: 0 0 $unit-8;
52 | }
53 |
54 | // Semantic text elements
55 | a {
56 | border-bottom: .05rem solid currentColor;
57 | font-weight: 500;
58 | padding-bottom: .1rem;
59 |
60 | &:focus,
61 | &:hover,
62 | &:active {
63 | text-decoration: none;
64 | }
65 | }
66 |
67 | a,
68 | ins,
69 | u {
70 | text-decoration-skip: ink edges;
71 | }
72 |
73 | del + del,
74 | del + s,
75 | ins + ins,
76 | ins + u,
77 | s + del,
78 | s + s,
79 | u + ins,
80 | u + u {
81 | margin-left: .125em;
82 | }
83 |
84 | // Divider
85 | hr {
86 | background: $border-color;
87 | border: none;
88 | display: block;
89 | height: 1px;
90 | margin: $unit-2 0 $unit-6;
91 | overflow: hidden;
92 |
93 | @include clearfix();
94 | }
95 |
96 | // Lists
97 | ul,
98 | ol {
99 | margin: $unit-8 0 $unit-8 $unit-8;
100 | padding: 0;
101 |
102 | ul,
103 | ol {
104 | margin: $unit-4 0 $unit-4 $unit-8;
105 | }
106 |
107 | li {
108 | margin-top: $unit-2;
109 |
110 | & > p {
111 | display: inline;
112 | }
113 | }
114 | }
115 |
116 | ul {
117 | list-style: disc inside;
118 |
119 | ul {
120 | list-style-type: circle;
121 | }
122 |
123 | //- Fix content wider than screen
124 | & > li > ul > li > ul {
125 | display: none;
126 | }
127 | }
128 |
129 | ol {
130 | list-style: decimal inside;
131 |
132 | ol {
133 | list-style-type: lower-alpha;
134 | }
135 | }
136 |
137 | // Images
138 | img {
139 | border: 0;
140 | display: block;
141 | height: auto;
142 | margin: 1rem auto;
143 | max-width: 100%;
144 |
145 | & + em {
146 | display: inline-block;
147 | color: $gray-color-dark;
148 | font-size: .7rem;
149 | text-align: center;
150 | width: 100%;
151 | }
152 |
153 | &.emojione {
154 | display: inline;
155 | height: 1rem;
156 | margin: 0;
157 | vertical-align: -10%;
158 | width: 1rem;
159 | }
160 | }
161 |
162 | // Blockquote
163 | blockquote {
164 | border-left: .2rem solid $gray-color-dark;
165 | margin: $unit-8 0;
166 | padding: $unit-4 $unit-8;
167 |
168 | &:empty {
169 | display: none;
170 | }
171 |
172 | p:last-child {
173 | margin-bottom: 0;
174 | }
175 | }
176 |
177 | // Tables
178 | table {
179 | border-collapse: collapse;
180 | border-spacing: 0;
181 | display: block;
182 | font-size: .7rem;
183 | margin: $unit-8 0;
184 | overflow-x: auto;
185 | padding-bottom: .75rem;
186 | text-align: left;
187 | white-space: nowrap;
188 | width: 100%;
189 |
190 | tbody {
191 | tr:nth-of-type(odd) {
192 | background: $bg-color;
193 | }
194 | }
195 |
196 | td,
197 | th {
198 | border-bottom: 1px solid $dark-color;
199 | width: 20%;
200 | padding: $unit-4;
201 | }
202 |
203 | th {
204 | border-bottom-width: 2px;
205 | }
206 | }
207 |
208 | // Code
209 | code {
210 | background: $bg-color;
211 | color: $code-color;
212 | font-family: $mono-font-family;
213 | font-size: .9em;
214 | padding: .2em;
215 | }
216 |
217 | pre {
218 | background: $bg-color;
219 | margin: $unit-8 0;
220 | overflow-x: auto;
221 | padding: $unit-2 $unit-4;
222 | }
223 |
224 | .codehilite {
225 | font-size: .9em;
226 | line-height: 1.8;
227 | }
228 | }
--------------------------------------------------------------------------------
/src/assets/near-logo.svg:
--------------------------------------------------------------------------------
1 |
186 |
187 |
Balance
188 |
{nearTo(currentUser.balance, 2)} Ⓝ
189 |
190 | fundDrop()}>+ Create New NEAR Drop
191 |
192 |
193 |
194 |
195 | setShowUsed(false)}>Active
196 | setShowUsed(true)}>Claimed
197 |
198 |
199 |
200 | {
201 | urlDrop &&
202 |
URL Drop
203 |
{nearTo(urlDrop.amount, 2)} Ⓝ
204 |
From: {urlDrop.from}
205 | { urlDrop.limited ?
206 |
claimMultisig(urlDrop.amount, urlDrop.key)}>Create Multisig
207 | :
208 | <>
209 |
claimDrop(urlDrop.amount, urlDrop.key)}>Claim Drop
210 |
claimAccount(urlDrop.amount, urlDrop.key)}>Create Account
211 |
claimContract(urlDrop.amount, urlDrop.key)}>Create Multisig
212 | >
213 | }
214 |
215 | }
216 | { !showUsed &&
217 |
218 | {
219 | activeDrops.length > 0 ?
220 |
221 | {
222 | activeDrops.map(({ public_key, amount, ts, walletLink }) =>
223 |
224 |
{nearTo(amount, 2)} Ⓝ
225 |
Active
226 |
Public Key: {public_key}
227 |
{
228 | await clipboard.writeText(walletLink)
229 | alert('🧧 NEAR Redpacket link copied.')
230 | }}>Share Link
231 |
reclaimDrop(public_key)}>Use Drop
232 |
)
233 | }
234 |
235 | :
236 |
237 |
🧧
238 |
No Available Redpackets
239 |
Click the button to create a new NEAR redpacket.
240 |
241 | }
242 |
243 | }
244 | { showUsed &&
245 | <>
246 | {
247 | usedDrops.length > 0 ?
248 |
249 | {
250 | usedDrops.map(({ public_key, amount, ts, walletLink }) =>
251 |
252 |
{nearTo(amount, 2)} Ⓝ
253 |
Claimed
254 |
Public Key: {public_key}
255 |
{
256 | await clipboard.writeText(walletLink)
257 | alert('🧧 NEAR Redpacket link copied.')
258 | }}>Share Link
259 |
removeDrop(public_key)}>Remove Drop
260 |
)
261 | }
262 |
263 | :
264 |
265 |
🧧
266 |
No Claimed Redpackets
267 |
Click the button to create a new NEAR redpacket.
268 |
269 | }
270 | >
271 | }
272 |
273 | )
274 | }
275 |
276 | export default Drops;
277 |
--------------------------------------------------------------------------------
/src/scss/_forms.scss:
--------------------------------------------------------------------------------
1 | // Forms
2 | .form-group {
3 | &:not(:last-child) {
4 | margin-bottom: $layout-spacing;
5 | }
6 | }
7 |
8 | fieldset {
9 | margin-bottom: $layout-spacing-lg;
10 | }
11 |
12 | legend {
13 | font-size: $font-size-lg;
14 | font-weight: 500;
15 | margin-bottom: $layout-spacing-lg;
16 | }
17 |
18 | // Form element: Label
19 | .form-label {
20 | display: block;
21 | line-height: $line-height;
22 | padding: $control-padding-y + $border-width 0;
23 |
24 | &.label-sm {
25 | font-size: $font-size-sm;
26 | padding: $control-padding-y-sm + $border-width 0;
27 | }
28 |
29 | &.label-lg {
30 | font-size: $font-size-lg;
31 | padding: $control-padding-y-lg + $border-width 0;
32 | }
33 | }
34 |
35 | // Form element: Input
36 | .form-input {
37 | appearance: none;
38 | background: $bg-color-light;
39 | background-image: none;
40 | border: $border-width solid $border-color-dark;
41 | border-radius: $border-radius;
42 | color: $body-font-color;
43 | display: block;
44 | font-size: $font-size;
45 | height: $control-size;
46 | line-height: $line-height;
47 | max-width: 100%;
48 | outline: none;
49 | padding: $control-padding-y $control-padding-x;
50 | position: relative;
51 | transition: background .2s, border .2s, box-shadow .2s, color .2s;
52 | width: 100%;
53 | &:focus {
54 | @include control-shadow();
55 | border-color: $primary-color;
56 | }
57 | &::placeholder {
58 | color: $gray-color;
59 | }
60 |
61 | // Input sizes
62 | &.input-sm {
63 | font-size: $font-size-sm;
64 | height: $control-size-sm;
65 | padding: $control-padding-y-sm $control-padding-x-sm;
66 | }
67 |
68 | &.input-lg {
69 | font-size: $font-size-lg;
70 | height: $control-size-lg;
71 | padding: $control-padding-y-lg $control-padding-x-lg;
72 | }
73 |
74 | &.input-inline {
75 | display: inline-block;
76 | vertical-align: middle;
77 | width: auto;
78 | }
79 |
80 | // Input types
81 | &[type="file"] {
82 | height: auto;
83 | }
84 | }
85 |
86 | // Form element: Textarea
87 | textarea.form-input {
88 | &,
89 | &.input-lg,
90 | &.input-sm {
91 | height: auto;
92 | }
93 | }
94 |
95 | // Form element: Input hint
96 | .form-input-hint {
97 | color: $gray-color;
98 | font-size: $font-size-sm;
99 | margin-top: $unit-1;
100 |
101 | .has-success &,
102 | .is-success + & {
103 | color: $success-color;
104 | }
105 |
106 | .has-error &,
107 | .is-error + & {
108 | color: $error-color;
109 | }
110 | }
111 |
112 | // Form element: Select
113 | .form-select {
114 | appearance: none;
115 | border: $border-width solid $border-color-dark;
116 | border-radius: $border-radius;
117 | color: inherit;
118 | font-size: $font-size;
119 | height: $control-size;
120 | line-height: $line-height;
121 | outline: none;
122 | padding: $control-padding-y $control-padding-x;
123 | vertical-align: middle;
124 | width: 100%;
125 | background: $bg-color-light;
126 | &:focus {
127 | @include control-shadow();
128 | border-color: $primary-color;
129 | }
130 | &::-ms-expand {
131 | display: none;
132 | }
133 |
134 | // Select sizes
135 | &.select-sm {
136 | font-size: $font-size-sm;
137 | height: $control-size-sm;
138 | padding: $control-padding-y-sm ($control-icon-size + $control-padding-x-sm) $control-padding-y-sm $control-padding-x-sm;
139 | }
140 |
141 | &.select-lg {
142 | font-size: $font-size-lg;
143 | height: $control-size-lg;
144 | padding: $control-padding-y-lg ($control-icon-size + $control-padding-x-lg) $control-padding-y-lg $control-padding-x-lg;
145 | }
146 |
147 | // Multiple select
148 | &[size],
149 | &[multiple] {
150 | height: auto;
151 | padding: $control-padding-y $control-padding-x;
152 |
153 | option {
154 | padding: $unit-h $unit-1;
155 | }
156 | }
157 | &:not([multiple]):not([size]) {
158 | background: $bg-color-light url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%204%205'%3E%3Cpath%20fill='%23667189'%20d='M2%200L0%202h4zm0%205L0%203h4z'/%3E%3C/svg%3E") no-repeat right .35rem center / .4rem .5rem;
159 | padding-right: $control-icon-size + $control-padding-x;
160 | }
161 | }
162 |
163 | // Form Icons
164 | .has-icon-left,
165 | .has-icon-right {
166 | position: relative;
167 |
168 | .form-icon {
169 | height: $control-icon-size;
170 | margin: 0 $control-padding-y;
171 | position: absolute;
172 | top: 50%;
173 | transform: translateY(-50%);
174 | width: $control-icon-size;
175 | z-index: $zindex-0 + 1;
176 | }
177 | }
178 |
179 | .has-icon-left {
180 | .form-icon {
181 | left: $border-width;
182 | }
183 |
184 | .form-input {
185 | padding-left: $control-icon-size + $control-padding-y * 2;
186 | }
187 | }
188 |
189 | .has-icon-right {
190 | .form-icon {
191 | right: $border-width;
192 | }
193 |
194 | .form-input {
195 | padding-right: $control-icon-size + $control-padding-y * 2;
196 | }
197 | }
198 |
199 | // Form element: Checkbox and Radio
200 | .form-checkbox,
201 | .form-radio,
202 | .form-switch {
203 | display: block;
204 | line-height: $line-height;
205 | margin: ($control-size - $control-size-sm) / 2 0;
206 | min-height: $control-size-sm;
207 | padding: (($control-size-sm - $line-height) / 2) $control-padding-x (($control-size-sm - $line-height) / 2) ($control-icon-size + $control-padding-x);
208 | position: relative;
209 |
210 | input {
211 | clip: rect(0, 0, 0, 0);
212 | height: 1px;
213 | margin: -1px;
214 | overflow: hidden;
215 | position: absolute;
216 | width: 1px;
217 | &:focus + .form-icon {
218 | @include control-shadow();
219 | border-color: $primary-color;
220 | }
221 | &:checked + .form-icon {
222 | background: $primary-color;
223 | border-color: $primary-color;
224 | }
225 | }
226 |
227 | .form-icon {
228 | border: $border-width solid $border-color-dark;
229 | cursor: pointer;
230 | display: inline-block;
231 | position: absolute;
232 | transition: background .2s, border .2s, box-shadow .2s, color .2s;
233 | }
234 |
235 | // Input checkbox, radio and switch sizes
236 | &.input-sm {
237 | font-size: $font-size-sm;
238 | margin: 0;
239 | }
240 |
241 | &.input-lg {
242 | font-size: $font-size-lg;
243 | margin: ($control-size-lg - $control-size-sm) / 2 0;
244 | }
245 | }
246 |
247 | .form-checkbox,
248 | .form-radio {
249 | .form-icon {
250 | background: $bg-color-light;
251 | height: $control-icon-size;
252 | left: 0;
253 | top: ($control-size-sm - $control-icon-size) / 2;
254 | width: $control-icon-size;
255 | }
256 |
257 | input {
258 | &:active + .form-icon {
259 | background: $bg-color-dark;
260 | }
261 | }
262 | }
263 | .form-checkbox {
264 | .form-icon {
265 | border-radius: $border-radius;
266 | }
267 |
268 | input {
269 | &:checked + .form-icon {
270 | &::before {
271 | background-clip: padding-box;
272 | border: $border-width-lg solid $light-color;
273 | border-left-width: 0;
274 | border-top-width: 0;
275 | content: "";
276 | height: 9px;
277 | left: 50%;
278 | margin-left: -3px;
279 | margin-top: -6px;
280 | position: absolute;
281 | top: 50%;
282 | transform: rotate(45deg);
283 | width: 6px;
284 | }
285 | }
286 | &:indeterminate + .form-icon {
287 | background: $primary-color;
288 | border-color: $primary-color;
289 | &::before {
290 | background: $bg-color-light;
291 | content: "";
292 | height: 2px;
293 | left: 50%;
294 | margin-left: -5px;
295 | margin-top: -1px;
296 | position: absolute;
297 | top: 50%;
298 | width: 10px;
299 | }
300 | }
301 | }
302 | }
303 | .form-radio {
304 | .form-icon {
305 | border-radius: 50%;
306 | }
307 |
308 | input {
309 | &:checked + .form-icon {
310 | &::before {
311 | background: $bg-color-light;
312 | border-radius: 50%;
313 | content: "";
314 | height: 6px;
315 | left: 50%;
316 | position: absolute;
317 | top: 50%;
318 | transform: translate(-50%, -50%);
319 | width: 6px;
320 | }
321 | }
322 | }
323 | }
324 |
325 | // Form element: Switch
326 | .form-switch {
327 | padding-left: ($unit-8 + $control-padding-x);
328 |
329 | .form-icon {
330 | background: $gray-color;
331 | background-clip: padding-box;
332 | border-radius: $unit-2 + $border-width;
333 | height: $unit-4 + $border-width * 2;
334 | left: 0;
335 | top: ($control-size-sm - $unit-4) / 2 - $border-width;
336 | width: $unit-8;
337 | &::before {
338 | background: $bg-color-light;
339 | border-radius: 50%;
340 | content: "";
341 | display: block;
342 | height: $unit-4;
343 | left: 0;
344 | position: absolute;
345 | top: 0;
346 | transition: background .2s, border .2s, box-shadow .2s, color .2s, left .2s;
347 | width: $unit-4;
348 | }
349 | }
350 |
351 | input {
352 | &:checked + .form-icon {
353 | &::before {
354 | left: 14px;
355 | }
356 | }
357 | &:active + .form-icon {
358 | &::before {
359 | background: $bg-color;
360 | }
361 | }
362 | }
363 | }
364 |
365 | // Form element: Input groups
366 | .input-group {
367 | display: flex;
368 |
369 | .input-group-addon {
370 | background: $bg-color;
371 | border: $border-width solid $border-color-dark;
372 | border-radius: $border-radius;
373 | line-height: $line-height;
374 | padding: $control-padding-y $control-padding-x;
375 | white-space: nowrap;
376 |
377 | &.addon-sm {
378 | font-size: $font-size-sm;
379 | padding: $control-padding-y-sm $control-padding-x-sm;
380 | }
381 |
382 | &.addon-lg {
383 | font-size: $font-size-lg;
384 | padding: $control-padding-y-lg $control-padding-x-lg;
385 | }
386 | }
387 |
388 | .form-input,
389 | .form-select {
390 | flex: 1 1 auto;
391 | width: 1%;
392 | }
393 |
394 | .input-group-btn {
395 | z-index: $zindex-0;
396 | }
397 |
398 | .form-input,
399 | .form-select,
400 | .input-group-addon,
401 | .input-group-btn {
402 | &:first-child:not(:last-child) {
403 | border-bottom-right-radius: 0;
404 | border-top-right-radius: 0;
405 | }
406 | &:not(:first-child):not(:last-child) {
407 | border-radius: 0;
408 | margin-left: -$border-width;
409 | }
410 | &:last-child:not(:first-child) {
411 | border-bottom-left-radius: 0;
412 | border-top-left-radius: 0;
413 | margin-left: -$border-width;
414 | }
415 | &:focus {
416 | z-index: $zindex-0 + 1;
417 | }
418 | }
419 |
420 | .form-select {
421 | width: auto;
422 | }
423 |
424 | &.input-inline {
425 | display: inline-flex;
426 | }
427 | }
428 |
429 | // Form validation states
430 | .form-input,
431 | .form-select {
432 | .has-success &,
433 | &.is-success {
434 | background: lighten($success-color, 53%);
435 | border-color: $success-color;
436 | &:focus {
437 | @include control-shadow($success-color);
438 | }
439 | }
440 |
441 | .has-error &,
442 | &.is-error {
443 | background: lighten($error-color, 53%);
444 | border-color: $error-color;
445 | &:focus {
446 | @include control-shadow($error-color);
447 | }
448 | }
449 | }
450 |
451 | .form-checkbox,
452 | .form-radio,
453 | .form-switch {
454 | .has-error &,
455 | &.is-error {
456 | .form-icon {
457 | border-color: $error-color;
458 | }
459 |
460 | input {
461 | &:checked + .form-icon {
462 | background: $error-color;
463 | border-color: $error-color;
464 | }
465 |
466 | &:focus + .form-icon {
467 | @include control-shadow($error-color);
468 | border-color: $error-color;
469 | }
470 | }
471 | }
472 | }
473 |
474 | .form-checkbox {
475 | .has-error &,
476 | &.is-error {
477 | input {
478 | &:indeterminate + .form-icon {
479 | background: $error-color;
480 | border-color: $error-color;
481 | }
482 | }
483 | }
484 | }
485 |
486 | // validation based on :placeholder-shown (Edge doesn't support it yet)
487 | .form-input {
488 | &:not(:placeholder-shown) {
489 | &:invalid {
490 | border-color: $error-color;
491 | &:focus {
492 | @include control-shadow($error-color);
493 | background: lighten($error-color, 53%);
494 | }
495 |
496 | & + .form-input-hint {
497 | color: $error-color;
498 | }
499 | }
500 | }
501 | }
502 |
503 | // Form disabled and readonly
504 | .form-input,
505 | .form-select {
506 | &:disabled,
507 | &.disabled {
508 | background-color: $bg-color-dark;
509 | cursor: not-allowed;
510 | opacity: .5;
511 | }
512 | }
513 |
514 | .form-input {
515 | &[readonly] {
516 | background-color: $bg-color;
517 | }
518 | }
519 |
520 | input {
521 | &:disabled,
522 | &.disabled {
523 | & + .form-icon {
524 | background: $bg-color-dark;
525 | cursor: not-allowed;
526 | opacity: .5;
527 | }
528 | }
529 | }
530 |
531 | .form-switch {
532 | input {
533 | &:disabled,
534 | &.disabled {
535 | & + .form-icon::before {
536 | background: $bg-color-light;
537 | }
538 | }
539 | }
540 | }
541 |
542 | // Form horizontal
543 | .form-horizontal {
544 | padding: $layout-spacing 0;
545 |
546 | .form-group {
547 | display: flex;
548 | flex-wrap: wrap;
549 | }
550 | }
551 |
552 | // Form inline
553 | .form-inline {
554 | display: inline-block;
555 | }
556 |
--------------------------------------------------------------------------------