From edf45be781c327566aa7a1c15c35ab5c679bb8c2 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 1 Oct 2025 17:51:03 +0200 Subject: [PATCH 001/145] wip --- packages/core/src/files.ts | 12 +- packages/core/src/index.ts | 2 + packages/core/src/precognition.ts | 115 ++++++++++++++++++ packages/vue3/src/form.ts | 49 +++++++- .../Pages/FormComponent/Precognition.vue | 34 ++++++ .../app/Http/Requests/StoreUserRequest.php | 21 ++++ playgrounds/vue3/package.json | 8 +- playgrounds/vue3/resources/js/Pages/Home.vue | 25 ++++ playgrounds/vue3/routes/web.php | 6 + tests/app/server.js | 46 +++++++ 10 files changed, 311 insertions(+), 7 deletions(-) create mode 100644 packages/core/src/precognition.ts create mode 100644 packages/vue3/test-app/Pages/FormComponent/Precognition.vue create mode 100644 playgrounds/vue3/app/Http/Requests/StoreUserRequest.php diff --git a/packages/core/src/files.ts b/packages/core/src/files.ts index 4d927f7b2..2817b3c7a 100644 --- a/packages/core/src/files.ts +++ b/packages/core/src/files.ts @@ -1,10 +1,16 @@ import { FormDataConvertible, RequestPayload } from './types' +export function isFile(value: unknown): boolean { + return ( + (typeof File !== 'undefined' && value instanceof File) || + value instanceof Blob || + (typeof FileList !== 'undefined' && value instanceof FileList && value.length > 0) + ) +} + export function hasFiles(data: RequestPayload | FormDataConvertible): boolean { return ( - data instanceof File || - data instanceof Blob || - (data instanceof FileList && data.length > 0) || + isFile(data) || (data instanceof FormData && Array.from(data.values()).some((value) => hasFiles(value))) || (typeof data === 'object' && data !== null && Object.values(data).some((value) => hasFiles(value))) ) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 08ecfbaae..342bbb1a2 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,11 +1,13 @@ import { Router } from './router' export { getScrollableParent } from './domUtils' +export { hasFiles } from './files' export { objectToFormData } from './formData' export { formDataToObject } from './formObject' export { default as createHeadManager } from './head' export { default as useInfiniteScroll } from './infiniteScroll' export { shouldIntercept, shouldNavigate } from './navigationEvents' +export { default as usePrecognition } from './precognition' export { hide as hideProgress, progress, reveal as revealProgress, default as setupProgress } from './progress' export { resetFormFields } from './resetFormFields' export * from './types' diff --git a/packages/core/src/precognition.ts b/packages/core/src/precognition.ts new file mode 100644 index 000000000..044ee35cf --- /dev/null +++ b/packages/core/src/precognition.ts @@ -0,0 +1,115 @@ +import { default as axios } from 'axios' +import { get, isEqual } from 'lodash-es' +import debounce from './debounce' +import { hasFiles, isFile } from './files' +import { ErrorBag, Errors, Method } from './types' + +type ValidatableData = Record + +export function forgetFiles(data: ValidatableData): ValidatableData { + const newData = { ...data } + + Object.keys(newData).forEach((name) => { + const value = newData[name] + + if (value === null) { + return + } + + if (isFile(value)) { + delete newData[name] + + return + } + + if (Array.isArray(value)) { + newData[name] = Object.values(forgetFiles({ ...value })) + + return + } + + if (typeof value === 'object') { + newData[name] = forgetFiles(newData[name] as ValidatableData) + + return + } + }) + + return newData +} + +interface UsePrecognitionOptions { + onStart: () => void + onFinish: () => void + onPrecognitionSuccess: () => void + onValidationError: (errors: Errors & ErrorBag) => void +} + +interface PrecognitionValidator {} + +export default function usePrecognition(precognitionOptions: UsePrecognitionOptions): PrecognitionValidator { + let oldData: ValidatableData = {} + let validatingData: ValidatableData = {} + + let validateFiles: boolean = false + let debounceTimeoutDuration = 1500 + + const setDebounceTimeout = (value: number) => { + debounceTimeoutDuration = value + validate = createValidateFunction() + } + + const createValidateFunction = () => + debounce((options: { action: string; method: Method; data: ValidatableData; only: string[] }) => { + const data = validateFiles ? options.data : forgetFiles(options.data) + + if (options.only && isEqual(get(data, options.only), get(oldData, options.only))) { + return + } + + oldData = validatingData = { ...data } + + precognitionOptions.onStart() + + axios({ + method: options.method, + url: options.action, + data: validatingData, + headers: { + 'Content-Type': hasFiles(data) ? 'multipart/form-data' : 'application/json', + Precognition: true, + ...(options.only.length ? { 'Precognition-Validate-Only': options.only.join(',') } : {}), + }, + }) + .then((response) => { + if (response.status === 204 && response.headers['precognition-success'] === 'true') { + return precognitionOptions.onPrecognitionSuccess() + } + }) + .catch((error) => { + if (error.response && error.response.status === 422) { + return precognitionOptions.onValidationError(error.response.data.errors || {}) + } else { + throw error + } + }) + .finally(() => { + precognitionOptions.onFinish() + }) + }, debounceTimeoutDuration) + + let validate = createValidateFunction() + + return { + setOldData(data: ValidatableData) { + oldData = { ...data } + }, + + validateFiles(value: boolean) { + validateFiles = value + }, + + validate, + setTimeout: setDebounceTimeout, + } +} diff --git a/packages/vue3/src/form.ts b/packages/vue3/src/form.ts index 630cbe6ff..f7be16b6d 100644 --- a/packages/vue3/src/form.ts +++ b/packages/vue3/src/form.ts @@ -8,6 +8,7 @@ import { mergeDataIntoQueryString, Method, resetFormFields, + usePrecognition, VisitOptions, } from '@inertiajs/core' import { isEqual } from 'lodash-es' @@ -146,14 +147,16 @@ const Form: InertiaForm = defineComponent({ // expects an object, and submitting a FormData instance directly causes problems with nested objects. const getData = (): Record => formDataToObject(getFormData()) - const submit = () => { - const [action, data] = mergeDataIntoQueryString( + const getActionAndData = (): [string, Record] => { + return mergeDataIntoQueryString( method.value, isUrlMethodPair(props.action) ? props.action.url : props.action, getData(), props.queryStringArrayFormat, ) + } + const submit = () => { const maybeReset = (resetOption: boolean | string[]) => { if (!resetOption) { return @@ -193,12 +196,15 @@ const Form: InertiaForm = defineComponent({ ...props.options, } + const [action, data] = getActionAndData() + // We need transform because we can't override the default data with different keys (by design) form.transform(() => props.transform(data)).submit(method.value, action, submitOptions) } const reset = (...fields: string[]) => { resetFormFields(formElement.value, defaultData.value, fields) + validator.setOldData(getData()) // TODO: should it really do this? } const resetAndClearErrors = (...fields: string[]) => { @@ -211,6 +217,37 @@ const Form: InertiaForm = defineComponent({ isDirty.value = false } + const validating = ref(false) + + const validator = usePrecognition({ + onStart: () => { + validating.value = true + }, + onFinish: () => { + validating.value = false + }, + onPrecognitionSuccess: () => form.clearErrors(), + onValidationError: (errors) => form.setError(errors), + }) + + onMounted(() => { + const [_action, data] = getActionAndData() + + // Set the initial data on the validator + validator.setOldData(data) + }) + + const validate = (field?: string | string[]) => { + const [action, data] = getActionAndData() + + validator.validate({ + action, + method: method.value, + data, + only: Array.isArray(field) ? field : [field], + }) + } + const exposed = { get errors() { return form.errors @@ -230,6 +267,9 @@ const Form: InertiaForm = defineComponent({ get recentlySuccessful() { return form.recentlySuccessful }, + get validating() { + return validating.value + }, clearErrors: (...fields: string[]) => form.clearErrors(...fields), resetAndClearErrors, setError: (fieldOrFields: string | Record, maybeValue?: string) => @@ -240,6 +280,11 @@ const Form: InertiaForm = defineComponent({ reset, submit, defaults, + + // Precognition + valid: (field: string) => form.errors[field] === undefined, + invalid: (field: string) => form.errors[field] !== undefined, + validate, } expose(exposed) diff --git a/packages/vue3/test-app/Pages/FormComponent/Precognition.vue b/packages/vue3/test-app/Pages/FormComponent/Precognition.vue new file mode 100644 index 000000000..9177235d5 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormComponent/Precognition.vue @@ -0,0 +1,34 @@ + + + diff --git a/playgrounds/vue3/app/Http/Requests/StoreUserRequest.php b/playgrounds/vue3/app/Http/Requests/StoreUserRequest.php new file mode 100644 index 000000000..392fa0763 --- /dev/null +++ b/playgrounds/vue3/app/Http/Requests/StoreUserRequest.php @@ -0,0 +1,21 @@ +|string> + */ + public function rules(): array + { + return [ + 'name' => ['required', 'string', 'min:3', 'max:255'], + 'email' => ['required', 'string', 'email', 'max:255'], + ]; + } +} diff --git a/playgrounds/vue3/package.json b/playgrounds/vue3/package.json index e089cc932..359dc0839 100644 --- a/playgrounds/vue3/package.json +++ b/playgrounds/vue3/package.json @@ -23,5 +23,9 @@ "vue": "^3.5.21", "vue-tsc": "^2.2.12" }, - "type": "module" -} + "type": "module", + "dependencies": { + "laravel-precognition": "link:../../../precognition/packages/core", + "laravel-precognition-vue": "link:../../../precognition/packages/vue" + } +} \ No newline at end of file diff --git a/playgrounds/vue3/resources/js/Pages/Home.vue b/playgrounds/vue3/resources/js/Pages/Home.vue index be2f51b9e..3e0729551 100644 --- a/playgrounds/vue3/resources/js/Pages/Home.vue +++ b/playgrounds/vue3/resources/js/Pages/Home.vue @@ -5,6 +5,15 @@ export default { layout: Layout } diff --git a/playgrounds/vue3/routes/web.php b/playgrounds/vue3/routes/web.php index efa24a69e..b51be2dba 100644 --- a/playgrounds/vue3/routes/web.php +++ b/playgrounds/vue3/routes/web.php @@ -1,6 +1,8 @@ middleware([HandlePrecognitiveRequests::class]); + Route::get('/users', function () { sleep(2); diff --git a/tests/app/server.js b/tests/app/server.js index 13a56b838..92aba77df 100644 --- a/tests/app/server.js +++ b/tests/app/server.js @@ -884,6 +884,52 @@ app.get('/form-component/invalidate-tags/:propType', (req, res) => }), ) +// + +app.post('/form-component/precognition', (req, res) => { + setTimeout(() => { + const only = req.headers['precognition-validate-only'] ? req.headers['precognition-validate-only'].split(',') : [] + const name = req.body['name'] + const email = req.body['email'] + const token = req.body['token'] + const errors = {} + + if (!name) { + errors.name = 'The name field is required.' + } + + if (name && name.length < 3) { + errors.name = 'The name must be at least 3 characters.' + } + + if (!email) { + errors.email = 'The email field is required.' + } + + if (email && !/\S+@\S+\.\S+/.test(email)) { + errors.email = 'The email must be a valid email address.' + } + + if (only.length) { + Object.keys(errors).forEach((key) => { + if (!only.includes(key)) { + delete errors[key] + } + }) + } + + res.header('Precognition', 'true') + + if (Object.keys(errors).length) { + return res.status(422).json({ errors }) + } + + return res.status(204).header('Precognition-Success', 'true').send() + }, 500) +}) + +// + function renderInfiniteScroll(req, res, component, total = 40, orderByDesc = false, perPage = 15) { const page = req.query.page ? parseInt(req.query.page) : 1 const partialReload = !!req.headers['x-inertia-partial-data'] From 3fd3af9487f83d284037b52567340ef86b80443b Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 1 Oct 2025 22:41:55 +0200 Subject: [PATCH 002/145] wip --- packages/core/src/precognition.ts | 85 +++++++++++--------- packages/vue3/src/form.ts | 28 ++++--- playgrounds/vue3/resources/js/Pages/Home.vue | 9 +++ tests/app/server.js | 1 + 4 files changed, 73 insertions(+), 50 deletions(-) diff --git a/packages/core/src/precognition.ts b/packages/core/src/precognition.ts index 044ee35cf..9632dcad3 100644 --- a/packages/core/src/precognition.ts +++ b/packages/core/src/precognition.ts @@ -41,8 +41,6 @@ export function forgetFiles(data: ValidatableData): ValidatableData { interface UsePrecognitionOptions { onStart: () => void onFinish: () => void - onPrecognitionSuccess: () => void - onValidationError: (errors: Errors & ErrorBag) => void } interface PrecognitionValidator {} @@ -60,43 +58,54 @@ export default function usePrecognition(precognitionOptions: UsePrecognitionOpti } const createValidateFunction = () => - debounce((options: { action: string; method: Method; data: ValidatableData; only: string[] }) => { - const data = validateFiles ? options.data : forgetFiles(options.data) - - if (options.only && isEqual(get(data, options.only), get(oldData, options.only))) { - return - } - - oldData = validatingData = { ...data } - - precognitionOptions.onStart() - - axios({ - method: options.method, - url: options.action, - data: validatingData, - headers: { - 'Content-Type': hasFiles(data) ? 'multipart/form-data' : 'application/json', - Precognition: true, - ...(options.only.length ? { 'Precognition-Validate-Only': options.only.join(',') } : {}), - }, - }) - .then((response) => { - if (response.status === 204 && response.headers['precognition-success'] === 'true') { - return precognitionOptions.onPrecognitionSuccess() - } + debounce( + (options: { + url: string + method: Method + data: ValidatableData + only: string[] + errorBag?: string + onPrecognitionSuccess: () => void + onValidationError: (errors: Errors & ErrorBag) => void + }) => { + const data = validateFiles ? options.data : forgetFiles(options.data) + + if (options.only && isEqual(get(data, options.only), get(oldData, options.only))) { + return + } + + oldData = validatingData = { ...data } + + precognitionOptions.onStart() + + axios({ + method: options.method, + url: options.url, + data: validatingData, + headers: { + 'Content-Type': hasFiles(data) ? 'multipart/form-data' : 'application/json', + Precognition: true, + ...(options.only.length ? { 'Precognition-Validate-Only': options.only.join(',') } : {}), + }, }) - .catch((error) => { - if (error.response && error.response.status === 422) { - return precognitionOptions.onValidationError(error.response.data.errors || {}) - } else { - throw error - } - }) - .finally(() => { - precognitionOptions.onFinish() - }) - }, debounceTimeoutDuration) + .then((response) => { + if (response.status === 204 && response.headers['precognition-success'] === 'true') { + return options.onPrecognitionSuccess() + } + }) + .catch((error) => { + if (error.response && error.response.status === 422) { + return options.onValidationError(error.response.data.errors || {}) + } else { + throw error + } + }) + .finally(() => { + precognitionOptions.onFinish() + }) + }, + debounceTimeoutDuration, + ) let validate = createValidateFunction() diff --git a/packages/vue3/src/form.ts b/packages/vue3/src/form.ts index f7be16b6d..b76e1fb83 100644 --- a/packages/vue3/src/form.ts +++ b/packages/vue3/src/form.ts @@ -220,14 +220,8 @@ const Form: InertiaForm = defineComponent({ const validating = ref(false) const validator = usePrecognition({ - onStart: () => { - validating.value = true - }, - onFinish: () => { - validating.value = false - }, - onPrecognitionSuccess: () => form.clearErrors(), - onValidationError: (errors) => form.setError(errors), + onStart: () => (validating.value = true), + onFinish: () => (validating.value = false), }) onMounted(() => { @@ -237,14 +231,24 @@ const Form: InertiaForm = defineComponent({ validator.setOldData(data) }) - const validate = (field?: string | string[]) => { - const [action, data] = getActionAndData() + const validate = (field: string | string[]) => { + const only = Array.isArray(field) ? field : [field] + + const [url, data] = getActionAndData() validator.validate({ - action, + url, method: method.value, data, - only: Array.isArray(field) ? field : [field], + only, + onPrecognitionSuccess: () => form.clearErrors(...only), + onValidationError: (errors) => { + const scopedErrors = props.errorBag ? errors[props.errorBag || ''] || {} : errors + const errorKeys = Object.keys(scopedErrors) + const valid = only.filter((field) => !errorKeys.includes(field)) + form.clearErrors(...valid) + form.setError(scopedErrors) + }, }) } diff --git a/playgrounds/vue3/resources/js/Pages/Home.vue b/playgrounds/vue3/resources/js/Pages/Home.vue index 3e0729551..1e0aaf3b5 100644 --- a/playgrounds/vue3/resources/js/Pages/Home.vue +++ b/playgrounds/vue3/resources/js/Pages/Home.vue @@ -14,6 +14,11 @@ const form = useForm('post', '/users', { }) const submit = () => form.submit() + +const validate = () => + form.validate({ + only: ['name', 'email'], + }) diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index a1aecddb8..81de9108e 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1431,6 +1431,69 @@ test.describe('Form Component', () => { }) }) + test.describe('Precognition', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/form-component/precognition') + }) + + test('shows validation error when field is invalid', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + }) + + test('clears validation error when field becomes valid', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + + await page.fill('input[name="name"]', 'John Doe') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() + }) + + test('validates only the specified field', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email field is required.')).not.toBeVisible() + }) + + test('validates multiple fields independently', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + }) + + test('does not clear unrelated field errors', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + + await page.fill('input[name="email"]', 'test@example.com') + await page.locator('input[name="email"]').blur() + + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + }) + }) + test.describe('React', () => { test.skip(process.env.PACKAGE !== 'react', 'Skipping React-specific tests') From 41ce2a6696fa3c414283e258248001d9680306f1 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 2 Oct 2025 12:31:10 +0200 Subject: [PATCH 006/145] Update form-component.spec.ts --- tests/form-component.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 81de9108e..25bea80ad 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1432,6 +1432,8 @@ test.describe('Form Component', () => { }) test.describe('Precognition', () => { + test.skip(process.env.PACKAGE !== 'vue', 'Precognition is Vue-only for now') + test.beforeEach(async ({ page }) => { await page.goto('/form-component/precognition') }) From 0a1d80ebab902f44eb7579ac6c12f0c38318fad2 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 2 Oct 2025 14:43:00 +0200 Subject: [PATCH 007/145] wip --- packages/vue3/src/form.ts | 5 +++-- tests/form-component.spec.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/vue3/src/form.ts b/packages/vue3/src/form.ts index e7330e511..19f250c0c 100644 --- a/packages/vue3/src/form.ts +++ b/packages/vue3/src/form.ts @@ -1,4 +1,5 @@ import { + Errors, FormComponentProps, FormComponentRef, FormComponentSlotProps, @@ -248,7 +249,7 @@ const Form: InertiaForm = defineComponent({ }, onValidationError: (errors) => { validated.value = [...validated.value, ...only] - const scopedErrors = props.errorBag ? errors[props.errorBag || ''] || {} : errors + const scopedErrors = (props.errorBag ? errors[props.errorBag || ''] || {} : errors) as Errors form.setError({ ...form.errors, ...scopedErrors }) }, }) @@ -288,7 +289,7 @@ const Form: InertiaForm = defineComponent({ defaults, // Precognition - valid: (field: string) => validated.value.has(field) && form.errors[field] === undefined, + valid: (field: string) => validated.value.includes(field) && form.errors[field] === undefined, invalid: (field: string) => form.errors[field] !== undefined, validate, setValidationTimeout: (duration: number) => validator.setTimeout(duration), diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 25bea80ad..fbcfaacdf 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1432,7 +1432,7 @@ test.describe('Form Component', () => { }) test.describe('Precognition', () => { - test.skip(process.env.PACKAGE !== 'vue', 'Precognition is Vue-only for now') + test.skip(process.env.PACKAGE !== 'vue3', 'Precognition is Vue-only for now') test.beforeEach(async ({ page }) => { await page.goto('/form-component/precognition') From b3608acfd55cbf8a5007b03122e1723458ee9d91 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 2 Oct 2025 14:50:33 +0200 Subject: [PATCH 008/145] Update package.json --- playgrounds/vue3/package.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/playgrounds/vue3/package.json b/playgrounds/vue3/package.json index 359dc0839..d36c26e42 100644 --- a/playgrounds/vue3/package.json +++ b/playgrounds/vue3/package.json @@ -23,9 +23,5 @@ "vue": "^3.5.21", "vue-tsc": "^2.2.12" }, - "type": "module", - "dependencies": { - "laravel-precognition": "link:../../../precognition/packages/core", - "laravel-precognition-vue": "link:../../../precognition/packages/vue" - } + "type": "module" } \ No newline at end of file From dc31fa0af2cc3c1a28f68afc83bd12efa8338d9e Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 09:39:00 +0200 Subject: [PATCH 009/145] Update form.ts --- packages/vue3/src/form.ts | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/vue3/src/form.ts b/packages/vue3/src/form.ts index 19f250c0c..87e954886 100644 --- a/packages/vue3/src/form.ts +++ b/packages/vue3/src/form.ts @@ -137,6 +137,7 @@ const Form: InertiaForm = defineComponent({ onMounted(() => { defaultData.value = getFormData() formEvents.forEach((e) => formElement.value.addEventListener(e, onFormUpdate)) + updateDataOnValidator() }) onBeforeUnmount(() => formEvents.forEach((e) => formElement.value?.removeEventListener(e, onFormUpdate))) @@ -203,9 +204,18 @@ const Form: InertiaForm = defineComponent({ form.transform(() => props.transform(data)).submit(method.value, action, submitOptions) } + const updateDataOnValidator = () => { + try { + // This might fail if the component is already unmounted but this function + // is called after navigating away after a form submission. + const data = getData() + validator.setOldData(data) + } catch {} + } + const reset = (...fields: string[]) => { resetFormFields(formElement.value, defaultData.value, fields) - validator.setOldData(getData()) + updateDataOnValidator() } const resetAndClearErrors = (...fields: string[]) => { @@ -226,22 +236,18 @@ const Form: InertiaForm = defineComponent({ onFinish: () => (validating.value = false), }) - onMounted(() => { - const [_action, data] = getActionAndData() - - // Set the initial data on the validator - validator.setOldData(data) - }) - const validate = (field: string | string[]) => { const only = Array.isArray(field) ? field : [field] - const [url, data] = getActionAndData() + // We're not using the data object from this method as it might be empty + // on GET requests, and we still want to pass a data object to the + // validator so it knows the current state of the form. + const [url] = getActionAndData() validator.validate({ url, method: method.value, - data, + data: getData(), only, onPrecognitionSuccess: () => { validated.value = [...validated.value, ...only] From 6bf015a7046b5dc072f21bd4ab11e292dd561556 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 10:24:04 +0200 Subject: [PATCH 010/145] refactor --- packages/core/src/files.ts | 32 ++++++++++++++++++++ packages/core/src/precognition.ts | 50 +++++-------------------------- packages/core/src/types.ts | 3 +- 3 files changed, 42 insertions(+), 43 deletions(-) diff --git a/packages/core/src/files.ts b/packages/core/src/files.ts index 2817b3c7a..34d271831 100644 --- a/packages/core/src/files.ts +++ b/packages/core/src/files.ts @@ -15,3 +15,35 @@ export function hasFiles(data: RequestPayload | FormDataConvertible): boolean { (typeof data === 'object' && data !== null && Object.values(data).some((value) => hasFiles(value))) ) } + +export function forgetFiles(data: Record): Record { + const newData = { ...data } + + Object.keys(newData).forEach((name) => { + const value = newData[name] + + if (value === null) { + return + } + + if (isFile(value)) { + delete newData[name] + + return + } + + if (Array.isArray(value)) { + newData[name] = Object.values(forgetFiles({ ...value })) + + return + } + + if (typeof value === 'object') { + newData[name] = forgetFiles(newData[name] as Record) + + return + } + }) + + return newData +} diff --git a/packages/core/src/precognition.ts b/packages/core/src/precognition.ts index c401b5421..26cdf322e 100644 --- a/packages/core/src/precognition.ts +++ b/packages/core/src/precognition.ts @@ -1,42 +1,8 @@ import { default as axios } from 'axios' import { get, isEqual } from 'lodash-es' import debounce from './debounce' -import { hasFiles, isFile } from './files' -import { ErrorBag, Errors, Method } from './types' - -type ValidatableData = Record - -export function forgetFiles(data: ValidatableData): ValidatableData { - const newData = { ...data } - - Object.keys(newData).forEach((name) => { - const value = newData[name] - - if (value === null) { - return - } - - if (isFile(value)) { - delete newData[name] - - return - } - - if (Array.isArray(value)) { - newData[name] = Object.values(forgetFiles({ ...value })) - - return - } - - if (typeof value === 'object') { - newData[name] = forgetFiles(newData[name] as ValidatableData) - - return - } - }) - - return newData -} +import { forgetFiles, hasFiles } from './files' +import { ErrorBag, Errors, Method, RequestData } from './types' interface UsePrecognitionOptions { onStart: () => void @@ -46,7 +12,7 @@ interface UsePrecognitionOptions { interface PrecognitionValidateOptions { url: string method: Method - data: ValidatableData + data: RequestData only: string[] errorBag?: string onPrecognitionSuccess: () => void @@ -54,15 +20,15 @@ interface PrecognitionValidateOptions { } interface PrecognitionValidator { - setOldData: (data: ValidatableData) => void + setOldData: (data: RequestData) => void validateFiles: (value: boolean) => void validate: (options: PrecognitionValidateOptions) => void setTimeout: (value: number) => void } export default function usePrecognition(precognitionOptions: UsePrecognitionOptions): PrecognitionValidator { - let oldData: ValidatableData = {} - let validatingData: ValidatableData = {} + let oldData: RequestData = {} + let validatingData: RequestData = {} let validateFiles: boolean = false let debounceTimeoutDuration = 1500 @@ -75,7 +41,7 @@ export default function usePrecognition(precognitionOptions: UsePrecognitionOpti const createValidateFunction = () => debounce( (options: PrecognitionValidateOptions) => { - const data = validateFiles ? options.data : forgetFiles(options.data) + const data = validateFiles ? options.data : (forgetFiles(options.data) as RequestData) const changed = options.only.filter((field) => !isEqual(get(data, field), get(oldData, field))) if (options.only.length > 0 && changed.length === 0) { @@ -120,7 +86,7 @@ export default function usePrecognition(precognitionOptions: UsePrecognitionOpti let validate = createValidateFunction() return { - setOldData(data: ValidatableData) { + setOldData(data: RequestData) { oldData = { ...data } }, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 1212a82a5..49d09b3f0 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -99,7 +99,8 @@ export type FormDataError = Partial, ErrorValue>> export type Method = 'get' | 'post' | 'put' | 'patch' | 'delete' -export type RequestPayload = Record | FormData +export type RequestData = Record +export type RequestPayload = RequestData | FormData export interface PageProps { [key: string]: unknown From 3ef1f6d2744c890f3ebc98743275ddc32e1f2f94 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 11:05:41 +0200 Subject: [PATCH 011/145] wip --- packages/core/src/types.ts | 8 ++++++++ packages/vue3/src/form.ts | 24 ++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 49d09b3f0..bd64a891f 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -489,6 +489,14 @@ export type FormComponentMethods = { defaults: () => void } +export type FormComponentPrecognition = { + valid: (field: string) => boolean + invalid: (field: string) => boolean + validate: (field?: string | string[]) => void + touch: (field: string | string[]) => void + validating: boolean +} + export type FormComponentonSubmitCompleteArguments = Pick export type FormComponentState = { diff --git a/packages/vue3/src/form.ts b/packages/vue3/src/form.ts index 87e954886..994fae646 100644 --- a/packages/vue3/src/form.ts +++ b/packages/vue3/src/form.ts @@ -1,5 +1,6 @@ import { Errors, + FormComponentPrecognition, FormComponentProps, FormComponentRef, FormComponentSlotProps, @@ -216,6 +217,12 @@ const Form: InertiaForm = defineComponent({ const reset = (...fields: string[]) => { resetFormFields(formElement.value, defaultData.value, fields) updateDataOnValidator() + + if (fields.length === 0) { + touched.value = [] + } else { + touched.value = touched.value.filter((field) => !fields.includes(field)) + } } const resetAndClearErrors = (...fields: string[]) => { @@ -230,14 +237,15 @@ const Form: InertiaForm = defineComponent({ const validating = ref(false) const validated = ref([]) + const touched = ref([]) const validator = usePrecognition({ onStart: () => (validating.value = true), onFinish: () => (validating.value = false), }) - const validate = (field: string | string[]) => { - const only = Array.isArray(field) ? field : [field] + const validate = (field?: string | string[]) => { + const only = field === undefined ? touched.value : Array.isArray(field) ? field : [field] // We're not using the data object from this method as it might be empty // on GET requests, and we still want to pass a data object to the @@ -261,6 +269,13 @@ const Form: InertiaForm = defineComponent({ }) } + const touch = (field: string | string[]) => { + const fields = Array.isArray(field) ? field : [field] + + // Use Set to avoid duplicates + touched.value = [...new Set([...touched.value, ...fields])] + } + const exposed = { get errors() { return form.errors @@ -298,11 +313,12 @@ const Form: InertiaForm = defineComponent({ valid: (field: string) => validated.value.includes(field) && form.errors[field] === undefined, invalid: (field: string) => form.errors[field] !== undefined, validate, + touch, setValidationTimeout: (duration: number) => validator.setTimeout(duration), validateFiles: () => validator.validateFiles(true), } - expose(exposed) + expose(exposed) return () => { return h( @@ -318,7 +334,7 @@ const Form: InertiaForm = defineComponent({ }, inert: props.disableWhileProcessing && form.processing, }, - slots.default ? slots.default(exposed) : [], + slots.default ? slots.default(exposed) : [], ) } }, From 131dfe7e5ecb19732d7a3c72f8a29fd8fd119865 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 11:37:22 +0200 Subject: [PATCH 012/145] test --- .../Pages/FormComponent/PrecognitionTouch.vue | 33 +++++++++++++++ playgrounds/vue3/resources/js/Pages/Home.vue | 40 ------------------- tests/form-component.spec.ts | 18 +++++++++ 3 files changed, 51 insertions(+), 40 deletions(-) create mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue new file mode 100644 index 000000000..00e9e4c51 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue @@ -0,0 +1,33 @@ + + + diff --git a/playgrounds/vue3/resources/js/Pages/Home.vue b/playgrounds/vue3/resources/js/Pages/Home.vue index 52f22457d..be2f51b9e 100644 --- a/playgrounds/vue3/resources/js/Pages/Home.vue +++ b/playgrounds/vue3/resources/js/Pages/Home.vue @@ -5,24 +5,6 @@ export default { layout: Layout } diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index fbcfaacdf..bb2ae8daa 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1494,6 +1494,24 @@ test.describe('Form Component', () => { await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() }) + + test('validates all touched fields when calling validate() without arguments', async ({ page }) => { + await page.goto('/form-component/precognition-touch') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + }) }) test.describe('React', () => { From fb3f9e6fd1a831644922fcdcd93ea92a5c0f714b Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 12:13:44 +0200 Subject: [PATCH 013/145] tests --- .../Pages/FormComponent/PrecognitionTouch.vue | 4 +- tests/form-component.spec.ts | 51 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue index 00e9e4c51..aded3eb0f 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue @@ -9,7 +9,7 @@ import { Form } from '@inertiajs/vue3'

Validating...

@@ -28,6 +28,8 @@ import { Form } from '@inertiajs/vue3' + +
diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index bb2ae8daa..5ef93a2b1 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1504,14 +1504,65 @@ test.describe('Form Component', () => { await page.fill('input[name="email"]', 'x') await page.locator('input[name="email"]').blur() + await expect(page.getByText('Validating...')).not.toBeVisible() await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() await page.getByRole('button', { name: 'Validate All Touched' }).click() + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() await expect(page.getByText('The email must be a valid email address.')).toBeVisible() }) + + test('reset all fields clears all touched fields', async ({ page }) => { + await page.goto('/form-component/precognition-touch') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await page.getByRole('button', { name: 'Reset All' }).click() + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + }) + + test('reset specific fields removes only those fields from touched', async ({ page }) => { + await page.goto('/form-component/precognition-touch') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await expect(page.locator('input[name="name"]')).toHaveValue('ab') + await expect(page.locator('input[name="email"]')).toHaveValue('x') + + await page.getByRole('button', { name: 'Reset Name' }).click() + + await expect(page.locator('input[name="name"]')).toHaveValue('') + await expect(page.locator('input[name="email"]')).toHaveValue('x') + + await page.fill('input[name="name"]', 'abc') + + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + }) }) test.describe('React', () => { From d205af11a4af4d1d463cbdc22c096ac88d9e449d Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 12:25:29 +0200 Subject: [PATCH 014/145] wip --- .../Pages/FormComponent/PrecognitionTouch.vue | 5 + tests/form-component.spec.ts | 110 +++++++++++++++++- 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue index aded3eb0f..89ba2c43f 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue @@ -28,8 +28,13 @@ import { Form } from '@inertiajs/vue3' + + + + + diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 5ef93a2b1..699f4c0e4 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1548,7 +1548,7 @@ test.describe('Form Component', () => { await expect(page.locator('input[name="name"]')).toHaveValue('ab') await expect(page.locator('input[name="email"]')).toHaveValue('x') - await page.getByRole('button', { name: 'Reset Name' }).click() + await page.getByRole('button', { name: 'Reset Name', exact: true }).click() await expect(page.locator('input[name="name"]')).toHaveValue('') await expect(page.locator('input[name="email"]')).toHaveValue('x') @@ -1563,6 +1563,114 @@ test.describe('Form Component', () => { await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() await expect(page.getByText('The email must be a valid email address.')).toBeVisible() }) + + test('touch with array marks multiple fields as touched', async ({ page }) => { + await page.goto('/form-component/precognition-touch') + + await page.fill('input[name="name"]', 'ab') + await page.fill('input[name="email"]', 'x') + + await page.getByRole('button', { name: 'Touch Name and Email' }).click() + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + }) + + test('touch deduplicates fields when called multiple times', async ({ page }) => { + await page.goto('/form-component/precognition-touch') + + await page.fill('input[name="name"]', 'ab') + + await page.getByRole('button', { name: 'Touch Name Twice' }).click() + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + }) + + test('validate with specific field works independently of touched state', async ({ page }) => { + await page.goto('/form-component/precognition-touch') + + await page.fill('input[name="name"]', 'ab') + await page.fill('input[name="email"]', 'x') + + await page.getByRole('button', { name: 'Validate Name', exact: true }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + }) + + test('validate with array of fields validates multiple fields', async ({ page }) => { + await page.goto('/form-component/precognition-touch') + + await page.fill('input[name="name"]', 'ab') + await page.fill('input[name="email"]', 'x') + + await page.getByRole('button', { name: 'Validate Name and Email' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + }) + + test('reset with array removes multiple fields from touched', async ({ page }) => { + await page.goto('/form-component/precognition-touch') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + + await page.getByRole('button', { name: 'Reset Name and Email' }).click() + + await page.fill('input[name="name"]', 'abc') + await page.fill('input[name="email"]', 'test@example.com') + + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await page.waitForTimeout(500) + + await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + }) + + test('touching one field and validating another does not validate the touched field', async ({ page }) => { + await page.goto('/form-component/precognition-touch') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await page.fill('input[name="email"]', 'x') + + await page.getByRole('button', { name: 'Validate Name', exact: true }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + }) }) test.describe('React', () => { From e73b45dacca8305acddc99ead5b78c2d535621bc Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 12:30:43 +0200 Subject: [PATCH 015/145] split --- .../Pages/FormComponent/PrecognitionReset.vue | 36 +++++++++++++++++++ .../Pages/FormComponent/PrecognitionTouch.vue | 17 +++++---- .../FormComponent/PrecognitionValidate.vue | 34 ++++++++++++++++++ tests/form-component.spec.ts | 12 +++---- 4 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionReset.vue create mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionValidate.vue diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionReset.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionReset.vue new file mode 100644 index 000000000..2b20a56d6 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionReset.vue @@ -0,0 +1,36 @@ + + + diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue index 89ba2c43f..363cc6e94 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue @@ -9,7 +9,7 @@ import { Form } from '@inertiajs/vue3'

Validating...

@@ -28,13 +28,16 @@ import { Form } from '@inertiajs/vue3' - - - - - - +
diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionValidate.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionValidate.vue new file mode 100644 index 000000000..7fb72fee2 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionValidate.vue @@ -0,0 +1,34 @@ + + + diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 699f4c0e4..514ef17e8 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1518,7 +1518,7 @@ test.describe('Form Component', () => { }) test('reset all fields clears all touched fields', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-reset') await page.fill('input[name="name"]', 'ab') await page.locator('input[name="name"]').blur() @@ -1537,7 +1537,7 @@ test.describe('Form Component', () => { }) test('reset specific fields removes only those fields from touched', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-reset') await page.fill('input[name="name"]', 'ab') await page.locator('input[name="name"]').blur() @@ -1596,7 +1596,7 @@ test.describe('Form Component', () => { }) test('validate with specific field works independently of touched state', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-validate') await page.fill('input[name="name"]', 'ab') await page.fill('input[name="email"]', 'x') @@ -1611,7 +1611,7 @@ test.describe('Form Component', () => { }) test('validate with array of fields validates multiple fields', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-validate') await page.fill('input[name="name"]', 'ab') await page.fill('input[name="email"]', 'x') @@ -1626,7 +1626,7 @@ test.describe('Form Component', () => { }) test('reset with array removes multiple fields from touched', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-reset') await page.fill('input[name="name"]', 'ab') await page.locator('input[name="name"]').blur() @@ -1656,7 +1656,7 @@ test.describe('Form Component', () => { }) test('touching one field and validating another does not validate the touched field', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-validate') await page.fill('input[name="name"]', 'ab') await page.locator('input[name="name"]').blur() From 3e43529bf5054693300c81aba7fef4abcad05a5c Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 13:17:33 +0200 Subject: [PATCH 016/145] valid method --- packages/vue3/src/form.ts | 7 ++ .../Pages/FormComponent/Precognition.vue | 8 +- .../Pages/FormComponent/PrecognitionTouch.vue | 6 +- tests/form-component.spec.ts | 85 +++++++++++++++++++ 4 files changed, 103 insertions(+), 3 deletions(-) diff --git a/packages/vue3/src/form.ts b/packages/vue3/src/form.ts index 994fae646..43ab7abc0 100644 --- a/packages/vue3/src/form.ts +++ b/packages/vue3/src/form.ts @@ -263,6 +263,13 @@ const Form: InertiaForm = defineComponent({ }, onValidationError: (errors) => { validated.value = [...validated.value, ...only] + + const validFields = only.filter((field) => errors[field] === undefined) + + if (validFields.length) { + form.clearErrors(...validFields) + } + const scopedErrors = (props.errorBag ? errors[props.errorBag || ''] || {} : errors) as Errors form.setError({ ...form.errors, ...scopedErrors }) }, diff --git a/packages/vue3/test-app/Pages/FormComponent/Precognition.vue b/packages/vue3/test-app/Pages/FormComponent/Precognition.vue index d470d15d9..8a3cc6a72 100644 --- a/packages/vue3/test-app/Pages/FormComponent/Precognition.vue +++ b/packages/vue3/test-app/Pages/FormComponent/Precognition.vue @@ -6,7 +6,11 @@ import { Form } from '@inertiajs/vue3'

Form Precognition

-
+

Validating...

@@ -14,6 +18,7 @@ import { Form } from '@inertiajs/vue3'

{{ errors.name }}

+

Name is valid!

@@ -21,6 +26,7 @@ import { Form } from '@inertiajs/vue3'

{{ errors.email }}

+

Email is valid!

diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue index 363cc6e94..80209562c 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue @@ -32,8 +32,10 @@ import { Form } from '@inertiajs/vue3' + + + + )} + + + ) +} diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionReset.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionReset.tsx new file mode 100644 index 000000000..50a267fe3 --- /dev/null +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionReset.tsx @@ -0,0 +1,40 @@ +import { Form } from '@inertiajs/react' + +export default () => { + return ( +
+

Form Precognition Reset

+ +
+ {({ invalid, errors, validate, touch, validating, reset }) => ( + <> + {validating &&

Validating...

} + +
+ touch('name')} /> + {invalid('name') &&

{errors.name}

} +
+ +
+ touch('email')} /> + {invalid('email') &&

{errors.email}

} +
+ + + + + + + )} +
+
+ ) +} diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionTouch.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionTouch.tsx new file mode 100644 index 000000000..2122b7b0c --- /dev/null +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionTouch.tsx @@ -0,0 +1,43 @@ +import { Form } from '@inertiajs/react' + +export default () => { + return ( +
+

Form Precognition Touch

+ +
+ {({ invalid, errors, validate, touch, validating }) => ( + <> + {validating &&

Validating...

} + +
+ touch('name')} /> + {invalid('name') &&

{errors.name}

} +
+ +
+ touch('email')} /> + {invalid('email') &&

{errors.email}

} +
+ + + + + + )} +
+
+ ) +} diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionValidate.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionValidate.tsx new file mode 100644 index 000000000..ae7c47070 --- /dev/null +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionValidate.tsx @@ -0,0 +1,34 @@ +import { Form } from '@inertiajs/react' + +export default () => { + return ( +
+

Form Precognition Validate

+ +
+ {({ invalid, errors, validate, touch, validating }) => ( + <> + {validating &&

Validating...

} + +
+ touch('name')} /> + {invalid('name') &&

{errors.name}

} +
+ +
+ + {invalid('email') &&

{errors.email}

} +
+ + + + + )} +
+
+ ) +} diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 6e818cd4f..7a9d9c214 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1432,8 +1432,6 @@ test.describe('Form Component', () => { }) test.describe('Precognition', () => { - test.skip(process.env.PACKAGE !== 'vue3', 'Precognition is Vue-only for now') - test.beforeEach(async ({ page }) => { await page.goto('/form-component/precognition') }) From 17f4bbc4458e61b73209dcfa857131b792ab736e Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 14:54:06 +0200 Subject: [PATCH 021/145] svelte --- packages/svelte/src/components/Form.svelte | 116 +++++++++++++++++- .../Pages/FormComponent/Precognition.svelte | 42 +++++++ .../FormComponent/PrecognitionFiles.svelte | 52 ++++++++ .../FormComponent/PrecognitionReset.svelte | 42 +++++++ .../FormComponent/PrecognitionTouch.svelte | 48 ++++++++ .../FormComponent/PrecognitionValidate.svelte | 39 ++++++ 6 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 packages/svelte/test-app/Pages/FormComponent/Precognition.svelte create mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionFiles.svelte create mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionReset.svelte create mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionTouch.svelte create mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionValidate.svelte diff --git a/packages/svelte/src/components/Form.svelte b/packages/svelte/src/components/Form.svelte index 194e4cf1e..04fa4437d 100644 --- a/packages/svelte/src/components/Form.svelte +++ b/packages/svelte/src/components/Form.svelte @@ -8,6 +8,7 @@ type FormDataConvertible, type VisitOptions, isUrlMethodPair, + usePrecognition, } from '@inertiajs/core' import { isEqual } from 'lodash-es' import { onMount } from 'svelte' @@ -37,6 +38,8 @@ export let resetOnError: FormComponentProps['resetOnError'] = false export let resetOnSuccess: FormComponentProps['resetOnSuccess'] = false export let setDefaultsOnSuccess: FormComponentProps['setDefaultsOnSuccess'] = false + export let validateFiles: FormComponentProps['validateFiles'] = false + export let validateTimeout: FormComponentProps['validateTimeout'] = 1500 type FormSubmitOptions = Omit @@ -45,6 +48,19 @@ let isDirty = false let defaultData: FormData = new FormData() + let validating = false + let validated: string[] = [] + let touched: string[] = [] + + const validator = usePrecognition({ + onStart: () => { + validating = true + }, + onFinish: () => { + validating = false + }, + }) + $: _method = isUrlMethodPair(action) ? action.method : (method.toLowerCase() as FormComponentProps['method']) $: _action = isUrlMethodPair(action) ? action.url : action @@ -59,12 +75,16 @@ return formDataToObject(getFormData()) } + function getActionAndData(): [string, Record] { + return mergeDataIntoQueryString(_method, _action, getData(), queryStringArrayFormat) + } + function updateDirtyState(event: Event) { isDirty = event.type === 'reset' ? false : !isEqual(getData(), formDataToObject(defaultData)) } export function submit() { - const [url, _data] = mergeDataIntoQueryString(_method, _action, getData(), queryStringArrayFormat) + const [url, _data] = getActionAndData() const maybeReset = (resetOption: boolean | string[] | undefined) => { if (!resetOption) { @@ -133,8 +153,24 @@ } } + function updateDataOnValidator() { + try { + // This might fail if the component is already unmounted but this function + // is called after navigating away after a form submission. + const data = getData() + validator.setOldData(data) + } catch {} + } + export function reset(...fields: string[]) { resetFormFields(formElement, defaultData, fields) + updateDataOnValidator() + + if (fields.length === 0) { + touched = [] + } else { + touched = touched.filter((field) => !fields.includes(field)) + } } export function clearErrors(...fields: string[]) { @@ -162,17 +198,87 @@ isDirty = false } + export function validate(field?: string | string[]) { + const only = field === undefined ? touched : Array.isArray(field) ? field : [field] + + // We're not using the data object from this method as it might be empty + // on GET requests, and we still want to pass a data object to the + // validator so it knows the current state of the form. + const [url] = getActionAndData() + + validator.validate({ + url, + method: _method, + data: getData(), + only, + onPrecognitionSuccess: () => { + validated = [...validated, ...only] + clearErrors(...only) + }, + onValidationError: (errors) => { + validated = [...validated, ...only] + + const validFields = only.filter((field) => errors[field] === undefined) + + if (validFields.length) { + clearErrors(...validFields) + } + + const scopedErrors = (errorBag ? errors[errorBag || ''] || {} : errors) as Errors + + // Merge current errors with new scopedErrors + const mergedErrors = { ...$form.errors, ...scopedErrors } + setError(mergedErrors) + }, + }) + } + + export function touch(field: string | string[]) { + const fields = Array.isArray(field) ? field : [field] + + // Use Set to avoid duplicates + touched = [...new Set([...touched, ...fields])] + } + + function valid(field: string): boolean { + return validated.includes(field) && $form.errors[field] === undefined + } + + function invalid(field: string): boolean { + return $form.errors[field] !== undefined + } + + export function setValidationTimeout(duration: number) { + validator.setTimeout(duration) + } + + export function validateFilesEnabled() { + validator.validateFiles(true) + } + onMount(() => { defaultData = getFormData() const formEvents = ['input', 'change', 'reset'] formEvents.forEach((e) => formElement.addEventListener(e, updateDirtyState)) + updateDataOnValidator() + validator.validateFiles(validateFiles) + validator.setTimeout(validateTimeout) + return () => { formEvents.forEach((e) => formElement?.removeEventListener(e, updateDirtyState)) } }) + + $: validator.validateFiles(validateFiles) + $: validator.setTimeout(validateTimeout) + $: slotErrors = $form.errors as Errors + + // Create reactive slot props that update when state changes + $: slotValid = (field: string) => validated.includes(field) && slotErrors[field] === undefined + $: slotInvalid = (field: string) => slotErrors[field] !== undefined
diff --git a/packages/svelte/test-app/Pages/FormComponent/Precognition.svelte b/packages/svelte/test-app/Pages/FormComponent/Precognition.svelte new file mode 100644 index 000000000..c9938186c --- /dev/null +++ b/packages/svelte/test-app/Pages/FormComponent/Precognition.svelte @@ -0,0 +1,42 @@ + + +
+

Form Precognition

+ +
+ {#if validating} +

Validating...

+ {/if} + +
+ validate('name')} /> + {#if invalid('name')} +

{errors.name}

+ {/if} + {#if valid('name')} +

Name is valid!

+ {/if} +
+ +
+ validate('email')} /> + {#if invalid('email')} +

{errors.email}

+ {/if} + {#if valid('email')} +

Email is valid!

+ {/if} +
+
+
diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionFiles.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionFiles.svelte new file mode 100644 index 000000000..fa6569d63 --- /dev/null +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionFiles.svelte @@ -0,0 +1,52 @@ + + +
+

Form Precognition Files

+ +
+ {#if validating} +

Validating...

+ {/if} + +
+ validate('name')} /> + {#if invalid('name')} +

{errors.name}

+ {/if} + {#if valid('name')} +

Name is valid!

+ {/if} +
+ +
+ + {#if invalid('avatar')} +

{errors.avatar}

+ {/if} + {#if valid('avatar')} +

Avatar is valid!

+ {/if} +
+ + + + +
+
diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionReset.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionReset.svelte new file mode 100644 index 000000000..89b6dbdc0 --- /dev/null +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionReset.svelte @@ -0,0 +1,42 @@ + + +
+

Form Precognition Reset

+ +
+ {#if validating} +

Validating...

+ {/if} + +
+ touch('name')} /> + {#if invalid('name')} +

{errors.name}

+ {/if} +
+ +
+ touch('email')} /> + {#if invalid('email')} +

{errors.email}

+ {/if} +
+ + + + + +
+
diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionTouch.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionTouch.svelte new file mode 100644 index 000000000..ec5c641e6 --- /dev/null +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionTouch.svelte @@ -0,0 +1,48 @@ + + +
+

Form Precognition Touch

+ +
+ {#if validating} +

Validating...

+ {/if} + +
+ touch('name')} /> + {#if invalid('name')} +

{errors.name}

+ {/if} +
+ +
+ touch('email')} /> + {#if invalid('email')} +

{errors.email}

+ {/if} +
+ + + + +
+
diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionValidate.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionValidate.svelte new file mode 100644 index 000000000..69f4a7c44 --- /dev/null +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionValidate.svelte @@ -0,0 +1,39 @@ + + +
+

Form Precognition Validate

+ +
+ {#if validating} +

Validating...

+ {/if} + +
+ touch('name')} /> + {#if invalid('name')} +

{errors.name}

+ {/if} +
+ +
+ + {#if invalid('email')} +

{errors.email}

+ {/if} +
+ + + +
+
From b73535c1614d3c4b1937c114e466309b09008b28 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 14:55:07 +0200 Subject: [PATCH 022/145] refactor --- packages/react/src/Form.ts | 23 +++++++++++----------- packages/svelte/src/components/Form.svelte | 6 +++--- packages/vue3/src/form.ts | 8 ++++---- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/packages/react/src/Form.ts b/packages/react/src/Form.ts index 7c311971d..cd43474f5 100644 --- a/packages/react/src/Form.ts +++ b/packages/react/src/Form.ts @@ -104,6 +104,15 @@ const Form = forwardRef( // expects an object, and submitting a FormData instance directly causes problems with nested objects. const getData = (): Record => formDataToObject(getFormData()) + const getUrlAndData = (): [string, Record] => { + return mergeDataIntoQueryString( + resolvedMethod, + isUrlMethodPair(action) ? action.url : action, + getData(), + queryStringArrayFormat, + ) + } + const updateDirtyState = (event: Event) => deferStateUpdate(() => setIsDirty(event.type === 'reset' ? false : !isEqual(getData(), formDataToObject(defaultData.current))), @@ -169,12 +178,7 @@ const Form = forwardRef( } const submit = () => { - const [url, _data] = mergeDataIntoQueryString( - resolvedMethod, - isUrlMethodPair(action) ? action.url : action, - getData(), - queryStringArrayFormat, - ) + const [url, _data] = getUrlAndData() const submitOptions: FormSubmitOptions = { headers, @@ -221,12 +225,7 @@ const Form = forwardRef( // We're not using the data object from this method as it might be empty // on GET requests, and we still want to pass a data object to the // validator so it knows the current state of the form. - const [url] = mergeDataIntoQueryString( - resolvedMethod, - isUrlMethodPair(action) ? action.url : action, - getData(), - queryStringArrayFormat, - ) + const [url] = getUrlAndData() validator.validate({ url, diff --git a/packages/svelte/src/components/Form.svelte b/packages/svelte/src/components/Form.svelte index 04fa4437d..e50c9d28a 100644 --- a/packages/svelte/src/components/Form.svelte +++ b/packages/svelte/src/components/Form.svelte @@ -75,7 +75,7 @@ return formDataToObject(getFormData()) } - function getActionAndData(): [string, Record] { + function getUrlAndData(): [string, Record] { return mergeDataIntoQueryString(_method, _action, getData(), queryStringArrayFormat) } @@ -84,7 +84,7 @@ } export function submit() { - const [url, _data] = getActionAndData() + const [url, _data] = getUrlAndData() const maybeReset = (resetOption: boolean | string[] | undefined) => { if (!resetOption) { @@ -204,7 +204,7 @@ // We're not using the data object from this method as it might be empty // on GET requests, and we still want to pass a data object to the // validator so it knows the current state of the form. - const [url] = getActionAndData() + const [url] = getUrlAndData() validator.validate({ url, diff --git a/packages/vue3/src/form.ts b/packages/vue3/src/form.ts index 139b12948..656338db3 100644 --- a/packages/vue3/src/form.ts +++ b/packages/vue3/src/form.ts @@ -179,7 +179,7 @@ const Form: InertiaForm = defineComponent({ // expects an object, and submitting a FormData instance directly causes problems with nested objects. const getData = (): Record => formDataToObject(getFormData()) - const getActionAndData = (): [string, Record] => { + const getUrlAndData = (): [string, Record] => { return mergeDataIntoQueryString( method.value, isUrlMethodPair(props.action) ? props.action.url : props.action, @@ -228,10 +228,10 @@ const Form: InertiaForm = defineComponent({ ...props.options, } - const [action, data] = getActionAndData() + const [url, data] = getUrlAndData() // We need transform because we can't override the default data with different keys (by design) - form.transform(() => props.transform(data)).submit(method.value, action, submitOptions) + form.transform(() => props.transform(data)).submit(method.value, url, submitOptions) } const updateDataOnValidator = () => { @@ -270,7 +270,7 @@ const Form: InertiaForm = defineComponent({ // We're not using the data object from this method as it might be empty // on GET requests, and we still want to pass a data object to the // validator so it knows the current state of the form. - const [url] = getActionAndData() + const [url] = getUrlAndData() validator.validate({ url, From cea03dbaae5477c33664a93acacf569f43290979 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 15:28:56 +0200 Subject: [PATCH 023/145] transform + callbacks --- packages/core/src/precognition.ts | 12 ++-- packages/core/src/types.ts | 7 ++ packages/react/src/Form.ts | 42 ++++++++--- .../FormComponent/PrecognitionCallbacks.tsx | 63 +++++++++++++++++ .../FormComponent/PrecognitionTransform.tsx | 28 ++++++++ packages/svelte/src/components/Form.svelte | 44 ++++++++---- .../PrecognitionCallbacks.svelte | 64 +++++++++++++++++ .../PrecognitionTransform.svelte | 33 +++++++++ packages/vue3/src/form.ts | 42 ++++++++--- .../FormComponent/PrecognitionCallbacks.vue | 69 +++++++++++++++++++ .../FormComponent/PrecognitionTransform.vue | 26 +++++++ playgrounds/vue3/package.json | 2 +- tests/app/server.js | 38 ++++++++-- tests/form-component.spec.ts | 41 +++++++++++ 14 files changed, 466 insertions(+), 45 deletions(-) create mode 100644 packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx create mode 100644 packages/react/test-app/Pages/FormComponent/PrecognitionTransform.tsx create mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte create mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte create mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue create mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionTransform.vue diff --git a/packages/core/src/precognition.ts b/packages/core/src/precognition.ts index d1bf0987e..c39dc2c6b 100644 --- a/packages/core/src/precognition.ts +++ b/packages/core/src/precognition.ts @@ -3,7 +3,7 @@ import { get, isEqual } from 'lodash-es' import debounce from './debounce' import { forgetFiles, hasFiles } from './files' import { objectToFormData } from './formData' -import { ErrorBag, Errors, Method, RequestData } from './types' +import { Errors, Method, RequestData } from './types' interface UsePrecognitionOptions { onStart: () => void @@ -15,9 +15,10 @@ interface PrecognitionValidateOptions { method: Method data: RequestData only: string[] - errorBag?: string + errorBag?: string | null onPrecognitionSuccess: () => void - onValidationError: (errors: Errors & ErrorBag) => void + onValidationError: (errors: Errors) => void + onFinish?: () => void } interface PrecognitionValidator { @@ -71,13 +72,16 @@ export default function usePrecognition(precognitionOptions: UsePrecognitionOpti }) .catch((error) => { if (error.response?.status === 422) { - return options.onValidationError(error.response.data?.errors || {}) + const errors = error.response.data?.errors || {} + const scopedErrors = (options.errorBag ? errors[options.errorBag] || {} : errors) as Errors + return options.onValidationError(scopedErrors) } throw error }) .finally(() => { oldData = { ...data } + options.onFinish?.() precognitionOptions.onFinish() }) }, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 7f49c116c..82c2f4af0 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -499,6 +499,13 @@ export type FormComponentPrecognition = { validating: boolean } +export type FormComponentPrecognitionValidateOptions = { + only?: string | string[] + onSuccess?: () => void + onError?: (errors: Errors) => void + onFinish?: () => void +} + export type FormComponentonSubmitCompleteArguments = Pick export type FormComponentState = { diff --git a/packages/react/src/Form.ts b/packages/react/src/Form.ts index cd43474f5..c4a6c46b2 100644 --- a/packages/react/src/Form.ts +++ b/packages/react/src/Form.ts @@ -1,6 +1,6 @@ import { - Errors, FormComponentPrecognition, + FormComponentPrecognitionValidateOptions, FormComponentProps, FormComponentRef, FormComponentSlotProps, @@ -219,8 +219,23 @@ const Form = forwardRef( setIsDirty(false) } - const validate = (field?: string | string[]) => { - const only = field === undefined ? touched : Array.isArray(field) ? field : [field] + const validate = ( + only?: string | string[] | FormComponentPrecognitionValidateOptions, + maybeOptions?: FormComponentPrecognitionValidateOptions, + ) => { + let fields: string[] + let options: FormComponentPrecognitionValidateOptions = {} + + if (typeof only === 'object' && !Array.isArray(only)) { + // Called as validate({ only: [...], onSuccess, onError, onFinish }) + const onlyFields = only.only + fields = onlyFields === undefined ? touched : Array.isArray(onlyFields) ? onlyFields : [onlyFields] + options = only + } else { + // Called as validate('field') or validate(['field1', 'field2']) or validate('field', {options}) + fields = only === undefined ? touched : Array.isArray(only) ? only : [only] + options = maybeOptions || {} + } // We're not using the data object from this method as it might be empty // on GET requests, and we still want to pass a data object to the @@ -230,23 +245,28 @@ const Form = forwardRef( validator.validate({ url, method: resolvedMethod, - data: getData(), - only, + data: transform(getData()), + only: fields, + errorBag, onPrecognitionSuccess: () => { - setValidated((prev) => [...prev, ...only]) - form.clearErrors(...only) + setValidated((prev) => [...prev, ...fields]) + form.clearErrors(...fields) + options.onSuccess?.() }, onValidationError: (errors) => { - setValidated((prev) => [...prev, ...only]) + setValidated((prev) => [...prev, ...fields]) - const validFields = only.filter((field) => errors[field] === undefined) + const validFields = fields.filter((field) => errors[field] === undefined) if (validFields.length) { form.clearErrors(...validFields) } - const scopedErrors = (errorBag ? errors[errorBag || ''] || {} : errors) as Errors - form.setError({ ...form.errors, ...scopedErrors }) + form.setError({ ...form.errors, ...errors }) + options.onError?.(errors) + }, + onFinish: () => { + options.onFinish?.() }, }) } diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx new file mode 100644 index 000000000..bc418536b --- /dev/null +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx @@ -0,0 +1,63 @@ +import { Form } from '@inertiajs/react' +import { useState } from 'react' + +export default () => { + const [successCalled, setSuccessCalled] = useState(false) + const [errorCalled, setErrorCalled] = useState(false) + const [finishCalled, setFinishCalled] = useState(false) + + return ( +
+

Form Precognition Callbacks

+ +
+ {({ validate, validating, touch }) => ( + <> + {validating &&

Validating...

} + {successCalled &&

onSuccess called!

} + {errorCalled &&

onError called!

} + {finishCalled &&

onFinish called!

} + +
+ touch('name')} /> +
+ + + + + + )} +
+
+ ) +} diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionTransform.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionTransform.tsx new file mode 100644 index 000000000..5d43bf8a0 --- /dev/null +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionTransform.tsx @@ -0,0 +1,28 @@ +import { Form } from '@inertiajs/react' + +export default () => { + return ( +
+

Form Precognition Transform

+ +
({ name: data.name.toUpperCase() })} + > + {({ invalid, errors, validate, valid, validating }) => ( + <> + {validating &&

Validating...

} + +
+ validate('name')} /> + {invalid('name') &&

{errors.name}

} + {valid('name') &&

Name is valid!

} +
+ + )} +
+
+ ) +} diff --git a/packages/svelte/src/components/Form.svelte b/packages/svelte/src/components/Form.svelte index e50c9d28a..d3ee93be1 100644 --- a/packages/svelte/src/components/Form.svelte +++ b/packages/svelte/src/components/Form.svelte @@ -6,6 +6,7 @@ type Errors, type FormComponentProps, type FormDataConvertible, + type FormComponentPrecognitionValidateOptions, type VisitOptions, isUrlMethodPair, usePrecognition, @@ -198,8 +199,23 @@ isDirty = false } - export function validate(field?: string | string[]) { - const only = field === undefined ? touched : Array.isArray(field) ? field : [field] + export function validate( + only?: string | string[] | FormComponentPrecognitionValidateOptions, + maybeOptions?: FormComponentPrecognitionValidateOptions, + ) { + let fields: string[] + let options: FormComponentPrecognitionValidateOptions = {} + + if (typeof only === 'object' && !Array.isArray(only)) { + // Called as validate({ only: [...], onSuccess, onError, onFinish }) + const onlyFields = only.only + fields = onlyFields === undefined ? touched : Array.isArray(onlyFields) ? onlyFields : [onlyFields] + options = only + } else { + // Called as validate('field') or validate(['field1', 'field2']) or validate('field', {options}) + fields = only === undefined ? touched : Array.isArray(only) ? only : [only] + options = maybeOptions || {} + } // We're not using the data object from this method as it might be empty // on GET requests, and we still want to pass a data object to the @@ -209,26 +225,30 @@ validator.validate({ url, method: _method, - data: getData(), - only, + data: transform(getData()), + only: fields, + errorBag, onPrecognitionSuccess: () => { - validated = [...validated, ...only] - clearErrors(...only) + validated = [...validated, ...fields] + clearErrors(...fields) + options.onSuccess?.() }, onValidationError: (errors) => { - validated = [...validated, ...only] + validated = [...validated, ...fields] - const validFields = only.filter((field) => errors[field] === undefined) + const validFields = fields.filter((field) => errors[field] === undefined) if (validFields.length) { clearErrors(...validFields) } - const scopedErrors = (errorBag ? errors[errorBag || ''] || {} : errors) as Errors - - // Merge current errors with new scopedErrors - const mergedErrors = { ...$form.errors, ...scopedErrors } + // Merge current errors with new errors + const mergedErrors = { ...$form.errors, ...errors } setError(mergedErrors) + options.onError?.(errors) + }, + onFinish: () => { + options.onFinish?.() }, }) } diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte new file mode 100644 index 000000000..acd97449e --- /dev/null +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte @@ -0,0 +1,64 @@ + + +
+

Form Precognition Callbacks

+ +
+ {#if validating} +

Validating...

+ {/if} + {#if successCalled} +

onSuccess called!

+ {/if} + {#if errorCalled} +

onError called!

+ {/if} + {#if finishCalled} +

onFinish called!

+ {/if} + +
+ touch('name')} /> +
+ + + + +
+
diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte new file mode 100644 index 000000000..87591c8cf --- /dev/null +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte @@ -0,0 +1,33 @@ + + +
+

Form Precognition Transform

+ +
({ name: data.name.toUpperCase() })} + let:invalid + let:errors + let:validate + let:valid + let:validating + > + {#if validating} +

Validating...

+ {/if} + +
+ validate('name')} /> + {#if invalid('name')} +

{errors.name}

+ {/if} + {#if valid('name')} +

Name is valid!

+ {/if} +
+
+
diff --git a/packages/vue3/src/form.ts b/packages/vue3/src/form.ts index 656338db3..dd3de777b 100644 --- a/packages/vue3/src/form.ts +++ b/packages/vue3/src/form.ts @@ -1,6 +1,6 @@ import { - Errors, FormComponentPrecognition, + FormComponentPrecognitionValidateOptions, FormComponentProps, FormComponentRef, FormComponentSlotProps, @@ -264,8 +264,23 @@ const Form: InertiaForm = defineComponent({ isDirty.value = false } - const validate = (field?: string | string[]) => { - const only = field === undefined ? touched.value : Array.isArray(field) ? field : [field] + const validate = ( + only?: string | string[] | FormComponentPrecognitionValidateOptions, + maybeOptions?: FormComponentPrecognitionValidateOptions, + ) => { + let fields: string[] + let options: FormComponentPrecognitionValidateOptions = {} + + if (typeof only === 'object' && !Array.isArray(only)) { + // Called as validate({ only: [...], onSuccess, onError, onFinish }) + const onlyFields = only.only + fields = onlyFields === undefined ? touched.value : Array.isArray(onlyFields) ? onlyFields : [onlyFields] + options = only + } else { + // Called as validate('field') or validate(['field1', 'field2']) or validate('field', {options}) + fields = only === undefined ? touched.value : Array.isArray(only) ? only : [only] + options = maybeOptions || {} + } // We're not using the data object from this method as it might be empty // on GET requests, and we still want to pass a data object to the @@ -275,23 +290,28 @@ const Form: InertiaForm = defineComponent({ validator.validate({ url, method: method.value, - data: getData(), - only, + data: props.transform(getData()), + only: fields, + errorBag: props.errorBag, onPrecognitionSuccess: () => { - validated.value = [...validated.value, ...only] - form.clearErrors(...only) + validated.value = [...validated.value, ...fields] + form.clearErrors(...fields) + options.onSuccess?.() }, onValidationError: (errors) => { - validated.value = [...validated.value, ...only] + validated.value = [...validated.value, ...fields] - const validFields = only.filter((field) => errors[field] === undefined) + const validFields = fields.filter((field) => errors[field] === undefined) if (validFields.length) { form.clearErrors(...validFields) } - const scopedErrors = (props.errorBag ? errors[props.errorBag || ''] || {} : errors) as Errors - form.setError({ ...form.errors, ...scopedErrors }) + form.setError({ ...form.errors, ...errors }) + options.onError?.(errors) + }, + onFinish: () => { + options.onFinish?.() }, }) } diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue new file mode 100644 index 000000000..3494406e9 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue @@ -0,0 +1,69 @@ + + + diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTransform.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTransform.vue new file mode 100644 index 000000000..580a882ac --- /dev/null +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTransform.vue @@ -0,0 +1,26 @@ + + + diff --git a/playgrounds/vue3/package.json b/playgrounds/vue3/package.json index d36c26e42..e089cc932 100644 --- a/playgrounds/vue3/package.json +++ b/playgrounds/vue3/package.json @@ -24,4 +24,4 @@ "vue-tsc": "^2.2.12" }, "type": "module" -} \ No newline at end of file +} diff --git a/tests/app/server.js b/tests/app/server.js index fdf433854..653e1946b 100644 --- a/tests/app/server.js +++ b/tests/app/server.js @@ -928,12 +928,6 @@ app.post('/form-component/precognition', (req, res) => { }, 500) }) -app.get('/form-component/precognition-files', (req, res) => { - inertia.render(req, res, { - component: 'FormComponent/PrecognitionFiles', - }) -}) - app.post('/form-component/precognition-files', upload.any(), (req, res) => { setTimeout(() => { console.log(req, req) @@ -973,6 +967,38 @@ app.post('/form-component/precognition-files', upload.any(), (req, res) => { }, 500) }) +app.post('/form-component/precognition-transform', (req, res) => { + setTimeout(() => { + const only = req.headers['precognition-validate-only'] ? req.headers['precognition-validate-only'].split(',') : [] + const name = req.body['name'] + const errors = {} + + // Validate that name is uppercase + if (!name) { + errors.name = 'The name field is required.' + } else if (name !== name.toUpperCase()) { + errors.name = 'The name must be uppercase.' + } + + if (only.length) { + Object.keys(errors).forEach((key) => { + if (!only.includes(key)) { + delete errors[key] + } + }) + } + + res.header('Precognition', 'true') + res.header('Vary', 'Precognition') + + if (Object.keys(errors).length) { + return res.status(422).json({ errors }) + } + + return res.status(204).header('Precognition-Success', 'true').send() + }, 500) +}) + // function renderInfiniteScroll(req, res, component, total = 40, orderByDesc = false, perPage = 15) { diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 7a9d9c214..0a3e185bb 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1793,6 +1793,47 @@ test.describe('Form Component', () => { await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() await expect(page.getByText('The avatar field is required.')).not.toBeVisible() }) + + test('transforms data for validation requests', async ({ page }) => { + await page.goto('/form-component/precognition-transform') + + await page.fill('input[name="name"]', 'taylor') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + // Should succeed because transform converts to uppercase + await expect(page.getByText('Name is valid!')).toBeVisible() + }) + + test('calls onSuccess and onFinish callbacks when validation succeeds', async ({ page }) => { + await page.goto('/form-component/precognition-callbacks') + + await page.fill('input[name="name"]', 'John Doe') + await page.click('button:has-text("Validate with onSuccess")') + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('onSuccess called!')).toBeVisible() + await expect(page.getByText('onError called!')).not.toBeVisible() + await expect(page.getByText('onFinish called!')).toBeVisible() + }) + + test('calls onError and onFinish callbacks when validation fails', async ({ page }) => { + await page.goto('/form-component/precognition-callbacks') + + await page.fill('input[name="name"]', 'ab') + await page.click('button:has-text("Validate with onError")') + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('onSuccess called!')).not.toBeVisible() + await expect(page.getByText('onError called!')).toBeVisible() + await expect(page.getByText('onFinish called!')).toBeVisible() + }) }) test.describe('React', () => { From 0da076084b3fdfcea7b81b2d0dd8e0f198fe138d Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 3 Oct 2025 15:31:43 +0200 Subject: [PATCH 024/145] types --- .../test-app/Pages/FormComponent/PrecognitionTransform.tsx | 2 +- .../test-app/Pages/FormComponent/PrecognitionTransform.svelte | 2 +- .../vue3/test-app/Pages/FormComponent/PrecognitionTransform.vue | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionTransform.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionTransform.tsx index 5d43bf8a0..4eb783f61 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionTransform.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionTransform.tsx @@ -9,7 +9,7 @@ export default () => { action="/form-component/precognition-transform" method="post" validateTimeout={100} - transform={(data) => ({ name: data.name.toUpperCase() })} + transform={(data) => ({ name: String(data.name || '').toUpperCase() })} > {({ invalid, errors, validate, valid, validating }) => ( <> diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte index 87591c8cf..265f17308 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte @@ -9,7 +9,7 @@ action="/form-component/precognition-transform" method="post" validateTimeout={100} - transform={(data) => ({ name: data.name.toUpperCase() })} + transform={(data) => ({ name: String(data.name || '').toUpperCase() })} let:invalid let:errors let:validate diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTransform.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTransform.vue index 580a882ac..8f9bb6cd4 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTransform.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionTransform.vue @@ -10,7 +10,7 @@ import { Form } from '@inertiajs/vue3' action="/form-component/precognition-transform" method="post" :validateTimeout="100" - :transform="(data) => ({ name: data.name.toUpperCase() })" + :transform="(data) => ({ name: String(data.name || '').toUpperCase() })" > From 25774a3df7ef77cbe2fb68969d7b97445f8fb70a Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 7 Oct 2025 17:52:13 +0200 Subject: [PATCH 033/145] Force simple errors payload --- packages/core/src/precognition.ts | 20 ++++++-- .../FormComponent/PrecognitionArrayErrors.tsx | 29 ++++++++++++ .../PrecognitionArrayErrors.svelte | 42 +++++++++++++++++ .../FormComponent/PrecognitionArrayErrors.vue | 34 ++++++++++++++ tests/app/server.js | 46 +++++++++++++++++++ tests/form-component.spec.ts | 14 ++++++ 6 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 packages/react/test-app/Pages/FormComponent/PrecognitionArrayErrors.tsx create mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionArrayErrors.svelte create mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionArrayErrors.vue diff --git a/packages/core/src/precognition.ts b/packages/core/src/precognition.ts index eba2ca16f..f7115f55f 100644 --- a/packages/core/src/precognition.ts +++ b/packages/core/src/precognition.ts @@ -33,8 +33,10 @@ export default function usePrecognition(precognitionOptions: UsePrecognitionOpti const abortControllers: Record = {} const cancelAll = () => { - Object.values(abortControllers).forEach((controller) => controller.abort()) - Object.keys(abortControllers).forEach((key) => delete abortControllers[key]) + Object.entries(abortControllers).forEach(([key, controller]) => { + controller.abort() + delete abortControllers[key] + }) } const setTimeout = (value: number) => { @@ -45,8 +47,16 @@ export default function usePrecognition(precognitionOptions: UsePrecognitionOpti } } - const createFingerprint = (options: PrecognitionValidateOptions) => { - return `${options.method}:${options.url}` + const createFingerprint = (options: PrecognitionValidateOptions) => `${options.method}:${options.url}` + + const toSimpleValidationErrors = (errors: Errors): Errors => { + return Object.keys(errors).reduce( + (carry, key) => ({ + ...carry, + [key]: Array.isArray(errors[key]) ? errors[key][0] : errors[key], + }), + {}, + ) } const createValidateFunction = () => @@ -102,7 +112,7 @@ export default function usePrecognition(precognitionOptions: UsePrecognitionOpti if (error.response?.status === 422) { const errors = error.response.data?.errors || {} const scopedErrors = (options.errorBag ? errors[options.errorBag] || {} : errors) as Errors - return options.onValidationError(scopedErrors) + return options.onValidationError(toSimpleValidationErrors(scopedErrors)) } if (options.onException) { diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionArrayErrors.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionArrayErrors.tsx new file mode 100644 index 000000000..d9f35c491 --- /dev/null +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionArrayErrors.tsx @@ -0,0 +1,29 @@ +import { Form } from '@inertiajs/react' + +export default () => { + return ( +
+

Form Precognition - Array Errors

+ +
+ {({ invalid, errors, validate, valid, validating }) => ( + <> + {validating &&

Validating...

} + +
+ validate('name')} /> + {invalid('name') &&

{errors.name}

} + {valid('name') &&

Name is valid!

} +
+ +
+ validate('email')} /> + {invalid('email') &&

{errors.email}

} + {valid('email') &&

Email is valid!

} +
+ + )} +
+
+ ) +} diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionArrayErrors.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionArrayErrors.svelte new file mode 100644 index 000000000..a36918728 --- /dev/null +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionArrayErrors.svelte @@ -0,0 +1,42 @@ + + +
+

Form Precognition - Array Errors

+ +
+ {#if validating} +

Validating...

+ {/if} + +
+ validate('name')} /> + {#if invalid('name')} +

{errors.name}

+ {/if} + {#if valid('name')} +

Name is valid!

+ {/if} +
+ +
+ validate('email')} /> + {#if invalid('email')} +

{errors.email}

+ {/if} + {#if valid('email')} +

Email is valid!

+ {/if} +
+
+
diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionArrayErrors.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionArrayErrors.vue new file mode 100644 index 000000000..724829dbc --- /dev/null +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionArrayErrors.vue @@ -0,0 +1,34 @@ + + + diff --git a/tests/app/server.js b/tests/app/server.js index 27c634edc..ad3cac327 100644 --- a/tests/app/server.js +++ b/tests/app/server.js @@ -950,6 +950,52 @@ app.post('/form-component/precognition', (req, res) => { }, 500) }) +app.post('/form-component/precognition-array-errors', (req, res) => { + setTimeout(() => { + const only = req.headers['precognition-validate-only'] ? req.headers['precognition-validate-only'].split(',') : [] + const name = req.body['name'] + const email = req.body['email'] + const errors = {} + + if (!name) { + errors.name = ['The name field is required.'] + } + + if (name && name.length < 3) { + errors.name = ['The name must be at least 3 characters.', 'The name contains invalid characters.'] + } + + if (!email) { + errors.email = ['The email field is required.'] + } + + if (email && !/\S+@\S+\.\S+/.test(email)) { + errors.email = ['The email must be a valid email address.', 'The email format is incorrect.'] + } + + if (only.length) { + Object.keys(errors).forEach((key) => { + if (!only.includes(key)) { + delete errors[key] + } + }) + } + + res.header('Precognition', 'true') + res.header('Vary', 'Precognition') + + if (Object.keys(errors).length) { + return res.status(422).json({ errors }) + } + + return res.status(204).header('Precognition-Success', 'true').send() + }, 500) +}) + +app.get('/form-component/precognition-array-errors', (req, res) => + inertia.render(req, res, { component: 'FormComponent/PrecognitionArrayErrors', props: {} }), +) + app.post('/form-component/precognition-files', upload.any(), (req, res) => { setTimeout(() => { console.log(req, req) diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index e338213a5..3b8109a69 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1443,6 +1443,20 @@ test.describe('Form Component', () => { await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() }) + test('shows only first error when server returns errors as array', async ({ page }) => { + await page.goto('/form-component/precognition-array-errors') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + // Should show only the first error from the array, not the second + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The name contains invalid characters.')).not.toBeVisible() + }) + test('clears validation error when field becomes valid', async ({ page }) => { await page.fill('input[name="name"]', 'ab') await page.locator('input[name="name"]').blur() From f502fddaa0acd34fa8e8dc7f02081541a50e06ea Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 7 Oct 2025 18:05:26 +0200 Subject: [PATCH 034/145] improve test --- packages/core/src/types.ts | 10 +-- .../PrecognitionBeforeValidation.tsx | 26 ++------ .../PrecognitionBeforeValidation.svelte | 36 +++++------ .../PrecognitionBeforeValidation.vue | 61 ++++++++----------- tests/form-component.spec.ts | 21 ++----- 5 files changed, 55 insertions(+), 99 deletions(-) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index aca50e76f..888419b37 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -481,17 +481,17 @@ export type FormComponentProps = Partial< validateTimeout?: number } -type OnBeforeValidationCallback = ( - newRequest: { data: RequestData; touched: string[] }, - oldRequest: { data: RequestData; touched: string[] }, -) => boolean | undefined +type RevalidatePayload = { + data: RequestData + touched: string[] +} export type FormComponentValidateOptions = { only?: string | string[] onSuccess?: () => void onError?: (errors: Errors) => void onFinish?: () => void - onBeforeValidation?: OnBeforeValidationCallback + onBeforeValidation?: (newRequest: RevalidatePayload, oldRequest: RevalidatePayload) => boolean | undefined onException?: (error: Error) => void } diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidation.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidation.tsx index fe78a31ab..778b7de4d 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidation.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidation.tsx @@ -1,31 +1,19 @@ import { Form } from '@inertiajs/react' -import { useState } from 'react' +import { isEqual } from 'lodash-es' export default function PrecognitionBeforeValidation() { - const [blocked, setBlocked] = useState(false) - const [dataCorrect, setDataCorrect] = useState(false) - const handleBeforeValidation = ( newRequest: { data: Record; touched: string[] }, oldRequest: { data: Record; touched: string[] }, ) => { - // Verify the data structure is correct - const hasNewData = typeof newRequest.data === 'object' && newRequest.data !== null - const hasNewTouched = Array.isArray(newRequest.touched) - const hasOldData = typeof oldRequest.data === 'object' && oldRequest.data !== null - const hasOldTouched = Array.isArray(oldRequest.touched) - const hasNameField = 'name' in newRequest.data - const touchedContainsName = newRequest.touched.includes('name') - - setDataCorrect(hasNewData && hasNewTouched && hasOldData && hasOldTouched && hasNameField && touchedContainsName) + const payloadIsCorrect = + isEqual(newRequest, { data: { name: 'block' }, touched: ['name'] }) && + isEqual(oldRequest, { data: {}, touched: [] }) - // Block validation if name is "block" - if (newRequest.data.name === 'block') { - setBlocked(true) + if (payloadIsCorrect && newRequest.data.name === 'block') { return false } - setBlocked(false) return true } @@ -33,7 +21,7 @@ export default function PrecognitionBeforeValidation() {

Precognition - onBeforeValidation

-
+ {({ errors, invalid, validate, validating }) => ( <>
@@ -57,8 +45,6 @@ export default function PrecognitionBeforeValidation() {
{validating &&

Validating...

} - {blocked &&

Validation blocked by onBeforeValidation

} - {dataCorrect &&

Data structure is correct

} diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionBeforeValidation.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionBeforeValidation.svelte index 44d3c1a51..39544007e 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionBeforeValidation.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionBeforeValidation.svelte @@ -1,30 +1,20 @@ @@ -32,7 +22,15 @@

Precognition - onBeforeValidation

- +
Validating...

{/if} - {#if blocked} -

Validation blocked by onBeforeValidation

- {/if} - {#if dataCorrect} -

Data structure is correct

- {/if} diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionBeforeValidation.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionBeforeValidation.vue index 2505d97e9..5a25b9f51 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionBeforeValidation.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionBeforeValidation.vue @@ -1,8 +1,33 @@ + + - - diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 3b8109a69..708b767df 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1852,26 +1852,13 @@ test.describe('Form Component', () => { test('onBeforeValidation can block validation', async ({ page }) => { await page.goto('/form-component/precognition-before-validation') - // First validate with a normal value - should work - await page.fill('input[name="name"]', 'John') - await page.locator('input[name="name"]').blur() - - await expect(page.getByText('Validating...')).toBeVisible() - await expect(page.getByText('Validating...')).not.toBeVisible() - await expect(page.getByText('Validation blocked by onBeforeValidation')).not.toBeVisible() - - // Verify data structure is correct - await expect(page.getByText('Data structure is correct')).toBeVisible() - - // Now validate with "block" - should be blocked await page.fill('input[name="name"]', 'block') await page.locator('input[name="name"]').blur() - await expect(page.getByText('Validation blocked by onBeforeValidation')).toBeVisible() - await expect(page.getByText('Validating...')).not.toBeVisible() - - // Data structure should still be correct even when blocking - await expect(page.getByText('Data structure is correct')).toBeVisible() + for (let i = 0; i < 5; i++) { + await expect(page.getByText('Validating...')).not.toBeVisible() + await page.waitForTimeout(50) + } }) test('onBeforeValidation can be passed per validate call', async ({ page }) => { From 0587acbb56495ed2bc41c6ab48f0b789b919b5ef Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 8 Oct 2025 17:33:45 +0200 Subject: [PATCH 035/145] `touched()` method --- packages/core/src/types.ts | 1 + packages/react/src/Form.ts | 9 ++++ .../Pages/FormComponent/PrecognitionTouch.tsx | 6 ++- packages/svelte/src/components/Form.svelte | 10 +++++ .../FormComponent/PrecognitionTouch.svelte | 5 +++ packages/vue3/src/form.ts | 9 ++++ .../Pages/FormComponent/PrecognitionTouch.vue | 6 ++- tests/form-component.spec.ts | 43 +++++++++++++++++++ 8 files changed, 87 insertions(+), 2 deletions(-) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 888419b37..b9724486c 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -510,6 +510,7 @@ export type FormComponentMethods = { maybeOptions?: FormComponentValidateOptions, ) => void touch: (field: string | string[]) => void + touched(field?: string): boolean } export type FormComponentonSubmitCompleteArguments = Pick diff --git a/packages/react/src/Form.ts b/packages/react/src/Form.ts index 2921d02c1..6ac5ca2bb 100644 --- a/packages/react/src/Form.ts +++ b/packages/react/src/Form.ts @@ -280,6 +280,14 @@ const Form = forwardRef( setTouched((prev) => [...new Set([...prev, ...fields])]) } + const isTouched = (field?: string): boolean => { + if (typeof field === 'string') { + return touched.includes(field) + } + + return touched.length > 0 + } + const exposed = () => ({ errors: form.errors, hasErrors: form.hasErrors, @@ -301,6 +309,7 @@ const Form = forwardRef( invalid: (field: string) => form.errors[field] !== undefined, validate, touch, + touched: isTouched, setValidationTimeout: (duration: number) => validator.setTimeout(duration), validateFiles: () => validator.validateFiles(true), }) diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionTouch.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionTouch.tsx index 2122b7b0c..9acfbde39 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionTouch.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionTouch.tsx @@ -6,7 +6,7 @@ export default () => {

Form Precognition Touch

- {({ invalid, errors, validate, touch, validating }) => ( + {({ invalid, errors, validate, touch, touched, validating }) => ( <> {validating &&

Validating...

} @@ -20,6 +20,10 @@ export default () => { {invalid('email') &&

{errors.email}

}
+

{touched('name') ? 'Name is touched' : 'Name is not touched'}

+

{touched('email') ? 'Email is touched' : 'Email is not touched'}

+

{touched() ? 'Form has touched fields' : 'Form has no touched fields'}

+ diff --git a/packages/svelte/src/components/Form.svelte b/packages/svelte/src/components/Form.svelte index f053e0b1e..d1adba604 100644 --- a/packages/svelte/src/components/Form.svelte +++ b/packages/svelte/src/components/Form.svelte @@ -263,6 +263,14 @@ touched = [...new Set([...touched, ...fields])] } + export function isTouched(field?: string): boolean { + if (typeof field === 'string') { + return touched.includes(field) + } + + return touched.length > 0 + } + export function valid(field: string): boolean { return validated.includes(field) && $form.errors[field] === undefined } @@ -302,6 +310,7 @@ // Create reactive slot props that update when state changes $: slotValid = (field: string) => validated.includes(field) && slotErrors[field] === undefined $: slotInvalid = (field: string) => slotErrors[field] !== undefined + $: slotTouched = (field?: string) => (typeof field === 'string' ? touched.includes(field) : touched.length > 0) {#if validating} @@ -33,6 +34,10 @@ {/if}
+

{touched('name') ? 'Name is touched' : 'Name is not touched'}

+

{touched('email') ? 'Email is touched' : 'Email is not touched'}

+

{touched() ? 'Form has touched fields' : 'Form has no touched fields'}

+
+

{{ touched('name') ? 'Name is touched' : 'Name is not touched' }}

+

{{ touched('email') ? 'Email is touched' : 'Email is not touched' }}

+

{{ touched() ? 'Form has touched fields' : 'Form has no touched fields' }}

+ + + + )} + + + ) +} diff --git a/packages/svelte/src/components/Form.svelte b/packages/svelte/src/components/Form.svelte index 366dab022..8038889ce 100644 --- a/packages/svelte/src/components/Form.svelte +++ b/packages/svelte/src/components/Form.svelte @@ -289,6 +289,11 @@ validator.validateFiles(true) } + export function cancelValidation() { + validator.cancelAll() + validating = false + } + onMount(() => { defaultData = getFormData() @@ -347,5 +352,6 @@ invalid={slotInvalid} {setValidationTimeout} {validateFilesEnabled} + {cancelValidation} /> diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionManualCancel.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionManualCancel.svelte new file mode 100644 index 000000000..2cfe7ca3c --- /dev/null +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionManualCancel.svelte @@ -0,0 +1,27 @@ + + +
+

Precognition - Manual Cancel

+ +
+ {#if validating} +

Validating...

+ {/if} + +
+ validate('name')} /> +
+ + + +
+
diff --git a/packages/vue3/src/form.ts b/packages/vue3/src/form.ts index 697e58706..d28376d25 100644 --- a/packages/vue3/src/form.ts +++ b/packages/vue3/src/form.ts @@ -381,6 +381,10 @@ const Form = defineComponent({ touched: isTouched, setValidationTimeout: (duration: number) => validator.setTimeout(duration), validateFiles: () => validator.validateFiles(true), + cancelValidation: () => { + validator.cancelAll() + validating.value = false + }, } expose(exposed) diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionManualCancel.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionManualCancel.vue new file mode 100644 index 000000000..0a07e6099 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionManualCancel.vue @@ -0,0 +1,25 @@ + + + diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 45753fdd9..8793c86d7 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -2020,6 +2020,24 @@ test.describe('Form Component', () => { expect(cancelledRequestError).toBe('net::ERR_ABORTED') }) + test('cancelValidation() cancels in-flight validation and resets validating state', async ({ page }) => { + await page.goto('/form-component/precognition-manual-cancel') + + requests.listenForFailed(page) + + await page.fill('#name-input', 'ab') + await page.locator('#name-input').blur() + await expect(page.getByText('Validating...')).toBeVisible() + + await page.getByText('Cancel Validation').click() + await expect(page.getByText('Validating...')).not.toBeVisible() + await page.waitForTimeout(100) + expect(requests.failed).toHaveLength(1) + + const cancelledRequestError = await requests.failed[0].failure()?.errorText + expect(cancelledRequestError).toBe('net::ERR_ABORTED') + }) + test('defaults() updates validator data as well', async ({ page }) => { await page.goto('/form-component/precognition-defaults') From 5ed51bb578d3919b1a15ae32fd3c3fe3d1e9ba96 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 9 Oct 2025 13:48:10 +0200 Subject: [PATCH 042/145] Remove redundant test --- .../PrecognitionBeforeValidationPerCall.tsx | 63 ------------------- ...PrecognitionBeforeValidationPerCall.svelte | 60 ------------------ .../PrecognitionBeforeValidationPerCall.vue | 59 ----------------- tests/form-component.spec.ts | 35 ----------- 4 files changed, 217 deletions(-) delete mode 100644 packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.tsx delete mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.svelte delete mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.vue diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.tsx deleted file mode 100644 index 3310817af..000000000 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { Form } from '@inertiajs/react' -import { useState } from 'react' - -export default function PrecognitionBeforeValidationPerCall() { - const [blockedFirst, setBlockedFirst] = useState(false) - const [blockedSecond, setBlockedSecond] = useState(false) - - const handleBeforeValidationFirst = () => { - setBlockedFirst(true) - return false - } - - const handleBeforeValidationSecond = () => { - setBlockedSecond(true) - return false - } - - return ( -
-

Precognition - onBeforeValidation Per Call

- -
- {({ validate, validating }) => ( - <> - {validating &&

Validating...

} - {blockedFirst &&

Blocked by first callback

} - {blockedSecond &&

Blocked by second callback

} - -
- -
- - {/* This button uses first callback */} - - - {/* This button uses second callback */} - - - - - )} -
-
- ) -} diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.svelte deleted file mode 100644 index f92365489..000000000 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.svelte +++ /dev/null @@ -1,60 +0,0 @@ - - -
-

Precognition - onBeforeValidation Per Call

- -
- {#if validating} -

Validating...

- {/if} - {#if blockedFirst} -

Blocked by first callback

- {/if} - {#if blockedSecond} -

Blocked by second callback

- {/if} - -
- -
- - - - - - - - -
-
diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.vue deleted file mode 100644 index d5d5fe11a..000000000 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionBeforeValidationPerCall.vue +++ /dev/null @@ -1,59 +0,0 @@ - - - diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 8793c86d7..ea5ecda35 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1932,41 +1932,6 @@ test.describe('Form Component', () => { } }) - test('onBeforeValidation can be passed per validate call', async ({ page }) => { - await page.goto('/form-component/precognition-before-validation-per-call') - - await page.fill('#name-input', 'ab') - - // Set up network listener to verify no validation requests are made - let validationRequestMade = false - page.on('request', (request) => { - if (request.url().includes('/form-component/precognition') && request.method() === 'POST') { - validationRequestMade = true - } - }) - - // First button uses first callback - should block validation - await page.click('button:has-text("Validate with First")') - - await expect(page.getByText('Blocked by first callback')).toBeVisible() - await expect(page.getByText('Blocked by second callback')).not.toBeVisible() - await expect(page.getByText('Validating...')).not.toBeVisible() - - // Wait a moment to ensure no request was made - await page.waitForTimeout(300) - expect(validationRequestMade).toBe(false) - - // Second button uses second callback - should also block validation - await page.click('button:has-text("Validate with Second")') - - await expect(page.getByText('Blocked by second callback')).toBeVisible() - await expect(page.getByText('Validating...')).not.toBeVisible() - - // Wait again to ensure no request was made - await page.waitForTimeout(300) - expect(validationRequestMade).toBe(false) - }) - test('onException handles non-422 errors during validation', async ({ page }) => { await page.goto('/form-component/precognition-exception') From d105ede1208f2698ce882b983883a03c05691e78 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 9 Oct 2025 14:22:07 +0200 Subject: [PATCH 043/145] Unify tests --- .../FormComponent/PrecognitionCallbacks.tsx | 40 ++++++++++++++++- .../FormComponent/PrecognitionException.tsx | 45 ------------------- .../PrecognitionCallbacks.svelte | 39 +++++++++++++++- .../PrecognitionException.svelte | 41 ----------------- .../FormComponent/PrecognitionCallbacks.vue | 36 ++++++++++++++- .../FormComponent/PrecognitionException.vue | 41 ----------------- tests/form-component.spec.ts | 2 +- 7 files changed, 113 insertions(+), 131 deletions(-) delete mode 100644 packages/react/test-app/Pages/FormComponent/PrecognitionException.tsx delete mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionException.svelte delete mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionException.vue diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx index bc418536b..ba6c70af4 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx @@ -5,11 +5,19 @@ export default () => { const [successCalled, setSuccessCalled] = useState(false) const [errorCalled, setErrorCalled] = useState(false) const [finishCalled, setFinishCalled] = useState(false) + const [exceptionCaught, setExceptionCaught] = useState(false) + const [exceptionMessage, setExceptionMessage] = useState('') + + const handleException = (error: Error) => { + setExceptionCaught(true) + setExceptionMessage(error.message || 'Unknown error') + } return (
-

Form Precognition Callbacks

+

Form Precognition Callbacks & Exceptions

+

Callbacks Test

{({ validate, validating, touch }) => ( <> @@ -58,6 +66,36 @@ export default () => { )}
+ +
+ +

Exception Test

+
+ {({ validate, validating }) => ( + <> + {validating &&

Validating...

} + {exceptionCaught &&

Exception caught: {exceptionMessage}

} + +
+ +
+ + {/* This will trigger a validation request to a non-existent endpoint */} + + + + + )} +
) } diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionException.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionException.tsx deleted file mode 100644 index 3f9e88551..000000000 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionException.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Form } from '@inertiajs/react' -import { useState } from 'react' - -export default function PrecognitionException() { - const [exceptionCaught, setExceptionCaught] = useState(false) - const [exceptionMessage, setExceptionMessage] = useState('') - - const handleException = (error: Error) => { - setExceptionCaught(true) - setExceptionMessage(error.message || 'Unknown error') - } - - return ( -
-

Precognition - onException

- -
- {({ validate, validating }) => ( - <> - {validating &&

Validating...

} - {exceptionCaught &&

Exception caught: {exceptionMessage}

} - -
- -
- - {/* This will trigger a validation request to a non-existent endpoint */} - - - - - )} -
-
- ) -} diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte index acd97449e..246a6268c 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte @@ -4,11 +4,19 @@ let successCalled = false let errorCalled = false let finishCalled = false + let exceptionCaught = false + let exceptionMessage = '' + + const handleException = (error: Error) => { + exceptionCaught = true + exceptionMessage = error.message || 'Unknown error' + }
-

Form Precognition Callbacks

+

Form Precognition Callbacks & Exceptions

+

Callbacks Test

{#if validating}

Validating...

@@ -61,4 +69,33 @@ Validate with onError
+ +
+ +

Exception Test

+
+ {#if validating} +

Validating...

+ {/if} + {#if exceptionCaught} +

Exception caught: {exceptionMessage}

+ {/if} + +
+ +
+ + + + + +
diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionException.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionException.svelte deleted file mode 100644 index ea3d17b14..000000000 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionException.svelte +++ /dev/null @@ -1,41 +0,0 @@ - - -
-

Precognition - onException

- -
- {#if validating} -

Validating...

- {/if} - {#if exceptionCaught} -

Exception caught: {exceptionMessage}

- {/if} - -
- -
- - - - - -
-
diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue index 3494406e9..ce2760d38 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue @@ -5,12 +5,20 @@ import { ref } from 'vue' const successCalled = ref(false) const errorCalled = ref(false) const finishCalled = ref(false) +const exceptionCaught = ref(false) +const exceptionMessage = ref('') + +const handleException = (error: Error) => { + exceptionCaught.value = true + exceptionMessage.value = error.message || 'Unknown error' +} diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionException.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionException.vue deleted file mode 100644 index a4039fe9e..000000000 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionException.vue +++ /dev/null @@ -1,41 +0,0 @@ - - - diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index ea5ecda35..343c91336 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1933,7 +1933,7 @@ test.describe('Form Component', () => { }) test('onException handles non-422 errors during validation', async ({ page }) => { - await page.goto('/form-component/precognition-exception') + await page.goto('/form-component/precognition-callbacks') await page.fill('#name-input', 'John') From 8343809f296e63be28fbfef42fdbb0504bb43858 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 9 Oct 2025 14:33:20 +0200 Subject: [PATCH 044/145] Unify tests --- .../FormComponent/PrecognitionCancel.tsx | 27 ++++++++++++++++-- .../PrecognitionManualCancel.tsx | 26 ----------------- .../FormComponent/PrecognitionCancel.svelte | 28 +++++++++++++++++-- .../PrecognitionManualCancel.svelte | 27 ------------------ .../FormComponent/PrecognitionCancel.vue | 24 ++++++++++++++-- .../PrecognitionManualCancel.vue | 25 ----------------- tests/form-component.spec.ts | 14 +++++----- 7 files changed, 79 insertions(+), 92 deletions(-) delete mode 100644 packages/react/test-app/Pages/FormComponent/PrecognitionManualCancel.tsx delete mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionManualCancel.svelte delete mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionManualCancel.vue diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionCancel.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionCancel.tsx index 3ed805956..35d685d35 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionCancel.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionCancel.tsx @@ -1,17 +1,18 @@ import { Form } from '@inertiajs/react' -export default function PrecognitionCancel() { +export default () => { return (
-

Precognition - Auto Cancel

+

Precognition - Cancel Tests

+

Auto Cancel Test

{({ invalid, errors, validate, validating }) => ( <> {validating &&

Validating...

}
- validate('name')} /> + validate('name')} /> {invalid('name') &&

{errors.name}

}
@@ -19,6 +20,26 @@ export default function PrecognitionCancel() { )}
+ +
+ +

Manual Cancel Test

+
+ {({ validate, cancelValidation, validating }) => ( + <> + {validating &&

Validating...

} + +
+ validate('name')} /> +
+ + + + + )} +
) } diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionManualCancel.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionManualCancel.tsx deleted file mode 100644 index 5624a7e80..000000000 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionManualCancel.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Form } from '@inertiajs/react' - -export default function PrecognitionManualCancel() { - return ( -
-

Precognition - Manual Cancel

- -
- {({ validate, cancelValidation, validating }) => ( - <> - {validating &&

Validating...

} - -
- validate('name')} /> -
- - - - - )} -
-
- ) -} diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionCancel.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionCancel.svelte index 046a3b3c5..8c9212503 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionCancel.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionCancel.svelte @@ -3,8 +3,9 @@
-

Precognition - Auto Cancel

+

Precognition - Cancel Tests

+

Auto Cancel Test

- validate('name')} /> + validate('name')} /> {#if invalid('name')}

{errors.name} @@ -29,4 +30,27 @@

+ +
+ +

Manual Cancel Test

+
+ {#if validating} +

Validating...

+ {/if} + +
+ validate('name')} /> +
+ + + +
diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionManualCancel.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionManualCancel.svelte deleted file mode 100644 index 2cfe7ca3c..000000000 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionManualCancel.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - -
-

Precognition - Manual Cancel

- -
- {#if validating} -

Validating...

- {/if} - -
- validate('name')} /> -
- - - -
-
diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionCancel.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionCancel.vue index 69eb3b1da..85cb7595c 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionCancel.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionCancel.vue @@ -4,8 +4,9 @@ import { Form } from '@inertiajs/vue3' diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionManualCancel.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionManualCancel.vue deleted file mode 100644 index 0a07e6099..000000000 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionManualCancel.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 343c91336..03cbcd602 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1967,13 +1967,13 @@ test.describe('Form Component', () => { requests.listenForFailed(page) requests.listenForResponses(page) - await page.fill('#name-input', 'ab') - await page.locator('#name-input').blur() + await page.fill('#auto-cancel-name-input', 'ab') + await page.locator('#auto-cancel-name-input').blur() await expect(page.getByText('Validating...')).toBeVisible() // Immediately change value and trigger new validation - should cancel the first one - await page.fill('#name-input', 'xy') - await page.locator('#name-input').blur() + await page.fill('#auto-cancel-name-input', 'xy') + await page.locator('#auto-cancel-name-input').blur() await expect(page.getByText('Validating...')).not.toBeVisible() await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() @@ -1986,12 +1986,12 @@ test.describe('Form Component', () => { }) test('cancelValidation() cancels in-flight validation and resets validating state', async ({ page }) => { - await page.goto('/form-component/precognition-manual-cancel') + await page.goto('/form-component/precognition-cancel') requests.listenForFailed(page) - await page.fill('#name-input', 'ab') - await page.locator('#name-input').blur() + await page.fill('#manual-cancel-name-input', 'ab') + await page.locator('#manual-cancel-name-input').blur() await expect(page.getByText('Validating...')).toBeVisible() await page.getByText('Cancel Validation').click() From eec5986339639b0fa228dca8ce5dbdf7b49e4c76 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 9 Oct 2025 15:03:08 +0200 Subject: [PATCH 045/145] Unify tests --- ...itionTouch.tsx => PrecognitionMethods.tsx} | 19 ++++++++- .../Pages/FormComponent/PrecognitionReset.tsx | 40 ------------------ .../FormComponent/PrecognitionValidate.tsx | 34 --------------- ...ouch.svelte => PrecognitionMethods.svelte} | 8 +++- .../FormComponent/PrecognitionReset.svelte | 42 ------------------- .../FormComponent/PrecognitionValidate.svelte | 39 ----------------- ...itionTouch.vue => PrecognitionMethods.vue} | 9 +++- .../Pages/FormComponent/PrecognitionReset.vue | 37 ---------------- .../FormComponent/PrecognitionValidate.vue | 35 ---------------- tests/form-component.spec.ts | 26 ++++++------ 10 files changed, 44 insertions(+), 245 deletions(-) rename packages/react/test-app/Pages/FormComponent/{PrecognitionTouch.tsx => PrecognitionMethods.tsx} (68%) delete mode 100644 packages/react/test-app/Pages/FormComponent/PrecognitionReset.tsx delete mode 100644 packages/react/test-app/Pages/FormComponent/PrecognitionValidate.tsx rename packages/svelte/test-app/Pages/FormComponent/{PrecognitionTouch.svelte => PrecognitionMethods.svelte} (72%) delete mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionReset.svelte delete mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionValidate.svelte rename packages/vue3/test-app/Pages/FormComponent/{PrecognitionTouch.vue => PrecognitionMethods.vue} (74%) delete mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionReset.vue delete mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionValidate.vue diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionTouch.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx similarity index 68% rename from packages/react/test-app/Pages/FormComponent/PrecognitionTouch.tsx rename to packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx index 9acfbde39..06c294596 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionTouch.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx @@ -3,10 +3,10 @@ import { Form } from '@inertiajs/react' export default () => { return (
-

Form Precognition Touch

+

Form Precognition - Touch, Reset & Validate

- {({ invalid, errors, validate, touch, touched, validating }) => ( + {({ invalid, errors, validate, touch, touched, validating, reset }) => ( <> {validating &&

Validating...

} @@ -27,6 +27,12 @@ export default () => { + + @@ -39,6 +45,15 @@ export default () => { > Touch Name Twice + + + )}
diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionReset.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionReset.tsx deleted file mode 100644 index 50a267fe3..000000000 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionReset.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Form } from '@inertiajs/react' - -export default () => { - return ( -
-

Form Precognition Reset

- -
- {({ invalid, errors, validate, touch, validating, reset }) => ( - <> - {validating &&

Validating...

} - -
- touch('name')} /> - {invalid('name') &&

{errors.name}

} -
- -
- touch('email')} /> - {invalid('email') &&

{errors.email}

} -
- - - - - - - )} -
-
- ) -} diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionValidate.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionValidate.tsx deleted file mode 100644 index ae7c47070..000000000 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionValidate.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Form } from '@inertiajs/react' - -export default () => { - return ( -
-

Form Precognition Validate

- -
- {({ invalid, errors, validate, touch, validating }) => ( - <> - {validating &&

Validating...

} - -
- touch('name')} /> - {invalid('name') &&

{errors.name}

} -
- -
- - {invalid('email') &&

{errors.email}

} -
- - - - - )} -
-
- ) -} diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionTouch.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionMethods.svelte similarity index 72% rename from packages/svelte/test-app/Pages/FormComponent/PrecognitionTouch.svelte rename to packages/svelte/test-app/Pages/FormComponent/PrecognitionMethods.svelte index a30e3850a..bc2f91a24 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionTouch.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionMethods.svelte @@ -3,7 +3,7 @@
-

Form Precognition Touch

+

Form Precognition - Touch, Reset & Validate

{#if validating}

Validating...

@@ -39,6 +40,8 @@

{touched() ? 'Form has touched fields' : 'Form has no touched fields'}

+ + + + +
diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionReset.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionReset.svelte deleted file mode 100644 index 89b6dbdc0..000000000 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionReset.svelte +++ /dev/null @@ -1,42 +0,0 @@ - - -
-

Form Precognition Reset

- -
- {#if validating} -

Validating...

- {/if} - -
- touch('name')} /> - {#if invalid('name')} -

{errors.name}

- {/if} -
- -
- touch('email')} /> - {#if invalid('email')} -

{errors.email}

- {/if} -
- - - - - -
-
diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionValidate.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionValidate.svelte deleted file mode 100644 index 69f4a7c44..000000000 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionValidate.svelte +++ /dev/null @@ -1,39 +0,0 @@ - - -
-

Form Precognition Validate

- -
- {#if validating} -

Validating...

- {/if} - -
- touch('name')} /> - {#if invalid('name')} -

{errors.name}

- {/if} -
- -
- - {#if invalid('email')} -

{errors.email}

- {/if} -
- - - -
-
diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionMethods.vue similarity index 74% rename from packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue rename to packages/vue3/test-app/Pages/FormComponent/PrecognitionMethods.vue index dd77870af..7e8bf30f5 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionTouch.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionMethods.vue @@ -4,13 +4,13 @@ import { Form } from '@inertiajs/vue3' diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionReset.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionReset.vue deleted file mode 100644 index 472569b1b..000000000 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionReset.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionValidate.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionValidate.vue deleted file mode 100644 index 0398592ee..000000000 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionValidate.vue +++ /dev/null @@ -1,35 +0,0 @@ - - - diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 03cbcd602..af20817ee 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1621,7 +1621,7 @@ test.describe('Form Component', () => { }) test('validates all touched fields when calling validate() without arguments', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-methods') await page.fill('input[name="name"]', 'ab') await page.locator('input[name="name"]').blur() @@ -1643,7 +1643,7 @@ test.describe('Form Component', () => { }) test('reset all fields clears all touched fields', async ({ page }) => { - await page.goto('/form-component/precognition-reset') + await page.goto('/form-component/precognition-methods') await page.fill('input[name="name"]', 'ab') await page.locator('input[name="name"]').blur() @@ -1662,7 +1662,7 @@ test.describe('Form Component', () => { }) test('reset specific fields removes only those fields from touched', async ({ page }) => { - await page.goto('/form-component/precognition-reset') + await page.goto('/form-component/precognition-methods') await page.fill('input[name="name"]', 'ab') await page.locator('input[name="name"]').blur() @@ -1690,7 +1690,7 @@ test.describe('Form Component', () => { }) test('touch with array marks multiple fields as touched', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-methods') await page.fill('input[name="name"]', 'ab') await page.fill('input[name="email"]', 'x') @@ -1706,7 +1706,7 @@ test.describe('Form Component', () => { }) test('touch deduplicates fields when called multiple times', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-methods') await page.fill('input[name="name"]', 'ab') @@ -1721,7 +1721,7 @@ test.describe('Form Component', () => { }) test('touched() returns false when no fields are touched', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-methods') await expect(page.getByTestId('any-touched')).toHaveText('Form has no touched fields') await expect(page.getByTestId('name-touched')).toHaveText('Name is not touched') @@ -1729,7 +1729,7 @@ test.describe('Form Component', () => { }) test('touched(field) returns true when specific field is touched', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-methods') await page.locator('input[name="name"]').focus() await page.locator('input[name="name"]').blur() @@ -1740,7 +1740,7 @@ test.describe('Form Component', () => { }) test('touched() returns true when any field is touched', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-methods') await page.locator('input[name="email"]').focus() await page.locator('input[name="email"]').blur() @@ -1751,7 +1751,7 @@ test.describe('Form Component', () => { }) test('touched() updates when multiple fields are touched', async ({ page }) => { - await page.goto('/form-component/precognition-touch') + await page.goto('/form-component/precognition-methods') await page.locator('input[name="name"]').focus() await page.locator('input[name="name"]').blur() @@ -1764,7 +1764,7 @@ test.describe('Form Component', () => { }) test('validate with specific field works independently of touched state', async ({ page }) => { - await page.goto('/form-component/precognition-validate') + await page.goto('/form-component/precognition-methods') await page.fill('input[name="name"]', 'ab') await page.fill('input[name="email"]', 'x') @@ -1779,7 +1779,7 @@ test.describe('Form Component', () => { }) test('validate with array of fields validates multiple fields', async ({ page }) => { - await page.goto('/form-component/precognition-validate') + await page.goto('/form-component/precognition-methods') await page.fill('input[name="name"]', 'ab') await page.fill('input[name="email"]', 'x') @@ -1794,7 +1794,7 @@ test.describe('Form Component', () => { }) test('reset with array removes multiple fields from touched', async ({ page }) => { - await page.goto('/form-component/precognition-reset') + await page.goto('/form-component/precognition-methods') await page.fill('input[name="name"]', 'ab') await page.locator('input[name="name"]').blur() @@ -1824,7 +1824,7 @@ test.describe('Form Component', () => { }) test('touching one field and validating another does not validate the touched field', async ({ page }) => { - await page.goto('/form-component/precognition-validate') + await page.goto('/form-component/precognition-methods') await page.fill('input[name="name"]', 'ab') await page.locator('input[name="name"]').blur() From a98ecb4258202dc946f63b21ef8460c11ef67060 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 14 Oct 2025 12:01:21 +0200 Subject: [PATCH 046/145] Refine test suite --- .../Pages/FormComponent/Precognition.tsx | 8 ++--- .../FormComponent/PrecognitionAllErrors.tsx | 16 +++++----- .../FormComponent/PrecognitionArrayErrors.tsx | 8 ++--- .../FormComponent/PrecognitionCallbacks.tsx | 16 +++++----- .../FormComponent/PrecognitionCancel.tsx | 12 +++---- .../FormComponent/PrecognitionDefaults.tsx | 6 ++-- .../Pages/FormComponent/PrecognitionFiles.tsx | 6 ++-- .../FormComponent/PrecognitionHeaders.tsx | 6 ++-- .../FormComponent/PrecognitionMethods.tsx | 14 ++++---- .../FormComponent/PrecognitionTransform.tsx | 6 ++-- .../Pages/FormComponent/Precognition.svelte | 12 +++---- .../PrecognitionAllErrors.svelte | 20 ++++++------ .../PrecognitionArrayErrors.svelte | 12 +++---- .../PrecognitionCallbacks.svelte | 16 +++++----- .../FormComponent/PrecognitionCancel.svelte | 18 +++++------ .../FormComponent/PrecognitionDefaults.svelte | 10 +++--- .../FormComponent/PrecognitionFiles.svelte | 10 +++--- .../FormComponent/PrecognitionHeaders.svelte | 10 +++--- .../FormComponent/PrecognitionMethods.svelte | 18 +++++------ .../PrecognitionTransform.svelte | 10 +++--- .../Pages/FormComponent/Precognition.vue | 8 ++--- .../FormComponent/PrecognitionAllErrors.vue | 16 +++++----- .../FormComponent/PrecognitionArrayErrors.vue | 8 ++--- .../FormComponent/PrecognitionCallbacks.vue | 16 +++++----- .../FormComponent/PrecognitionCancel.vue | 12 +++---- .../FormComponent/PrecognitionDefaults.vue | 6 ++-- .../Pages/FormComponent/PrecognitionFiles.vue | 6 ++-- .../FormComponent/PrecognitionHeaders.vue | 6 ++-- .../FormComponent/PrecognitionMethods.vue | 14 ++++---- .../FormComponent/PrecognitionTransform.vue | 6 ++-- tests/form-component.spec.ts | 32 +++++++++---------- 31 files changed, 182 insertions(+), 182 deletions(-) diff --git a/packages/react/test-app/Pages/FormComponent/Precognition.tsx b/packages/react/test-app/Pages/FormComponent/Precognition.tsx index 845aecd63..2ff56745b 100644 --- a/packages/react/test-app/Pages/FormComponent/Precognition.tsx +++ b/packages/react/test-app/Pages/FormComponent/Precognition.tsx @@ -8,19 +8,19 @@ export default () => {
{({ invalid, errors, validate, valid, validating }) => ( <> - {validating &&

Validating...

} -
- validate('name')} /> + validate('name')} /> {invalid('name') &&

{errors.name}

} {valid('name') &&

Name is valid!

}
- validate('email')} /> + validate('email')} /> {invalid('email') &&

{errors.email}

} {valid('email') &&

Email is valid!

}
+ + {validating &&

Validating...

} )}
diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionAllErrors.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionAllErrors.tsx index a0be71ede..4b63a3df7 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionAllErrors.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionAllErrors.tsx @@ -13,20 +13,18 @@ export default () => { > {({ invalid, errors, validate, valid, validating }) => ( <> - {validating &&

Validating...

} -
- validate('name')} /> + validate('name')} /> {invalid('name') && (
{Array.isArray(errors.name) ? ( errors.name.map((error, index) => ( -

+

{error}

)) ) : ( -

{errors.name}

+

{errors.name}

)}
)} @@ -34,22 +32,24 @@ export default () => {
- validate('email')} /> + validate('email')} /> {invalid('email') && (
{Array.isArray(errors.email) ? ( errors.email.map((error, index) => ( -

+

{error}

)) ) : ( -

{errors.email}

+

{errors.email}

)}
)} {valid('email') &&

Email is valid!

}
+ + {validating &&

Validating...

} )} diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionArrayErrors.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionArrayErrors.tsx index d9f35c491..a1a4ffe79 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionArrayErrors.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionArrayErrors.tsx @@ -8,19 +8,19 @@ export default () => {
{({ invalid, errors, validate, valid, validating }) => ( <> - {validating &&

Validating...

} -
- validate('name')} /> + validate('name')} /> {invalid('name') &&

{errors.name}

} {valid('name') &&

Name is valid!

}
- validate('email')} /> + validate('email')} /> {invalid('email') &&

{errors.email}

} {valid('email') &&

Email is valid!

}
+ + {validating &&

Validating...

} )}
diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx index ba6c70af4..b2e5e583a 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx @@ -21,15 +21,15 @@ export default () => {
{({ validate, validating, touch }) => ( <> +
+ touch('name')} /> +
+ {validating &&

Validating...

} {successCalled &&

onSuccess called!

} {errorCalled &&

onError called!

} {finishCalled &&

onFinish called!

} -
- touch('name')} /> -
- )} @@ -27,12 +27,12 @@ export default () => { {({ validate, cancelValidation, validating }) => ( <> - {validating &&

Validating...

} -
- validate('name')} /> + validate('name')} />
+ {validating &&

Validating...

} + diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx index a610c96ad..0333b43cb 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx @@ -15,13 +15,13 @@ export default function PrecognitionDefaults() { {({ invalid, errors, validate, validating }) => ( <> - {validating &&

Validating...

} -
- + {invalid('name') &&

{errors.name}

}
+ {validating &&

Validating...

} + diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionFiles.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionFiles.tsx index db7db4b46..2265275c8 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionFiles.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionFiles.tsx @@ -16,10 +16,8 @@ export default () => { > {({ invalid, errors, validate, valid, validating, touch }) => ( <> - {validating &&

Validating...

} -
- validate('name')} /> + validate('name')} /> {invalid('name') &&

{errors.name}

} {valid('name') &&

Name is valid!

}
@@ -30,6 +28,8 @@ export default () => { {valid('avatar') &&

Avatar is valid!

}
+ {validating &&

Validating...

} + diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionHeaders.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionHeaders.tsx index 931fd6231..edbd99d9f 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionHeaders.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionHeaders.tsx @@ -13,13 +13,13 @@ export default function PrecognitionHeaders() { > {({ invalid, errors, validate, validating }) => ( <> - {validating &&

Validating...

} -
- validate('name')} /> + validate('name')} /> {invalid('name') &&

{errors.name}

}
+ {validating &&

Validating...

} + )} diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx index 06c294596..3fb5fdca3 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx @@ -8,21 +8,21 @@ export default () => { {({ invalid, errors, validate, touch, touched, validating, reset }) => ( <> - {validating &&

Validating...

} -
- touch('name')} /> + touch('name')} /> {invalid('name') &&

{errors.name}

}
- touch('email')} /> + touch('email')} /> {invalid('email') &&

{errors.email}

}
-

{touched('name') ? 'Name is touched' : 'Name is not touched'}

-

{touched('email') ? 'Email is touched' : 'Email is not touched'}

-

{touched() ? 'Form has touched fields' : 'Form has no touched fields'}

+ {validating &&

Validating...

} + +

{touched('name') ? 'Name is touched' : 'Name is not touched'}

+

{touched('email') ? 'Email is touched' : 'Email is not touched'}

+

{touched() ? 'Form has touched fields' : 'Form has no touched fields'}

@@ -42,14 +42,14 @@ let:cancelValidation let:validating > +
+ validate('name')} /> +
+ {#if validating}

Validating...

{/if} -
- validate('name')} /> -
- diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionDefaults.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionDefaults.svelte index 2a2cfd3b7..31475a453 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionDefaults.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionDefaults.svelte @@ -21,12 +21,8 @@ let:validate let:validating > - {#if validating} -

Validating...

- {/if} -
- + {#if invalid('name')}

{errors.name} @@ -34,6 +30,10 @@ {/if}

+ {#if validating} +

Validating...

+ {/if} + diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionFiles.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionFiles.svelte index fa6569d63..7c9e8bfa7 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionFiles.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionFiles.svelte @@ -19,12 +19,8 @@ let:validating let:touch > - {#if validating} -

Validating...

- {/if} -
- validate('name')} /> + validate('name')} /> {#if invalid('name')}

{errors.name}

{/if} @@ -43,6 +39,10 @@ {/if}
+ {#if validating} +

Validating...

+ {/if} + diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionHeaders.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionHeaders.svelte index 6fb67a051..ada432b86 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionHeaders.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionHeaders.svelte @@ -15,12 +15,8 @@ let:validate let:validating > - {#if validating} -

Validating...

- {/if} -
- validate('name')} /> + validate('name')} /> {#if invalid('name')}

{errors.name} @@ -28,6 +24,10 @@ {/if}

+ {#if validating} +

Validating...

+ {/if} + diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionMethods.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionMethods.svelte index bc2f91a24..199a121e8 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionMethods.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionMethods.svelte @@ -17,27 +17,27 @@ let:validating let:reset > - {#if validating} -

Validating...

- {/if} -
- touch('name')} /> + touch('name')} /> {#if invalid('name')}

{errors.name}

{/if}
- touch('email')} /> + touch('email')} /> {#if invalid('email')}

{errors.email}

{/if}
-

{touched('name') ? 'Name is touched' : 'Name is not touched'}

-

{touched('email') ? 'Email is touched' : 'Email is not touched'}

-

{touched() ? 'Form has touched fields' : 'Form has no touched fields'}

+ {#if validating} +

Validating...

+ {/if} + +

{touched('name') ? 'Name is touched' : 'Name is not touched'}

+

{touched('email') ? 'Email is touched' : 'Email is not touched'}

+

{touched() ? 'Form has touched fields' : 'Form has no touched fields'}

diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte index 265f17308..6dc294178 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionTransform.svelte @@ -16,12 +16,8 @@ let:valid let:validating > - {#if validating} -

Validating...

- {/if} -
- validate('name')} /> + validate('name')} /> {#if invalid('name')}

{errors.name}

{/if} @@ -29,5 +25,9 @@

Name is valid!

{/if}
+ + {#if validating} +

Validating...

+ {/if} diff --git a/packages/vue3/test-app/Pages/FormComponent/Precognition.vue b/packages/vue3/test-app/Pages/FormComponent/Precognition.vue index 32aabe1a5..ce7ae4213 100644 --- a/packages/vue3/test-app/Pages/FormComponent/Precognition.vue +++ b/packages/vue3/test-app/Pages/FormComponent/Precognition.vue @@ -12,10 +12,8 @@ import { Form } from '@inertiajs/vue3' :validate-timeout="100" #default="{ invalid, errors, validate, valid, validating }" > -

Validating...

-
- +

{{ errors.name }}

@@ -23,12 +21,14 @@ import { Form } from '@inertiajs/vue3'
- +

{{ errors.email }}

Email is valid!

+ +

Validating...

diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionAllErrors.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionAllErrors.vue index b88737c29..9e4519de0 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionAllErrors.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionAllErrors.vue @@ -13,33 +13,33 @@ import { Form } from '@inertiajs/vue3' :simple-validation-errors="false" #default="{ invalid, errors, validate, valid, validating }" > -

Validating...

-
- +
-

{{ errors.name }}

+

{{ errors.name }}

Name is valid!

- +
-

{{ errors.email }}

+

{{ errors.email }}

Email is valid!

+ +

Validating...

diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionArrayErrors.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionArrayErrors.vue index 724829dbc..559d650a2 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionArrayErrors.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionArrayErrors.vue @@ -12,10 +12,8 @@ import { Form } from '@inertiajs/vue3' :validate-timeout="100" #default="{ invalid, errors, validate, valid, validating }" > -

Validating...

-
- +

{{ errors.name }}

@@ -23,12 +21,14 @@ import { Form } from '@inertiajs/vue3'
- +

{{ errors.email }}

Email is valid!

+ +

Validating...

diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue index ce2760d38..33fe56981 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue @@ -21,15 +21,15 @@ const handleException = (error: Error) => {

Callbacks Test

diff --git a/packages/vue3/test-app/package.json b/packages/vue3/test-app/package.json index 754e96752..d860eafcc 100755 --- a/packages/vue3/test-app/package.json +++ b/packages/vue3/test-app/package.json @@ -5,12 +5,12 @@ "type-check": "vue-tsc --noEmit" }, "devDependencies": { - "@vitejs/plugin-vue": "^5.0.5", - "nodemon": "^3.0.0", - "typescript": "^5.9.2", - "vite": "^6.3.0", - "vue": "^3.4.33", - "vue-tsc": "^2.2.4" + "@vitejs/plugin-vue": "^5.2.4", + "nodemon": "^3.1.10", + "typescript": "^5.9.3", + "vite": "^6.4.1", + "vue": "^3.5.22", + "vue-tsc": "^2.2.12" }, "dependencies": { "@inertiajs/core": "workspace:*", diff --git a/playgrounds/react/package.json b/playgrounds/react/package.json index 1f7b6d555..11abf6d94 100644 --- a/playgrounds/react/package.json +++ b/playgrounds/react/package.json @@ -9,20 +9,20 @@ "devDependencies": { "@inertiajs/react": "workspace:*", "@laravel/stream-react": "^0.3.9", - "@tailwindcss/typography": "^0.5.18", - "@tailwindcss/vite": "^4.1.13", - "@types/react": "^19.1.13", - "@types/react-dom": "^19.1.9", + "@tailwindcss/typography": "^0.5.19", + "@tailwindcss/vite": "^4.1.16", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", "@vitejs/plugin-react": "^4.7.0", "autosize": "^6.0.1", - "axios": "^1.12.2", + "axios": "^1.13.1", "laravel-vite-plugin": "^1.3.0", "lodash": "^4.17.21", - "marked": "^16.3.0", - "react": "^19.1.1", - "react-dom": "^19.1.1", - "tailwindcss": "^4.1.13", + "marked": "^16.4.1", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "tailwindcss": "^4.1.16", "typescript": "^4.9.5", - "vite": "^6.3.6" + "vite": "^6.4.1" } } diff --git a/playgrounds/svelte4/package.json b/playgrounds/svelte4/package.json index 8def422a7..7e3cbded9 100644 --- a/playgrounds/svelte4/package.json +++ b/playgrounds/svelte4/package.json @@ -11,15 +11,15 @@ "devDependencies": { "@inertiajs/svelte": "workspace:*", "@sveltejs/vite-plugin-svelte": "^3.1.2", - "@tailwindcss/vite": "^4.1.13", + "@tailwindcss/vite": "^4.1.16", "@tsconfig/svelte": "^5.0.5", - "axios": "^1.12.2", + "axios": "^1.13.1", "laravel-vite-plugin": "^1.3.0", "lodash": "^4.17.21", "svelte": "^4.2.20", - "svelte-check": "^4.3.2", - "tailwindcss": "^4.1.13", - "typescript": "^5.9.2", - "vite": "^5.4.20" + "svelte-check": "^4.3.3", + "tailwindcss": "^4.1.16", + "typescript": "^5.9.3", + "vite": "^5.4.21" } } diff --git a/playgrounds/svelte5/package.json b/playgrounds/svelte5/package.json index 8a54a148c..e899d6244 100644 --- a/playgrounds/svelte5/package.json +++ b/playgrounds/svelte5/package.json @@ -11,15 +11,15 @@ "devDependencies": { "@inertiajs/svelte": "workspace:*", "@sveltejs/vite-plugin-svelte": "^5.1.1", - "@tailwindcss/vite": "^4.1.13", + "@tailwindcss/vite": "^4.1.16", "@tsconfig/svelte": "^5.0.5", - "axios": "^1.12.2", + "axios": "^1.13.1", "laravel-vite-plugin": "^1.3.0", "lodash": "^4.17.21", - "svelte": "^5.39.5", - "svelte-check": "^4.3.2", - "tailwindcss": "^4.1.13", - "typescript": "^5.9.2", - "vite": "^6.3.6" + "svelte": "^5.43.0", + "svelte-check": "^4.3.3", + "tailwindcss": "^4.1.16", + "typescript": "^5.9.3", + "vite": "^6.4.1" } } diff --git a/playgrounds/vue3/package.json b/playgrounds/vue3/package.json index e089cc932..e1a83d8f7 100644 --- a/playgrounds/vue3/package.json +++ b/playgrounds/vue3/package.json @@ -8,19 +8,19 @@ "devDependencies": { "@inertiajs/vue3": "workspace:*", "@laravel/stream-vue": "^0.3.9", - "@tailwindcss/typography": "^0.5.18", - "@tailwindcss/vite": "^4.1.13", + "@tailwindcss/typography": "^0.5.19", + "@tailwindcss/vite": "^4.1.16", "@vitejs/plugin-vue": "^5.2.4", - "@vue/server-renderer": "^3.5.21", + "@vue/server-renderer": "^3.5.22", "autosize": "^6.0.1", - "axios": "^1.12.2", + "axios": "^1.13.1", "laravel-vite-plugin": "^1.3.0", "lodash": "^4.17.21", - "marked": "^16.3.0", - "tailwindcss": "^4.1.13", - "typescript": "^5.9.2", - "vite": "^6.3.6", - "vue": "^3.5.21", + "marked": "^16.4.1", + "tailwindcss": "^4.1.16", + "typescript": "^5.9.3", + "vite": "^6.4.1", + "vue": "^3.5.22", "vue-tsc": "^2.2.12" }, "type": "module" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index db148aac0..cd2e1d4c7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,24 +9,24 @@ importers: .: dependencies: '@playwright/test': - specifier: ^1.55.1 - version: 1.55.1 + specifier: ^1.56.1 + version: 1.56.1 prettier: specifier: ^3.6.2 version: 3.6.2 prettier-plugin-organize-imports: specifier: ^4.3.0 - version: 4.3.0(prettier@3.6.2)(typescript@5.9.2)(vue-tsc@2.2.12(typescript@5.9.2)) + version: 4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)) prettier-plugin-svelte: specifier: ^3.4.0 - version: 3.4.0(prettier@3.6.2)(svelte@5.39.5) + version: 3.4.0(prettier@3.6.2)(svelte@5.43.0) prettier-plugin-tailwindcss: specifier: ^0.6.14 - version: 0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.2)(vue-tsc@2.2.12(typescript@5.9.2)))(prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.39.5))(prettier@3.6.2) + version: 0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)))(prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.43.0))(prettier@3.6.2) optionalDependencies: '@rollup/rollup-linux-x64-gnu': - specifier: ^4.52.2 - version: 4.52.2 + specifier: ^4.52.5 + version: 4.52.5 packages/core: dependencies: @@ -34,8 +34,8 @@ importers: specifier: ^4.17.12 version: 4.17.12 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 lodash-es: specifier: ^4.17.21 version: 4.17.21 @@ -47,8 +47,8 @@ importers: specifier: ^2.2.3 version: 2.2.3 '@types/node': - specifier: ^18.19.127 - version: 18.19.127 + specifier: ^18.19.130 + version: 18.19.130 '@types/nprogress': specifier: ^0.2.3 version: 0.2.3 @@ -56,17 +56,20 @@ importers: specifier: ^6.14.0 version: 6.14.0 es-check: - specifier: ^9.3.1 - version: 9.3.1 + specifier: ^9.4.4 + version: 9.4.4 esbuild: - specifier: ^0.25.10 - version: 0.25.10 + specifier: ^0.25.11 + version: 0.25.11 esbuild-node-externals: specifier: ^1.18.0 - version: 1.18.0(esbuild@0.25.10) + version: 1.18.0(esbuild@0.25.11) + laravel-precognition: + specifier: ^0.7.3 + version: 0.7.3 typescript: - specifier: ^5.9.2 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 packages/react: dependencies: @@ -76,34 +79,37 @@ importers: '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 + laravel-precognition: + specifier: ^0.7.3 + version: 0.7.3 lodash-es: specifier: ^4.17.21 version: 4.17.21 devDependencies: '@types/react': - specifier: ^19.1.13 - version: 19.1.13 + specifier: ^19.2.2 + version: 19.2.2 '@types/react-dom': - specifier: ^19.1.9 - version: 19.1.9(@types/react@19.1.13) + specifier: ^19.2.2 + version: 19.2.2(@types/react@19.2.2) axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 es-check: - specifier: ^9.3.1 - version: 9.3.1 + specifier: ^9.4.4 + version: 9.4.4 esbuild: - specifier: ^0.25.10 - version: 0.25.10 + specifier: ^0.25.11 + version: 0.25.11 esbuild-node-externals: specifier: ^1.18.0 - version: 1.18.0(esbuild@0.25.10) + version: 1.18.0(esbuild@0.25.11) react: - specifier: ^19.1.1 - version: 19.1.1 + specifier: ^19.2.0 + version: 19.2.0 typescript: - specifier: ^5.9.2 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 packages/react/test-app: dependencies: @@ -114,33 +120,33 @@ importers: specifier: workspace:* version: link:.. '@vitejs/plugin-react': - specifier: ^4.3.1 - version: 4.7.0(vite@6.3.6(@types/node@24.3.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) + specifier: ^4.7.0 + version: 4.7.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) react: - specifier: ^19.0.0 - version: 19.1.1 + specifier: ^19.2.0 + version: 19.2.0 react-dom: - specifier: ^19.0.0 - version: 19.1.1(react@19.1.1) + specifier: ^19.2.0 + version: 19.2.0(react@19.2.0) devDependencies: '@types/node': - specifier: ^24.1.0 - version: 24.3.2 + specifier: ^24.9.2 + version: 24.9.2 '@types/react': - specifier: ^19.1.9 - version: 19.1.13 + specifier: ^19.2.2 + version: 19.2.2 '@types/react-dom': - specifier: ^19.1.7 - version: 19.1.9(@types/react@19.1.13) + specifier: ^19.2.2 + version: 19.2.2(@types/react@19.2.2) nodemon: - specifier: ^3.0.0 + specifier: ^3.1.10 version: 3.1.10 typescript: - specifier: ^5.9.2 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 vite: - specifier: ^6.3.0 - version: 6.3.6(@types/node@24.3.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) + specifier: ^6.4.1 + version: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) packages/svelte: dependencies: @@ -150,28 +156,31 @@ importers: '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 + laravel-precognition: + specifier: ^0.7.3 + version: 0.7.3 lodash-es: specifier: ^4.17.21 version: 4.17.21 devDependencies: '@sveltejs/adapter-auto': specifier: ^3.3.1 - version: 3.3.1(@sveltejs/kit@2.43.2(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0))) + version: 3.3.1(@sveltejs/kit@2.48.3(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0))) '@sveltejs/kit': - specifier: ^2.43.2 - version: 2.43.2(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) + specifier: ^2.48.3 + version: 2.48.3(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) '@sveltejs/package': specifier: ^2.5.4 - version: 2.5.4(svelte@4.2.20)(typescript@5.9.2) + version: 2.5.4(svelte@4.2.20)(typescript@5.9.3) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) + version: 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 es-check: - specifier: ^9.3.1 - version: 9.3.1 + specifier: ^9.4.4 + version: 9.4.4 publint: specifier: ^0.2.12 version: 0.2.12 @@ -179,17 +188,17 @@ importers: specifier: ^4.2.20 version: 4.2.20 svelte-check: - specifier: ^4.3.2 - version: 4.3.2(picomatch@4.0.3)(svelte@4.2.20)(typescript@5.9.2) + specifier: ^4.3.3 + version: 4.3.3(picomatch@4.0.3)(svelte@4.2.20)(typescript@5.9.3) tslib: specifier: ^2.8.1 version: 2.8.1 typescript: - specifier: ^5.9.2 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 vite: - specifier: ^5.4.20 - version: 5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0) + specifier: ^5.4.21 + version: 5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0) packages/svelte/test-app: dependencies: @@ -202,25 +211,25 @@ importers: devDependencies: '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) + version: 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) '@tsconfig/svelte': - specifier: ^5.0.4 + specifier: ^5.0.5 version: 5.0.5 nodemon: - specifier: ^3.0.0 + specifier: ^3.1.10 version: 3.1.10 svelte: - specifier: ^4.2.14 + specifier: ^4.2.20 version: 4.2.20 svelte-check: - specifier: ^4.1.0 - version: 4.3.1(picomatch@4.0.3)(svelte@4.2.20)(typescript@5.9.2) + specifier: ^4.3.3 + version: 4.3.3(picomatch@4.0.3)(svelte@4.2.20)(typescript@5.9.3) typescript: - specifier: ^5.9.2 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 vite: - specifier: ^5.4.20 - version: 5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0) + specifier: ^5.4.21 + version: 5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0) packages/vue3: dependencies: @@ -230,31 +239,34 @@ importers: '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 + laravel-precognition: + specifier: ^0.7.3 + version: 0.7.3 lodash-es: specifier: ^4.17.21 version: 4.17.21 devDependencies: '@types/node': - specifier: ^22.18.6 - version: 22.18.6 + specifier: ^22.18.13 + version: 22.18.13 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 es-check: - specifier: ^9.3.1 - version: 9.3.1 + specifier: ^9.4.4 + version: 9.4.4 esbuild: - specifier: ^0.25.10 - version: 0.25.10 + specifier: ^0.25.11 + version: 0.25.11 esbuild-node-externals: specifier: ^1.18.0 - version: 1.18.0(esbuild@0.25.10) + version: 1.18.0(esbuild@0.25.11) typescript: - specifier: ^5.9.2 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 vue: - specifier: ^3.5.21 - version: 3.5.21(typescript@5.9.2) + specifier: ^3.5.22 + version: 3.5.22(typescript@5.9.3) packages/vue3/test-app: dependencies: @@ -266,23 +278,23 @@ importers: version: link:.. devDependencies: '@vitejs/plugin-vue': - specifier: ^5.0.5 - version: 5.2.4(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0))(vue@3.5.21(typescript@5.9.2)) + specifier: ^5.2.4 + version: 5.2.4(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))(vue@3.5.22(typescript@5.9.3)) nodemon: - specifier: ^3.0.0 + specifier: ^3.1.10 version: 3.1.10 typescript: - specifier: ^5.9.2 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 vite: - specifier: ^6.3.0 - version: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) + specifier: ^6.4.1 + version: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) vue: - specifier: ^3.4.33 - version: 3.5.21(typescript@5.9.2) + specifier: ^3.5.22 + version: 3.5.22(typescript@5.9.3) vue-tsc: - specifier: ^2.2.4 - version: 2.2.12(typescript@5.9.2) + specifier: ^2.2.12 + version: 2.2.12(typescript@5.9.3) playgrounds/react: devDependencies: @@ -291,52 +303,52 @@ importers: version: link:../../packages/react '@laravel/stream-react': specifier: ^0.3.9 - version: 0.3.9(react@19.1.1) + version: 0.3.9(react@19.2.0) '@tailwindcss/typography': - specifier: ^0.5.18 - version: 0.5.18(tailwindcss@4.1.13) + specifier: ^0.5.19 + version: 0.5.19(tailwindcss@4.1.16) '@tailwindcss/vite': - specifier: ^4.1.13 - version: 4.1.13(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) + specifier: ^4.1.16 + version: 4.1.16(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) '@types/react': - specifier: ^19.1.13 - version: 19.1.13 + specifier: ^19.2.2 + version: 19.2.2 '@types/react-dom': - specifier: ^19.1.9 - version: 19.1.9(@types/react@19.1.13) + specifier: ^19.2.2 + version: 19.2.2(@types/react@19.2.2) '@vitejs/plugin-react': specifier: ^4.7.0 - version: 4.7.0(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) + version: 4.7.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) autosize: specifier: ^6.0.1 version: 6.0.1 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 laravel-vite-plugin: specifier: ^1.3.0 - version: 1.3.0(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) + version: 1.3.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) lodash: specifier: ^4.17.21 version: 4.17.21 marked: - specifier: ^16.3.0 - version: 16.3.0 + specifier: ^16.4.1 + version: 16.4.1 react: - specifier: ^19.1.1 - version: 19.1.1 + specifier: ^19.2.0 + version: 19.2.0 react-dom: - specifier: ^19.1.1 - version: 19.1.1(react@19.1.1) + specifier: ^19.2.0 + version: 19.2.0(react@19.2.0) tailwindcss: - specifier: ^4.1.13 - version: 4.1.13 + specifier: ^4.1.16 + version: 4.1.16 typescript: specifier: ^4.9.5 version: 4.9.5 vite: - specifier: ^6.3.6 - version: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) + specifier: ^6.4.1 + version: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) playgrounds/svelte4: devDependencies: @@ -345,19 +357,19 @@ importers: version: link:../../packages/svelte '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) + version: 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) '@tailwindcss/vite': - specifier: ^4.1.13 - version: 4.1.13(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) + specifier: ^4.1.16 + version: 4.1.16(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) '@tsconfig/svelte': specifier: ^5.0.5 version: 5.0.5 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 laravel-vite-plugin: specifier: ^1.3.0 - version: 1.3.0(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) + version: 1.3.0(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) lodash: specifier: ^4.17.21 version: 4.17.21 @@ -365,17 +377,17 @@ importers: specifier: ^4.2.20 version: 4.2.20 svelte-check: - specifier: ^4.3.2 - version: 4.3.2(picomatch@4.0.3)(svelte@4.2.20)(typescript@5.9.2) + specifier: ^4.3.3 + version: 4.3.3(picomatch@4.0.3)(svelte@4.2.20)(typescript@5.9.3) tailwindcss: - specifier: ^4.1.13 - version: 4.1.13 + specifier: ^4.1.16 + version: 4.1.16 typescript: - specifier: ^5.9.2 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 vite: - specifier: ^5.4.20 - version: 5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0) + specifier: ^5.4.21 + version: 5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0) playgrounds/svelte5: devDependencies: @@ -384,37 +396,37 @@ importers: version: link:../../packages/svelte '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.39.5)(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) + version: 5.1.1(svelte@5.43.0)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) '@tailwindcss/vite': - specifier: ^4.1.13 - version: 4.1.13(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) + specifier: ^4.1.16 + version: 4.1.16(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) '@tsconfig/svelte': specifier: ^5.0.5 version: 5.0.5 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 laravel-vite-plugin: specifier: ^1.3.0 - version: 1.3.0(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) + version: 1.3.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) lodash: specifier: ^4.17.21 version: 4.17.21 svelte: - specifier: ^5.39.5 - version: 5.39.5 + specifier: ^5.43.0 + version: 5.43.0 svelte-check: - specifier: ^4.3.2 - version: 4.3.2(picomatch@4.0.3)(svelte@5.39.5)(typescript@5.9.2) + specifier: ^4.3.3 + version: 4.3.3(picomatch@4.0.3)(svelte@5.43.0)(typescript@5.9.3) tailwindcss: - specifier: ^4.1.13 - version: 4.1.13 + specifier: ^4.1.16 + version: 4.1.16 typescript: - specifier: ^5.9.2 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 vite: - specifier: ^6.3.6 - version: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) + specifier: ^6.4.1 + version: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) playgrounds/vue3: devDependencies: @@ -423,69 +435,69 @@ importers: version: link:../../packages/vue3 '@laravel/stream-vue': specifier: ^0.3.9 - version: 0.3.9(vue@3.5.21(typescript@5.9.2)) + version: 0.3.9(vue@3.5.22(typescript@5.9.3)) '@tailwindcss/typography': - specifier: ^0.5.18 - version: 0.5.18(tailwindcss@4.1.13) + specifier: ^0.5.19 + version: 0.5.19(tailwindcss@4.1.16) '@tailwindcss/vite': - specifier: ^4.1.13 - version: 4.1.13(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) + specifier: ^4.1.16 + version: 4.1.16(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) '@vitejs/plugin-vue': specifier: ^5.2.4 - version: 5.2.4(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0))(vue@3.5.21(typescript@5.9.2)) + version: 5.2.4(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))(vue@3.5.22(typescript@5.9.3)) '@vue/server-renderer': - specifier: ^3.5.21 - version: 3.5.21(vue@3.5.21(typescript@5.9.2)) + specifier: ^3.5.22 + version: 3.5.22(vue@3.5.22(typescript@5.9.3)) autosize: specifier: ^6.0.1 version: 6.0.1 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 laravel-vite-plugin: specifier: ^1.3.0 - version: 1.3.0(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) + version: 1.3.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) lodash: specifier: ^4.17.21 version: 4.17.21 marked: - specifier: ^16.3.0 - version: 16.3.0 + specifier: ^16.4.1 + version: 16.4.1 tailwindcss: - specifier: ^4.1.13 - version: 4.1.13 + specifier: ^4.1.16 + version: 4.1.16 typescript: - specifier: ^5.9.2 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 vite: - specifier: ^6.3.6 - version: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) + specifier: ^6.4.1 + version: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) vue: - specifier: ^3.5.21 - version: 3.5.21(typescript@5.9.2) + specifier: ^3.5.22 + version: 3.5.22(typescript@5.9.3) vue-tsc: specifier: ^2.2.12 - version: 2.2.12(typescript@5.9.2) + version: 2.2.12(typescript@5.9.3) tests/app: devDependencies: body-parser: - specifier: ^1.19.0 + specifier: ^1.20.3 version: 1.20.3 css-loader: - specifier: ^5.0.1 + specifier: ^5.2.7 version: 5.2.7(webpack@5.101.3) eslint: - specifier: ^7.17.0 + specifier: ^7.32.0 version: 7.32.0 express: - specifier: ^4.21.1 + specifier: ^4.21.2 version: 4.21.2 multer: specifier: ^2.0.2 version: 2.0.2 nodemon: - specifier: ^3.0.0 + specifier: ^3.1.10 version: 3.1.10 packages: @@ -501,16 +513,16 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.4': - resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==} + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.4': - resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.3': - resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.27.2': @@ -539,8 +551,8 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} '@babel/helper-validator-option@7.27.1': @@ -555,8 +567,8 @@ packages: resolution: {integrity: sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.4': - resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -576,20 +588,20 @@ packages: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.4': - resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.4': - resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} '@colors/colors@1.6.0': resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} - '@dabh/diagnostics@2.0.3': - resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + '@dabh/diagnostics@2.0.8': + resolution: {integrity: sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==} '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} @@ -597,8 +609,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.25.10': - resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==} + '@esbuild/aix-ppc64@0.25.11': + resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -609,8 +621,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.25.10': - resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==} + '@esbuild/android-arm64@0.25.11': + resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -621,8 +633,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.10': - resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==} + '@esbuild/android-arm@0.25.11': + resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -633,8 +645,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.25.10': - resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==} + '@esbuild/android-x64@0.25.11': + resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -645,8 +657,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.25.10': - resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==} + '@esbuild/darwin-arm64@0.25.11': + resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -657,8 +669,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.25.10': - resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==} + '@esbuild/darwin-x64@0.25.11': + resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -669,8 +681,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.10': - resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==} + '@esbuild/freebsd-arm64@0.25.11': + resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -681,8 +693,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.10': - resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==} + '@esbuild/freebsd-x64@0.25.11': + resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -693,8 +705,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.25.10': - resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==} + '@esbuild/linux-arm64@0.25.11': + resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -705,8 +717,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.25.10': - resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==} + '@esbuild/linux-arm@0.25.11': + resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -717,8 +729,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.25.10': - resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==} + '@esbuild/linux-ia32@0.25.11': + resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -729,8 +741,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.10': - resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==} + '@esbuild/linux-loong64@0.25.11': + resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -741,8 +753,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.25.10': - resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==} + '@esbuild/linux-mips64el@0.25.11': + resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -753,8 +765,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.25.10': - resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==} + '@esbuild/linux-ppc64@0.25.11': + resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -765,8 +777,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.25.10': - resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==} + '@esbuild/linux-riscv64@0.25.11': + resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -777,8 +789,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.25.10': - resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==} + '@esbuild/linux-s390x@0.25.11': + resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -789,14 +801,14 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.25.10': - resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==} + '@esbuild/linux-x64@0.25.11': + resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.10': - resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} + '@esbuild/netbsd-arm64@0.25.11': + resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -807,14 +819,14 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.10': - resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==} + '@esbuild/netbsd-x64@0.25.11': + resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.10': - resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==} + '@esbuild/openbsd-arm64@0.25.11': + resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -825,14 +837,14 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.10': - resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==} + '@esbuild/openbsd-x64@0.25.11': + resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.10': - resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} + '@esbuild/openharmony-arm64@0.25.11': + resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] @@ -843,8 +855,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.25.10': - resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==} + '@esbuild/sunos-x64@0.25.11': + resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -855,8 +867,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.10': - resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==} + '@esbuild/win32-arm64@0.25.11': + resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -867,8 +879,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.10': - resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==} + '@esbuild/win32-ia32@0.25.11': + resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -879,8 +891,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.25.10': - resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==} + '@esbuild/win32-x64@0.25.11': + resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -898,10 +910,6 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} deprecated: Use @eslint/object-schema instead - '@isaacs/fs-minipass@4.0.1': - resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} - engines: {node: '>=18.0.0'} - '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -943,8 +951,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@playwright/test@1.55.1': - resolution: {integrity: sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==} + '@playwright/test@1.56.1': + resolution: {integrity: sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==} engines: {node: '>=18'} hasBin: true @@ -954,121 +962,124 @@ packages: '@rolldown/pluginutils@1.0.0-beta.27': resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} - '@rollup/rollup-android-arm-eabi@4.52.2': - resolution: {integrity: sha512-o3pcKzJgSGt4d74lSZ+OCnHwkKBeAbFDmbEm5gg70eA8VkyCuC/zV9TwBnmw6VjDlRdF4Pshfb+WE9E6XY1PoQ==} + '@rollup/rollup-android-arm-eabi@4.52.5': + resolution: {integrity: sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.52.2': - resolution: {integrity: sha512-cqFSWO5tX2vhC9hJTK8WAiPIm4Q8q/cU8j2HQA0L3E1uXvBYbOZMhE2oFL8n2pKB5sOCHY6bBuHaRwG7TkfJyw==} + '@rollup/rollup-android-arm64@4.52.5': + resolution: {integrity: sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.52.2': - resolution: {integrity: sha512-vngduywkkv8Fkh3wIZf5nFPXzWsNsVu1kvtLETWxTFf/5opZmflgVSeLgdHR56RQh71xhPhWoOkEBvbehwTlVA==} + '@rollup/rollup-darwin-arm64@4.52.5': + resolution: {integrity: sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.52.2': - resolution: {integrity: sha512-h11KikYrUCYTrDj6h939hhMNlqU2fo/X4NB0OZcys3fya49o1hmFaczAiJWVAFgrM1NCP6RrO7lQKeVYSKBPSQ==} + '@rollup/rollup-darwin-x64@4.52.5': + resolution: {integrity: sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.52.2': - resolution: {integrity: sha512-/eg4CI61ZUkLXxMHyVlmlGrSQZ34xqWlZNW43IAU4RmdzWEx0mQJ2mN/Cx4IHLVZFL6UBGAh+/GXhgvGb+nVxw==} + '@rollup/rollup-freebsd-arm64@4.52.5': + resolution: {integrity: sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.52.2': - resolution: {integrity: sha512-QOWgFH5X9+p+S1NAfOqc0z8qEpJIoUHf7OWjNUGOeW18Mx22lAUOiA9b6r2/vpzLdfxi/f+VWsYjUOMCcYh0Ng==} + '@rollup/rollup-freebsd-x64@4.52.5': + resolution: {integrity: sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.52.2': - resolution: {integrity: sha512-kDWSPafToDd8LcBYd1t5jw7bD5Ojcu12S3uT372e5HKPzQt532vW+rGFFOaiR0opxePyUkHrwz8iWYEyH1IIQA==} + '@rollup/rollup-linux-arm-gnueabihf@4.52.5': + resolution: {integrity: sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.52.2': - resolution: {integrity: sha512-gKm7Mk9wCv6/rkzwCiUC4KnevYhlf8ztBrDRT9g/u//1fZLapSRc+eDZj2Eu2wpJ+0RzUKgtNijnVIB4ZxyL+w==} + '@rollup/rollup-linux-arm-musleabihf@4.52.5': + resolution: {integrity: sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.52.2': - resolution: {integrity: sha512-66lA8vnj5mB/rtDNwPgrrKUOtCLVQypkyDa2gMfOefXK6rcZAxKLO9Fy3GkW8VkPnENv9hBkNOFfGLf6rNKGUg==} + '@rollup/rollup-linux-arm64-gnu@4.52.5': + resolution: {integrity: sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.52.2': - resolution: {integrity: sha512-s+OPucLNdJHvuZHuIz2WwncJ+SfWHFEmlC5nKMUgAelUeBUnlB4wt7rXWiyG4Zn07uY2Dd+SGyVa9oyLkVGOjA==} + '@rollup/rollup-linux-arm64-musl@4.52.5': + resolution: {integrity: sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.52.2': - resolution: {integrity: sha512-8wTRM3+gVMDLLDdaT6tKmOE3lJyRy9NpJUS/ZRWmLCmOPIJhVyXwjBo+XbrrwtV33Em1/eCTd5TuGJm4+DmYjw==} + '@rollup/rollup-linux-loong64-gnu@4.52.5': + resolution: {integrity: sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.52.2': - resolution: {integrity: sha512-6yqEfgJ1anIeuP2P/zhtfBlDpXUb80t8DpbYwXQ3bQd95JMvUaqiX+fKqYqUwZXqdJDd8xdilNtsHM2N0cFm6A==} + '@rollup/rollup-linux-ppc64-gnu@4.52.5': + resolution: {integrity: sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.52.2': - resolution: {integrity: sha512-sshYUiYVSEI2B6dp4jMncwxbrUqRdNApF2c3bhtLAU0qA8Lrri0p0NauOsTWh3yCCCDyBOjESHMExonp7Nzc0w==} + '@rollup/rollup-linux-riscv64-gnu@4.52.5': + resolution: {integrity: sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.52.2': - resolution: {integrity: sha512-duBLgd+3pqC4MMwBrKkFxaZerUxZcYApQVC5SdbF5/e/589GwVvlRUnyqMFbM8iUSb1BaoX/3fRL7hB9m2Pj8Q==} + '@rollup/rollup-linux-riscv64-musl@4.52.5': + resolution: {integrity: sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.52.2': - resolution: {integrity: sha512-tzhYJJidDUVGMgVyE+PmxENPHlvvqm1KILjjZhB8/xHYqAGeizh3GBGf9u6WdJpZrz1aCpIIHG0LgJgH9rVjHQ==} + '@rollup/rollup-linux-s390x-gnu@4.52.5': + resolution: {integrity: sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.52.2': - resolution: {integrity: sha512-opH8GSUuVcCSSyHHcl5hELrmnk4waZoVpgn/4FDao9iyE4WpQhyWJ5ryl5M3ocp4qkRuHfyXnGqg8M9oKCEKRA==} + '@rollup/rollup-linux-x64-gnu@4.52.5': + resolution: {integrity: sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.52.2': - resolution: {integrity: sha512-LSeBHnGli1pPKVJ79ZVJgeZWWZXkEe/5o8kcn23M8eMKCUANejchJbF/JqzM4RRjOJfNRhKJk8FuqL1GKjF5oQ==} + '@rollup/rollup-linux-x64-musl@4.52.5': + resolution: {integrity: sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.52.2': - resolution: {integrity: sha512-uPj7MQ6/s+/GOpolavm6BPo+6CbhbKYyZHUDvZ/SmJM7pfDBgdGisFX3bY/CBDMg2ZO4utfhlApkSfZ92yXw7Q==} + '@rollup/rollup-openharmony-arm64@4.52.5': + resolution: {integrity: sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.52.2': - resolution: {integrity: sha512-Z9MUCrSgIaUeeHAiNkm3cQyst2UhzjPraR3gYYfOjAuZI7tcFRTOD+4cHLPoS/3qinchth+V56vtqz1Tv+6KPA==} + '@rollup/rollup-win32-arm64-msvc@4.52.5': + resolution: {integrity: sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.52.2': - resolution: {integrity: sha512-+GnYBmpjldD3XQd+HMejo+0gJGwYIOfFeoBQv32xF/RUIvccUz20/V6Otdv+57NE70D5pa8W/jVGDoGq0oON4A==} + '@rollup/rollup-win32-ia32-msvc@4.52.5': + resolution: {integrity: sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.52.2': - resolution: {integrity: sha512-ApXFKluSB6kDQkAqZOKXBjiaqdF1BlKi+/eqnYe9Ee7U2K3pUDKsIyr8EYm/QDHTJIM+4X+lI0gJc3TTRhd+dA==} + '@rollup/rollup-win32-x64-gnu@4.52.5': + resolution: {integrity: sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.52.2': - resolution: {integrity: sha512-ARz+Bs8kY6FtitYM96PqPEVvPXqEZmPZsSkXvyX19YzDqkCaIlhCieLLMI5hxO9SRZ2XtCtm8wxhy0iJ2jxNfw==} + '@rollup/rollup-win32-x64-msvc@4.52.5': + resolution: {integrity: sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==} cpu: [x64] os: [win32] + '@so-ric/colorspace@1.1.6': + resolution: {integrity: sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==} + '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} - '@sveltejs/acorn-typescript@1.0.5': - resolution: {integrity: sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==} + '@sveltejs/acorn-typescript@1.0.6': + resolution: {integrity: sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ==} peerDependencies: acorn: ^8.9.0 @@ -1077,8 +1088,8 @@ packages: peerDependencies: '@sveltejs/kit': ^2.0.0 - '@sveltejs/kit@2.43.2': - resolution: {integrity: sha512-M27eBoqWmU7dEpotMGBaA1CK6Y/wK1b176mVOkrSJZwt17bk6Z1IjLQv0iuVYm7D8d1Z/I4HzJ3hSqy8auj1Sw==} + '@sveltejs/kit@2.48.3': + resolution: {integrity: sha512-jf8mx3yctRXE9hvixgcqqK94YI2hDnbxI/12Upkz99XFMvxnJKCMzvz0j7lmbXSyBSNEycWO5xHvi7b73y9qkQ==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -1127,65 +1138,65 @@ packages: svelte: ^5.0.0 vite: ^6.0.0 - '@tailwindcss/node@4.1.13': - resolution: {integrity: sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==} + '@tailwindcss/node@4.1.16': + resolution: {integrity: sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==} - '@tailwindcss/oxide-android-arm64@4.1.13': - resolution: {integrity: sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==} + '@tailwindcss/oxide-android-arm64@4.1.16': + resolution: {integrity: sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.1.13': - resolution: {integrity: sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==} + '@tailwindcss/oxide-darwin-arm64@4.1.16': + resolution: {integrity: sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.1.13': - resolution: {integrity: sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==} + '@tailwindcss/oxide-darwin-x64@4.1.16': + resolution: {integrity: sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.1.13': - resolution: {integrity: sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==} + '@tailwindcss/oxide-freebsd-x64@4.1.16': + resolution: {integrity: sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13': - resolution: {integrity: sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16': + resolution: {integrity: sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.1.13': - resolution: {integrity: sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==} + '@tailwindcss/oxide-linux-arm64-gnu@4.1.16': + resolution: {integrity: sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.1.13': - resolution: {integrity: sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==} + '@tailwindcss/oxide-linux-arm64-musl@4.1.16': + resolution: {integrity: sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.1.13': - resolution: {integrity: sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==} + '@tailwindcss/oxide-linux-x64-gnu@4.1.16': + resolution: {integrity: sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.1.13': - resolution: {integrity: sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==} + '@tailwindcss/oxide-linux-x64-musl@4.1.16': + resolution: {integrity: sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-wasm32-wasi@4.1.13': - resolution: {integrity: sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==} + '@tailwindcss/oxide-wasm32-wasi@4.1.16': + resolution: {integrity: sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -1196,29 +1207,29 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.1.13': - resolution: {integrity: sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==} + '@tailwindcss/oxide-win32-arm64-msvc@4.1.16': + resolution: {integrity: sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.1.13': - resolution: {integrity: sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==} + '@tailwindcss/oxide-win32-x64-msvc@4.1.16': + resolution: {integrity: sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.1.13': - resolution: {integrity: sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==} + '@tailwindcss/oxide@4.1.16': + resolution: {integrity: sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg==} engines: {node: '>= 10'} - '@tailwindcss/typography@0.5.18': - resolution: {integrity: sha512-dDIgwZOlf+tVkZ7A029VvQ1+ngKATENDjMEx2N35s2yPjfTS05RWSM8ilhEWSa5DMJ6ci2Ha9WNZEd2GQjrdQg==} + '@tailwindcss/typography@0.5.19': + resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==} peerDependencies: tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' - '@tailwindcss/vite@4.1.13': - resolution: {integrity: sha512-0PmqLQ010N58SbMTJ7BVJ4I2xopiQn/5i6nlb4JmxzQf8zcS5+m2Cv6tqh+sfDwtIdjoEnOvwsGQ1hkUi8QEHQ==} + '@tailwindcss/vite@4.1.16': + resolution: {integrity: sha512-bbguNBcDxsRmi9nnlWJxhfDWamY3lmcyACHcdO1crxfzuLpOhHLLtEIN/nCbbAtj5rchUgQD17QVAKi1f7IsKg==} peerDependencies: vite: ^5.2.0 || ^6 || ^7 @@ -1262,17 +1273,14 @@ packages: '@types/lodash@4.17.20': resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} - '@types/node@18.19.127': - resolution: {integrity: sha512-gSjxjrnKXML/yo0BO099uPixMqfpJU0TKYjpfLU7TrtA2WWDki412Np/RSTPRil1saKBhvVVKzVx/p/6p94nVA==} - - '@types/node@22.18.6': - resolution: {integrity: sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==} + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} - '@types/node@24.3.2': - resolution: {integrity: sha512-6L8PkB+m1SSb2kaGGFk3iXENxl8lrs7cyVl7AXH6pgdMfulDfM6yUrVdjtxdnGrLrGzzuav8fFnZMY+rcscqcA==} + '@types/node@22.18.13': + resolution: {integrity: sha512-Bo45YKIjnmFtv6I1TuC8AaHBbqXtIo+Om5fE4QiU1Tj8QR/qt+8O3BAtOimG5IFmwaWiPmB3Mv3jtYzBA4Us2A==} - '@types/node@24.5.2': - resolution: {integrity: sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==} + '@types/node@24.9.2': + resolution: {integrity: sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==} '@types/nprogress@0.2.3': resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} @@ -1280,13 +1288,13 @@ packages: '@types/qs@6.14.0': resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} - '@types/react-dom@19.1.9': - resolution: {integrity: sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==} + '@types/react-dom@19.2.2': + resolution: {integrity: sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==} peerDependencies: - '@types/react': ^19.0.0 + '@types/react': ^19.2.0 - '@types/react@19.1.13': - resolution: {integrity: sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==} + '@types/react@19.2.2': + resolution: {integrity: sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==} '@types/triple-beam@1.3.5': resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} @@ -1313,17 +1321,17 @@ packages: '@volar/typescript@2.4.15': resolution: {integrity: sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==} - '@vue/compiler-core@3.5.21': - resolution: {integrity: sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==} + '@vue/compiler-core@3.5.22': + resolution: {integrity: sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==} - '@vue/compiler-dom@3.5.21': - resolution: {integrity: sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==} + '@vue/compiler-dom@3.5.22': + resolution: {integrity: sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==} - '@vue/compiler-sfc@3.5.21': - resolution: {integrity: sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==} + '@vue/compiler-sfc@3.5.22': + resolution: {integrity: sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==} - '@vue/compiler-ssr@3.5.21': - resolution: {integrity: sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==} + '@vue/compiler-ssr@3.5.22': + resolution: {integrity: sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==} '@vue/compiler-vue2@2.7.16': resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} @@ -1336,22 +1344,22 @@ packages: typescript: optional: true - '@vue/reactivity@3.5.21': - resolution: {integrity: sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==} + '@vue/reactivity@3.5.22': + resolution: {integrity: sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==} - '@vue/runtime-core@3.5.21': - resolution: {integrity: sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==} + '@vue/runtime-core@3.5.22': + resolution: {integrity: sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ==} - '@vue/runtime-dom@3.5.21': - resolution: {integrity: sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==} + '@vue/runtime-dom@3.5.22': + resolution: {integrity: sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww==} - '@vue/server-renderer@3.5.21': - resolution: {integrity: sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==} + '@vue/server-renderer@3.5.22': + resolution: {integrity: sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ==} peerDependencies: - vue: 3.5.21 + vue: 3.5.22 - '@vue/shared@3.5.21': - resolution: {integrity: sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==} + '@vue/shared@3.5.22': + resolution: {integrity: sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==} '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -1506,8 +1514,8 @@ packages: autosize@6.0.1: resolution: {integrity: sha512-f86EjiUKE6Xvczc4ioP1JBlWG7FKrE13qe/DxBCpe8GCipCq2nFw73aO8QEBKHfSbYGDN5eB9jXWKen7tspDqQ==} - axios@1.12.2: - resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} + axios@1.13.1: + resolution: {integrity: sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==} axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} @@ -1516,8 +1524,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - baseline-browser-mapping@2.8.6: - resolution: {integrity: sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==} + baseline-browser-mapping@2.8.21: + resolution: {integrity: sha512-JU0h5APyQNsHOlAM7HnQnPToSDQoEBZqzu/YBlqDnEeymPnZDREeXJA3KBMQee+dKteAxZ2AtvQEvVYdZf241Q==} hasBin: true big.js@5.2.2: @@ -1541,8 +1549,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.26.2: - resolution: {integrity: sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==} + browserslist@4.27.0: + resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1569,8 +1577,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001743: - resolution: {integrity: sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==} + caniuse-lite@1.0.30001751: + resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -1588,10 +1596,6 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} - chownr@3.0.0: - resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} - engines: {node: '>=18'} - chrome-trace-event@1.0.4: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} @@ -1610,27 +1614,34 @@ packages: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} + color-convert@3.1.2: + resolution: {integrity: sha512-UNqkvCDXstVck3kdowtOTWROIJQwafjOfXSmddoDrXo4cewMKmusCeF22Q24zvjR8nwWib/3S/dfyzPItPEiJg==} + engines: {node: '>=14.6'} + color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + color-name@2.0.2: + resolution: {integrity: sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==} + engines: {node: '>=12.20'} - color@3.2.1: - resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + color-string@2.1.2: + resolution: {integrity: sha512-RxmjYxbWemV9gKu4zPgiZagUxbH3RQpEIO77XoSSX0ivgABDZ+h8Zuash/EMFLTI4N9QgFPOJ6JQpPZKFxa+dA==} + engines: {node: '>=18'} - colorspace@1.1.4: - resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + color@5.0.2: + resolution: {integrity: sha512-e2hz5BzbUPcYlIRHo8ieAhYgoajrJr+hWoceg6E345TPsATMUKqDgzt8fSXZJJbxfpiPzkWyphz8yn8At7q3fA==} + engines: {node: '>=18'} combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} - commander@14.0.0: - resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} + commander@14.0.1: + resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==} engines: {node: '>=20'} commander@2.20.3: @@ -1698,15 +1709,6 @@ packages: supports-color: optional: true - debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1738,12 +1740,12 @@ packages: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - detect-libc@2.1.0: - resolution: {integrity: sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - devalue@5.3.2: - resolution: {integrity: sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==} + devalue@5.4.2: + resolution: {integrity: sha512-MwPZTKEPK2k8Qgfmqrd48ZKVvzSQjgW0lXLxiIBA8dQjtf/6mw6pggHNLcyDKyf+fI6eXxlQwPsfaCMTU5U+Bw==} doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} @@ -1756,8 +1758,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.223: - resolution: {integrity: sha512-qKm55ic6nbEmagFlTFczML33rF90aU+WtrJ9MdTCThrcvDNdUHN4p6QfVN78U06ZmguqXIyMPyYhw2TrbDUwPQ==} + electron-to-chromium@1.5.243: + resolution: {integrity: sha512-ZCphxFW3Q1TVhcgS9blfut1PX8lusVi2SvXQgmEEnK4TCmE1JhH2JkjJN+DNt0pJJwfBri5AROBnz2b/C+YU9g==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1789,8 +1791,8 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - es-check@9.3.1: - resolution: {integrity: sha512-9cDv061bddtgqtqc6xbxA1mfwNYQsNGyaiElpQhcNycTaW7Pnpk183jy+3eOjhMSbZCy/RqCfu2lZZufrlo2mA==} + es-check@9.4.4: + resolution: {integrity: sha512-Ppp6r1diw1jy0t5uQX47HN3JqvosoAymZshdimrwpxCY1GQfZvqTqb9tHiiDbkm+aqGLdVDCZoL9okue7tdXZw==} engines: {node: '>= 4'} hasBin: true @@ -1824,8 +1826,8 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.25.10: - resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==} + esbuild@0.25.11: + resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} engines: {node: '>=18'} hasBin: true @@ -1882,8 +1884,8 @@ packages: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} - esrap@2.1.0: - resolution: {integrity: sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==} + esrap@2.1.1: + resolution: {integrity: sha512-ebTT9B6lOtZGMgJ3o5r12wBacHctG7oEWazIda8UlPfA3HD/Wrv8FdXoVo73vzdpwCxNyXjPauyN2bbJzMkB9A==} esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} @@ -1919,6 +1921,9 @@ packages: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} + fast-brake@0.1.6: + resolution: {integrity: sha512-V3j0HTIs70OOxRpbqT0bWVdrmP86s6N8TBPw/WyKJqdJ2Fwh3CuMmlO83uIIDpqik6m1Io9fT6qwNn69EqvXYA==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -2126,9 +2131,6 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - is-arrayish@0.3.4: - resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} - is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -2163,8 +2165,8 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} - jiti@2.6.0: - resolution: {integrity: sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ==} + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true js-tokens@4.0.0: @@ -2209,6 +2211,9 @@ packages: kuler@2.0.0: resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + laravel-precognition@0.7.3: + resolution: {integrity: sha512-Z97i35Q0wmsRC9WFUY2EmFS2W1F6FF/HakwZg6PqSaR9lHBgbdIs1YZpDlkChVkgcmmvbN19ujKss3ZqbjPM1g==} + laravel-vite-plugin@1.3.0: resolution: {integrity: sha512-P5qyG56YbYxM8OuYmK2OkhcKe0AksNVJUjq9LUZ5tOekU9fBn9LujYyctI4t9XoLjuMvHJXXpCoPntY1oKltuA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -2220,76 +2225,82 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lightningcss-darwin-arm64@1.30.1: - resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} + lightningcss-android-arm64@1.30.2: + resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.30.2: + resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.30.1: - resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==} + lightningcss-darwin-x64@1.30.2: + resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.30.1: - resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==} + lightningcss-freebsd-x64@1.30.2: + resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.30.1: - resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==} + lightningcss-linux-arm-gnueabihf@1.30.2: + resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.30.1: - resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==} + lightningcss-linux-arm64-gnu@1.30.2: + resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - lightningcss-linux-arm64-musl@1.30.1: - resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} + lightningcss-linux-arm64-musl@1.30.2: + resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - lightningcss-linux-x64-gnu@1.30.1: - resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} + lightningcss-linux-x64-gnu@1.30.2: + resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - lightningcss-linux-x64-musl@1.30.1: - resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} + lightningcss-linux-x64-musl@1.30.2: + resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - lightningcss-win32-arm64-msvc@1.30.1: - resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} + lightningcss-win32-arm64-msvc@1.30.2: + resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.30.1: - resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==} + lightningcss-win32-x64-msvc@1.30.2: + resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.30.1: - resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} + lightningcss@1.30.2: + resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} engines: {node: '>= 12.0.0'} lilconfig@3.1.3: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} - loader-runner@4.3.0: - resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + loader-runner@4.3.1: + resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} engines: {node: '>=6.11.5'} loader-utils@2.0.4: @@ -2322,11 +2333,11 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - magic-string@0.30.19: - resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - marked@16.3.0: - resolution: {integrity: sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==} + marked@16.4.1: + resolution: {integrity: sha512-ntROs7RaN3EvWfy3EZi14H4YxmT6A5YvywfhO+0pm+cH/dnSQRmdAmoFIc3B9aiwTehyk7pESH4ofyBY+V5hZg==} engines: {node: '>= 20'} hasBin: true @@ -2386,14 +2397,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - - minizlib@3.1.0: - resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} - engines: {node: '>= 18'} - mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -2439,8 +2442,8 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - node-releases@2.0.21: - resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==} + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} nodemon@3.1.10: resolution: {integrity: sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==} @@ -2534,13 +2537,13 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} - playwright-core@1.55.1: - resolution: {integrity: sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==} + playwright-core@1.56.1: + resolution: {integrity: sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==} engines: {node: '>=18'} hasBin: true - playwright@1.55.1: - resolution: {integrity: sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==} + playwright@1.56.1: + resolution: {integrity: sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==} engines: {node: '>=18'} hasBin: true @@ -2714,17 +2717,17 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} - react-dom@19.1.1: - resolution: {integrity: sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==} + react-dom@19.2.0: + resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} peerDependencies: - react: ^19.1.1 + react: ^19.2.0 react-refresh@0.17.0: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} - react@19.1.1: - resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} + react@19.2.0: + resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} engines: {node: '>=0.10.0'} readable-stream@3.6.2: @@ -2760,8 +2763,8 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rollup@4.52.2: - resolution: {integrity: sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==} + rollup@4.52.5: + resolution: {integrity: sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2782,15 +2785,15 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - scheduler@0.26.0: - resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} - schema-utils@4.3.2: - resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==} + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} engines: {node: '>= 10.13.0'} scule@1.3.0: @@ -2800,8 +2803,8 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true @@ -2816,8 +2819,8 @@ packages: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} - set-cookie-parser@2.7.1: - resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -2846,9 +2849,6 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} - simple-swizzle@0.2.4: - resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} - simple-update-notifier@2.0.0: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} @@ -2917,16 +2917,8 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} - svelte-check@4.3.1: - resolution: {integrity: sha512-lkh8gff5gpHLjxIV+IaApMxQhTGnir2pNUAqcNgeKkvK5bT/30Ey/nzBxNLDlkztCH4dP7PixkMt9SWEKFPBWg==} - engines: {node: '>= 18.0.0'} - hasBin: true - peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.0 - typescript: '>=5.0.0' - - svelte-check@4.3.2: - resolution: {integrity: sha512-71udP5w2kaSTcX8iV0hn3o2FWlabQHhJTJLIQrCqMsrcOeDUO2VhCQKKCA8AMVHSPwdxLEWkUWh9OKxns5PD9w==} + svelte-check@4.3.3: + resolution: {integrity: sha512-RYP0bEwenDXzfv0P1sKAwjZSlaRyqBn0Fz1TVni58lqyEiqgwztTpmodJrGzP6ZT2aHl4MbTvWP6gbmQ3FOnBg==} engines: {node: '>= 18.0.0'} hasBin: true peerDependencies: @@ -2939,8 +2931,8 @@ packages: peerDependencies: svelte: ^3.19.0 || ^4.0.0 - svelte2tsx@0.7.44: - resolution: {integrity: sha512-opuH+bCboss0/ncxnfAO+qt0IAprxc8OqwuC7otafWeO5CHjJ6UAAwvQmu/+xjpCSarX8pQKydXQuoJmbCDcTg==} + svelte2tsx@0.7.45: + resolution: {integrity: sha512-cSci+mYGygYBHIZLHlm/jYlEc1acjAHqaQaDFHdEBpUueM9kSTnPpvPtSl5VkJOU1qSJ7h1K+6F/LIUYiqC8VA==} peerDependencies: svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0 typescript: ^4.9.4 || ^5.0.0 @@ -2949,25 +2941,21 @@ packages: resolution: {integrity: sha512-eeEgGc2DtiUil5ANdtd8vPwt9AgaMdnuUFnPft9F5oMvU/FHu5IHFic+p1dR/UOB7XU2mX2yHW+NcTch4DCh5Q==} engines: {node: '>=16'} - svelte@5.39.5: - resolution: {integrity: sha512-YrTmQAgJNB5He5t14g+BH76xTjskcx0Dg3p6qKqfPcgha+9Rzdgkoazdk18ahzNfkFYgykZIjfnBvlPcp3NpYg==} + svelte@5.43.0: + resolution: {integrity: sha512-1sRxVbgJAB+UGzwkc3GUoiBSzEOf0jqzccMaVoI2+pI+kASUe9qubslxace8+Mzhqw19k4syTA5niCIJwfXpOA==} engines: {node: '>=18'} table@6.9.0: resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} engines: {node: '>=10.0.0'} - tailwindcss@4.1.13: - resolution: {integrity: sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==} + tailwindcss@4.1.16: + resolution: {integrity: sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==} - tapable@2.2.3: - resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==} + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} - tar@7.5.1: - resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==} - engines: {node: '>=18'} - terser-webpack-plugin@5.3.14: resolution: {integrity: sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==} engines: {node: '>= 10.13.0'} @@ -3042,8 +3030,8 @@ packages: engines: {node: '>=4.2.0'} hasBin: true - typescript@5.9.2: - resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true @@ -3056,18 +3044,15 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@7.10.0: - resolution: {integrity: sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==} - - undici-types@7.12.0: - resolution: {integrity: sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + update-browserslist-db@1.1.4: + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -3092,8 +3077,8 @@ packages: vite-plugin-full-reload@1.2.0: resolution: {integrity: sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA==} - vite@5.4.20: - resolution: {integrity: sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==} + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -3123,8 +3108,8 @@ packages: terser: optional: true - vite@6.3.6: - resolution: {integrity: sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==} + vite@6.4.1: + resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -3188,8 +3173,8 @@ packages: peerDependencies: typescript: '>=5.0.0' - vue@3.5.21: - resolution: {integrity: sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA==} + vue@3.5.22: + resolution: {integrity: sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==} peerDependencies: typescript: '*' peerDependenciesMeta: @@ -3241,10 +3226,6 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yallist@5.0.0: - resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} - engines: {node: '>=18'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -3265,45 +3246,45 @@ snapshots: '@babel/code-frame@7.27.1': dependencies: - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.28.4': {} + '@babel/compat-data@7.28.5': {} - '@babel/core@7.28.4': + '@babel/core@7.28.5': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 + '@babel/generator': 7.28.5 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.28.3': + '@babel/generator@7.28.5': dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.28.4 + '@babel/compat-data': 7.28.5 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.26.2 + browserslist: 4.27.0 lru-cache: 5.1.1 semver: 6.3.1 @@ -3311,17 +3292,17 @@ snapshots: '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)': + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.5 '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.4 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color @@ -3329,218 +3310,218 @@ snapshots: '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-identifier@7.28.5': {} '@babel/helper-validator-option@7.27.1': {} '@babel/helpers@7.28.4': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@babel/highlight@7.25.9': dependencies: - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 chalk: 2.4.2 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/parser@7.28.4': + '@babel/parser@7.28.5': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.4)': + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.5 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.4)': + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.5 '@babel/helper-plugin-utils': 7.27.1 '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 - '@babel/traverse@7.28.4': + '@babel/traverse@7.28.5': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 + '@babel/generator': 7.28.5 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/types': 7.28.4 - debug: 4.4.3 + '@babel/types': 7.28.5 + debug: 4.4.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color - '@babel/types@7.28.4': + '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 '@colors/colors@1.6.0': {} - '@dabh/diagnostics@2.0.3': + '@dabh/diagnostics@2.0.8': dependencies: - colorspace: 1.1.4 + '@so-ric/colorspace': 1.1.6 enabled: 2.0.0 kuler: 2.0.0 '@esbuild/aix-ppc64@0.21.5': optional: true - '@esbuild/aix-ppc64@0.25.10': + '@esbuild/aix-ppc64@0.25.11': optional: true '@esbuild/android-arm64@0.21.5': optional: true - '@esbuild/android-arm64@0.25.10': + '@esbuild/android-arm64@0.25.11': optional: true '@esbuild/android-arm@0.21.5': optional: true - '@esbuild/android-arm@0.25.10': + '@esbuild/android-arm@0.25.11': optional: true '@esbuild/android-x64@0.21.5': optional: true - '@esbuild/android-x64@0.25.10': + '@esbuild/android-x64@0.25.11': optional: true '@esbuild/darwin-arm64@0.21.5': optional: true - '@esbuild/darwin-arm64@0.25.10': + '@esbuild/darwin-arm64@0.25.11': optional: true '@esbuild/darwin-x64@0.21.5': optional: true - '@esbuild/darwin-x64@0.25.10': + '@esbuild/darwin-x64@0.25.11': optional: true '@esbuild/freebsd-arm64@0.21.5': optional: true - '@esbuild/freebsd-arm64@0.25.10': + '@esbuild/freebsd-arm64@0.25.11': optional: true '@esbuild/freebsd-x64@0.21.5': optional: true - '@esbuild/freebsd-x64@0.25.10': + '@esbuild/freebsd-x64@0.25.11': optional: true '@esbuild/linux-arm64@0.21.5': optional: true - '@esbuild/linux-arm64@0.25.10': + '@esbuild/linux-arm64@0.25.11': optional: true '@esbuild/linux-arm@0.21.5': optional: true - '@esbuild/linux-arm@0.25.10': + '@esbuild/linux-arm@0.25.11': optional: true '@esbuild/linux-ia32@0.21.5': optional: true - '@esbuild/linux-ia32@0.25.10': + '@esbuild/linux-ia32@0.25.11': optional: true '@esbuild/linux-loong64@0.21.5': optional: true - '@esbuild/linux-loong64@0.25.10': + '@esbuild/linux-loong64@0.25.11': optional: true '@esbuild/linux-mips64el@0.21.5': optional: true - '@esbuild/linux-mips64el@0.25.10': + '@esbuild/linux-mips64el@0.25.11': optional: true '@esbuild/linux-ppc64@0.21.5': optional: true - '@esbuild/linux-ppc64@0.25.10': + '@esbuild/linux-ppc64@0.25.11': optional: true '@esbuild/linux-riscv64@0.21.5': optional: true - '@esbuild/linux-riscv64@0.25.10': + '@esbuild/linux-riscv64@0.25.11': optional: true '@esbuild/linux-s390x@0.21.5': optional: true - '@esbuild/linux-s390x@0.25.10': + '@esbuild/linux-s390x@0.25.11': optional: true '@esbuild/linux-x64@0.21.5': optional: true - '@esbuild/linux-x64@0.25.10': + '@esbuild/linux-x64@0.25.11': optional: true - '@esbuild/netbsd-arm64@0.25.10': + '@esbuild/netbsd-arm64@0.25.11': optional: true '@esbuild/netbsd-x64@0.21.5': optional: true - '@esbuild/netbsd-x64@0.25.10': + '@esbuild/netbsd-x64@0.25.11': optional: true - '@esbuild/openbsd-arm64@0.25.10': + '@esbuild/openbsd-arm64@0.25.11': optional: true '@esbuild/openbsd-x64@0.21.5': optional: true - '@esbuild/openbsd-x64@0.25.10': + '@esbuild/openbsd-x64@0.25.11': optional: true - '@esbuild/openharmony-arm64@0.25.10': + '@esbuild/openharmony-arm64@0.25.11': optional: true '@esbuild/sunos-x64@0.21.5': optional: true - '@esbuild/sunos-x64@0.25.10': + '@esbuild/sunos-x64@0.25.11': optional: true '@esbuild/win32-arm64@0.21.5': optional: true - '@esbuild/win32-arm64@0.25.10': + '@esbuild/win32-arm64@0.25.11': optional: true '@esbuild/win32-ia32@0.21.5': optional: true - '@esbuild/win32-ia32@0.25.10': + '@esbuild/win32-ia32@0.25.11': optional: true '@esbuild/win32-x64@0.21.5': optional: true - '@esbuild/win32-x64@0.25.10': + '@esbuild/win32-x64@0.25.11': optional: true '@eslint/eslintrc@0.4.3': dependencies: ajv: 6.12.6 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) espree: 7.3.1 globals: 13.24.0 ignore: 4.0.6 @@ -3554,17 +3535,13 @@ snapshots: '@humanwhocodes/config-array@0.5.0': dependencies: '@humanwhocodes/object-schema': 1.2.1 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color '@humanwhocodes/object-schema@1.2.1': {} - '@isaacs/fs-minipass@4.0.1': - dependencies: - minipass: 7.1.2 - '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -3589,14 +3566,14 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@laravel/stream-react@0.3.9(react@19.1.1)': + '@laravel/stream-react@0.3.9(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@laravel/stream-vue@0.3.9(vue@3.5.21(typescript@5.9.2))': + '@laravel/stream-vue@0.3.9(vue@3.5.22(typescript@5.9.3))': dependencies: nanoid: 5.1.6 - vue: 3.5.21(typescript@5.9.2) + vue: 3.5.22(typescript@5.9.3) '@nodelib/fs.scandir@2.1.5': dependencies: @@ -3610,271 +3587,273 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 - '@playwright/test@1.55.1': + '@playwright/test@1.56.1': dependencies: - playwright: 1.55.1 + playwright: 1.56.1 '@polka/url@1.0.0-next.29': {} '@rolldown/pluginutils@1.0.0-beta.27': {} - '@rollup/rollup-android-arm-eabi@4.52.2': + '@rollup/rollup-android-arm-eabi@4.52.5': optional: true - '@rollup/rollup-android-arm64@4.52.2': + '@rollup/rollup-android-arm64@4.52.5': optional: true - '@rollup/rollup-darwin-arm64@4.52.2': + '@rollup/rollup-darwin-arm64@4.52.5': optional: true - '@rollup/rollup-darwin-x64@4.52.2': + '@rollup/rollup-darwin-x64@4.52.5': optional: true - '@rollup/rollup-freebsd-arm64@4.52.2': + '@rollup/rollup-freebsd-arm64@4.52.5': optional: true - '@rollup/rollup-freebsd-x64@4.52.2': + '@rollup/rollup-freebsd-x64@4.52.5': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.52.2': + '@rollup/rollup-linux-arm-gnueabihf@4.52.5': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.52.2': + '@rollup/rollup-linux-arm-musleabihf@4.52.5': optional: true - '@rollup/rollup-linux-arm64-gnu@4.52.2': + '@rollup/rollup-linux-arm64-gnu@4.52.5': optional: true - '@rollup/rollup-linux-arm64-musl@4.52.2': + '@rollup/rollup-linux-arm64-musl@4.52.5': optional: true - '@rollup/rollup-linux-loong64-gnu@4.52.2': + '@rollup/rollup-linux-loong64-gnu@4.52.5': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.52.2': + '@rollup/rollup-linux-ppc64-gnu@4.52.5': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.52.2': + '@rollup/rollup-linux-riscv64-gnu@4.52.5': optional: true - '@rollup/rollup-linux-riscv64-musl@4.52.2': + '@rollup/rollup-linux-riscv64-musl@4.52.5': optional: true - '@rollup/rollup-linux-s390x-gnu@4.52.2': + '@rollup/rollup-linux-s390x-gnu@4.52.5': optional: true - '@rollup/rollup-linux-x64-gnu@4.52.2': + '@rollup/rollup-linux-x64-gnu@4.52.5': optional: true - '@rollup/rollup-linux-x64-musl@4.52.2': + '@rollup/rollup-linux-x64-musl@4.52.5': optional: true - '@rollup/rollup-openharmony-arm64@4.52.2': + '@rollup/rollup-openharmony-arm64@4.52.5': optional: true - '@rollup/rollup-win32-arm64-msvc@4.52.2': + '@rollup/rollup-win32-arm64-msvc@4.52.5': optional: true - '@rollup/rollup-win32-ia32-msvc@4.52.2': + '@rollup/rollup-win32-ia32-msvc@4.52.5': optional: true - '@rollup/rollup-win32-x64-gnu@4.52.2': + '@rollup/rollup-win32-x64-gnu@4.52.5': optional: true - '@rollup/rollup-win32-x64-msvc@4.52.2': + '@rollup/rollup-win32-x64-msvc@4.52.5': optional: true + '@so-ric/colorspace@1.1.6': + dependencies: + color: 5.0.2 + text-hex: 1.0.0 + '@standard-schema/spec@1.0.0': {} - '@sveltejs/acorn-typescript@1.0.5(acorn@8.15.0)': + '@sveltejs/acorn-typescript@1.0.6(acorn@8.15.0)': dependencies: acorn: 8.15.0 - '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.43.2(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)))': + '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.48.3(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)))': dependencies: - '@sveltejs/kit': 2.43.2(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) + '@sveltejs/kit': 2.48.3(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) import-meta-resolve: 4.2.0 - '@sveltejs/kit@2.43.2(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0))': + '@sveltejs/kit@2.48.3(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: '@standard-schema/spec': 1.0.0 - '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) + '@sveltejs/acorn-typescript': 1.0.6(acorn@8.15.0) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) '@types/cookie': 0.6.0 acorn: 8.15.0 cookie: 0.6.0 - devalue: 5.3.2 + devalue: 5.4.2 esm-env: 1.2.2 kleur: 4.1.5 - magic-string: 0.30.19 + magic-string: 0.30.21 mrmime: 2.0.1 sade: 1.8.1 - set-cookie-parser: 2.7.1 + set-cookie-parser: 2.7.2 sirv: 3.0.2 svelte: 4.2.20 - vite: 5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0) + vite: 5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0) - '@sveltejs/package@2.5.4(svelte@4.2.20)(typescript@5.9.2)': + '@sveltejs/package@2.5.4(svelte@4.2.20)(typescript@5.9.3)': dependencies: chokidar: 4.0.3 kleur: 4.1.5 sade: 1.8.1 - semver: 7.7.2 + semver: 7.7.3 svelte: 4.2.20 - svelte2tsx: 0.7.44(svelte@4.2.20)(typescript@5.9.2) + svelte2tsx: 0.7.45(svelte@4.2.20)(typescript@5.9.3) transitivePeerDependencies: - typescript - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) - debug: 4.4.3 + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) + debug: 4.4.3(supports-color@5.5.0) svelte: 4.2.20 - vite: 5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0) + vite: 5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.39.5)(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)))(svelte@5.39.5)(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0))': + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.0)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@5.43.0)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.39.5)(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) - debug: 4.4.3 - svelte: 5.39.5 - vite: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) + '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.43.0)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + debug: 4.4.3(supports-color@5.5.0) + svelte: 5.43.0 + vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0))': + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) - debug: 4.4.3 + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) + debug: 4.4.3(supports-color@5.5.0) deepmerge: 4.3.1 kleur: 4.1.5 - magic-string: 0.30.19 + magic-string: 0.30.21 svelte: 4.2.20 svelte-hmr: 0.16.0(svelte@4.2.20) - vite: 5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0) - vitefu: 0.2.5(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)) + vite: 5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0) + vitefu: 0.2.5(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.39.5)(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0))': + '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.0)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.39.5)(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)))(svelte@5.39.5)(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) - debug: 4.4.3 + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.0)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@5.43.0)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + debug: 4.4.3(supports-color@5.5.0) deepmerge: 4.3.1 kleur: 4.1.5 - magic-string: 0.30.19 - svelte: 5.39.5 - vite: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) - vitefu: 1.1.1(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)) + magic-string: 0.30.21 + svelte: 5.43.0 + vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + vitefu: 1.1.1(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) transitivePeerDependencies: - supports-color - '@tailwindcss/node@4.1.13': + '@tailwindcss/node@4.1.16': dependencies: '@jridgewell/remapping': 2.3.5 enhanced-resolve: 5.18.3 - jiti: 2.6.0 - lightningcss: 1.30.1 - magic-string: 0.30.19 + jiti: 2.6.1 + lightningcss: 1.30.2 + magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.1.13 + tailwindcss: 4.1.16 - '@tailwindcss/oxide-android-arm64@4.1.13': + '@tailwindcss/oxide-android-arm64@4.1.16': optional: true - '@tailwindcss/oxide-darwin-arm64@4.1.13': + '@tailwindcss/oxide-darwin-arm64@4.1.16': optional: true - '@tailwindcss/oxide-darwin-x64@4.1.13': + '@tailwindcss/oxide-darwin-x64@4.1.16': optional: true - '@tailwindcss/oxide-freebsd-x64@4.1.13': + '@tailwindcss/oxide-freebsd-x64@4.1.16': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.1.13': + '@tailwindcss/oxide-linux-arm64-gnu@4.1.16': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.1.13': + '@tailwindcss/oxide-linux-arm64-musl@4.1.16': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.1.13': + '@tailwindcss/oxide-linux-x64-gnu@4.1.16': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.1.13': + '@tailwindcss/oxide-linux-x64-musl@4.1.16': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.1.13': + '@tailwindcss/oxide-wasm32-wasi@4.1.16': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.1.13': + '@tailwindcss/oxide-win32-arm64-msvc@4.1.16': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.1.13': + '@tailwindcss/oxide-win32-x64-msvc@4.1.16': optional: true - '@tailwindcss/oxide@4.1.13': - dependencies: - detect-libc: 2.1.0 - tar: 7.5.1 + '@tailwindcss/oxide@4.1.16': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.1.13 - '@tailwindcss/oxide-darwin-arm64': 4.1.13 - '@tailwindcss/oxide-darwin-x64': 4.1.13 - '@tailwindcss/oxide-freebsd-x64': 4.1.13 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.13 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.13 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.13 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.13 - '@tailwindcss/oxide-linux-x64-musl': 4.1.13 - '@tailwindcss/oxide-wasm32-wasi': 4.1.13 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.13 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.13 - - '@tailwindcss/typography@0.5.18(tailwindcss@4.1.13)': + '@tailwindcss/oxide-android-arm64': 4.1.16 + '@tailwindcss/oxide-darwin-arm64': 4.1.16 + '@tailwindcss/oxide-darwin-x64': 4.1.16 + '@tailwindcss/oxide-freebsd-x64': 4.1.16 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.16 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.16 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.16 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.16 + '@tailwindcss/oxide-linux-x64-musl': 4.1.16 + '@tailwindcss/oxide-wasm32-wasi': 4.1.16 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.16 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.16 + + '@tailwindcss/typography@0.5.19(tailwindcss@4.1.16)': dependencies: postcss-selector-parser: 6.0.10 - tailwindcss: 4.1.13 + tailwindcss: 4.1.16 - '@tailwindcss/vite@4.1.13(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0))': + '@tailwindcss/vite@4.1.16(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@tailwindcss/node': 4.1.13 - '@tailwindcss/oxide': 4.1.13 - tailwindcss: 4.1.13 - vite: 5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0) + '@tailwindcss/node': 4.1.16 + '@tailwindcss/oxide': 4.1.16 + tailwindcss: 4.1.16 + vite: 5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0) - '@tailwindcss/vite@4.1.13(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0))': + '@tailwindcss/vite@4.1.16(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@tailwindcss/node': 4.1.13 - '@tailwindcss/oxide': 4.1.13 - tailwindcss: 4.1.13 - vite: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) + '@tailwindcss/node': 4.1.16 + '@tailwindcss/oxide': 4.1.16 + tailwindcss: 4.1.16 + vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) '@tsconfig/svelte@5.0.5': {} '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@types/cookie@0.6.0': {} @@ -3902,64 +3881,48 @@ snapshots: '@types/lodash@4.17.20': {} - '@types/node@18.19.127': + '@types/node@18.19.130': dependencies: undici-types: 5.26.5 - '@types/node@22.18.6': + '@types/node@22.18.13': dependencies: undici-types: 6.21.0 - '@types/node@24.3.2': - dependencies: - undici-types: 7.10.0 - - '@types/node@24.5.2': + '@types/node@24.9.2': dependencies: - undici-types: 7.12.0 + undici-types: 7.16.0 '@types/nprogress@0.2.3': {} '@types/qs@6.14.0': {} - '@types/react-dom@19.1.9(@types/react@19.1.13)': + '@types/react-dom@19.2.2(@types/react@19.2.2)': dependencies: - '@types/react': 19.1.13 + '@types/react': 19.2.2 - '@types/react@19.1.13': + '@types/react@19.2.2': dependencies: csstype: 3.1.3 '@types/triple-beam@1.3.5': {} - '@vitejs/plugin-react@4.7.0(vite@6.3.6(@types/node@24.3.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0))': + '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@babel/core': 7.28.4 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.4) + '@babel/core': 7.28.5 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5) '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.3.6(@types/node@24.3.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) + vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@4.7.0(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0))': + '@vitejs/plugin-vue@5.2.4(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))(vue@3.5.22(typescript@5.9.3))': dependencies: - '@babel/core': 7.28.4 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.4) - '@rolldown/pluginutils': 1.0.0-beta.27 - '@types/babel__core': 7.20.5 - react-refresh: 0.17.0 - vite: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) - transitivePeerDependencies: - - supports-color - - '@vitejs/plugin-vue@5.2.4(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0))(vue@3.5.21(typescript@5.9.2))': - dependencies: - vite: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) - vue: 3.5.21(typescript@5.9.2) + vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + vue: 3.5.22(typescript@5.9.3) '@volar/language-core@2.4.15': dependencies: @@ -3973,77 +3936,77 @@ snapshots: path-browserify: 1.0.1 vscode-uri: 3.1.0 - '@vue/compiler-core@3.5.21': + '@vue/compiler-core@3.5.22': dependencies: - '@babel/parser': 7.28.4 - '@vue/shared': 3.5.21 + '@babel/parser': 7.28.5 + '@vue/shared': 3.5.22 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.1 - '@vue/compiler-dom@3.5.21': + '@vue/compiler-dom@3.5.22': dependencies: - '@vue/compiler-core': 3.5.21 - '@vue/shared': 3.5.21 + '@vue/compiler-core': 3.5.22 + '@vue/shared': 3.5.22 - '@vue/compiler-sfc@3.5.21': + '@vue/compiler-sfc@3.5.22': dependencies: - '@babel/parser': 7.28.4 - '@vue/compiler-core': 3.5.21 - '@vue/compiler-dom': 3.5.21 - '@vue/compiler-ssr': 3.5.21 - '@vue/shared': 3.5.21 + '@babel/parser': 7.28.5 + '@vue/compiler-core': 3.5.22 + '@vue/compiler-dom': 3.5.22 + '@vue/compiler-ssr': 3.5.22 + '@vue/shared': 3.5.22 estree-walker: 2.0.2 - magic-string: 0.30.19 + magic-string: 0.30.21 postcss: 8.5.6 source-map-js: 1.2.1 - '@vue/compiler-ssr@3.5.21': + '@vue/compiler-ssr@3.5.22': dependencies: - '@vue/compiler-dom': 3.5.21 - '@vue/shared': 3.5.21 + '@vue/compiler-dom': 3.5.22 + '@vue/shared': 3.5.22 '@vue/compiler-vue2@2.7.16': dependencies: de-indent: 1.0.2 he: 1.2.0 - '@vue/language-core@2.2.12(typescript@5.9.2)': + '@vue/language-core@2.2.12(typescript@5.9.3)': dependencies: '@volar/language-core': 2.4.15 - '@vue/compiler-dom': 3.5.21 + '@vue/compiler-dom': 3.5.22 '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.5.21 + '@vue/shared': 3.5.22 alien-signals: 1.0.13 minimatch: 9.0.5 muggle-string: 0.4.1 path-browserify: 1.0.1 optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 - '@vue/reactivity@3.5.21': + '@vue/reactivity@3.5.22': dependencies: - '@vue/shared': 3.5.21 + '@vue/shared': 3.5.22 - '@vue/runtime-core@3.5.21': + '@vue/runtime-core@3.5.22': dependencies: - '@vue/reactivity': 3.5.21 - '@vue/shared': 3.5.21 + '@vue/reactivity': 3.5.22 + '@vue/shared': 3.5.22 - '@vue/runtime-dom@3.5.21': + '@vue/runtime-dom@3.5.22': dependencies: - '@vue/reactivity': 3.5.21 - '@vue/runtime-core': 3.5.21 - '@vue/shared': 3.5.21 + '@vue/reactivity': 3.5.22 + '@vue/runtime-core': 3.5.22 + '@vue/shared': 3.5.22 csstype: 3.1.3 - '@vue/server-renderer@3.5.21(vue@3.5.21(typescript@5.9.2))': + '@vue/server-renderer@3.5.22(vue@3.5.22(typescript@5.9.3))': dependencies: - '@vue/compiler-ssr': 3.5.21 - '@vue/shared': 3.5.21 - vue: 3.5.21(typescript@5.9.2) + '@vue/compiler-ssr': 3.5.22 + '@vue/shared': 3.5.22 + vue: 3.5.22(typescript@5.9.3) - '@vue/shared@3.5.21': {} + '@vue/shared@3.5.22': {} '@webassemblyjs/ast@1.14.1': dependencies: @@ -4210,7 +4173,7 @@ snapshots: autosize@6.0.1: {} - axios@1.12.2: + axios@1.13.1: dependencies: follow-redirects: 1.15.11 form-data: 4.0.4 @@ -4222,7 +4185,7 @@ snapshots: balanced-match@1.0.2: {} - baseline-browser-mapping@2.8.6: {} + baseline-browser-mapping@2.8.21: {} big.js@5.2.2: {} @@ -4258,13 +4221,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.26.2: + browserslist@4.27.0: dependencies: - baseline-browser-mapping: 2.8.6 - caniuse-lite: 1.0.30001743 - electron-to-chromium: 1.5.223 - node-releases: 2.0.21 - update-browserslist-db: 1.1.3(browserslist@4.26.2) + baseline-browser-mapping: 2.8.21 + caniuse-lite: 1.0.30001751 + electron-to-chromium: 1.5.243 + node-releases: 2.0.27 + update-browserslist-db: 1.1.4(browserslist@4.27.0) buffer-from@1.1.2: {} @@ -4286,7 +4249,7 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001743: {} + caniuse-lite@1.0.30001751: {} chalk@2.4.2: dependencies: @@ -4315,8 +4278,6 @@ snapshots: dependencies: readdirp: 4.1.2 - chownr@3.0.0: {} - chrome-trace-event@1.0.4: {} clsx@2.1.1: {} @@ -4337,30 +4298,30 @@ snapshots: dependencies: color-name: 1.1.4 + color-convert@3.1.2: + dependencies: + color-name: 2.0.2 + color-name@1.1.3: {} color-name@1.1.4: {} - color-string@1.9.1: - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.4 + color-name@2.0.2: {} - color@3.2.1: + color-string@2.1.2: dependencies: - color-convert: 1.9.3 - color-string: 1.9.1 + color-name: 2.0.2 - colorspace@1.1.4: + color@5.0.2: dependencies: - color: 3.2.1 - text-hex: 1.0.0 + color-convert: 3.1.2 + color-string: 2.1.2 combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 - commander@14.0.0: {} + commander@14.0.1: {} commander@2.20.3: {} @@ -4404,7 +4365,7 @@ snapshots: postcss-modules-values: 4.0.0(postcss@8.5.6) postcss-value-parser: 4.2.0 schema-utils: 3.3.0 - semver: 7.7.2 + semver: 7.7.3 webpack: 5.101.3 css-tree@2.3.1: @@ -4422,16 +4383,12 @@ snapshots: dependencies: ms: 2.0.0 - debug@4.4.1(supports-color@5.5.0): + debug@4.4.3(supports-color@5.5.0): dependencies: ms: 2.1.3 optionalDependencies: supports-color: 5.5.0 - debug@4.4.3: - dependencies: - ms: 2.1.3 - dedent-js@1.0.1: {} deep-is@0.1.4: {} @@ -4444,9 +4401,9 @@ snapshots: destroy@1.2.0: {} - detect-libc@2.1.0: {} + detect-libc@2.1.2: {} - devalue@5.3.2: {} + devalue@5.4.2: {} doctrine@3.0.0: dependencies: @@ -4460,7 +4417,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.223: {} + electron-to-chromium@1.5.243: {} emoji-regex@8.0.0: {} @@ -4475,7 +4432,7 @@ snapshots: enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 - tapable: 2.2.3 + tapable: 2.3.0 enquirer@2.4.1: dependencies: @@ -4484,12 +4441,13 @@ snapshots: entities@4.5.0: {} - es-check@9.3.1: + es-check@9.4.4: dependencies: acorn: 8.15.0 acorn-walk: 8.3.4 - browserslist: 4.26.2 - commander: 14.0.0 + browserslist: 4.27.0 + commander: 14.0.1 + fast-brake: 0.1.6 fast-glob: 3.3.3 lilconfig: 3.1.3 source-map: 0.7.6 @@ -4513,9 +4471,9 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 - esbuild-node-externals@1.18.0(esbuild@0.25.10): + esbuild-node-externals@1.18.0(esbuild@0.25.11): dependencies: - esbuild: 0.25.10 + esbuild: 0.25.11 find-up: 5.0.0 esbuild@0.21.5: @@ -4544,34 +4502,34 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - esbuild@0.25.10: + esbuild@0.25.11: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.10 - '@esbuild/android-arm': 0.25.10 - '@esbuild/android-arm64': 0.25.10 - '@esbuild/android-x64': 0.25.10 - '@esbuild/darwin-arm64': 0.25.10 - '@esbuild/darwin-x64': 0.25.10 - '@esbuild/freebsd-arm64': 0.25.10 - '@esbuild/freebsd-x64': 0.25.10 - '@esbuild/linux-arm': 0.25.10 - '@esbuild/linux-arm64': 0.25.10 - '@esbuild/linux-ia32': 0.25.10 - '@esbuild/linux-loong64': 0.25.10 - '@esbuild/linux-mips64el': 0.25.10 - '@esbuild/linux-ppc64': 0.25.10 - '@esbuild/linux-riscv64': 0.25.10 - '@esbuild/linux-s390x': 0.25.10 - '@esbuild/linux-x64': 0.25.10 - '@esbuild/netbsd-arm64': 0.25.10 - '@esbuild/netbsd-x64': 0.25.10 - '@esbuild/openbsd-arm64': 0.25.10 - '@esbuild/openbsd-x64': 0.25.10 - '@esbuild/openharmony-arm64': 0.25.10 - '@esbuild/sunos-x64': 0.25.10 - '@esbuild/win32-arm64': 0.25.10 - '@esbuild/win32-ia32': 0.25.10 - '@esbuild/win32-x64': 0.25.10 + '@esbuild/aix-ppc64': 0.25.11 + '@esbuild/android-arm': 0.25.11 + '@esbuild/android-arm64': 0.25.11 + '@esbuild/android-x64': 0.25.11 + '@esbuild/darwin-arm64': 0.25.11 + '@esbuild/darwin-x64': 0.25.11 + '@esbuild/freebsd-arm64': 0.25.11 + '@esbuild/freebsd-x64': 0.25.11 + '@esbuild/linux-arm': 0.25.11 + '@esbuild/linux-arm64': 0.25.11 + '@esbuild/linux-ia32': 0.25.11 + '@esbuild/linux-loong64': 0.25.11 + '@esbuild/linux-mips64el': 0.25.11 + '@esbuild/linux-ppc64': 0.25.11 + '@esbuild/linux-riscv64': 0.25.11 + '@esbuild/linux-s390x': 0.25.11 + '@esbuild/linux-x64': 0.25.11 + '@esbuild/netbsd-arm64': 0.25.11 + '@esbuild/netbsd-x64': 0.25.11 + '@esbuild/openbsd-arm64': 0.25.11 + '@esbuild/openbsd-x64': 0.25.11 + '@esbuild/openharmony-arm64': 0.25.11 + '@esbuild/sunos-x64': 0.25.11 + '@esbuild/win32-arm64': 0.25.11 + '@esbuild/win32-ia32': 0.25.11 + '@esbuild/win32-x64': 0.25.11 escalade@3.2.0: {} @@ -4602,7 +4560,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) doctrine: 3.0.0 enquirer: 2.4.1 escape-string-regexp: 4.0.0 @@ -4630,7 +4588,7 @@ snapshots: optionator: 0.9.4 progress: 2.0.3 regexpp: 3.2.0 - semver: 7.7.2 + semver: 7.7.3 strip-ansi: 6.0.1 strip-json-comments: 3.1.1 table: 6.9.0 @@ -4653,7 +4611,7 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@2.1.0: + esrap@2.1.1: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -4713,6 +4671,8 @@ snapshots: transitivePeerDependencies: - supports-color + fast-brake@0.1.6: {} + fast-deep-equal@3.1.3: {} fast-glob@3.3.3: @@ -4909,8 +4869,6 @@ snapshots: ipaddr.js@1.9.1: {} - is-arrayish@0.3.4: {} - is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -4935,11 +4893,11 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 24.5.2 + '@types/node': 24.9.2 merge-stream: 2.0.0 supports-color: 8.1.1 - jiti@2.6.0: {} + jiti@2.6.1: {} js-tokens@4.0.0: {} @@ -4970,16 +4928,23 @@ snapshots: kuler@2.0.0: {} - laravel-vite-plugin@1.3.0(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)): + laravel-precognition@0.7.3: + dependencies: + axios: 1.13.1 + lodash-es: 4.17.21 + transitivePeerDependencies: + - debug + + laravel-vite-plugin@1.3.0(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)): dependencies: picocolors: 1.1.1 - vite: 5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0) + vite: 5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0) vite-plugin-full-reload: 1.2.0 - laravel-vite-plugin@1.3.0(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)): + laravel-vite-plugin@1.3.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)): dependencies: picocolors: 1.1.1 - vite: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) + vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) vite-plugin-full-reload: 1.2.0 levn@0.4.1: @@ -4987,54 +4952,58 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lightningcss-darwin-arm64@1.30.1: + lightningcss-android-arm64@1.30.2: + optional: true + + lightningcss-darwin-arm64@1.30.2: optional: true - lightningcss-darwin-x64@1.30.1: + lightningcss-darwin-x64@1.30.2: optional: true - lightningcss-freebsd-x64@1.30.1: + lightningcss-freebsd-x64@1.30.2: optional: true - lightningcss-linux-arm-gnueabihf@1.30.1: + lightningcss-linux-arm-gnueabihf@1.30.2: optional: true - lightningcss-linux-arm64-gnu@1.30.1: + lightningcss-linux-arm64-gnu@1.30.2: optional: true - lightningcss-linux-arm64-musl@1.30.1: + lightningcss-linux-arm64-musl@1.30.2: optional: true - lightningcss-linux-x64-gnu@1.30.1: + lightningcss-linux-x64-gnu@1.30.2: optional: true - lightningcss-linux-x64-musl@1.30.1: + lightningcss-linux-x64-musl@1.30.2: optional: true - lightningcss-win32-arm64-msvc@1.30.1: + lightningcss-win32-arm64-msvc@1.30.2: optional: true - lightningcss-win32-x64-msvc@1.30.1: + lightningcss-win32-x64-msvc@1.30.2: optional: true - lightningcss@1.30.1: + lightningcss@1.30.2: dependencies: - detect-libc: 2.1.0 + detect-libc: 2.1.2 optionalDependencies: - lightningcss-darwin-arm64: 1.30.1 - lightningcss-darwin-x64: 1.30.1 - lightningcss-freebsd-x64: 1.30.1 - lightningcss-linux-arm-gnueabihf: 1.30.1 - lightningcss-linux-arm64-gnu: 1.30.1 - lightningcss-linux-arm64-musl: 1.30.1 - lightningcss-linux-x64-gnu: 1.30.1 - lightningcss-linux-x64-musl: 1.30.1 - lightningcss-win32-arm64-msvc: 1.30.1 - lightningcss-win32-x64-msvc: 1.30.1 + lightningcss-android-arm64: 1.30.2 + lightningcss-darwin-arm64: 1.30.2 + lightningcss-darwin-x64: 1.30.2 + lightningcss-freebsd-x64: 1.30.2 + lightningcss-linux-arm-gnueabihf: 1.30.2 + lightningcss-linux-arm64-gnu: 1.30.2 + lightningcss-linux-arm64-musl: 1.30.2 + lightningcss-linux-x64-gnu: 1.30.2 + lightningcss-linux-x64-musl: 1.30.2 + lightningcss-win32-arm64-msvc: 1.30.2 + lightningcss-win32-x64-msvc: 1.30.2 lilconfig@3.1.3: {} - loader-runner@4.3.0: {} + loader-runner@4.3.1: {} loader-utils@2.0.4: dependencies: @@ -5069,11 +5038,11 @@ snapshots: dependencies: yallist: 3.1.1 - magic-string@0.30.19: + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - marked@16.3.0: {} + marked@16.4.1: {} math-intrinsics@1.1.0: {} @@ -5116,12 +5085,6 @@ snapshots: minimist@1.2.8: {} - minipass@7.1.2: {} - - minizlib@3.1.0: - dependencies: - minipass: 7.1.2 - mkdirp@0.5.6: dependencies: minimist: 1.2.8 @@ -5156,16 +5119,16 @@ snapshots: neo-async@2.6.2: {} - node-releases@2.0.21: {} + node-releases@2.0.27: {} nodemon@3.1.10: dependencies: chokidar: 3.6.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) ignore-by-default: 1.0.1 minimatch: 3.1.2 pstree.remy: 1.1.8 - semver: 7.7.2 + semver: 7.7.3 simple-update-notifier: 2.0.0 supports-color: 5.5.0 touch: 3.1.1 @@ -5247,11 +5210,11 @@ snapshots: picomatch@4.0.3: {} - playwright-core@1.55.1: {} + playwright-core@1.56.1: {} - playwright@1.55.1: + playwright@1.56.1: dependencies: - playwright-core: 1.55.1 + playwright-core: 1.56.1 optionalDependencies: fsevents: 2.3.2 @@ -5296,24 +5259,24 @@ snapshots: prelude-ls@1.2.1: {} - prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.2)(vue-tsc@2.2.12(typescript@5.9.2)): + prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)): dependencies: prettier: 3.6.2 - typescript: 5.9.2 + typescript: 5.9.3 optionalDependencies: - vue-tsc: 2.2.12(typescript@5.9.2) + vue-tsc: 2.2.12(typescript@5.9.3) - prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.39.5): + prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.43.0): dependencies: prettier: 3.6.2 - svelte: 5.39.5 + svelte: 5.43.0 - prettier-plugin-tailwindcss@0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.2)(vue-tsc@2.2.12(typescript@5.9.2)))(prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.39.5))(prettier@3.6.2): + prettier-plugin-tailwindcss@0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)))(prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.43.0))(prettier@3.6.2): dependencies: prettier: 3.6.2 optionalDependencies: - prettier-plugin-organize-imports: 4.3.0(prettier@3.6.2)(typescript@5.9.2)(vue-tsc@2.2.12(typescript@5.9.2)) - prettier-plugin-svelte: 3.4.0(prettier@3.6.2)(svelte@5.39.5) + prettier-plugin-organize-imports: 4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)) + prettier-plugin-svelte: 3.4.0(prettier@3.6.2)(svelte@5.43.0) prettier@3.6.2: {} @@ -5359,14 +5322,14 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 - react-dom@19.1.1(react@19.1.1): + react-dom@19.2.0(react@19.2.0): dependencies: - react: 19.1.1 - scheduler: 0.26.0 + react: 19.2.0 + scheduler: 0.27.0 react-refresh@0.17.0: {} - react@19.1.1: {} + react@19.2.0: {} readable-stream@3.6.2: dependencies: @@ -5392,32 +5355,32 @@ snapshots: dependencies: glob: 7.2.3 - rollup@4.52.2: + rollup@4.52.5: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.52.2 - '@rollup/rollup-android-arm64': 4.52.2 - '@rollup/rollup-darwin-arm64': 4.52.2 - '@rollup/rollup-darwin-x64': 4.52.2 - '@rollup/rollup-freebsd-arm64': 4.52.2 - '@rollup/rollup-freebsd-x64': 4.52.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.52.2 - '@rollup/rollup-linux-arm-musleabihf': 4.52.2 - '@rollup/rollup-linux-arm64-gnu': 4.52.2 - '@rollup/rollup-linux-arm64-musl': 4.52.2 - '@rollup/rollup-linux-loong64-gnu': 4.52.2 - '@rollup/rollup-linux-ppc64-gnu': 4.52.2 - '@rollup/rollup-linux-riscv64-gnu': 4.52.2 - '@rollup/rollup-linux-riscv64-musl': 4.52.2 - '@rollup/rollup-linux-s390x-gnu': 4.52.2 - '@rollup/rollup-linux-x64-gnu': 4.52.2 - '@rollup/rollup-linux-x64-musl': 4.52.2 - '@rollup/rollup-openharmony-arm64': 4.52.2 - '@rollup/rollup-win32-arm64-msvc': 4.52.2 - '@rollup/rollup-win32-ia32-msvc': 4.52.2 - '@rollup/rollup-win32-x64-gnu': 4.52.2 - '@rollup/rollup-win32-x64-msvc': 4.52.2 + '@rollup/rollup-android-arm-eabi': 4.52.5 + '@rollup/rollup-android-arm64': 4.52.5 + '@rollup/rollup-darwin-arm64': 4.52.5 + '@rollup/rollup-darwin-x64': 4.52.5 + '@rollup/rollup-freebsd-arm64': 4.52.5 + '@rollup/rollup-freebsd-x64': 4.52.5 + '@rollup/rollup-linux-arm-gnueabihf': 4.52.5 + '@rollup/rollup-linux-arm-musleabihf': 4.52.5 + '@rollup/rollup-linux-arm64-gnu': 4.52.5 + '@rollup/rollup-linux-arm64-musl': 4.52.5 + '@rollup/rollup-linux-loong64-gnu': 4.52.5 + '@rollup/rollup-linux-ppc64-gnu': 4.52.5 + '@rollup/rollup-linux-riscv64-gnu': 4.52.5 + '@rollup/rollup-linux-riscv64-musl': 4.52.5 + '@rollup/rollup-linux-s390x-gnu': 4.52.5 + '@rollup/rollup-linux-x64-gnu': 4.52.5 + '@rollup/rollup-linux-x64-musl': 4.52.5 + '@rollup/rollup-openharmony-arm64': 4.52.5 + '@rollup/rollup-win32-arm64-msvc': 4.52.5 + '@rollup/rollup-win32-ia32-msvc': 4.52.5 + '@rollup/rollup-win32-x64-gnu': 4.52.5 + '@rollup/rollup-win32-x64-msvc': 4.52.5 fsevents: 2.3.3 run-parallel@1.2.0: @@ -5434,7 +5397,7 @@ snapshots: safer-buffer@2.1.2: {} - scheduler@0.26.0: {} + scheduler@0.27.0: {} schema-utils@3.3.0: dependencies: @@ -5442,7 +5405,7 @@ snapshots: ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) - schema-utils@4.3.2: + schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 ajv: 8.17.1 @@ -5453,7 +5416,7 @@ snapshots: semver@6.3.1: {} - semver@7.7.2: {} + semver@7.7.3: {} send@0.19.0: dependencies: @@ -5486,7 +5449,7 @@ snapshots: transitivePeerDependencies: - supports-color - set-cookie-parser@2.7.1: {} + set-cookie-parser@2.7.2: {} setprototypeof@1.2.0: {} @@ -5524,13 +5487,9 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - simple-swizzle@0.2.4: - dependencies: - is-arrayish: 0.3.4 - simple-update-notifier@2.0.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 sirv@3.0.2: dependencies: @@ -5591,19 +5550,7 @@ snapshots: dependencies: has-flag: 4.0.0 - svelte-check@4.3.1(picomatch@4.0.3)(svelte@4.2.20)(typescript@5.9.2): - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - chokidar: 4.0.3 - fdir: 6.5.0(picomatch@4.0.3) - picocolors: 1.1.1 - sade: 1.8.1 - svelte: 4.2.20 - typescript: 5.9.2 - transitivePeerDependencies: - - picomatch - - svelte-check@4.3.2(picomatch@4.0.3)(svelte@4.2.20)(typescript@5.9.2): + svelte-check@4.3.3(picomatch@4.0.3)(svelte@4.2.20)(typescript@5.9.3): dependencies: '@jridgewell/trace-mapping': 0.3.31 chokidar: 4.0.3 @@ -5611,19 +5558,19 @@ snapshots: picocolors: 1.1.1 sade: 1.8.1 svelte: 4.2.20 - typescript: 5.9.2 + typescript: 5.9.3 transitivePeerDependencies: - picomatch - svelte-check@4.3.2(picomatch@4.0.3)(svelte@5.39.5)(typescript@5.9.2): + svelte-check@4.3.3(picomatch@4.0.3)(svelte@5.43.0)(typescript@5.9.3): dependencies: '@jridgewell/trace-mapping': 0.3.31 chokidar: 4.0.3 fdir: 6.5.0(picomatch@4.0.3) picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.39.5 - typescript: 5.9.2 + svelte: 5.43.0 + typescript: 5.9.3 transitivePeerDependencies: - picomatch @@ -5631,12 +5578,12 @@ snapshots: dependencies: svelte: 4.2.20 - svelte2tsx@0.7.44(svelte@4.2.20)(typescript@5.9.2): + svelte2tsx@0.7.45(svelte@4.2.20)(typescript@5.9.3): dependencies: dedent-js: 1.0.1 scule: 1.3.0 svelte: 4.2.20 - typescript: 5.9.2 + typescript: 5.9.3 svelte@4.2.20: dependencies: @@ -5652,24 +5599,24 @@ snapshots: estree-walker: 3.0.3 is-reference: 3.0.3 locate-character: 3.0.0 - magic-string: 0.30.19 + magic-string: 0.30.21 periscopic: 3.1.0 - svelte@5.39.5: + svelte@5.43.0: dependencies: '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 - '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) + '@sveltejs/acorn-typescript': 1.0.6(acorn@8.15.0) '@types/estree': 1.0.8 acorn: 8.15.0 aria-query: 5.3.2 axobject-query: 4.1.0 clsx: 2.1.1 esm-env: 1.2.2 - esrap: 2.1.0 + esrap: 2.1.1 is-reference: 3.0.3 locate-character: 3.0.0 - magic-string: 0.30.19 + magic-string: 0.30.21 zimmerframe: 1.1.4 table@6.9.0: @@ -5680,23 +5627,15 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - tailwindcss@4.1.13: {} + tailwindcss@4.1.16: {} - tapable@2.2.3: {} - - tar@7.5.1: - dependencies: - '@isaacs/fs-minipass': 4.0.1 - chownr: 3.0.0 - minipass: 7.1.2 - minizlib: 3.1.0 - yallist: 5.0.0 + tapable@2.3.0: {} terser-webpack-plugin@5.3.14(webpack@5.101.3): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 - schema-utils: 4.3.2 + schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.44.0 webpack: 5.101.3 @@ -5746,7 +5685,7 @@ snapshots: typescript@4.9.5: {} - typescript@5.9.2: {} + typescript@5.9.3: {} undefsafe@2.0.5: {} @@ -5754,15 +5693,13 @@ snapshots: undici-types@6.21.0: {} - undici-types@7.10.0: {} - - undici-types@7.12.0: {} + undici-types@7.16.0: {} unpipe@1.0.0: {} - update-browserslist-db@1.1.3(browserslist@4.26.2): + update-browserslist-db@1.1.4(browserslist@4.27.0): dependencies: - browserslist: 4.26.2 + browserslist: 4.27.0 escalade: 3.2.0 picocolors: 1.1.1 @@ -5783,72 +5720,57 @@ snapshots: picocolors: 1.1.1 picomatch: 2.3.1 - vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0): + vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0): dependencies: esbuild: 0.21.5 postcss: 8.5.6 - rollup: 4.52.2 + rollup: 4.52.5 optionalDependencies: - '@types/node': 24.5.2 + '@types/node': 24.9.2 fsevents: 2.3.3 - lightningcss: 1.30.1 + lightningcss: 1.30.2 terser: 5.44.0 - vite@6.3.6(@types/node@24.3.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0): + vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0): dependencies: - esbuild: 0.25.10 + esbuild: 0.25.11 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.52.2 + rollup: 4.52.5 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.3.2 + '@types/node': 24.9.2 fsevents: 2.3.3 - jiti: 2.6.0 - lightningcss: 1.30.1 + jiti: 2.6.1 + lightningcss: 1.30.2 terser: 5.44.0 - vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0): - dependencies: - esbuild: 0.25.10 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.52.2 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 24.5.2 - fsevents: 2.3.3 - jiti: 2.6.0 - lightningcss: 1.30.1 - terser: 5.44.0 - - vitefu@0.2.5(vite@5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0)): + vitefu@0.2.5(vite@5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0)): optionalDependencies: - vite: 5.4.20(@types/node@24.5.2)(lightningcss@1.30.1)(terser@5.44.0) + vite: 5.4.21(@types/node@24.9.2)(lightningcss@1.30.2)(terser@5.44.0) - vitefu@1.1.1(vite@6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)): + vitefu@1.1.1(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)): optionalDependencies: - vite: 6.3.6(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0) + vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) vscode-uri@3.1.0: {} - vue-tsc@2.2.12(typescript@5.9.2): + vue-tsc@2.2.12(typescript@5.9.3): dependencies: '@volar/typescript': 2.4.15 - '@vue/language-core': 2.2.12(typescript@5.9.2) - typescript: 5.9.2 + '@vue/language-core': 2.2.12(typescript@5.9.3) + typescript: 5.9.3 - vue@3.5.21(typescript@5.9.2): + vue@3.5.22(typescript@5.9.3): dependencies: - '@vue/compiler-dom': 3.5.21 - '@vue/compiler-sfc': 3.5.21 - '@vue/runtime-dom': 3.5.21 - '@vue/server-renderer': 3.5.21(vue@3.5.21(typescript@5.9.2)) - '@vue/shared': 3.5.21 + '@vue/compiler-dom': 3.5.22 + '@vue/compiler-sfc': 3.5.22 + '@vue/runtime-dom': 3.5.22 + '@vue/server-renderer': 3.5.22(vue@3.5.22(typescript@5.9.3)) + '@vue/shared': 3.5.22 optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 watchpack@2.4.4: dependencies: @@ -5867,7 +5789,7 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.26.2 + browserslist: 4.27.0 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.3 es-module-lexer: 1.7.0 @@ -5876,11 +5798,11 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 + loader-runner: 4.3.1 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 4.3.2 - tapable: 2.2.3 + schema-utils: 4.3.3 + tapable: 2.3.0 terser-webpack-plugin: 5.3.14(webpack@5.101.3) watchpack: 2.4.4 webpack-sources: 3.3.3 @@ -5902,7 +5824,7 @@ snapshots: winston@3.17.0: dependencies: '@colors/colors': 1.6.0 - '@dabh/diagnostics': 2.0.3 + '@dabh/diagnostics': 2.0.8 async: 3.2.6 is-stream: 2.0.1 logform: 2.7.0 @@ -5921,8 +5843,6 @@ snapshots: yallist@3.1.1: {} - yallist@5.0.0: {} - yocto-queue@0.1.0: {} zimmerframe@1.1.4: {} diff --git a/tests/app/package.json b/tests/app/package.json index 1cc66b0b7..ffbefe448 100644 --- a/tests/app/package.json +++ b/tests/app/package.json @@ -5,11 +5,11 @@ "serve:watch": "nodemon server.js" }, "devDependencies": { - "body-parser": "^1.19.0", - "css-loader": "^5.0.1", - "eslint": "^7.17.0", - "express": "^4.21.1", + "body-parser": "^1.20.3", + "css-loader": "^5.2.7", + "eslint": "^7.32.0", + "express": "^4.21.2", "multer": "^2.0.2", - "nodemon": "^3.0.0" + "nodemon": "^3.1.10" } } diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 9d258e21d..1ea756e29 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1746,7 +1746,7 @@ test.describe('Form Component', () => { await expect(page.locator('#any-touched')).toHaveText('Form has touched fields') }) - test('validate with specific field works independently of touched state', async ({ page }) => { + test('validating a specific field also validates previously touched inputs', async ({ page }) => { await page.goto('/form-component/precognition-methods') await page.fill('input[name="name"]', 'ab') @@ -1758,7 +1758,7 @@ test.describe('Form Component', () => { await expect(page.getByText('Validating...')).not.toBeVisible() await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() - await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() }) test('validate with array of fields validates multiple fields', async ({ page }) => { @@ -1806,23 +1806,6 @@ test.describe('Form Component', () => { await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() }) - test('touching one field and validating another does not validate the touched field', async ({ page }) => { - await page.goto('/form-component/precognition-methods') - - await page.fill('input[name="name"]', 'ab') - await page.locator('input[name="name"]').blur() - - await page.fill('input[name="email"]', 'x') - - await page.getByRole('button', { name: 'Validate Name', exact: true }).click() - - await expect(page.getByText('Validating...')).toBeVisible() - await expect(page.getByText('Validating...')).not.toBeVisible() - - await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() - await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() - }) - test('does not submit files by default', async ({ page }) => { await page.goto('/form-component/precognition-files') @@ -1923,21 +1906,6 @@ test.describe('Form Component', () => { } }) - test('onException handles non-422 errors during validation', async ({ page }) => { - await page.goto('/form-component/precognition-callbacks') - - await page.fill('#name-input', 'John') - - // Trigger validation that will return 500 error - await page.click('button:has-text("Validate with Exception Handler")') - - await expect(page.getByText('Validating...')).toBeVisible() - await expect(page.getByText('Validating...')).not.toBeVisible() - - // Exception should be caught and displayed - await expect(page.getByText(/Exception caught:/)).toBeVisible() - }) - test('sends custom headers with validation requests', async ({ page }) => { await page.goto('/form-component/precognition-headers') @@ -1976,24 +1944,6 @@ test.describe('Form Component', () => { expect(cancelledRequestError).toBe('net::ERR_ABORTED') }) - test('cancelValidation() cancels in-flight validation and resets validating state', async ({ page }) => { - await page.goto('/form-component/precognition-cancel') - - requests.listenForFailed(page) - - await page.fill('#manual-cancel-name-input', 'ab') - await page.locator('#manual-cancel-name-input').blur() - await expect(page.getByText('Validating...')).toBeVisible() - - await page.getByText('Cancel Validation').click() - await expect(page.getByText('Validating...')).not.toBeVisible() - await page.waitForTimeout(100) - expect(requests.failed).toHaveLength(1) - - const cancelledRequestError = await requests.failed[0].failure()?.errorText - expect(cancelledRequestError).toBe('net::ERR_ABORTED') - }) - test('defaults() updates validator data as well', async ({ page }) => { await page.goto('/form-component/precognition-defaults') From 8425e8de2153e58cf4b3136a017887523197b1af Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 30 Oct 2025 12:18:04 +0100 Subject: [PATCH 058/145] React --- packages/react/src/Form.ts | 195 ++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 111 deletions(-) diff --git a/packages/react/src/Form.ts b/packages/react/src/Form.ts index 555a662cd..4564aa556 100644 --- a/packages/react/src/Form.ts +++ b/packages/react/src/Form.ts @@ -1,17 +1,23 @@ import { + Errors, FormComponentProps, FormComponentRef, FormComponentSlotProps, - FormComponentValidateOptions, FormDataConvertible, formDataToObject, isUrlMethodPair, mergeDataIntoQueryString, Method, resetFormFields, - usePrecognition, VisitOptions, } from '@inertiajs/core' +import { + createValidator, + NamedInputEvent, + toSimpleValidationErrors, + ValidationConfig, + Validator, +} from 'laravel-precognition' import { isEqual } from 'lodash-es' import React, { createElement, @@ -85,18 +91,10 @@ const Form = forwardRef( const defaultData = useRef(new FormData()) const [validating, setValidating] = useState(false) - const [validated, setValidated] = useState([]) + const [valid, setValid] = useState([]) const [touched, setTouched] = useState([]) - const validator = useMemo( - () => - usePrecognition({ - timeout: validateTimeout, - onStart: () => setValidating(true), - onFinish: () => setValidating(false), - }), - [], - ) + const [validator, setValidator] = useState(null) const getFormData = (): FormData => new FormData(formElement.current) @@ -119,6 +117,25 @@ const Form = forwardRef( setIsDirty(event.type === 'reset' ? false : !isEqual(getData(), formDataToObject(defaultData.current))), ) + const clearErrors = (...names: string[]) => { + form.clearErrors(...names) + + if (validator) { + if (names.length === 0) { + validator.setErrors({}) + } else { + names.forEach(validator.forgetError) + } + } + + return form + } + + const getTransformedData = (): Record => { + const [_url, data] = getUrlAndData() + return transform(data) + } + useEffect(() => { defaultData.current = getFormData() @@ -126,42 +143,65 @@ const Form = forwardRef( formEvents.forEach((e) => formElement.current.addEventListener(e, updateDirtyState)) - return () => formEvents.forEach((e) => formElement.current?.removeEventListener(e, updateDirtyState)) - }, []) - - useEffect(() => { - validator.validateFiles(validateFiles) - }, [validateFiles, validator]) + // Initialize validator + const newValidator = createValidator( + (client) => + client[resolvedMethod](getUrlAndData()[0], getTransformedData(), { + headers, + }), + getTransformedData(), + ) + .on('validatingChanged', () => { + setValidating(newValidator.validating()) + }) + .on('validatedChanged', () => { + setValid(newValidator.valid()) + }) + .on('touchedChanged', () => { + setTouched(newValidator.touched()) + }) + .on('errorsChanged', () => { + form.clearErrors() + + form.setError( + (simpleValidationErrors + ? toSimpleValidationErrors(newValidator.errors()) + : newValidator.errors()) as Errors, + ) + + setValid(newValidator.valid()) + }) + + newValidator.setTimeout(validateTimeout) + + if (validateFiles) { + newValidator.validateFiles() + } - useEffect(() => { - validator.setTimeout(validateTimeout) - }, [validateTimeout, validator]) + setValidator(newValidator) - useEffect(() => { - updateDataOnValidator() + return () => { + formEvents.forEach((e) => formElement.current?.removeEventListener(e, updateDirtyState)) + newValidator?.reset() + } }, []) - const updateDataOnValidator = () => { - try { - // This might fail if the component is already unmounted but this function - // is called after navigating away after a form submission. - validator.setOldData(transform(getData())) - } catch {} - } + useEffect(() => { + if (validator) { + validator.setTimeout(validateTimeout) + } + }, [validateTimeout, validator]) const reset = (...fields: string[]) => { resetFormFields(formElement.current, defaultData.current, fields) - updateDataOnValidator() - if (fields.length === 0) { - setTouched([]) - } else { - setTouched((prev) => prev.filter((field) => !fields.includes(field))) + if (validator) { + validator.reset(...fields) } } const resetAndClearErrors = (...fields: string[]) => { - form.clearErrors(...fields) + clearErrors(...fields) reset(...fields) } @@ -217,70 +257,12 @@ const Form = forwardRef( const defaults = () => { defaultData.current = getFormData() setIsDirty(false) - updateDataOnValidator() } - const validate = ( - only?: string | string[] | FormComponentValidateOptions, - maybeOptions?: FormComponentValidateOptions, - ) => { - let fields: string[] - let options: FormComponentValidateOptions = {} - - if (typeof only === 'object' && !Array.isArray(only)) { - // Called as validate({ only: [...], onSuccess, onError, onFinish }) - const onlyFields = only.only - fields = onlyFields === undefined ? touched : Array.isArray(onlyFields) ? onlyFields : [onlyFields] - options = only - } else { - // Called as validate('field') or validate(['field1', 'field2']) or validate('field', {options}) - fields = only === undefined ? touched : Array.isArray(only) ? only : [only] - options = maybeOptions || {} + const touch = (...fields: string[]) => { + if (validator) { + validator.touch(fields) } - - // We're not using the data object from this method as it might be empty - // on GET requests, and we still want to pass a data object to the - // validator so it knows the current state of the form. - const [url] = getUrlAndData() - - validator.validate({ - url, - method: resolvedMethod, - data: transform(getData()), - only: fields, - errorBag, - headers, - simpleValidationErrors, - onBefore: options.onBefore, - onPrecognitionSuccess: () => { - setValidated((prev) => [...prev, ...fields]) - form.clearErrors(...fields) - options.onSuccess?.() - }, - onValidationError: (errors) => { - setValidated((prev) => [...prev, ...fields]) - - const validFields = fields.filter((field) => errors[field] === undefined) - - if (validFields.length) { - form.clearErrors(...validFields) - } - - form.setError({ ...form.errors, ...errors }) - options.onError?.(errors) - }, - onException: options.onException, - onFinish: () => { - options.onFinish?.() - }, - }) - } - - const touch = (field: string | string[]) => { - const fields = Array.isArray(field) ? field : [field] - - // Use Set to avoid duplicates - setTouched((prev) => [...new Set([...prev, ...fields])]) } const isTouched = (field?: string): boolean => { @@ -299,7 +281,7 @@ const Form = forwardRef( wasSuccessful: form.wasSuccessful, recentlySuccessful: form.recentlySuccessful, isDirty, - clearErrors: form.clearErrors, + clearErrors, resetAndClearErrors, setError: form.setError, reset, @@ -308,24 +290,15 @@ const Form = forwardRef( // Precognition validating, - valid: (field: string) => validated.includes(field) && form.errors[field] === undefined, + valid: (field: string) => valid.includes(field), invalid: (field: string) => form.errors[field] !== undefined, - validate, + validate: (input?: string | NamedInputEvent | ValidationConfig, value?: unknown, config?: ValidationConfig) => + validator?.validate(input, value, config), touch, touched: isTouched, }) - useImperativeHandle(ref, exposed, [ - form, - isDirty, - submit, - validating, - validated, - touched, - validate, - touch, - validator, - ]) + useImperativeHandle(ref, exposed, [form, isDirty, submit, validating, valid, touched, touch, validator]) return createElement( 'form', From 622f23702813a42cf9a4d39bc6374a2ce22a5360 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 30 Oct 2025 13:48:35 +0100 Subject: [PATCH 059/145] Svelte --- packages/react/src/Form.ts | 1 - packages/svelte/src/components/Form.svelte | 169 ++++++++---------- .../PrecognitionCallbacks.svelte | 2 +- 3 files changed, 75 insertions(+), 97 deletions(-) diff --git a/packages/react/src/Form.ts b/packages/react/src/Form.ts index 4564aa556..01a8b653d 100644 --- a/packages/react/src/Form.ts +++ b/packages/react/src/Form.ts @@ -182,7 +182,6 @@ const Form = forwardRef( return () => { formEvents.forEach((e) => formElement.current?.removeEventListener(e, updateDirtyState)) - newValidator?.reset() } }, []) diff --git a/packages/svelte/src/components/Form.svelte b/packages/svelte/src/components/Form.svelte index 25db4c033..bf0238c7a 100644 --- a/packages/svelte/src/components/Form.svelte +++ b/packages/svelte/src/components/Form.svelte @@ -6,11 +6,16 @@ type Errors, type FormComponentProps, type FormDataConvertible, - type FormComponentValidateOptions, type VisitOptions, isUrlMethodPair, - usePrecognition, } from '@inertiajs/core' + import { + createValidator, + toSimpleValidationErrors, + type NamedInputEvent, + type ValidationConfig, + type Validator, + } from 'laravel-precognition' import { isEqual } from 'lodash-es' import { onMount } from 'svelte' import useForm from '../useForm' @@ -51,18 +56,9 @@ let defaultData: FormData = new FormData() let validating = false - let validated: string[] = [] + let validFields: string[] = [] let touchedFields: string[] = [] - - const validator = usePrecognition({ - timeout: validateTimeout, - onStart: () => { - validating = true - }, - onFinish: () => { - validating = false - }, - }) + let validator: Validator | null = null $: _method = isUrlMethodPair(action) ? action.method : (method.toLowerCase() as FormComponentProps['method']) $: _action = isUrlMethodPair(action) ? action.url : action @@ -86,6 +82,11 @@ isDirty = event.type === 'reset' ? false : !isEqual(getData(), formDataToObject(defaultData)) } + function getTransformedData(): Record { + const [_url, data] = getUrlAndData() + return transform!(data) + } + export function submit() { const [url, _data] = getUrlAndData() @@ -156,33 +157,29 @@ } } - function updateDataOnValidator() { - try { - // This might fail if the component is already unmounted but this function - // is called after navigating away after a form submission. - validator.setOldData(transform(getData())) - } catch {} - } - export function reset(...fields: string[]) { resetFormFields(formElement, defaultData, fields) - updateDataOnValidator() - if (fields.length === 0) { - touchedFields = [] - } else { - touchedFields = touchedFields.filter((field) => !fields.includes(field)) + if (validator) { + validator.reset(...fields) } } export function clearErrors(...fields: string[]) { // @ts-expect-error $form.clearErrors(...fields) + + if (validator) { + if (fields.length === 0) { + validator.setErrors({}) + } else { + fields.forEach(validator.forgetError) + } + } } export function resetAndClearErrors(...fields: string[]) { - // @ts-expect-error - $form.clearErrors(...fields) + clearErrors(...fields) reset(...fields) } @@ -198,72 +195,22 @@ export function defaults() { defaultData = getFormData() isDirty = false - updateDataOnValidator() } export function validate( - only?: string | string[] | FormComponentValidateOptions, - maybeOptions?: FormComponentValidateOptions, + input?: string | NamedInputEvent | ValidationConfig, + value?: unknown, + config?: ValidationConfig, ) { - let fields: string[] - let options: FormComponentValidateOptions = {} - - if (typeof only === 'object' && !Array.isArray(only)) { - // Called as validate({ only: [...], onSuccess, onError, onFinish }) - const onlyFields = only.only - fields = onlyFields === undefined ? touchedFields : Array.isArray(onlyFields) ? onlyFields : [onlyFields] - options = only - } else { - // Called as validate('field') or validate(['field1', 'field2']) or validate('field', {options}) - fields = only === undefined ? touchedFields : Array.isArray(only) ? only : [only] - options = maybeOptions || {} + if (validator) { + return validator.validate(input, value, config) } - - // We're not using the data object from this method as it might be empty - // on GET requests, and we still want to pass a data object to the - // validator so it knows the current state of the form. - const [url] = getUrlAndData() - - validator.validate({ - url, - method: _method, - data: transform(getData()), - only: fields, - errorBag, - headers, - simpleValidationErrors, - onBefore: options.onBefore, - onPrecognitionSuccess: () => { - validated = [...validated, ...fields] - clearErrors(...fields) - options.onSuccess?.() - }, - onValidationError: (errors) => { - validated = [...validated, ...fields] - - const validFields = fields.filter((field) => errors[field] === undefined) - - if (validFields.length) { - clearErrors(...validFields) - } - - // Merge current errors with new errors - const mergedErrors = { ...$form.errors, ...errors } - setError(mergedErrors) - options.onError?.(errors) - }, - onException: options.onException, - onFinish: () => { - options.onFinish?.() - }, - }) } - export function touch(field: string | string[]) { - const fields = Array.isArray(field) ? field : [field] - - // Use Set to avoid duplicates - touchedFields = [...new Set([...touchedFields, ...fields])] + export function touch(...fields: string[]) { + if (validator) { + validator.touch(fields) + } } export function touched(field?: string): boolean { @@ -275,36 +222,68 @@ } export function valid(field: string): boolean { - return validated.includes(field) && $form.errors[field] === undefined + return validFields.includes(field) } export function invalid(field: string): boolean { return $form.errors[field] !== undefined } - onMount(() => { defaultData = getFormData() const formEvents = ['input', 'change', 'reset'] formEvents.forEach((e) => formElement.addEventListener(e, updateDirtyState)) - updateDataOnValidator() - validator.validateFiles(validateFiles) - validator.setTimeout(validateTimeout) + // Initialize validator + validator = createValidator( + (client) => + client[_method!](getUrlAndData()[0], getTransformedData(), { + headers, + }), + getTransformedData(), + ) + .on('validatingChanged', () => { + validating = validator!.validating() + }) + .on('validatedChanged', () => { + validFields = validator!.valid() + }) + .on('touchedChanged', () => { + touchedFields = validator!.touched() + }) + .on('errorsChanged', () => { + // Clear form errors first + $form.clearErrors() + + // Set new errors + const errors = simpleValidationErrors ? toSimpleValidationErrors(validator!.errors()) : validator!.errors() + + $form.setError(errors as Errors) + validFields = validator!.valid() + }) + + validator.setTimeout(validateTimeout!) + + if (validateFiles) { + validator.validateFiles() + } return () => { formEvents.forEach((e) => formElement?.removeEventListener(e, updateDirtyState)) } }) - $: validator.validateFiles(validateFiles) - $: validator.setTimeout(validateTimeout) + $: { + if (validator) { + validator.setTimeout(validateTimeout!) + } + } $: slotErrors = $form.errors as Errors // Create reactive slot props that update when state changes - $: validMethod = (field: string) => validated.includes(field) && slotErrors[field] === undefined + $: validMethod = (field: string) => validFields.includes(field) $: invalidMethod = (field: string) => slotErrors[field] !== undefined $: touchedMethod = (field?: string) => typeof field === 'string' ? touchedFields.includes(field) : touchedFields.length > 0 diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte index 1237f4b37..af497791a 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte @@ -61,7 +61,7 @@ errorCalled = false finishCalled = false validate({ - onError: () => { + onValidationError: () => { errorCalled = true }, onFinish: () => { From 56bc4416907113325ab7ac02ed91c6bfa62c05b9 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 30 Oct 2025 16:26:46 +0100 Subject: [PATCH 060/145] fixes --- packages/core/src/types.ts | 2 +- packages/react/package.json | 2 +- packages/react/src/Form.ts | 6 ++---- .../FormComponent/PrecognitionBeforeValidation.tsx | 10 +++++----- .../Pages/FormComponent/PrecognitionCallbacks.tsx | 7 ------- .../Pages/FormComponent/PrecognitionDefaults.tsx | 3 ++- .../Pages/FormComponent/PrecognitionFiles.tsx | 4 ++-- .../Pages/FormComponent/PrecognitionMethods.tsx | 4 ++-- packages/react/test-app/package.json | 2 +- packages/svelte/package.json | 2 +- packages/svelte/src/components/Form.svelte | 13 ++++--------- .../FormComponent/PrecognitionAllErrors.svelte | 4 ++-- .../PrecognitionBeforeValidation.svelte | 6 +++--- .../FormComponent/PrecognitionCallbacks.svelte | 7 ------- .../Pages/FormComponent/PrecognitionDefaults.svelte | 3 ++- .../Pages/FormComponent/PrecognitionFiles.svelte | 3 +-- .../Pages/FormComponent/PrecognitionMethods.svelte | 4 ++-- packages/svelte/test-app/package.json | 2 +- packages/vue3/package.json | 2 +- packages/vue3/src/form.ts | 2 +- .../FormComponent/PrecognitionBeforeValidation.vue | 6 +++--- .../Pages/FormComponent/PrecognitionCallbacks.vue | 7 ------- .../Pages/FormComponent/PrecognitionDefaults.vue | 5 +++-- .../Pages/FormComponent/PrecognitionFiles.vue | 4 ++-- .../Pages/FormComponent/PrecognitionMethods.vue | 4 ++-- packages/vue3/test-app/package.json | 2 +- 26 files changed, 45 insertions(+), 71 deletions(-) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 566c5c9d3..2ba3e033c 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -588,7 +588,7 @@ export type FormComponentMethods = { valid: (field: string) => boolean invalid: (field: string) => boolean validate: Validator['validate'] - touch: (field: string | string[]) => void + touch: (...fields: string[]) => void touched(field?: string): boolean } diff --git a/packages/react/package.json b/packages/react/package.json index 00caf4b73..1cabd99f6 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -70,4 +70,4 @@ "laravel-precognition": "^0.7.3", "lodash-es": "^4.17.21" } -} \ No newline at end of file +} diff --git a/packages/react/src/Form.ts b/packages/react/src/Form.ts index de4d8f197..c9137d83a 100644 --- a/packages/react/src/Form.ts +++ b/packages/react/src/Form.ts @@ -259,9 +259,7 @@ const Form = forwardRef( } const touch = (...fields: string[]) => { - if (validator) { - validator.touch(fields) - } + validator!.touch(fields) } const isTouched = (field?: string): boolean => { @@ -294,7 +292,7 @@ const Form = forwardRef( valid: (field: string) => valid.includes(field), invalid: (field: string) => form.errors[field] !== undefined, validate: (input?: string | NamedInputEvent | ValidationConfig, value?: unknown, config?: ValidationConfig) => - validator?.validate(input, value, config), + validator!.validate(input, value, config), touch, touched: isTouched, }) diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidation.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidation.tsx index bbb2bd98d..cdbf63e35 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidation.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionBeforeValidation.tsx @@ -3,8 +3,8 @@ import { isEqual } from 'lodash-es' export default function PrecognitionBefore() { const handleBeforeValidation = ( - newRequest: { data: Record; touched: string[] }, - oldRequest: { data: Record; touched: string[] }, + newRequest: { data: Record; touched: string[] }, + oldRequest: { data: Record; touched: string[] }, ) => { const payloadIsCorrect = isEqual(newRequest, { data: { name: 'block' }, touched: ['name'] }) && @@ -29,11 +29,11 @@ export default function PrecognitionBefore() { { + onChange={() => validate('name', { - onBefore: handleBeforeValidation, + onBeforeValidation: handleBeforeValidation, }) - }} + } /> {invalid('name') &&

{errors.name}

} diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx index 370c2eb81..3b587b698 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionCallbacks.tsx @@ -5,13 +5,6 @@ export default () => { const [successCalled, setSuccessCalled] = useState(false) const [errorCalled, setErrorCalled] = useState(false) const [finishCalled, setFinishCalled] = useState(false) - const [exceptionCaught, setExceptionCaught] = useState(false) - const [exceptionMessage, setExceptionMessage] = useState('') - - const handleException = (error: Error) => { - setExceptionCaught(true) - setExceptionMessage(error.message || 'Unknown error') - } return (
diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx index 0333b43cb..2eb4f768a 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx @@ -1,8 +1,9 @@ +import { FormComponentRef } from '@inertiajs/core' import { Form } from '@inertiajs/react' import { useRef } from 'react' export default function PrecognitionDefaults() { - const formRef = useRef(null) + const formRef = useRef(null) const handleSetDefaults = () => { formRef.current?.defaults() diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionFiles.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionFiles.tsx index 2265275c8..c438494e8 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionFiles.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionFiles.tsx @@ -14,7 +14,7 @@ export default () => { validateTimeout={100} validateFiles={validateFilesEnabled} > - {({ invalid, errors, validate, valid, validating, touch }) => ( + {({ invalid, errors, validate, valid, validating }) => ( <>
validate('name')} /> @@ -34,7 +34,7 @@ export default () => { Toggle Validate Files ({validateFilesEnabled ? 'enabled' : 'disabled'}) - diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx index 3fb5fdca3..b29f5d8d4 100644 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx +++ b/packages/react/test-app/Pages/FormComponent/PrecognitionMethods.tsx @@ -30,10 +30,10 @@ export default () => { - - - - + + - - )} diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte index ea23cad79..1b85ddba3 100644 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte +++ b/packages/svelte/test-app/Pages/FormComponent/PrecognitionCallbacks.svelte @@ -7,7 +7,7 @@
-

Form Precognition Callbacks & Exceptions

+

Form Precognition Callbacks

Callbacks Test

@@ -19,10 +19,10 @@

Validating...

{/if} {#if successCalled} -

onSuccess called!

+

onPrecognitionSuccess called!

{/if} {#if errorCalled} -

onError called!

+

onValidationError called!

{/if} {#if finishCalled}

onFinish called!

@@ -38,22 +38,6 @@ onPrecognitionSuccess: () => { successCalled = true }, - onFinish: () => { - finishCalled = true - }, - }) - }} - > - Validate with onSuccess - - -
diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue index ee4d996ad..824d98b4b 100644 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue +++ b/packages/vue3/test-app/Pages/FormComponent/PrecognitionCallbacks.vue @@ -9,7 +9,7 @@ const finishCalled = ref(false) diff --git a/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx b/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx index d0388b83a..f64cb7139 100644 --- a/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx +++ b/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx @@ -245,8 +245,8 @@ const FormComponentPrecognition = () => { {(callbacks.success || callbacks.error || callbacks.finish) && (
- {callbacks.success &&

onSuccess called!

} - {callbacks.error &&

onError called!

} + {callbacks.success &&

onPrecognitionSuccess called!

} + {callbacks.error &&

onValidationError called!

} {callbacks.finish &&

onFinish called!

} {callbacks.exception && (

onException: {callbacks.exceptionMessage}

diff --git a/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte b/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte index 44b70730c..583d22296 100644 --- a/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte +++ b/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte @@ -256,10 +256,10 @@ {#if callbacks.success || callbacks.error || callbacks.finish}
{#if callbacks.success} -

onSuccess called!

+

onPrecognitionSuccess called!

{/if} {#if callbacks.error} -

onError called!

+

onValidationError called!

{/if} {#if callbacks.finish}

onFinish called!

diff --git a/playgrounds/svelte5/resources/js/Pages/FormComponentPrecognition.svelte b/playgrounds/svelte5/resources/js/Pages/FormComponentPrecognition.svelte index 30b2ade76..caa39e56b 100644 --- a/playgrounds/svelte5/resources/js/Pages/FormComponentPrecognition.svelte +++ b/playgrounds/svelte5/resources/js/Pages/FormComponentPrecognition.svelte @@ -234,10 +234,10 @@ {#if callbacks.success || callbacks.error || callbacks.finish}
{#if callbacks.success} -

onSuccess called!

+

onPrecognitionSuccess called!

{/if} {#if callbacks.error} -

onError called!

+

onValidationError called!

{/if} {#if callbacks.finish}

onFinish called!

diff --git a/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue b/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue index 384fc0b71..5b649ef61 100644 --- a/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue +++ b/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue @@ -209,8 +209,8 @@ const validateTimeout = ref(1500)

Validating...

-

onSuccess called!

-

onError called!

+

onPrecognitionSuccess called!

+

onValidationError called!

onFinish called!

onException: {{ callbacks.exceptionMessage }} diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 4d37ecab0..038e6fe2f 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1688,17 +1688,14 @@ test.describe('Form Component', () => { test('touch with array marks multiple fields as touched', async ({ page }) => { await page.goto('/form-component/precognition-methods') - await page.fill('input[name="name"]', 'ab') - await page.fill('input[name="email"]', 'x') - await page.getByRole('button', { name: 'Touch Name and Email' }).click() await page.getByRole('button', { name: 'Validate All Touched' }).click() await expect(page.getByText('Validating...')).toBeVisible() await expect(page.getByText('Validating...')).not.toBeVisible() - await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() - await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + await expect(page.getByText('The name field is required.')).toBeVisible() + await expect(page.getByText('The email field is required.')).toBeVisible() }) test('touch deduplicates fields when called multiple times', async ({ page }) => { @@ -1777,16 +1774,13 @@ test.describe('Form Component', () => { test('validate with array of fields validates multiple fields', async ({ page }) => { await page.goto('/form-component/precognition-methods') - await page.fill('input[name="name"]', 'ab') - await page.fill('input[name="email"]', 'x') - await page.getByRole('button', { name: 'Validate Name and Email' }).click() await expect(page.getByText('Validating...')).toBeVisible() await expect(page.getByText('Validating...')).not.toBeVisible() - await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() - await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + await expect(page.getByText('The name field is required.')).toBeVisible() + await expect(page.getByText('The email field is required.')).toBeVisible() }) test('reset with array removes multiple fields from touched', async ({ page }) => { @@ -1808,6 +1802,13 @@ test.describe('Form Component', () => { await page.getByRole('button', { name: 'Reset Name and Email' }).click() + await expect(page.locator('input[name="name"]')).toHaveValue('') + await expect(page.locator('input[name="email"]')).toHaveValue('') + + await expect(page.getByText('Name is not touched')).toBeVisible() + await expect(page.getByText('Email is not touched')).toBeVisible() + await expect(page.getByText('Form has no touched fields')).toBeVisible() + await page.fill('input[name="name"]', 'abc') await page.fill('input[name="email"]', 'test@example.com') @@ -1879,31 +1880,31 @@ test.describe('Form Component', () => { await expect(page.getByText('Name is valid!')).toBeVisible() }) - test('calls onSuccess and onFinish callbacks when validation succeeds', async ({ page }) => { + test('calls onPrecognitionSuccess and onFinish callbacks when validation succeeds', async ({ page }) => { await page.goto('/form-component/precognition-callbacks') await page.fill('input[name="name"]', 'John Doe') - await page.click('button:has-text("Validate with onSuccess")') + await page.click('button:has-text("Validate")') await expect(page.getByText('Validating...')).toBeVisible() await expect(page.getByText('Validating...')).not.toBeVisible() - await expect(page.getByText('onSuccess called!')).toBeVisible() - await expect(page.getByText('onError called!')).not.toBeVisible() + await expect(page.getByText('onPrecognitionSuccess called!')).toBeVisible() + await expect(page.getByText('onValidationError called!')).not.toBeVisible() await expect(page.getByText('onFinish called!')).toBeVisible() }) - test('calls onError and onFinish callbacks when validation fails', async ({ page }) => { + test('calls onValidationError and onFinish callbacks when validation fails', async ({ page }) => { await page.goto('/form-component/precognition-callbacks') await page.fill('input[name="name"]', 'ab') - await page.click('button:has-text("Validate with onError")') + await page.click('button:has-text("Validate")') await expect(page.getByText('Validating...')).toBeVisible() await expect(page.getByText('Validating...')).not.toBeVisible() - await expect(page.getByText('onSuccess called!')).not.toBeVisible() - await expect(page.getByText('onError called!')).toBeVisible() + await expect(page.getByText('onPrecognitionSuccess called!')).not.toBeVisible() + await expect(page.getByText('onValidationError called!')).toBeVisible() await expect(page.getByText('onFinish called!')).toBeVisible() }) From 4f2d66d6629f8b604659d0a68d5017918f8f0f8a Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 31 Oct 2025 14:49:48 +0100 Subject: [PATCH 072/145] cleanup --- .../FormComponent/PrecognitionDefaults.tsx | 38 ----------------- .../FormComponent/PrecognitionDefaults.svelte | 42 ------------------- .../FormComponent/PrecognitionDefaults.vue | 38 ----------------- tests/form-component.spec.ts | 22 ---------- 4 files changed, 140 deletions(-) delete mode 100644 packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx delete mode 100644 packages/svelte/test-app/Pages/FormComponent/PrecognitionDefaults.svelte delete mode 100644 packages/vue3/test-app/Pages/FormComponent/PrecognitionDefaults.vue diff --git a/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx b/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx deleted file mode 100644 index 2eb4f768a..000000000 --- a/packages/react/test-app/Pages/FormComponent/PrecognitionDefaults.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { FormComponentRef } from '@inertiajs/core' -import { Form } from '@inertiajs/react' -import { useRef } from 'react' - -export default function PrecognitionDefaults() { - const formRef = useRef(null) - - const handleSetDefaults = () => { - formRef.current?.defaults() - } - - return ( -

-

Precognition - Defaults Updates Validator

- -
- {({ invalid, errors, validate, validating }) => ( - <> -
- - {invalid('name') &&

{errors.name}

} -
- - {validating &&

Validating...

} - - - - - - )} -
-
- ) -} diff --git a/packages/svelte/test-app/Pages/FormComponent/PrecognitionDefaults.svelte b/packages/svelte/test-app/Pages/FormComponent/PrecognitionDefaults.svelte deleted file mode 100644 index 01dc4b324..000000000 --- a/packages/svelte/test-app/Pages/FormComponent/PrecognitionDefaults.svelte +++ /dev/null @@ -1,42 +0,0 @@ - - -
-

Precognition - Defaults Updates Validator

- -
-
- - {#if invalid('name')} -

- {errors.name} -

- {/if} -
- - {#if validating} -

Validating...

- {/if} - - - - -
-
diff --git a/packages/vue3/test-app/Pages/FormComponent/PrecognitionDefaults.vue b/packages/vue3/test-app/Pages/FormComponent/PrecognitionDefaults.vue deleted file mode 100644 index d49acd90c..000000000 --- a/packages/vue3/test-app/Pages/FormComponent/PrecognitionDefaults.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - diff --git a/tests/form-component.spec.ts b/tests/form-component.spec.ts index 038e6fe2f..94ac7ebc9 100644 --- a/tests/form-component.spec.ts +++ b/tests/form-component.spec.ts @@ -1957,28 +1957,6 @@ test.describe('Form Component', () => { const cancelledRequestError = await requests.failed[0].failure()?.errorText expect(cancelledRequestError).toBe('net::ERR_ABORTED') }) - - test('defaults() updates validator data as well', async ({ page }) => { - await page.goto('/form-component/precognition-defaults') - - await page.fill('#name-input', 'John') - await page.locator('#name-input').blur() - await page.click('button:has-text("Validate Name")') - - await expect(page.getByText('Validating...')).toBeVisible() - await expect(page.getByText('Validating...')).not.toBeVisible() - - // Click again, should not validate again because data hasn't changed - await expect(page.getByText('Validating...')).not.toBeVisible() - await page.click('button:has-text("Validate Name")') - await expect(page.getByText('Validating...')).not.toBeVisible() - - // Now change default to a different value, should not validate because value matches new default - await page.fill('#name-input', 'Johnny') - await page.click('button:has-text("Set Defaults")') - await page.click('button:has-text("Validate Name")') - await expect(page.getByText('Validating...')).not.toBeVisible() - }) }) test.describe('React', () => { From b3edfa2f1b65726f08f668df92dfc896ce6253bf Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 31 Oct 2025 16:01:20 +0100 Subject: [PATCH 073/145] playgrounds --- .../js/Pages/FormComponentPrecognition.tsx | 18 ++++++---------- .../js/Pages/FormComponentPrecognition.svelte | 19 +++++++---------- .../js/Pages/FormComponentPrecognition.svelte | 21 +++++++------------ .../js/Pages/FormComponentPrecognition.vue | 18 ++++++---------- 4 files changed, 27 insertions(+), 49 deletions(-) diff --git a/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx b/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx index f64cb7139..f5085fbf6 100644 --- a/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx +++ b/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx @@ -1,3 +1,4 @@ +import { FormComponentMethods } from '@inertiajs/core' import { Form, Head } from '@inertiajs/react' import { useState } from 'react' import Layout from '../Components/Layout' @@ -7,26 +8,22 @@ const FormComponentPrecognition = () => { success: false, error: false, finish: false, - exception: false, - exceptionMessage: '', }) - const validateWithCallbacks = (validate) => { + const validateWithCallbacks = (validate: FormComponentMethods['validate']) => { setCallbacks({ success: false, error: false, finish: false, - exception: false, - exceptionMessage: '', }) validate('name', { - onSuccess: () => setCallbacks((prev) => ({ ...prev, success: true })), - onError: () => setCallbacks((prev) => ({ ...prev, error: true })), + onPrecognitionSuccess: () => setCallbacks((prev) => ({ ...prev, success: true })), + onValidationError: () => setCallbacks((prev) => ({ ...prev, error: true })), onFinish: () => setCallbacks((prev) => ({ ...prev, finish: true })), - onBefore: (newReq, oldReq) => { + onBeforeValidation: (newReq, oldReq) => { // Prevent validation if name is 'block' - if (newReq.data.name === 'block') { + if (newReq.data?.name === 'block') { alert('Validation blocked by onBefore!') return false } @@ -248,9 +245,6 @@ const FormComponentPrecognition = () => { {callbacks.success &&

onPrecognitionSuccess called!

} {callbacks.error &&

onValidationError called!

} {callbacks.finish &&

onFinish called!

} - {callbacks.exception && ( -

onException: {callbacks.exceptionMessage}

- )}
)} diff --git a/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte b/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte index 583d22296..407450ff2 100644 --- a/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte +++ b/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte @@ -3,6 +3,8 @@ - @@ -11,26 +12,22 @@ const callbacks = ref({ success: false, error: false, finish: false, - exception: false, - exceptionMessage: '', }) -const validateWithCallbacks = (validate) => { +const validateWithCallbacks = (validate: FormComponentMethods['validate']) => { callbacks.value = { success: false, error: false, finish: false, - exception: false, - exceptionMessage: '', } validate('name', { - onSuccess: () => (callbacks.value.success = true), - onError: () => (callbacks.value.error = true), + onPrecognitionSuccess: () => (callbacks.value.success = true), + onValidationError: () => (callbacks.value.error = true), onFinish: () => (callbacks.value.finish = true), - onBefore: (newReq, oldReq) => { + onBeforeValidation: (newReq, oldReq) => { // Prevent validation if name is 'block' - if (newReq.data.name === 'block') { + if (newReq.data?.name === 'block') { alert('Validation blocked by onBefore!') return false } @@ -212,9 +209,6 @@ const validateTimeout = ref(1500)

onPrecognitionSuccess called!

onValidationError called!

onFinish called!

-

- onException: {{ callbacks.exceptionMessage }} -

From 5ad07b7471e3a42ac09a97899010610efbee5f91 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 31 Oct 2025 16:09:10 +0100 Subject: [PATCH 074/145] playgrounds --- .../react/resources/js/Pages/FormComponentPrecognition.tsx | 2 +- .../svelte4/resources/js/Pages/FormComponentPrecognition.svelte | 2 +- .../svelte5/resources/js/Pages/FormComponentPrecognition.svelte | 2 +- .../vue3/resources/js/Pages/FormComponentPrecognition.vue | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx b/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx index f5085fbf6..89d4b02cf 100644 --- a/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx +++ b/playgrounds/react/resources/js/Pages/FormComponentPrecognition.tsx @@ -17,7 +17,7 @@ const FormComponentPrecognition = () => { finish: false, }) - validate('name', { + validate({ onPrecognitionSuccess: () => setCallbacks((prev) => ({ ...prev, success: true })), onValidationError: () => setCallbacks((prev) => ({ ...prev, error: true })), onFinish: () => setCallbacks((prev) => ({ ...prev, finish: true })), diff --git a/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte b/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte index 407450ff2..045e64e2e 100644 --- a/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte +++ b/playgrounds/svelte4/resources/js/Pages/FormComponentPrecognition.svelte @@ -22,7 +22,7 @@ finish: false, } - validate('name', { + validate({ onPrecognitionSuccess: () => (callbacks.success = true), onValidationError: () => (callbacks.error = true), onFinish: () => (callbacks.finish = true), diff --git a/playgrounds/svelte5/resources/js/Pages/FormComponentPrecognition.svelte b/playgrounds/svelte5/resources/js/Pages/FormComponentPrecognition.svelte index 45c4a89f4..ea2a8c69c 100644 --- a/playgrounds/svelte5/resources/js/Pages/FormComponentPrecognition.svelte +++ b/playgrounds/svelte5/resources/js/Pages/FormComponentPrecognition.svelte @@ -22,7 +22,7 @@ finish: false, } - validate('name', { + validate({ onPrecognitionSuccess: () => (callbacks.success = true), onValidationError: () => (callbacks.error = true), onFinish: () => (callbacks.finish = true), diff --git a/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue b/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue index 865e12218..7328c7a19 100644 --- a/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue +++ b/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue @@ -21,7 +21,7 @@ const validateWithCallbacks = (validate: FormComponentMethods['validate']) => { finish: false, } - validate('name', { + validate({ onPrecognitionSuccess: () => (callbacks.value.success = true), onValidationError: () => (callbacks.value.error = true), onFinish: () => (callbacks.value.finish = true), From a3146c977a4f33d53695545baa3b188ce75507fe Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 31 Oct 2025 16:26:51 +0100 Subject: [PATCH 075/145] move import --- .../vue3/resources/js/Pages/FormComponentPrecognition.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue b/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue index 7328c7a19..ef102ca40 100644 --- a/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue +++ b/playgrounds/vue3/resources/js/Pages/FormComponentPrecognition.vue @@ -1,10 +1,10 @@ + + diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/ArrayErrors.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/ArrayErrors.vue new file mode 100644 index 000000000..cf9a40ccf --- /dev/null +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/ArrayErrors.vue @@ -0,0 +1,32 @@ + + + diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/BeforeValidation.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/BeforeValidation.vue new file mode 100644 index 000000000..e891221b0 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/BeforeValidation.vue @@ -0,0 +1,57 @@ + + + diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/Callbacks.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/Callbacks.vue new file mode 100644 index 000000000..b9aa16d80 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/Callbacks.vue @@ -0,0 +1,56 @@ + + + diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/Cancel.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/Cancel.vue new file mode 100644 index 000000000..f8bf59d97 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/Cancel.vue @@ -0,0 +1,29 @@ + + + diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/Default.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/Default.vue new file mode 100644 index 000000000..58201ac95 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/Default.vue @@ -0,0 +1,32 @@ + + + diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue new file mode 100644 index 000000000..9883699cd --- /dev/null +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue @@ -0,0 +1,46 @@ + + + diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/Headers.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/Headers.vue new file mode 100644 index 000000000..9967ee9b6 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/Headers.vue @@ -0,0 +1,32 @@ + + + diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/Methods.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/Methods.vue new file mode 100644 index 000000000..77f5480b3 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/Methods.vue @@ -0,0 +1,53 @@ + + + diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/Transform.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/Transform.vue new file mode 100644 index 000000000..91d0b6ea7 --- /dev/null +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/Transform.vue @@ -0,0 +1,24 @@ + + + diff --git a/packages/vue3/test-app/package.json b/packages/vue3/test-app/package.json index 2750f85a8..56b8d5bef 100755 --- a/packages/vue3/test-app/package.json +++ b/packages/vue3/test-app/package.json @@ -7,16 +7,16 @@ "type-check": "vue-tsc --noEmit" }, "devDependencies": { - "@eslint/js": "^9.38.0", + "@eslint/js": "^9.39.1", "@vitejs/plugin-vue": "^5.2.4", "@vue/eslint-config-typescript": "^14.6.0", - "eslint": "^9.38.0", + "eslint": "^9.39.1", "eslint-config-prettier": "^10.1.8", "eslint-plugin-vue": "^10.5.1", - "globals": "^16.4.0", + "globals": "^16.5.0", "nodemon": "^3.1.10", "typescript": "^5.9.3", - "typescript-eslint": "^8.46.2", + "typescript-eslint": "^8.46.3", "vite": "^6.4.1", "vue": "^3.5.22", "vue-tsc": "^2.2.12" diff --git a/playgrounds/react/package.json b/playgrounds/react/package.json index 8efae28f1..ffa86dc14 100644 --- a/playgrounds/react/package.json +++ b/playgrounds/react/package.json @@ -11,18 +11,18 @@ "@inertiajs/react": "workspace:*", "@laravel/stream-react": "^0.3.9", "@tailwindcss/typography": "^0.5.19", - "@tailwindcss/vite": "^4.1.15", + "@tailwindcss/vite": "^4.1.16", "@types/react": "^19.2.2", "@types/react-dom": "^19.2.2", "@vitejs/plugin-react": "^4.7.0", "autosize": "^6.0.1", - "axios": "^1.12.2", + "axios": "^1.13.1", "laravel-vite-plugin": "^1.3.0", "lodash": "^4.17.21", "marked": "^16.4.1", "react": "^19.2.0", "react-dom": "^19.2.0", - "tailwindcss": "^4.1.15", + "tailwindcss": "^4.1.16", "typescript": "^4.9.5", "vite": "^6.4.1" } diff --git a/playgrounds/svelte4/package.json b/playgrounds/svelte4/package.json index dfd2bbe84..a3c0f51d2 100644 --- a/playgrounds/svelte4/package.json +++ b/playgrounds/svelte4/package.json @@ -12,14 +12,14 @@ "@inertiajs/core": "workspace:*", "@inertiajs/svelte": "workspace:*", "@sveltejs/vite-plugin-svelte": "^3.1.2", - "@tailwindcss/vite": "^4.1.15", + "@tailwindcss/vite": "^4.1.16", "@tsconfig/svelte": "^5.0.5", - "axios": "^1.12.2", + "axios": "^1.13.1", "laravel-vite-plugin": "^1.3.0", "lodash": "^4.17.21", "svelte": "^4.2.20", "svelte-check": "^4.3.3", - "tailwindcss": "^4.1.15", + "tailwindcss": "^4.1.16", "typescript": "^5.9.3", "vite": "^5.4.21" } diff --git a/playgrounds/svelte5/package.json b/playgrounds/svelte5/package.json index 43c6dc760..61ff816e3 100644 --- a/playgrounds/svelte5/package.json +++ b/playgrounds/svelte5/package.json @@ -12,14 +12,14 @@ "@inertiajs/core": "workspace:*", "@inertiajs/svelte": "workspace:*", "@sveltejs/vite-plugin-svelte": "^5.1.1", - "@tailwindcss/vite": "^4.1.15", + "@tailwindcss/vite": "^4.1.16", "@tsconfig/svelte": "^5.0.5", - "axios": "^1.12.2", + "axios": "^1.13.1", "laravel-vite-plugin": "^1.3.0", "lodash": "^4.17.21", - "svelte": "^5.41.1", + "svelte": "^5.43.3", "svelte-check": "^4.3.3", - "tailwindcss": "^4.1.15", + "tailwindcss": "^4.1.16", "typescript": "^5.9.3", "vite": "^6.4.1" } diff --git a/playgrounds/vue3/package.json b/playgrounds/vue3/package.json index ced3a6aa9..611843520 100644 --- a/playgrounds/vue3/package.json +++ b/playgrounds/vue3/package.json @@ -10,15 +10,15 @@ "@inertiajs/vue3": "workspace:*", "@laravel/stream-vue": "^0.3.9", "@tailwindcss/typography": "^0.5.19", - "@tailwindcss/vite": "^4.1.15", + "@tailwindcss/vite": "^4.1.16", "@vitejs/plugin-vue": "^5.2.4", "@vue/server-renderer": "^3.5.22", "autosize": "^6.0.1", - "axios": "^1.12.2", + "axios": "^1.13.1", "laravel-vite-plugin": "^1.3.0", "lodash": "^4.17.21", "marked": "^16.4.1", - "tailwindcss": "^4.1.15", + "tailwindcss": "^4.1.16", "typescript": "^5.9.3", "vite": "^6.4.1", "vue": "^3.5.22", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3945c6520..940c9fe8d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,10 +19,10 @@ importers: version: 4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)) prettier-plugin-svelte: specifier: ^3.4.0 - version: 3.4.0(prettier@3.6.2)(svelte@5.41.1) + version: 3.4.0(prettier@3.6.2)(svelte@5.43.3) prettier-plugin-tailwindcss: specifier: ^0.6.14 - version: 0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)))(prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.41.1))(prettier@3.6.2) + version: 0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)))(prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.43.3))(prettier@3.6.2) optionalDependencies: '@rollup/rollup-linux-x64-gnu': specifier: ^4.52.5 @@ -34,8 +34,11 @@ importers: specifier: ^4.17.12 version: 4.17.12 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 + laravel-precognition: + specifier: ^0.7.3 + version: 0.7.3 lodash-es: specifier: ^4.17.21 version: 4.17.21 @@ -59,11 +62,11 @@ importers: specifier: ^9.4.4 version: 9.4.4 esbuild: - specifier: ^0.25.11 - version: 0.25.11 + specifier: ^0.25.12 + version: 0.25.12 esbuild-node-externals: specifier: ^1.18.0 - version: 1.18.0(esbuild@0.25.11) + version: 1.18.0(esbuild@0.25.12) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -76,6 +79,9 @@ importers: '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 + laravel-precognition: + specifier: ^0.7.3 + version: 0.7.3 lodash-es: specifier: ^4.17.21 version: 4.17.21 @@ -87,17 +93,17 @@ importers: specifier: ^19.2.2 version: 19.2.2(@types/react@19.2.2) axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 es-check: specifier: ^9.4.4 version: 9.4.4 esbuild: - specifier: ^0.25.11 - version: 0.25.11 + specifier: ^0.25.12 + version: 0.25.12 esbuild-node-externals: specifier: ^1.18.0 - version: 1.18.0(esbuild@0.25.11) + version: 1.18.0(esbuild@0.25.12) react: specifier: ^19.2.0 version: 19.2.0 @@ -115,7 +121,7 @@ importers: version: link:.. '@vitejs/plugin-react': specifier: ^4.7.0 - version: 4.7.0(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 4.7.0(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) react: specifier: ^19.2.0 version: 19.2.0 @@ -124,11 +130,11 @@ importers: version: 19.2.0(react@19.2.0) devDependencies: '@eslint/js': - specifier: ^9.38.0 - version: 9.38.0 + specifier: ^9.39.1 + version: 9.39.1 '@types/node': - specifier: ^24.9.1 - version: 24.9.1 + specifier: ^24.10.0 + version: 24.10.0 '@types/react': specifier: ^19.2.2 version: 19.2.2 @@ -136,20 +142,20 @@ importers: specifier: ^19.2.2 version: 19.2.2(@types/react@19.2.2) eslint: - specifier: ^9.38.0 - version: 9.38.0(jiti@2.6.1) + specifier: ^9.39.1 + version: 9.39.1(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.38.0(jiti@2.6.1)) + version: 10.1.8(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-react: specifier: ^7.37.5 - version: 7.37.5(eslint@9.38.0(jiti@2.6.1)) + version: 7.37.5(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-react-hooks: specifier: ^5.2.0 - version: 5.2.0(eslint@9.38.0(jiti@2.6.1)) + version: 5.2.0(eslint@9.39.1(jiti@2.6.1)) globals: - specifier: ^16.4.0 - version: 16.4.0 + specifier: ^16.5.0 + version: 16.5.0 nodemon: specifier: ^3.1.10 version: 3.1.10 @@ -157,11 +163,11 @@ importers: specifier: ^5.9.3 version: 5.9.3 typescript-eslint: - specifier: ^8.46.2 - version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + specifier: ^8.46.3 + version: 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + version: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) packages/svelte: dependencies: @@ -171,25 +177,28 @@ importers: '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 + laravel-precognition: + specifier: ^0.7.3 + version: 0.7.3 lodash-es: specifier: ^4.17.21 version: 4.17.21 devDependencies: '@sveltejs/adapter-auto': specifier: ^3.3.1 - version: 3.3.1(@sveltejs/kit@2.47.2(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0))) + version: 3.3.1(@sveltejs/kit@2.48.4(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0))) '@sveltejs/kit': - specifier: ^2.47.2 - version: 2.47.2(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + specifier: ^2.48.4 + version: 2.48.4(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) '@sveltejs/package': specifier: ^2.5.4 version: 2.5.4(svelte@4.2.20)(typescript@5.9.3) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 es-check: specifier: ^9.4.4 version: 9.4.4 @@ -210,7 +219,7 @@ importers: version: 5.9.3 vite: specifier: ^5.4.21 - version: 5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0) + version: 5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0) packages/svelte/test-app: dependencies: @@ -222,26 +231,26 @@ importers: version: link:.. devDependencies: '@eslint/js': - specifier: ^9.38.0 - version: 9.38.0 + specifier: ^9.39.1 + version: 9.39.1 '@sveltejs/eslint-config': specifier: ^8.3.4 - version: 8.3.4(@stylistic/eslint-plugin-js@4.4.1(eslint@9.38.0(jiti@2.6.1)))(eslint-config-prettier@10.1.8(eslint@9.38.0(jiti@2.6.1)))(eslint-plugin-n@17.23.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-plugin-svelte@3.12.5(eslint@9.38.0(jiti@2.6.1))(svelte@4.2.20))(eslint@9.38.0(jiti@2.6.1))(typescript-eslint@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(typescript@5.9.3) + version: 8.3.4(@stylistic/eslint-plugin-js@4.4.1(eslint@9.39.1(jiti@2.6.1)))(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint-plugin-n@17.23.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-plugin-svelte@3.13.0(eslint@9.39.1(jiti@2.6.1))(svelte@4.2.20))(eslint@9.39.1(jiti@2.6.1))(typescript-eslint@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(typescript@5.9.3) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) '@tsconfig/svelte': specifier: ^5.0.5 version: 5.0.5 eslint: - specifier: ^9.38.0 - version: 9.38.0(jiti@2.6.1) + specifier: ^9.39.1 + version: 9.39.1(jiti@2.6.1) eslint-plugin-svelte: - specifier: ^3.12.5 - version: 3.12.5(eslint@9.38.0(jiti@2.6.1))(svelte@4.2.20) + specifier: ^3.13.0 + version: 3.13.0(eslint@9.39.1(jiti@2.6.1))(svelte@4.2.20) globals: - specifier: ^16.4.0 - version: 16.4.0 + specifier: ^16.5.0 + version: 16.5.0 nodemon: specifier: ^3.1.10 version: 3.1.10 @@ -255,11 +264,11 @@ importers: specifier: ^5.9.3 version: 5.9.3 typescript-eslint: - specifier: ^8.46.2 - version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + specifier: ^8.46.3 + version: 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) vite: specifier: ^5.4.21 - version: 5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0) + version: 5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0) packages/vue3: dependencies: @@ -269,25 +278,28 @@ importers: '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 + laravel-precognition: + specifier: ^0.7.3 + version: 0.7.3 lodash-es: specifier: ^4.17.21 version: 4.17.21 devDependencies: '@types/node': - specifier: ^22.18.12 - version: 22.18.12 + specifier: ^22.19.0 + version: 22.19.0 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 es-check: specifier: ^9.4.4 version: 9.4.4 esbuild: - specifier: ^0.25.11 - version: 0.25.11 + specifier: ^0.25.12 + version: 0.25.12 esbuild-node-externals: specifier: ^1.18.0 - version: 1.18.0(esbuild@0.25.11) + version: 1.18.0(esbuild@0.25.12) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -305,26 +317,26 @@ importers: version: link:.. devDependencies: '@eslint/js': - specifier: ^9.38.0 - version: 9.38.0 + specifier: ^9.39.1 + version: 9.39.1 '@vitejs/plugin-vue': specifier: ^5.2.4 - version: 5.2.4(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))(vue@3.5.22(typescript@5.9.3)) + version: 5.2.4(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))(vue@3.5.22(typescript@5.9.3)) '@vue/eslint-config-typescript': specifier: ^14.6.0 - version: 14.6.0(eslint-plugin-vue@10.5.1(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@2.6.1))))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + version: 14.6.0(eslint-plugin-vue@10.5.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.39.1(jiti@2.6.1))))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) eslint: - specifier: ^9.38.0 - version: 9.38.0(jiti@2.6.1) + specifier: ^9.39.1 + version: 9.39.1(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.38.0(jiti@2.6.1)) + version: 10.1.8(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-vue: specifier: ^10.5.1 - version: 10.5.1(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@2.6.1))) + version: 10.5.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.39.1(jiti@2.6.1))) globals: - specifier: ^16.4.0 - version: 16.4.0 + specifier: ^16.5.0 + version: 16.5.0 nodemon: specifier: ^3.1.10 version: 3.1.10 @@ -332,11 +344,11 @@ importers: specifier: ^5.9.3 version: 5.9.3 typescript-eslint: - specifier: ^8.46.2 - version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + specifier: ^8.46.3 + version: 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + version: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) vue: specifier: ^3.5.22 version: 3.5.22(typescript@5.9.3) @@ -357,10 +369,10 @@ importers: version: 0.3.9(react@19.2.0) '@tailwindcss/typography': specifier: ^0.5.19 - version: 0.5.19(tailwindcss@4.1.15) + version: 0.5.19(tailwindcss@4.1.16) '@tailwindcss/vite': - specifier: ^4.1.15 - version: 4.1.15(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + specifier: ^4.1.16 + version: 4.1.16(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) '@types/react': specifier: ^19.2.2 version: 19.2.2 @@ -369,16 +381,16 @@ importers: version: 19.2.2(@types/react@19.2.2) '@vitejs/plugin-react': specifier: ^4.7.0 - version: 4.7.0(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 4.7.0(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) autosize: specifier: ^6.0.1 version: 6.0.1 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 laravel-vite-plugin: specifier: ^1.3.0 - version: 1.3.0(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 1.3.0(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) lodash: specifier: ^4.17.21 version: 4.17.21 @@ -392,14 +404,14 @@ importers: specifier: ^19.2.0 version: 19.2.0(react@19.2.0) tailwindcss: - specifier: ^4.1.15 - version: 4.1.15 + specifier: ^4.1.16 + version: 4.1.16 typescript: specifier: ^4.9.5 version: 4.9.5 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + version: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) playgrounds/svelte4: devDependencies: @@ -411,19 +423,19 @@ importers: version: link:../../packages/svelte '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) '@tailwindcss/vite': - specifier: ^4.1.15 - version: 4.1.15(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + specifier: ^4.1.16 + version: 4.1.16(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) '@tsconfig/svelte': specifier: ^5.0.5 version: 5.0.5 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 laravel-vite-plugin: specifier: ^1.3.0 - version: 1.3.0(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 1.3.0(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) lodash: specifier: ^4.17.21 version: 4.17.21 @@ -434,14 +446,14 @@ importers: specifier: ^4.3.3 version: 4.3.3(picomatch@4.0.3)(svelte@4.2.20)(typescript@5.9.3) tailwindcss: - specifier: ^4.1.15 - version: 4.1.15 + specifier: ^4.1.16 + version: 4.1.16 typescript: specifier: ^5.9.3 version: 5.9.3 vite: specifier: ^5.4.21 - version: 5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0) + version: 5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0) playgrounds/svelte5: devDependencies: @@ -453,37 +465,37 @@ importers: version: link:../../packages/svelte '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.41.1)(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 5.1.1(svelte@5.43.3)(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) '@tailwindcss/vite': - specifier: ^4.1.15 - version: 4.1.15(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + specifier: ^4.1.16 + version: 4.1.16(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) '@tsconfig/svelte': specifier: ^5.0.5 version: 5.0.5 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 laravel-vite-plugin: specifier: ^1.3.0 - version: 1.3.0(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 1.3.0(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) lodash: specifier: ^4.17.21 version: 4.17.21 svelte: - specifier: ^5.41.1 - version: 5.41.1 + specifier: ^5.43.3 + version: 5.43.3 svelte-check: specifier: ^4.3.3 - version: 4.3.3(picomatch@4.0.3)(svelte@5.41.1)(typescript@5.9.3) + version: 4.3.3(picomatch@4.0.3)(svelte@5.43.3)(typescript@5.9.3) tailwindcss: - specifier: ^4.1.15 - version: 4.1.15 + specifier: ^4.1.16 + version: 4.1.16 typescript: specifier: ^5.9.3 version: 5.9.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + version: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) playgrounds/vue3: devDependencies: @@ -498,13 +510,13 @@ importers: version: 0.3.9(vue@3.5.22(typescript@5.9.3)) '@tailwindcss/typography': specifier: ^0.5.19 - version: 0.5.19(tailwindcss@4.1.15) + version: 0.5.19(tailwindcss@4.1.16) '@tailwindcss/vite': - specifier: ^4.1.15 - version: 4.1.15(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + specifier: ^4.1.16 + version: 4.1.16(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) '@vitejs/plugin-vue': specifier: ^5.2.4 - version: 5.2.4(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))(vue@3.5.22(typescript@5.9.3)) + version: 5.2.4(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))(vue@3.5.22(typescript@5.9.3)) '@vue/server-renderer': specifier: ^3.5.22 version: 3.5.22(vue@3.5.22(typescript@5.9.3)) @@ -512,11 +524,11 @@ importers: specifier: ^6.0.1 version: 6.0.1 axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.1 + version: 1.13.1 laravel-vite-plugin: specifier: ^1.3.0 - version: 1.3.0(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 1.3.0(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) lodash: specifier: ^4.17.21 version: 4.17.21 @@ -524,14 +536,14 @@ importers: specifier: ^16.4.1 version: 16.4.1 tailwindcss: - specifier: ^4.1.15 - version: 4.1.15 + specifier: ^4.1.16 + version: 4.1.16 typescript: specifier: ^5.9.3 version: 5.9.3 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + version: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) vue: specifier: ^3.5.22 version: 3.5.22(typescript@5.9.3) @@ -573,16 +585,16 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.4': - resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==} + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.4': - resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.3': - resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.27.2': @@ -611,8 +623,8 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} '@babel/helper-validator-option@7.27.1': @@ -627,8 +639,8 @@ packages: resolution: {integrity: sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.4': - resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -648,12 +660,12 @@ packages: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.4': - resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.4': - resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} '@colors/colors@1.6.0': @@ -669,8 +681,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.25.11': - resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -681,8 +693,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.25.11': - resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -693,8 +705,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.11': - resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -705,8 +717,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.25.11': - resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -717,8 +729,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.25.11': - resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -729,8 +741,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.25.11': - resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -741,8 +753,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.11': - resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -753,8 +765,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.11': - resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -765,8 +777,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.25.11': - resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -777,8 +789,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.25.11': - resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -789,8 +801,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.25.11': - resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -801,8 +813,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.11': - resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -813,8 +825,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.25.11': - resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -825,8 +837,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.25.11': - resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -837,8 +849,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.25.11': - resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -849,8 +861,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.25.11': - resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -861,14 +873,14 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.25.11': - resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.11': - resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -879,14 +891,14 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.11': - resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.11': - resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -897,14 +909,14 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.11': - resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.11': - resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] @@ -915,8 +927,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.25.11': - resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -927,8 +939,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.11': - resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -939,8 +951,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.11': - resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -951,8 +963,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.25.11': - resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -963,20 +975,20 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} '@eslint/config-array@0.21.1': resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.4.1': - resolution: {integrity: sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==} + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.16.0': - resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==} + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@0.4.3': @@ -987,16 +999,16 @@ packages: resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.38.0': - resolution: {integrity: sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==} + '@eslint/js@9.39.1': + resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.7': resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.4.0': - resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==} + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@humanfs/core@0.19.1': @@ -1219,8 +1231,8 @@ packages: typescript: '>= 5' typescript-eslint: '>= 8' - '@sveltejs/kit@2.47.2': - resolution: {integrity: sha512-mbUomaJTiADTrq6GT4ZvQ7v1rs0S+wXGMzrjFwjARAKMEF8FpOUmz2uEJ4M9WMJMQOXCMHpKFzJfdjo9O7M22A==} + '@sveltejs/kit@2.48.4': + resolution: {integrity: sha512-TGFX1pZUt9qqY20Cv5NyYvy0iLWHf2jXi8s+eCGsig7jQMdwZWKUFMR6TbvFNhfDSUpc1sH/Y5EHv20g3HHA3g==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -1269,65 +1281,65 @@ packages: svelte: ^5.0.0 vite: ^6.0.0 - '@tailwindcss/node@4.1.15': - resolution: {integrity: sha512-HF4+7QxATZWY3Jr8OlZrBSXmwT3Watj0OogeDvdUY/ByXJHQ+LBtqA2brDb3sBxYslIFx6UP94BJ4X6a4L9Bmw==} + '@tailwindcss/node@4.1.16': + resolution: {integrity: sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==} - '@tailwindcss/oxide-android-arm64@4.1.15': - resolution: {integrity: sha512-TkUkUgAw8At4cBjCeVCRMc/guVLKOU1D+sBPrHt5uVcGhlbVKxrCaCW9OKUIBv1oWkjh4GbunD/u/Mf0ql6kEA==} + '@tailwindcss/oxide-android-arm64@4.1.16': + resolution: {integrity: sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.1.15': - resolution: {integrity: sha512-xt5XEJpn2piMSfvd1UFN6jrWXyaKCwikP4Pidcf+yfHTSzSpYhG3dcMktjNkQO3JiLCp+0bG0HoWGvz97K162w==} + '@tailwindcss/oxide-darwin-arm64@4.1.16': + resolution: {integrity: sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.1.15': - resolution: {integrity: sha512-TnWaxP6Bx2CojZEXAV2M01Yl13nYPpp0EtGpUrY+LMciKfIXiLL2r/SiSRpagE5Fp2gX+rflp/Os1VJDAyqymg==} + '@tailwindcss/oxide-darwin-x64@4.1.16': + resolution: {integrity: sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.1.15': - resolution: {integrity: sha512-quISQDWqiB6Cqhjc3iWptXVZHNVENsWoI77L1qgGEHNIdLDLFnw3/AfY7DidAiiCIkGX/MjIdB3bbBZR/G2aJg==} + '@tailwindcss/oxide-freebsd-x64@4.1.16': + resolution: {integrity: sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.15': - resolution: {integrity: sha512-ObG76+vPlab65xzVUQbExmDU9FIeYLQ5k2LrQdR2Ud6hboR+ZobXpDoKEYXf/uOezOfIYmy2Ta3w0ejkTg9yxg==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16': + resolution: {integrity: sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.1.15': - resolution: {integrity: sha512-4WbBacRmk43pkb8/xts3wnOZMDKsPFyEH/oisCm2q3aLZND25ufvJKcDUpAu0cS+CBOL05dYa8D4U5OWECuH/Q==} + '@tailwindcss/oxide-linux-arm64-gnu@4.1.16': + resolution: {integrity: sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.1.15': - resolution: {integrity: sha512-AbvmEiteEj1nf42nE8skdHv73NoR+EwXVSgPY6l39X12Ex8pzOwwfi3Kc8GAmjsnsaDEbk+aj9NyL3UeyHcTLg==} + '@tailwindcss/oxide-linux-arm64-musl@4.1.16': + resolution: {integrity: sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.1.15': - resolution: {integrity: sha512-+rzMVlvVgrXtFiS+ES78yWgKqpThgV19ISKD58Ck+YO5pO5KjyxLt7AWKsWMbY0R9yBDC82w6QVGz837AKQcHg==} + '@tailwindcss/oxide-linux-x64-gnu@4.1.16': + resolution: {integrity: sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.1.15': - resolution: {integrity: sha512-fPdEy7a8eQN9qOIK3Em9D3TO1z41JScJn8yxl/76mp4sAXFDfV4YXxsiptJcOwy6bGR+70ZSwFIZhTXzQeqwQg==} + '@tailwindcss/oxide-linux-x64-musl@4.1.16': + resolution: {integrity: sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-wasm32-wasi@4.1.15': - resolution: {integrity: sha512-sJ4yd6iXXdlgIMfIBXuVGp/NvmviEoMVWMOAGxtxhzLPp9LOj5k0pMEMZdjeMCl4C6Up+RM8T3Zgk+BMQ0bGcQ==} + '@tailwindcss/oxide-wasm32-wasi@4.1.16': + resolution: {integrity: sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -1338,20 +1350,20 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.1.15': - resolution: {integrity: sha512-sJGE5faXnNQ1iXeqmRin7Ds/ru2fgCiaQZQQz3ZGIDtvbkeV85rAZ0QJFMDg0FrqsffZG96H1U9AQlNBRLsHVg==} + '@tailwindcss/oxide-win32-arm64-msvc@4.1.16': + resolution: {integrity: sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.1.15': - resolution: {integrity: sha512-NLeHE7jUV6HcFKS504bpOohyi01zPXi2PXmjFfkzTph8xRxDdxkRsXm/xDO5uV5K3brrE1cCwbUYmFUSHR3u1w==} + '@tailwindcss/oxide-win32-x64-msvc@4.1.16': + resolution: {integrity: sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.1.15': - resolution: {integrity: sha512-krhX+UOOgnsUuks2SR7hFafXmLQrKxB4YyRTERuCE59JlYL+FawgaAlSkOYmDRJdf1Q+IFNDMl9iRnBW7QBDfQ==} + '@tailwindcss/oxide@4.1.16': + resolution: {integrity: sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg==} engines: {node: '>= 10'} '@tailwindcss/typography@0.5.19': @@ -1359,8 +1371,8 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' - '@tailwindcss/vite@4.1.15': - resolution: {integrity: sha512-B6s60MZRTUil+xKoZoGe6i0Iar5VuW+pmcGlda2FX+guDuQ1G1sjiIy1W0frneVpeL/ZjZ4KEgWZHNrIm++2qA==} + '@tailwindcss/vite@4.1.16': + resolution: {integrity: sha512-bbguNBcDxsRmi9nnlWJxhfDWamY3lmcyACHcdO1crxfzuLpOhHLLtEIN/nCbbAtj5rchUgQD17QVAKi1f7IsKg==} peerDependencies: vite: ^5.2.0 || ^6 || ^7 @@ -1407,11 +1419,11 @@ packages: '@types/node@18.19.130': resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} - '@types/node@22.18.12': - resolution: {integrity: sha512-BICHQ67iqxQGFSzfCFTT7MRQ5XcBjG5aeKh5Ok38UBbPe5fxTyE+aHFxwVrGyr8GNlqFMLKD1D3P2K/1ks8tog==} + '@types/node@22.19.0': + resolution: {integrity: sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==} - '@types/node@24.9.1': - resolution: {integrity: sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==} + '@types/node@24.10.0': + resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==} '@types/nprogress@0.2.3': resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} @@ -1430,63 +1442,63 @@ packages: '@types/triple-beam@1.3.5': resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} - '@typescript-eslint/eslint-plugin@8.46.2': - resolution: {integrity: sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==} + '@typescript-eslint/eslint-plugin@8.46.3': + resolution: {integrity: sha512-sbaQ27XBUopBkRiuY/P9sWGOWUW4rl8fDoHIUmLpZd8uldsTyB4/Zg6bWTegPoTLnKj9Hqgn3QD6cjPNB32Odw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.46.2 + '@typescript-eslint/parser': ^8.46.3 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.46.2': - resolution: {integrity: sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==} + '@typescript-eslint/parser@8.46.3': + resolution: {integrity: sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.46.2': - resolution: {integrity: sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==} + '@typescript-eslint/project-service@8.46.3': + resolution: {integrity: sha512-Fz8yFXsp2wDFeUElO88S9n4w1I4CWDTXDqDr9gYvZgUpwXQqmZBr9+NTTql5R3J7+hrJZPdpiWaB9VNhAKYLuQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.46.2': - resolution: {integrity: sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==} + '@typescript-eslint/scope-manager@8.46.3': + resolution: {integrity: sha512-FCi7Y1zgrmxp3DfWfr+3m9ansUUFoy8dkEdeQSgA9gbm8DaHYvZCdkFRQrtKiedFf3Ha6VmoqoAaP68+i+22kg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.46.2': - resolution: {integrity: sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==} + '@typescript-eslint/tsconfig-utils@8.46.3': + resolution: {integrity: sha512-GLupljMniHNIROP0zE7nCcybptolcH8QZfXOpCfhQDAdwJ/ZTlcaBOYebSOZotpti/3HrHSw7D3PZm75gYFsOA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.46.2': - resolution: {integrity: sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==} + '@typescript-eslint/type-utils@8.46.3': + resolution: {integrity: sha512-ZPCADbr+qfz3aiTTYNNkCbUt+cjNwI/5McyANNrFBpVxPt7GqpEYz5ZfdwuFyGUnJ9FdDXbGODUu6iRCI6XRXw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.46.2': - resolution: {integrity: sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==} + '@typescript-eslint/types@8.46.3': + resolution: {integrity: sha512-G7Ok9WN/ggW7e/tOf8TQYMaxgID3Iujn231hfi0Pc7ZheztIJVpO44ekY00b7akqc6nZcvregk0Jpah3kep6hA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.46.2': - resolution: {integrity: sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==} + '@typescript-eslint/typescript-estree@8.46.3': + resolution: {integrity: sha512-f/NvtRjOm80BtNM5OQtlaBdM5BRFUv7gf381j9wygDNL+qOYSNOgtQ/DCndiYi80iIOv76QqaTmp4fa9hwI0OA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.46.2': - resolution: {integrity: sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==} + '@typescript-eslint/utils@8.46.3': + resolution: {integrity: sha512-VXw7qmdkucEx9WkmR3ld/u6VhRyKeiF1uxWwCy/iuNfokjJ7VhsgLSOTjsol8BunSw190zABzpwdNsze2Kpo4g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.46.2': - resolution: {integrity: sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==} + '@typescript-eslint/visitor-keys@8.46.3': + resolution: {integrity: sha512-uk574k8IU0rOF/AjniX8qbLSGURJVUCeM5e4MIMKBFFi8weeiLrG1fyQejyLXQpRZbU/1BuQasleV/RfHC3hHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vitejs/plugin-react@4.7.0': @@ -1754,8 +1766,8 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axios@1.12.2: - resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} + axios@1.13.1: + resolution: {integrity: sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==} axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} @@ -1764,8 +1776,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - baseline-browser-mapping@2.8.18: - resolution: {integrity: sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w==} + baseline-browser-mapping@2.8.23: + resolution: {integrity: sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==} hasBin: true big.js@5.2.2: @@ -1792,8 +1804,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.26.3: - resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==} + browserslist@4.27.0: + resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1824,8 +1836,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001751: - resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} + caniuse-lite@1.0.30001753: + resolution: {integrity: sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -2011,8 +2023,8 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - devalue@5.4.1: - resolution: {integrity: sha512-YtoaOfsqjbZQKGIMRYDWKjUmSB4VJ/RElB+bXZawQAQYAo4xu08GKTMVlsZDTF6R2MbAgjcAQRPI5eIyRAT2OQ==} + devalue@5.4.2: + resolution: {integrity: sha512-MwPZTKEPK2k8Qgfmqrd48ZKVvzSQjgW0lXLxiIBA8dQjtf/6mw6pggHNLcyDKyf+fI6eXxlQwPsfaCMTU5U+Bw==} doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} @@ -2029,8 +2041,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.237: - resolution: {integrity: sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==} + electron-to-chromium@1.5.244: + resolution: {integrity: sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2113,8 +2125,8 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.25.11: - resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} hasBin: true @@ -2169,8 +2181,8 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - eslint-plugin-svelte@3.12.5: - resolution: {integrity: sha512-4KRG84eAHQfYd9OjZ1K7sCHy0nox+9KwT+s5WCCku3jTim5RV4tVENob274nCwIaApXsYPKAUAZFBxKZ3Wyfjw==} + eslint-plugin-svelte@3.13.0: + resolution: {integrity: sha512-2ohCCQJJTNbIpQCSDSTWj+FN0OVfPmSO03lmSNT7ytqMaWF6kpT86LdzDqtm4sh7TVPl/OEWJ/d7R87bXP2Vjg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.1 || ^9.0.0 @@ -2227,8 +2239,8 @@ packages: deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true - eslint@9.38.0: - resolution: {integrity: sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==} + eslint@9.39.1: + resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -2257,8 +2269,8 @@ packages: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} - esrap@2.1.0: - resolution: {integrity: sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==} + esrap@2.1.2: + resolution: {integrity: sha512-DgvlIQeowRNyvLPWW4PT7Gu13WznY288Du086E751mwwbsgr29ytBiYeLzAGIo0qk3Ujob0SDk8TiSaM5WQzNg==} esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} @@ -2433,8 +2445,8 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.12.0: - resolution: {integrity: sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw==} + get-tsconfig@4.13.0: + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -2468,8 +2480,8 @@ packages: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} - globals@16.4.0: - resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + globals@16.5.0: + resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} engines: {node: '>=18'} globalthis@1.0.4: @@ -2769,6 +2781,9 @@ packages: kuler@2.0.0: resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + laravel-precognition@0.7.3: + resolution: {integrity: sha512-Z97i35Q0wmsRC9WFUY2EmFS2W1F6FF/HakwZg6PqSaR9lHBgbdIs1YZpDlkChVkgcmmvbN19ujKss3ZqbjPM1g==} + laravel-vite-plugin@1.3.0: resolution: {integrity: sha512-P5qyG56YbYxM8OuYmK2OkhcKe0AksNVJUjq9LUZ5tOekU9fBn9LujYyctI4t9XoLjuMvHJXXpCoPntY1oKltuA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -2896,8 +2911,8 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - magic-string@0.30.19: - resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} marked@16.4.1: resolution: {integrity: sha512-ntROs7RaN3EvWfy3EZi14H4YxmT6A5YvywfhO+0pm+cH/dnSQRmdAmoFIc3B9aiwTehyk7pESH4ofyBY+V5hZg==} @@ -3005,8 +3020,8 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - node-releases@2.0.26: - resolution: {integrity: sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==} + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} nodemon@3.1.10: resolution: {integrity: sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==} @@ -3477,8 +3492,8 @@ packages: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} - set-cookie-parser@2.7.1: - resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} @@ -3647,16 +3662,16 @@ packages: resolution: {integrity: sha512-eeEgGc2DtiUil5ANdtd8vPwt9AgaMdnuUFnPft9F5oMvU/FHu5IHFic+p1dR/UOB7XU2mX2yHW+NcTch4DCh5Q==} engines: {node: '>=16'} - svelte@5.41.1: - resolution: {integrity: sha512-0a/huwc8e2es+7KFi70esqsReRfRbrT8h1cJSY/+z1lF0yKM6TT+//HYu28Yxstr50H7ifaqZRDGd0KuKDxP7w==} + svelte@5.43.3: + resolution: {integrity: sha512-kjkAjCk41mJfvJZG56XcJNOdJSke94JxtcX8zFzzz2vrt47E0LnoBzU6azIZ1aBxJgUep8qegAkguSf1GjxLXQ==} engines: {node: '>=18'} table@6.9.0: resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} engines: {node: '>=10.0.0'} - tailwindcss@4.1.15: - resolution: {integrity: sha512-k2WLnWkYFkdpRv+Oby3EBXIyQC8/s1HOFMBUViwtAh6Z5uAozeUSMQlIsn/c6Q2iJzqG6aJT3wdPaRNj70iYxQ==} + tailwindcss@4.1.16: + resolution: {integrity: sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==} tapable@2.3.0: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} @@ -3758,8 +3773,8 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript-eslint@8.46.2: - resolution: {integrity: sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg==} + typescript-eslint@8.46.3: + resolution: {integrity: sha512-bAfgMavTuGo+8n6/QQDVQz4tZ4f7Soqg53RbrlZQEoAltYop/XR4RAts/I0BrO3TTClTSTFJ0wYbla+P8cEWJA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3795,8 +3810,8 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + update-browserslist-db@1.1.4: + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -4020,23 +4035,23 @@ snapshots: '@babel/code-frame@7.27.1': dependencies: - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.28.4': {} + '@babel/compat-data@7.28.5': {} - '@babel/core@7.28.4': + '@babel/core@7.28.5': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 + '@babel/generator': 7.28.5 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3(supports-color@5.5.0) @@ -4046,19 +4061,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.28.3': + '@babel/generator@7.28.5': dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.28.4 + '@babel/compat-data': 7.28.5 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.26.3 + browserslist: 4.27.0 lru-cache: 5.1.1 semver: 6.3.1 @@ -4066,17 +4081,17 @@ snapshots: '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)': + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.5 '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.4 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color @@ -4084,58 +4099,58 @@ snapshots: '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-identifier@7.28.5': {} '@babel/helper-validator-option@7.27.1': {} '@babel/helpers@7.28.4': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@babel/highlight@7.25.9': dependencies: - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 chalk: 2.4.2 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/parser@7.28.4': + '@babel/parser@7.28.5': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.4)': + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.5 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.4)': + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.5 '@babel/helper-plugin-utils': 7.27.1 '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 - '@babel/traverse@7.28.4': + '@babel/traverse@7.28.5': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 + '@babel/generator': 7.28.5 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 debug: 4.4.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color - '@babel/types@7.28.4': + '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 '@colors/colors@1.6.0': {} @@ -4148,156 +4163,156 @@ snapshots: '@esbuild/aix-ppc64@0.21.5': optional: true - '@esbuild/aix-ppc64@0.25.11': + '@esbuild/aix-ppc64@0.25.12': optional: true '@esbuild/android-arm64@0.21.5': optional: true - '@esbuild/android-arm64@0.25.11': + '@esbuild/android-arm64@0.25.12': optional: true '@esbuild/android-arm@0.21.5': optional: true - '@esbuild/android-arm@0.25.11': + '@esbuild/android-arm@0.25.12': optional: true '@esbuild/android-x64@0.21.5': optional: true - '@esbuild/android-x64@0.25.11': + '@esbuild/android-x64@0.25.12': optional: true '@esbuild/darwin-arm64@0.21.5': optional: true - '@esbuild/darwin-arm64@0.25.11': + '@esbuild/darwin-arm64@0.25.12': optional: true '@esbuild/darwin-x64@0.21.5': optional: true - '@esbuild/darwin-x64@0.25.11': + '@esbuild/darwin-x64@0.25.12': optional: true '@esbuild/freebsd-arm64@0.21.5': optional: true - '@esbuild/freebsd-arm64@0.25.11': + '@esbuild/freebsd-arm64@0.25.12': optional: true '@esbuild/freebsd-x64@0.21.5': optional: true - '@esbuild/freebsd-x64@0.25.11': + '@esbuild/freebsd-x64@0.25.12': optional: true '@esbuild/linux-arm64@0.21.5': optional: true - '@esbuild/linux-arm64@0.25.11': + '@esbuild/linux-arm64@0.25.12': optional: true '@esbuild/linux-arm@0.21.5': optional: true - '@esbuild/linux-arm@0.25.11': + '@esbuild/linux-arm@0.25.12': optional: true '@esbuild/linux-ia32@0.21.5': optional: true - '@esbuild/linux-ia32@0.25.11': + '@esbuild/linux-ia32@0.25.12': optional: true '@esbuild/linux-loong64@0.21.5': optional: true - '@esbuild/linux-loong64@0.25.11': + '@esbuild/linux-loong64@0.25.12': optional: true '@esbuild/linux-mips64el@0.21.5': optional: true - '@esbuild/linux-mips64el@0.25.11': + '@esbuild/linux-mips64el@0.25.12': optional: true '@esbuild/linux-ppc64@0.21.5': optional: true - '@esbuild/linux-ppc64@0.25.11': + '@esbuild/linux-ppc64@0.25.12': optional: true '@esbuild/linux-riscv64@0.21.5': optional: true - '@esbuild/linux-riscv64@0.25.11': + '@esbuild/linux-riscv64@0.25.12': optional: true '@esbuild/linux-s390x@0.21.5': optional: true - '@esbuild/linux-s390x@0.25.11': + '@esbuild/linux-s390x@0.25.12': optional: true '@esbuild/linux-x64@0.21.5': optional: true - '@esbuild/linux-x64@0.25.11': + '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/netbsd-arm64@0.25.11': + '@esbuild/netbsd-arm64@0.25.12': optional: true '@esbuild/netbsd-x64@0.21.5': optional: true - '@esbuild/netbsd-x64@0.25.11': + '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.25.11': + '@esbuild/openbsd-arm64@0.25.12': optional: true '@esbuild/openbsd-x64@0.21.5': optional: true - '@esbuild/openbsd-x64@0.25.11': + '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/openharmony-arm64@0.25.11': + '@esbuild/openharmony-arm64@0.25.12': optional: true '@esbuild/sunos-x64@0.21.5': optional: true - '@esbuild/sunos-x64@0.25.11': + '@esbuild/sunos-x64@0.25.12': optional: true '@esbuild/win32-arm64@0.21.5': optional: true - '@esbuild/win32-arm64@0.25.11': + '@esbuild/win32-arm64@0.25.12': optional: true '@esbuild/win32-ia32@0.21.5': optional: true - '@esbuild/win32-ia32@0.25.11': + '@esbuild/win32-ia32@0.25.12': optional: true '@esbuild/win32-x64@0.21.5': optional: true - '@esbuild/win32-x64@0.25.11': + '@esbuild/win32-x64@0.25.12': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.38.0(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.6.1))': dependencies: - eslint: 9.38.0(jiti@2.6.1) + eslint: 9.39.1(jiti@2.6.1) eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.12.1': {} + '@eslint-community/regexpp@4.12.2': {} '@eslint/config-array@0.21.1': dependencies: @@ -4307,11 +4322,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.4.1': + '@eslint/config-helpers@0.4.2': dependencies: - '@eslint/core': 0.16.0 + '@eslint/core': 0.17.0 - '@eslint/core@0.16.0': + '@eslint/core@0.17.0': dependencies: '@types/json-schema': 7.0.15 @@ -4343,13 +4358,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.38.0': {} + '@eslint/js@9.39.1': {} '@eslint/object-schema@2.1.7': {} - '@eslint/plugin-kit@0.4.0': + '@eslint/plugin-kit@0.4.1': dependencies: - '@eslint/core': 0.16.0 + '@eslint/core': 0.17.0 levn: 0.4.1 '@humanfs/core@0.19.1': {} @@ -4499,9 +4514,9 @@ snapshots: '@standard-schema/spec@1.0.0': {} - '@stylistic/eslint-plugin-js@4.4.1(eslint@9.38.0(jiti@2.6.1))': + '@stylistic/eslint-plugin-js@4.4.1(eslint@9.39.1(jiti@2.6.1))': dependencies: - eslint: 9.38.0(jiti@2.6.1) + eslint: 9.39.1(jiti@2.6.1) eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -4509,40 +4524,40 @@ snapshots: dependencies: acorn: 8.15.0 - '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.47.2(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)))': + '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.48.4(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)))': dependencies: - '@sveltejs/kit': 2.47.2(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + '@sveltejs/kit': 2.48.4(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) import-meta-resolve: 4.2.0 - '@sveltejs/eslint-config@8.3.4(@stylistic/eslint-plugin-js@4.4.1(eslint@9.38.0(jiti@2.6.1)))(eslint-config-prettier@10.1.8(eslint@9.38.0(jiti@2.6.1)))(eslint-plugin-n@17.23.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-plugin-svelte@3.12.5(eslint@9.38.0(jiti@2.6.1))(svelte@4.2.20))(eslint@9.38.0(jiti@2.6.1))(typescript-eslint@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(typescript@5.9.3)': + '@sveltejs/eslint-config@8.3.4(@stylistic/eslint-plugin-js@4.4.1(eslint@9.39.1(jiti@2.6.1)))(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint-plugin-n@17.23.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-plugin-svelte@3.13.0(eslint@9.39.1(jiti@2.6.1))(svelte@4.2.20))(eslint@9.39.1(jiti@2.6.1))(typescript-eslint@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(typescript@5.9.3)': dependencies: - '@stylistic/eslint-plugin-js': 4.4.1(eslint@9.38.0(jiti@2.6.1)) - eslint: 9.38.0(jiti@2.6.1) - eslint-config-prettier: 10.1.8(eslint@9.38.0(jiti@2.6.1)) - eslint-plugin-n: 17.23.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - eslint-plugin-svelte: 3.12.5(eslint@9.38.0(jiti@2.6.1))(svelte@4.2.20) + '@stylistic/eslint-plugin-js': 4.4.1(eslint@9.39.1(jiti@2.6.1)) + eslint: 9.39.1(jiti@2.6.1) + eslint-config-prettier: 10.1.8(eslint@9.39.1(jiti@2.6.1)) + eslint-plugin-n: 17.23.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + eslint-plugin-svelte: 3.13.0(eslint@9.39.1(jiti@2.6.1))(svelte@4.2.20) globals: 15.15.0 typescript: 5.9.3 - typescript-eslint: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + typescript-eslint: 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - '@sveltejs/kit@2.47.2(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0))': + '@sveltejs/kit@2.48.4(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: '@standard-schema/spec': 1.0.0 '@sveltejs/acorn-typescript': 1.0.6(acorn@8.15.0) - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) '@types/cookie': 0.6.0 acorn: 8.15.0 cookie: 0.6.0 - devalue: 5.4.1 + devalue: 5.4.2 esm-env: 1.2.2 kleur: 4.1.5 - magic-string: 0.30.19 + magic-string: 0.30.21 mrmime: 2.0.1 sade: 1.8.1 - set-cookie-parser: 2.7.1 + set-cookie-parser: 2.7.2 sirv: 3.0.2 svelte: 4.2.20 - vite: 5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0) + vite: 5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0) '@sveltejs/package@2.5.4(svelte@4.2.20)(typescript@5.9.3)': dependencies: @@ -4555,153 +4570,153 @@ snapshots: transitivePeerDependencies: - typescript - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) debug: 4.4.3(supports-color@5.5.0) svelte: 4.2.20 - vite: 5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0) + vite: 5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.41.1)(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@5.41.1)(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.3)(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@5.43.3)(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.41.1)(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.43.3)(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) debug: 4.4.3(supports-color@5.5.0) - svelte: 5.41.1 - vite: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + svelte: 5.43.3 + vite: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0))': + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@4.2.20)(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) debug: 4.4.3(supports-color@5.5.0) deepmerge: 4.3.1 kleur: 4.1.5 - magic-string: 0.30.19 + magic-string: 0.30.21 svelte: 4.2.20 svelte-hmr: 0.16.0(svelte@4.2.20) - vite: 5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0) - vitefu: 0.2.5(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)) + vite: 5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0) + vitefu: 0.2.5(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.41.1)(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': + '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.3)(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.41.1)(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@5.41.1)(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.3)(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)))(svelte@5.43.3)(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) debug: 4.4.3(supports-color@5.5.0) deepmerge: 4.3.1 kleur: 4.1.5 - magic-string: 0.30.19 - svelte: 5.41.1 - vite: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) - vitefu: 1.1.1(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + magic-string: 0.30.21 + svelte: 5.43.3 + vite: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + vitefu: 1.1.1(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) transitivePeerDependencies: - supports-color - '@tailwindcss/node@4.1.15': + '@tailwindcss/node@4.1.16': dependencies: '@jridgewell/remapping': 2.3.5 enhanced-resolve: 5.18.3 jiti: 2.6.1 lightningcss: 1.30.2 - magic-string: 0.30.19 + magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.1.15 + tailwindcss: 4.1.16 - '@tailwindcss/oxide-android-arm64@4.1.15': + '@tailwindcss/oxide-android-arm64@4.1.16': optional: true - '@tailwindcss/oxide-darwin-arm64@4.1.15': + '@tailwindcss/oxide-darwin-arm64@4.1.16': optional: true - '@tailwindcss/oxide-darwin-x64@4.1.15': + '@tailwindcss/oxide-darwin-x64@4.1.16': optional: true - '@tailwindcss/oxide-freebsd-x64@4.1.15': + '@tailwindcss/oxide-freebsd-x64@4.1.16': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.15': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.1.15': + '@tailwindcss/oxide-linux-arm64-gnu@4.1.16': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.1.15': + '@tailwindcss/oxide-linux-arm64-musl@4.1.16': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.1.15': + '@tailwindcss/oxide-linux-x64-gnu@4.1.16': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.1.15': + '@tailwindcss/oxide-linux-x64-musl@4.1.16': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.1.15': + '@tailwindcss/oxide-wasm32-wasi@4.1.16': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.1.15': + '@tailwindcss/oxide-win32-arm64-msvc@4.1.16': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.1.15': + '@tailwindcss/oxide-win32-x64-msvc@4.1.16': optional: true - '@tailwindcss/oxide@4.1.15': + '@tailwindcss/oxide@4.1.16': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.1.15 - '@tailwindcss/oxide-darwin-arm64': 4.1.15 - '@tailwindcss/oxide-darwin-x64': 4.1.15 - '@tailwindcss/oxide-freebsd-x64': 4.1.15 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.15 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.15 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.15 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.15 - '@tailwindcss/oxide-linux-x64-musl': 4.1.15 - '@tailwindcss/oxide-wasm32-wasi': 4.1.15 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.15 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.15 - - '@tailwindcss/typography@0.5.19(tailwindcss@4.1.15)': + '@tailwindcss/oxide-android-arm64': 4.1.16 + '@tailwindcss/oxide-darwin-arm64': 4.1.16 + '@tailwindcss/oxide-darwin-x64': 4.1.16 + '@tailwindcss/oxide-freebsd-x64': 4.1.16 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.16 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.16 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.16 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.16 + '@tailwindcss/oxide-linux-x64-musl': 4.1.16 + '@tailwindcss/oxide-wasm32-wasi': 4.1.16 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.16 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.16 + + '@tailwindcss/typography@0.5.19(tailwindcss@4.1.16)': dependencies: postcss-selector-parser: 6.0.10 - tailwindcss: 4.1.15 + tailwindcss: 4.1.16 - '@tailwindcss/vite@4.1.15(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0))': + '@tailwindcss/vite@4.1.16(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@tailwindcss/node': 4.1.15 - '@tailwindcss/oxide': 4.1.15 - tailwindcss: 4.1.15 - vite: 5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0) + '@tailwindcss/node': 4.1.16 + '@tailwindcss/oxide': 4.1.16 + tailwindcss: 4.1.16 + vite: 5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0) - '@tailwindcss/vite@4.1.15(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': + '@tailwindcss/vite@4.1.16(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@tailwindcss/node': 4.1.15 - '@tailwindcss/oxide': 4.1.15 - tailwindcss: 4.1.15 - vite: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + '@tailwindcss/node': 4.1.16 + '@tailwindcss/oxide': 4.1.16 + tailwindcss: 4.1.16 + vite: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) '@tsconfig/svelte@5.0.5': {} '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@types/cookie@0.6.0': {} @@ -4733,11 +4748,11 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/node@22.18.12': + '@types/node@22.19.0': dependencies: undici-types: 6.21.0 - '@types/node@24.9.1': + '@types/node@24.10.0': dependencies: undici-types: 7.16.0 @@ -4755,15 +4770,15 @@ snapshots: '@types/triple-beam@1.3.5': {} - '@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.46.2 - '@typescript-eslint/type-utils': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.2 - eslint: 9.38.0(jiti@2.6.1) + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.46.3 + '@typescript-eslint/type-utils': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.3 + eslint: 9.39.1(jiti@2.6.1) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -4772,56 +4787,56 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.46.2 - '@typescript-eslint/types': 8.46.2 - '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.2 + '@typescript-eslint/scope-manager': 8.46.3 + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.3 debug: 4.4.3(supports-color@5.5.0) - eslint: 9.38.0(jiti@2.6.1) + eslint: 9.39.1(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.46.2(typescript@5.9.3)': + '@typescript-eslint/project-service@8.46.3(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.9.3) - '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/tsconfig-utils': 8.46.3(typescript@5.9.3) + '@typescript-eslint/types': 8.46.3 debug: 4.4.3(supports-color@5.5.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.46.2': + '@typescript-eslint/scope-manager@8.46.3': dependencies: - '@typescript-eslint/types': 8.46.2 - '@typescript-eslint/visitor-keys': 8.46.2 + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/visitor-keys': 8.46.3 - '@typescript-eslint/tsconfig-utils@8.46.2(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.46.3(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.46.2 - '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) debug: 4.4.3(supports-color@5.5.0) - eslint: 9.38.0(jiti@2.6.1) + eslint: 9.39.1(jiti@2.6.1) ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.46.2': {} + '@typescript-eslint/types@8.46.3': {} - '@typescript-eslint/typescript-estree@8.46.2(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.46.3(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.46.2(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.9.3) - '@typescript-eslint/types': 8.46.2 - '@typescript-eslint/visitor-keys': 8.46.2 + '@typescript-eslint/project-service': 8.46.3(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.46.3(typescript@5.9.3) + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/visitor-keys': 8.46.3 debug: 4.4.3(supports-color@5.5.0) fast-glob: 3.3.3 is-glob: 4.0.3 @@ -4832,37 +4847,37 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.46.2 - '@typescript-eslint/types': 8.46.2 - '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.9.3) - eslint: 9.38.0(jiti@2.6.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.46.3 + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) + eslint: 9.39.1(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.46.2': + '@typescript-eslint/visitor-keys@8.46.3': dependencies: - '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/types': 8.46.3 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': + '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: - '@babel/core': 7.28.4 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.4) + '@babel/core': 7.28.5 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5) '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + vite: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.2.4(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))(vue@3.5.22(typescript@5.9.3))': + '@vitejs/plugin-vue@5.2.4(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))(vue@3.5.22(typescript@5.9.3))': dependencies: - vite: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + vite: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) vue: 3.5.22(typescript@5.9.3) '@volar/language-core@2.4.15': @@ -4879,7 +4894,7 @@ snapshots: '@vue/compiler-core@3.5.22': dependencies: - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@vue/shared': 3.5.22 entities: 4.5.0 estree-walker: 2.0.2 @@ -4892,13 +4907,13 @@ snapshots: '@vue/compiler-sfc@3.5.22': dependencies: - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@vue/compiler-core': 3.5.22 '@vue/compiler-dom': 3.5.22 '@vue/compiler-ssr': 3.5.22 '@vue/shared': 3.5.22 estree-walker: 2.0.2 - magic-string: 0.30.19 + magic-string: 0.30.21 postcss: 8.5.6 source-map-js: 1.2.1 @@ -4912,14 +4927,14 @@ snapshots: de-indent: 1.0.2 he: 1.2.0 - '@vue/eslint-config-typescript@14.6.0(eslint-plugin-vue@10.5.1(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@2.6.1))))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': + '@vue/eslint-config-typescript@14.6.0(eslint-plugin-vue@10.5.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.39.1(jiti@2.6.1))))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/utils': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.38.0(jiti@2.6.1) - eslint-plugin-vue: 10.5.1(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@2.6.1))) + '@typescript-eslint/utils': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.1(jiti@2.6.1) + eslint-plugin-vue: 10.5.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.39.1(jiti@2.6.1))) fast-glob: 3.3.3 - typescript-eslint: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - vue-eslint-parser: 10.2.0(eslint@9.38.0(jiti@2.6.1)) + typescript-eslint: 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + vue-eslint-parser: 10.2.0(eslint@9.39.1(jiti@2.6.1)) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -5196,7 +5211,7 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - axios@1.12.2: + axios@1.13.1: dependencies: follow-redirects: 1.15.11 form-data: 4.0.4 @@ -5208,7 +5223,7 @@ snapshots: balanced-match@1.0.2: {} - baseline-browser-mapping@2.8.18: {} + baseline-browser-mapping@2.8.23: {} big.js@5.2.2: {} @@ -5246,13 +5261,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.26.3: + browserslist@4.27.0: dependencies: - baseline-browser-mapping: 2.8.18 - caniuse-lite: 1.0.30001751 - electron-to-chromium: 1.5.237 - node-releases: 2.0.26 - update-browserslist-db: 1.1.3(browserslist@4.26.3) + baseline-browser-mapping: 2.8.23 + caniuse-lite: 1.0.30001753 + electron-to-chromium: 1.5.244 + node-releases: 2.0.27 + update-browserslist-db: 1.1.4(browserslist@4.27.0) buffer-from@1.1.2: {} @@ -5281,7 +5296,7 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001751: {} + caniuse-lite@1.0.30001753: {} chalk@2.4.2: dependencies: @@ -5465,7 +5480,7 @@ snapshots: detect-libc@2.1.2: {} - devalue@5.4.1: {} + devalue@5.4.2: {} doctrine@2.1.0: dependencies: @@ -5483,7 +5498,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.237: {} + electron-to-chromium@1.5.244: {} emoji-regex@8.0.0: {} @@ -5568,7 +5583,7 @@ snapshots: dependencies: acorn: 8.15.0 acorn-walk: 8.3.4 - browserslist: 4.26.3 + browserslist: 4.27.0 commander: 14.0.1 fast-brake: 0.1.6 fast-glob: 3.3.3 @@ -5623,9 +5638,9 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild-node-externals@1.18.0(esbuild@0.25.11): + esbuild-node-externals@1.18.0(esbuild@0.25.12): dependencies: - esbuild: 0.25.11 + esbuild: 0.25.12 find-up: 5.0.0 esbuild@0.21.5: @@ -5654,34 +5669,34 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - esbuild@0.25.11: + esbuild@0.25.12: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.11 - '@esbuild/android-arm': 0.25.11 - '@esbuild/android-arm64': 0.25.11 - '@esbuild/android-x64': 0.25.11 - '@esbuild/darwin-arm64': 0.25.11 - '@esbuild/darwin-x64': 0.25.11 - '@esbuild/freebsd-arm64': 0.25.11 - '@esbuild/freebsd-x64': 0.25.11 - '@esbuild/linux-arm': 0.25.11 - '@esbuild/linux-arm64': 0.25.11 - '@esbuild/linux-ia32': 0.25.11 - '@esbuild/linux-loong64': 0.25.11 - '@esbuild/linux-mips64el': 0.25.11 - '@esbuild/linux-ppc64': 0.25.11 - '@esbuild/linux-riscv64': 0.25.11 - '@esbuild/linux-s390x': 0.25.11 - '@esbuild/linux-x64': 0.25.11 - '@esbuild/netbsd-arm64': 0.25.11 - '@esbuild/netbsd-x64': 0.25.11 - '@esbuild/openbsd-arm64': 0.25.11 - '@esbuild/openbsd-x64': 0.25.11 - '@esbuild/openharmony-arm64': 0.25.11 - '@esbuild/sunos-x64': 0.25.11 - '@esbuild/win32-arm64': 0.25.11 - '@esbuild/win32-ia32': 0.25.11 - '@esbuild/win32-x64': 0.25.11 + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 escalade@3.2.0: {} @@ -5691,29 +5706,29 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-compat-utils@0.5.1(eslint@9.38.0(jiti@2.6.1)): + eslint-compat-utils@0.5.1(eslint@9.39.1(jiti@2.6.1)): dependencies: - eslint: 9.38.0(jiti@2.6.1) + eslint: 9.39.1(jiti@2.6.1) semver: 7.7.3 - eslint-config-prettier@10.1.8(eslint@9.38.0(jiti@2.6.1)): + eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)): dependencies: - eslint: 9.38.0(jiti@2.6.1) + eslint: 9.39.1(jiti@2.6.1) - eslint-plugin-es-x@7.8.0(eslint@9.38.0(jiti@2.6.1)): + eslint-plugin-es-x@7.8.0(eslint@9.39.1(jiti@2.6.1)): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.1 - eslint: 9.38.0(jiti@2.6.1) - eslint-compat-utils: 0.5.1(eslint@9.38.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + eslint: 9.39.1(jiti@2.6.1) + eslint-compat-utils: 0.5.1(eslint@9.39.1(jiti@2.6.1)) - eslint-plugin-n@17.23.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3): + eslint-plugin-n@17.23.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) enhanced-resolve: 5.18.3 - eslint: 9.38.0(jiti@2.6.1) - eslint-plugin-es-x: 7.8.0(eslint@9.38.0(jiti@2.6.1)) - get-tsconfig: 4.12.0 + eslint: 9.39.1(jiti@2.6.1) + eslint-plugin-es-x: 7.8.0(eslint@9.39.1(jiti@2.6.1)) + get-tsconfig: 4.13.0 globals: 15.15.0 globrex: 0.1.2 ignore: 5.3.2 @@ -5722,11 +5737,11 @@ snapshots: transitivePeerDependencies: - typescript - eslint-plugin-react-hooks@5.2.0(eslint@9.38.0(jiti@2.6.1)): + eslint-plugin-react-hooks@5.2.0(eslint@9.39.1(jiti@2.6.1)): dependencies: - eslint: 9.38.0(jiti@2.6.1) + eslint: 9.39.1(jiti@2.6.1) - eslint-plugin-react@7.37.5(eslint@9.38.0(jiti@2.6.1)): + eslint-plugin-react@7.37.5(eslint@9.39.1(jiti@2.6.1)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -5734,7 +5749,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.38.0(jiti@2.6.1) + eslint: 9.39.1(jiti@2.6.1) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -5748,13 +5763,13 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-svelte@3.12.5(eslint@9.38.0(jiti@2.6.1))(svelte@4.2.20): + eslint-plugin-svelte@3.13.0(eslint@9.39.1(jiti@2.6.1))(svelte@4.2.20): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) '@jridgewell/sourcemap-codec': 1.5.5 - eslint: 9.38.0(jiti@2.6.1) + eslint: 9.39.1(jiti@2.6.1) esutils: 2.0.3 - globals: 16.4.0 + globals: 16.5.0 known-css-properties: 0.37.0 postcss: 8.5.6 postcss-load-config: 3.1.4(postcss@8.5.6) @@ -5766,18 +5781,18 @@ snapshots: transitivePeerDependencies: - ts-node - eslint-plugin-vue@10.5.1(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@2.6.1))): + eslint-plugin-vue@10.5.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.39.1(jiti@2.6.1))): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) - eslint: 9.38.0(jiti@2.6.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) + eslint: 9.39.1(jiti@2.6.1) natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.2 semver: 7.7.3 - vue-eslint-parser: 10.2.0(eslint@9.38.0(jiti@2.6.1)) + vue-eslint-parser: 10.2.0(eslint@9.39.1(jiti@2.6.1)) xml-name-validator: 4.0.0 optionalDependencies: - '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) eslint-scope@5.1.1: dependencies: @@ -5846,16 +5861,16 @@ snapshots: transitivePeerDependencies: - supports-color - eslint@9.38.0(jiti@2.6.1): + eslint@9.39.1(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.1 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 - '@eslint/config-helpers': 0.4.1 - '@eslint/core': 0.16.0 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.38.0 - '@eslint/plugin-kit': 0.4.0 + '@eslint/js': 9.39.1 + '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -5907,7 +5922,7 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@2.1.0: + esrap@2.1.2: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -6108,7 +6123,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 - get-tsconfig@4.12.0: + get-tsconfig@4.13.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -6147,7 +6162,7 @@ snapshots: globals@15.15.0: {} - globals@16.4.0: {} + globals@16.5.0: {} globalthis@1.0.4: dependencies: @@ -6375,7 +6390,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 24.9.1 + '@types/node': 24.10.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -6423,16 +6438,23 @@ snapshots: kuler@2.0.0: {} - laravel-vite-plugin@1.3.0(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)): + laravel-precognition@0.7.3: + dependencies: + axios: 1.13.1 + lodash-es: 4.17.21 + transitivePeerDependencies: + - debug + + laravel-vite-plugin@1.3.0(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)): dependencies: picocolors: 1.1.1 - vite: 5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0) + vite: 5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0) vite-plugin-full-reload: 1.2.0 - laravel-vite-plugin@1.3.0(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)): + laravel-vite-plugin@1.3.0(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)): dependencies: picocolors: 1.1.1 - vite: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + vite: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) vite-plugin-full-reload: 1.2.0 levn@0.4.1: @@ -6532,7 +6554,7 @@ snapshots: dependencies: yallist: 3.1.1 - magic-string@0.30.19: + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -6613,7 +6635,7 @@ snapshots: neo-async@2.6.2: {} - node-releases@2.0.26: {} + node-releases@2.0.27: {} nodemon@3.1.10: dependencies: @@ -6826,17 +6848,17 @@ snapshots: optionalDependencies: vue-tsc: 2.2.12(typescript@5.9.3) - prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.41.1): + prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.43.3): dependencies: prettier: 3.6.2 - svelte: 5.41.1 + svelte: 5.43.3 - prettier-plugin-tailwindcss@0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)))(prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.41.1))(prettier@3.6.2): + prettier-plugin-tailwindcss@0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)))(prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.43.3))(prettier@3.6.2): dependencies: prettier: 3.6.2 optionalDependencies: prettier-plugin-organize-imports: 4.3.0(prettier@3.6.2)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3)) - prettier-plugin-svelte: 3.4.0(prettier@3.6.2)(svelte@5.41.1) + prettier-plugin-svelte: 3.4.0(prettier@3.6.2)(svelte@5.43.3) prettier@3.6.2: {} @@ -7064,7 +7086,7 @@ snapshots: transitivePeerDependencies: - supports-color - set-cookie-parser@2.7.1: {} + set-cookie-parser@2.7.2: {} set-function-length@1.2.2: dependencies: @@ -7250,14 +7272,14 @@ snapshots: transitivePeerDependencies: - picomatch - svelte-check@4.3.3(picomatch@4.0.3)(svelte@5.41.1)(typescript@5.9.3): + svelte-check@4.3.3(picomatch@4.0.3)(svelte@5.43.3)(typescript@5.9.3): dependencies: '@jridgewell/trace-mapping': 0.3.31 chokidar: 4.0.3 fdir: 6.5.0(picomatch@4.0.3) picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.41.1 + svelte: 5.43.3 typescript: 5.9.3 transitivePeerDependencies: - picomatch @@ -7298,10 +7320,10 @@ snapshots: estree-walker: 3.0.3 is-reference: 3.0.3 locate-character: 3.0.0 - magic-string: 0.30.19 + magic-string: 0.30.21 periscopic: 3.1.0 - svelte@5.41.1: + svelte@5.43.3: dependencies: '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 @@ -7312,10 +7334,10 @@ snapshots: axobject-query: 4.1.0 clsx: 2.1.1 esm-env: 1.2.2 - esrap: 2.1.0 + esrap: 2.1.2 is-reference: 3.0.3 locate-character: 3.0.0 - magic-string: 0.30.19 + magic-string: 0.30.21 zimmerframe: 1.1.4 table@6.9.0: @@ -7326,7 +7348,7 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - tailwindcss@4.1.15: {} + tailwindcss@4.1.16: {} tapable@2.3.0: {} @@ -7424,13 +7446,13 @@ snapshots: typedarray@0.0.6: {} - typescript-eslint@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3): + typescript-eslint@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.38.0(jiti@2.6.1) + '@typescript-eslint/eslint-plugin': 8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.1(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -7456,9 +7478,9 @@ snapshots: unpipe@1.0.0: {} - update-browserslist-db@1.1.3(browserslist@4.26.3): + update-browserslist-db@1.1.4(browserslist@4.27.0): dependencies: - browserslist: 4.26.3 + browserslist: 4.27.0 escalade: 3.2.0 picocolors: 1.1.1 @@ -7479,46 +7501,46 @@ snapshots: picocolors: 1.1.1 picomatch: 2.3.1 - vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0): + vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0): dependencies: esbuild: 0.21.5 postcss: 8.5.6 rollup: 4.52.5 optionalDependencies: - '@types/node': 24.9.1 + '@types/node': 24.10.0 fsevents: 2.3.3 lightningcss: 1.30.2 terser: 5.44.0 - vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0): + vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0): dependencies: - esbuild: 0.25.11 + esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 rollup: 4.52.5 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.9.1 + '@types/node': 24.10.0 fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 terser: 5.44.0 - vitefu@0.2.5(vite@5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0)): + vitefu@0.2.5(vite@5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0)): optionalDependencies: - vite: 5.4.21(@types/node@24.9.1)(lightningcss@1.30.2)(terser@5.44.0) + vite: 5.4.21(@types/node@24.10.0)(lightningcss@1.30.2)(terser@5.44.0) - vitefu@1.1.1(vite@6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)): + vitefu@1.1.1(vite@6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)): optionalDependencies: - vite: 6.4.1(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + vite: 6.4.1(@types/node@24.10.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) vscode-uri@3.1.0: {} - vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@2.6.1)): + vue-eslint-parser@10.2.0(eslint@9.39.1(jiti@2.6.1)): dependencies: debug: 4.4.3(supports-color@5.5.0) - eslint: 9.38.0(jiti@2.6.1) + eslint: 9.39.1(jiti@2.6.1) eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -7560,7 +7582,7 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.26.3 + browserslist: 4.27.0 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.3 es-module-lexer: 1.7.0 diff --git a/tests/app/server.js b/tests/app/server.js index f9238a104..d011d8006 100644 --- a/tests/app/server.js +++ b/tests/app/server.js @@ -282,6 +282,158 @@ app.post('/form-helper/events/errors', (req, res) => { }, 250) }) +app.post('/precognition/default', (req, res) => { + setTimeout( + () => { + const only = req.headers['precognition-validate-only'] ? req.headers['precognition-validate-only'].split(',') : [] + const name = req.body['name'] + const email = req.body['email'] + const errors = {} + + if (!name) { + errors.name = 'The name field is required.' + } + + if (name && name.length < 3) { + errors.name = 'The name must be at least 3 characters.' + } + + if (!email) { + errors.email = 'The email field is required.' + } + + if (email && !/\S+@\S+\.\S+/.test(email)) { + errors.email = 'The email must be a valid email address.' + } + + if (only.length) { + Object.keys(errors).forEach((key) => { + if (!only.includes(key)) { + delete errors[key] + } + }) + } + + res.header('Precognition', 'true') + res.header('Vary', 'Precognition') + + if (Object.keys(errors).length) { + return res.status(422).json({ errors }) + } + + return res.status(204).header('Precognition-Success', 'true').send() + }, + !!req.query['slow'] ? 2000 : 250, + ) +}) + +app.post('/precognition/array-errors', (req, res) => { + setTimeout(() => { + const only = req.headers['precognition-validate-only'] ? req.headers['precognition-validate-only'].split(',') : [] + const name = req.body['name'] + const email = req.body['email'] + const errors = {} + + if (!name) { + errors.name = ['The name field is required.'] + } + + if (name && name.length < 3) { + errors.name = ['The name must be at least 3 characters.', 'The name contains invalid characters.'] + } + + if (!email) { + errors.email = ['The email field is required.'] + } + + if (email && !/\S+@\S+\.\S+/.test(email)) { + errors.email = ['The email must be a valid email address.', 'The email format is incorrect.'] + } + + if (only.length) { + Object.keys(errors).forEach((key) => { + if (!only.includes(key)) { + delete errors[key] + } + }) + } + + res.header('Precognition', 'true') + res.header('Vary', 'Precognition') + + if (Object.keys(errors).length) { + return res.status(422).json({ errors }) + } + + return res.status(204).header('Precognition-Success', 'true').send() + }, 250) +}) + +app.post('/precognition/files', upload.any(), (req, res) => { + setTimeout(() => { + console.log(req, req) + const only = req.headers['precognition-validate-only'] ? req.headers['precognition-validate-only'].split(',') : [] + const name = req.body['name'] + const hasAvatar = req.files && req.files.avatar + const errors = {} + + if (!name) { + errors.name = 'The name field is required.' + } + + if (name && name.length < 3) { + errors.name = 'The name must be at least 3 characters.' + } + + if (!hasAvatar) { + errors.avatar = 'The avatar field is required.' + } + + if (only.length) { + Object.keys(errors).forEach((key) => { + if (!only.includes(key)) { + delete errors[key] + } + }) + } + + res.header('Precognition', 'true') + res.header('Vary', 'Precognition') + + if (Object.keys(errors).length) { + return res.status(422).json({ errors }) + } + + return res.status(204).header('Precognition-Success', 'true').send() + }, 250) +}) + +app.post('/precognition/headers', (req, res) => { + setTimeout(() => { + const customHeader = req.headers['x-custom-header'] + const name = req.body['name'] + const errors = {} + + // Show error when custom header IS present (to prove it was sent) + if (customHeader === 'custom-value') { + errors.name = 'Custom header received: custom-value' + } else if (!name) { + errors.name = 'The name field is required.' + } else if (name.length < 3) { + errors.name = 'The name must be at least 3 characters.' + } + + res.header('Precognition', 'true') + res.header('Vary', 'Precognition') + + if (Object.keys(errors).length) { + return res.status(422).json({ errors }) + } + + return res.status(204).header('Precognition-Success', 'true').send() + }, 250) +}) + const methods = ['get', 'post', 'put', 'patch', 'delete'] methods.forEach((method) => diff --git a/tests/precognition.spec.ts b/tests/precognition.spec.ts new file mode 100644 index 000000000..9331e6c37 --- /dev/null +++ b/tests/precognition.spec.ts @@ -0,0 +1,538 @@ +import test, { expect } from '@playwright/test' +import { requests } from './support' + +const integrations = ['form-helper'] + +integrations.forEach((integration) => { + test.skip(process.env.PACKAGE !== 'vue', '[WIP] Only for Vue') + + test.describe(integration === 'form-helper' ? 'Form Helper' : 'Form Component', () => { + test.describe('Precognition', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/' + integration + '/precognition/default') + }) + + test('does not validate when field is untouched', async ({ page }) => { + await page.locator('input[name="name"]').focus() + await page.waitForTimeout(100) + await page.locator('input[name="name"]').blur() + + for (let i = 0; i < 5; i++) { + await expect(page.getByText('Validating...')).not.toBeVisible() + await page.waitForTimeout(50) + } + + await expect(page.getByText('The name field is required.')).not.toBeVisible() + }) + + test('shows validation error when field is invalid', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + }) + + test('clears validation error when field becomes valid', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + + await page.fill('input[name="name"]', 'John Doe') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() + }) + + test('validates only the specified field', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email field is required.')).not.toBeVisible() + }) + + test('validates multiple fields independently', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + }) + + test('does not clear unrelated field errors', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + + await page.fill('input[name="email"]', 'test@example.com') + await page.locator('input[name="email"]').blur() + + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + }) + + test('field is valid when validated and no errors exist', async ({ page }) => { + await expect(page.getByText('Name is valid!')).not.toBeVisible() + + await page.fill('input[name="name"]', 'John Doe') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('Name is valid!')).toBeVisible() + }) + + test('field is not valid before validation', async ({ page }) => { + await expect(page.getByText('Name is valid!')).not.toBeVisible() + + await page.fill('input[name="name"]', 'John Doe') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('Name is valid!')).toBeVisible() + await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() + }) + + test('field is not valid after failed validation', async ({ page }) => { + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('Name is valid!')).not.toBeVisible() + }) + + test('valid field persists after successful validation', async ({ page }) => { + await page.fill('input[name="name"]', 'John Doe') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('Name is valid!')).toBeVisible() + + await page.fill('input[name="name"]', 'Jane Doe') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('Name is valid!')).toBeVisible() + }) + + test('valid field becomes invalid when field is revalidated with errors', async ({ page }) => { + await page.fill('input[name="name"]', 'John Doe') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('Name is valid!')).toBeVisible() + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('Name is valid!')).not.toBeVisible() + }) + + test('shows only first error when server returns errors as array', async ({ page }) => { + await page.goto('/' + integration + '/precognition/array-errors') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + // Should show only the first error from the array, not the second + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The name contains invalid characters.')).not.toBeVisible() + }) + + test('shows all errors when simpleValidationErrors is false', async ({ page }) => { + await page.goto('/' + integration + '/precognition/all-errors') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + // Should show all errors from the array + await expect(page.locator('#name-error-0')).toHaveText('The name must be at least 3 characters.') + await expect(page.locator('#name-error-1')).toHaveText('The name contains invalid characters.') + }) + + test('validates all touched fields when calling validate() without arguments', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await expect(page.getByText('Validating...')).not.toBeVisible() + await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + }) + + test('reset all fields clears all touched fields', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await page.getByRole('button', { name: 'Reset All' }).click() + + await expect(page.locator('input[name="name"]')).toHaveValue('') + await expect(page.locator('input[name="email"]')).toHaveValue('') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email field is required.')).not.toBeVisible() + }) + + test('reset specific fields removes only those fields from touched', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await expect(page.locator('input[name="name"]')).toHaveValue('ab') + await expect(page.locator('input[name="email"]')).toHaveValue('x') + + await page.getByRole('button', { name: 'Reset Name', exact: true }).click() + + await expect(page.locator('input[name="name"]')).toHaveValue('') + await expect(page.locator('input[name="email"]')).toHaveValue('x') + + await page.fill('input[name="email"]', 'y') + + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name field is required.')).not.toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + }) + + test('touch with array marks multiple fields as touched', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.getByRole('button', { name: 'Touch Name and Email' }).click() + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name field is required.')).toBeVisible() + await expect(page.getByText('The email field is required.')).toBeVisible() + }) + + test('touch deduplicates fields when called multiple times', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.fill('input[name="name"]', 'ab') + + await page.getByRole('button', { name: 'Touch Name Twice' }).click() + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + }) + + test('touched() returns false when no fields are touched', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await expect(page.locator('#any-touched')).toHaveText('Form has no touched fields') + await expect(page.locator('#name-touched')).toHaveText('Name is not touched') + await expect(page.locator('#email-touched')).toHaveText('Email is not touched') + }) + + test('touched(field) returns true when specific field is touched', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.locator('input[name="name"]').focus() + await page.locator('input[name="name"]').blur() + + await expect(page.locator('#name-touched')).toHaveText('Name is touched') + await expect(page.locator('#email-touched')).toHaveText('Email is not touched') + await expect(page.locator('#any-touched')).toHaveText('Form has touched fields') + }) + + test('touched() returns true when any field is touched', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.locator('input[name="email"]').focus() + await page.locator('input[name="email"]').blur() + + await expect(page.locator('#any-touched')).toHaveText('Form has touched fields') + await expect(page.locator('#email-touched')).toHaveText('Email is touched') + await expect(page.locator('#name-touched')).toHaveText('Name is not touched') + }) + + test('touched() updates when multiple fields are touched', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.locator('input[name="name"]').focus() + await page.locator('input[name="name"]').blur() + await page.locator('input[name="email"]').focus() + await page.locator('input[name="email"]').blur() + + await expect(page.locator('#name-touched')).toHaveText('Name is touched') + await expect(page.locator('#email-touched')).toHaveText('Email is touched') + await expect(page.locator('#any-touched')).toHaveText('Form has touched fields') + }) + + test('validating a specific field also validates previously touched inputs', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.fill('input[name="name"]', 'ab') + await page.fill('input[name="email"]', 'x') + + await page.getByRole('button', { name: 'Validate Name', exact: true }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + }) + + test('validate with array of fields validates multiple fields', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.getByRole('button', { name: 'Validate Name and Email' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name field is required.')).toBeVisible() + await expect(page.getByText('The email field is required.')).toBeVisible() + }) + + test('reset with array removes multiple fields from touched', async ({ page }) => { + await page.goto('/' + integration + '/precognition/methods') + + await page.fill('input[name="name"]', 'ab') + await page.locator('input[name="name"]').blur() + + await page.fill('input[name="email"]', 'x') + await page.locator('input[name="email"]').blur() + + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).toBeVisible() + + await page.getByRole('button', { name: 'Reset Name and Email' }).click() + + await expect(page.locator('input[name="name"]')).toHaveValue('') + await expect(page.locator('input[name="email"]')).toHaveValue('') + + await expect(page.getByText('Name is not touched')).toBeVisible() + await expect(page.getByText('Email is not touched')).toBeVisible() + await expect(page.getByText('Form has no touched fields')).toBeVisible() + + await page.fill('input[name="name"]', 'abc') + await page.fill('input[name="email"]', 'test@example.com') + + await page.getByRole('button', { name: 'Validate All Touched' }).click() + + await page.waitForTimeout(500) + + await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() + await expect(page.getByText('The email must be a valid email address.')).not.toBeVisible() + }) + + test('does not submit files by default', async ({ page }) => { + await page.goto('/' + integration + '/precognition/files') + + await page.setInputFiles('#avatar', { + name: 'avatar.jpg', + mimeType: 'image/jpeg', + buffer: Buffer.from('fake image data'), + }) + + await page.getByRole('button', { name: 'Validate Both' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name field is required.')).toBeVisible() + await expect(page.getByText('The avatar field is required.')).toBeVisible() + }) + + test('validates files when validate-files prop is true', async ({ page }) => { + await page.goto('/' + integration + '/precognition/files') + await page.getByRole('button', { name: /Toggle Validate Files/ }).click() + await expect(page.getByText('Toggle Validate Files (enabled)')).toBeVisible() + + await page.fill('input[name="name"]', 'ab') + await page.setInputFiles('#avatar', { + name: 'avatar.jpg', + mimeType: 'image/jpeg', + buffer: Buffer.from('fake image data'), + }) + + await page.getByRole('button', { name: 'Validate Both' }).click() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + await expect(page.getByText('The avatar field is required.')).not.toBeVisible() + }) + + test('transforms data for validation requests', async ({ page }) => { + await page.goto('/' + integration + '/precognition/transform') + + await page.fill('input[name="name"]', 'a') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + + await page.fill('input[name="name"]', 'aa') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('The name must be at least 3 characters.')).not.toBeVisible() + await expect(page.getByText('Name is valid!')).toBeVisible() + }) + + test('calls onPrecognitionSuccess and onFinish callbacks when validation succeeds', async ({ page }) => { + await page.goto('/' + integration + '/precognition/callbacks') + + await page.fill('input[name="name"]', 'John Doe') + await page.click('button:has-text("Validate")') + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('onPrecognitionSuccess called!')).toBeVisible() + await expect(page.getByText('onValidationError called!')).not.toBeVisible() + await expect(page.getByText('onFinish called!')).toBeVisible() + }) + + test('calls onValidationError and onFinish callbacks when validation fails', async ({ page }) => { + await page.goto('/' + integration + '/precognition/callbacks') + + await page.fill('input[name="name"]', 'ab') + await page.click('button:has-text("Validate")') + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + await expect(page.getByText('onPrecognitionSuccess called!')).not.toBeVisible() + await expect(page.getByText('onValidationError called!')).toBeVisible() + await expect(page.getByText('onFinish called!')).toBeVisible() + }) + + test('onBefore can block validation', async ({ page }) => { + await page.goto('/' + integration + '/precognition/before-validation') + + await page.fill('input[name="name"]', 'block') + await page.locator('input[name="name"]').blur() + + for (let i = 0; i < 5; i++) { + await expect(page.getByText('Validating...')).not.toBeVisible() + await page.waitForTimeout(50) + } + }) + + test('sends custom headers with validation requests', async ({ page }) => { + await page.goto('/' + integration + '/precognition/headers') + + // Fill in a valid name to trigger validation + await page.fill('input[name="name"]', 'John Doe') + await page.locator('input[name="name"]').blur() + + await expect(page.getByText('Validating...')).toBeVisible() + await expect(page.getByText('Validating...')).not.toBeVisible() + + // Should show error confirming custom header was received + await expect(page.getByText('Custom header received: custom-value')).toBeVisible() + }) + + test('automatically cancels previous validation when new validation starts', async ({ page }) => { + await page.goto('/' + integration + '/precognition/cancel') + + requests.listenForFailed(page) + requests.listenForResponses(page) + + await page.fill('#auto-cancel-name-input', 'ab') + await page.locator('#auto-cancel-name-input').blur() + await expect(page.getByText('Validating...')).toBeVisible() + + // Immediately change value and trigger new validation - should cancel the first one + await page.fill('#auto-cancel-name-input', 'xy') + await page.locator('#auto-cancel-name-input').blur() + await expect(page.getByText('Validating...')).not.toBeVisible() + await expect(page.getByText('The name must be at least 3 characters.')).toBeVisible() + + // One cancelled, one 422 response + expect(requests.failed).toHaveLength(1) + expect(requests.responses).toHaveLength(1) + + const cancelledRequestError = await requests.failed[0].failure()?.errorText + expect(cancelledRequestError).toBe('net::ERR_ABORTED') + }) + }) + }) +}) diff --git a/tests/support.ts b/tests/support.ts index bae7d4abb..baba83c2b 100644 --- a/tests/support.ts +++ b/tests/support.ts @@ -43,6 +43,8 @@ export const consoleMessages = { export const requests = { requests: [] as Request[], finished: [] as Request[], + failed: [] as Request[], + responses: [] as Response[], listen(page: Page) { this.requests = [] @@ -53,6 +55,16 @@ export const requests = { this.finished = [] page.on('requestfinished', (request) => this.finished.push(request)) }, + + listenForFailed(page: Page) { + this.failed = [] + page.on('requestfailed', (request) => this.failed.push(request)) + }, + + listenForResponses(page: Page) { + this.responses = [] + page.on('response', (data) => this.responses.push(data)) + }, } export const shouldBeDumpPage = async (page: Page, method: 'get' | 'post' | 'patch' | 'put' | 'delete') => { From 350b6e4f28f3c0c49547fa28402455e835489d4a Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 4 Nov 2025 14:32:36 +0100 Subject: [PATCH 077/145] Update Files.vue --- .../test-app/Pages/FormHelper/Precognition/Files.vue | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue index 9883699cd..761315d32 100644 --- a/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue @@ -2,7 +2,10 @@ import { useForm } from '@inertiajs/vue3' import { ref, watch } from 'vue' -const form = useForm({ +const form = useForm<{ + name: string + avatar: File | null +}>({ name: '', avatar: null, }) @@ -28,7 +31,12 @@ watch(validateFiles, (enabled) => {
- +

{{ form.errors.avatar }}

From 065ff960e6ffdc714e54e5efb56b80826d0c8e2a Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 4 Nov 2025 14:38:21 +0100 Subject: [PATCH 078/145] Update Files.vue --- .../vue3/test-app/Pages/FormHelper/Precognition/Files.vue | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue b/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue index 761315d32..c4566ed16 100644 --- a/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue +++ b/packages/vue3/test-app/Pages/FormHelper/Precognition/Files.vue @@ -14,10 +14,7 @@ const form = useForm<{ const validateFiles = ref(false) -watch(validateFiles, (enabled) => { - enabled ? form.validateFiles() : form.withoutFileValidation() - console.log(`File validation ${enabled ? 'enabled' : 'disabled'}`) -}) +watch(validateFiles, (enabled) => (enabled ? form.validateFiles() : form.withoutFileValidation()))