@marianmeres/stuic 3.156.0 → 3.158.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 (36) hide show
  1. package/dist/components/Checkout/CheckoutGuestForm.svelte +124 -5
  2. package/dist/components/Checkout/CheckoutGuestOrLoginForm.svelte +4 -0
  3. package/dist/components/Checkout/CheckoutGuestOrLoginForm.svelte.d.ts +1 -1
  4. package/dist/components/ContactUsForm/ContactUsForm.svelte +107 -10
  5. package/dist/components/ContactUsForm/README.md +16 -1
  6. package/dist/components/ContactUsForm/_internal/contact-form-types.d.ts +6 -1
  7. package/dist/components/LoginForm/LoginForm.svelte +40 -5
  8. package/dist/components/LoginForm/README.md +34 -19
  9. package/dist/components/LoginOrRegisterForm/LoginOrRegisterForm.svelte +73 -16
  10. package/dist/components/LoginOrRegisterForm/LoginOrRegisterForm.svelte.d.ts +12 -1
  11. package/dist/components/LoginOrRegisterForm/LoginOrRegisterFormModal.svelte +32 -1
  12. package/dist/components/LoginOrRegisterForm/LoginOrRegisterFormModal.svelte.d.ts +7 -1
  13. package/dist/components/LoginOrRegisterForm/README.md +45 -29
  14. package/dist/components/LoginOrRegisterForm/_internal/login-or-register-form-i18n-defaults.js +1 -0
  15. package/dist/components/LoginOrRegisterForm/index.css +18 -0
  16. package/dist/components/RegisterForm/README.md +177 -37
  17. package/dist/components/RegisterForm/RegisterForm.svelte +329 -76
  18. package/dist/components/RegisterForm/RegisterForm.svelte.d.ts +77 -3
  19. package/dist/components/RegisterForm/RegisterFormModal.svelte +78 -0
  20. package/dist/components/RegisterForm/RegisterFormModal.svelte.d.ts +31 -0
  21. package/dist/components/RegisterForm/_internal/register-form-i18n-defaults.js +1 -0
  22. package/dist/components/RegisterForm/_internal/register-form-types.d.ts +12 -2
  23. package/dist/components/RegisterForm/_internal/register-form-utils.d.ts +19 -2
  24. package/dist/components/RegisterForm/_internal/register-form-utils.js +34 -17
  25. package/dist/components/RegisterForm/index.css +33 -2
  26. package/dist/components/RegisterForm/index.d.ts +2 -1
  27. package/dist/components/RegisterForm/index.js +1 -1
  28. package/dist/utils/field-errors.svelte.d.ts +114 -0
  29. package/dist/utils/field-errors.svelte.js +131 -0
  30. package/dist/utils/index.d.ts +1 -0
  31. package/dist/utils/index.js +1 -0
  32. package/docs/domains/components.md +54 -38
  33. package/docs/domains/utils.md +57 -0
  34. package/package.json +10 -10
  35. package/dist/components/Input/node_modules/.vite/vitest/d2a04d71301a8915217dd5faf81d12cffd6cd958/_svelte_metadata.json +0 -1
  36. package/dist/components/Input/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/_svelte_metadata.json +0 -1
