beercss 3.12.13 → 3.13.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.
@@ -1,4 +1,4 @@
1
- import { addClass, next, prev, hasTag, insertBefore, wait, create, hasClass, removeClass, on, off, queryAllDataUi, blurActiveElement, query } from "../utils";
1
+ import { addClass, next, prev, hasTag, insertBefore, wait, create, hasClass, removeClass, on, off, queryAllDataUi, blurActiveElement, query, onWeak } from "../utils";
2
2
 
3
3
  const _dialogs: Array<HTMLDialogElement> = [];
4
4
 
@@ -62,7 +62,7 @@ export async function updateDialog(from: Element, dialog: HTMLDialogElement): Pr
62
62
  await wait(90);
63
63
  }
64
64
 
65
- if (!isModal) on(overlay, "click", onClickOverlay, false);
65
+ if (!isModal) onWeak(overlay, "click", onClickOverlay, false);
66
66
 
67
67
  if (isActive) closeDialog(dialog, overlay);
68
68
  else void openDialog(dialog, overlay, isModal, from);
@@ -1,44 +1,36 @@
1
1
  .field {
2
- --_size: 3rem;
2
+ --_input: 3rem;
3
3
  --_start: 1.2rem;
4
- block-size: var(--_size);
5
- margin-block-end: 2rem;
4
+ --_middle: calc(var(--_input) / 2);
6
5
  border-radius: 0.25rem 0.25rem 0 0;
7
- max-block-size: 12rem;
8
- }
9
-
10
- .grid > * > .field {
11
- margin-block-end: 1rem;
12
- }
13
-
14
- .grid > * > .field + .field {
15
- margin-block-start: 2rem;
16
- }
17
-
18
- .grid.no-space > * > .field + .field {
19
- margin-block-start: 1rem;
6
+ min-block-size: var(--_input);
7
+ display: flex;
8
+ flex-direction: column;
20
9
  }
21
10
 
