@sveltia/ui 0.42.1 → 0.44.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.
@@ -290,7 +290,7 @@
290
290
  .resizable-handle:focus-visible, .resizable-handle:hover, .resizable-handle.dragging {
291
291
  outline: none;
292
292
  z-index: 1;
293
- background-color: var(--sui-primary-accent-color-translucent);
293
+ background-color: var(--sui-primary-accent-color-translucent-light);
294
294
  }
295
295
  .resizable-handle:focus-visible .handle-bar, .resizable-handle:hover .handle-bar, .resizable-handle.dragging .handle-bar {
296
296
  background-color: var(--sui-primary-accent-color);
@@ -283,8 +283,7 @@
283
283
  outline: none;
284
284
  }
285
285
  .select-tags span[draggable]:focus-within {
286
- outline: var(--sui-focus-ring-width) solid var(--sui-primary-accent-color-translucent);
287
- outline-offset: 1px;
286
+ outline: var(--sui-focus-ring-width) solid var(--sui-focus-ring-color);
288
287
  }
289
288
  .select-tags span[draggable].drag-source {
290
289
  opacity: 0.4;
@@ -310,6 +309,9 @@
310
309
  .select-tags span[draggable] .label {
311
310
  outline: none;
312
311
  }
312
+ .select-tags span[draggable] :global(button) {
313
+ outline-offset: -2px;
314
+ }
313
315
  .select-tags span[draggable] :global(.icon) {
314
316
  font-size: var(--sui-font-size-large);
315
317
  }</style>
@@ -117,7 +117,7 @@ button:focus-visible {
117
117
  outline: 0;
118
118
  }
119
119
  button:focus-visible span {
120
- outline-color: var(--sui-primary-accent-color-translucent);
120
+ outline-color: var(--sui-focus-ring-color);
121
121
  }
122
122
  button[aria-checked=true] span {
123
123
  background-color: var(--sui-primary-accent-color);
@@ -119,7 +119,12 @@
119
119
 
120
120
  <style>.code-editor {
121
121
  margin: var(--sui-focus-ring-width);
122
+ border-radius: var(--sui-textbox-border-radius);
122
123
  width: calc(100% - var(--sui-focus-ring-width) * 2);
124
+ transition: all 200ms;
125
+ }
126
+ .code-editor:focus-within {
127
+ outline: var(--sui-focus-ring-width) solid var(--sui-focus-ring-color);
123
128
  }
124
129
  .code-editor.flex:not([hidden]) {
125
130
  display: block;
@@ -28,6 +28,7 @@ import {
28
28
  ListNode,
29
29
  } from '@lexical/list';
30
30
  import {
31
+ CODE,
31
32
  $convertFromMarkdownString as convertFromMarkdownString,
32
33
  $convertToMarkdownString as convertToMarkdownString,
33
34
  registerMarkdownShortcuts,
@@ -210,11 +211,11 @@ export const initEditor = ({
210
211
  .filter(([button]) => enabledButtons.includes(/** @type {TextEditorNodeType} */ (button)))
211
212
  .flatMap(([, nodes]) => nodes),
212
213
  ),
213
- ...(isCodeEditor ? [CodeNode, CodeHighlightNode] : []),
214
- HorizontalRuleNode,
215
- TableNode,
216
- TableCellNode,
217
- TableRowNode,
214
+ ...(isCodeEditor
215
+ ? [CodeNode, CodeHighlightNode]
216
+ : // We haven’t implemented buttons for horizontal rules and tables yet, but we still want
217
+ // to support them in Markdown, so always include them in the node list
218
+ [HorizontalRuleNode, TableNode, TableCellNode, TableRowNode]),
218
219
  ],
219
220
  theme: EDITOR_THEME,
220
221
  };
@@ -227,8 +228,10 @@ export const initEditor = ({
227
228
  .filter(([button]) => enabledButtons.includes(/** @type {TextEditorNodeType} */ (button)))
228
229
  .flatMap(([, transformers]) => transformers),
229
230
  ),
230
- HR,
231
- TABLE,
231
+ ...(isCodeEditor
232
+ ? [CODE]
233
+ : // See the comment above for why we always include horizontal rules and tables
234
+ [HR, TABLE]),
232
235
  ];
233
236
 
234
237
  const editor = createEditor(editorConfig);
@@ -133,7 +133,12 @@
133
133
 
134
134
  <style>.text-editor {
135
135
  margin: var(--sui-focus-ring-width);
136
+ border-radius: var(--sui-textbox-border-radius);
136
137
  width: calc(100% - var(--sui-focus-ring-width) * 2);
138
+ transition: all 200ms;
139
+ }
140
+ .text-editor:focus-within {
141
+ outline: var(--sui-focus-ring-width) solid var(--sui-focus-ring-color);
137
142
  }
138
143
  .text-editor.flex:not([hidden]) {
139
144
  display: block;
@@ -123,7 +123,6 @@
123
123
  transition-duration: 0ms;
124
124
  }
125
125
  :is(textarea, .clone):focus {
126
- border-color: var(--sui-textbox-border-color-focus, var(--sui-primary-accent-color));
127
126
  color: var(--sui-textbox-foreground-color-focus, var(--sui-textbox-foreground-color));
128
127
  background-color: var(--sui-textbox-background-color-focus, var(--sui-textbox-background-color));
129
128
  }
@@ -172,7 +172,6 @@ input {
172
172
  transition: all 200ms;
173
173
  }
174
174
  input:focus {
175
- border-color: var(--sui-textbox-border-color-focus, var(--sui-primary-accent-color));
176
175
  color: var(--sui-textbox-foreground-color-focus, var(--sui-textbox-foreground-color));
177
176
  background-color: var(--sui-textbox-background-color-focus, var(--sui-textbox-background-color));
178
177
  }
@@ -6,7 +6,6 @@
6
6
  -->
7
7
  <script>
8
8
  import { onMount } from 'svelte';
9
- import { initLocales } from '../../services/i18n';
10
9
 
11
10
  /**
12
11
  * @import { Snippet } from 'svelte';
@@ -39,10 +38,6 @@
39
38
 
40
39
  let fontLoaded = $state(false);
41
40
 
42
- $effect.pre(() => {
43
- initLocales();
44
- });
45
-
46
41
  onMount(() => {
47
42
  const mediaQuery = globalThis.matchMedia('(prefers-color-scheme: dark)');
48
43
  const { dataset } = document.documentElement;
@@ -183,7 +178,8 @@
183
178
  var(--sui-success-color-hue) var(--sui-alert-background-color-saturation)
184
179
  var(--sui-alert-background-color-lightness)
185
180
  );
186
- --sui-focus-ring-width: 4px;
181
+ --sui-focus-ring-width: 2px;
182
+ --sui-focus-ring-color: var(--sui-primary-accent-color-translucent);
187
183
  --sui-primary-border-color: hsl(var(--sui-border-color-2-hsl));
188
184
  --sui-secondary-border-color: hsl(var(--sui-border-color-3-hsl));
189
185
  --sui-error-border-color: hsl(
@@ -329,7 +325,8 @@
329
325
  --sui-primary-accent-color: hsl(var(--sui-base-hue) 80% 40%);
330
326
  --sui-primary-accent-color-dark: hsl(var(--sui-base-hue) 80% 35%);
331
327
  --sui-primary-accent-color-inverted: hsl(var(--sui-base-hue) 10% 100%);
332
- --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 40%);
328
+ --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 60%);
329
+ --sui-primary-accent-color-translucent-light: hsl(var(--sui-base-hue) 80% 50% / 40%);
333
330
  --sui-error-color-hue: 0;
334
331
  --sui-warning-color-hue: 40;
335
332
  --sui-info-color-hue: 210;
@@ -363,7 +360,8 @@
363
360
  --sui-primary-accent-color: hsl(var(--sui-base-hue) 100% 40%);
364
361
  --sui-primary-accent-color-dark: hsl(var(--sui-base-hue) 100% 35%);
365
362
  --sui-primary-accent-color-inverted: hsl(var(--sui-base-hue) 10% 100%);
366
- --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 40%);
363
+ --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 60%);
364
+ --sui-primary-accent-color-translucent-light: hsl(var(--sui-base-hue) 80% 50% / 40%);
367
365
  --sui-error-color-hue: 0;
368
366
  --sui-warning-color-hue: 40;
369
367
  --sui-info-color-hue: 210;
@@ -398,7 +396,8 @@
398
396
  --sui-primary-accent-color: hsl(var(--sui-base-hue) 80% 40%);
399
397
  --sui-primary-accent-color-dark: hsl(var(--sui-base-hue) 80% 35%);
400
398
  --sui-primary-accent-color-inverted: hsl(var(--sui-base-hue) 10% 100%);
401
- --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 40%);
399
+ --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 60%);
400
+ --sui-primary-accent-color-translucent-light: hsl(var(--sui-base-hue) 80% 50% / 40%);
402
401
  --sui-error-color-hue: 0;
403
402
  --sui-warning-color-hue: 40;
404
403
  --sui-info-color-hue: 210;
@@ -434,7 +433,8 @@
434
433
  --sui-primary-accent-color: hsl(var(--sui-base-hue) 100% 40%);
435
434
  --sui-primary-accent-color-dark: hsl(var(--sui-base-hue) 100% 35%);
436
435
  --sui-primary-accent-color-inverted: hsl(var(--sui-base-hue) 10% 100%);
437
- --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 40%);
436
+ --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 60%);
437
+ --sui-primary-accent-color-translucent-light: hsl(var(--sui-base-hue) 80% 50% / 40%);
438
438
  --sui-error-color-hue: 0;
439
439
  --sui-warning-color-hue: 40;
440
440
  --sui-info-color-hue: 210;
@@ -474,7 +474,7 @@
474
474
  }
475
475
  }
476
476
  :global(::selection) {
477
- background-color: var(--sui-primary-accent-color-translucent);
477
+ background-color: var(--sui-primary-accent-color-translucent-light);
478
478
  }
479
479
  :global(*) {
480
480
  -webkit-tap-highlight-color: transparent;
@@ -484,7 +484,7 @@
484
484
  outline-width: 0;
485
485
  }
486
486
  :global(:focus-visible) {
487
- outline-color: var(--sui-primary-accent-color-translucent);
487
+ outline-color: var(--sui-focus-ring-color);
488
488
  z-index: 2;
489
489
  }
490
490
  :global(h1) {
package/dist/index.d.ts CHANGED
@@ -78,4 +78,4 @@ export { default as EmptyState } from "./components/util/empty-state.svelte";
78
78
  export { default as Group } from "./components/util/group.svelte";
79
79
  export { default as Modal } from "./components/util/modal.svelte";
80
80
  export * from "./typedefs.js";
81
- export { initLocales, resources } from "./services/i18n.js";
81
+ export { initLocales, strings } from "./services/i18n.js";
package/dist/index.js CHANGED
@@ -77,7 +77,7 @@ export { default as AppShell } from './components/util/app-shell.svelte';
77
77
  export { default as EmptyState } from './components/util/empty-state.svelte';
78
78
  export { default as Group } from './components/util/group.svelte';
79
79
  export { default as Modal } from './components/util/modal.svelte';
80
- export { initLocales, resources } from './services/i18n.js';
80
+ export { initLocales, strings } from './services/i18n.js';
81
81
 
82
82
  // eslint-disable-next-line import/export
83
83
  export * from './typedefs.js';
@@ -3,7 +3,7 @@
3
3
  * strings as values.
4
4
  * @type {Record<string, Record<string, string>>}
5
5
  */
6
- export const resources: Record<string, Record<string, string>>;
6
+ export const strings: Record<string, Record<string, string>>;
7
7
  export function initLocales({ fallbackLocale, initialLocale }?: {
8
8
  fallbackLocale?: string | undefined;
9
9
  initialLocale?: string | undefined;
@@ -1,22 +1,22 @@
1
1
  import { addMessages, init } from '@sveltia/i18n';
2
2
 
3
- const rawResources = import.meta.glob('../locales/*.yaml', { eager: true, import: 'default' });
3
+ const resources = import.meta.glob('../locales/*.yaml', { eager: true, import: 'default' });
4
4
 
5
5
  /**
6
6
  * Object containing all the locale resources, with the locale names as keys and the corresponding
7
7
  * strings as values.
8
8
  * @type {Record<string, Record<string, string>>}
9
9
  */
10
- export const resources = Object.fromEntries(
11
- Object.entries(rawResources).map(([path, resource]) => [
10
+ export const strings = Object.fromEntries(
11
+ Object.entries(resources).map(([path, resource]) => [
12
12
  /** @type {string} */ (path.match(/.+\/(?<locale>.+?)\.yaml$/)?.groups?.locale),
13
13
  /** @type {Record<string, string>} */ (resource),
14
14
  ]),
15
15
  );
16
16
 
17
17
  /**
18
- * Load strings and initialize the locales. Consumers can use this function to load the localized
19
- * strings for their application. If `<AppShell>` is used, this function is called automatically.
18
+ * Load strings and initialize the locales. Consumers can use this function or {@link strings} to
19
+ * load the localized strings for their application.
20
20
  * @param {object} [init] Initialize options.
21
21
  * @param {string} [init.fallbackLocale] Fallback locale.
22
22
  * @param {string} [init.initialLocale] Initial locale.
@@ -24,7 +24,7 @@ export const resources = Object.fromEntries(
24
24
  * @see https://vitejs.dev/guide/features.html#glob-import
25
25
  */
26
26
  export const initLocales = ({ fallbackLocale = 'en', initialLocale = 'en' } = {}) => {
27
- Object.entries(resources).forEach(([locale, resource]) => {
27
+ Object.entries(strings).forEach(([locale, resource]) => {
28
28
  // Add `_sui` suffix to avoid collision with app localization
29
29
  addMessages(locale, { _sui: resource });
30
30
  });
@@ -29,8 +29,11 @@ class Popup {
29
29
  if (value) {
30
30
  this.checkPosition();
31
31
  } else if (this.anchorElement.getAttribute('aria-expanded') === 'true') {
32
- this.anchorElement.focus();
33
- this.anchorElement.removeAttribute('aria-controls');
32
+ // Wait for the popup to close before focusing the anchor, otherwise the focus will be lost
33
+ window.requestAnimationFrame(() => {
34
+ this.anchorElement.focus();
35
+ this.anchorElement.removeAttribute('aria-controls');
36
+ });
34
37
  }
35
38
 
36
39
  this.anchorElement.setAttribute('aria-expanded', String(value));
@@ -31,7 +31,7 @@
31
31
  }
32
32
 
33
33
  ::selection {
34
- background-color: var(--sui-primary-accent-color-translucent);
34
+ background-color: var(--sui-primary-accent-color-translucent-light);
35
35
  }
36
36
 
37
37
  * {
@@ -44,7 +44,7 @@
44
44
  }
45
45
 
46
46
  :focus-visible {
47
- outline-color: var(--sui-primary-accent-color-translucent);
47
+ outline-color: var(--sui-focus-ring-color);
48
48
  z-index: 2;
49
49
  }
50
50
 
@@ -20,7 +20,8 @@
20
20
  --sui-primary-accent-color: hsl(var(--sui-base-hue) 80% 40%);
21
21
  --sui-primary-accent-color-dark: hsl(var(--sui-base-hue) 80% 35%);
22
22
  --sui-primary-accent-color-inverted: hsl(var(--sui-base-hue) 10% 100%); // white
23
- --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 40%);
23
+ --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 60%);
24
+ --sui-primary-accent-color-translucent-light: hsl(var(--sui-base-hue) 80% 50% / 40%);
24
25
  // Alerts
25
26
  --sui-error-color-hue: 0;
26
27
  --sui-warning-color-hue: 40;
@@ -56,7 +57,8 @@
56
57
  --sui-primary-accent-color: hsl(var(--sui-base-hue) 100% 40%);
57
58
  --sui-primary-accent-color-dark: hsl(var(--sui-base-hue) 100% 35%);
58
59
  --sui-primary-accent-color-inverted: hsl(var(--sui-base-hue) 10% 100%); // white
59
- --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 40%);
60
+ --sui-primary-accent-color-translucent: hsl(var(--sui-base-hue) 80% 50% / 60%);
61
+ --sui-primary-accent-color-translucent-light: hsl(var(--sui-base-hue) 80% 50% / 40%);
60
62
  // Alerts
61
63
  --sui-error-color-hue: 0;
62
64
  --sui-warning-color-hue: 40;
@@ -127,7 +129,8 @@
127
129
  var(--sui-alert-background-color-lightness)
128
130
  );
129
131
  // Outline
130
- --sui-focus-ring-width: 4px;
132
+ --sui-focus-ring-width: 2px;
133
+ --sui-focus-ring-color: var(--sui-primary-accent-color-translucent);
131
134
  // Borders
132
135
  --sui-primary-border-color: hsl(var(--sui-border-color-2-hsl));
133
136
  --sui-secondary-border-color: hsl(var(--sui-border-color-3-hsl));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltia/ui",
3
- "version": "0.42.1",
3
+ "version": "0.44.0",
4
4
  "description": "A collection of Svelte components and utilities for building user interfaces.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -45,7 +45,7 @@
45
45
  "@lexical/selection": "^0.47.0",
46
46
  "@lexical/table": "^0.47.0",
47
47
  "@lexical/utils": "^0.47.0",
48
- "@sveltia/i18n": "^1.1.2",
48
+ "@sveltia/i18n": "^1.1.3",
49
49
  "@sveltia/utils": "^0.10.7",
50
50
  "lexical": "^0.47.0",
51
51
  "prismjs": "^1.30.0"
@@ -53,22 +53,22 @@
53
53
  "devDependencies": {
54
54
  "@rollup/plugin-yaml": "^5.0.0",
55
55
  "@sveltejs/adapter-auto": "^7.0.1",
56
- "@sveltejs/kit": "^2.69.2",
56
+ "@sveltejs/kit": "^2.69.3",
57
57
  "@sveltejs/package": "^2.5.8",
58
58
  "@sveltejs/vite-plugin-svelte": "^7.2.0",
59
59
  "@vitest/coverage-v8": "^4.1.10",
60
60
  "cspell": "^10.0.1",
61
61
  "eslint": "^9.39.5",
62
- "eslint-config-airbnb-extended": "^3.1.0",
62
+ "eslint-config-airbnb-extended": "^3.1.1",
63
63
  "eslint-config-prettier": "^10.1.8",
64
64
  "eslint-plugin-import": "^2.32.0",
65
65
  "eslint-plugin-jsdoc": "^63.0.13",
66
- "eslint-plugin-package-json": "^1.5.0",
66
+ "eslint-plugin-package-json": "^1.6.0",
67
67
  "eslint-plugin-svelte": "^3.20.0",
68
68
  "globals": "^17.7.0",
69
69
  "happy-dom": "^20.10.6",
70
- "oxlint": "^1.73.0",
71
- "postcss": "^8.5.16",
70
+ "oxlint": "^1.74.0",
71
+ "postcss": "^8.5.19",
72
72
  "postcss-html": "^1.8.1",
73
73
  "prettier": "^3.9.5",
74
74
  "prettier-plugin-svelte": "^4.1.1",
@@ -76,7 +76,7 @@
76
76
  "stylelint": "^17.14.0",
77
77
  "stylelint-config-recommended-scss": "^17.0.1",
78
78
  "stylelint-scss": "^7.2.0",
79
- "svelte": "^5.56.4",
79
+ "svelte": "^5.56.5",
80
80
  "svelte-check": "^4.7.2",
81
81
  "svelte-preprocess": "^6.0.5",
82
82
  "tslib": "^2.8.1",