UNPKG

sanity

Version:

Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches

971 lines (919 loc) • 22.6 kB
import {ComponentType} from 'react' import {ForwardRefExoticComponent} from 'react' import {FunctionComponent} from 'react' import {HTMLProps} from 'react' import {MouseEventHandler} from 'react' import {ReactNode} from 'react' import {RefAttributes} from 'react' import {RouterContext} from 'sanity/_singletons' /** * Base intent parameters * * @public * @todo dedupe with core/structure */ export declare interface BaseIntentParams { /** * Document schema type name to create/edit. * Required for `create` intents, optional for `edit` (but encouraged, safer and faster) */ type?: string /** * ID of the document to create/edit. * Required for `edit` intents, optional for `create`. */ id?: string template?: string /** * Experimental field path * * @beta * @experimental * @hidden */ path?: string /** * Optional "mode" to use for edit intent. * Known modes are `structure` and `presentation`. */ mode?: string /** * Arbitrary/custom parameters are generally discouraged - try to keep them to a minimum, * or use `payload` (arbitrary JSON-serializable object) instead. */ [key: string]: string | undefined } /** * @internal * @param options - Route node options */ export declare function _createNode(options: RouteNodeOptions): Router /** * Decode a path segment containing JSON parameters * * @param pathSegment - The path segment to decode * @returns The decoded parameters * @internal * @hidden */ export declare function decodeJsonParams(pathSegment?: string): any /** * Encodes a set of parameters as a path segment, using base64url * * @param params - Paramters to encode * @returns The encoded parameters as a path segment * @internal * @hidden */ export declare function encodeJsonParams(params?: any): string /** * Intent parameters (json) * * @public */ export declare type IntentJsonParams = { [key: string]: any } /** * @public * * @param props - Props to pass to `IntentLink` component. * See {@link IntentLinkProps} * * @example * ```tsx * function MyComponent() { * return <IntentLink intent="edit" params={{id: 'abc123'}}>Edit</IntentLink> * } * ``` */ export declare const IntentLink: ForwardRefExoticComponent< Omit<IntentLinkProps & HTMLProps<HTMLAnchorElement>, 'ref'> & RefAttributes<HTMLAnchorElement> > /** * Props for the {@link IntentLink} component. * * @public */ export declare interface IntentLinkProps { /** * The name of the intent. */ intent: string /** * The parameters to include in the intent. * {@link IntentParameters} */ params?: IntentParameters /** * Whether to replace the current URL in the browser history instead of adding a new entry. */ replace?: boolean /** * search params to include in the intent. */ searchParams?: SearchParam[] } /** * @public * @todo dedupe with intent types in core */ export declare type IntentParameters = BaseIntentParams | [BaseIntentParams, IntentJsonParams] /** @internal */ export declare type InternalSearchParam = [scopedPath: string[], value: string] /** * A component that creates an HTML anchor element. * * @public * * @param props - Props to pass to the `Link` component. * See {@link LinkProps} * * @example * ```tsx * function MyComponent() { * return ( * <Link href="https://www.sanity.io" target="_blank" replace> * Go to Sanity * </Link> * ) * } * ``` */ export declare const Link: ForwardRefExoticComponent< Omit<LinkProps & HTMLProps<HTMLAnchorElement>, 'ref'> & RefAttributes<HTMLAnchorElement> > /** * Props for the {@link Link} component. * * @public */ export declare interface LinkProps { /** * Whether to replace the current URL in the browser history instead of adding a new entry. */ replace?: boolean } /** @internal */ export declare interface MatchError { type: 'error' node: RouterNode /** * Parameters found in the route string but not provided as a key in the state object */ missingKeys: string[] /** * These are keys found in the state object but not in the route definition (and can't be mapped to a child route) */ unmappableStateKeys: string[] } /** @internal */ export declare interface MatchOk { type: 'ok' node: RouterNode matchedState: Record<string, string> searchParams: InternalSearchParam[] child: MatchOk | undefined } /** @internal */ export declare type MatchResult = MatchError | MatchOk /** * @public */ export declare interface NavigateBaseOptions { replace?: boolean } /** * @public */ export declare interface NavigateOptions extends NavigateBaseOptions { stickyParams?: Record<string, string | undefined | null> } /** * @public */ export declare interface NavigateOptionsWithState extends NavigateOptions { state?: RouterState | null } /** * Type representing either a new router state or navigation options with an optional state. * @internal */ export declare type NextStateOrOptions = | RouterState | (NavigateOptions & { state?: RouterState | null }) /** * @public */ export declare interface Route { /** * The raw string representation of the route. */ raw: string /** * An array of route segments that make up the route. * See {@link RouteSegment} */ segments: RouteSegment[] /** * An optional object containing route transforms. * See {@link RouteTransform} and {@link RouterState} */ transform?: { [key: string]: RouteTransform<RouterState> } } /** * An object containing functions for creating routers and router scopes. * See {@link RouteObject} * * @public * * @example * ```ts * const router = route.create({ * path: "/foo", * children: [ * route.create({ * path: "/bar", * children: [ * route.create({ * path: "/:baz", * transform: { * baz: { * toState: (id) => ({ id }), * toPath: (state) => state.id, * }, * }, * }), * ], * }), * ], * }); * ``` */ export declare const route: RouteObject /** * @public */ export declare type RouteChildren = | RouterNode[] | ((state: RouterState) => Router | RouterNode | RouterNode[] | undefined | false) /** * @public */ export declare interface RouteNodeOptions { /** * The path of the route node. */ path?: string /** * The children of the route node. See {@link RouteChildren} */ children?: RouteChildren /** * The transforms to apply to the route node. See {@link RouteTransform} */ transform?: { [key: string]: RouteTransform<any> } /** * The scope of the route node. */ scope?: string /** * Optionally disable scoping of search params * Scoped search params will be represented as scope[param]=value in the url * Disabling this will still scope search params based on any parent scope unless the parent scope also has disabled search params scoping * Caution: enabling this can cause conflicts with multiple plugins defining search params with the same name */ __unsafe_disableScopedSearchParams?: boolean } /** * Interface for the {@link route} object. * * @public */ export declare interface RouteObject { /** * Creates a new router. * Returns {@link Router} * See {@link RouteNodeOptions} and {@link RouteChildren} */ create: ( routeOrOpts: RouteNodeOptions | string, childrenOrOpts?: RouteNodeOptions | RouteChildren | null, children?: Router | RouteChildren, ) => Router /** * Creates a new router for handling intents. * Returns {@link Router} */ intents: (base: string) => Router /** * Creates a new router scope. * Returns {@link Router} */ scope( scopeName: string, routeOrOpts: RouteNodeOptions | string, childrenOrOpts?: RouteNodeOptions | RouteChildren | null, children?: Router | RouteChildren, ): Router } /** * @public */ export declare interface Router extends RouterNode { /** * Indicates whether this router is a route. * @internal */ _isRoute: boolean /** * Encodes the specified router state into a path string. * See {@link RouterState} * */ encode: (state: RouterState) => string /** * Decodes the specified path string into a router state. * See {@link RouterState} */ decode: (path: string) => RouterState | null /** * Determines whether the specified path is not found. */ isNotFound: (path: string) => boolean /** * Gets the base path of this router. */ getBasePath: () => string /** * Gets the redirect base of this router. */ getRedirectBase: (pathname: string) => string | null /** * Determines whether the specified path is the root path. */ isRoot: (path: string) => boolean } export {RouterContext} /** * @public */ export declare interface RouterContextValue { /** * Resolves the path from the given router state. See {@link RouterState} * * When state is null, it will resolve the path from the current state * and navigate to the root path. */ resolvePathFromState: (state: RouterState | null) => string /** * Resolves the intent link for the given intent name and parameters. * See {@link IntentParameters} */ resolveIntentLink: ( intentName: string, params?: IntentParameters, searchParams?: SearchParam[], ) => string /** * Navigates to the given URL. * The function requires an object that has a path and an optional replace property. */ navigateUrl: (opts: {path: string; replace?: boolean}) => void /** * @deprecated Use `navigate({stickyParams: params, ...options})` instead */ navigateStickyParams: ( params: NavigateOptions['stickyParams'], options?: NavigateBaseOptions, ) => void /** * Updates the router state and navigates to a new path. * Allows specifying new state values and optionally merging sticky parameters. * * See {@link RouterState} and {@link NavigateOptions} * * @public * * @example Navigate with sticky params only, staying on the current path * ```tsx * router.navigate({stickyParams: {baz: 'qux'}}) * ``` * @remarks `null` sticky parameter value will remove the sticky parameter from the url * * @example Navigate with state and sticky params * ```tsx * router.navigate({stickyParams: {baz: 'qux'}, state: {foo: 'bar'}}) * ``` * * @example Navigate to root path * ```tsx * router.navigate({stickyParams: {baz: 'qux'}, state: null}) * ``` */ navigate: { (nextState: RouterState, options?: NavigateOptions): void ( options: NavigateOptions & { state?: RouterState | null }, ): void } /** * Navigates to the given intent. * See {@link RouterState} and {@link NavigateBaseOptions} */ navigateIntent: ( intentName: string, params?: IntentParameters, options?: NavigateBaseOptions, ) => void /** * The current router state. See {@link RouterState} */ state: RouterState /** * The current router state. See {@link RouterState} */ stickyParams: Record<string, string | undefined | null> } /** * @public */ export declare interface RouterNode { /** * The route information for this node. See {@link Route} */ route: Route /** * An optional scope for this node. */ scope?: string /** * Optionally disable scoping of search params * Scoped search params will be represented as scope[param]=value in the url * Disabling this will still scope search params based on any parent scope unless the parent scope also has disabled search params scoping * Caution: enabling this can cause conflicts with multiple plugins defining search params with the same name */ __unsafe_disableScopedSearchParams?: boolean /** * An optional object containing transforms to apply to this node. * See {@link RouteTransform} and {@link RouterState} */ transform?: { [key: string]: RouteTransform<RouterState> } /** * The child nodes of this node. See {@link RouteChildren} */ children: RouteChildren } /** * @example * ```tsx * import { * NavigateOptions, * route, * RouterProvider, * RouterState * } from 'sanity' * import {useCallback, useMemo} from 'react' * * function Root() { * const [router] = useState(() => route.create('/')) * * const [state, setState] = useState<RouterState>({}) * * const handleNavigate = useCallback(( * path: string, * options?: NavigateOptions * ) => { * console.log('navigate', path, options) * * setState(router.decode(path)) * }, [router]) * * return ( * <RouterProvider * onNavigate={handleNavigate} * router={router} * state={state} * > * <div>This is a routed application</div> * </RouterProvider> * ) * } * ``` * * @param props - The component props. * {@link RouterProviderProps} * * @public */ export declare function RouterProvider(props: RouterProviderProps): React.JSX.Element /** * The props for the {@link RouterProvider} component. * * @public */ export declare interface RouterProviderProps { /** * A function that is called when the user navigates to a new path. * Takes an object containing the path to navigate to and an optional `replace` flag. */ onNavigate: (opts: {path: string; replace?: boolean}) => void /** * The router object that is used to handle navigation. See {@link Router} */ router: Router /** * The current state of the router. See {@link RouterState} */ state: RouterState /** * The child elements to render. */ children: ReactNode } /** * @public */ export declare type RouterState = Record<string, unknown> & { _searchParams?: SearchParam[] } /** * A component that wraps a scoped router context, so that calls to * `useRouter()`, `useRouterState()`, and usage of `<StateLink />` * will be prefixed with the scope segment. * * @public * * @param props - Props to pass `RouteScope` component. * See {@link RouteScopeProps} * * @example * ```tsx * function MyComponent() { * return ( * <RouteScope scope="foo"> * <StateLink state={{bar: 'baz'}}>Link</StateLink> * </RouteScope> * ) * } * ``` */ export declare const RouteScope: { (props: RouteScopeProps): React.JSX.Element displayName: string } /** * Props for the {@link RouteScope} component. * * @public */ export declare interface RouteScopeProps { /** * The scope for the nested routes. */ scope: string /** * Optionally disable scoping of search params * Scoped search params will be represented as scope[param]=value in the url * Disabling this will still scope search params based on any parent scope unless the parent scope also has disabled search params scoping * Caution: enabling this can cause conflicts with multiple plugins defining search params with the same name */ __unsafe_disableScopedSearchParams?: boolean /** * The content to display inside the route scope. */ children: ReactNode } /** * @public */ export declare interface RouteSegment { /** * The name of the segment. */ name: string /** * The type of the segment. * Can be either "dir" or "param". */ type: 'dir' | 'param' } /** * @public */ export declare interface RouteTransform<T> { /** * Converts a path string to a state object. */ toState: (value: string) => T /** * Converts a state object to a path string. */ toPath: (value: T) => string } /** * @public */ export declare type SearchParam = [key: string, value: string] /** * A component that creates a link that updates the URL state. * * @remarks * This component uses the {@link useStateLink} hook * to create a link that updates the URL state. * * @param props - Props to pass to the `StateLink` component. * See {@link StateLinkProps}. * * @public * * @example * ```tsx * function MyComponent() { * return <StateLink state={{foo: 'bar'}}>Link</StateLink> * } * ``` */ export declare const StateLink: ForwardRefExoticComponent< Omit<StateLinkProps & Omit<HTMLProps<HTMLAnchorElement>, 'href'>, 'ref'> & RefAttributes<HTMLAnchorElement> > /** * Props for the {@link StateLink} component. * * @public */ export declare interface StateLinkProps { /** * Whether to replace the current history entry instead of adding a new one. */ replace?: boolean /** * The state to associate with the link. */ state?: Record<string, unknown> /** * Whether to navigate to the index page of the app. */ toIndex?: boolean } /** * @internal */ export declare const STICKY_PARAMS: string[] /** * * Returns props for an anchor element that will trigger an intent when clicked. * * @example * ```tsx * const {onClick, href} = useIntentLink({ * intent: 'edit', * params: {id: 'foo'} * }) * * <a href={href} onClick={onClick}>Link to "foo" editor</a> * ``` * * @public * * @param options - Options to use for the link * {@link UseIntentLinkOptions} * * @returns - An object with `onClick` and `href` props to use for the link */ export declare function useIntentLink(options: UseIntentLinkOptions): { onClick: React.MouseEventHandler<HTMLElement> href: string } /** * @public */ export declare interface UseIntentLinkOptions { /** * The name of the intent to trigger. */ intent: string /** * An optional click event handler. */ onClick?: React.MouseEventHandler<HTMLElement> /** * Optional parameters to pass to the intent. See {@link IntentParameters} */ params?: IntentParameters /** * Whether to replace the current URL in the browser history. */ replace?: boolean /** * The target window or frame to open the link in. */ target?: string searchParams?: SearchParam[] } /** * Returns an object with an `onClick` function that can be used as a click handler for a link. * * @public * * @param options - An object containing the properties for the link. * See {@link UseLinkOptions} * * @returns An object with an `onClick` function. * * @example * ```tsx * const linkProps = useLink({ * href: 'https://www.sanity.io', * target: '_blank' * }) * * <a {...linkProps}>Link</a> * ``` */ export declare function useLink(options: UseLinkOptions): { onClick: React.MouseEventHandler<HTMLElement> } /** * @public */ export declare interface UseLinkOptions { /** * The URL that the link should navigate to. */ href?: string /** * The event handler function that should be called when the link is clicked. */ onClick?: React.MouseEventHandler<HTMLElement> /** * Whether the link should replace the current URL in the browser history. */ replace?: boolean /** * The target window or frame that the linked document will open in. */ target?: string } /** * Returns the router context value. * @public * * @returns The router context value. * {@link RouterContextValue} * @throws An error if the router context value is missing. * * @example * ```tsx * const router = useRouter() * ``` */ export declare function useRouter(): RouterContextValue /** * @public * * @param selector - A selector function that receives the router state and returns a value. See {@link RouterState} * * @returns The value returned by the selector function or RouterState. See {@link RouterState} * * @example * ```tsx * const {activeTool} = useRouterState(state => state.tool) * ``` */ export declare function useRouterState<R = RouterState>( selector: (routerState: RouterState) => R, ): R /** * @public * * @returns The router state. See {@link RouterState} * * @example * ```tsx * const routerState = useRouterState() * ``` */ export declare function useRouterState(): RouterState /** * @public * * @param options - Options to use for the link * {@link UseStateLinkOptions} * * @returns - An object with `onClick` and `href` props to use for the link * * @example * ```tsx * const {onClick, href} = useStateLink({state: {foo: 'bar'}}) * ``` */ export declare function useStateLink(options: UseStateLinkOptions): { onClick: MouseEventHandler<HTMLElement> href: string } /** * @public */ export declare interface UseStateLinkOptions { /** * The click event handler for the link. */ onClick?: MouseEventHandler<HTMLElement> /** * Whether to replace the current history entry instead of adding a new one. */ replace?: boolean /** * The state object to update when the link is clicked. */ state?: Record<string, unknown> /** * The target window or frame to open the linked document in. */ target?: string /** * Whether to navigate to the index page of the linked document. */ toIndex?: boolean } /** * A higher-order component that injects the router object into its child component. * * @internal * @deprecated - Use the `useRouter` hook instead. * * @returns The rendered component. * * @example * ```tsx * function MyComponent(props: {router: Router}) { * const {location} = props.router * const {pathname} = location * return <p>The current path is: {pathname}</p> * } * * function App() { * return ( * <Router> * <WithRouter> * {router => <MyComponent router={router} />} * </WithRouter> * </Router> * ) * } * ``` */ export declare const WithRouter: FunctionComponent<Omit<WithRouterProps, 'router'>> /** * A higher-order component that injects the `router` object from the `useRouter` hook * into the props of the wrapped component. * * @internal * @deprecated - Use the `useRouter` hook instead. * * @param Component - The component to wrap. * * @returns The wrapped component. * * @example * ```tsx * function MyComponent(props) { * return <div>{props.router.state.myParam}</div> * } * * export default withRouter(MyComponent) * ``` */ export declare function withRouter< Props extends { router: RouterContextValue }, >(Component: ComponentType<Props>): FunctionComponent<Omit<Props, 'router'>> /** * @internal * @deprecated - Use the `useRouter` hook instead. */ export declare interface WithRouterProps { /** * The `router` object from the `useRouter` hook. * {@link RouterContextValue} */ router: RouterContextValue /** * A function that renders the wrapped component with the `router` object as a parameter. */ children: (router: RouterContextValue) => React.JSX.Element } export {}