@sveltia/ui 0.31.1 → 0.31.2

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.
@@ -9,6 +9,7 @@
9
9
  -->
10
10
  <script>
11
11
  import { onMount } from 'svelte';
12
+ import { isRTL } from '../../services/i18n.js';
12
13
 
13
14
  /**
14
15
  * @import { Snippet } from 'svelte';
@@ -81,22 +82,23 @@
81
82
 
82
83
  /**
83
84
  * Move a thumb with mouse.
84
- * @param {number} diff Distance from the original X position in pixels.
85
+ * @param {number} physicalX Physical X position in pixels from the left edge.
85
86
  */
86
- const moveThumb = (diff) => {
87
- if (diff < 0) {
88
- diff = 0;
89
- } else if (diff > barWidth) {
90
- diff = barWidth;
91
- }
87
+ const moveThumb = (physicalX) => {
88
+ // Convert physical position to logical position (always LTR)
89
+ // In RTL, left side (physicalX=0) maps to max value (logicalX=barWidth)
90
+ // In LTR, left side (physicalX=0) maps to min value (logicalX=0)
91
+ const logicalX = $isRTL ? barWidth - physicalX : physicalX;
92
92
 
93
- const fromIndex = positionList.findLastIndex((s) => s <= diff);
94
- const toIndex = positionList.findIndex((s) => diff <= s);
93
+ if (logicalX < 0 || logicalX > barWidth) {
94
+ return;
95
+ }
95
96
 
96
- const index =
97
- Math.abs(positionList[fromIndex] - diff) < Math.abs(positionList[toIndex] - diff)
98
- ? fromIndex
99
- : toIndex;
97
+ const fromIndex = positionList.findLastIndex((s) => s <= logicalX);
98
+ const toIndex = positionList.findIndex((s) => logicalX <= s);
99
+ const fromDiff = Math.abs(positionList[fromIndex] - logicalX);
100
+ const toDiff = Math.abs(positionList[toIndex] - logicalX);
101
+ const index = fromDiff < toDiff ? fromIndex : toIndex;
100
102
 
101
103
  if (
102
104
  sliderPositions[targetValueIndex] === positionList[index] ||
@@ -130,8 +132,11 @@
130
132
 
131
133
  const _value = multiThumb ? /** @type {[number, number]} */ (values)[valueIndex] : value;
132
134
  let index = -1;
135
+ // In RTL, ArrowLeft increases value, ArrowRight decreases value
136
+ const decreaseKeys = $isRTL ? ['ArrowDown', 'ArrowRight'] : ['ArrowDown', 'ArrowLeft'];
137
+ const increaseKeys = $isRTL ? ['ArrowUp', 'ArrowLeft'] : ['ArrowUp', 'ArrowRight'];
133
138
 
134
- if (['ArrowDown', 'ArrowLeft'].includes(key)) {
139
+ if (decreaseKeys.includes(key)) {
135
140
  if (_value > min) {
136
141
  index = valueList.indexOf(_value) - 1;
137
142
  }
@@ -140,7 +145,7 @@
140
145
  event.stopPropagation();
141
146
  }
142
147
 
143
- if (['ArrowUp', 'ArrowRight'].includes(key)) {
148
+ if (increaseKeys.includes(key)) {
144
149
  if (_value < max) {
145
150
  index = valueList.indexOf(_value) + 1;
146
151
  }
@@ -180,7 +185,11 @@
180
185
 
181
186
  event.stopPropagation();
182
187
 
183
- moveThumb(startX + (screenX - startScreenX));
188
+ const screenDiff = screenX - startScreenX;
189
+ // Calculate new physical position from left edge
190
+ const physicalX = startX + screenDiff;
191
+
192
+ moveThumb(physicalX);
184
193
  };
185
194
 
186
195
  /**
@@ -198,7 +207,11 @@
198
207
 
199
208
  // Handle a click on the bars
200
209
  if (/** @type {HTMLElement} */ (event.target).matches('.base-bar, .slider-bar')) {
201
- moveThumb(/** @type {any} */ (event).layerX);
210
+ const rect = /** @type {HTMLElement} */ (base).getBoundingClientRect();
211
+ // Get physical X position from left edge
212
+ const physicalX = /** @type {any} */ (event).clientX - rect.left;
213
+
214
+ moveThumb(physicalX);
202
215
  }
203
216
 
204
217
  // Reset everything
@@ -228,7 +241,11 @@
228
241
  event.stopPropagation();
229
242
 
230
243
  dragging = true;
231
- startX = clientX - /** @type {HTMLElement} */ (base).getBoundingClientRect().x;
244
+
245
+ const rect = /** @type {HTMLElement} */ (base).getBoundingClientRect();
246
+
247
+ // Store physical X position from left edge (same in LTR and RTL)
248
+ startX = clientX - rect.left;
232
249
  startScreenX = screenX;
233
250
  targetPointerId = pointerId;
234
251
  targetValueIndex = valueIndex;
@@ -89,12 +89,13 @@
89
89
  }
90
90
  }}
91
91
  >
92
- <Option label={$_('_sui.text_editor.plain_text')} value="plain" />
92
+ <Option label={$_('_sui.text_editor.plain_text')} value="plain" dir="ltr" />
93
93
  {#each codeLanguages as { key, label, aliases } (key)}
94
94
  <Option
95
95
  {label}
96
96
  value={key}
97
97
  selected={key === selectedLanguage || aliases.includes(selectedLanguage)}
98
+ dir="ltr"
98
99
  />
99
100
  {/each}
100
101
  </Select>
@@ -4,6 +4,8 @@
4
4
 
5
5
  import { generateElementId } from '@sveltia/utils/element';
6
6
  import { sleep } from '@sveltia/utils/misc';
7
+ import { get } from 'svelte/store';
8
+ import { isRTL } from './i18n.js';
7
9
  import { getSelectedItemDetail } from './select.svelte';
8
10
 
9
11
  /**
@@ -11,7 +13,7 @@ import { getSelectedItemDetail } from './select.svelte';
11
13
  * apply basic normalization.
12
14
  * @param {string} value Original value.
13
15
  * @returns {string} Normalized value.
14
- * @todo Move this to @sveltia/utils.
16
+ * @todo Move this to `@sveltia/utils`.
15
17
  */
16
18
  const normalize = (value) => {
17
19
  value = value.trim();
@@ -428,6 +430,7 @@ class Group {
428
430
 
429
431
  if (this.grid) {
430
432
  const colCount = Math.floor(this.parent.clientWidth / activeMembers[0].clientWidth);
433
+ const _isRTL = get(isRTL);
431
434
 
432
435
  index = currentTarget ? allMembers.indexOf(currentTarget) : -1;
433
436
 
@@ -439,12 +442,13 @@ class Group {
439
442
  newTarget = allMembers[index + colCount];
440
443
  }
441
444
 
445
+ // In RTL, ArrowLeft moves right (next), ArrowRight moves left (previous)
442
446
  if (key === 'ArrowLeft' && index > 0) {
443
- newTarget = allMembers[index - 1];
447
+ newTarget = allMembers[index + (_isRTL ? 1 : -1)];
444
448
  }
445
449
 
446
450
  if (key === 'ArrowRight' && index < allMembers.length - 1) {
447
- newTarget = allMembers[index + 1];
451
+ newTarget = allMembers[index + (_isRTL ? -1 : 1)];
448
452
  }
449
453
 
450
454
  if (newTarget?.matches('[aria-disabled="true"], [aria-hidden="true"]')) {
@@ -453,7 +457,16 @@ class Group {
453
457
  } else {
454
458
  index = currentTarget ? activeMembers.indexOf(currentTarget) : -1;
455
459
 
456
- if (key === (this.orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp')) {
460
+ const _isRTL = get(isRTL);
461
+
462
+ // For horizontal orientation in RTL: ArrowLeft moves forward, ArrowRight moves backward
463
+ const prevKey =
464
+ this.orientation === 'horizontal' ? (_isRTL ? 'ArrowRight' : 'ArrowLeft') : 'ArrowUp';
465
+
466
+ const nextKey =
467
+ this.orientation === 'horizontal' ? (_isRTL ? 'ArrowLeft' : 'ArrowRight') : 'ArrowDown';
468
+
469
+ if (key === prevKey) {
457
470
  if (index > 0) {
458
471
  // Previous member
459
472
  newTarget = activeMembers[index - 1];
@@ -465,7 +478,7 @@ class Group {
465
478
  }
466
479
  }
467
480
 
468
- if (key === (this.orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown')) {
481
+ if (key === nextKey) {
469
482
  if (index < activeMembers.length - 1) {
470
483
  // Next member
471
484
  newTarget = activeMembers[index + 1];
@@ -1,5 +1,3 @@
1
- /* eslint-disable no-nested-ternary */
2
-
3
1
  import { generateElementId } from '@sveltia/utils/element';
4
2
  import { sleep } from '@sveltia/utils/misc';
5
3
  import { on } from 'svelte/events';
@@ -82,6 +80,12 @@ class Popup {
82
80
  }
83
81
  }
84
82
 
83
+ if (position.endsWith('-right')) {
84
+ if (intersectionRect.right - contentWidth < 8) {
85
+ position = /** @type {PopupPosition} */ (position.replace('-right', '-left'));
86
+ }
87
+ }
88
+
85
89
  const top = position.startsWith('bottom-')
86
90
  ? `${Math.round(intersectionRect.bottom)}px`
87
91
  : position.endsWith('-top')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltia/ui",
3
- "version": "0.31.1",
3
+ "version": "0.31.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -8,18 +8,18 @@
8
8
  "url": "github:sveltia/sveltia-ui"
9
9
  },
10
10
  "dependencies": {
11
- "@lexical/code": "^0.36.2",
12
- "@lexical/dragon": "^0.36.2",
13
- "@lexical/history": "^0.36.2",
14
- "@lexical/link": "^0.36.2",
15
- "@lexical/list": "^0.36.2",
16
- "@lexical/markdown": "^0.36.2",
17
- "@lexical/rich-text": "^0.36.2",
18
- "@lexical/selection": "^0.36.2",
19
- "@lexical/table": "^0.36.2",
20
- "@lexical/utils": "^0.36.2",
11
+ "@lexical/code": "^0.37.0",
12
+ "@lexical/dragon": "^0.37.0",
13
+ "@lexical/history": "^0.37.0",
14
+ "@lexical/link": "^0.37.0",
15
+ "@lexical/list": "^0.37.0",
16
+ "@lexical/markdown": "^0.37.0",
17
+ "@lexical/rich-text": "^0.37.0",
18
+ "@lexical/selection": "^0.37.0",
19
+ "@lexical/table": "^0.37.0",
20
+ "@lexical/utils": "^0.37.0",
21
21
  "@sveltia/utils": "^0.8.5",
22
- "lexical": "^0.36.2",
22
+ "lexical": "^0.37.0",
23
23
  "prismjs": "^1.30.0",
24
24
  "svelte-i18n": "^4.0.1"
25
25
  },
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "devDependencies": {
30
30
  "@sveltejs/adapter-auto": "^6.1.1",
31
- "@sveltejs/kit": "^2.46.2",
31
+ "@sveltejs/kit": "^2.46.5",
32
32
  "@sveltejs/package": "^2.5.4",
33
33
  "@sveltejs/vite-plugin-svelte": "^6.2.1",
34
34
  "cspell": "^9.2.1",
@@ -36,9 +36,9 @@
36
36
  "eslint-config-airbnb-base": "^15.0.0",
37
37
  "eslint-config-prettier": "^10.1.8",
38
38
  "eslint-plugin-import": "^2.32.0",
39
- "eslint-plugin-jsdoc": "^57.2.1",
39
+ "eslint-plugin-jsdoc": "^61.1.1",
40
40
  "eslint-plugin-svelte": "^2.46.1",
41
- "oxlint": "^1.20.0",
41
+ "oxlint": "^1.22.0",
42
42
  "postcss": "^8.5.6",
43
43
  "postcss-html": "^1.8.0",
44
44
  "prettier": "^3.6.2",
@@ -47,8 +47,8 @@
47
47
  "stylelint": "^16.25.0",
48
48
  "stylelint-config-recommended-scss": "^16.0.2",
49
49
  "stylelint-scss": "^6.12.1",
50
- "svelte": "^5.39.10",
51
- "svelte-check": "^4.3.2",
50
+ "svelte": "^5.39.12",
51
+ "svelte-check": "^4.3.3",
52
52
  "svelte-preprocess": "^6.0.3",
53
53
  "tslib": "^2.8.1",
54
54
  "vite": "^7.1.9",