@marianmeres/stuic 3.107.0 → 3.109.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.
Files changed (26) hide show
  1. package/dist/components/Checkout/CheckoutAddressForm.svelte +6 -6
  2. package/dist/components/Checkout/CheckoutAddressForm.svelte.d.ts +3 -3
  3. package/dist/components/Input/FieldCountry.svelte +63 -14
  4. package/dist/components/Input/FieldCountry.svelte.d.ts +24 -3
  5. package/dist/components/Input/FieldPhoneNumber.svelte +10 -8
  6. package/dist/components/Input/_internal/PhonePrefixPicker.svelte +2 -2
  7. package/dist/components/Input/_internal/PhonePrefixPicker.svelte.d.ts +1 -1
  8. package/dist/components/Input/index.d.ts +0 -1
  9. package/dist/components/Input/index.js +0 -1
  10. package/dist/components/MarkdownEditor/MarkdownEditor.svelte +541 -0
  11. package/dist/components/MarkdownEditor/MarkdownEditor.svelte.d.ts +87 -0
  12. package/dist/components/MarkdownEditor/README.md +172 -0
  13. package/dist/components/MarkdownEditor/_internal/codemirror.d.ts +2 -0
  14. package/dist/components/MarkdownEditor/_internal/codemirror.js +201 -0
  15. package/dist/components/MarkdownEditor/_internal/milkdown.d.ts +2 -0
  16. package/dist/components/MarkdownEditor/_internal/milkdown.js +199 -0
  17. package/dist/components/MarkdownEditor/_internal/types.d.ts +57 -0
  18. package/dist/components/MarkdownEditor/_internal/types.js +7 -0
  19. package/dist/components/MarkdownEditor/index.css +285 -0
  20. package/dist/components/MarkdownEditor/index.d.ts +2 -0
  21. package/dist/components/MarkdownEditor/index.js +1 -0
  22. package/dist/icons/index.d.ts +13 -0
  23. package/dist/icons/index.js +15 -0
  24. package/package.json +89 -6
  25. package/dist/components/Input/_internal/countries.d.ts +0 -20
  26. package/dist/components/Input/_internal/countries.js +0 -252
@@ -1,14 +1,14 @@
1
1
  <script lang="ts" module>
2
+ import type { Country } from "@marianmeres/countries";
2
3
  import type { Snippet } from "svelte";
3
4
  import type { HTMLAttributes } from "svelte/elements";
4
5
  import type { TranslateFn } from "../../types.js";
6
+ import type { Props as FieldCountryProps } from "../Input/FieldCountry.svelte";
7
+ import type { Props as FieldPhoneNumberProps } from "../Input/FieldPhoneNumber.svelte";
5
8
  import type {
6
9
  CheckoutAddressData,
7
10
  CheckoutValidationError,
8
11
  } from "./_internal/checkout-types.js";
9
- import type { Props as FieldPhoneNumberProps } from "../Input/FieldPhoneNumber.svelte";
10
- import type { Props as FieldCountryProps } from "../Input/FieldCountry.svelte";
11
- import type { Country } from "../Input/_internal/countries.js";
12
12
 
