1651 lines
50 KiB
JavaScript
1651 lines
50 KiB
JavaScript
// src/index.ts
|
|
import { config as coreConfig, progress as Progress2, router as Router } from "@inertiajs/core";
|
|
|
|
// src/App.ts
|
|
import {
|
|
createHeadManager,
|
|
router
|
|
} from "@inertiajs/core";
|
|
import { createElement, useEffect, useMemo, useState } from "react";
|
|
import { flushSync } from "react-dom";
|
|
|
|
// src/HeadContext.ts
|
|
import { createContext } from "react";
|
|
var headContext = createContext(null);
|
|
headContext.displayName = "InertiaHeadContext";
|
|
var HeadContext_default = headContext;
|
|
|
|
// src/PageContext.ts
|
|
import { createContext as createContext2 } from "react";
|
|
var pageContext = createContext2(null);
|
|
pageContext.displayName = "InertiaPageContext";
|
|
var PageContext_default = pageContext;
|
|
|
|
// src/App.ts
|
|
var currentIsInitialPage = true;
|
|
var routerIsInitialized = false;
|
|
var swapComponent = async () => {
|
|
currentIsInitialPage = false;
|
|
};
|
|
function App({
|
|
children,
|
|
initialPage,
|
|
initialComponent,
|
|
resolveComponent,
|
|
titleCallback,
|
|
onHeadUpdate
|
|
}) {
|
|
const [current, setCurrent] = useState({
|
|
component: initialComponent || null,
|
|
page: { ...initialPage, flash: initialPage.flash ?? {} },
|
|
key: null
|
|
});
|
|
const headManager = useMemo(() => {
|
|
return createHeadManager(
|
|
typeof window === "undefined",
|
|
titleCallback || ((title) => title),
|
|
onHeadUpdate || (() => {
|
|
})
|
|
);
|
|
}, []);
|
|
if (!routerIsInitialized) {
|
|
router.init({
|
|
initialPage,
|
|
resolveComponent,
|
|
swapComponent: async (args) => swapComponent(args),
|
|
onFlash: (flash) => {
|
|
setCurrent((current2) => ({
|
|
...current2,
|
|
page: { ...current2.page, flash }
|
|
}));
|
|
}
|
|
});
|
|
routerIsInitialized = true;
|
|
}
|
|
useEffect(() => {
|
|
swapComponent = async ({ component, page, preserveState }) => {
|
|
if (currentIsInitialPage) {
|
|
currentIsInitialPage = false;
|
|
return;
|
|
}
|
|
flushSync(
|
|
() => setCurrent((current2) => ({
|
|
component,
|
|
page,
|
|
key: preserveState ? current2.key : Date.now()
|
|
}))
|
|
);
|
|
};
|
|
router.on("navigate", () => headManager.forceUpdate());
|
|
}, []);
|
|
if (!current.component) {
|
|
return createElement(
|
|
HeadContext_default.Provider,
|
|
{ value: headManager },
|
|
createElement(PageContext_default.Provider, { value: current.page }, null)
|
|
);
|
|
}
|
|
const renderChildren = children || (({ Component, props, key }) => {
|
|
const child = createElement(Component, { key, ...props });
|
|
if (typeof Component.layout === "function") {
|
|
return Component.layout(child);
|
|
}
|
|
if (Array.isArray(Component.layout)) {
|
|
return Component.layout.concat(child).reverse().reduce((children2, Layout) => createElement(Layout, { children: children2, ...props }));
|
|
}
|
|
return child;
|
|
});
|
|
return createElement(
|
|
HeadContext_default.Provider,
|
|
{ value: headManager },
|
|
createElement(
|
|
PageContext_default.Provider,
|
|
{ value: current.page },
|
|
renderChildren({
|
|
Component: current.component,
|
|
key: current.key,
|
|
props: current.page.props
|
|
})
|
|
)
|
|
);
|
|
}
|
|
App.displayName = "Inertia";
|
|
|
|
// src/createInertiaApp.ts
|
|
import {
|
|
getInitialPageFromDOM,
|
|
router as router2,
|
|
setupProgress
|
|
} from "@inertiajs/core";
|
|
import { createElement as createElement2, Fragment } from "react";
|
|
async function createInertiaApp({
|
|
id = "app",
|
|
resolve,
|
|
setup,
|
|
title,
|
|
progress: progress2 = {},
|
|
page,
|
|
render,
|
|
defaults = {}
|
|
}) {
|
|
config.replace(defaults);
|
|
const isServer = typeof window === "undefined";
|
|
const useScriptElementForInitialPage = config.get("future.useScriptElementForInitialPage");
|
|
const initialPage = page || getInitialPageFromDOM(id, useScriptElementForInitialPage);
|
|
const resolveComponent = (name) => Promise.resolve(resolve(name)).then((module) => module.default || module);
|
|
let head = [];
|
|
const reactApp = await Promise.all([
|
|
resolveComponent(initialPage.component),
|
|
router2.decryptHistory().catch(() => {
|
|
})
|
|
]).then(([initialComponent]) => {
|
|
const props = {
|
|
initialPage,
|
|
initialComponent,
|
|
resolveComponent,
|
|
titleCallback: title
|
|
};
|
|
if (isServer) {
|
|
const ssrSetup = setup;
|
|
return ssrSetup({
|
|
el: null,
|
|
App,
|
|
props: { ...props, onHeadUpdate: (elements) => head = elements }
|
|
});
|
|
}
|
|
const csrSetup = setup;
|
|
return csrSetup({
|
|
el: document.getElementById(id),
|
|
App,
|
|
props
|
|
});
|
|
});
|
|
if (!isServer && progress2) {
|
|
setupProgress(progress2);
|
|
}
|
|
if (isServer && render) {
|
|
const element = () => {
|
|
if (!useScriptElementForInitialPage) {
|
|
return createElement2(
|
|
"div",
|
|
{
|
|
id,
|
|
"data-page": JSON.stringify(initialPage)
|
|
},
|
|
reactApp
|
|
);
|
|
}
|
|
return createElement2(
|
|
Fragment,
|
|
null,
|
|
createElement2("script", {
|
|
"data-page": id,
|
|
type: "application/json",
|
|
dangerouslySetInnerHTML: { __html: JSON.stringify(initialPage).replace(/\//g, "\\/") }
|
|
}),
|
|
createElement2("div", { id }, reactApp)
|
|
);
|
|
};
|
|
const body = await render(element());
|
|
return { head, body };
|
|
}
|
|
}
|
|
|
|
// src/Deferred.ts
|
|
import { useEffect as useEffect3, useMemo as useMemo2, useState as useState2 } from "react";
|
|
|
|
// src/usePage.ts
|
|
import React2 from "react";
|
|
|
|
// src/react.ts
|
|
import React, { useEffect as useEffect2, useLayoutEffect } from "react";
|
|
function useIsomorphicLayoutEffect(effect, deps) {
|
|
typeof window === "undefined" ? useEffect2(effect, deps) : useLayoutEffect(effect, deps);
|
|
}
|
|
var isReact19 = typeof React.use === "function";
|
|
|
|
// src/usePage.ts
|
|
function usePage() {
|
|
const page = isReact19 ? React2.use(PageContext_default) : React2.useContext(PageContext_default);
|
|
if (!page) {
|
|
throw new Error("usePage must be used within the Inertia component");
|
|
}
|
|
return page;
|
|
}
|
|
|
|
// src/Deferred.ts
|
|
var urlWithoutHash = (url) => {
|
|
url = new URL(url.href);
|
|
url.hash = "";
|
|
return url;
|
|
};
|
|
var isSameUrlWithoutHash = (url1, url2) => {
|
|
return urlWithoutHash(url1).href === urlWithoutHash(url2).href;
|
|
};
|
|
var Deferred = ({ children, data, fallback }) => {
|
|
if (!data) {
|
|
throw new Error("`<Deferred>` requires a `data` prop to be a string or array of strings");
|
|
}
|
|
const [loaded, setLoaded] = useState2(false);
|
|
const pageProps = usePage().props;
|
|
const keys = useMemo2(() => Array.isArray(data) ? data : [data], [data]);
|
|
useEffect3(() => {
|
|
const removeListener = router3.on("start", (e) => {
|
|
const isPartialVisit = e.detail.visit.only.length > 0 || e.detail.visit.except.length > 0;
|
|
const isReloadingKey = e.detail.visit.only.find((key) => keys.includes(key));
|
|
if (isSameUrlWithoutHash(e.detail.visit.url, window.location) && (!isPartialVisit || isReloadingKey)) {
|
|
setLoaded(false);
|
|
}
|
|
});
|
|
return () => {
|
|
removeListener();
|
|
};
|
|
}, []);
|
|
useEffect3(() => {
|
|
setLoaded(keys.every((key) => pageProps[key] !== void 0));
|
|
}, [pageProps, keys]);
|
|
const propsAreDefined = useMemo2(() => keys.every((key) => pageProps[key] !== void 0), [keys, pageProps]);
|
|
if (loaded && propsAreDefined) {
|
|
return typeof children === "function" ? children() : children;
|
|
}
|
|
return typeof fallback === "function" ? fallback() : fallback;
|
|
};
|
|
Deferred.displayName = "InertiaDeferred";
|
|
var Deferred_default = Deferred;
|
|
|
|
// src/Form.ts
|
|
import {
|
|
FormComponentResetSymbol,
|
|
formDataToObject,
|
|
isUrlMethodPair,
|
|
mergeDataIntoQueryString,
|
|
resetFormFields,
|
|
UseFormUtils as UseFormUtils2
|
|
} from "@inertiajs/core";
|
|
import { isEqual as isEqual2 } from "lodash-es";
|
|
import React3, {
|
|
createContext as createContext3,
|
|
createElement as createElement3,
|
|
forwardRef,
|
|
useContext,
|
|
useEffect as useEffect6,
|
|
useImperativeHandle,
|
|
useMemo as useMemo4,
|
|
useRef as useRef2,
|
|
useState as useState5
|
|
} from "react";
|
|
|
|
// src/useForm.ts
|
|
import {
|
|
router as router5,
|
|
UseFormUtils
|
|
} from "@inertiajs/core";
|
|
import {
|
|
createValidator,
|
|
resolveName,
|
|
toSimpleValidationErrors
|
|
} from "laravel-precognition";
|
|
import { cloneDeep, get, has, isEqual, set } from "lodash-es";
|
|
import { useCallback, useEffect as useEffect5, useMemo as useMemo3, useRef, useState as useState4 } from "react";
|
|
|
|
// src/useRemember.ts
|
|
import { router as router4 } from "@inertiajs/core";
|
|
import { useEffect as useEffect4, useState as useState3 } from "react";
|
|
function useRemember(initialState, key, excludeKeysRef) {
|
|
const [state, setState] = useState3(() => {
|
|
const restored = router4.restore(key);
|
|
return restored !== void 0 ? restored : initialState;
|
|
});
|
|
useEffect4(() => {
|
|
const keys = excludeKeysRef?.current;
|
|
if (keys && keys.length > 0 && typeof state === "object" && state !== null) {
|
|
const filtered = { ...state };
|
|
keys.forEach((k) => delete filtered[k]);
|
|
router4.remember(filtered, key);
|
|
} else {
|
|
router4.remember(state, key);
|
|
}
|
|
}, [state, key]);
|
|
return [state, setState];
|
|
}
|
|
|
|
// src/useForm.ts
|
|
function useForm(...args) {
|
|
const isMounted = useRef(false);
|
|
const parsedArgs = UseFormUtils.parseUseFormArguments(...args);
|
|
const { rememberKey, data: initialData } = parsedArgs;
|
|
const precognitionEndpoint = useRef(parsedArgs.precognitionEndpoint);
|
|
const [defaults, setDefaults] = useState4(
|
|
typeof initialData === "function" ? cloneDeep(initialData()) : cloneDeep(initialData)
|
|
);
|
|
const cancelToken = useRef(null);
|
|
const recentlySuccessfulTimeoutId = useRef(void 0);
|
|
const excludeKeysRef = useRef([]);
|
|
const [data, setData] = rememberKey ? useRemember(defaults, `${rememberKey}:data`, excludeKeysRef) : useState4(defaults);
|
|
const [errors, setErrors] = rememberKey ? useRemember({}, `${rememberKey}:errors`) : useState4({});
|
|
const [hasErrors, setHasErrors] = useState4(false);
|
|
const [processing, setProcessing] = useState4(false);
|
|
const [progress2, setProgress] = useState4(null);
|
|
const [wasSuccessful, setWasSuccessful] = useState4(false);
|
|
const [recentlySuccessful, setRecentlySuccessful] = useState4(false);
|
|
const transform = useRef((data2) => data2);
|
|
const isDirty = useMemo3(() => !isEqual(data, defaults), [data, defaults]);
|
|
const validatorRef = useRef(null);
|
|
const [validating, setValidating] = useState4(false);
|
|
const [touchedFields, setTouchedFields] = useState4([]);
|
|
const [validFields, setValidFields] = useState4([]);
|
|
const withAllErrors = useRef(false);
|
|
useEffect5(() => {
|
|
isMounted.current = true;
|
|
return () => {
|
|
isMounted.current = false;
|
|
};
|
|
}, []);
|
|
const setDefaultsCalledInOnSuccess = useRef(false);
|
|
const submit = useCallback(
|
|
(...args2) => {
|
|
const { method, url, options } = UseFormUtils.parseSubmitArguments(args2, precognitionEndpoint.current);
|
|
setDefaultsCalledInOnSuccess.current = false;
|
|
const _options = {
|
|
...options,
|
|
onCancelToken: (token) => {
|
|
cancelToken.current = token;
|
|
if (options.onCancelToken) {
|
|
return options.onCancelToken(token);
|
|
}
|
|
},
|
|
onBefore: (visit) => {
|
|
setWasSuccessful(false);
|
|
setRecentlySuccessful(false);
|
|
clearTimeout(recentlySuccessfulTimeoutId.current);
|
|
if (options.onBefore) {
|
|
return options.onBefore(visit);
|
|
}
|
|
},
|
|
onStart: (visit) => {
|
|
setProcessing(true);
|
|
if (options.onStart) {
|
|
return options.onStart(visit);
|
|
}
|
|
},
|
|
onProgress: (event) => {
|
|
setProgress(event || null);
|
|
if (options.onProgress) {
|
|
return options.onProgress(event);
|
|
}
|
|
},
|
|
onSuccess: async (page) => {
|
|
if (isMounted.current) {
|
|
setProcessing(false);
|
|
setProgress(null);
|
|
setErrors({});
|
|
setHasErrors(false);
|
|
setWasSuccessful(true);
|
|
setRecentlySuccessful(true);
|
|
recentlySuccessfulTimeoutId.current = setTimeout(() => {
|
|
if (isMounted.current) {
|
|
setRecentlySuccessful(false);
|
|
}
|
|
}, config.get("form.recentlySuccessfulDuration"));
|
|
}
|
|
const onSuccess = options.onSuccess ? await options.onSuccess(page) : null;
|
|
if (isMounted.current && !setDefaultsCalledInOnSuccess.current) {
|
|
setData((data2) => {
|
|
setDefaults(cloneDeep(data2));
|
|
return data2;
|
|
});
|
|
}
|
|
return onSuccess;
|
|
},
|
|
onError: (errors2) => {
|
|
if (isMounted.current) {
|
|
setProcessing(false);
|
|
setProgress(null);
|
|
setErrors(errors2);
|
|
setHasErrors(Object.keys(errors2).length > 0);
|
|
validatorRef.current?.setErrors(errors2);
|
|
}
|
|
if (options.onError) {
|
|
return options.onError(errors2);
|
|
}
|
|
},
|
|
onCancel: () => {
|
|
if (isMounted.current) {
|
|
setProcessing(false);
|
|
setProgress(null);
|
|
}
|
|
if (options.onCancel) {
|
|
return options.onCancel();
|
|
}
|
|
},
|
|
onFinish: (visit) => {
|
|
if (isMounted.current) {
|
|
setProcessing(false);
|
|
setProgress(null);
|
|
}
|
|
cancelToken.current = null;
|
|
if (options.onFinish) {
|
|
return options.onFinish(visit);
|
|
}
|
|
}
|
|
};
|
|
const transformedData = transform.current(data);
|
|
if (method === "delete") {
|
|
router5.delete(url, { ..._options, data: transformedData });
|
|
} else {
|
|
router5[method](url, transformedData, _options);
|
|
}
|
|
},
|
|
[data, setErrors, transform]
|
|
);
|
|
const setDataFunction = useCallback(
|
|
(keyOrData, maybeValue) => {
|
|
if (typeof keyOrData === "string") {
|
|
setData((data2) => set(cloneDeep(data2), keyOrData, maybeValue));
|
|
} else if (typeof keyOrData === "function") {
|
|
setData((data2) => keyOrData(data2));
|
|
} else {
|
|
setData(keyOrData);
|
|
}
|
|
},
|
|
[setData]
|
|
);
|
|
const [dataAsDefaults, setDataAsDefaults] = useState4(false);
|
|
const dataRef = useRef(data);
|
|
useEffect5(() => {
|
|
dataRef.current = data;
|
|
});
|
|
const setDefaultsFunction = useCallback(
|
|
(fieldOrFields, maybeValue) => {
|
|
setDefaultsCalledInOnSuccess.current = true;
|
|
let newDefaults = {};
|
|
if (typeof fieldOrFields === "undefined") {
|
|
newDefaults = { ...dataRef.current };
|
|
setDefaults(dataRef.current);
|
|
setDataAsDefaults(true);
|
|
} else {
|
|
setDefaults((defaults2) => {
|
|
newDefaults = typeof fieldOrFields === "string" ? set(cloneDeep(defaults2), fieldOrFields, maybeValue) : Object.assign(cloneDeep(defaults2), fieldOrFields);
|
|
return newDefaults;
|
|
});
|
|
}
|
|
validatorRef.current?.defaults(newDefaults);
|
|
},
|
|
[setDefaults]
|
|
);
|
|
useIsomorphicLayoutEffect(() => {
|
|
if (!dataAsDefaults) {
|
|
return;
|
|
}
|
|
if (isDirty) {
|
|
setDefaults(data);
|
|
}
|
|
setDataAsDefaults(false);
|
|
}, [dataAsDefaults]);
|
|
const reset = useCallback(
|
|
(...fields) => {
|
|
if (fields.length === 0) {
|
|
setData(defaults);
|
|
} else {
|
|
setData(
|
|
(data2) => fields.filter((key) => has(defaults, key)).reduce(
|
|
(carry, key) => {
|
|
return set(carry, key, get(defaults, key));
|
|
},
|
|
{ ...data2 }
|
|
)
|
|
);
|
|
}
|
|
validatorRef.current?.reset(...fields);
|
|
},
|
|
[setData, defaults]
|
|
);
|
|
const setError = useCallback(
|
|
(fieldOrFields, maybeValue) => {
|
|
setErrors((errors2) => {
|
|
const newErrors = {
|
|
...errors2,
|
|
...typeof fieldOrFields === "string" ? { [fieldOrFields]: maybeValue } : fieldOrFields
|
|
};
|
|
setHasErrors(Object.keys(newErrors).length > 0);
|
|
validatorRef.current?.setErrors(newErrors);
|
|
return newErrors;
|
|
});
|
|
},
|
|
[setErrors, setHasErrors]
|
|
);
|
|
const clearErrors = useCallback(
|
|
(...fields) => {
|
|
setErrors((errors2) => {
|
|
const newErrors = Object.keys(errors2).reduce(
|
|
(carry, field) => ({
|
|
...carry,
|
|
...fields.length > 0 && !fields.includes(field) ? { [field]: errors2[field] } : {}
|
|
}),
|
|
{}
|
|
);
|
|
setHasErrors(Object.keys(newErrors).length > 0);
|
|
if (validatorRef.current) {
|
|
if (fields.length === 0) {
|
|
validatorRef.current.setErrors({});
|
|
} else {
|
|
fields.forEach(validatorRef.current.forgetError);
|
|
}
|
|
}
|
|
return newErrors;
|
|
});
|
|
},
|
|
[setErrors, setHasErrors]
|
|
);
|
|
const resetAndClearErrors = useCallback(
|
|
(...fields) => {
|
|
reset(...fields);
|
|
clearErrors(...fields);
|
|
},
|
|
[reset, clearErrors]
|
|
);
|
|
const createSubmitMethod = (method) => (url, options = {}) => {
|
|
submit(method, url, options);
|
|
};
|
|
const getMethod = useCallback(createSubmitMethod("get"), [submit]);
|
|
const post = useCallback(createSubmitMethod("post"), [submit]);
|
|
const put = useCallback(createSubmitMethod("put"), [submit]);
|
|
const patch = useCallback(createSubmitMethod("patch"), [submit]);
|
|
const deleteMethod = useCallback(createSubmitMethod("delete"), [submit]);
|
|
const cancel = useCallback(() => {
|
|
if (cancelToken.current) {
|
|
cancelToken.current.cancel();
|
|
}
|
|
}, []);
|
|
const transformFunction = useCallback((callback) => {
|
|
transform.current = callback;
|
|
}, []);
|
|
const form = {
|
|
data,
|
|
setData: setDataFunction,
|
|
isDirty,
|
|
errors,
|
|
hasErrors,
|
|
processing,
|
|
progress: progress2,
|
|
wasSuccessful,
|
|
recentlySuccessful,
|
|
transform: transformFunction,
|
|
setDefaults: setDefaultsFunction,
|
|
reset,
|
|
setError,
|
|
clearErrors,
|
|
resetAndClearErrors,
|
|
submit,
|
|
get: getMethod,
|
|
post,
|
|
put,
|
|
patch,
|
|
delete: deleteMethod,
|
|
cancel,
|
|
dontRemember: (...keys) => {
|
|
excludeKeysRef.current = keys;
|
|
return form;
|
|
}
|
|
};
|
|
const tap = (value, callback) => {
|
|
callback(value);
|
|
return value;
|
|
};
|
|
const valid = useCallback(
|
|
(field) => validFields.includes(field),
|
|
[validFields]
|
|
);
|
|
const invalid = useCallback((field) => field in errors, [errors]);
|
|
const touched = useCallback(
|
|
(field) => typeof field === "string" ? touchedFields.includes(field) : touchedFields.length > 0,
|
|
[touchedFields]
|
|
);
|
|
const validate = (field, config2) => {
|
|
if (typeof field === "object" && !("target" in field)) {
|
|
config2 = field;
|
|
field = void 0;
|
|
}
|
|
if (field === void 0) {
|
|
validatorRef.current.validate(config2);
|
|
} else {
|
|
const fieldName = resolveName(field);
|
|
const currentData = dataRef.current;
|
|
const transformedData = transform.current(currentData);
|
|
validatorRef.current.validate(fieldName, get(transformedData, fieldName), config2);
|
|
}
|
|
return form;
|
|
};
|
|
const withPrecognition = (...args2) => {
|
|
precognitionEndpoint.current = UseFormUtils.createWayfinderCallback(...args2);
|
|
if (!validatorRef.current) {
|
|
const validator = createValidator((client) => {
|
|
const { method, url } = precognitionEndpoint.current();
|
|
const currentData = dataRef.current;
|
|
const transformedData = transform.current(currentData);
|
|
return client[method](url, transformedData);
|
|
}, cloneDeep(defaults));
|
|
validatorRef.current = validator;
|
|
validator.on("validatingChanged", () => {
|
|
setValidating(validator.validating());
|
|
}).on("validatedChanged", () => {
|
|
setValidFields(validator.valid());
|
|
}).on("touchedChanged", () => {
|
|
setTouchedFields(validator.touched());
|
|
}).on("errorsChanged", () => {
|
|
const validationErrors = withAllErrors.current ? validator.errors() : toSimpleValidationErrors(validator.errors());
|
|
setErrors(validationErrors);
|
|
setHasErrors(Object.keys(validationErrors).length > 0);
|
|
setValidFields(validator.valid());
|
|
});
|
|
}
|
|
const precognitiveForm = Object.assign(form, {
|
|
validating,
|
|
validator: () => validatorRef.current,
|
|
valid,
|
|
invalid,
|
|
touched,
|
|
withoutFileValidation: () => tap(precognitiveForm, () => validatorRef.current?.withoutFileValidation()),
|
|
touch: (field, ...fields) => {
|
|
if (Array.isArray(field)) {
|
|
validatorRef.current?.touch(field);
|
|
} else if (typeof field === "string") {
|
|
validatorRef.current?.touch([field, ...fields]);
|
|
} else {
|
|
validatorRef.current?.touch(field);
|
|
}
|
|
return precognitiveForm;
|
|
},
|
|
withAllErrors: () => tap(precognitiveForm, () => withAllErrors.current = true),
|
|
setValidationTimeout: (duration) => tap(precognitiveForm, () => validatorRef.current?.setTimeout(duration)),
|
|
validateFiles: () => tap(precognitiveForm, () => validatorRef.current?.validateFiles()),
|
|
validate,
|
|
setErrors: (errors2) => tap(precognitiveForm, () => form.setError(errors2)),
|
|
forgetError: (field) => tap(
|
|
precognitiveForm,
|
|
() => form.clearErrors(resolveName(field))
|
|
)
|
|
});
|
|
return precognitiveForm;
|
|
};
|
|
form.withPrecognition = withPrecognition;
|
|
return precognitionEndpoint.current ? form.withPrecognition(precognitionEndpoint.current) : form;
|
|
}
|
|
|
|
// src/Form.ts
|
|
var deferStateUpdate = (callback) => {
|
|
typeof React3.startTransition === "function" ? React3.startTransition(callback) : setTimeout(callback, 0);
|
|
};
|
|
var noop = () => void 0;
|
|
var FormContext = createContext3(void 0);
|
|
var Form = forwardRef(
|
|
({
|
|
action = "",
|
|
method = "get",
|
|
headers = {},
|
|
queryStringArrayFormat = "brackets",
|
|
errorBag = null,
|
|
showProgress = true,
|
|
transform = (data) => data,
|
|
options = {},
|
|
onStart = noop,
|
|
onProgress = noop,
|
|
onFinish = noop,
|
|
onBefore = noop,
|
|
onCancel = noop,
|
|
onSuccess = noop,
|
|
onError = noop,
|
|
onCancelToken = noop,
|
|
onSubmitComplete = noop,
|
|
disableWhileProcessing = false,
|
|
resetOnError = false,
|
|
resetOnSuccess = false,
|
|
setDefaultsOnSuccess = false,
|
|
invalidateCacheTags = [],
|
|
validateFiles = false,
|
|
validationTimeout = 1500,
|
|
withAllErrors = false,
|
|
children,
|
|
...props
|
|
}, ref) => {
|
|
const getTransformedData = () => {
|
|
const [_url, data] = getUrlAndData();
|
|
return transform(data);
|
|
};
|
|
const form = useForm({}).withPrecognition(
|
|
() => resolvedMethod,
|
|
() => getUrlAndData()[0]
|
|
).setValidationTimeout(validationTimeout);
|
|
if (validateFiles) {
|
|
form.validateFiles();
|
|
}
|
|
if (withAllErrors) {
|
|
form.withAllErrors();
|
|
}
|
|
form.transform(getTransformedData);
|
|
const formElement = useRef2(void 0);
|
|
const resolvedMethod = useMemo4(() => {
|
|
return isUrlMethodPair(action) ? action.method : method.toLowerCase();
|
|
}, [action, method]);
|
|
const [isDirty, setIsDirty] = useState5(false);
|
|
const defaultData = useRef2(new FormData());
|
|
const getFormData = (submitter) => new FormData(formElement.current, submitter);
|
|
const getData = (submitter) => formDataToObject(getFormData(submitter));
|
|
const getUrlAndData = (submitter) => {
|
|
return mergeDataIntoQueryString(
|
|
resolvedMethod,
|
|
isUrlMethodPair(action) ? action.url : action,
|
|
getData(submitter),
|
|
queryStringArrayFormat
|
|
);
|
|
};
|
|
const updateDirtyState = (event) => {
|
|
if (event.type === "reset" && event.detail?.[FormComponentResetSymbol]) {
|
|
event.preventDefault();
|
|
}
|
|
deferStateUpdate(
|
|
() => setIsDirty(event.type === "reset" ? false : !isEqual2(getData(), formDataToObject(defaultData.current)))
|
|
);
|
|
};
|
|
const clearErrors = (...names) => {
|
|
form.clearErrors(...names);
|
|
return form;
|
|
};
|
|
useEffect6(() => {
|
|
defaultData.current = getFormData();
|
|
form.setDefaults(getData());
|
|
const formEvents = ["input", "change", "reset"];
|
|
formEvents.forEach((e) => formElement.current.addEventListener(e, updateDirtyState));
|
|
return () => {
|
|
formEvents.forEach((e) => formElement.current?.removeEventListener(e, updateDirtyState));
|
|
};
|
|
}, []);
|
|
useEffect6(() => {
|
|
form.setValidationTimeout(validationTimeout);
|
|
}, [validationTimeout]);
|
|
useEffect6(() => {
|
|
if (validateFiles) {
|
|
form.validateFiles();
|
|
} else {
|
|
form.withoutFileValidation();
|
|
}
|
|
}, [validateFiles]);
|
|
const reset = (...fields) => {
|
|
if (formElement.current) {
|
|
resetFormFields(formElement.current, defaultData.current, fields);
|
|
}
|
|
form.reset(...fields);
|
|
};
|
|
const resetAndClearErrors = (...fields) => {
|
|
clearErrors(...fields);
|
|
reset(...fields);
|
|
};
|
|
const maybeReset = (resetOption) => {
|
|
if (!resetOption) {
|
|
return;
|
|
}
|
|
if (resetOption === true) {
|
|
reset();
|
|
} else if (resetOption.length > 0) {
|
|
reset(...resetOption);
|
|
}
|
|
};
|
|
const submit = (submitter) => {
|
|
const [url, data] = getUrlAndData(submitter);
|
|
const formTarget = submitter?.getAttribute("formtarget");
|
|
if (formTarget === "_blank" && resolvedMethod === "get") {
|
|
window.open(url, "_blank");
|
|
return;
|
|
}
|
|
const submitOptions = {
|
|
headers,
|
|
queryStringArrayFormat,
|
|
errorBag,
|
|
showProgress,
|
|
invalidateCacheTags,
|
|
onCancelToken,
|
|
onBefore,
|
|
onStart,
|
|
onProgress,
|
|
onFinish,
|
|
onCancel,
|
|
onSuccess: (...args) => {
|
|
onSuccess(...args);
|
|
onSubmitComplete({
|
|
reset,
|
|
defaults
|
|
});
|
|
maybeReset(resetOnSuccess);
|
|
if (setDefaultsOnSuccess === true) {
|
|
defaults();
|
|
}
|
|
},
|
|
onError(...args) {
|
|
onError(...args);
|
|
maybeReset(resetOnError);
|
|
},
|
|
...options
|
|
};
|
|
form.transform(() => transform(data));
|
|
form.submit(resolvedMethod, url, submitOptions);
|
|
form.transform(getTransformedData);
|
|
};
|
|
const defaults = () => {
|
|
defaultData.current = getFormData();
|
|
setIsDirty(false);
|
|
};
|
|
const exposed = {
|
|
errors: form.errors,
|
|
hasErrors: form.hasErrors,
|
|
processing: form.processing,
|
|
progress: form.progress,
|
|
wasSuccessful: form.wasSuccessful,
|
|
recentlySuccessful: form.recentlySuccessful,
|
|
isDirty,
|
|
clearErrors,
|
|
resetAndClearErrors,
|
|
setError: form.setError,
|
|
reset,
|
|
submit,
|
|
defaults,
|
|
getData,
|
|
getFormData,
|
|
// Precognition
|
|
validator: () => form.validator(),
|
|
validating: form.validating,
|
|
valid: form.valid,
|
|
invalid: form.invalid,
|
|
validate: (field, config2) => form.validate(...UseFormUtils2.mergeHeadersForValidation(field, config2, headers)),
|
|
touch: form.touch,
|
|
touched: form.touched
|
|
};
|
|
useImperativeHandle(ref, () => exposed, [form, isDirty, submit]);
|
|
const formNode = createElement3(
|
|
"form",
|
|
{
|
|
...props,
|
|
ref: formElement,
|
|
action: isUrlMethodPair(action) ? action.url : action,
|
|
method: resolvedMethod,
|
|
onSubmit: (event) => {
|
|
event.preventDefault();
|
|
submit(event.nativeEvent.submitter);
|
|
},
|
|
// React 19 supports passing a boolean to the `inert` attribute, but shows
|
|
// a warning when receiving a string. Earlier versions require the string 'true'.
|
|
// See: https://github.com/inertiajs/inertia/pull/2536
|
|
inert: disableWhileProcessing && form.processing && (isReact19 ? true : "true")
|
|
},
|
|
typeof children === "function" ? children(exposed) : children
|
|
);
|
|
return createElement3(FormContext.Provider, { value: exposed }, formNode);
|
|
}
|
|
);
|
|
Form.displayName = "InertiaForm";
|
|
function useFormContext() {
|
|
return useContext(FormContext);
|
|
}
|
|
var Form_default = Form;
|
|
|
|
// src/Head.ts
|
|
import { escape } from "lodash-es";
|
|
import React4, { useContext as useContext2, useEffect as useEffect7, useMemo as useMemo5 } from "react";
|
|
var Head = function({ children, title }) {
|
|
const headManager = useContext2(HeadContext_default);
|
|
const provider = useMemo5(() => headManager.createProvider(), [headManager]);
|
|
const isServer = typeof window === "undefined";
|
|
useEffect7(() => {
|
|
provider.reconnect();
|
|
provider.update(renderNodes(children));
|
|
return () => {
|
|
provider.disconnect();
|
|
};
|
|
}, [provider, children, title]);
|
|
function isUnaryTag(node) {
|
|
return typeof node.type === "string" && [
|
|
"area",
|
|
"base",
|
|
"br",
|
|
"col",
|
|
"embed",
|
|
"hr",
|
|
"img",
|
|
"input",
|
|
"keygen",
|
|
"link",
|
|
"meta",
|
|
"param",
|
|
"source",
|
|
"track",
|
|
"wbr"
|
|
].indexOf(node.type) > -1;
|
|
}
|
|
function renderTagStart(node) {
|
|
const attrs = Object.keys(node.props).reduce((carry, name) => {
|
|
if (["head-key", "children", "dangerouslySetInnerHTML"].includes(name)) {
|
|
return carry;
|
|
}
|
|
const value = String(node.props[name]);
|
|
if (value === "") {
|
|
return carry + ` ${name}`;
|
|
}
|
|
return carry + ` ${name}="${escape(value)}"`;
|
|
}, "");
|
|
return `<${String(node.type)}${attrs}>`;
|
|
}
|
|
function renderTagChildren(node) {
|
|
const { children: children2 } = node.props;
|
|
if (typeof children2 === "string") {
|
|
return children2;
|
|
}
|
|
if (Array.isArray(children2)) {
|
|
return children2.reduce((html, child) => html + renderTag(child), "");
|
|
}
|
|
return "";
|
|
}
|
|
function renderTag(node) {
|
|
let html = renderTagStart(node);
|
|
if (node.props.children) {
|
|
html += renderTagChildren(node);
|
|
}
|
|
if (node.props.dangerouslySetInnerHTML) {
|
|
html += node.props.dangerouslySetInnerHTML.__html;
|
|
}
|
|
if (!isUnaryTag(node)) {
|
|
html += `</${String(node.type)}>`;
|
|
}
|
|
return html;
|
|
}
|
|
function ensureNodeHasInertiaProp(node) {
|
|
return React4.cloneElement(node, {
|
|
[provider.preferredAttribute()]: node.props["head-key"] !== void 0 ? node.props["head-key"] : ""
|
|
});
|
|
}
|
|
function renderNode(node) {
|
|
return renderTag(ensureNodeHasInertiaProp(node));
|
|
}
|
|
function renderNodes(nodes) {
|
|
const elements = React4.Children.toArray(nodes).filter((node) => node).map((node) => renderNode(node));
|
|
if (title && !elements.find((tag) => tag.startsWith("<title"))) {
|
|
elements.push(`<title ${provider.preferredAttribute()}>${title}</title>`);
|
|
}
|
|
return elements;
|
|
}
|
|
if (isServer) {
|
|
provider.update(renderNodes(children));
|
|
}
|
|
return null;
|
|
};
|
|
var Head_default = Head;
|
|
|
|
// src/InfiniteScroll.ts
|
|
import {
|
|
getScrollableParent,
|
|
useInfiniteScroll
|
|
} from "@inertiajs/core";
|
|
import React5, {
|
|
createElement as createElement4,
|
|
forwardRef as forwardRef2,
|
|
useCallback as useCallback2,
|
|
useEffect as useEffect8,
|
|
useImperativeHandle as useImperativeHandle2,
|
|
useMemo as useMemo6,
|
|
useRef as useRef3,
|
|
useState as useState6
|
|
} from "react";
|
|
var resolveHTMLElement = (value, fallback) => {
|
|
if (!value) {
|
|
return fallback;
|
|
}
|
|
if (value && typeof value === "object" && "current" in value) {
|
|
return value.current;
|
|
}
|
|
if (typeof value === "string") {
|
|
return document.querySelector(value);
|
|
}
|
|
return fallback;
|
|
};
|
|
var renderSlot = (slotContent, slotProps, fallback = null) => {
|
|
if (!slotContent) {
|
|
return fallback;
|
|
}
|
|
return typeof slotContent === "function" ? slotContent(slotProps) : slotContent;
|
|
};
|
|
var InfiniteScroll = forwardRef2(
|
|
({
|
|
data,
|
|
buffer = 0,
|
|
as = "div",
|
|
manual = false,
|
|
manualAfter = 0,
|
|
preserveUrl = false,
|
|
reverse = false,
|
|
autoScroll,
|
|
children,
|
|
startElement,
|
|
endElement,
|
|
itemsElement,
|
|
previous,
|
|
next,
|
|
loading,
|
|
onlyNext = false,
|
|
onlyPrevious = false,
|
|
...props
|
|
}, ref) => {
|
|
const [startElementFromRef, setStartElementFromRef] = useState6(null);
|
|
const startElementRef = useCallback2((node) => setStartElementFromRef(node), []);
|
|
const [endElementFromRef, setEndElementFromRef] = useState6(null);
|
|
const endElementRef = useCallback2((node) => setEndElementFromRef(node), []);
|
|
const [itemsElementFromRef, setItemsElementFromRef] = useState6(null);
|
|
const itemsElementRef = useCallback2((node) => setItemsElementFromRef(node), []);
|
|
const [loadingPrevious, setLoadingPrevious] = useState6(false);
|
|
const [loadingNext, setLoadingNext] = useState6(false);
|
|
const [requestCount, setRequestCount] = useState6(0);
|
|
const [hasPreviousPage, setHasPreviousPage] = useState6(false);
|
|
const [hasNextPage, setHasNextPage] = useState6(false);
|
|
const [resolvedStartElement, setResolvedStartElement] = useState6(null);
|
|
const [resolvedEndElement, setResolvedEndElement] = useState6(null);
|
|
const [resolvedItemsElement, setResolvedItemsElement] = useState6(null);
|
|
useEffect8(() => {
|
|
const element = startElement ? resolveHTMLElement(startElement, startElementFromRef) : startElementFromRef;
|
|
setResolvedStartElement(element);
|
|
}, [startElement, startElementFromRef]);
|
|
useEffect8(() => {
|
|
const element = endElement ? resolveHTMLElement(endElement, endElementFromRef) : endElementFromRef;
|
|
setResolvedEndElement(element);
|
|
}, [endElement, endElementFromRef]);
|
|
useEffect8(() => {
|
|
const element = itemsElement ? resolveHTMLElement(itemsElement, itemsElementFromRef) : itemsElementFromRef;
|
|
setResolvedItemsElement(element);
|
|
}, [itemsElement, itemsElementFromRef]);
|
|
const scrollableParent = useMemo6(() => getScrollableParent(resolvedItemsElement), [resolvedItemsElement]);
|
|
const callbackPropsRef = useRef3({
|
|
buffer,
|
|
onlyNext,
|
|
onlyPrevious,
|
|
reverse,
|
|
preserveUrl
|
|
});
|
|
callbackPropsRef.current = {
|
|
buffer,
|
|
onlyNext,
|
|
onlyPrevious,
|
|
reverse,
|
|
preserveUrl
|
|
};
|
|
const [infiniteScroll, setInfiniteScroll] = useState6(null);
|
|
const dataManager = useMemo6(() => infiniteScroll?.dataManager, [infiniteScroll]);
|
|
const elementManager = useMemo6(() => infiniteScroll?.elementManager, [infiniteScroll]);
|
|
const scrollToBottom = useCallback2(() => {
|
|
if (scrollableParent) {
|
|
scrollableParent.scrollTo({
|
|
top: scrollableParent.scrollHeight,
|
|
behavior: "instant"
|
|
});
|
|
} else {
|
|
window.scrollTo({
|
|
top: document.body.scrollHeight,
|
|
behavior: "instant"
|
|
});
|
|
}
|
|
}, [scrollableParent]);
|
|
useEffect8(() => {
|
|
if (!resolvedItemsElement) {
|
|
return;
|
|
}
|
|
function syncStateFromDataManager() {
|
|
setRequestCount(infiniteScrollInstance.dataManager.getRequestCount());
|
|
setHasPreviousPage(infiniteScrollInstance.dataManager.hasPrevious());
|
|
setHasNextPage(infiniteScrollInstance.dataManager.hasNext());
|
|
}
|
|
const infiniteScrollInstance = useInfiniteScroll({
|
|
// Data
|
|
getPropName: () => data,
|
|
inReverseMode: () => callbackPropsRef.current.reverse,
|
|
shouldFetchNext: () => !callbackPropsRef.current.onlyPrevious,
|
|
shouldFetchPrevious: () => !callbackPropsRef.current.onlyNext,
|
|
shouldPreserveUrl: () => callbackPropsRef.current.preserveUrl,
|
|
// Elements
|
|
getTriggerMargin: () => callbackPropsRef.current.buffer,
|
|
getStartElement: () => resolvedStartElement,
|
|
getEndElement: () => resolvedEndElement,
|
|
getItemsElement: () => resolvedItemsElement,
|
|
getScrollableParent: () => scrollableParent,
|
|
// Callbacks
|
|
onBeforePreviousRequest: () => setLoadingPrevious(true),
|
|
onBeforeNextRequest: () => setLoadingNext(true),
|
|
onCompletePreviousRequest: () => {
|
|
setLoadingPrevious(false);
|
|
syncStateFromDataManager();
|
|
},
|
|
onCompleteNextRequest: () => {
|
|
setLoadingNext(false);
|
|
syncStateFromDataManager();
|
|
},
|
|
onDataReset: syncStateFromDataManager
|
|
});
|
|
setInfiniteScroll(infiniteScrollInstance);
|
|
const { dataManager: dataManager2, elementManager: elementManager2 } = infiniteScrollInstance;
|
|
syncStateFromDataManager();
|
|
elementManager2.setupObservers();
|
|
elementManager2.processServerLoadedElements(dataManager2.getLastLoadedPage());
|
|
if (autoLoad) {
|
|
elementManager2.enableTriggers();
|
|
}
|
|
return () => {
|
|
infiniteScrollInstance.flush();
|
|
setInfiniteScroll(null);
|
|
};
|
|
}, [data, resolvedItemsElement, resolvedStartElement, resolvedEndElement, scrollableParent]);
|
|
const manualMode = useMemo6(
|
|
() => manual || manualAfter > 0 && requestCount >= manualAfter,
|
|
[manual, manualAfter, requestCount]
|
|
);
|
|
const autoLoad = useMemo6(() => !manualMode, [manualMode]);
|
|
useEffect8(() => {
|
|
autoLoad ? elementManager?.enableTriggers() : elementManager?.disableTriggers();
|
|
}, [autoLoad, onlyNext, onlyPrevious, resolvedStartElement, resolvedEndElement]);
|
|
useEffect8(() => {
|
|
const shouldAutoScroll = autoScroll !== void 0 ? autoScroll : reverse;
|
|
if (shouldAutoScroll) {
|
|
scrollToBottom();
|
|
}
|
|
}, [scrollableParent]);
|
|
useImperativeHandle2(
|
|
ref,
|
|
() => ({
|
|
fetchNext: dataManager?.fetchNext || (() => {
|
|
}),
|
|
fetchPrevious: dataManager?.fetchPrevious || (() => {
|
|
}),
|
|
hasPrevious: dataManager?.hasPrevious || (() => false),
|
|
hasNext: dataManager?.hasNext || (() => false)
|
|
}),
|
|
[dataManager]
|
|
);
|
|
const headerAutoMode = autoLoad && !onlyNext;
|
|
const footerAutoMode = autoLoad && !onlyPrevious;
|
|
const sharedExposed = {
|
|
loadingPrevious,
|
|
loadingNext,
|
|
hasPrevious: hasPreviousPage,
|
|
hasNext: hasNextPage
|
|
};
|
|
const exposedPrevious = {
|
|
loading: loadingPrevious,
|
|
fetch: dataManager?.fetchPrevious ?? (() => {
|
|
}),
|
|
autoMode: headerAutoMode,
|
|
manualMode: !headerAutoMode,
|
|
hasMore: hasPreviousPage,
|
|
...sharedExposed
|
|
};
|
|
const exposedNext = {
|
|
loading: loadingNext,
|
|
fetch: dataManager?.fetchNext ?? (() => {
|
|
}),
|
|
autoMode: footerAutoMode,
|
|
manualMode: !footerAutoMode,
|
|
hasMore: hasNextPage,
|
|
...sharedExposed
|
|
};
|
|
const exposedSlot = {
|
|
loading: loadingPrevious || loadingNext,
|
|
loadingPrevious,
|
|
loadingNext
|
|
};
|
|
const renderElements = [];
|
|
if (!startElement) {
|
|
renderElements.push(
|
|
createElement4(
|
|
"div",
|
|
{ ref: startElementRef },
|
|
// Render previous slot or fallback to loading indicator
|
|
renderSlot(previous, exposedPrevious, loadingPrevious ? renderSlot(loading, exposedPrevious) : null)
|
|
)
|
|
);
|
|
}
|
|
renderElements.push(
|
|
createElement4(
|
|
as,
|
|
{ ...props, ref: itemsElementRef },
|
|
typeof children === "function" ? children(exposedSlot) : children
|
|
)
|
|
);
|
|
if (!endElement) {
|
|
renderElements.push(
|
|
createElement4(
|
|
"div",
|
|
{ ref: endElementRef },
|
|
// Render next slot or fallback to loading indicator
|
|
renderSlot(next, exposedNext, loadingNext ? renderSlot(loading, exposedNext) : null)
|
|
)
|
|
);
|
|
}
|
|
return createElement4(React5.Fragment, {}, ...reverse ? [...renderElements].reverse() : renderElements);
|
|
}
|
|
);
|
|
InfiniteScroll.displayName = "InertiaInfiniteScroll";
|
|
var InfiniteScroll_default = InfiniteScroll;
|
|
|
|
// src/Link.ts
|
|
import {
|
|
isUrlMethodPair as isUrlMethodPair2,
|
|
mergeDataIntoQueryString as mergeDataIntoQueryString2,
|
|
router as router6,
|
|
shouldIntercept,
|
|
shouldNavigate
|
|
} from "@inertiajs/core";
|
|
import { createElement as createElement5, forwardRef as forwardRef3, useEffect as useEffect9, useMemo as useMemo7, useRef as useRef4, useState as useState7 } from "react";
|
|
var noop2 = () => void 0;
|
|
var Link = forwardRef3(
|
|
({
|
|
children,
|
|
as = "a",
|
|
data = {},
|
|
href = "",
|
|
method = "get",
|
|
preserveScroll = false,
|
|
preserveState = null,
|
|
preserveUrl = false,
|
|
replace = false,
|
|
only = [],
|
|
except = [],
|
|
headers = {},
|
|
queryStringArrayFormat = "brackets",
|
|
async = false,
|
|
onClick = noop2,
|
|
onCancelToken = noop2,
|
|
onBefore = noop2,
|
|
onStart = noop2,
|
|
onProgress = noop2,
|
|
onFinish = noop2,
|
|
onCancel = noop2,
|
|
onSuccess = noop2,
|
|
onError = noop2,
|
|
onPrefetching = noop2,
|
|
onPrefetched = noop2,
|
|
prefetch = false,
|
|
cacheFor = 0,
|
|
cacheTags = [],
|
|
viewTransition = false,
|
|
...props
|
|
}, ref) => {
|
|
const [inFlightCount, setInFlightCount] = useState7(0);
|
|
const hoverTimeout = useRef4(void 0);
|
|
const _method = useMemo7(() => {
|
|
return isUrlMethodPair2(href) ? href.method : method.toLowerCase();
|
|
}, [href, method]);
|
|
const _as = useMemo7(() => {
|
|
if (typeof as !== "string" || as.toLowerCase() !== "a") {
|
|
return as;
|
|
}
|
|
return _method !== "get" ? "button" : as.toLowerCase();
|
|
}, [as, _method]);
|
|
const mergeDataArray = useMemo7(
|
|
() => mergeDataIntoQueryString2(_method, isUrlMethodPair2(href) ? href.url : href, data, queryStringArrayFormat),
|
|
[href, _method, data, queryStringArrayFormat]
|
|
);
|
|
const url = useMemo7(() => mergeDataArray[0], [mergeDataArray]);
|
|
const _data = useMemo7(() => mergeDataArray[1], [mergeDataArray]);
|
|
const baseParams = useMemo7(
|
|
() => ({
|
|
data: _data,
|
|
method: _method,
|
|
preserveScroll,
|
|
preserveState: preserveState ?? _method !== "get",
|
|
preserveUrl,
|
|
replace,
|
|
only,
|
|
except,
|
|
headers,
|
|
async
|
|
}),
|
|
[_data, _method, preserveScroll, preserveState, preserveUrl, replace, only, except, headers, async]
|
|
);
|
|
const visitParams = useMemo7(
|
|
() => ({
|
|
...baseParams,
|
|
viewTransition,
|
|
onCancelToken,
|
|
onBefore,
|
|
onStart(visit) {
|
|
setInFlightCount((count) => count + 1);
|
|
onStart(visit);
|
|
},
|
|
onProgress,
|
|
onFinish(visit) {
|
|
setInFlightCount((count) => count - 1);
|
|
onFinish(visit);
|
|
},
|
|
onCancel,
|
|
onSuccess,
|
|
onError
|
|
}),
|
|
[
|
|
baseParams,
|
|
viewTransition,
|
|
onCancelToken,
|
|
onBefore,
|
|
onStart,
|
|
onProgress,
|
|
onFinish,
|
|
onCancel,
|
|
onSuccess,
|
|
onError
|
|
]
|
|
);
|
|
const prefetchModes = useMemo7(
|
|
() => {
|
|
if (prefetch === true) {
|
|
return ["hover"];
|
|
}
|
|
if (prefetch === false) {
|
|
return [];
|
|
}
|
|
if (Array.isArray(prefetch)) {
|
|
return prefetch;
|
|
}
|
|
return [prefetch];
|
|
},
|
|
Array.isArray(prefetch) ? prefetch : [prefetch]
|
|
);
|
|
const cacheForValue = useMemo7(() => {
|
|
if (cacheFor !== 0) {
|
|
return cacheFor;
|
|
}
|
|
if (prefetchModes.length === 1 && prefetchModes[0] === "click") {
|
|
return 0;
|
|
}
|
|
return config.get("prefetch.cacheFor");
|
|
}, [cacheFor, prefetchModes]);
|
|
const doPrefetch = useMemo7(() => {
|
|
return () => {
|
|
router6.prefetch(
|
|
url,
|
|
{
|
|
...baseParams,
|
|
onPrefetching,
|
|
onPrefetched
|
|
},
|
|
{ cacheFor: cacheForValue, cacheTags }
|
|
);
|
|
};
|
|
}, [url, baseParams, onPrefetching, onPrefetched, cacheForValue, cacheTags]);
|
|
useEffect9(() => {
|
|
return () => {
|
|
clearTimeout(hoverTimeout.current);
|
|
};
|
|
}, []);
|
|
useEffect9(() => {
|
|
if (prefetchModes.includes("mount")) {
|
|
setTimeout(() => doPrefetch());
|
|
}
|
|
}, prefetchModes);
|
|
const regularEvents = {
|
|
onClick: (event) => {
|
|
onClick(event);
|
|
if (shouldIntercept(event)) {
|
|
event.preventDefault();
|
|
router6.visit(url, visitParams);
|
|
}
|
|
}
|
|
};
|
|
const prefetchHoverEvents = {
|
|
onMouseEnter: () => {
|
|
hoverTimeout.current = window.setTimeout(() => {
|
|
doPrefetch();
|
|
}, config.get("prefetch.hoverDelay"));
|
|
},
|
|
onMouseLeave: () => {
|
|
clearTimeout(hoverTimeout.current);
|
|
},
|
|
onClick: regularEvents.onClick
|
|
};
|
|
const prefetchClickEvents = {
|
|
onMouseDown: (event) => {
|
|
if (shouldIntercept(event)) {
|
|
event.preventDefault();
|
|
doPrefetch();
|
|
}
|
|
},
|
|
onKeyDown: (event) => {
|
|
if (shouldNavigate(event)) {
|
|
event.preventDefault();
|
|
doPrefetch();
|
|
}
|
|
},
|
|
onMouseUp: (event) => {
|
|
if (shouldIntercept(event)) {
|
|
event.preventDefault();
|
|
router6.visit(url, visitParams);
|
|
}
|
|
},
|
|
onKeyUp: (event) => {
|
|
if (shouldNavigate(event)) {
|
|
event.preventDefault();
|
|
router6.visit(url, visitParams);
|
|
}
|
|
},
|
|
onClick: (event) => {
|
|
onClick(event);
|
|
if (shouldIntercept(event)) {
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
};
|
|
const elProps = useMemo7(() => {
|
|
if (_as === "button") {
|
|
return { type: "button" };
|
|
}
|
|
if (_as === "a" || typeof _as !== "string") {
|
|
return { href: url };
|
|
}
|
|
return {};
|
|
}, [_as, url]);
|
|
return createElement5(
|
|
_as,
|
|
{
|
|
...props,
|
|
...elProps,
|
|
ref,
|
|
...(() => {
|
|
if (prefetchModes.includes("hover")) {
|
|
return prefetchHoverEvents;
|
|
}
|
|
if (prefetchModes.includes("click")) {
|
|
return prefetchClickEvents;
|
|
}
|
|
return regularEvents;
|
|
})(),
|
|
"data-loading": inFlightCount > 0 ? "" : void 0
|
|
},
|
|
children
|
|
);
|
|
}
|
|
);
|
|
Link.displayName = "InertiaLink";
|
|
var Link_default = Link;
|
|
|
|
// src/usePoll.ts
|
|
import { router as router7 } from "@inertiajs/core";
|
|
import { useEffect as useEffect10, useRef as useRef5 } from "react";
|
|
function usePoll(interval, requestOptions = {}, options = {
|
|
keepAlive: false,
|
|
autoStart: true
|
|
}) {
|
|
const pollRef = useRef5(
|
|
router7.poll(interval, requestOptions, {
|
|
...options,
|
|
autoStart: false
|
|
})
|
|
);
|
|
useEffect10(() => {
|
|
if (options.autoStart ?? true) {
|
|
pollRef.current.start();
|
|
}
|
|
return () => pollRef.current.stop();
|
|
}, []);
|
|
return {
|
|
stop: pollRef.current.stop,
|
|
start: pollRef.current.start
|
|
};
|
|
}
|
|
|
|
// src/usePrefetch.ts
|
|
import { router as router8 } from "@inertiajs/core";
|
|
import { useEffect as useEffect11, useState as useState8 } from "react";
|
|
function usePrefetch(options = {}) {
|
|
const cached = typeof window === "undefined" ? null : router8.getCached(window.location.pathname, options);
|
|
const inFlight = typeof window === "undefined" ? null : router8.getPrefetching(window.location.pathname, options);
|
|
const [lastUpdatedAt, setLastUpdatedAt] = useState8(cached?.staleTimestamp || null);
|
|
const [isPrefetching, setIsPrefetching] = useState8(inFlight !== null);
|
|
const [isPrefetched, setIsPrefetched] = useState8(cached !== null);
|
|
useEffect11(() => {
|
|
const onPrefetchingListener = router8.on("prefetching", (e) => {
|
|
if (e.detail.visit.url.pathname === window.location.pathname) {
|
|
setIsPrefetching(true);
|
|
}
|
|
});
|
|
const onPrefetchedListener = router8.on("prefetched", (e) => {
|
|
if (e.detail.visit.url.pathname === window.location.pathname) {
|
|
setIsPrefetching(false);
|
|
setIsPrefetched(true);
|
|
setLastUpdatedAt(e.detail.fetchedAt);
|
|
}
|
|
});
|
|
return () => {
|
|
onPrefetchedListener();
|
|
onPrefetchingListener();
|
|
};
|
|
}, []);
|
|
return {
|
|
lastUpdatedAt,
|
|
isPrefetching,
|
|
isPrefetched,
|
|
flush: () => router8.flush(window.location.pathname, options)
|
|
};
|
|
}
|
|
|
|
// src/WhenVisible.ts
|
|
import { router as router9 } from "@inertiajs/core";
|
|
import { createElement as createElement6, useCallback as useCallback3, useEffect as useEffect12, useMemo as useMemo8, useRef as useRef6, useState as useState9 } from "react";
|
|
var WhenVisible = ({ children, data, params, buffer, as, always, fallback }) => {
|
|
always = always ?? false;
|
|
as = as ?? "div";
|
|
fallback = fallback ?? null;
|
|
const pageProps = usePage().props;
|
|
const keys = useMemo8(() => data ? Array.isArray(data) ? data : [data] : [], [data]);
|
|
const [loaded, setLoaded] = useState9(() => keys.length > 0 && keys.every((key) => pageProps[key] !== void 0));
|
|
const [isFetching, setIsFetching] = useState9(false);
|
|
const fetching = useRef6(false);
|
|
const ref = useRef6(null);
|
|
const observer = useRef6(null);
|
|
const getReloadParamsRef = useRef6(() => ({}));
|
|
useEffect12(() => {
|
|
if (keys.length > 0) {
|
|
setLoaded(keys.every((key) => pageProps[key] !== void 0));
|
|
}
|
|
}, [pageProps, keys]);
|
|
const getReloadParams = useCallback3(() => {
|
|
const reloadParams = { ...params };
|
|
if (data) {
|
|
reloadParams.only = Array.isArray(data) ? data : [data];
|
|
}
|
|
return reloadParams;
|
|
}, [params, data]);
|
|
getReloadParamsRef.current = getReloadParams;
|
|
const registerObserver = () => {
|
|
observer.current?.disconnect();
|
|
observer.current = new IntersectionObserver(
|
|
(entries) => {
|
|
if (!entries[0].isIntersecting) {
|
|
return;
|
|
}
|
|
if (fetching.current) {
|
|
return;
|
|
}
|
|
if (!always && loaded) {
|
|
return;
|
|
}
|
|
fetching.current = true;
|
|
setIsFetching(true);
|
|
const reloadParams = getReloadParamsRef.current();
|
|
router9.reload({
|
|
...reloadParams,
|
|
onStart: (e) => {
|
|
fetching.current = true;
|
|
setIsFetching(true);
|
|
reloadParams.onStart?.(e);
|
|
},
|
|
onFinish: (e) => {
|
|
setLoaded(true);
|
|
fetching.current = false;
|
|
setIsFetching(false);
|
|
reloadParams.onFinish?.(e);
|
|
if (!always) {
|
|
observer.current?.disconnect();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
{
|
|
rootMargin: `${buffer || 0}px`
|
|
}
|
|
);
|
|
observer.current.observe(ref.current);
|
|
};
|
|
useEffect12(() => {
|
|
if (!ref.current) {
|
|
return;
|
|
}
|
|
if (loaded && !always) {
|
|
return;
|
|
}
|
|
registerObserver();
|
|
return () => {
|
|
observer.current?.disconnect();
|
|
};
|
|
}, [always, loaded, buffer]);
|
|
const resolveChildren = () => typeof children === "function" ? children({ fetching: isFetching }) : children;
|
|
const resolveFallback = () => typeof fallback === "function" ? fallback() : fallback;
|
|
if (always || !loaded) {
|
|
return createElement6(
|
|
as,
|
|
{
|
|
props: null,
|
|
ref
|
|
},
|
|
loaded ? resolveChildren() : resolveFallback()
|
|
);
|
|
}
|
|
return loaded ? resolveChildren() : null;
|
|
};
|
|
WhenVisible.displayName = "InertiaWhenVisible";
|
|
var WhenVisible_default = WhenVisible;
|
|
|
|
// src/index.ts
|
|
var progress = Progress2;
|
|
var router3 = Router;
|
|
var config = coreConfig.extend();
|
|
export {
|
|
App,
|
|
Deferred_default as Deferred,
|
|
Form_default as Form,
|
|
Head_default as Head,
|
|
InfiniteScroll_default as InfiniteScroll,
|
|
Link_default as Link,
|
|
WhenVisible_default as WhenVisible,
|
|
config,
|
|
createInertiaApp,
|
|
progress,
|
|
router3 as router,
|
|
useForm,
|
|
useFormContext,
|
|
usePage,
|
|
usePoll,
|
|
usePrefetch,
|
|
useRemember
|
|
};
|
|
//# sourceMappingURL=index.esm.js.map
|