attio 0.0.1-experimental.20241008.3 → 0.0.1-experimental.20241011
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client/components/action.d.ts +21 -1
- package/lib/client/components/combobox.d.ts +21 -0
- package/lib/client/components/multistep.d.ts +7 -0
- package/lib/client/components/row.d.ts +4 -1
- package/lib/client/components/section.d.ts +9 -1
- package/lib/client/components/text-block.d.ts +7 -1
- package/lib/client/forms/array.d.ts +6 -2
- package/lib/client/forms/index.d.ts +0 -2
- package/lib/client/forms/number.d.ts +21 -1
- package/lib/client/forms/path.d.ts +3 -7
- package/lib/client/forms/string.d.ts +23 -2
- package/lib/client/forms/value.d.ts +6 -0
- package/lib/client/hooks/index.d.ts +2 -1
- package/lib/client/hooks/use-async-cache.d.ts +51 -2
- package/lib/client/hooks/use-dialog.d.ts +59 -5
- package/lib/client/hooks/use-form.d.ts +177 -0
- package/lib/client/hooks/use-query.d.ts +46 -5
- package/lib/client/hooks/use-record.d.ts +6 -1
- package/lib/client/index.d.ts +1 -2
- package/lib/client/register-record-action.d.ts +19 -1
- package/lib/client/run-query.d.ts +49 -5
- package/lib/graphql/generate-operations.js +3 -1
- package/lib/machines/dev-machine.js +1 -10
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/schema.graphql +199 -230
- package/lib/client/forms/build.d.ts +0 -48
- package/lib/client/forms/connection.d.ts +0 -17
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Icon } from "../icon";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* An “action button” is a button that can appear in the Attio UI,
|
|
5
|
+
* typically on a record page.
|
|
6
|
+
*
|
|
7
|
+
* You must “register” the component that renders this component
|
|
8
|
+
* using `registerRecordAction()`.
|
|
5
9
|
*/
|
|
6
10
|
export declare function Action(props: {
|
|
11
|
+
/**
|
|
12
|
+
* A function to execute when the button is clicked (or tapped)
|
|
13
|
+
*/
|
|
7
14
|
onTrigger: () => void;
|
|
15
|
+
/**
|
|
16
|
+
* An icon to display in the button, either an `AttioIcon` or
|
|
17
|
+
* a string `.png` referencing a file in your app’s `assets`
|
|
18
|
+
* directory.
|
|
19
|
+
*
|
|
20
|
+
* If no `icon` prop is provided, it will default to your app’s icon.
|
|
21
|
+
*/
|
|
8
22
|
icon?: Icon;
|
|
23
|
+
/**
|
|
24
|
+
* Whether or not the button is disabled. Defaults to `false`.
|
|
25
|
+
*/
|
|
9
26
|
disabled?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The text content of the button.
|
|
29
|
+
*/
|
|
10
30
|
children: React.ReactNode;
|
|
11
31
|
}): React.JSX.Element;
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
export interface ComboboxOption {
|
|
2
|
+
/** The value that will be saved into your form data when this option is selected */
|
|
2
3
|
value: string;
|
|
4
|
+
/** The label the user will see for this option */
|
|
3
5
|
label: string;
|
|
6
|
+
/**
|
|
7
|
+
* An optional CSS color to display for this option
|
|
8
|
+
*
|
|
9
|
+
* It will be displayed in a little circle next to the label.
|
|
10
|
+
*/
|
|
4
11
|
color?: string;
|
|
5
12
|
}
|
|
6
13
|
export interface ComboboxOptionsProvider {
|
|
14
|
+
/**
|
|
15
|
+
* An async function that, given an option value, returns the label and color of the option.
|
|
16
|
+
*
|
|
17
|
+
* @param value - The value of the option
|
|
18
|
+
* @returns - The label and color of the option
|
|
19
|
+
*/
|
|
7
20
|
getOption: (value: string) => Promise<Omit<ComboboxOption, "value">>;
|
|
21
|
+
/**
|
|
22
|
+
* An async function that, given a search query, returns a list of "matching" combobox options.
|
|
23
|
+
*
|
|
24
|
+
* What "matching" means is up to the developer.
|
|
25
|
+
*
|
|
26
|
+
* @param query - The search query
|
|
27
|
+
* @returns - A list of combobox options
|
|
28
|
+
*/
|
|
8
29
|
search: (query: string) => Promise<Array<ComboboxOption>>;
|
|
9
30
|
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* A step in a multi-step component.
|
|
4
|
+
*
|
|
5
|
+
* @deprecated This is not ready for use yet.
|
|
6
|
+
*/
|
|
2
7
|
export interface Step {
|
|
3
8
|
title: string;
|
|
4
9
|
content: React.ReactNode;
|
|
@@ -6,6 +11,8 @@ export interface Step {
|
|
|
6
11
|
}
|
|
7
12
|
/**
|
|
8
13
|
* A multi-step component
|
|
14
|
+
*
|
|
15
|
+
* @deprecated This is not ready for use yet.
|
|
9
16
|
*/
|
|
10
17
|
export declare function Multistep(props: {
|
|
11
18
|
initialStep?: number;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
/**
|
|
3
|
-
* A component for laying children
|
|
3
|
+
* A component for laying out children horizontally.
|
|
4
|
+
*
|
|
5
|
+
* On the web, it can fit up to three children horizontally,
|
|
6
|
+
* and on mobile, all children will be presented vertically.
|
|
4
7
|
*/
|
|
5
8
|
export declare function Row(props: {
|
|
6
9
|
children: React.ReactNode;
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
/**
|
|
3
|
-
* A section of a page
|
|
3
|
+
* A section of a page with a title.
|
|
4
4
|
*/
|
|
5
5
|
export declare function Section(props: {
|
|
6
|
+
/**
|
|
7
|
+
* The title of the section.
|
|
8
|
+
*
|
|
9
|
+
* It will be displayed in a stronger font than the content of the section.
|
|
10
|
+
*/
|
|
6
11
|
title: string;
|
|
12
|
+
/**
|
|
13
|
+
* The content of the section, either text or other components.
|
|
14
|
+
*/
|
|
7
15
|
children?: React.ReactNode;
|
|
8
16
|
}): React.JSX.Element;
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
/**
|
|
3
|
-
* A text block
|
|
3
|
+
* A text block, whose content can optionally be aligned.
|
|
4
4
|
*/
|
|
5
5
|
export declare function TextBlock(props: {
|
|
6
|
+
/**
|
|
7
|
+
* How to align the content of the text block.
|
|
8
|
+
*/
|
|
6
9
|
align?: "flex-start" | "flex-end" | "center" | "stretch" | "baseline" | "initial" | "inherit";
|
|
10
|
+
/**
|
|
11
|
+
* The content of the text block. Usually text, but can also be other components.
|
|
12
|
+
*/
|
|
7
13
|
children: React.ReactNode;
|
|
8
14
|
}): React.JSX.Element;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
import { FormValue } from "./value";
|
|
1
2
|
/**
|
|
2
3
|
* An array form value.
|
|
3
4
|
*/
|
|
4
|
-
export interface FormArray<T> {
|
|
5
|
+
export interface FormArray<T> extends FormValue {
|
|
5
6
|
type: "array";
|
|
6
7
|
elementType: T;
|
|
8
|
+
/**
|
|
9
|
+
* Make this array optional, i.e. allow `null` or `undefined` values.
|
|
10
|
+
*/
|
|
7
11
|
optional(): FormArray<T>;
|
|
8
12
|
}
|
|
9
13
|
/**
|
|
10
14
|
* Create a new array form value.
|
|
11
15
|
*/
|
|
12
|
-
export declare function array<T
|
|
16
|
+
export declare function array<T extends FormValue | Record<string, FormValue>>(elementType: T): FormArray<T>;
|
|
@@ -1,11 +1,31 @@
|
|
|
1
|
+
import { FormValue } from "./value";
|
|
1
2
|
/**
|
|
2
3
|
* A number form value.
|
|
3
4
|
*/
|
|
4
|
-
export interface FormNumber {
|
|
5
|
+
export interface FormNumber extends FormValue {
|
|
5
6
|
type: "number";
|
|
7
|
+
/**
|
|
8
|
+
* Whether this number is optional, i.e. allows `null` or `undefined` values.
|
|
9
|
+
*/
|
|
6
10
|
isOptional: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Make this number optional, i.e. allow `null` or `undefined` values.
|
|
13
|
+
*/
|
|
14
|
+
optional(): FormNumber;
|
|
15
|
+
/**
|
|
16
|
+
* Set the default value of this number. The default value will be returned if the user
|
|
17
|
+
* doesn't provide a value.
|
|
18
|
+
*
|
|
19
|
+
* NOTE that this is not the same as an initial value!
|
|
20
|
+
*/
|
|
7
21
|
default(value: number): FormNumber;
|
|
22
|
+
/**
|
|
23
|
+
* Set the maximum value of this number.
|
|
24
|
+
*/
|
|
8
25
|
max(max: number): FormNumber;
|
|
26
|
+
/**
|
|
27
|
+
* Set the minimum value of this number.
|
|
28
|
+
*/
|
|
9
29
|
min(min: number): FormNumber;
|
|
10
30
|
}
|
|
11
31
|
/**
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Prettify } from "../util/prettify";
|
|
2
2
|
import { FormArray } from "./array";
|
|
3
|
-
import { FormConnection, Connection } from "./connection";
|
|
4
3
|
import { FormNumber } from "./number";
|
|
5
4
|
import { FormString } from "./string";
|
|
6
5
|
type Assert<TCat, TAnimal> = TCat extends TAnimal ? TCat : never;
|
|
7
6
|
type Join<A extends string | number | null, B extends string | number> = A extends null ? B : `${A}.${B}`;
|
|
8
|
-
export type ValueType = "string" | "number" | "
|
|
9
|
-
export type SchemaNode = FormString | FormNumber |
|
|
7
|
+
export type ValueType = "string" | "number" | "connection" | "array";
|
|
8
|
+
export type SchemaNode = FormString | FormNumber | FormArray<any> | {
|
|
10
9
|
type: "object";
|
|
11
10
|
};
|
|
12
11
|
type PathWithTypeRecursive<TState, TRoot extends string | number | null> = TState extends FormString ? {
|
|
@@ -15,9 +14,6 @@ type PathWithTypeRecursive<TState, TRoot extends string | number | null> = TStat
|
|
|
15
14
|
} : TState extends FormNumber ? {
|
|
16
15
|
path: TRoot;
|
|
17
16
|
type: "number";
|
|
18
|
-
} : TState extends FormConnection ? {
|
|
19
|
-
path: TRoot;
|
|
20
|
-
type: "connection";
|
|
21
17
|
} : TState extends FormArray<infer TElement> ? {
|
|
22
18
|
path: TRoot;
|
|
23
19
|
type: "array";
|
|
@@ -32,7 +28,7 @@ export type Path<TState> = PathWithType<TState>["path"];
|
|
|
32
28
|
export type PathTo<TState, TType extends ValueType> = Extract<PathWithType<TState>, {
|
|
33
29
|
type: TType;
|
|
34
30
|
}>["path"];
|
|
35
|
-
export type ValueOf<TState> = TState extends FormString ? string : TState extends FormNumber ? number : TState extends
|
|
31
|
+
export type ValueOf<TState> = TState extends FormString ? string : TState extends FormNumber ? number : TState extends FormArray<infer TElement> ? Array<ValueOf<TElement>> : {
|
|
36
32
|
[K in keyof TState]: K extends string ? ValueOf<TState[K]> : never;
|
|
37
33
|
};
|
|
38
34
|
export {};
|
|
@@ -1,13 +1,34 @@
|
|
|
1
|
+
import { FormValue } from "./value";
|
|
1
2
|
/**
|
|
2
3
|
* A string form value.
|
|
3
4
|
*/
|
|
4
|
-
export interface FormString {
|
|
5
|
+
export interface FormString extends FormValue {
|
|
5
6
|
type: "string";
|
|
7
|
+
/**
|
|
8
|
+
* Whether or not this string is multiline.
|
|
9
|
+
*
|
|
10
|
+
* Multiline strings are rendered as textarea fields.
|
|
11
|
+
*/
|
|
6
12
|
isMultiline: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Whether this string is optional, i.e. allows `null` or `undefined` values.
|
|
15
|
+
*/
|
|
7
16
|
isOptional: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Set the default value of this string. The default value will be returned if the user
|
|
19
|
+
* doesn't provide a value.
|
|
20
|
+
*
|
|
21
|
+
* NOTE that this is not the same as an initial value!
|
|
22
|
+
*/
|
|
8
23
|
default(value: string): FormString;
|
|
9
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Make this string optional, i.e. allow `null` or `undefined` values.
|
|
26
|
+
*/
|
|
10
27
|
optional(): FormString;
|
|
28
|
+
/**
|
|
29
|
+
* Make this string multiline, i.e. render as textarea field.
|
|
30
|
+
*/
|
|
31
|
+
multiline(): FormString;
|
|
11
32
|
}
|
|
12
33
|
/**
|
|
13
34
|
* Create a new string form value.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { useDialog } from "./use-dialog.js";
|
|
2
1
|
export { useAsyncCache, AsyncCacheConfig, AsyncFunction } from "./use-async-cache.js";
|
|
2
|
+
export { useDialog } from "./use-dialog.js";
|
|
3
|
+
export { useForm, FormApi, FormSchema } from "./use-form.js";
|
|
3
4
|
export { useQuery } from "./use-query.js";
|
|
4
5
|
export { useRecord } from "./use-record.js";
|
|
@@ -12,8 +12,57 @@ export interface AsyncCacheConfig {
|
|
|
12
12
|
[K: string]: AsyncFunction<Array<any>, any> | [AsyncFunction<Array<any>, any>, ...Array<any>];
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* A hook that returns, and caches, the results of calling
|
|
16
|
-
* typically to load data.
|
|
15
|
+
* A hook that returns, and caches, the results of calling one or more async functions,
|
|
16
|
+
* typically to load data from a third party via server functions.
|
|
17
|
+
*
|
|
18
|
+
* The component it is used in will suspend until ALL async functions have resolved.
|
|
19
|
+
*
|
|
20
|
+
* ## EXAMPLE USAGE
|
|
21
|
+
*
|
|
22
|
+
* ----
|
|
23
|
+
* ```ts
|
|
24
|
+
* // load-widgets.server.ts
|
|
25
|
+
* export default async function loadWidgets() : Promise<Array<Widget>> {
|
|
26
|
+
* // fetch widgets from somewhere
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
* ----
|
|
30
|
+
* ```ts
|
|
31
|
+
* // load-sprockets.server.ts
|
|
32
|
+
* export default async function loadSprockets(
|
|
33
|
+
* material: Material,
|
|
34
|
+
* max?: number
|
|
35
|
+
* ): Promise<Array<Sprocket>> {
|
|
36
|
+
* // fetch sprockets from somewhere
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
* ----
|
|
40
|
+
* ```ts
|
|
41
|
+
* import { useAsyncCache } from "attio/client"
|
|
42
|
+
*
|
|
43
|
+
* import loadWidgets from "./load-widgets.server.ts"
|
|
44
|
+
* import loadSprockets from "./load-sprockets.server.ts"
|
|
45
|
+
*
|
|
46
|
+
* ...
|
|
47
|
+
*
|
|
48
|
+
* // inside component:
|
|
49
|
+
*
|
|
50
|
+
* const results = useAsyncCache({
|
|
51
|
+
* // loadWidgets takes zero parameters and can thus be called without an array
|
|
52
|
+
* widgets: loadWidgets,
|
|
53
|
+
* // loadSprockets takes a `material` parameter, so we call it like this
|
|
54
|
+
* ironSprockets: [loadSprockets, "iron"],
|
|
55
|
+
* copperSprockets: [loadSprockets, "copper", 42],
|
|
56
|
+
* })
|
|
57
|
+
*
|
|
58
|
+
* const { widgets, ironSprockets, copperSprockets } = results.values
|
|
59
|
+
*
|
|
60
|
+
* ...
|
|
61
|
+
*
|
|
62
|
+
* // inside an event handler, perhaps, to refetch _only_ the iron sprockets
|
|
63
|
+
* results.invalidate("ironSprockets")
|
|
64
|
+
* ```
|
|
65
|
+
* ----
|
|
17
66
|
*/
|
|
18
67
|
export declare function useAsyncCache<Config extends AsyncCacheConfig>(config: Config): {
|
|
19
68
|
values: {
|
|
@@ -1,17 +1,71 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Dialog component
|
|
4
|
+
*
|
|
5
|
+
* IMPORTANT: The <Dialog/> component should _always_ be rendered in your app.
|
|
6
|
+
* Do not render it conditionally.
|
|
7
|
+
*/
|
|
8
|
+
interface Dialog extends React.FC<{
|
|
9
|
+
/**
|
|
10
|
+
* A required title for the dialog.
|
|
11
|
+
*/
|
|
12
|
+
title: string;
|
|
13
|
+
/**
|
|
14
|
+
* An optional callback that will be called when the dialog is closed.
|
|
15
|
+
*/
|
|
16
|
+
onClose?: () => void;
|
|
17
|
+
/**
|
|
18
|
+
* The content of the dialog.
|
|
19
|
+
*/
|
|
20
|
+
children: React.ReactNode;
|
|
21
|
+
}> {
|
|
22
|
+
}
|
|
1
23
|
/**
|
|
2
24
|
* This hook allows you to create a modal dialog.
|
|
3
25
|
*
|
|
26
|
+
* ## EXAMPLE USAGE
|
|
27
|
+
*
|
|
28
|
+
* ----
|
|
29
|
+
* ```tsx
|
|
30
|
+
* import { useDialog } from "attio/client"
|
|
31
|
+
*
|
|
32
|
+
* ...
|
|
33
|
+
*
|
|
34
|
+
* // inside component:
|
|
35
|
+
* const dialog = useDialog()
|
|
36
|
+
*
|
|
37
|
+
* return (
|
|
38
|
+
* <>
|
|
39
|
+
* <Action onTrigger={() => dialog.open()}>Do Stuff</Action>
|
|
40
|
+
* <dialog.Dialog>
|
|
41
|
+
* Here is my useful UI
|
|
42
|
+
* </dialog.Dialog>
|
|
43
|
+
* </>
|
|
44
|
+
* )
|
|
45
|
+
* ```
|
|
46
|
+
* ----
|
|
47
|
+
*
|
|
4
48
|
* @returns An object with the following properties:
|
|
5
49
|
* - `Dialog`: A React component that you should render with the dialog contents as its children.
|
|
6
50
|
* - `open`: Opens the rendered dialog.
|
|
7
51
|
* - `close`: Closes the rendered dialog.
|
|
8
52
|
*/
|
|
9
53
|
export declare function useDialog(): {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
54
|
+
/**
|
|
55
|
+
* The dialog component to render.
|
|
56
|
+
*
|
|
57
|
+
* IMPORTANT: The <Dialog/> component should _always_ be rendered in your app.
|
|
58
|
+
* Do not render it conditionally.
|
|
59
|
+
*/
|
|
60
|
+
Dialog: Dialog;
|
|
61
|
+
/**
|
|
62
|
+
* A function to imperatively open the dialog. Often called via an
|
|
63
|
+
* `onTrigger` prop on an `<Action/>` button.
|
|
64
|
+
*/
|
|
15
65
|
open: () => void;
|
|
66
|
+
/**
|
|
67
|
+
* A function to imperatively close the dialog.
|
|
68
|
+
*/
|
|
16
69
|
close: () => void;
|
|
17
70
|
};
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ComboboxOption, ComboboxOptionsProvider } from "../components/combobox";
|
|
3
|
+
import { PathTo, ValueOf } from "../forms/path";
|
|
4
|
+
import { FormValue } from "../forms/value";
|
|
5
|
+
export type FormSchema = Record<string, FormValue>;
|
|
6
|
+
/**
|
|
7
|
+
* A <Form> component that must wrap all the fields and provide a submit handler.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <Form onSubmit={(values) => {
|
|
12
|
+
* console.log(values)
|
|
13
|
+
* }}>
|
|
14
|
+
* <Input label="Name" data="name" />
|
|
15
|
+
* <SubmitButton label="Submit" />
|
|
16
|
+
* </Form>
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
type Form<TSchema extends FormSchema> = React.FC<{
|
|
20
|
+
/** The contents of the form, including layout and input components */
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
/**
|
|
23
|
+
* The function to call when the form is submitted.
|
|
24
|
+
*
|
|
25
|
+
* `onSubmit` will NOT be called if there are validation errors.
|
|
26
|
+
*/
|
|
27
|
+
onSubmit: (values: ValueOf<TSchema>) => void;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* A text, number, or connection input field.
|
|
31
|
+
*/
|
|
32
|
+
type Input<TSchema extends FormSchema> = React.FC<{
|
|
33
|
+
/** The label of the input field */
|
|
34
|
+
label: string;
|
|
35
|
+
/** The path to the value of the input field, e.g. `"name"` or `"address.street"` */
|
|
36
|
+
data: PathTo<TSchema, "string" | "number" | "connection">;
|
|
37
|
+
/** The optional placeholder text of the input field */
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
/** Whether the input field is disabled */
|
|
40
|
+
disabled?: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* A combobox input field.
|
|
44
|
+
*/
|
|
45
|
+
type Combobox<TSchema extends FormSchema> = React.FC<{
|
|
46
|
+
/** The label of the combobox field */
|
|
47
|
+
label: string;
|
|
48
|
+
/** The path to the value of the combobox field, e.g. `"mode"` or `"shipping.method"` */
|
|
49
|
+
data: PathTo<TSchema, "string">;
|
|
50
|
+
/**
|
|
51
|
+
* The options of the combobox field
|
|
52
|
+
*
|
|
53
|
+
* Either an array of options, or a provider that asynchronously fetches options.
|
|
54
|
+
*/
|
|
55
|
+
options: Array<ComboboxOption> | ComboboxOptionsProvider;
|
|
56
|
+
/** The optional placeholder text of the combobox field */
|
|
57
|
+
placeholder?: string;
|
|
58
|
+
/** Whether the combobox field is disabled */
|
|
59
|
+
disabled?: boolean;
|
|
60
|
+
}>;
|
|
61
|
+
/**
|
|
62
|
+
* A component used to render a collection of inputs.
|
|
63
|
+
*/
|
|
64
|
+
type Collection<TSchema extends FormSchema, TPath extends PathTo<TSchema, "array">> = React.FC<{
|
|
65
|
+
/** The label of the collection field */
|
|
66
|
+
label: string;
|
|
67
|
+
/** The path to the value of the collection field, e.g. `"items"` or `"shipping.items"` */
|
|
68
|
+
data: TPath;
|
|
69
|
+
/**
|
|
70
|
+
* A render prop that receives the path and index of one of the items and renders
|
|
71
|
+
* the inputs for that item
|
|
72
|
+
*/
|
|
73
|
+
children: (args: {
|
|
74
|
+
path: `${TPath}.${number}`;
|
|
75
|
+
index: number;
|
|
76
|
+
}) => React.ReactNode;
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* A component used to group inputs in a collection together
|
|
80
|
+
*/
|
|
81
|
+
type CollectionItem = React.FC<{
|
|
82
|
+
/** The label of the collection item */
|
|
83
|
+
label: string;
|
|
84
|
+
/** The inputs of the collection item */
|
|
85
|
+
children: React.ReactNode;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* A submit button for the form.
|
|
89
|
+
*
|
|
90
|
+
* If the form is rendered inside a dialog, the submit button will be placed at the bottom of the dialog.
|
|
91
|
+
*/
|
|
92
|
+
type SubmitButton = React.FC<{
|
|
93
|
+
/** The label of the submit button */
|
|
94
|
+
label: string;
|
|
95
|
+
/**
|
|
96
|
+
* Whether the submit button is disabled
|
|
97
|
+
*
|
|
98
|
+
* It will automatically become disabled while the form is submitting.
|
|
99
|
+
* You do not need to manage that state.
|
|
100
|
+
*/
|
|
101
|
+
disabled?: boolean;
|
|
102
|
+
}>;
|
|
103
|
+
interface WithStateProps<TSchema extends FormSchema, TValues extends boolean = false, TSubmitting extends boolean = false, TErrors extends boolean = false> {
|
|
104
|
+
values?: TValues;
|
|
105
|
+
submitting?: TSubmitting;
|
|
106
|
+
errors?: TErrors;
|
|
107
|
+
children: (state: {
|
|
108
|
+
values: TValues extends true ? ValueOf<TSchema> : never;
|
|
109
|
+
submitting: TSubmitting extends true ? boolean : never;
|
|
110
|
+
errors: TErrors extends true ? Record<string, string> : never;
|
|
111
|
+
}) => React.ReactNode;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* A component that provides the form state via a render prop.
|
|
115
|
+
*
|
|
116
|
+
* You may specifically request various parts of form state, such as
|
|
117
|
+
* `values`, `submitting`, and `errors`. This component will rerender
|
|
118
|
+
* whenever any of the values requested change.
|
|
119
|
+
*/
|
|
120
|
+
interface WithState<TSchema extends FormSchema> {
|
|
121
|
+
(props: WithStateProps<TSchema, true>): React.ReactElement;
|
|
122
|
+
(props: WithStateProps<TSchema, boolean, true>): React.ReactElement;
|
|
123
|
+
(props: WithStateProps<TSchema, boolean, boolean, true>): React.ReactElement;
|
|
124
|
+
<T extends WithStateProps<TSchema>>(props: T): React.ReactElement;
|
|
125
|
+
}
|
|
126
|
+
export interface FormApi<TSchema extends FormSchema> {
|
|
127
|
+
/**
|
|
128
|
+
* Submits the form.
|
|
129
|
+
*
|
|
130
|
+
* This will validate the form and call the `onSubmit` handler.
|
|
131
|
+
*/
|
|
132
|
+
submit: () => void;
|
|
133
|
+
/**
|
|
134
|
+
* The <Form> component to wrap the fields of this form and provide a submit handler.
|
|
135
|
+
*/
|
|
136
|
+
Form: Form<TSchema>;
|
|
137
|
+
/**
|
|
138
|
+
* An input field for a string, number, or connection.
|
|
139
|
+
*/
|
|
140
|
+
Input: Input<TSchema>;
|
|
141
|
+
/**
|
|
142
|
+
* A combobox input field.
|
|
143
|
+
*/
|
|
144
|
+
Combobox: Combobox<TSchema>;
|
|
145
|
+
/**
|
|
146
|
+
* A component used to render a collection of inputs.
|
|
147
|
+
*/
|
|
148
|
+
Collection: Collection<TSchema, any>;
|
|
149
|
+
/**
|
|
150
|
+
* A component used to group inputs in a collection together.
|
|
151
|
+
*/
|
|
152
|
+
CollectionItem: CollectionItem;
|
|
153
|
+
/**
|
|
154
|
+
* A submit button for the form.
|
|
155
|
+
*/
|
|
156
|
+
SubmitButton: SubmitButton;
|
|
157
|
+
/**
|
|
158
|
+
* A component that provides the form state via a render prop.
|
|
159
|
+
*/
|
|
160
|
+
WithState: WithState<TSchema>;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Creates a form API for a given schema and initial values.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```tsx
|
|
167
|
+
* const api = useForm({
|
|
168
|
+
* name: Forms.string(),
|
|
169
|
+
* age: Forms.number(),
|
|
170
|
+
* }, {
|
|
171
|
+
* name: "John",
|
|
172
|
+
* age: 30,
|
|
173
|
+
* });
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export declare function useForm<TSchema extends FormSchema>(schema: TSchema, initialValues: Partial<ValueOf<TSchema>>): FormApi<TSchema>;
|
|
177
|
+
export {};
|
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
import { Query } from "../run-query";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
/**
|
|
3
|
+
* A hook that runs a GraphQL query and returns the result.
|
|
4
|
+
*
|
|
5
|
+
* Your component will suspend until the query completes.
|
|
6
|
+
*
|
|
7
|
+
* If you import the query from a `.graphql` file, and run `attio dev`,
|
|
8
|
+
* your query variables and result will be strongly typed.
|
|
9
|
+
*
|
|
10
|
+
* ## EXAMPLE USAGE
|
|
11
|
+
*
|
|
12
|
+
* ----
|
|
13
|
+
* ```graphql
|
|
14
|
+
* # get-person.graphql
|
|
15
|
+
* query getPerson($id: String!) {
|
|
16
|
+
* workspace {
|
|
17
|
+
* person(id: $id) {
|
|
18
|
+
* name {
|
|
19
|
+
* first
|
|
20
|
+
* last
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
* ----
|
|
27
|
+
* ```tsx
|
|
28
|
+
* // Component.tsx
|
|
29
|
+
* import { useQuery, useRecord } from "attio/client"
|
|
30
|
+
* import getPersonQuery from "./get-person.graphql"
|
|
31
|
+
*
|
|
32
|
+
* ...
|
|
33
|
+
*
|
|
34
|
+
* // in component:
|
|
35
|
+
* const { recordId } = useRecord()
|
|
36
|
+
* const result = useQuery(getPersonQuery, { id: recordId })
|
|
37
|
+
*
|
|
38
|
+
* const firstName : string | null = result.workspace?.person?.name?.first
|
|
39
|
+
* const lastName : string | null = result.workspace?.person?.name?.last
|
|
40
|
+
* ```
|
|
41
|
+
* ----
|
|
42
|
+
*
|
|
43
|
+
* @param query - The GraphQL query to run.
|
|
44
|
+
* @param variableValues - The variables to pass to the query.
|
|
45
|
+
* @returns The result of the query.
|
|
46
|
+
*/
|
|
47
|
+
export declare function useQuery<Variables extends Record<string, any> | never, Result>(query: Query<Variables, Result>, variableValues?: Variables extends never ? never : Variables): Result;
|
|
@@ -3,7 +3,12 @@ import { ObjectSlug } from "../object-slug.js";
|
|
|
3
3
|
* Get information about the current record.
|
|
4
4
|
*/
|
|
5
5
|
export declare function useRecord(): {
|
|
6
|
+
/**
|
|
7
|
+
* The ID of the current record.
|
|
8
|
+
*/
|
|
6
9
|
recordId: string;
|
|
10
|
+
/**
|
|
11
|
+
* The object type of the current record.
|
|
12
|
+
*/
|
|
7
13
|
object: ObjectSlug;
|
|
8
|
-
epithet: string;
|
|
9
14
|
};
|
package/lib/client/index.d.ts
CHANGED
|
@@ -5,8 +5,7 @@ export * as Forms from "./forms/index.js";
|
|
|
5
5
|
export { FormArray } from "./forms/array.js";
|
|
6
6
|
export { FormNumber } from "./forms/number.js";
|
|
7
7
|
export { FormString } from "./forms/string.js";
|
|
8
|
-
export {
|
|
8
|
+
export { FormValue } from "./forms/value.js";
|
|
9
9
|
export * from "./forms/path.js";
|
|
10
|
-
export { Form } from "./forms/build.js";
|
|
11
10
|
export { Icon, AttioIcon } from "./icon.js";
|
|
12
11
|
export { registerRecordAction } from "./register-record-action.js";
|