@nqmcreative/ui 0.4.0 → 0.4.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.
Files changed (132) hide show
  1. package/README.md +16 -18
  2. package/dist/core/calendar.d.ts +1 -1
  3. package/dist/core/calendar.js +1 -1
  4. package/dist/core/date.d.ts +3 -3
  5. package/dist/core/date.js +1 -1
  6. package/dist/core/files.d.ts +2 -3
  7. package/dist/core/files.js +2 -3
  8. package/dist/core/index.d.ts +1 -3
  9. package/dist/core/index.js +1 -3
  10. package/dist/core/password.d.ts +1 -1
  11. package/dist/core/password.js +1 -1
  12. package/dist/styles/matte/Alert.svelte +1 -3
  13. package/dist/styles/matte/Breadcrumb.svelte +1 -4
  14. package/dist/styles/matte/Calendar.svelte +6 -9
  15. package/dist/styles/matte/ColorInput.svelte +1 -4
  16. package/dist/styles/matte/Combobox.svelte +3 -6
  17. package/dist/styles/matte/CommandPalette.svelte +3 -6
  18. package/dist/styles/matte/ConfirmDialog.svelte +2 -5
  19. package/dist/styles/matte/ContextMenu.svelte +1 -4
  20. package/dist/styles/matte/CurrencyInput.svelte +1 -1
  21. package/dist/styles/matte/CurrencyInput.svelte.d.ts +1 -1
  22. package/dist/styles/matte/DatePicker.svelte +9 -9
  23. package/dist/styles/matte/DatePicker.svelte.d.ts +3 -0
  24. package/dist/styles/matte/Drawer.svelte +1 -3
  25. package/dist/styles/matte/Dropdown.svelte +2 -5
  26. package/dist/styles/matte/Dropdown.svelte.d.ts +1 -1
  27. package/dist/styles/matte/Dropzone.svelte +9 -12
  28. package/dist/styles/matte/Dropzone.svelte.d.ts +1 -1
  29. package/dist/styles/matte/FileInput.svelte +11 -14
  30. package/dist/styles/matte/FileInput.svelte.d.ts +2 -2
  31. package/dist/styles/matte/Footer.svelte +1 -1
  32. package/dist/styles/matte/Footer.svelte.d.ts +1 -1
  33. package/dist/styles/matte/Modal.svelte +1 -3
  34. package/dist/styles/matte/MultiSelect.svelte +5 -8
  35. package/dist/styles/matte/Navbar.svelte +3 -9
  36. package/dist/styles/matte/Pagination.svelte +3 -6
  37. package/dist/styles/matte/PinInput.svelte +1 -4
  38. package/dist/styles/matte/SearchInput.svelte +1 -4
  39. package/dist/styles/matte/Sidebar.svelte +3 -6
  40. package/dist/styles/matte/Spinner.svelte +2 -5
  41. package/dist/styles/matte/Spinner.svelte.d.ts +1 -1
  42. package/dist/styles/matte/Table.svelte +5 -8
  43. package/dist/styles/matte/TagsInput.svelte +5 -8
  44. package/dist/styles/matte/ThemeToggle.svelte +5 -8
  45. package/dist/styles/matte/TimeInput.svelte +2 -5
  46. package/dist/styles/matte/Toaster.svelte +2 -5
  47. package/dist/styles/matte/index.d.ts +2 -3
  48. package/dist/styles/matte/index.js +1 -3
  49. package/dist/styles/paper/Alert.svelte +1 -3
  50. package/dist/styles/paper/Breadcrumb.svelte +1 -4
  51. package/dist/styles/paper/Calendar.svelte +6 -9
  52. package/dist/styles/paper/ColorInput.svelte +1 -4
  53. package/dist/styles/paper/Combobox.svelte +3 -6
  54. package/dist/styles/paper/CommandPalette.svelte +3 -6
  55. package/dist/styles/paper/ConfirmDialog.svelte +2 -5
  56. package/dist/styles/paper/ContextMenu.svelte +1 -4
  57. package/dist/styles/paper/CurrencyInput.svelte +1 -1
  58. package/dist/styles/paper/CurrencyInput.svelte.d.ts +1 -1
  59. package/dist/styles/paper/DatePicker.svelte +9 -9
  60. package/dist/styles/paper/DatePicker.svelte.d.ts +3 -0
  61. package/dist/styles/paper/Drawer.svelte +1 -3
  62. package/dist/styles/paper/Dropdown.svelte +2 -5
  63. package/dist/styles/paper/Dropdown.svelte.d.ts +1 -1
  64. package/dist/styles/paper/Dropzone.svelte +9 -12
  65. package/dist/styles/paper/Dropzone.svelte.d.ts +1 -1
  66. package/dist/styles/paper/FileInput.svelte +11 -14
  67. package/dist/styles/paper/FileInput.svelte.d.ts +2 -2
  68. package/dist/styles/paper/Footer.svelte +1 -1
  69. package/dist/styles/paper/Footer.svelte.d.ts +1 -1
  70. package/dist/styles/paper/Modal.svelte +1 -3
  71. package/dist/styles/paper/MultiSelect.svelte +5 -8
  72. package/dist/styles/paper/Navbar.svelte +3 -9
  73. package/dist/styles/paper/Pagination.svelte +3 -6
  74. package/dist/styles/paper/PinInput.svelte +1 -4
  75. package/dist/styles/paper/SearchInput.svelte +1 -4
  76. package/dist/styles/paper/Sidebar.svelte +3 -6
  77. package/dist/styles/paper/Spinner.svelte +2 -5
  78. package/dist/styles/paper/Spinner.svelte.d.ts +1 -1
  79. package/dist/styles/paper/Table.svelte +5 -8
  80. package/dist/styles/paper/TagsInput.svelte +5 -8
  81. package/dist/styles/paper/ThemeToggle.svelte +5 -8
  82. package/dist/styles/paper/TimeInput.svelte +2 -5
  83. package/dist/styles/paper/Toaster.svelte +3 -6
  84. package/dist/styles/paper/index.d.ts +2 -3
  85. package/dist/styles/paper/index.js +1 -3
  86. package/dist/styles/sprout/Alert.svelte +1 -3
  87. package/dist/styles/sprout/Breadcrumb.svelte +1 -4
  88. package/dist/styles/sprout/Calendar.svelte +6 -9
  89. package/dist/styles/sprout/ColorInput.svelte +1 -4
  90. package/dist/styles/sprout/Combobox.svelte +3 -6
  91. package/dist/styles/sprout/CommandPalette.svelte +3 -6
  92. package/dist/styles/sprout/ConfirmDialog.svelte +2 -5
  93. package/dist/styles/sprout/ContextMenu.svelte +1 -4
  94. package/dist/styles/sprout/CurrencyInput.svelte +1 -1
  95. package/dist/styles/sprout/CurrencyInput.svelte.d.ts +1 -1
  96. package/dist/styles/sprout/DatePicker.svelte +9 -9
  97. package/dist/styles/sprout/DatePicker.svelte.d.ts +3 -0
  98. package/dist/styles/sprout/Drawer.svelte +1 -3
  99. package/dist/styles/sprout/Dropdown.svelte +2 -5
  100. package/dist/styles/sprout/Dropdown.svelte.d.ts +1 -1
  101. package/dist/styles/sprout/Dropzone.svelte +9 -12
  102. package/dist/styles/sprout/Dropzone.svelte.d.ts +1 -1
  103. package/dist/styles/sprout/FileInput.svelte +11 -14
  104. package/dist/styles/sprout/FileInput.svelte.d.ts +2 -2
  105. package/dist/styles/sprout/Footer.svelte +1 -1
  106. package/dist/styles/sprout/Footer.svelte.d.ts +1 -1
  107. package/dist/styles/sprout/Modal.svelte +1 -3
  108. package/dist/styles/sprout/MultiSelect.svelte +5 -8
  109. package/dist/styles/sprout/Navbar.svelte +3 -9
  110. package/dist/styles/sprout/Pagination.svelte +3 -6
  111. package/dist/styles/sprout/PinInput.svelte +1 -4
  112. package/dist/styles/sprout/SearchInput.svelte +1 -4
  113. package/dist/styles/sprout/Sidebar.svelte +3 -6
  114. package/dist/styles/sprout/Spinner.svelte +2 -5
  115. package/dist/styles/sprout/Spinner.svelte.d.ts +1 -1
  116. package/dist/styles/sprout/Table.svelte +5 -8
  117. package/dist/styles/sprout/TagsInput.svelte +5 -8
  118. package/dist/styles/sprout/ThemeToggle.svelte +5 -8
  119. package/dist/styles/sprout/TimeInput.svelte +2 -5
  120. package/dist/styles/sprout/Toaster.svelte +3 -6
  121. package/dist/styles/sprout/index.d.ts +2 -3
  122. package/dist/styles/sprout/index.js +1 -3
  123. package/package.json +2 -19
  124. package/registry.json +3 -44
  125. package/dist/core/locale.svelte.d.ts +0 -101
  126. package/dist/core/locale.svelte.js +0 -167
  127. package/dist/styles/matte/LocaleProvider.svelte +0 -24
  128. package/dist/styles/matte/LocaleProvider.svelte.d.ts +0 -10
  129. package/dist/styles/paper/LocaleProvider.svelte +0 -24
  130. package/dist/styles/paper/LocaleProvider.svelte.d.ts +0 -10
  131. package/dist/styles/sprout/LocaleProvider.svelte +0 -24
  132. package/dist/styles/sprout/LocaleProvider.svelte.d.ts +0 -10
