svelte-tel-input 4.1.1 → 4.3.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.
@@ -1,10 +1,10 @@
1
1
  <script lang="ts">
2
2
  import { onMount, untrack } from 'svelte';
3
- import { ParseError } from 'libphonenumber-js/max';
3
+ import { ParseError } from 'libphonenumber-js/max/es6';
4
4
  import { generatePlaceholder } from '../../utils/index.js';
5
5
  import { parsePhoneInput } from '../../utils/helpers.js';
6
6
  import { telInputAction } from '../../utils/directives/telInputAction.js';
7
- import { getCountry, guessCountryByPartialNumber } from '../../utils/countryHelpers.js';
7
+ import { getCountryByIso2, guessCountryByPartialNumber } from '../../utils/countryHelpers.js';
8
8
  import type { CountryCode, TelInputOptions, Props, ValidationError } from '../../types';
9
9
 
10
10
  const defaultOptions = {
@@ -29,6 +29,7 @@
29
29
  onValueChange,
30
30
  onError,
31
31
  initialFormat = 'international',
32
+ placeholderFormat = undefined,
32
33
  value = $bindable(''),
33
34
  country = $bindable(null),
34
35
  defaultCountry = null,
@@ -37,46 +38,59 @@
37
38
  validationError = $bindable<Readonly<ValidationError>>(null),
38
39
  options = defaultOptions,
39
40
  el = $bindable(undefined),
41
+ validateProps = false,
40
42
  'aria-invalid': ariaInvalidProp = undefined,
41
43
  ...rest
42
44
  }: Props = $props();
43
45
 
44
- untrack(() => {
45
- const badProp = (prop: string, expected: string, got: unknown): never => {
46
- const gotDesc =
47
- got !== null && typeof got === 'object'
48
- ? Array.isArray(got)
49
- ? 'array'
50
- : `object { ${Object.keys(got as object)
51
- .slice(0, 4)
52
- .join(', ')}${Object.keys(got as object).length > 4 ? ', …' : ''} }`
53
- : typeof got;
54
- throw new TypeError(
55
- `<TelInput> invalid prop "${prop}": expected ${expected}, but received ${gotDesc}.`
56
- );
57
- };
58
-
59
- if (typeof value !== 'string') badProp('value', 'string', value);
60
- if (country !== null && country !== undefined && typeof country !== 'string')
61
- badProp('country', 'CountryCode | null | undefined', country);
62
- if (name !== null && name !== undefined && typeof name !== 'string')
63
- badProp('name', 'string | null', name);
64
- if (placeholder !== null && placeholder !== undefined && typeof placeholder !== 'string')
65
- badProp('placeholder', 'string | null', placeholder);
66
- if (disabled !== undefined && disabled !== null && typeof disabled !== 'boolean')
67
- badProp('disabled', 'boolean', disabled);
68
- if (readonly !== null && readonly !== undefined && typeof readonly !== 'boolean')
69
- badProp('readonly', 'boolean | null', readonly);
70
- if (required !== null && required !== undefined && typeof required !== 'boolean')
71
- badProp('required', 'boolean | null', required);
72
- if (size !== null && size !== undefined && typeof size !== 'number')
73
- badProp('size', 'number | null', size);
74
- if (
75
- options !== undefined &&
76
- (typeof options !== 'object' || options === null || Array.isArray(options))
77
- )
78
- badProp('options', 'TelInputOptions object', options);
79
- });
46
+ // Runtime prop type-checking, opt-in via `validateProps`. Off by default so the
47
+ // checks add nothing to production bundles; enable it (e.g. in development) to
48
+ // get descriptive errors on malformed props.
49
+ // Intentionally reads the initial value only — this is a one-time init guard.
50
+ // svelte-ignore state_referenced_locally
51
+ if (validateProps)
52
+ untrack(() => {
53
+ const badProp = (prop: string, expected: string, got: unknown): never => {
54
+ const gotDesc =
55
+ got !== null && typeof got === 'object'
56
+ ? Array.isArray(got)
57
+ ? 'array'
58
+ : `object { ${Object.keys(got as object)
59
+ .slice(0, 4)
60
+ .join(
61
+ ', '
62
+ )}${Object.keys(got as object).length > 4 ? ', …' : ''} }`
63
+ : typeof got;
64
+ throw new TypeError(
65
+ `<TelInput> invalid prop "${prop}": expected ${expected}, but received ${gotDesc}.`
66
+ );
67
+ };
68
+
69
+ if (typeof value !== 'string') badProp('value', 'string', value);
70
+ if (country !== null && country !== undefined && typeof country !== 'string')
71
+ badProp('country', 'CountryCode | null | undefined', country);
72
+ if (name !== null && name !== undefined && typeof name !== 'string')
73
+ badProp('name', 'string | null', name);
74
+ if (
75
+ placeholder !== null &&
76
+ placeholder !== undefined &&
77
+ typeof placeholder !== 'string'
78
+ )
79
+ badProp('placeholder', 'string | null', placeholder);
80
+ if (disabled !== undefined && disabled !== null && typeof disabled !== 'boolean')
81
+ badProp('disabled', 'boolean', disabled);
82
+ if (readonly !== null && readonly !== undefined && typeof readonly !== 'boolean')
83
+ badProp('readonly', 'boolean | null', readonly);
84
+ if (required !== null && required !== undefined && typeof required !== 'boolean')
85
+ badProp('required', 'boolean | null', required);
86
+ if (size !== null && size !== undefined && typeof size !== 'number')
87
+ badProp('size', 'number | null', size);
88
+ if (
89
+ options !== undefined &&
90
+ (typeof options !== 'object' || options === null || Array.isArray(options))
91
+ )
92
+ badProp('options', 'TelInputOptions object', options);
93
+ });
80
94
 