@@ -0,0 +1,131 @@
1
+ import { untrack } from "svelte";
2
+ /** Content — not array identity, not order — of a set of errors. */
3
+ function errorsKey(errs) {
4
+ return JSON.stringify(errs.map((e) => [e.field, e.message]).sort());
5
+ }
6
+ /**
7
+ * Give a form's consumer-supplied `errors` prop a lifecycle.
8
+ *
9
+ * `errors` is consumer-owned: a form can render it but cannot clear it. Taken
10
+ * literally that wedges the form permanently — the field's `customValidator`
11
+ * keeps reporting the server error whatever the user types, so
12
+ * `onSubmitValidityCheck` routes every later submit to `submit_invalid` and
13
+ * `onSubmit` never fires again, *including* the consumer's own handler that
14
+ * would have cleared the errors. (Forms without that action hit the same wall
15
+ * through their `externalErrors.length === 0` submit gate.)
16
+ *
17
+ * So: remember the value each field held when a set of errors was delivered.
18
+ * An error on a rendered field stays live while that field still holds that
19
+ * value and goes stale once the user edits it — dropped from the inline
20
+ * messages and from the submit gate, the same lifecycle internal validation
21
+ * errors already have. Typing the rejected value back in makes it live again,
22
+ * which is correct: that exact value is known-bad.
23
+ *
24
+ * Two details that look like over-engineering and are not:
25
+ *
26
+ * - Delivery is detected by the errors' **content**, never by array identity.
27
+ * Consumers routinely pass an inline literal or a freshly derived array whose
28
+ * identity changes on every parent re-render; re-snapshotting mid-typing would
29
+ * resurrect the error and restore the deadlock.
30
+ * - Because of that, an identical error redelivered after a resubmit would look
31
+ * like the previous, already-answered one. `markSubmitted()` disambiguates:
32
+ * the next delivery after it counts as fresh even when byte-identical.
33
+ *
34
+ * Must be called during component initialization (it registers an `$effect`).
35
+ *
36
+ * @example
37
+ * ```svelte
38
+ * <script>
39
+ * let { errors: externalErrors = [], formData = $bindable(...) } = $props();
40
+ *
41
+ * const external = createExternalFieldErrors({
42
+ * errors: () => externalErrors,
43
+ * isRendered: (f) => f === "email" || f === "password",
44
+ * valueOf: (f) => (f === "email" ? formData.email : formData.password) ?? "",
45
+ * });
46
+ *
47
+ * function handleSubmitValid() {
48
+ * // ...
49
+ * if (!validationErrors.length && !external.live.length) {
50
+ * external.markSubmitted();
51
+ * onSubmit(formData);
52
+ * }
53
+ * }
54
+ * </script>
55
+ * ```
56
+ */
57
+ export function createExternalFieldErrors(options) {
58
+ // Reassigned wholesale, never mutated — that is what makes it reactive, so a
59
+ // plain Map is correct here (a SvelteMap would only add overhead).
60
+ let snapshot = $state.raw(new Map());
61
+ // Deliberately NOT `$state`: these must not re-trigger the effect below.
62
+ let submittedSinceSnapshot = false;
63
+ let lastKey = null;
64
+ $effect(() => {
65
+ const errs = options.errors();
66
+ const key = errorsKey(errs);
67
+ untrack(() => {
68
+ if (key === lastKey && !submittedSinceSnapshot)
69
+ return;
70
+ lastKey = key;
71
+ submittedSinceSnapshot = false;
72
+ const next = new Map();
73
+ for (const e of errs) {
74
+ if (options.isRendered(e.field))
75
+ next.set(e.field, options.valueOf(e.field));
76
+ }
77
+ snapshot = next;
78
+ });
79
+ });
80
+ const live = $derived(options.errors().filter((e) => {
81
+ if (!options.isRendered(e.field))
82
+ return true;
83
+ const snapped = snapshot.get(e.field);
84
+ // no snapshot yet (first paint, before the effect above runs) => live
85
+ return snapped === undefined || snapped === options.valueOf(e.field);
86
+ }));
87
+ return {
88
+ get live() {
89
+ return live;
90
+ },
91
+ markSubmitted() {
92
+ submittedSinceSnapshot = true;
93
+ },
94
+ };
95
+ }
96
+ /**
97
+ * Render a field's error message as soon as it exists, instead of waiting for
98
+ * the user's next interaction.
99
+ *
100
+ * Inline messages come from each field's own validation run, and the `validate`
101
+ * action fires on `change` / first blur. An error that appears *after* the
102
+ * validators last ran therefore paints nothing:
103
+ *
104
+ * - a form's own validator result is computed on `submit_valid`, i.e. after
105
+ * `onSubmitValidityCheck` has already re-run every field's validator, so a
106
+ * rule with no DOM equivalent (a password mismatch, a custom validator, an
107
+ * email that satisfies `type="email"` but not a stricter regex) produced a
108
+ * completely silent first click — the CTA appeared to do nothing;
109
+ * - a server `errors` delivery lands once the submit is over, so it stayed
110
+ * invisible until the user clicked again.
111
+ *
112
+ * Only fields gaining an error are re-validated; clearing is left to the field's
113
+ * own next change/blur, so fixing one field doesn't wipe the messages still
114
+ * standing on its siblings.
115
+ *
116
+ * Must be called during component initialization (it registers an `$effect`).
117
+ *
118
+ * @param errors - all currently applicable errors (internal + live external)
119
+ * @param fieldByName - resolves a field name to its rendered component, if any
120
+ */
121
+ export function repaintFieldErrors(errors, fieldByName) {
122
+ $effect(() => {
123
+ const named = errors().map((e) => e.field);
124
+ if (!named.length)
125
+ return;
126
+ untrack(() => {
127
+ for (const name of named)
128
+ fieldByName(name)?.validate?.();
129
+ });
130
+ });
131
+ }
@@ -8,6 +8,7 @@ export * from "./device-pointer.svelte.js";
8
8
  export * from "./escape-regex.js";
