@sveltia/ui 0.38.0 → 0.39.1

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.
@@ -55,6 +55,7 @@
55
55
  {@render input()}
56
56
  {:else}
57
57
  <TextInput
58
+ dir="auto"
58
59
  bind:value
59
60
  flex
60
61
  autofocus
@@ -144,6 +144,7 @@
144
144
  {:else}
145
145
  <TextInput
146
146
  {...restProps}
147
+ dir="auto"
147
148
  bind:element={inputElement}
148
149
  role="combobox"
149
150
  {id}
@@ -27,6 +27,7 @@
27
27
  * @typedef {object} Props
28
28
  * @property {string} [value] Input value.
29
29
  * @property {boolean} [flex] Make the text input container flexible.
30
+ * @property {'ltr' | 'rtl' | 'auto'} [dir] The `dir` attribute on the `<textarea>` element.
30
31
  * @property {TextEditorMode[]} [modes] Enabled modes.
31
32
  * @property {(TextEditorBlockType | TextEditorInlineType)[]} [buttons] Enabled buttons.
32
33
  * @property {TextEditorComponent[]} [components] Editor components.
@@ -50,6 +51,7 @@
50
51
  /* eslint-disable prefer-const */
51
52
  value = $bindable(''),
52
53
  flex = false,
54
+ dir = undefined,
53
55
  modes = ['rich-text', 'plain-text'],
54
56
  buttons = [...INLINE_BUTTON_TYPES, ...BLOCK_BUTTON_TYPES],
55
57
  components = [],
@@ -110,6 +112,7 @@
110
112
  autoResize={true}
111
113
  bind:value={editorStore.inputValue}
112
114
  {flex}
115
+ {dir}
113
116
  hidden={editorStore.useRichText || hidden}
114
117
  {disabled}
115
118
  {readonly}