@@ -2,7 +2,6 @@
2
2
  import type { Snippet } from 'svelte';
3
3
  import { iconLg } from './icon.js';
4
4
  import type { HTMLDialogAttributes } from 'svelte/elements';
5
- import { useLocale } from '../../core/locale.svelte.js';
6
5
  import { isBackdropClick, syncDialog } from '../../core/dialog.svelte.js';
7
6
  import { float } from './lift.js';
8
7
 
@@ -41,7 +40,6 @@
41
40
  ...rest
42
41
  }: Props = $props();
43
42
 
44
- const t = useLocale();
45
43
  let dialog: HTMLDialogElement | null = $state(null);
46
44
 
47
45
  const closable = $derived(showClose ?? dismissible);
@@ -93,7 +91,7 @@
93
91
  <button
94
92
  type="button"
95
93
  onclick={close}
96
- aria-label={t.current.close}
94
+ aria-label="Close"
97
95
  class="-m-1 shrink-0 rounded-xl p-1 text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand"
98
96
  >
99
97
  <svg class="size-4" viewBox="0 0 14 14" fill="none" aria-hidden="true">
@@ -16,7 +16,6 @@
16
16
  import { anchored } from '../../core/actions/anchor.js';
17
17
  import { clickOutside, portal } from '../../core/actions/dismissable.js';