9
9
  export * from "./event-emitter.js";
10
10
  export * from "./event-modifiers.js";
11
+ export * from "./field-errors.svelte.js";
11
12
  export * from "./file-from-bloburl.js";
12
13
  export * from "./force-download.js";
13
14
  export * from "./get-file-type-label.js";
@@ -8,6 +8,7 @@ export * from "./device-pointer.svelte.js";
8
8
  export * from "./escape-regex.js";
9
9
  export * from "./event-emitter.js";
10
10
  export * from "./event-modifiers.js";
11
+ export * from "./field-errors.svelte.js";
11
12
  export * from "./file-from-bloburl.js";
12
13
  export * from "./force-download.js";
13
14
  export * from "./get-file-type-label.js";
@@ -188,6 +188,8 @@ expose:
188
188
  | `validate()` | `boolean` | Run every inner field's validator. `true` if all valid. |
189
189
  | `scrollToFirstError(opts?)` | `boolean` | Scroll the first invalid field into view + focus it. Call after `validate()`. |
190
190
 
191
+ `focusField(name)` (`boolean`) is additionally available on `RegisterForm`, `RegisterFormModal`, `LoginOrRegisterForm` and `LoginOrRegisterFormModal` — the composites delegate to the active inner form, so it returns `false` in login / verify mode.
192
+
191
193
  ```svelte
192
194
  <script>
193
195
  let loginForm = $state<LoginForm>();
@@ -298,6 +300,8 @@ Prefix: `--stuic-login-form-*`
298
300
 
299
301
  Standalone registration form. Mirrors `LoginForm` conventions: `formData`, `onSubmit`, validation, errors, i18n, notifications, social-logins. Adds declarative `extraFields` (top/bottom positioning, custom validators) and an `extraFieldsSlot` escape hatch (e.g., terms checkbox).
300
302
 
303
+ Also covers **identity-first signup** (identity established by an OAuth provider / invite / magic link before the account exists): `showEmail` / `showPassword` unmount the credential fields, `credentialsSlot` replaces them, `socialPosition="top"` moves the provider buttons above the credentials.
304
+
301
305
  ### Exports
302
306
 
303
307
  | Export | Kind | Description |
@@ -307,33 +311,44 @@ Standalone registration form. Mirrors `LoginForm` conventions: `formData`, `onSu
307
311
  | `RegisterFormData` | type | `{ email, password, passwordConfirm, extra }` |
308
312
  | `RegisterFormValidationError` | type | `{ field, message }` |
309
313
  | `RegisterFieldConfig` | type | Declarative extra-field descriptor |
314
+ | `ValidateRegisterFormOptions` | type | Options for `validateRegisterForm` |
310
315
  | `createEmptyRegisterFormData` | function | Factory for an empty `RegisterFormData` |