@@ -13,6 +13,10 @@ declare const TextEditor: import("svelte").Component<{
13
13
  * Make the text input container flexible.
14
14
  */
15
15
  flex?: boolean | undefined;
16
+ /**
17
+ * The `dir` attribute on the `<textarea>` element.
18
+ */
19
+ dir?: "ltr" | "rtl" | "auto" | undefined;
16
20
  /**
17
21
  * Enabled modes.
18
22
  */
@@ -67,6 +71,10 @@ type Props = {
67
71
  * Make the text input container flexible.
68
72
  */
69
73
  flex?: boolean | undefined;
74
+ /**
75
+ * The `dir` attribute on the `<textarea>` element.
76
+ */
77
+ dir?: "ltr" | "rtl" | "auto" | undefined;
70
78
  /**
71
79
  * Enabled modes.
72
80
  */
@@ -216,6 +216,7 @@
216
216
  <div role="none">
217
217
  <label for="{id}-url">{_('_sui.text_editor.url')}</label>
218
218
  <TextInput
219
+ dir="ltr"
219
220
  id="{id}-url"
220
221
  bind:value={anchorURL}
221
222
  flex
@@ -229,6 +230,7 @@
229
230
  <div role="none">
230
231
  <label for="{id}-text">{_('_sui.text_editor.text')}</label>
231
232
  <TextInput
233
+ dir="auto"
232
234
  id="{id}-text"
233
235
  bind:value={anchorText}
234
236
  flex
@@ -156,6 +156,7 @@
156
156
  </Button>
157
157
  </div>
158
158
  <TextInput
159
+ dir="ltr"
159
160
  {...restProps}
160
161
  role="spinbutton"
161
162
  {id}
@@ -65,6 +65,7 @@
65
65
  {hidden}
66
66
  >
67
67
  <TextInput
68
+ dir="ltr"
68
69
  bind:element={inputElement}
69
70
  {...restProps}
70
71
  {id}
@@ -79,6 +79,7 @@
79
79
  {/if}
80
80
  </span>
81
81
  <TextInput
82
+ dir="auto"
82
83
  bind:element={inputElement}
83
84
  {...restProps}
84
85
  role="searchbox"
@@ -62,6 +62,7 @@
62
62
  {hidden}
63
63
  >
64
64
  <TextInput
65
+ dir="ltr"
65
66
  bind:element={inputElement}
66
67
  {...restProps}
67
68
  {id}
@@ -59,6 +59,14 @@
59
59
  let setOpenClass = $state(false);
60
60
  let setActiveClass = $state(false);
61
61
  let showContent = $state(false);
62
+ /**
63
+ * Monotonically increasing counter used to detect stale async operations. Incremented at the
64
+ * start of each `openDialog`/`closeDialog` call; any suspended continuation that finds its
65
+ * captured value no longer matches the current counter knows it has been superseded and exits
66
+ * without mutating state.
67
+ * @type {number}
68
+ */
69
+ let generation = 0;
62
70
 
63
71
  /**
64
72
  * Resolve once the transition is complete.
@@ -88,13 +96,19 @@
88
96
  return;
89
97
  }
90
98
 
99
+ generation += 1;
100
+
101
+ const gen = generation;
102
+
91
103
  onOpening?.(new CustomEvent('Opening'));
92
104
  showContent = true;
93
105
  dialog.showModal();
94
106
  onOpen?.(new CustomEvent('Open'));
95
107
  await sleep(0);
108
+ if (gen !== generation) return;
96
109
  setOpenClass = true;
97
110
  await waitForTransition();
111
+ if (gen !== generation) return;
98
112
  setActiveClass = true;
99
113
  };
100
114
 
@@ -106,6 +120,10 @@
106
120
  return;
107
121
  }
108
122
 
123
+ generation += 1;
124
+
125
+ const gen = generation;
126
+ const wasOpen = setOpenClass;
109
127
  const { returnValue } = dialog;
110
128
 
111
129
  onClosing?.(new CustomEvent('Closing'));
@@ -115,7 +133,16 @@
115
133
  document.body.inert = false;
116
134
  setActiveClass = false;
117
135
  setOpenClass = false;
118
- await waitForTransition();
136
+
137
+ // Only wait for the closing transition if the dialog was visually open (i.e. the `.open` CSS
138
+ // class was set). If the dialog was closed before the opening transition even started, there is
139
+ // no CSS transition in progress and `transitionend` will never fire.
140
+ if (wasOpen) {
141
+ await waitForTransition();
142
+ }
143
+
144
+ if (gen !== generation) return;
145
+
119
146
  showContent = false;
120
147
 
121
148
  if (returnValue === 'ok') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltia/ui",
3
- "version": "0.38.0",
3
+ "version": "0.39.1",
4
4
  "description": "A collection of Svelte components and utilities for building user interfaces.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -45,18 +45,18 @@
45
45
  "@lexical/selection": "^0.44.0",
46
46
  "@lexical/table": "^0.44.0",
47
47
  "@lexical/utils": "^0.44.0",
48
- "@sveltia/i18n": "^1.0.5",
48
+ "@sveltia/i18n": "^1.1.0",
49
49
  "@sveltia/utils": "^0.10.6",
50
50
  "lexical": "^0.44.0",
51
51
  "prismjs": "^1.30.0",
52
- "yaml": "^2.8.4"
52
+ "yaml": "^2.9.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@sveltejs/adapter-auto": "^7.0.1",
56
56
  "@sveltejs/kit": "^2.59.1",
57
57
  "@sveltejs/package": "^2.5.7",
58
58
  "@sveltejs/vite-plugin-svelte": "^7.1.2",
59
- "@vitest/coverage-v8": "^4.1.5",
59
+ "@vitest/coverage-v8": "^4.1.6",
60
60
  "cspell": "^10.0.0",
61
61
  "eslint": "^9.39.4",
62
62
  "eslint-config-airbnb-extended": "^3.1.0",
@@ -67,21 +67,21 @@
67
67
  "eslint-plugin-svelte": "^3.17.1",
68
68
  "globals": "^17.6.0",
69
69
  "happy-dom": "^20.9.0",
70
- "oxlint": "^1.63.0",
70
+ "oxlint": "^1.64.0",
71
71
  "postcss": "^8.5.14",
72
72
  "postcss-html": "^1.8.1",
73
73
  "prettier": "^3.8.3",
74
- "prettier-plugin-svelte": "^3.5.1",
74
+ "prettier-plugin-svelte": "^3.5.2",
75
75
  "sass": "^1.99.0",
76
76
  "stylelint": "^17.11.0",
77
77
  "stylelint-config-recommended-scss": "^17.0.1",
78
- "stylelint-scss": "^7.0.0",
78
+ "stylelint-scss": "^7.1.1",
79
79
  "svelte": "^5.55.5",
80
80
  "svelte-check": "^4.4.8",
81
81
  "svelte-preprocess": "^6.0.3",
82
82
  "tslib": "^2.8.1",
83
- "vite": "^8.0.11",
84
- "vitest": "^4.1.5"
83
+ "vite": "^8.0.12",
84
+ "vitest": "^4.1.6"
85
85
  },
86
86
  "peerDependencies": {
87
87
  "svelte": "^5.0.0"