18
18
  import { ListCursor, groupItems, matchQuery, revealIndex } from '../../core/list.svelte.js';
19
- import { useLocale } from '../../core/locale.svelte.js';
20
19
  import { iconMd, iconSm } from './icon.js';
21
20
  import { toneFocusWithinBorder, toneSoft, toneText, type Tone } from '../../core/tones.js';
22
21
  import { edge, soft } from './lift.js';
@@ -59,8 +58,6 @@
59
58
  class: className = ''
60
59
  }: Props = $props();
61
60
 
62
- const t = useLocale();
63
-
64
61
  let open = $state(false);
65
62
  let query = $state('');
66
63
  let wrapper: HTMLElement | null = $state(null);
@@ -150,7 +147,7 @@
150
147
  class="inline-flex items-center rounded-xl px-2 py-0.5 text-xs font-medium {toneSoft[tone]}"
151
148
  >
152
149
  {chosen.length}
153
- {t.current.selected}
150
+ selected
154
151
  </span>
155
152
  {:else}
156
153
  {#each chosen as option (option.value)}
@@ -163,7 +160,7 @@
163
160
  <button
164
161
  type="button"
165
162
  onclick={() => remove(option)}
166
- aria-label="{t.current.removeItem} {option.label}"
163
+ aria-label="Remove {option.label}"
167
164
  class="inline-flex size-4 items-center justify-center rounded transition-colors duration-150 hover:bg-bg/70 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-current"
168
165
  >
169
166
  <svg class="size-2.5" viewBox="0 0 14 14" fill="none" aria-hidden="true">
@@ -190,7 +187,7 @@
190
187
  aria-expanded={open}
191
188
  aria-controls="{id ?? 'multiselect'}-listbox"
192
189
  aria-invalid={invalid ? 'true' : undefined}
193
- placeholder={chosen.length ? '' : (placeholder ?? t.current.comboboxPlaceholder)}
190
+ placeholder={chosen.length ? '' : (placeholder ?? 'Search…')}
194
191
  oninput={() => {
195
192
  open = true;
196
193
  cursor.index = 0;
@@ -212,7 +209,7 @@
212
209
  onchange?.([]);
213
210
  inputEl?.focus();
214
211
  }}
215
- aria-label={t.current.clear}
212
+ aria-label="Clear selection"
216
213
  class="shrink-0 rounded p-1 text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
217
214
  >
218
215
  <svg class="size-3.5" viewBox="0 0 14 14" fill="none" aria-hidden="true">
@@ -240,7 +237,7 @@
240
237
  >
241
238
  {#if flat.length === 0}
242
239
  <p class="px-3 py-6 text-center text-sm text-text-muted">
243
- {emptyText ?? t.current.noMatches}
240
+ {emptyText ?? 'No matches'}
244
241
  </p>
245
242
  {:else}
246
243
  {#each groups as [group, items] (group)}
@@ -16,7 +16,6 @@
16
16
 
17
17
  <script lang="ts">
18
18
  import type { Snippet } from 'svelte';
19
- import { useLocale } from '../../core/locale.svelte.js';
20
19
  import { iconMd } from './icon.js';
21
20
  import { focusRing, toneRing, toneSoft, toneText, type Tone } from '../../core/tones.js';
22
21
  import Drawer from './Drawer.svelte';
@@ -53,8 +52,6 @@
53
52
  class: className = ''
54
53
  }: Props = $props();
55
54
 
56
- const t = useLocale();
57
-
58
55
  // sprout gives the active link a filled pill rather than a colour change, so
59
56
  // the current page is legible without relying on hue alone.
60
57
  const link =
@@ -66,10 +63,7 @@
66
63
  ? 'border-b border-hairline'
67
64
  : ''} {className}"
68
65
  >
69
- <nav
70
- aria-label={t.current.navigation}
71
- class="mx-auto flex h-16 w-full max-w-6xl items-center gap-6 px-6"
72
- >
66
+ <nav aria-label="Navigation" class="mx-auto flex h-16 w-full max-w-6xl items-center gap-6 px-6">
73
67
  {#if brand}
74
68
  <div class="flex shrink-0 items-center">{@render brand()}</div>
75
69
  {/if}
@@ -140,7 +134,7 @@
140
134
  <button
141
135
  type="button"
142
136
  onclick={() => (menuOpen = true)}
143
- aria-label={t.current.openMenu}
137
+ aria-label="Open menu"
144
138
  aria-expanded={menuOpen}
145
139
  class="inline-flex size-9 items-center justify-center rounded-xl text-text-secondary transition-colors duration-150 hover:bg-bg-inset hover:text-text md:hidden {focusRing} {toneRing[
146
140
  tone
@@ -159,7 +153,7 @@
159
153
  </nav>
160
154
  </header>
161
155
 
162
- <Drawer bind:open={menuOpen} side="right" size="sm" title={t.current.navigation}>
156
+ <Drawer bind:open={menuOpen} side="right" size="sm" title="Navigation">
163
157
  <ul class="flex flex-col gap-0.5">
164
158
  {#each items as item (item.label)}
165
159
  <li>
@@ -1,7 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { HTMLAttributes } from 'svelte/elements';
3
3
  import { focusRing, toneRing, toneSolid, type Tone } from '../../core/tones.js';
4
- import { useLocale } from '../../core/locale.svelte.js';
5
4
  import { pageRange } from '../../core/pagination.js';
6
5
  import { liftSm } from './lift.js';
7
6
 
@@ -26,8 +25,6 @@
26
25
  ...rest
27
26
  }: Props = $props();
28
27
 
29
- const t = useLocale();
30
-
31
28
  const pages = $derived(pageRange(page, total, siblings));
32
29
 
33
30
  function go(next: number) {
@@ -40,12 +37,12 @@
40
37
  const cell = `inline-flex h-9 min-w-9 items-center justify-center rounded-full px-2 font-sans text-sm font-medium tabular-nums transition-colors duration-150 ease-brand-out disabled:opacity-40 disabled:pointer-events-none ${focusRing}`;
41
38
  </script>
42
39
 
43
- <nav aria-label={t.current.pagination} class="flex items-center gap-1 {className}" {...rest}>
40
+ <nav aria-label="Pagination" class="flex items-center gap-1 {className}" {...rest}>
44
41
  <button
45
42
  type="button"
46
43
  class="{cell} {toneRing[tone]} text-text-secondary hover:bg-bg-inset"
47
44
  disabled={page <= 1}
48
- aria-label={t.current.previousPage}
45
+ aria-label="Previous page"
49
46
  onclick={() => go(page - 1)}
50
47
  >
51
48
  <svg class="size-4" viewBox="0 0 16 16" fill="none" aria-hidden="true">
@@ -74,7 +71,7 @@
74
71
  type="button"
75
72
  class="{cell} {toneRing[tone]} text-text-secondary hover:bg-bg-inset"
76
73
  disabled={page >= total}
77
- aria-label={t.current.nextPage}
74
+ aria-label="Next page"
78
75
  onclick={() => go(page + 1)}
79
76
  >
80
77
  <svg class="size-4" viewBox="0 0 16 16" fill="none" aria-hidden="true">
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { useLocale } from '../../core/locale.svelte.js';
3
2
  import { caretIndex, clearFrom, fillFrom, sanitisePin, type PinMode } from '../../core/pin.js';
4
3
  import { toneFocusBorder, type Tone } from '../../core/tones.js';
5
4
  import { edge } from './lift.js';
@@ -39,8 +38,6 @@
39
38
  class: className = ''
40
39
  }: Props = $props();
41
40
 
42
- const t = useLocale();
43
-
44
41
  let boxes: HTMLInputElement[] = $state([]);
45
42
 
46
43
  const chars = $derived(Array.from({ length }, (_, i) => value[i] ?? ''));
@@ -120,7 +117,7 @@
120
117
  autocapitalize="characters"
121
118
  spellcheck="false"
122
119
  maxlength={length}
123
- aria-label="{t.current.digit} {index + 1}"
120
+ aria-label="Digit {index + 1}"
124
121
  aria-invalid={invalid ? 'true' : undefined}
125
122
  oninput={(event) => onInput(event, index)}
126
123
  onkeydown={(event) => onKeydown(event, index)}
@@ -1,7 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
3
  import type { HTMLInputAttributes } from 'svelte/elements';
4
- import { useLocale } from '../../core/locale.svelte.js';
5
4
  import type { Tone } from '../../core/tones.js';
6
5
  import Input, { type InputSize } from './Input.svelte';
7
6
 
@@ -37,8 +36,6 @@
37
36
  ...rest
38
37
  }: Props = $props();
39
38
 
40
- const t = useLocale();
41
-
42
39
  // The timer is cleared by the effect's own teardown, so a keystroke that
43
40
  // lands mid-wait restarts the clock rather than queueing a second call.
44
41
  $effect(() => {
@@ -75,7 +72,7 @@
75
72
  <button
76
73
  type="button"
77
74
  onclick={clear}
78
- aria-label={t.current.clearSearch}
75
+ aria-label="Clear search"
79
76
  class="-mr-1 rounded p-1 text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
80
77
  >
81
78
  <svg class="size-3.5" viewBox="0 0 14 14" fill="none" aria-hidden="true">
@@ -35,7 +35,6 @@
35
35
  </script>
36
36
 
37
37
  <script lang="ts">
38
- import { useLocale } from '../../core/locale.svelte.js';
39
38
  import { iconMd } from './icon.js';
40
39
  import { focusRing, toneRing, toneSoft, type Tone } from '../../core/tones.js';
41
40
 
@@ -69,8 +68,6 @@
69
68
  class: className = ''
70
69
  }: Props = $props();
71
70
 
72
- const t = useLocale();
73
-
74
71
  const keyOf = (item: SidebarItem) => item.id ?? item.href ?? item.label;
75
72
 
76
73
  /** Groups start open when asked, or when they contain the active item. */
@@ -141,7 +138,7 @@
141
138
  </div>
142
139
  {/if}
143
140
 
144
- <nav aria-label={t.current.navigation} class="flex-1 overflow-y-auto p-2">
141
+ <nav aria-label="Navigation" class="flex-1 overflow-y-auto p-2">
145
142
  {#each sections as section, i (section.label ?? i)}
146
143
  <div class="flex flex-col gap-0.5 {i > 0 ? 'mt-4' : ''}">
147
144
  {#if section.label && !collapsed}
@@ -230,7 +227,7 @@
230
227
  <button
231
228
  type="button"
232
229
  onclick={() => (collapsed = !collapsed)}
233
- aria-label={collapsed ? t.current.expandSidebar : t.current.collapseSidebar}
230
+ aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
234
231
  class="inline-flex h-8 items-center justify-center gap-2 rounded-xl font-sans text-xs text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text {focusRing} {toneRing[
235
232
  tone
236
233
  ]}"
@@ -248,7 +245,7 @@
248
245
  stroke-linecap="round"
249
246
  />
250
247
  </svg>
251
- {#if !collapsed}<span>{t.current.collapseSidebar}</span>{/if}
248
+ {#if !collapsed}<span>Collapse sidebar</span>{/if}
252
249
  </button>
253
250
  {/if}
254
251
  </div>
@@ -1,7 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { HTMLAttributes } from 'svelte/elements';
3
3
  import { toneText, type Tone } from '../../core/tones.js';
4
- import { useLocale } from '../../core/locale.svelte.js';
5
4
 
6
5
  export type SpinnerSize = 'xs' | 'sm' | 'md' | 'lg';
7
6
 
@@ -9,12 +8,10 @@
9
8
  size?: SpinnerSize;
10
9
  /** Omit to inherit the parent's `currentColor` (e.g. inside a Button). */
11
10
  tone?: Tone;
12
- /** Defaults to the locale's loading string; pass `''` to hide it. */
11
+ /** Defaults to `Loading`; pass `''` to hide it. */
13
12
  label?: string;
14
13
  }
15
14
 
16
- const t = useLocale();
17
-
18
15
  let { size = 'md', tone, label, class: className = '', ...rest }: Props = $props();
19
16
 
20
17
  const sizes: Record<SpinnerSize, string> = {
@@ -27,7 +24,7 @@
27
24
 
28
25
  <span
29
26
  role="status"
30
- aria-label={label ?? t.current.loading}
27
+ aria-label={label ?? 'Loading'}
31
28
  class="inline-block shrink-0 animate-spin rounded-full border-current/25 border-t-current
32
29
  {sizes[size]} {tone ? toneText[tone] : ''} {className}"
33
30
  {...rest}
@@ -5,7 +5,7 @@ interface Props extends HTMLAttributes<HTMLSpanElement> {
5
5
  size?: SpinnerSize;
6
6
  /** Omit to inherit the parent's `currentColor` (e.g. inside a Button). */
7
7
  tone?: Tone;
8
- /** Defaults to the locale's loading string; pass `''` to hide it. */
8
+ /** Defaults to `Loading`; pass `''` to hide it. */
9
9
  label?: string;
10
10
  }
11
11
  declare const Spinner: import("svelte").Component<Props, {}, "">;
@@ -16,7 +16,6 @@
16
16
  import Checkbox from './Checkbox.svelte';
17
17
  import type { Tone } from '../../core/tones.js';
18
18
  import { nextSort, sortRows, toggleKey, type TableSort } from '../../core/table.js';
19
- import { useLocale } from '../../core/locale.svelte.js';
20
19
  import { edge } from './lift.js';
21
20
 
22
21
  interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'onselect'> {
@@ -83,8 +82,6 @@
83
82
  ...rest
84
83
  }: Props = $props();
85
84
 
86
- const t = useLocale();
87
-
88
85
  const aligns = {
89
86
  left: 'text-left',
90
87
  center: 'text-center',
@@ -140,14 +137,14 @@
140
137
  >
141
138
  <span class="font-sans text-[13px] font-semibold text-text">
142
139
  {selected.length}
143
- {t.current.selected}
140
+ selected
144
141
  </span>
145
142
  <button
146
143
  type="button"
147
144
  onclick={clearSelection}
148
145
  class="rounded-full font-sans text-[13px] font-medium text-text-muted transition-colors duration-150 hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
149
146
  >
150
- {t.current.clear}
147
+ Clear selection
151
148
  </button>
152
149
  <div class="ml-auto flex flex-wrap items-center gap-2">
153
150
  {@render bulkActions?.({ selected, clear: clearSelection })}
@@ -177,7 +174,7 @@
177
174
  checked={allSelected}
178
175
  indeterminate={someSelected}
179
176
  {tone}
180
- aria-label={t.current.selectAllRows}
177
+ aria-label="Select all rows"
181
178
  onchange={toggleAll}
182
179
  />
183
180
  </th>
@@ -224,7 +221,7 @@
224
221
  colspan={columns.length + (selectable ? 1 : 0)}
225
222
  class="px-4 py-10 text-center text-sm text-text-muted"
226
223
  >
227
- {#if empty}{@render empty()}{:else}{t.current.noData}{/if}
224
+ {#if empty}{@render empty()}{:else}No data{/if}
228
225
  </td>
229
226
  </tr>
230
227
  {:else}
@@ -241,7 +238,7 @@
241
238
  <Checkbox
242
239
  checked={isSelected}
243
240
  {tone}
244
- aria-label={t.current.selectRow}
241
+ aria-label="Select row"
245
242
  onchange={() => toggleRow(row)}
246
243
  />
247
244
  </td>
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { useLocale } from '../../core/locale.svelte.js';
3
2
  import { addTag, splitTags, type TagRejection } from '../../core/tags.js';
4
3
  import { toneFocusWithinBorder, toneSoft, type Tone } from '../../core/tones.js';
5
4
  import { edge } from './lift.js';
@@ -47,8 +46,6 @@
47
46
  class: className = ''
48
47
  }: Props = $props();
49
48
 
50
- const t = useLocale();
51
-
52
49
  let draft = $state('');
53
50
  let field: HTMLInputElement | null = $state(null);
54
51
  /** The last refusal, cleared as soon as the next keystroke lands. */
@@ -112,8 +109,8 @@
112
109
  const messages: Record<TagRejection, string> = $derived({
113
110
  empty: '',
114
111
  short: `${minLength}+`,
115
- duplicate: t.current.duplicateTag,
116
- full: `${t.current.selected} ${tags.length}/${max}`
112
+ duplicate: 'Already added',
113
+ full: `$selected ${tags.length}/${max}`
117
114
  });
118
115
  </script>
119
116
 
@@ -137,7 +134,7 @@
137
134
  <button
138
135
  type="button"
139
136
  onclick={() => remove(index)}
140
- aria-label="{t.current.removeItem} {tag}"
137
+ aria-label="Remove {tag}"
141
138
  class="inline-flex size-4 items-center justify-center rounded transition-colors duration-150 hover:bg-bg/70 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-current"
142
139
  >
143
140
  <svg class="size-2.5" viewBox="0 0 10 10" fill="none" aria-hidden="true">
@@ -157,8 +154,8 @@
157
154
  bind:value={draft}
158
155
  {disabled}
159
156
  readonly={full}
160
- placeholder={tags.length === 0 ? (placeholder ?? t.current.addTag) : ''}
161
- aria-label={placeholder ?? t.current.addTag}
157
+ placeholder={tags.length === 0 ? (placeholder ?? 'Add a tag') : ''}
158
+ aria-label={placeholder ?? 'Add a tag'}
162
159
  aria-invalid={invalid ? 'true' : undefined}
163
160
  onkeydown={onKeydown}
164
161
  onpaste={onPaste}
@@ -10,7 +10,6 @@
10
10
  storedTheme,
11
11
  type Theme
12
12
  } from '../../core/theme.svelte.js';
13
- import { useLocale } from '../../core/locale.svelte.js';
14
13
  import { edge } from './lift.js';
15
14
 
16
15
  interface Props {
@@ -34,8 +33,6 @@
34
33
  class: className = ''
35
34
  }: Props = $props();
36
35
 
37
- const t = useLocale();
38
-
39
36
  $effect(() => {
40
37
  applyTheme(theme);
41
38
  if (persist) persistTheme(theme);
@@ -51,8 +48,8 @@
51
48
  }
52
49
 
53
50
  const options = $derived([
54
- { value: 'light' as Theme, label: t.current.lightMode },
55
- { value: 'dark' as Theme, label: t.current.darkMode },
51
+ { value: 'light' as Theme, label: 'Light' },
52
+ { value: 'dark' as Theme, label: 'Dark' },
56
53
  { value: 'system' as Theme, label: 'Auto' }
57
54
  ]);
58
55
  </script>
@@ -96,7 +93,7 @@
96
93
  {#if variant === 'segmented'}
97
94
  <div
98
95
  role="radiogroup"
99
- aria-label={t.current.toggleTheme}
96
+ aria-label="Toggle theme"
100
97
  class="inline-flex items-center gap-1 rounded-2xl border border-hairline bg-bg-inset p-1 {className}"
101
98
  >
102
99
  {#each options as option (option.value)}
@@ -120,8 +117,8 @@
120
117
  <button
121
118
  type="button"
122
119
  onclick={cycle}
123
- aria-label="{t.current.toggleTheme} ({theme})"
124
- title={t.current.toggleTheme}
120
+ aria-label="Toggle theme ({theme})"
121
+ title="Toggle theme"
125
122
  class="inline-flex size-9 items-center justify-center rounded-xl border border-hairline bg-bg text-text-secondary {edge} transition-colors duration-150 ease-brand-out hover:bg-bg-alt hover:text-text {focusRing} {toneRing[
126
123
  tone
127
124
  ]} {className}"
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">
2
2
  import type { HTMLInputAttributes } from 'svelte/elements';
3
- import { useLocale } from '../../core/locale.svelte.js';
4
3
  import { clampTime, formatTime, parseTime, stepTime } from '../../core/time.js';
5
4
  import type { Tone } from '../../core/tones.js';
6
5
  import Input, { type InputSize } from './Input.svelte';
@@ -38,8 +37,6 @@
38
37
  ...rest
39
38
  }: Props = $props();
40
39
 
41
- const t = useLocale();
42
-
43
40
  // Typed text and the bound value are separate until the field settles:
44
41
  // `9` is a valid thing to be halfway through typing and an invalid time.
45
42
  let text = $state('');
@@ -120,7 +117,7 @@
120
117
  class={stepper}
121
118
  {disabled}
122
119
  onclick={() => nudge(1)}
123
- aria-label={t.current.increase}
120
+ aria-label="Increase"
124
121
  >
125
122
  <svg class="size-3" viewBox="0 0 12 12" fill="none" aria-hidden="true">
126
123
  <path
@@ -137,7 +134,7 @@
137
134
  class={stepper}
138
135
  {disabled}
139
136
  onclick={() => nudge(-1)}
140
- aria-label={t.current.decrease}
137
+ aria-label="Decrease"
141
138
  >
142
139
  <svg class="size-3" viewBox="0 0 12 12" fill="none" aria-hidden="true">
143
140
  <path
@@ -6,7 +6,6 @@
6
6
  import { toneText } from '../../core/tones.js';
7
7
  import { iconMd } from './icon.js';
8
8
  import Spinner from './Spinner.svelte';
9
- import { useLocale } from '../../core/locale.svelte.js';
10
9
  import { soft } from './lift.js';
11
10
 
12
11
  export type ToasterPosition =
@@ -19,8 +18,6 @@
19
18
 
20
19
  let { position = 'bottom-right', class: className = '' }: Props = $props();
21
20
 
22
- const t = useLocale();
23
-
24
21
  const positions: Record<ToasterPosition, string> = {
25
22
  'top-left': 'top-4 left-4 items-start',
26
23
  'top-center': 'top-4 left-1/2 -translate-x-1/2 items-center',
@@ -42,8 +39,8 @@
42
39
  <div
43
40
  use:portal
44
41
  aria-live="polite"
45
- aria-label={t.current.notifications}
46
- class="pointer-events-none fixed z-[100] flex w-[min(24rem,calc(100vw-2rem))] flex-col gap-2.5 {positions[
42
+ aria-label="Notifications"
43
+ class="pointer-events-none fixed z-100 flex w-[min(24rem,calc(100vw-2rem))] flex-col gap-2.5 {positions[
47
44
  position
48
45
  ]} {fromTop ? '' : 'flex-col-reverse'} {className}"
49
46
  >
@@ -119,7 +116,7 @@
119
116
  <button
120
117
  type="button"
121
118
  onclick={() => toast.dismiss(item.id)}
122
- aria-label={t.current.dismiss}
119
+ aria-label="Dismiss"
123
120
  class="-m-1 shrink-0 rounded p-1 text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
124
121
  >
125
122
  <svg class="size-3.5" viewBox="0 0 14 14" fill="none" aria-hidden="true">
@@ -5,9 +5,8 @@
5
5
  * `@nqmcreative/ui/core`, re-exported below so this one import covers
6
6
  * the whole style.
7
7
  */
8
- export { TONES, focusRing, peerFocusRing, toneBorder, toneBorderLeft, toneBorderSoft, toneFill, toneFocusBorder, toneFocusWithinBorder, toneHoverBorder, toneHoverText, tonePeerChecked, tonePeerFocus, toneRing, toneSoft, toneSoftHover, toneSolid, toneSolidHover, toneSurface, toneText, anchored, clickOutside, focusTrap, focusable, navigateList, portal, toast, locale, setLocale, provideLocale, useLocale, enUS, idID, LocaleStore, applyTheme, storedTheme, toISO, fromISO, today, isSameDay, addDays, addMonths, monthGrid, weekdayNames, monthLabel, isOutOfRange, formatISO, parseFormatted } from '../../core/index.js';
9
- export type { Tone, Placement, AnchorOptions, ClickOutsideOptions, FocusTrapOptions, Toast, ToastOptions, ToastAction, Locale, Theme, DateFormat, TableSort, SortDirection, RejectedFile } from '../../core/index.js';
10
- export { default as LocaleProvider } from './LocaleProvider.svelte';
8
+ export { TONES, focusRing, peerFocusRing, toneBorder, toneBorderLeft, toneBorderSoft, toneFill, toneFocusBorder, toneFocusWithinBorder, toneHoverBorder, toneHoverText, tonePeerChecked, tonePeerFocus, toneRing, toneSoft, toneSoftHover, toneSolid, toneSolidHover, toneSurface, toneText, anchored, clickOutside, focusTrap, focusable, navigateList, portal, toast, applyTheme, storedTheme, toISO, fromISO, today, isSameDay, addDays, addMonths, monthGrid, weekdayNames, monthLabel, isOutOfRange, formatISO, parseFormatted } from '../../core/index.js';
9
+ export type { Tone, Placement, AnchorOptions, ClickOutsideOptions, FocusTrapOptions, Toast, ToastOptions, ToastAction, Theme, DateFormat, TableSort, SortDirection, RejectedFile } from '../../core/index.js';
11
10
  export { default as Button } from './Button.svelte';
12
11
  export type { ButtonVariant, ButtonSize } from './Button.svelte';
13
12
  export { default as Link } from './Link.svelte';
@@ -6,9 +6,7 @@
6
6
  * the whole style.
7
7
  */
8
8
  /* --- shared behaviour --- */
9
- export { TONES, focusRing, peerFocusRing, toneBorder, toneBorderLeft, toneBorderSoft, toneFill, toneFocusBorder, toneFocusWithinBorder, toneHoverBorder, toneHoverText, tonePeerChecked, tonePeerFocus, toneRing, toneSoft, toneSoftHover, toneSolid, toneSolidHover, toneSurface, toneText, anchored, clickOutside, focusTrap, focusable, navigateList, portal, toast, locale, setLocale, provideLocale, useLocale, enUS, idID, LocaleStore, applyTheme, storedTheme, toISO, fromISO, today, isSameDay, addDays, addMonths, monthGrid, weekdayNames, monthLabel, isOutOfRange, formatISO, parseFormatted } from '../../core/index.js';
10
- /* --- locale --- */
11
- export { default as LocaleProvider } from './LocaleProvider.svelte';
9
+ export { TONES, focusRing, peerFocusRing, toneBorder, toneBorderLeft, toneBorderSoft, toneFill, toneFocusBorder, toneFocusWithinBorder, toneHoverBorder, toneHoverText, tonePeerChecked, tonePeerFocus, toneRing, toneSoft, toneSoftHover, toneSolid, toneSolidHover, toneSurface, toneText, anchored, clickOutside, focusTrap, focusable, navigateList, portal, toast, applyTheme, storedTheme, toISO, fromISO, today, isSameDay, addDays, addMonths, monthGrid, weekdayNames, monthLabel, isOutOfRange, formatISO, parseFormatted } from '../../core/index.js';
12
10
  /* --- actions --- */
13
11
  export { default as Button } from './Button.svelte';
14
12
  export { default as Link } from './Link.svelte';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nqmcreative/ui",
3
- "version": "0.4.0",
4
- "description": "Svelte 5 + Tailwind CSS v4 component library — three styles (matte, paper, sprout), 71 components each, one shared behaviour core. No runtime dependencies.",
3
+ "version": "0.4.1",
4
+ "description": "Svelte 5 + Tailwind CSS v4 component library — three styles (matte, paper, sprout), 70 components each, one shared behaviour core. No runtime dependencies.",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
7
7
  "build": "vite build && svelte-kit sync && svelte-package && node scripts/strip-dist-tests.mjs && node scripts/generate-index.mjs && node scripts/generate-exports.mjs && node scripts/generate-registry.mjs && node scripts/generate-scoped-css.mjs && node scripts/generate-demos.mjs && publint",
@@ -42,11 +42,6 @@
42
42
  "svelte": "./dist/core/tones.js",
43
43
  "default": "./dist/core/tones.js"
44
44
  },
45
- "./core/locale": {
46
- "types": "./dist/core/locale.svelte.d.ts",
47
- "svelte": "./dist/core/locale.svelte.js",
48
- "default": "./dist/core/locale.svelte.js"
49
- },
50
45
  "./core/date": {
51
46
  "types": "./dist/core/date.d.ts",
52
47
  "svelte": "./dist/core/date.js",
@@ -91,10 +86,6 @@
91
86
  "types": "./dist/styles/matte/index.d.ts",
92
87
  "svelte": "./dist/styles/matte/index.js"
93
88
  },
94
- "./matte/locale-provider": {
95
- "types": "./dist/styles/matte/LocaleProvider.svelte.d.ts",
96
- "svelte": "./dist/styles/matte/LocaleProvider.svelte"
97
- },
98
89
  "./matte/button": {
99
90
  "types": "./dist/styles/matte/Button.svelte.d.ts",
100
91
  "svelte": "./dist/styles/matte/Button.svelte"
@@ -381,10 +372,6 @@
381
372
  "types": "./dist/styles/paper/index.d.ts",
382
373
  "svelte": "./dist/styles/paper/index.js"
383
374
  },
384
- "./paper/locale-provider": {
385
- "types": "./dist/styles/paper/LocaleProvider.svelte.d.ts",
386
- "svelte": "./dist/styles/paper/LocaleProvider.svelte"
387
- },
388
375
  "./paper/button": {
389
376
  "types": "./dist/styles/paper/Button.svelte.d.ts",
390
377
  "svelte": "./dist/styles/paper/Button.svelte"
@@ -671,10 +658,6 @@
671
658
  "types": "./dist/styles/sprout/index.d.ts",
672
659
  "svelte": "./dist/styles/sprout/index.js"
673
660
  },
674
- "./sprout/locale-provider": {
675
- "types": "./dist/styles/sprout/LocaleProvider.svelte.d.ts",
676
- "svelte": "./dist/styles/sprout/LocaleProvider.svelte"
677
- },
678
661
  "./sprout/button": {
679
662
  "types": "./dist/styles/sprout/Button.svelte.d.ts",
680
663
  "svelte": "./dist/styles/sprout/Button.svelte"