316
+ | `validateRegisterForm` | function | `(data, t?, extraFields?, opts?) => Error[]` |
311
317
 
312
318
  ### Key Props
313
319
 
314
- | Prop | Type | Default | Description |
315
- | --------------------- | ------------------------------- | -------- | --------------------------------------- |
316
- | `formData` | `RegisterFormData` | empty | Bindable form data |
317
- | `onSubmit` | `(data) => void` | required | Submit callback |
318
- | `isSubmitting` | `boolean` | `false` | Disables CTA |
319
- | `errors` | `RegisterFormValidationError[]` | `[]` | Field-specific server errors |
320
- | `error` | `string` | — | General error (alert above form) |
321
- | `showPasswordConfirm` | `boolean` | `true` | Render password-confirm field |
322
- | `passwordMinLength` | `number` | `8` | Min password length (input + validator) |
323
- | `extraFields` | `RegisterFieldConfig[]` | `[]` | Declarative extra fields (top/bottom) |
324
- | `extraFieldsSlot` | `Snippet` | — | Escape-hatch for non-FieldInput extras |
325
- | `submitButton` | `Snippet` | — | Custom CTA section |
326
- | `socialLogins` | `Snippet` | — | OAuth buttons below form |
327
- | `footer` | `Snippet` | — | Content below form |
328
- | `notifications` | `NotificationsStack` | — | Route errors to notifications |
329
- | `compact` | `boolean` | `false` | Compact layout |
330
- | `t` | `TranslateFn` | built-in | Translation function |
320
+ | Prop | Type | Default | Description |
321
+ | ---------------------------------------------------------------------- | ------------------------------- | ---------- | ----------------------------------------------------------------------- |
322
+ | `formData` | `RegisterFormData` | empty | Bindable form data |
323
+ | `onSubmit` | `(data) => void` | required | Submit callback |
324
+ | `isSubmitting` | `boolean` | `false` | Disables CTA |
325
+ | `submitDisabled` | `boolean` | `false` | Consumer-owned block: disables CTA + blocks submit |
326
+ | `errors` | `RegisterFormValidationError[]` | `[]` | Server field errors — self-clearing (see below) |
327
+ | `error` | `string` | — | General error (alert above form) |
328
+ | `showEmail` | `boolean` | `true` | Render (mount) the email field |
329
+ | `showPassword` | `boolean` | `true` | Render (mount) the password + confirm fields |
330
+ | `showPasswordConfirm` | `boolean` | `true` | Render password-confirm field |
331
+ | `passwordMinLength` | `number` | `8` | Min password length (input + validator) |
332
+ | `credentialsSlot` | `Snippet` | — | Content at the credentials position |
333
+ | `emailFieldProps` / `passwordFieldProps` / `passwordConfirmFieldProps` | `Partial<FieldInputProps>` | — | Passthrough props per core field (`validate` composed, `value` ignored) |
334
+ | `extraFields` | `RegisterFieldConfig[]` | `[]` | Declarative extra fields (top/bottom) |
335
+ | `extraFieldsSlot` | `Snippet` | — | Escape-hatch for non-FieldInput extras |
336
+ | `submitButton` | `Snippet` | — | Custom CTA section |
337
+ | `socialLogins` | `Snippet` | — | OAuth buttons |
338
+ | `socialPosition` | `"top" \| "bottom"` | `"bottom"` | Social block above the credentials or after the CTA |
339
+ | `footer` | `Snippet` | — | Content below form |
340
+ | `notifications` | `NotificationsStack` | — | Route errors to notifications |
341
+ | `t` | `TranslateFn` | built-in | Translation function |
342
+
343
+ **Imperative** (`bind:this`): `validate()`, `scrollToFirstError(opts?)`, `focusField(name)` — also forwarded by `RegisterFormModal`.
344
+
345
+ **`errors` lifecycle** (shared by `LoginForm`, `RegisterForm`, `ContactUsForm` and `CheckoutGuestForm` — see `createExternalFieldErrors` in [utils](./utils.md)): an entry whose `field` the form renders is tied to that field's value at delivery and self-clears (message + submit block) once the user edits it. An entry for anything else — a field you render yourself from a slot, or one switched off by a `show*` / `fields` prop — keeps blocking until the consumer removes it, since no edit there can answer it. Messages are painted as soon as they exist, so a failed submit never leaves a CTA that silently does nothing.
331
346
 
