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
TypeScript
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 {}