22
- .grid.medium-space > * > .field + .field {
23
- margin-block-start: 2.5rem;
11
+ .field.fill {
12
+ --_background: var(--surface-variant);
13
+ background-color: unset !important;
14
+ color: unset !important;
24
15
  }
25
16
 
26
- .grid.large-space > * > .field + .field {
27
- margin-block-start: 3rem;
17
+ .field.fill > :is(input, select, textarea) {
18
+ background-color: var(--_background);
19
+ z-index: 0;
28
20
  }
29
21
 
30
22
  .field.small {
31
- --_size: 2.5rem;
23
+ --_input: 2.5rem;
32
24
  --_start: 1rem;
33
25
  }
34
26
 
35
27
  .field.large {
36
- --_size: 3.5rem;
28
+ --_input: 3.5rem;
37
29
  --_start: 1.4rem;
38
30
  }
39
31
 
40
32
  .field.extra {
41
- --_size: 4rem;
33
+ --_input: 4rem;
42
34
  --_start: 1.6rem;
43
35
  }
44
36
 
@@ -63,42 +55,42 @@
63
55
  }
64
56
 
65
57
  /* icon */
66
- .field > :is(i, img, svg, progress, a:not(.helper, .error)) {
58
+ .field > :is(i, img, svg, progress.circle, a) {
67
59
  position: absolute;
68
- inset: 50% auto auto auto;
69
- transform: translateY(-50%);
60
+ inset: calc((var(--_input) / 2) - 0.75rem) auto auto auto;
70
61
  cursor: pointer;
71
- z-index: 0;
62
+ z-index: 10;
72
63
  inline-size: 1.5rem;
73
64
  block-size: 1.5rem;
65
+ margin: auto 0;
66
+ pointer-events: none;
74
67
  }
75
68
 
76
- .field > :is(i, img, svg, progress, a:not(.helper, .error)),
77
- [dir=rtl] .field > :is(i, img, svg, progress, a:not(.helper, .error)):first-child {
78
- inset: 50% 1rem auto auto;
69
+ .field > :is(a, .front) {
70
+ pointer-events: all !important;
79
71
  }
80
72
 
81
- .field > :is(i, img, svg, progress, a:not(.helper, .error)):first-child,
82
- [dir=rtl] .field > :is(i, img, svg, progress, a:not(.helper, .error)) {
83
- inset: 50% auto auto 1rem;
73
+ .field > a > :is(i, img, svg, progress.circle, a) {
74
+ inline-size: 1.5rem;
75
+ block-size: 1.5rem;
84
76
  }
85
77
 
86
- .field.invalid > i {
87
- color: var(--error);
78
+ .field > :is(i, img, svg, progress.circle, a),
79
+ [dir=rtl] .field > :is(i, img, svg, progress.circle, a):first-child {
80
+ inset: calc(var(--_middle) - 0.75rem) 1rem auto auto;
88
81
  }
89
82
 
90
- .field > progress.circle {
91
- inset-block-start: calc(50% - 0.75rem) !important;
92
- border-width: 0.1875rem;
83
+ .field > :is(i, img, svg, progress.circle, a):first-child,
84
+ [dir=rtl] .field > :is(i, img, svg, progress.circle, a) {
85
+ inset: calc(var(--_middle) - 0.75rem) auto auto 1rem;
93
86
  }
94
87
 
95
- .field > a:not(.helper, .error) {
96
- z-index: 10;
88
+ .field.invalid > i {
89
+ color: var(--error);
97
90
  }
98
91
 
99
- .field > a > :is(i, img, svg, progress, a:not(.helper, .error)) {
100
- inline-size: 1.5rem;
101
- block-size: 1.5rem;
92
+ .field > progress.circle {
93
+ border-width: 0.1875rem;
102
94
  }
103
95
 
104
96
  /* input, textarea and select */
@@ -114,7 +106,7 @@
114
106
  font-family: inherit;
115
107
  font-size: 1rem;
116
108
  inline-size: 100%;
117
- block-size: 100%;
109
+ min-block-size: var(--_input);
118
110
  outline: none;
119
111
  z-index: 1;
120
112
  background: none;
@@ -137,10 +129,9 @@ input::-webkit-date-and-time-value {
137
129
  padding: 0 0.875rem;
138
130
  }
139
131
 
140
- .field.min > textarea {
141
- overflow: hidden auto;
142
- position: absolute;
143
- inset: 0;
132
+ .field > textarea:not([rows]) {
133
+ field-sizing: content;
134
+ max-block-size: 12rem;
144
135
  }
145
136
 
146
137
  input[type=file],
@@ -249,22 +240,6 @@ input[type=number] {
249
240
  cursor: not-allowed;
250
241
  }
251
242
 
252
- .field.textarea.small:not(.min) {
253
- --_size: 5rem;
254
- }
255
-
256
- .field.textarea:not(.min) {
257
- --_size: 5.5rem;
258
- }
259
-
260
- .field.textarea.large:not(.min) {
261
- --_size: 6rem;
262
- }
263
-
264
- .field.textarea.extra:not(.min) {
265
- --_size: 6.5rem;
266
- }
267
-
268
243
  .field > select {
269
244
  user-select: none;
270
245
  }
@@ -287,32 +262,31 @@ input[type=number] {
287
262
  background-color: var(--surface);
288
263
  }
289
264
 
290
- .field.label > :is(input, select) {
265
+ .field > :is(input, select) {
291
266
  padding-block-start: 1rem;
292
267
  }
293
268
 
294
- .field.label.border:not(.fill) > :is(input, select) {
269
+ .field:not(.label) > :is(input, select),
270
+ .field.border:not(.fill) > :is(input, select) {
295
271
  padding-block-start: 0;
296
272
  }
297
273
 
298
274
  .field > textarea {
299
- padding-block-start: var(--_start);
300
- white-space: pre-wrap;
301
- overflow-wrap: break-word;
275
+ padding-block-start: calc(var(--_start)) !important;
302
276
  }
303
277
 
304
278
  .field > textarea:focus {
305
- padding-block-start: calc(var(--_start) - 0.06rem);
279
+ padding-block-start: calc(var(--_start) - 0.01rem) !important;
306
280
  }
307
281
 
308
282
  .field:not(.label) > textarea,
309
- .field.border.label:not(.fill) > textarea {
310
- padding-block-start: calc(var(--_start) - 0.5rem);
283
+ .field.border:not(.fill) > textarea {
284
+ padding-block-start: calc(var(--_start) - 0.5rem) !important;
311
285
  }
312
286
 
313
287
  .field:not(.label) > textarea:focus,
314
- .field.border.label:not(.fill) > textarea:focus {
315
- padding-block-start: calc(var(--_start) - 0.56rem);
288
+ .field.border:not(.fill) > textarea:focus {
289
+ padding-block-start: calc(var(--_start) - 0.51rem) !important;
316
290
  }
317
291
 
318
292
  /* label */
@@ -321,21 +295,25 @@ input[type=number] {
321
295
  position: absolute;
322
296
  inset: -0.5rem 1rem 0 var(--_start);
323
297
  display: flex;
324
- block-size: calc(var(--_size) + 1rem);
325
- line-height: calc(var(--_size) + 1rem);
298
+ block-size: calc(var(--_input) + 1rem);
299
+ line-height: calc(var(--_input) + 1rem);
326
300
  font-size: 1rem;
327
301
  transition: all 0.2s;
328
302
  gap: 0.25rem;
329
303
  white-space: nowrap;
304
+ pointer-events: none;
305
+ }
306
+
307
+ [dir=rtl] .field.label > label {
308
+ inset: -0.5rem var(--_start) 0 1rem;
330
309
  }
331
310
 
332
311
  .field.label.round > label {
333
312
  inset: -0.5rem 1.75rem 0 var(--_start);
334
313
  }
335
314
 
336
- .field.label.textarea:not(.min) > label {
337
- block-size: calc(var(--_size) - 1.5rem);
338
- line-height: calc(var(--_size) - 1.5rem);
315
+ [dir=rtl] .field.label.round > label {
316
+ inset: -0.5rem 1.75rem 0 var(--_start);
339
317
  }
340
318
 
341
319
  .field.label.border.prefix:not(.fill) > :is(label.active, :focus + label, [placeholder]:not(:placeholder-shown) + label, select + label) {
@@ -420,32 +398,24 @@ input[type=number] {
420
398
  }
421
399
 
422
400
  /* helper */
423
- .field > :is(.helper, .error) {
424
- position: absolute;
425
- inset: auto auto 0 1rem;
426
- transform: translateY(100%);
401
+ .field > output {
402
+ display: inline-block;
427
403
  font-size: 0.75rem;
428
404
  background: none !important;
429
- padding-block-start: 0.125rem;
430
- }
431
-
432
- [dir=rtl] .field > :is(.helper, .error) {
433
- inset: auto 1rem 0 auto;
434
- }
435
-
436
- a.helper {
437
- color: var(--primary);
405
+ padding: 0.25rem 1rem;
406
+ line-height: 1.25rem;
407
+ align-self: start;
438
408
  }
439
409
 
440
- .field > .error {
410
+ .field > output.invalid {
441
411
  color: var(--error) !important;
442
412
  }
443
413
 
444
- .field.round > :is(.helper, .error) {
445
- inset-inline-start: 1.5rem;
414
+ .field.round > output {
415
+ padding: 0.25rem 1.5rem;
446
416
  }
447
417
 
448
- .field.invalid > .helper {
418
+ .field.invalid > output:not(.invalid) {
449
419
  display: none;
450
420
  }
451
421
 
@@ -1,4 +1,4 @@
1
- import { query, hasClass, on, next, prev, hasType, parent, queryAll } from "../utils";
1
+ import { query, next, prev, hasType, parent, queryAll, onWeak, isChrome, isMac, isIOS, on, hasClass, rootSizeInPixels } from "../utils";
2
2
 
3
3
  function updatePlaceholder(element: HTMLInputElement | HTMLTextAreaElement) {
4
4
  if (!element.placeholder) element.placeholder = " ";
@@ -41,27 +41,29 @@ function onKeydownColor(e: KeyboardEvent) {
41
41
  updateColor(input, e);
42
42
  }
43
43
 
44
- function onInputTextarea(e: Event) {
45
- const textarea = e.currentTarget as HTMLTextAreaElement;
46
- updateTextarea(textarea);
47
- }
48
-
49
44
  function onPasswordIconClick(e: Event) {
50
45
  const icon = e.currentTarget as HTMLElement;
51
46
  const input = query("input", parent(icon)) as HTMLInputElement;
52
47
  if (input && icon.textContent?.includes("visibility")) input.type = input.type === "password" ? "text" : "password";
53
48
  }
54
49
 
50
+ function onInputTextarea(e: Event) {
51
+ const textarea = e.currentTarget as HTMLTextAreaElement;
52
+ updateTextarea(textarea);
53
+ }
54
+
55
55
  function updateAllLabels() {
56
56
  const labels = queryAll(".field > label");
57
- for (let i=0; i<labels.length; i++) on(labels[i], "click", onClickLabel);
57
+ for (let i=0; i<labels.length; i++) {
58
+ onWeak(labels[i], "click", onClickLabel);
59
+ }
58
60
  }
59
61
 
60
62
  function updateAllInputs() {
61
63
  const inputs = queryAll(".field > input:not([type=file], [type=color], [type=range])") as NodeListOf<HTMLInputElement>;
62
64
  for (let i=0; i<inputs.length; i++) {
63
- on(inputs[i], "focus", onFocusInput);
64
- on(inputs[i], "blur", onBlurInput);
65
+ onWeak(inputs[i], "focus", onFocusInput);
66
+ onWeak(inputs[i], "blur", onBlurInput);
65
67
  updateInput(inputs[i]);
66
68
  }
67
69
  }
@@ -69,15 +71,15 @@ function updateAllInputs() {
69
71
  function updateAllSelects() {
70
72
  const selects = queryAll(".field > select") as NodeListOf<HTMLSelectElement>;
71
73
  for (let i=0; i<selects.length; i++) {
72
- on(selects[i], "focus", onFocusInput);
73
- on(selects[i], "blur", onBlurInput);
74
+ onWeak(selects[i], "focus", onFocusInput);
75
+ onWeak(selects[i], "blur", onBlurInput);
74
76
  }
75
77
  }
76
78
 
77
79
  function updateAllFiles() {
78
80
  const files = queryAll(".field > input[type=file]") as NodeListOf<HTMLInputElement>;
79
81
  for (let i=0; i<files.length; i++) {
80
- on(files[i], "change", onChangeFile);
82
+ onWeak(files[i], "change", onChangeFile);
81
83
  updateFile(files[i]);
82
84
  }
83
85
  }
@@ -85,24 +87,26 @@ function updateAllFiles() {
85
87
  function updateAllColors() {
86
88
  const colors = queryAll(".field > input[type=color]") as NodeListOf<HTMLInputElement>;
87
89
  for (let i=0; i<colors.length; i++) {
88
- on(colors[i], "change", onChangeColor);
90
+ onWeak(colors[i], "change", onChangeColor);
89
91
  updateColor(colors[i]);
90
92
  }
91
93
  }
92
94
 
93
95
  function updateAllTextareas() {
94
- const textareas = queryAll(".field.textarea > textarea") as NodeListOf<HTMLTextAreaElement>;
96
+ if (isChrome && !isMac && !isIOS) return;
97
+
98
+ const textareas = queryAll(".field > textarea") as NodeListOf<HTMLTextAreaElement>;
95
99
  for (let i=0; i<textareas.length; i++) {
96
- on(textareas[i], "focus", onFocusInput);
97
- on(textareas[i], "blur", onBlurInput);
98
- on(textareas[i], "input", onInputTextarea);
100
+ onWeak(textareas[i], "focus", onFocusInput);
101
+ onWeak(textareas[i], "blur", onBlurInput);
102
+ onWeak(textareas[i], "input", onInputTextarea);
99
103
  updateTextarea(textareas[i]);
100
104
  }
101
105
  }
102
106
 
103
107
  function updateAllPasswordIcons() {
104
108
  const icons = queryAll("input[type=password] ~ :is(i, a)");
105
- for (let i=0; i<icons.length; i++) on(icons[i], "click", onPasswordIconClick);
109
+ for (let i=0; i<icons.length; i++) onWeak(icons[i], "click", onPasswordIconClick);
106
110
  }
107
111
 
108
112
  function updateInput(input: HTMLInputElement) {
@@ -121,7 +125,7 @@ function updateFile(input: HTMLInputElement, e?: KeyboardEvent) {
121
125
  if (!hasType(nextInput, "text")) return;
122
126
  nextInput.value = input.files ? Array.from(input.files).map((x) => x.name).join(", ") : "";
123
127
  nextInput.readOnly = true;
124
- on(nextInput, "keydown", onKeydownFile, false);
128
+ onWeak(nextInput, "keydown", onKeydownFile, false);
125
129
  updateInput(nextInput);
126
130
  }
127
131
 
@@ -136,15 +140,18 @@ function updateColor(input: HTMLInputElement, e?: KeyboardEvent) {
136
140
  if (!hasType(nextInput, "text")) return;
137
141
  nextInput.readOnly = true;
138
142
  nextInput.value = input.value;
139
- on(nextInput, "keydown", onKeydownColor, false);
143
+ onWeak(nextInput, "keydown", onKeydownColor, false);
140
144
  updateInput(nextInput);
141
145
  }
142
146
 
143
147
  function updateTextarea(textarea: HTMLTextAreaElement) {
144
148
  updatePlaceholder(textarea);
145
- const field = parent(textarea) as HTMLElement;
146
- field.removeAttribute("style");
147
- if (hasClass(field, "min")) field.style.setProperty("--_size", `${Math.max(textarea.scrollHeight, field.offsetHeight)}px`);
149
+
150
+ if (textarea.hasAttribute("rows")) return;
151
+
152
+ const rootSize = rootSizeInPixels();
153
+ textarea.style.blockSize = "auto";
154
+ textarea.style.blockSize = `${textarea.scrollHeight - rootSize}px`;
148
155
  }
149
156
 
150
157
  export function updateAllFields() {
@@ -14,6 +14,7 @@ progress {
14
14
  writing-mode: horizontal-tb;
15
15
  direction: ltr;
16
16
  -webkit-appearance: none;
17
+ appearance: none;
17
18
  }
18
19
 
19
20
  .dark progress {
@@ -93,32 +94,42 @@ progress.wavy::-moz-progress-bar {
93
94
  }
94
95
 
95
96
  progress.circle {
96
- display: inline-block;
97
+ --_value: attr(value type(<number>), 50);
97
98
  inline-size: 2.5rem;
98
99
  block-size: 2.5rem;
100
+ background: conic-gradient(currentColor calc(var(--_value) * 1%), var(--active) 0%);
99
101
  border-radius: 50%;
100
- border-width: 0.3rem;
101
- border-style: solid;
102
- border-color: currentcolor;
103
- animation: 1.6s to-circular linear infinite;
102
+ mask-image: radial-gradient(circle at center, transparent 57%, currentColor 60%);
103
+ }
104
+
105
+ progress.circle::-webkit-progress-value {
104
106
  background: none;
105
- flex: none;
106
107
  }
107
108
 
108
109
  progress.circle::-moz-progress-bar {
109
110
  background: none;
110
111
  }
111
112
 
113
+ progress.circle.wavy {
114
+ background: conic-gradient(currentColor calc(var(--_value) * 1%), var(--active) 0);
115
+ mask-repeat: no-repeat;
116
+ mask-position: center;
117
+ mask-size: contain;
118
+ mask-image: url(../shapes/wavy-circle.svg);
119
+ }
120
+
112
121
  progress.circle.small {
113
122
  inline-size: 1.5rem;
114
123
  block-size: 1.5rem;
115
- border-width: 0.2rem;
116
124
  }
117
125
 
118
126
  progress.circle.large {
119
127
  inline-size: 3.5rem;
120
128
  block-size: 3.5rem;
121
- border-width: 0.4rem;
129
+ }
130
+
131
+ progress.circle:not([value]) {
132
+ animation: to-rotate 1s infinite linear;
122
133
  }
123
134
 
124
135
  :is(nav, .row, .field) > progress:not(.circle, .small, .medium, .large) {
@@ -143,19 +154,6 @@ progress.max[class*='-text'] {
143
154
  opacity: 1;
144
155
  }
145
156
 
146
- progress:is(.horizontal, .vertical, .max) {
147
- display: unset;
148
- inline-size: 100% !important;
149
- }
150
-
151
- progress.vertical {
152
- writing-mode: vertical-lr;
153
- }
154
-
155
- progress.max.vertical {
156
- transform: rotate(-180deg);
157
- }
158
-
159
157
  progress.max + * {
160
158
  margin-block-start: 0;
161
159
  }
@@ -164,12 +162,6 @@ progress.max + * {
164
162
  color: inherit;
165
163
  }
166
164
 
167
- @supports (-moz-appearance:none) {
168
- progress.max.vertical {
169
- transform: none;
170
- }
171
- }
172
-
173
165
  @keyframes to-linear {
174
166
  0% {
175
167
  margin-inline-start: -100%;
@@ -184,46 +176,14 @@ progress.max + * {
184
176
  }
185
177
  }
186
178
 
187
- @keyframes to-circular {
188
- 0% {
179
+ @keyframes to-rotate {
180
+ from {
181
+ --_value: 50;
189
182
  transform: rotate(0deg);
190
- clip-path: polygon(50% 50%, 0% 0%, 50% 0%, 50% 0%, 50% 0%, 50% 0%, 50% 0%, 50% 0%, 50% 0%);
191
183
  }
192
184
 
193
- 20% {
194
- clip-path: polygon(50% 50%, 0% 0%, 50% 0%, 100% 0%, 100% 0%, 100% 0%, 100% 0%, 100% 0%, 100% 0%);
195
- }
196
-
197
- 30% {
198
- clip-path: polygon(50% 50%, 0% 0%, 50% 0%, 100% 0%, 100% 50%, 100% 50%, 100% 50%, 100% 50%, 100% 50%);
199
- }
200
-
201
- 40% {
202
- clip-path: polygon(50% 50%, 0% 0%, 50% 0%, 100% 0%, 100% 50%, 100% 100%, 100% 100%, 100% 100%, 100% 100%);
203
- }
204
-
205
- 50% {
206
- clip-path: polygon(50% 50%, 50% 0%, 50% 0%, 100% 0%, 100% 50%, 100% 100%, 50% 100%, 50% 100%, 50% 100%);
207
- }
208
-
209
- 60% {
210
- clip-path: polygon(50% 50%, 100% 50%, 100% 50%, 100% 50%, 100% 50%, 100% 100%, 50% 100%, 0% 100%, 0% 100%);
211
- }
212
-
213
- 70% {
214
- clip-path: polygon(50% 50%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 0% 100%, 0% 50%);
215
- }
216
-
217
- 80% {
218
- clip-path: polygon(50% 50%, 0% 100%, 0% 100%, 0% 100%, 0% 100%, 0% 100%, 0% 100%, 0% 100%, 0% 50%);
219
- }
220
-
221
- 90% {
185
+ to {
186
+ --_value: 50;
222
187
  transform: rotate(360deg);
223
- clip-path: polygon(50% 50%, 0% 50%, 0% 50%, 0% 50%, 0% 50%, 0% 50%, 0% 50%, 0% 50%, 0% 50%);
224
188
  }
225
-
226
- 100% {
227
- clip-path: polygon(50% 50%, 0% 50%, 0% 50%, 0% 50%, 0% 50%, 0% 50%, 0% 50%, 0% 50%, 0% 50%);
228
- }
229
- }
189
+ }
@@ -0,0 +1,26 @@
1
+ import { queryAll, hasTag, off, on, isMac, isIOS, isChrome } from "../utils";
2
+
3
+
4
+ function onInputDocument(e: Event) {
5
+ const progress = e.target as HTMLProgressElement;
6
+
7
+ if (hasTag(progress, "progress")) {
8
+ updateProgress(progress);
9
+ } else {
10
+ updateAllProgress();
11
+ }
12
+ }
13
+
14
+ function updateProgress(progress: HTMLProgressElement) {
15
+ progress.style.setProperty("--_value", String(progress.value));
16
+ }
17
+
18
+ export function updateAllProgress() {
19
+ if (isChrome && !isMac && !isIOS) return;
20
+
21
+ const body = document.body;
22
+ const progresses = queryAll("progress") as NodeListOf<HTMLProgressElement>;
23
+ if (!progresses.length) off(body, "input", onInputDocument, false);
24
+ else on(body, "input", onInputDocument, false);
25
+ for (let i = 0; i < progresses.length; i++) updateProgress(progresses[i]);
26
+ }
@@ -3,7 +3,6 @@
3
3
  .radio,
4
4
  .switch {
5
5
  --_size: 1.5rem;
6
- direction: ltr;
7
6
  inline-size: auto;
8
7
  block-size: auto;
9
8
  line-height: normal;
@@ -13,6 +12,10 @@
13
12
  align-items: center;
14
13
  }
15
14
 
15
+ .switch {
16
+ direction: ltr;
17
+ }
18
+
16
19
  :is(.checkbox, .radio, .switch).small {
17
20
  --_size: 1rem;
18
21
  }
@@ -66,6 +69,13 @@
66
69
  z-index: 1;
67
70
  }
68
71
 
72
+ [dir=rtl] :is(.checkbox, .radio) > span::before,
73
+ [dir=rtl] :is(.checkbox, .radio) > span > i,
74
+ [dir=rtl] :is(.checkbox, .radio) > span::after {
75
+ --_size: inherit;
76
+ inset: auto calc(var(--_size) * -1) auto auto;
77
+ }
78
+
69
79
  .switch > span::before,
70
80
  .switch.icon > span > i {
71
81
  position: absolute;
@@ -165,16 +175,31 @@
165
175
  transform: translate(-1.75rem, -50%) scale(1);
166
176
  }
167
177
 
178
+ [dir=rtl] .switch > input:checked + span::before,
179
+ [dir=rtl] .switch.icon > input:checked + span > i {
180
+ transform: translate(-1.75rem, -50%) scale(-1);
181
+ }
182
+
168
183
  .switch > input:active:not(:disabled) + span::before,
169
184
  .switch.icon > input:active:not(:disabled) + span > i {
170
185
  transform: translate(-3rem, -50%) scale(1.2);
171
186
  }
172
187
 
188
+ [dir=rtl] .switch > input:active:not(:disabled) + span::before,
189
+ [dir=rtl] .switch.icon > input:active:not(:disabled) + span > i {
190
+ transform: translate(-3rem, -50%) scale(-1.2);
191
+ }
192
+
173
193
  .switch > input:active:checked:not(:disabled) + span::before,
174
194
  .switch.icon > input:active:checked:not(:disabled) + span > i {
175
195
  transform: translate(-1.75rem, -50%) scale(1.2);
176
196
  }
177
197
 
198
+ [dir=rtl] .switch > input:active:checked:not(:disabled) + span::before,
199
+ [dir=rtl] .switch.icon > input:active:checked:not(:disabled) + span > i {
200
+ transform: translate(-1.75rem, -50%) scale(-1.2);
201
+ }
202
+
178
203
  :is(.checkbox, .radio, .switch) > input:disabled + span {
179
204
  opacity: 0.5;
180
205
  cursor: not-allowed;
@@ -351,4 +351,8 @@
351
351
  .slider > :hover ~ .tooltip.bottom {
352
352
  inset-block: auto -1rem !important;
353
353
  }
354
+
355
+ body:has(input[type=range]:focus) {
356
+ overflow: hidden;
357
+ }
354
358
  }