13
13
  export interface Props extends Omit<HTMLAttributes<HTMLFieldSetElement>, "children"> {
14
14
  /**
@@ -106,12 +106,12 @@
106
106
  scrollToFirstInvalidField,
107
107
  validateAllFields,
108
108
  } from "../../utils/validate-fields.js";
109
- import { t_default } from "./_internal/checkout-i18n-defaults.js";
110
- import { createEmptyAddress } from "./_internal/checkout-utils.js";
109
+ import FieldCountry from "../Input/FieldCountry.svelte";
111
110
  import FieldInput from "../Input/FieldInput.svelte";
112
111
  import FieldPhoneNumber from "../Input/FieldPhoneNumber.svelte";
113
- import FieldCountry from "../Input/FieldCountry.svelte";
114
112
  import { validatePhoneNumber } from "../Input/phone-validation.js";
113
+ import { t_default } from "./_internal/checkout-i18n-defaults.js";
114
+ import { createEmptyAddress } from "./_internal/checkout-utils.js";
115
115
 
116
116
  const DEFAULT_REQUIRED = ["name", "street", "city", "postal_code", "country"];
117
117
 
@@ -1,10 +1,10 @@
1
+ import type { Country } from "@marianmeres/countries";
1
2
  import type { Snippet } from "svelte";
2
3
  import type { HTMLAttributes } from "svelte/elements";
3
4
  import type { TranslateFn } from "../../types.js";
4
- import type { CheckoutAddressData, CheckoutValidationError } from "./_internal/checkout-types.js";
5
- import type { Props as FieldPhoneNumberProps } from "../Input/FieldPhoneNumber.svelte";
6
5
  import type { Props as FieldCountryProps } from "../Input/FieldCountry.svelte";
7
- import type { Country } from "../Input/_internal/countries.js";
6
+ import type { Props as FieldPhoneNumberProps } from "../Input/FieldPhoneNumber.svelte";
7
+ import type { CheckoutAddressData, CheckoutValidationError } from "./_internal/checkout-types.js";
8
8
  export interface Props extends Omit<HTMLAttributes<HTMLFieldSetElement>, "children"> {
9
9
  /**
10
10
  * Bindable address data. Default: createEmptyAddress().
@@ -1,9 +1,9 @@
1
1
  <script lang="ts" module>
2
+ import type { Country } from "@marianmeres/countries";
2
3
  import type { Snippet } from "svelte";
3
4
  import type { ValidateOptions } from "../../actions/validate.svelte.js";
4
5
  import type { TranslateFn } from "../../types.js";
5
6
  import type { THC } from "../Thc/Thc.svelte";
6
- import type { Country } from "./_internal/countries.js";
7
7
  import type { InputWrapClassProps } from "./types.js";
8
8
 
9
9
  type SnippetWithId = Snippet<[{ id: string }]>;
@@ -26,11 +26,33 @@
26
26
 
27
27
  /**
28
28
  * Override displayed country names. Keys are ISO alpha-2 codes,
29
- * values are the localized name. Missing keys fall back to the English
30
- * name from countries.ts.
29
+ * values are the localized name. Takes precedence over `locale`; missing
30
+ * keys fall back to the locale-resolved name (then the English name).
31
31
  */
32
32
  countryNames?: Record<string, string>;
33
33
 
34
+ /**
35
+ * Display country names in this locale (ISO 639-1 code, e.g. "sk").
36
+ * Resolved via @marianmeres/countries' built-in locales.
37
+ *
38
+ * Locales load lazily (code-split), so by default names render in
39
+ * English for one frame until the chunk arrives. To avoid that flash,
40
+ * make the locale synchronously available before this field renders —
41
+ * either register it once at app startup:
42
+ *
43
+ * ```ts
44
+ * import { registerLocale } from "@marianmeres/countries";
45
+ * import sk from "@marianmeres/countries/locales/sk";
46
+ * registerLocale("sk", sk);
47
+ * ```
48
+ *
49
+ * …or skip the `locale` prop entirely and pass the statically-imported
50
+ * map straight to `countryNames={sk}` (it's keyed by ISO code).
51
+ *
52
+ * Default: "en". Overridden per-country by `countryNames`.
53
+ */
54
+ locale?: string;
55
+
34
56
  /** Show country flag emoji in dropdown items. Default: true. */
35
57
  flags?: boolean;
36
58
 
@@ -68,21 +90,28 @@
68
90
  </script>
69
91
 
70
92
  <script lang="ts">
93
+ import {
94
+ COUNTRIES,
95
+ DEFAULT_LOCALE,
96
+ ISO_MAP,
97
+ getName,
98
+ hasLocale,
99
+ loadLocale,
100
+ } from "@marianmeres/countries";
71
101
  import { tick } from "svelte";
72
102
  import {
73
103
  validate as validateAction,
74
104
  type ValidationResult,
75
105
  } from "../../actions/validate.svelte.js";
106
+ import { iconChevronDown } from "../../icons/index.js";
76
107
  import { getId } from "../../utils/get-id.js";
77
108
  import { twMerge } from "../../utils/tw-merge.js";
78
- import { iconChevronDown } from "../../icons/index.js";
79
109
  import DropdownMenu, {
80
110
  type DropdownMenuActionItem,
81
111
  type DropdownMenuItem,
82
112
  type DropdownMenuSearchConfig,
83
113
  } from "../DropdownMenu/DropdownMenu.svelte";
84
114
  import InputWrap from "./_internal/InputWrap.svelte";
85
- import { COUNTRIES, ISO_MAP } from "./_internal/countries.js";
86
115
 
87
116
  let {
88
117
  value = $bindable(""),
@@ -90,6 +119,7 @@
90
119
  countryList: countryListProp,
91
120
  preferredCountries,
92
121
  countryNames,
122
+ locale = DEFAULT_LOCALE,
93
123
  flags = true,
94
124
  //
95
125
  name,
@@ -171,8 +201,32 @@
171
201
  });