81
95
  // Fix: initialize to null so server and client start with an identical render.
82
96
  // The ID is generated only in onMount (client-only), avoiding UUID hydration mismatches.
@@ -123,7 +137,7 @@
123
137
  if (fullDialCodeMatch) effectiveCountryIso2 = detected?.iso2 ?? null;
124
138
  }
125
139
  const countryObj = effectiveCountryIso2
126
- ? getCountry({ field: 'iso2', value: effectiveCountryIso2 })
140
+ ? getCountryByIso2(effectiveCountryIso2)
127
141
  : undefined;
128
142
  try {
129
143
  const details = parsePhoneInput(value, countryObj);
@@ -159,7 +173,6 @@
159
173
  //Initialized to the incoming prop values so the first render never false-fires.
160
174
  let _lastWrittenValue: string = value;
161
175
  let _lastWrittenCountry: CountryCode | null | undefined = untrack(() => country);
162
- // let isInitialized = $state(false);
163
176
 
164
177
  // When true, `handleParsePhoneNumber` and the spaces-effect will display the
165
178
  // national (dial-code-stripped) format. Starts as `true` when
@@ -249,7 +262,7 @@
249
262
  };
250
263
 
251
264
  const getCountryObj = (iso2: CountryCode | null | undefined) =>
252
- iso2 ? getCountry({ field: 'iso2', value: iso2 }) : undefined;
265
+ iso2 ? getCountryByIso2(iso2) : undefined;
253
266
 
254
267
  const handleParsePhoneNumber = (
255
268
  rawInput: string | null,
@@ -419,7 +432,8 @@
419
432
  const getPlaceholder = $derived(
420
433
  combinedOptions.autoPlaceholder && initialCountry
421
434
  ? generatePlaceholder(initialCountry, {
422
- spaces: combinedOptions.spaces
435
+ spaces: combinedOptions.spaces,
436
+ format: placeholderFormat ?? initialFormat
423
437
  })
424
438
  : placeholder
425
439
  );
@@ -493,7 +507,6 @@
493
507
  // so national format is applied automatically when initialFormat='national'. Later maybe this could be optional.
494
508
  handleParsePhoneNumber(value, currentCountry);
495
509
  }
496
- // isInitialized = true;
497
510
  onLoad?.();
498
511
  });
499
512
 
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { default as TelInput } from './components/input/TelInput.svelte';
2
- export { parse, normalizeToE164, pickCountries } from './utils/index.js';
2
+ export { parse, normalizeToE164, pickCountries, getCountryByIso2 } from './utils/index.js';
3
3
  export { countries } from './assets/index.js';
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export { default as TelInput } from './components/input/TelInput.svelte';
2
- export { parse, normalizeToE164, pickCountries } from './utils/index.js';
2
+ export { parse, normalizeToE164, pickCountries, getCountryByIso2 } from './utils/index.js';
3
3
  export { countries } from './assets/index.js';