332
347
  ### CSS Tokens
333
348
 
334
349
  Prefix: `--stuic-register-form-*`
335
350
 
336
- `gap`, `gap-row`, `social-margin-top`, `social-gap`, `social-divider-color`, `social-divider-line-color`, `social-divider-font-size`, `social-divider-margin-bottom`
351
+ `gap`, `gap-row`, `social-margin-top`, `social-margin-bottom`, `social-gap`, `social-divider-color`, `social-divider-line-color`, `social-divider-font-size`, `social-divider-margin-bottom`, `social-divider-margin-top`
337
352
 
338
353
  ---
339
354
 
@@ -353,25 +368,26 @@ Composite form that toggles between `LoginForm`, `RegisterForm`, and (since 3.71
353
368
 
354
369
  ### Key Props
355
370
 
356
- | Prop | Type | Default | Description |
357
- | --------------- | ------------------------------- | --------- | -------------------------------------------------------------------------- |
358
- | `mode` | `LoginOrRegisterFormMode` | `"login"` | Bindable active mode |
359
- | `loginData` | `LoginFormData` | empty | Bindable login form data |
360
- | `registerData` | `RegisterFormData` | empty | Bindable register form data |
361
- | `verifyEmail` | `string` | `""` | Bindable email used by EmailVerifyForm (auto-seeded on transitions) |
362
- | `onLogin` | `(data) => void` | required | Login submit callback |
363
- | `onRegister` | `(data) => void` | required | Register submit callback |
364
- | `onVerify` | `(code: string) => void` | — | Verify submit callback (required only when using verify mode) |
365
- | `onResendCode` | `() => Promise<void> \| void` | — | Resend handler — when set, EmailVerifyForm renders the resend control |
366
- | `loginProps` | `Partial<LoginFormProps>` | — | Pass-through to inner LoginForm |
367
- | `registerProps` | `Partial<RegisterFormProps>` | — | Pass-through to inner RegisterForm |
368
- | `verifyProps` | `Partial<EmailVerifyFormProps>` | — | Pass-through to inner EmailVerifyForm (e.g., `error`, `attemptsRemaining`) |
369
- | `modeSwitcher` | `Snippet` | — | Override the built-in ButtonGroupRadio |
370
- | `socialLogins` | `Snippet` | — | Shared OAuth buttons (hidden in verify mode) |
371
- | `footer` | `Snippet<[{ mode, setMode }]>` | — | Mode-aware footer |
372
- | `isSubmitting` | `boolean` | `false` | Forwarded to all three forms |
373
- | `notifications` | `NotificationsStack` | — | Routes errors to notifications |
374
- | `t` | `TranslateFn` | built-in | Translation function |
371
+ | Prop | Type | Default | Description |
372
+ | ---------------- | ------------------------------- | ---------- | -------------------------------------------------------------------------- |
373
+ | `mode` | `LoginOrRegisterFormMode` | `"login"` | Bindable active mode |
374
+ | `loginData` | `LoginFormData` | empty | Bindable login form data |
375
+ | `registerData` | `RegisterFormData` | empty | Bindable register form data |
376
+ | `verifyEmail` | `string` | `""` | Bindable email used by EmailVerifyForm (auto-seeded on transitions) |
377
+ | `onLogin` | `(data) => void` | required | Login submit callback |
378
+ | `onRegister` | `(data) => void` | required | Register submit callback |
379
+ | `onVerify` | `(code: string) => void` | — | Verify submit callback (required only when using verify mode) |
380
+ | `onResendCode` | `() => Promise<void> \| void` | — | Resend handler — when set, EmailVerifyForm renders the resend control |
381
+ | `loginProps` | `Partial<LoginFormProps>` | — | Pass-through to inner LoginForm |
382
+ | `registerProps` | `Partial<RegisterFormProps>` | — | Pass-through to inner RegisterForm |
383
+ | `verifyProps` | `Partial<EmailVerifyFormProps>` | — | Pass-through to inner EmailVerifyForm (e.g., `error`, `attemptsRemaining`) |
384
+ | `modeSwitcher` | `Snippet` | — | Override the built-in ButtonGroupRadio |
385
+ | `socialLogins` | `Snippet` | — | Shared OAuth buttons (hidden in verify mode) |
386
+ | `socialPosition` | `"top" \| "bottom"` | `"bottom"` | Shared social block above the active form or below it |
387
+ | `footer` | `Snippet<[{ mode, setMode }]>` | — | Mode-aware footer |
388
+ | `isSubmitting` | `boolean` | `false` | Forwarded to all three forms |
389
+ | `notifications` | `NotificationsStack` | — | Routes errors to notifications |
390
+ | `t` | `TranslateFn` | built-in | Translation function |
375
391
 
376
392
  ### Modal additions (`LoginOrRegisterFormModal`)
377
393
 
@@ -388,7 +404,7 @@ Inherits all `LoginOrRegisterForm` props, plus:
388
404
 
389
405
  Prefix: `--stuic-login-or-register-form-*`
390
406
 
391
- `gap`, `switcher-margin-bottom`, `social-margin-top`, `social-gap`, `social-divider-*`
407
+ `gap`, `switcher-margin-bottom`, `social-margin-top`, `social-margin-bottom`, `social-gap`, `social-divider-*`
392
408
 
393
409
  ### i18n
394
410
 
@@ -210,6 +210,63 @@ without filtering first.
210
210
 
211
211
  ---
212
212
 
213
+ ## Server-Error Lifecycle (.svelte.ts)
214
+
215
+ Used by every STUIC form that takes an `errors` prop (`LoginForm`,
216
+ `RegisterForm`, `ContactUsForm`, `CheckoutGuestForm`) — and available for your
217
+ own forms.
218
+
219
+ | Util | Purpose |
220
+ | --------------------------- | ---------------------------------------------------------------------------------------- |
221
+ | `createExternalFieldErrors` | Gives a consumer-owned `errors` prop a lifecycle: entries on rendered fields self-clear. |
222
+ | `repaintFieldErrors` | Paints a field's message as soon as the error exists, not on the next interaction. |
223
+ | `FieldError` (interface) | `{ field, message }` — every form's `*ValidationError` satisfies it. |
224
+
225
+ `errors` is consumer-owned: a form can render it but cannot clear it. Taken
226
+ literally that wedges the form — the field's `customValidator` keeps reporting
227
+ the server error whatever the user types, so every later submit is routed to
228
+ `submit_invalid` and the consumer's own handler (the one that would have cleared
229
+ the errors) never runs. `createExternalFieldErrors` remembers the value each
230
+ field held when a set of errors arrived and drops an entry once the user edits
231
+ that field; entries for fields the form does not render keep applying, since no
232
+ edit there can answer them.
233
+
234
+ `repaintFieldErrors` covers the other half: inline messages come from each
235
+ field's own validation run (on `change` / first blur), so a form-level validator
236
+ result — computed _after_ the submit-time validity walk already re-ran every
237
+ field — used to paint nothing at all on the first click.
238
+
239
+ ```svelte
240
+ <script lang="ts">
241
+ import {
242
+ createExternalFieldErrors,
243
+ repaintFieldErrors,
244
+ } from "@marianmeres/stuic/utils";
245
+
246
+ let { errors: externalErrors = [], formData = $bindable(initial) } = $props();
247
+
248
+ const external = createExternalFieldErrors({
249
+ errors: () => externalErrors,
250
+ isRendered: (f) => f === "email" || f === "password",
251
+ valueOf: (f) => formData[f] ?? "",
252
+ });
253
+
254
+ let allErrors = $derived([...internalErrors, ...external.live]);
255
+ repaintFieldErrors(() => allErrors, fieldByName);
256
+
257
+ function submit() {
258
+ if (!internalErrors.length && !external.live.length) {
259
+ external.markSubmitted(); // arms identical-repeat detection
260
+ onSubmit(formData);
261
+ }
262
+ }
263
+ </script>
264
+ ```
265
+
266
+ Both register `$effect`s, so call them during component initialization.
267
+
268
+ ---
269
+
213
270
  ## Key Files