172
202
  }
173
203
 
204
+ // Reactive marker: bumps once the requested locale is registered, so the
205
+ // derived names below recompute. The locale registry in @marianmeres/countries
206
+ // is plain module state, not a Svelte reactive source, hence this $state tick.
207
+ let localeLoaded = $state(DEFAULT_LOCALE);
208
+ $effect(() => {
209
+ const code = locale;
210
+ if (hasLocale(code)) {
211
+ localeLoaded = code;
212
+ return;
213
+ }
214
+ let cancelled = false;
215
+ loadLocale(code)
216
+ .then(() => {
217
+ if (!cancelled) localeLoaded = code;
218
+ })
219
+ .catch(() => {
220
+ if (!cancelled) localeLoaded = DEFAULT_LOCALE;
221
+ });
222
+ return () => {
223
+ cancelled = true;
224
+ };
225
+ });
226
+
174
227
  function localizedName(c: Country): string {
175
- return countryNames?.[c.iso] ?? c.name;
228
+ void localeLoaded; // establish reactive dependency on locale load
229
+ return countryNames?.[c.iso] ?? getName(c.iso, locale) ?? c.name;
176
230
  }
177
231
 
178
232
  // Resolve the working country list (accept ISO codes or Country objects).
@@ -180,9 +234,7 @@
180
234
  if (!countryListProp) return COUNTRIES;
181
235
  if (countryListProp.length === 0) return [];
182
236
  if (typeof countryListProp[0] === "string") {
183
- const set = new Set(
184
- (countryListProp as string[]).map((c) => c.toUpperCase())
185
- );
237
+ const set = new Set((countryListProp as string[]).map((c) => c.toUpperCase()));
186
238
  return COUNTRIES.filter((c) => set.has(c.iso));
187
239
  }
188
240
  return countryListProp as Country[];
@@ -223,9 +275,7 @@
223
275
 
224
276
  let items: DropdownMenuItem[] = $derived.by(() => {
225
277
  const result: DropdownMenuItem[] = [];
226
- const preferredSet = new Set(
227
- preferredCountries?.map((c) => c.toUpperCase()) ?? []
228
- );
278
+ const preferredSet = new Set(preferredCountries?.map((c) => c.toUpperCase()) ?? []);
229
279
 
230
280
  if (preferredSet.size > 0) {
231
281
  // Preserve the order given in `preferredCountries`.
@@ -260,8 +310,7 @@
260
310
  return `${localized} ${c.name} ${c.iso}`;
261
311
  },
262
312
  autoFocus: true,
263
- noResultsMessage:
264
- t?.("checkout.address.country_no_results") || "No country found",
313
+ noResultsMessage: t?.("checkout.address.country_no_results") || "No country found",
265
314
  });
266
315
 