@@ -138,6 +138,13 @@ export interface Props extends HTMLInputAttributes {
138
138
  options?: TelInputOptions;
139
139
  /** Binding to the underlying `<input>` element */
140
140
  el?: HTMLInputElement | undefined;
141
+ /**
142
+ * Run runtime type-checking on incoming props, throwing a descriptive
143
+ * `TypeError` on a mismatch. Off by default so it adds nothing to production
144
+ * bundles; enable it (e.g. in development) to catch malformed props early.
145
+ * @default false
146
+ */
147
+ validateProps?: boolean;
141
148
  /**
142
149
  * Callback fired when the country changes (auto-detected or user-selected).
143
150
  * @param newCountry The new country code or null.
@@ -173,6 +180,14 @@ export interface Props extends HTMLInputAttributes {
173
180
  * @default 'international'
174
181
  */
175
182
  initialFormat?: 'international' | 'national';
183
+ /**
184
+ * Controls the format of the auto-generated placeholder (when `autoPlaceholder` is enabled).
185
+ * - `'international'` — placeholder includes the country dial code prefix (e.g. `+1 201 555 0123`).
186
+ * - `'national'` — placeholder shows the national part only (e.g. `201 555 0123`).
187
+ *
188
+ * When not provided, `initialFormat` is used as the fallback. If neither is provided, defaults to `'international'`.
189
+ */
190
+ placeholderFormat?: 'international' | 'national';
176
191
  }
177
192
 
178
193
  export type { CountryCode };
@@ -1,4 +1,10 @@
1
1
  import type { CountryCode, Country } from '../types/index.js';