214
271
 
215
272
  | File | Purpose |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/stuic",
3
- "version": "3.156.0",
3
+ "version": "3.158.0",
4
4
  "packageManager": "pnpm@11.5.0",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
@@ -128,12 +128,12 @@
128
128
  }
129
129
  },
130
130
  "devDependencies": {
131
- "@codemirror/commands": "^6.10.4",
131
+ "@codemirror/commands": "^6.11.0",
132
132
  "@codemirror/lang-markdown": "^6.5.2",
133
133
  "@codemirror/language": "^6.12.4",
134
134
  "@codemirror/language-data": "^6.5.2",
135
135
  "@codemirror/state": "^6.7.1",
136
- "@codemirror/view": "^6.43.8",
136
+ "@codemirror/view": "^6.43.9",
137
137
  "@eslint/js": "^9.39.5",
138
138
  "@marianmeres/random-human-readable": "^1.10.2",
139
139
  "@milkdown/core": "^7.22.1",
@@ -146,7 +146,7 @@
146
146
  "@milkdown/transformer": "^7.22.1",
147
147
  "@milkdown/utils": "^7.22.1",
148
148
  "@sveltejs/adapter-auto": "^4.0.0",
149
- "@sveltejs/kit": "^2.70.2",
149
+ "@sveltejs/kit": "^2.70.3",
150
150
  "@sveltejs/package": "^2.5.8",
151
151
  "@sveltejs/vite-plugin-svelte": "^6.2.4",
152
152
  "@tailwindcss/cli": "^4.3.3",
@@ -154,22 +154,22 @@
154
154
  "@tailwindcss/typography": "^0.5.20",
155
155
  "@tailwindcss/vite": "^4.3.3",
156
156
  "@types/node": "^25.9.5",
157
- "@vitest/browser-playwright": "^4.1.10",
157
+ "@vitest/browser-playwright": "^4.1.11",
158
158
  "dotenv": "^16.6.1",
159
159
  "eslint": "^9.39.5",
160
160
  "globals": "^16.5.0",
161
161
  "playwright": "^1.62.1",
162
162
  "prettier": "^3.9.6",
163
163
  "prettier-plugin-svelte": "^3.5.2",
164
- "publint": "^0.3.23",
165
- "svelte": "^5.56.9",
164
+ "publint": "^0.3.24",
165
+ "svelte": "^5.56.10",
166
166
  "svelte-check": "^4.7.6",
167
167
  "tailwindcss": "^4.3.3",
168
168
  "tsx": "^4.23.12",
169
169
  "typescript": "^5.9.3",
170
170
  "typescript-eslint": "^8.67.0",
171
171
  "vite": "^7.3.6",
172
- "vitest": "^4.1.10",
172
+ "vitest": "^4.1.11",
173
173
  "vitest-browser-svelte": "^2.2.1"
174
174
  },