267
316
  let triggerText = $derived.by(() => {
@@ -1,8 +1,8 @@
1
+ import type { Country } from "@marianmeres/countries";
1
2
  import type { Snippet } from "svelte";
2
3
  import type { ValidateOptions } from "../../actions/validate.svelte.js";
3
4
  import type { TranslateFn } from "../../types.js";
4
5
  import type { THC } from "../Thc/Thc.svelte";
5
- import type { Country } from "./_internal/countries.js";
6
6
  import type { InputWrapClassProps } from "./types.js";
7
7
  type SnippetWithId = Snippet<[{
8
8
  id: string;
@@ -21,10 +21,31 @@ export interface Props extends InputWrapClassProps, Record<string, any> {
21
21
  preferredCountries?: string[];
22
22
  /**
23
23
  * Override displayed country names. Keys are ISO alpha-2 codes,
24
- * values are the localized name. Missing keys fall back to the English
25
- * name from countries.ts.
24
+ * values are the localized name. Takes precedence over `locale`; missing
25
+ * keys fall back to the locale-resolved name (then the English name).
26
26
  */
27
27
  countryNames?: Record<string, string>;
28
+ /**
29
+ * Display country names in this locale (ISO 639-1 code, e.g. "sk").
30
+ * Resolved via @marianmeres/countries' built-in locales.
31
+ *
32
+ * Locales load lazily (code-split), so by default names render in
33
+ * English for one frame until the chunk arrives. To avoid that flash,
34
+ * make the locale synchronously available before this field renders —
35
+ * either register it once at app startup:
36
+ *
37
+ * ```ts
38
+ * import { registerLocale } from "@marianmeres/countries";
39
+ * import sk from "@marianmeres/countries/locales/sk";
40
+ * registerLocale("sk", sk);
41
+ * ```
42
+ *
43
+ * …or skip the `locale` prop entirely and pass the statically-imported
44
+ * map straight to `countryNames={sk}` (it's keyed by ISO code).
45
+ *
46
+ * Default: "en". Overridden per-country by `countryNames`.
47
+ */
48
+ locale?: string;
28
49
  /** Show country flag emoji in dropdown items. Default: true. */
29
50
  flags?: boolean;
30
51
  /** Hidden input name (enables form submission + validation). */
@@ -59,6 +59,13 @@
59
59
  </script>
60
60
 
61
61
  <script lang="ts">
62
+ import {
63
+ COUNTRIES,
64
+ DIAL_CODES_DESC,
65
+ DIAL_CODE_MAP,
66
+ ISO_MAP,
67
+ type Country,
68
+ } from "@marianmeres/countries";
62
69
  import { tick, untrack } from "svelte";
63
70
  import {
64
71
  validate as validateAction,
@@ -68,13 +75,6 @@
68
75
  import { twMerge } from "../../utils/tw-merge.js";
69
76
  import InputWrap from "./_internal/InputWrap.svelte";
70
77
  import PhonePrefixPicker from "./_internal/PhonePrefixPicker.svelte";
71
- import {
72
- COUNTRIES,
73
- ISO_MAP,
74
- DIAL_CODES_DESC,
75
- DIAL_CODE_MAP,
76
- type Country,
77
- } from "./_internal/countries.js";
78
78
  import { validatePhoneNumber } from "./phone-validation.js";
79
79
 
80
80
  let {
@@ -173,7 +173,9 @@
173
173
 
174
174
  // Selected country object (initialize once from defaultCountry prop)
175
175
  let selectedCountry: Country | undefined = $state(
176
- untrack(() => (defaultCountry ? ISO_MAP.get(defaultCountry.toUpperCase()) : undefined))
176
+ untrack(() =>
177
+ defaultCountry ? ISO_MAP.get(defaultCountry.toUpperCase()) : undefined
178
+ )
177
179
  );
178
180
 
179
181
  // Internal local number (for controlled input)
@@ -1,12 +1,12 @@
1
1
  <script lang="ts">
2
- import { twMerge } from "../../../utils/tw-merge.js";
2
+ import { type Country, ISO_MAP } from "@marianmeres/countries";
3
3
  import { iconChevronDown } from "../../../icons/index.js";
4
+ import { twMerge } from "../../../utils/tw-merge.js";
4
5
  import DropdownMenu, {
5
6
  type DropdownMenuActionItem,
6
7
  type DropdownMenuItem,
7
8
  type DropdownMenuSearchConfig,
8
9
  } from "../../DropdownMenu/DropdownMenu.svelte";
9
- import { type Country, ISO_MAP } from "./countries.js";
10
10
 
11
11
  interface Props {
12
12
  selectedCountry?: Country;
@@ -1,4 +1,4 @@
1
- import { type Country } from "./countries.js";
1
+ import { type Country } from "@marianmeres/countries";
2
2
  interface Props {
3
3
  selectedCountry?: Country;
4
4
  countryList: Country[];
@@ -16,4 +16,3 @@ export { default as FieldObject, type Props as FieldObjectProps, } from "./Field
16
16
  export { default as FieldPhoneNumber, type Props as FieldPhoneNumberProps, } from "./FieldPhoneNumber.svelte";
17
17
  export { default as FieldCountry, type Props as FieldCountryProps, } from "./FieldCountry.svelte";
18
18
  export { validatePhoneNumber } from "./phone-validation.js";
19
- export { type Country, COUNTRIES, ISO_MAP } from "./_internal/countries.js";
@@ -16,4 +16,3 @@ export { default as FieldObject, } from "./FieldObject.svelte";
16
16
  export { default as FieldPhoneNumber, } from "./FieldPhoneNumber.svelte";
17
17
  export { default as FieldCountry, } from "./FieldCountry.svelte";
18
18
  export { validatePhoneNumber } from "./phone-validation.js";
19
- export { COUNTRIES, ISO_MAP } from "./_internal/countries.js";