2
+ /**
3
+ * Look up a country by its ISO 3166-1 alpha-2 code (e.g. `'US'`, `'HU'`).
4
+ *
5
+ * O(1) against the bundled country list. Returns `undefined` if not found.
6
+ */
7
+ export declare const getCountryByIso2: (iso2: CountryCode) => Country | undefined;
2
8
  export declare const getCountry: ({ field, value, countries }: {
3
9
  /**
4
10
  * Field to search by
@@ -1,8 +1,22 @@
1
1
  import { countries as normalizedCountries } from '../assets/index.js';
2
+ // O(1) lookup index for the default country list, keyed by ISO 3166-1 alpha-2.
3
+ // Built once at module load. iso2 lookups run on every keystroke, so they go
4
+ // through this Map instead of a linear scan over ~249 countries.
5
+ const iso2Index = new Map(normalizedCountries.map((c) => [c.iso2, c]));
6
+ /**
7
+ * Look up a country by its ISO 3166-1 alpha-2 code (e.g. `'US'`, `'HU'`).
8
+ *
9
+ * O(1) against the bundled country list. Returns `undefined` if not found.
10
+ */
11
+ export const getCountryByIso2 = (iso2) => iso2Index.get(iso2);
2
12
  export const getCountry = ({ field, value, countries = normalizedCountries }) => {
3
13
  if (['priority'].includes(field)) {
4
14
  throw new Error(`Field "${field}" is not supported`);
5
15
  }
16
+ // Fast path: iso2 lookups against the default list hit the prebuilt index.
17
+ if (field === 'iso2' && countries === normalizedCountries) {
18
+ return iso2Index.get(value);
19
+ }
6
20
  return countries.find((currentCountry) => {
7
21
  return value === currentCountry[field];
8
22
  });
@@ -1,7 +1,6 @@
1
1
  interface CalculateCursorPositionProps {
2
2
  beforeValue: string;
3
3
  beforeCursor: number;
4
- beforeSelection: number;
5
4
  afterInputValue?: string;
6
5
  afterInputCursor?: number;
7
6
  afterValue: string;
@@ -18,16 +17,4 @@ export declare const isDigit: (char?: string) => boolean;
18
17
  * Calculate the correct cursor position after input formatting
19
18
  */
20
19
  export declare const calculateCursorPosition: ({ beforeValue, beforeCursor, afterInputValue, afterInputCursor, afterValue, currentCursor, isDeletion, deletionDirection, hasSelection }: CalculateCursorPositionProps) => number;
21
- interface GetCursorPositionProps {
22
- phoneBeforeInput: string;
23
- phoneAfterInput: string;
24
- phoneAfterFormatted: string;
25
- cursorPositionAfterInput: number;
26
- leftOffset?: number;
27
- deletion?: 'forward' | 'backward' | undefined;
28
- isReplacement?: boolean;
29
- }
30
- export declare const isNumeric: (char?: string) => boolean;
31
- export declare const getCursorPosition: (props: GetCursorPositionProps) => number;
32
- export declare const setCursorPosition: (node: HTMLInputElement, cursorPosition: number) => void;
33
20
  export {};
@@ -104,31 +104,3 @@ export const calculateCursorPosition = ({ beforeValue, beforeCursor, afterInputV
104
104
  const newPos = findNthRelevantPosition(afterValue, digitsBefore, true);
105
105
  return Math.min(skipFormattingChars(afterValue, newPos), afterValue.length);
106
106
  };
107
- export const isNumeric = isDigit;
108
- export const getCursorPosition = (props) => {
109
- return calculateCursorPosition({
110
- beforeValue: props.phoneBeforeInput,
111
- beforeCursor: props.cursorPositionAfterInput,
112
- beforeSelection: 0,
113
- afterInputValue: props.phoneAfterInput,
114
- afterInputCursor: props.cursorPositionAfterInput,
115
- afterValue: props.phoneAfterFormatted,
116
- isDeletion: !!props.deletion,
117
- deletionDirection: props.deletion || null,
118
- hasSelection: false
119
- });
120
- };
121
- export const setCursorPosition = (node, cursorPosition) => {
122
- /**
123
- * HACK: should set cursor on the next tick to make sure that the phone value is updated
124
- * useTimeout with 0ms provides issues when two keys are pressed same time
125
- */
126
- Promise.resolve().then(() => {
127
- // workaround for safari autofocus bug:
128
- // Check if the input is focused before setting the cursor, otherwise safari sometimes autofocuses on setSelectionRange
129
- if (typeof window === 'undefined' || node !== document?.activeElement) {
130
- return;
131
- }
132
- node?.setSelectionRange(cursorPosition, cursorPosition);
133
- });
134
- };
@@ -1,4 +1,4 @@
1
- import { getCountry } from '../countryHelpers.js';
1
+ import { getCountryByIso2 } from '../countryHelpers.js';
2
2
  import { parsePhoneInput } from '../helpers.js';
3
3
  import { calculateCursorPosition } from '../cursorPosition.js';
4
4
  let inputState = null;
@@ -109,9 +109,7 @@ const onInput = (event, params, node) => {
109
109
  const userInput = node.value;
110
110
  const currentCursor = node.selectionStart ?? 0;
111
111
  const normalized = normalizeUserInput(userInput);
112
- const countryObj = params.country
113
- ? getCountry({ field: 'iso2', value: params.country })
114
- : undefined;
112
+ const countryObj = params.country ? getCountryByIso2(params.country) : undefined;
115
113
  const details = parsePhoneInput(normalized, countryObj);
116
114
  // Display formatting:
117
115
  // - When `spaces` is true, show formatted-as-you-type output (national or intl)
@@ -123,7 +121,6 @@ const onInput = (event, params, node) => {
123
121
  const newPosition = calculateCursorPosition({
124
122
  beforeValue: state.beforeValue,
125
123
  beforeCursor: state.beforeCursor,
126
- beforeSelection: state.beforeSelection,
127
124
  afterInputValue: userInput,
128
125
  afterInputCursor: currentCursor,
129
126
  afterValue: formattedInput,
@@ -1,23 +1,8 @@
1
1
  import type { Country, DetailedValue } from '../types/index.js';
2
2
  import type { CountryCode } from 'libphonenumber-js';
3
- export declare const generatePlaceholder: (country: CountryCode, { spaces }?: {
3
+ export declare const generatePlaceholder: (country: CountryCode, { spaces, format }?: {
4
4
  spaces: boolean;
5
- }) => string;
6
- export declare const isSelected: <T extends {
7
- id: string;
8
- }>(itemToSelect: T | string, selectedItem: (T | undefined | null) | string) => boolean;
9
- /**
10
- * These mappings map a character (key) to a specific digit that should
11
- * replace it for normalization purposes.
12
- * @param {string} character
13
- * @returns {string}
14
- */
15
- export declare const allowedCharacters: (character: string, { spaces, plusSign }?: {
16
- spaces?: boolean;
17
- plusSign?: boolean;
18
- }) => string | undefined;
19
- export declare const inputParser: (input: string, { allowSpaces }: {
20
- allowSpaces: boolean;
5
+ format?: "international" | "national";
21
6
  }) => string;
22
7
  export declare const parsePhoneInput: (input: string, country: Country | undefined) => DetailedValue;
23
8
  /**
@@ -1,13 +1,20 @@
1
- import { AsYouType, getExampleNumber, formatIncompletePhoneNumber, validatePhoneNumberLength } from 'libphonenumber-js/max';
1
+ import { AsYouType, getExampleNumber, formatIncompletePhoneNumber, validatePhoneNumberLength } from 'libphonenumber-js/max/es6';
2
2
  import { examplePhoneNumbers, countries } from '../assets/index.js';
3
- import { getCountry } from './countryHelpers.js';
4
- const whiteSpaceRegex = new RegExp('[\\t\\n\\v\\f\\r \\u00a0\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u200b\\u2028\\u2029\\u3000]', 'g');
5
- const plusSignRegex = new RegExp('\\+', 'g');
6
- export const generatePlaceholder = (country, { spaces } = {
7
- spaces: true
3
+ import { getCountryByIso2 } from './countryHelpers.js';
4
+ export const generatePlaceholder = (country, { spaces, format } = {
5
+ spaces: true,
6
+ format: 'international'
8
7
  }) => {
9
8
  const examplePhoneNumber = getExampleNumber(country, examplePhoneNumbers);
10
9
  if (examplePhoneNumber) {
10
+ if (format === 'national') {
11
+ const international = examplePhoneNumber.formatInternational().trim();
12
+ const prefix = `+${examplePhoneNumber.countryCallingCode} `;
13
+ const national = international.startsWith(prefix)
14
+ ? international.slice(prefix.length)
15
+ : international;
16
+ return spaces ? national : national.replace(/\s/g, '');
17
+ }
11
18
  return spaces ? examplePhoneNumber.formatInternational().trim() : examplePhoneNumber.number;
12
19
  }
13
20
  else {
@@ -15,98 +22,6 @@ export const generatePlaceholder = (country, { spaces } = {
15
22
  return '';
16
23
  }
17
24
  };
18
- export const isSelected = (itemToSelect, selectedItem) => {
19
- if (!selectedItem) {
20
- return false;
21
- }
22
- if (typeof selectedItem === 'object' && typeof itemToSelect === 'object') {
23
- return selectedItem.id === itemToSelect.id;
24
- }
25
- return itemToSelect === selectedItem;
26
- };
27
- /**
28
- * These mappings map a character (key) to a specific digit that should
29
- * replace it for normalization purposes.
30
- * @param {string} character
31
- * @returns {string}
32
- */
33
- export const allowedCharacters = (character, { spaces, plusSign } = {
34
- spaces: true,
35
- plusSign: true
36
- }) => {
37
- const DIGITS = {
38
- '0': '0',
39
- '1': '1',
40
- '2': '2',
41
- '3': '3',
42
- '4': '4',
43
- '5': '5',
44
- '6': '6',
45
- '7': '7',
46
- '8': '8',
47
- '9': '9',
48
- '\uFF10': '0', // Fullwidth digit 0
49
- '\uFF11': '1', // Fullwidth digit 1
50
- '\uFF12': '2', // Fullwidth digit 2
51
- '\uFF13': '3', // Fullwidth digit 3
52
- '\uFF14': '4', // Fullwidth digit 4
53
- '\uFF15': '5', // Fullwidth digit 5
54
- '\uFF16': '6', // Fullwidth digit 6
55
- '\uFF17': '7', // Fullwidth digit 7
56
- '\uFF18': '8', // Fullwidth digit 8
57
- '\uFF19': '9', // Fullwidth digit 9
58
- '\u0660': '0', // Arabic-indic digit 0
59
- '\u0661': '1', // Arabic-indic digit 1
60
- '\u0662': '2', // Arabic-indic digit 2
61
- '\u0663': '3', // Arabic-indic digit 3
62
- '\u0664': '4', // Arabic-indic digit 4
63
- '\u0665': '5', // Arabic-indic digit 5
64
- '\u0666': '6', // Arabic-indic digit 6
65
- '\u0667': '7', // Arabic-indic digit 7
66
- '\u0668': '8', // Arabic-indic digit 8
67
- '\u0669': '9', // Arabic-indic digit 9
68
- '\u06F0': '0', // Eastern-Arabic digit 0
69
- '\u06F1': '1', // Eastern-Arabic digit 1
70
- '\u06F2': '2', // Eastern-Arabic digit 2
71
- '\u06F3': '3', // Eastern-Arabic digit 3
72
- '\u06F4': '4', // Eastern-Arabic digit 4
73
- '\u06F5': '5', // Eastern-Arabic digit 5
74
- '\u06F6': '6', // Eastern-Arabic digit 6
75
- '\u06F7': '7', // Eastern-Arabic digit 7
76
- '\u06F8': '8', // Eastern-Arabic digit 8
77
- '\u06F9': '9' // Eastern-Arabic digit 9,
78
- };
79
- // Type Guard for index signature.
80
- const isValidKey = (key) => {
81
- return key in DIGITS;
82
- };
83
- // Allow spaces && plus sign character
84
- if ((spaces && whiteSpaceRegex.test(character)) ||
85
- (plusSign && plusSignRegex.test(character))) {
86
- return character;
87
- }
88
- if (isValidKey(character))
89
- return DIGITS[character];
90
- };
91
- export const inputParser = (input, { allowSpaces }) => {
92
- let value = '';
93
- for (let index = 0; index < input.length; index++) {
94
- if (input[index] === '+' && !value) {
95
- value += input[index];
96
- }
97
- else {
98
- const character = allowedCharacters(input[index], { spaces: allowSpaces });
99
- if (character !== undefined) {
100
- value += character;
101
- }
102
- }
103
- }
104
- // We force the + sign as a prefix for the number.
105
- if (value.length > 0 && !value.startsWith('+')) {
106
- value = '+' + value;
107
- }
108
- return value;
109
- };
110
25
  // ---------------------------------------------------------------------------
111
26
  // Phone-number normalizer
112
27
  // ---------------------------------------------------------------------------
@@ -256,7 +171,7 @@ export const parsePhoneInput = (input, country) => {
256
171
  * default country when the number has no leading `+`.
257
172
  */
258
173
  export const parse = (raw, country) => {
259
- const countryObj = country ? getCountry({ field: 'iso2', value: country }) : undefined;
174
+ const countryObj = country ? getCountryByIso2(country) : undefined;
260
175
  return parsePhoneInput(raw, countryObj);
261
176
  };
262
177
  /**
@@ -1 +1,2 @@
1
1
  export { generatePlaceholder, parse, normalizeToE164, pickCountries } from './helpers.js';
2
+ export { getCountryByIso2 } from './countryHelpers.js';
@@ -1 +1,2 @@
1
1
  export { generatePlaceholder, parse, normalizeToE164, pickCountries } from './helpers.js';
2
+ export { getCountryByIso2 } from './countryHelpers.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "svelte-tel-input",
3
3
  "description": "svelte-tel-input",
4
- "version": "4.1.1",
4
+ "version": "4.3.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/gyurielf/svelte-tel-input.git"
@@ -30,34 +30,34 @@
30
30
  "svelte": "^5.0.0"
31
31
  },
32
32
  "dependencies": {
33
- "libphonenumber-js": "1.12.41"
33
+ "libphonenumber-js": "1.13.6"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@sveltejs/adapter-auto": "7.0.1",
37
37
  "@sveltejs/kit": "^2.57.1",
38
- "@sveltejs/package": "^2.5.7",
38
+ "@sveltejs/package": "^2.5.8",
39
39
  "@sveltejs/vite-plugin-svelte": "^6.2.4",
40
- "@tailwindcss/vite": "^4.2.3",
40
+ "@tailwindcss/vite": "^4.3.1",
41
41
  "@testing-library/jest-dom": "6.9.1",
42
42
  "@testing-library/svelte": "^5.3.1",
43
43
  "@testing-library/user-event": "^14.6.1",
44
44
  "@types/micromatch": "^4.0.10",
45
45
  "@types/node": "^22.17.0",
46
46
  "dotenv": "^17.4.2",
47
- "jsdom": "^29.0.2",
47
+ "jsdom": "^29.1.1",
48
48
  "micromatch": "^4.0.8",
49
49
  "postcss": "^8.5.10",
50
- "publint": "^0.3.18",
50
+ "publint": "^0.3.21",
51
51
  "svelte": "^5.55.4",
52
- "svelte-check": "^4.4.6",
53
- "svelte2tsx": "^0.7.53",
54
- "tailwindcss": "^4.2.3",
52
+ "svelte-check": "^4.6.0",
53
+ "svelte2tsx": "^0.7.56",
54
+ "tailwindcss": "^4.3.1",
55
55
  "tslib": "^2.8.1",
56
56
  "typescript": "^5.9.3",
57
- "valibot": "^1.3.1",
57
+ "valibot": "^1.4.1",
58
58
  "vite": "^7.3.2",
59
- "vitest": "^4.1.4",
60
- "zod": "^4.3.6"
59
+ "vitest": "^4.1.5",
60
+ "zod": "^4.4.3"
61
61
  },
62
62
  "type": "module",
63
63
  "license": "MIT",