175
175
  "dependencies": {
@@ -177,13 +177,13 @@
177
177
  "@marianmeres/countries": "^1.1.0",
178
178
  "@marianmeres/cron-parser": "^1.0.1",
179
179
  "@marianmeres/design-tokens": "^1.17.0",
180
- "@marianmeres/icons-fns": "^5.0.0",
180
+ "@marianmeres/icons-fns": "^6.0.0",
181
181
  "@marianmeres/item-collection": "^1.4.2",
182
182
  "@marianmeres/paging-store": "^2.1.1",
183
183
  "@marianmeres/parse-boolean": "^2.1.0",
184
184
  "@marianmeres/ticker": "^1.17.1",
185
185
  "@marianmeres/tree": "^2.3.0",
186
- "libphonenumber-js": "^1.13.10",
186
+ "libphonenumber-js": "^1.13.11",
187
187
  "runed": "^0.23.4",
188
188
  "tailwind-merge": "^3.6.0"
189
189
  }
@@ -1 +0,0 @@
1
- {"compilerOptions":{"css":"external","dev":true,"hmr":false},"configFile":false,"extensions":[".svelte"],"preprocess":{"script":"({ content, filename }) => {\n\t\tif (!filename) return;\n\n\t\tconst basename = path.basename(filename);\n\t\tif (basename.startsWith('+page.') || basename.startsWith('+layout.')) {\n\t\t\tconst match = content.match(options_regex);\n\t\t\tif (match && match.index !== undefined && !should_ignore(content, match.index)) {\n\t\t\t\tconst fixed = basename.replace('.svelte', '(.server).js/ts');\n\n\t\t\t\tconst message =\n\t\t\t\t\t`\\n${colors.bold().red(path.relative('.', filename))}\\n` +\n\t\t\t\t\t`\\`${match[1]}\\` will be ignored — move it to ${fixed} instead. See https://svelte.dev/docs/kit/page-options for more information.`;\n\n\t\t\t\tif (!warned.has(message)) {\n\t\t\t\t\tconsole.log(message);\n\t\t\t\t\twarned.add(message);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}","markup":"({ content, filename }) => {\n\t\tif (!filename) return;\n\n\t\tconst basename = path.basename(filename);\n\n\t\tif (basename.startsWith('+layout.') && !has_children(content, isSvelte5Plus())) {\n\t\t\tconst message =\n\t\t\t\t`\\n${colors.bold().red(path.relative('.', filename))}\\n` +\n\t\t\t\t`\\`<slot />\\`${isSvelte5Plus() ? ' or `{@render ...}` tag' : ''}` +\n\t\t\t\t' missing — inner content will not be rendered';\n\n\t\t\tif (!warned.has(message)) {\n\t\t\t\tconsole.log(message);\n\t\t\t\twarned.add(message);\n\t\t\t}\n\t\t}\n\t}"}}
@@ -1 +0,0 @@
1
- {"compilerOptions":{"css":"external","dev":true,"hmr":false},"configFile":false,"extensions":[".svelte"],"preprocess":{"script":"({ content, filename }) => {\n\t\tif (!filename) return;\n\n\t\tconst basename = path.basename(filename);\n\t\tif (basename.startsWith('+page.') || basename.startsWith('+layout.')) {\n\t\t\tconst match = content.match(options_regex);\n\t\t\tif (match && match.index !== undefined && !should_ignore(content, match.index)) {\n\t\t\t\tconst fixed = basename.replace('.svelte', '(.server).js/ts');\n\n\t\t\t\tconst message =\n\t\t\t\t\t`\\n${colors.bold().red(path.relative('.', filename))}\\n` +\n\t\t\t\t\t`\\`${match[1]}\\` will be ignored — move it to ${fixed} instead. See https://svelte.dev/docs/kit/page-options for more information.`;\n\n\t\t\t\tif (!warned.has(message)) {\n\t\t\t\t\tconsole.log(message);\n\t\t\t\t\twarned.add(message);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}","markup":"({ content, filename }) => {\n\t\tif (!filename) return;\n\n\t\tconst basename = path.basename(filename);\n\n\t\tif (basename.startsWith('+layout.') && !has_children(content, isSvelte5Plus())) {\n\t\t\tconst message =\n\t\t\t\t`\\n${colors.bold().red(path.relative('.', filename))}\\n` +\n\t\t\t\t`\\`<slot />\\`${isSvelte5Plus() ? ' or `{@render ...}` tag' : ''}` +\n\t\t\t\t' missing — inner content will not be rendered';\n\n\t\t\tif (!warned.has(message)) {\n\t\t\t\tconsole.log(message);\n\t\t\t\twarned.add(message);\n\t\t\t}\n\t\t}\n\t}"}}