@postrun/react 0.1.0
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/LICENSE +202 -0
- package/README.md +56 -0
- package/dist/index.cjs +1325 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1237 -0
- package/dist/index.d.ts +1237 -0
- package/dist/index.js +1284 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1237 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
3
|
+
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
4
|
+
import { QueryClient, QueryKey } from '@tanstack/react-query';
|
|
5
|
+
import { PostrunClient, ListProfilesQuery, ConnectablePlatform, MediaTarget, MediaKind, CreateMediaInput, MediaResource, ListPostsQuery, ComposePostInput, XPostVariant, LinkedInPostVariant } from '@postrun/js';
|
|
6
|
+
import { TwitterComponents } from 'react-tweet';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The value every hook and component reads from context: the typed SDK client
|
|
10
|
+
* plus a private TanStack `QueryClient` that powers caching, dedup, and
|
|
11
|
+
* revalidation. Hooks pass this `queryClient` explicitly to `useQuery` /
|
|
12
|
+
* `useMutation`, so it stays fully isolated from any QueryClient the host app
|
|
13
|
+
* runs of its own — no `QueryClientProvider` setup required from the customer.
|
|
14
|
+
*/
|
|
15
|
+
interface PostrunContextValue {
|
|
16
|
+
client: PostrunClient;
|
|
17
|
+
queryClient: QueryClient;
|
|
18
|
+
}
|
|
19
|
+
interface PostrunProviderProps {
|
|
20
|
+
/**
|
|
21
|
+
* Returns a valid short-lived scoped token. The host app's backend mints it
|
|
22
|
+
* from a secret `pr_` key (`POST /v1/tokens`); the secret never reaches the
|
|
23
|
+
* browser. Called per request — cache and refresh before `exp` inside here.
|
|
24
|
+
*/
|
|
25
|
+
getToken: () => string | Promise<string>;
|
|
26
|
+
/** Override the API base URL (defaults to the production gateway). */
|
|
27
|
+
baseUrl?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Bring your own TanStack `QueryClient` (advanced: shared DevTools, custom
|
|
30
|
+
* defaults, tests). Omit it and a private, isolated one is created for you.
|
|
31
|
+
*/
|
|
32
|
+
queryClient?: QueryClient;
|
|
33
|
+
children: ReactNode;
|
|
34
|
+
}
|
|
35
|
+
declare function PostrunProvider({ getToken, baseUrl, queryClient, children, }: PostrunProviderProps): react.FunctionComponentElement<react.ProviderProps<PostrunContextValue | null>>;
|
|
36
|
+
/** Access the configured Postrun client. Throws if used outside a provider. */
|
|
37
|
+
declare function usePostrun(): PostrunContextValue;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The offset-pagination envelope every Postrun list endpoint returns. The helper
|
|
41
|
+
* only needs these fields; the concrete page type comes from the SDK response
|
|
42
|
+
* (e.g. `PostList`), which satisfies this structurally — nothing is redeclared.
|
|
43
|
+
*/
|
|
44
|
+
interface PageEnvelope<TItem> {
|
|
45
|
+
data: TItem[];
|
|
46
|
+
total: number;
|
|
47
|
+
offset: number;
|
|
48
|
+
has_more: boolean;
|
|
49
|
+
}
|
|
50
|
+
/** A flattened, append-style ("load more") view over a paginated list endpoint. */
|
|
51
|
+
interface InfiniteList<TItem> {
|
|
52
|
+
/** Every item loaded so far, flattened across all fetched pages. */
|
|
53
|
+
items: TItem[];
|
|
54
|
+
/** Total items matching the filter (from the first page's envelope). */
|
|
55
|
+
total: number;
|
|
56
|
+
/** Fetch the next page and append it. No-op once `hasMore` is false. */
|
|
57
|
+
loadMore: () => void;
|
|
58
|
+
/** Whether another page exists beyond what's loaded. */
|
|
59
|
+
hasMore: boolean;
|
|
60
|
+
/** The first page is loading (no items yet). */
|
|
61
|
+
isLoading: boolean;
|
|
62
|
+
/** A `loadMore()` is in flight (items are already shown). */
|
|
63
|
+
isLoadingMore: boolean;
|
|
64
|
+
/** The last error, or null. Narrow with `instanceof PostrunError`. */
|
|
65
|
+
error: Error | null;
|
|
66
|
+
/** Refetch from the first page (re-runs every loaded page). */
|
|
67
|
+
refetch: () => void;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Turn an offset-paginated Postrun list endpoint into a clean append-style
|
|
71
|
+
* `{ items, loadMore, hasMore, … }` surface — the "Load more" / infinite-scroll
|
|
72
|
+
* shape a feed or calendar wants.
|
|
73
|
+
*
|
|
74
|
+
* Built on TanStack `useInfiniteQuery`, so page accumulation is its job and never
|
|
75
|
+
* hand-rolled. The next offset is read from the envelope itself
|
|
76
|
+
* (`offset + data.length`), so it stays correct regardless of page size.
|
|
77
|
+
* `fetchPage` supplies the resource-specific SDK call; the page type is inferred
|
|
78
|
+
* from its return, so item types are derived, never redeclared.
|
|
79
|
+
*/
|
|
80
|
+
declare function useInfiniteList<TItem>(args: {
|
|
81
|
+
queryKey: QueryKey;
|
|
82
|
+
fetchPage: (page: {
|
|
83
|
+
limit: number;
|
|
84
|
+
offset: number;
|
|
85
|
+
}) => Promise<PageEnvelope<TItem>>;
|
|
86
|
+
/** Items per page (default 20, the API's own default). */
|
|
87
|
+
limit?: number;
|
|
88
|
+
enabled?: boolean;
|
|
89
|
+
}): InfiniteList<TItem>;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* List the account's profiles (client/brand workspaces), filtered and paginated.
|
|
93
|
+
* `data` is the typed `ProfileList` envelope — inferred straight from the SDK
|
|
94
|
+
* call, never hand-typed. Caching, dedup, and revalidation come from the
|
|
95
|
+
* provider's private QueryClient.
|
|
96
|
+
*/
|
|
97
|
+
declare function useProfiles(query?: ListProfilesQuery): _tanstack_react_query.UseQueryResult<NoInfer<{
|
|
98
|
+
object: "list";
|
|
99
|
+
data: Array<{
|
|
100
|
+
id: string;
|
|
101
|
+
name: string;
|
|
102
|
+
description: string | null;
|
|
103
|
+
external_id: string | null;
|
|
104
|
+
metadata: {
|
|
105
|
+
[key: string]: string | number | boolean;
|
|
106
|
+
};
|
|
107
|
+
created_at: string | null;
|
|
108
|
+
updated_at: string | null;
|
|
109
|
+
}>;
|
|
110
|
+
total: number;
|
|
111
|
+
limit: number;
|
|
112
|
+
offset: number;
|
|
113
|
+
has_more: boolean;
|
|
114
|
+
}>, Error>;
|
|
115
|
+
/**
|
|
116
|
+
* List profiles with append-style ("load more") pagination. Returns
|
|
117
|
+
* `{ items, loadMore, hasMore, isLoading, isLoadingMore, total }`: render
|
|
118
|
+
* `items`, call `loadMore()` while `hasMore`. `pageSize` defaults to 20. Filters
|
|
119
|
+
* match `useProfiles` minus paging, which the hook owns. Shares list-cache
|
|
120
|
+
* invalidation with the other profile hooks.
|
|
121
|
+
*/
|
|
122
|
+
declare function useProfilesInfinite(filters?: Omit<ListProfilesQuery, 'limit' | 'offset'>, options?: {
|
|
123
|
+
pageSize?: number;
|
|
124
|
+
}): InfiniteList<{
|
|
125
|
+
id: string;
|
|
126
|
+
name: string;
|
|
127
|
+
description: string | null;
|
|
128
|
+
external_id: string | null;
|
|
129
|
+
metadata: {
|
|
130
|
+
[key: string]: string | number | boolean;
|
|
131
|
+
};
|
|
132
|
+
created_at: string | null;
|
|
133
|
+
updated_at: string | null;
|
|
134
|
+
}>;
|
|
135
|
+
/** Retrieve a single profile by id. Disabled until an id is provided. */
|
|
136
|
+
declare function useProfile(id: string): _tanstack_react_query.UseQueryResult<NoInfer<{
|
|
137
|
+
id: string;
|
|
138
|
+
name: string;
|
|
139
|
+
description: string | null;
|
|
140
|
+
external_id: string | null;
|
|
141
|
+
metadata: {
|
|
142
|
+
[key: string]: string | number | boolean;
|
|
143
|
+
};
|
|
144
|
+
created_at: string | null;
|
|
145
|
+
updated_at: string | null;
|
|
146
|
+
}>, Error>;
|
|
147
|
+
/** Create a profile; on success the profile lists are refetched. */
|
|
148
|
+
declare function useCreateProfile(): _tanstack_react_query.UseMutationResult<{
|
|
149
|
+
id: string;
|
|
150
|
+
name: string;
|
|
151
|
+
description: string | null;
|
|
152
|
+
external_id: string | null;
|
|
153
|
+
metadata: {
|
|
154
|
+
[key: string]: string | number | boolean;
|
|
155
|
+
};
|
|
156
|
+
created_at: string | null;
|
|
157
|
+
updated_at: string | null;
|
|
158
|
+
}, Error, {
|
|
159
|
+
name: string;
|
|
160
|
+
description?: string;
|
|
161
|
+
external_id?: string;
|
|
162
|
+
metadata?: {
|
|
163
|
+
[key: string]: string | number | boolean;
|
|
164
|
+
};
|
|
165
|
+
}, unknown>;
|
|
166
|
+
/** Update a profile by id; on success the lists and that profile are refreshed. */
|
|
167
|
+
declare function useUpdateProfile(): _tanstack_react_query.UseMutationResult<{
|
|
168
|
+
id: string;
|
|
169
|
+
name: string;
|
|
170
|
+
description: string | null;
|
|
171
|
+
external_id: string | null;
|
|
172
|
+
metadata: {
|
|
173
|
+
[key: string]: string | number | boolean;
|
|
174
|
+
};
|
|
175
|
+
created_at: string | null;
|
|
176
|
+
updated_at: string | null;
|
|
177
|
+
}, Error, {
|
|
178
|
+
id: string;
|
|
179
|
+
} & {
|
|
180
|
+
name?: string;
|
|
181
|
+
description?: string | null;
|
|
182
|
+
external_id?: string;
|
|
183
|
+
metadata?: {
|
|
184
|
+
[key: string]: string | number | boolean;
|
|
185
|
+
};
|
|
186
|
+
}, unknown>;
|
|
187
|
+
/** Delete a profile by id; on success the lists refresh and its detail is dropped. */
|
|
188
|
+
declare function useDeleteProfile(): _tanstack_react_query.UseMutationResult<{
|
|
189
|
+
id: string;
|
|
190
|
+
object: "profile";
|
|
191
|
+
deleted: true;
|
|
192
|
+
}, Error, string, unknown>;
|
|
193
|
+
|
|
194
|
+
interface ConnectParams {
|
|
195
|
+
/** The profile to attach the new connection to. */
|
|
196
|
+
profileId: string;
|
|
197
|
+
/** The platform to connect (X, LinkedIn, Meta, …). */
|
|
198
|
+
platform: ConnectablePlatform;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Start a connect flow: mint a session and redirect the browser to the hosted
|
|
202
|
+
* connect URL on postrun.ai, where the full white-labeled OAuth journey runs and
|
|
203
|
+
* the user is returned to the host app. Bare-bones by design — the OAuth UI is
|
|
204
|
+
* ours and hosted, so the host app just calls `mutate({ profileId, platform })`.
|
|
205
|
+
* On return, the new connection appears via `useConnections`.
|
|
206
|
+
*/
|
|
207
|
+
declare function useConnect(): _tanstack_react_query.UseMutationResult<{
|
|
208
|
+
connect_session_token: string;
|
|
209
|
+
connect_url: string;
|
|
210
|
+
expires_at: string;
|
|
211
|
+
}, Error, ConnectParams, unknown>;
|
|
212
|
+
/** List a profile's connected accounts. */
|
|
213
|
+
declare function useConnections(profileId: string): _tanstack_react_query.UseQueryResult<NoInfer<{
|
|
214
|
+
object: "list";
|
|
215
|
+
data: Array<{
|
|
216
|
+
id: string;
|
|
217
|
+
profile_id: string;
|
|
218
|
+
platform: "meta_ads" | "google_ads" | "tiktok_ads" | "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
219
|
+
external_account_id: string | null;
|
|
220
|
+
external_account_name: string | null;
|
|
221
|
+
currency: string | null;
|
|
222
|
+
created_at: string | null;
|
|
223
|
+
updated_at: string | null;
|
|
224
|
+
}>;
|
|
225
|
+
total: number;
|
|
226
|
+
limit: number;
|
|
227
|
+
offset: number;
|
|
228
|
+
has_more: boolean;
|
|
229
|
+
}>, Error>;
|
|
230
|
+
/** Retrieve a single connection by id. */
|
|
231
|
+
declare function useConnection(id: string): _tanstack_react_query.UseQueryResult<NoInfer<{
|
|
232
|
+
id: string;
|
|
233
|
+
profile_id: string;
|
|
234
|
+
platform: "meta_ads" | "google_ads" | "tiktok_ads" | "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
235
|
+
external_account_id: string | null;
|
|
236
|
+
external_account_name: string | null;
|
|
237
|
+
currency: string | null;
|
|
238
|
+
created_at: string | null;
|
|
239
|
+
updated_at: string | null;
|
|
240
|
+
}>, Error>;
|
|
241
|
+
/** List the accounts discoverable on a pending connection (for selection). */
|
|
242
|
+
declare function useDiscoverableAccounts(id: string): _tanstack_react_query.UseQueryResult<NoInfer<{
|
|
243
|
+
object: "list";
|
|
244
|
+
data: Array<{
|
|
245
|
+
external_account_id: string;
|
|
246
|
+
name: string | null;
|
|
247
|
+
currency: string | null;
|
|
248
|
+
instagram?: {
|
|
249
|
+
external_account_id: string;
|
|
250
|
+
name: string | null;
|
|
251
|
+
} | null;
|
|
252
|
+
}>;
|
|
253
|
+
}>, Error>;
|
|
254
|
+
/** Select an account on a pending connection, activating it. */
|
|
255
|
+
declare function useSelectAccount(): _tanstack_react_query.UseMutationResult<{
|
|
256
|
+
id: string;
|
|
257
|
+
profile_id: string;
|
|
258
|
+
platform: "meta_ads" | "google_ads" | "tiktok_ads" | "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
259
|
+
external_account_id: string | null;
|
|
260
|
+
external_account_name: string | null;
|
|
261
|
+
currency: string | null;
|
|
262
|
+
created_at: string | null;
|
|
263
|
+
updated_at: string | null;
|
|
264
|
+
}, Error, {
|
|
265
|
+
id: string;
|
|
266
|
+
} & {
|
|
267
|
+
external_account_id: string;
|
|
268
|
+
}, unknown>;
|
|
269
|
+
/** Disconnect (delete) a connection by id. */
|
|
270
|
+
declare function useDisconnect(): _tanstack_react_query.UseMutationResult<{
|
|
271
|
+
id: string;
|
|
272
|
+
object: "connection";
|
|
273
|
+
deleted: true;
|
|
274
|
+
}, Error, string, unknown>;
|
|
275
|
+
|
|
276
|
+
type MediaUploadStatus = 'idle' | 'uploading' | 'processing' | 'ready' | 'failed';
|
|
277
|
+
interface MediaUploadOptions {
|
|
278
|
+
/** Profile that owns the asset. */
|
|
279
|
+
profileId: string;
|
|
280
|
+
/** Platforms to validate + render for (omit to add later via useUpdateMedia). */
|
|
281
|
+
targets?: MediaTarget[];
|
|
282
|
+
/** Override the kind inferred from the file's MIME. */
|
|
283
|
+
kind?: MediaKind;
|
|
284
|
+
/** The file's MIME type. Defaults to `file.type`; required when that's empty. */
|
|
285
|
+
contentType?: string;
|
|
286
|
+
/** Store as-is with zero processing. */
|
|
287
|
+
raw?: boolean;
|
|
288
|
+
altText?: string;
|
|
289
|
+
externalId?: string;
|
|
290
|
+
metadata?: CreateMediaInput['metadata'];
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Upload a file and get back a platform-validated asset. The hook owns the whole
|
|
294
|
+
* journey: infer kind/content_type from the `File`, create the asset, PUT the
|
|
295
|
+
* bytes with live `progress` + retry, poll until processing settles, and expose
|
|
296
|
+
* `media.per_platform` (per-target status, url, warnings, errors). `cancel()`
|
|
297
|
+
* aborts an in-flight upload.
|
|
298
|
+
*/
|
|
299
|
+
declare function useMediaUpload(): {
|
|
300
|
+
upload: (file: File, options: MediaUploadOptions) => Promise<MediaResource>;
|
|
301
|
+
cancel: () => void | undefined;
|
|
302
|
+
reset: () => void;
|
|
303
|
+
status: MediaUploadStatus;
|
|
304
|
+
progress: number;
|
|
305
|
+
media: {
|
|
306
|
+
id: string;
|
|
307
|
+
object: "media";
|
|
308
|
+
profile_id: string;
|
|
309
|
+
kind: "image" | "video" | "gif" | "document";
|
|
310
|
+
status: "uploading" | "processing" | "ready" | "failed";
|
|
311
|
+
raw: boolean;
|
|
312
|
+
error: {
|
|
313
|
+
code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
|
|
314
|
+
message: string;
|
|
315
|
+
hint?: string;
|
|
316
|
+
allowed?: Array<string>;
|
|
317
|
+
got?: string;
|
|
318
|
+
} | null;
|
|
319
|
+
source: {
|
|
320
|
+
format: string;
|
|
321
|
+
bytes: number;
|
|
322
|
+
width: number | null;
|
|
323
|
+
height: number | null;
|
|
324
|
+
duration_ms: number | null;
|
|
325
|
+
} | null;
|
|
326
|
+
alt_text: string | null;
|
|
327
|
+
per_platform: {
|
|
328
|
+
[key: string]: {
|
|
329
|
+
status: "processing" | "ready" | "failed";
|
|
330
|
+
url: string | null;
|
|
331
|
+
width: number | null;
|
|
332
|
+
height: number | null;
|
|
333
|
+
bytes: number | null;
|
|
334
|
+
warnings: Array<{
|
|
335
|
+
code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
|
|
336
|
+
message: string;
|
|
337
|
+
hint?: string;
|
|
338
|
+
allowed?: Array<string>;
|
|
339
|
+
got?: string;
|
|
340
|
+
}>;
|
|
341
|
+
errors: Array<{
|
|
342
|
+
code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
|
|
343
|
+
message: string;
|
|
344
|
+
hint?: string;
|
|
345
|
+
allowed?: Array<string>;
|
|
346
|
+
got?: string;
|
|
347
|
+
}>;
|
|
348
|
+
};
|
|
349
|
+
};
|
|
350
|
+
external_id: string | null;
|
|
351
|
+
metadata: {
|
|
352
|
+
[key: string]: string | number | boolean;
|
|
353
|
+
};
|
|
354
|
+
created_at: string;
|
|
355
|
+
updated_at: string;
|
|
356
|
+
} | null;
|
|
357
|
+
error: unknown;
|
|
358
|
+
};
|
|
359
|
+
/** Retrieve a media asset; auto-polls while it is still uploading/processing. */
|
|
360
|
+
declare function useMedia(id: string): _tanstack_react_query.UseQueryResult<NoInfer<{
|
|
361
|
+
id: string;
|
|
362
|
+
object: "media";
|
|
363
|
+
profile_id: string;
|
|
364
|
+
kind: "image" | "video" | "gif" | "document";
|
|
365
|
+
status: "uploading" | "processing" | "ready" | "failed";
|
|
366
|
+
raw: boolean;
|
|
367
|
+
error: {
|
|
368
|
+
code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
|
|
369
|
+
message: string;
|
|
370
|
+
hint?: string;
|
|
371
|
+
allowed?: Array<string>;
|
|
372
|
+
got?: string;
|
|
373
|
+
} | null;
|
|
374
|
+
source: {
|
|
375
|
+
format: string;
|
|
376
|
+
bytes: number;
|
|
377
|
+
width: number | null;
|
|
378
|
+
height: number | null;
|
|
379
|
+
duration_ms: number | null;
|
|
380
|
+
} | null;
|
|
381
|
+
alt_text: string | null;
|
|
382
|
+
per_platform: {
|
|
383
|
+
[key: string]: {
|
|
384
|
+
status: "processing" | "ready" | "failed";
|
|
385
|
+
url: string | null;
|
|
386
|
+
width: number | null;
|
|
387
|
+
height: number | null;
|
|
388
|
+
bytes: number | null;
|
|
389
|
+
warnings: Array<{
|
|
390
|
+
code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
|
|
391
|
+
message: string;
|
|
392
|
+
hint?: string;
|
|
393
|
+
allowed?: Array<string>;
|
|
394
|
+
got?: string;
|
|
395
|
+
}>;
|
|
396
|
+
errors: Array<{
|
|
397
|
+
code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
|
|
398
|
+
message: string;
|
|
399
|
+
hint?: string;
|
|
400
|
+
allowed?: Array<string>;
|
|
401
|
+
got?: string;
|
|
402
|
+
}>;
|
|
403
|
+
};
|
|
404
|
+
};
|
|
405
|
+
external_id: string | null;
|
|
406
|
+
metadata: {
|
|
407
|
+
[key: string]: string | number | boolean;
|
|
408
|
+
};
|
|
409
|
+
created_at: string;
|
|
410
|
+
updated_at: string;
|
|
411
|
+
}>, Error>;
|
|
412
|
+
/** Update a media asset: alt text / metadata / external_id, or extend targets. */
|
|
413
|
+
declare function useUpdateMedia(): _tanstack_react_query.UseMutationResult<{
|
|
414
|
+
id: string;
|
|
415
|
+
object: "media";
|
|
416
|
+
profile_id: string;
|
|
417
|
+
kind: "image" | "video" | "gif" | "document";
|
|
418
|
+
status: "uploading" | "processing" | "ready" | "failed";
|
|
419
|
+
raw: boolean;
|
|
420
|
+
error: {
|
|
421
|
+
code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
|
|
422
|
+
message: string;
|
|
423
|
+
hint?: string;
|
|
424
|
+
allowed?: Array<string>;
|
|
425
|
+
got?: string;
|
|
426
|
+
} | null;
|
|
427
|
+
source: {
|
|
428
|
+
format: string;
|
|
429
|
+
bytes: number;
|
|
430
|
+
width: number | null;
|
|
431
|
+
height: number | null;
|
|
432
|
+
duration_ms: number | null;
|
|
433
|
+
} | null;
|
|
434
|
+
alt_text: string | null;
|
|
435
|
+
per_platform: {
|
|
436
|
+
[key: string]: {
|
|
437
|
+
status: "processing" | "ready" | "failed";
|
|
438
|
+
url: string | null;
|
|
439
|
+
width: number | null;
|
|
440
|
+
height: number | null;
|
|
441
|
+
bytes: number | null;
|
|
442
|
+
warnings: Array<{
|
|
443
|
+
code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
|
|
444
|
+
message: string;
|
|
445
|
+
hint?: string;
|
|
446
|
+
allowed?: Array<string>;
|
|
447
|
+
got?: string;
|
|
448
|
+
}>;
|
|
449
|
+
errors: Array<{
|
|
450
|
+
code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
|
|
451
|
+
message: string;
|
|
452
|
+
hint?: string;
|
|
453
|
+
allowed?: Array<string>;
|
|
454
|
+
got?: string;
|
|
455
|
+
}>;
|
|
456
|
+
};
|
|
457
|
+
};
|
|
458
|
+
external_id: string | null;
|
|
459
|
+
metadata: {
|
|
460
|
+
[key: string]: string | number | boolean;
|
|
461
|
+
};
|
|
462
|
+
created_at: string;
|
|
463
|
+
updated_at: string;
|
|
464
|
+
}, Error, {
|
|
465
|
+
id: string;
|
|
466
|
+
} & {
|
|
467
|
+
alt_text?: string | null;
|
|
468
|
+
external_id?: string | null;
|
|
469
|
+
metadata?: {
|
|
470
|
+
[key: string]: string | number | boolean;
|
|
471
|
+
};
|
|
472
|
+
targets?: Array<"x" | "linkedin" | "facebook_page" | "instagram" | "tiktok" | "google_ads">;
|
|
473
|
+
}, unknown>;
|
|
474
|
+
/** Delete a media asset and its stored renditions. */
|
|
475
|
+
declare function useDeleteMedia(): _tanstack_react_query.UseMutationResult<{
|
|
476
|
+
id: string;
|
|
477
|
+
object: "media";
|
|
478
|
+
deleted: true;
|
|
479
|
+
}, Error, string, unknown>;
|
|
480
|
+
|
|
481
|
+
/** A failed direct-to-storage upload, carrying the HTTP status (0 = network). */
|
|
482
|
+
declare class UploadError extends Error {
|
|
483
|
+
readonly status: number;
|
|
484
|
+
constructor(status: number, message: string);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* The calendar/queue filter surface — a date window over `schedule_at` plus a
|
|
489
|
+
* derived-status multi-select, scoped to an optional profile. Picked straight
|
|
490
|
+
* from the generated `ListPostsQuery` contract (no hand-typed shapes), so it
|
|
491
|
+
* can never drift from the API. Pagination still rides through via `usePosts`.
|
|
492
|
+
*/
|
|
493
|
+
type CalendarFilters = Pick<ListPostsQuery, 'profile_id' | 'scheduled_after' | 'scheduled_before' | 'status'>;
|
|
494
|
+
/** Per-hook live-poll control: live is on by default; `{ live: false }` opts out. */
|
|
495
|
+
interface LiveOptions {
|
|
496
|
+
/** Auto-poll while a post is in-flight (default `true`). Set `false` for one-shot. */
|
|
497
|
+
live?: boolean;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* List posts — the calendar/queue data, filtered (profile_id / external_id /
|
|
501
|
+
* metadata) and paginated. `data` is the typed `PostList` envelope, with each
|
|
502
|
+
* post's derived status (draft / scheduled / publishing / published / failed).
|
|
503
|
+
*/
|
|
504
|
+
declare function usePosts(query?: ListPostsQuery): _tanstack_react_query.UseQueryResult<NoInfer<{
|
|
505
|
+
object: "list";
|
|
506
|
+
data: Array<{
|
|
507
|
+
id: string;
|
|
508
|
+
object: "post";
|
|
509
|
+
profile_id: string;
|
|
510
|
+
external_id: string | null;
|
|
511
|
+
status: "draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed";
|
|
512
|
+
schedule_at: string | null;
|
|
513
|
+
tags: Array<string>;
|
|
514
|
+
notes: string | null;
|
|
515
|
+
metadata: {
|
|
516
|
+
[key: string]: string | number | boolean;
|
|
517
|
+
};
|
|
518
|
+
variants: Array<{
|
|
519
|
+
id: string;
|
|
520
|
+
object: "post_variant";
|
|
521
|
+
connection_id: string;
|
|
522
|
+
platform: "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
523
|
+
post_type: "text" | "single_image" | "multi_image" | "video" | "reel" | "carousel";
|
|
524
|
+
body: string | null;
|
|
525
|
+
status: "draft" | "scheduled" | "publishing" | "published" | "failed";
|
|
526
|
+
settings: {
|
|
527
|
+
[key: string]: unknown;
|
|
528
|
+
};
|
|
529
|
+
schedule_at: string | null;
|
|
530
|
+
result: {
|
|
531
|
+
platform_post_id: string;
|
|
532
|
+
permalink: string | null;
|
|
533
|
+
published_at: string;
|
|
534
|
+
} | null;
|
|
535
|
+
error: {
|
|
536
|
+
code: string;
|
|
537
|
+
message: string;
|
|
538
|
+
} | null;
|
|
539
|
+
media: Array<{
|
|
540
|
+
media_id: string;
|
|
541
|
+
position: number;
|
|
542
|
+
crop_box: {
|
|
543
|
+
[key: string]: unknown;
|
|
544
|
+
} | null;
|
|
545
|
+
alt_text_override: string | null;
|
|
546
|
+
}>;
|
|
547
|
+
}>;
|
|
548
|
+
created_at: string;
|
|
549
|
+
updated_at: string;
|
|
550
|
+
}>;
|
|
551
|
+
total: number;
|
|
552
|
+
limit: number;
|
|
553
|
+
offset: number;
|
|
554
|
+
has_more: boolean;
|
|
555
|
+
}>, Error>;
|
|
556
|
+
/**
|
|
557
|
+
* List posts with append-style ("load more") pagination — the calendar/queue
|
|
558
|
+
* feed. Returns `{ items, loadMore, hasMore, isLoading, isLoadingMore, total }`:
|
|
559
|
+
* render `items`, call `loadMore()` (on a button or scroll end) while `hasMore`.
|
|
560
|
+
* `pageSize` defaults to 20. Filters are the same as `usePosts` minus paging,
|
|
561
|
+
* which the hook owns. Shares list-cache invalidation with the other post hooks,
|
|
562
|
+
* so a create/update/delete refreshes it automatically.
|
|
563
|
+
*/
|
|
564
|
+
declare function usePostsInfinite(filters?: Omit<ListPostsQuery, 'limit' | 'offset'>, options?: {
|
|
565
|
+
pageSize?: number;
|
|
566
|
+
}): InfiniteList<{
|
|
567
|
+
id: string;
|
|
568
|
+
object: "post";
|
|
569
|
+
profile_id: string;
|
|
570
|
+
external_id: string | null;
|
|
571
|
+
status: "draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed";
|
|
572
|
+
schedule_at: string | null;
|
|
573
|
+
tags: Array<string>;
|
|
574
|
+
notes: string | null;
|
|
575
|
+
metadata: {
|
|
576
|
+
[key: string]: string | number | boolean;
|
|
577
|
+
};
|
|
578
|
+
variants: Array<{
|
|
579
|
+
id: string;
|
|
580
|
+
object: "post_variant";
|
|
581
|
+
connection_id: string;
|
|
582
|
+
platform: "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
583
|
+
post_type: "text" | "single_image" | "multi_image" | "video" | "reel" | "carousel";
|
|
584
|
+
body: string | null;
|
|
585
|
+
status: "draft" | "scheduled" | "publishing" | "published" | "failed";
|
|
586
|
+
settings: {
|
|
587
|
+
[key: string]: unknown;
|
|
588
|
+
};
|
|
589
|
+
schedule_at: string | null;
|
|
590
|
+
result: {
|
|
591
|
+
platform_post_id: string;
|
|
592
|
+
permalink: string | null;
|
|
593
|
+
published_at: string;
|
|
594
|
+
} | null;
|
|
595
|
+
error: {
|
|
596
|
+
code: string;
|
|
597
|
+
message: string;
|
|
598
|
+
} | null;
|
|
599
|
+
media: Array<{
|
|
600
|
+
media_id: string;
|
|
601
|
+
position: number;
|
|
602
|
+
crop_box: {
|
|
603
|
+
[key: string]: unknown;
|
|
604
|
+
} | null;
|
|
605
|
+
alt_text_override: string | null;
|
|
606
|
+
}>;
|
|
607
|
+
}>;
|
|
608
|
+
created_at: string;
|
|
609
|
+
updated_at: string;
|
|
610
|
+
}>;
|
|
611
|
+
/**
|
|
612
|
+
* Calendar/queue view — list posts in a `schedule_at` date window, optionally
|
|
613
|
+
* narrowed to a profile and to one or more derived statuses (e.g. only
|
|
614
|
+
* `scheduled` + `failed`). Forwards the date-range + multi-status filters (and
|
|
615
|
+
* any `limit`/`offset`) to the generated `postsList` and returns the same typed
|
|
616
|
+
* `PostList` envelope. It shares the `postKeys.list(filters)` cache identity with
|
|
617
|
+
* `usePosts` but owns its own self-terminating poll: while ANY post in the
|
|
618
|
+
* window is in-flight it refetches (5s — a list is heavier than one detail), and
|
|
619
|
+
* stops once every item is terminal (or the window is empty). `live` is a
|
|
620
|
+
* separate option, never mixed into the API filter object; default-on, opt out
|
|
621
|
+
* with `{ live: false }`.
|
|
622
|
+
*/
|
|
623
|
+
declare function useCalendar(filters?: CalendarFilters & Pick<ListPostsQuery, 'limit' | 'offset'>, options?: LiveOptions): _tanstack_react_query.UseQueryResult<NoInfer<{
|
|
624
|
+
object: "list";
|
|
625
|
+
data: Array<{
|
|
626
|
+
id: string;
|
|
627
|
+
object: "post";
|
|
628
|
+
profile_id: string;
|
|
629
|
+
external_id: string | null;
|
|
630
|
+
status: "draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed";
|
|
631
|
+
schedule_at: string | null;
|
|
632
|
+
tags: Array<string>;
|
|
633
|
+
notes: string | null;
|
|
634
|
+
metadata: {
|
|
635
|
+
[key: string]: string | number | boolean;
|
|
636
|
+
};
|
|
637
|
+
variants: Array<{
|
|
638
|
+
id: string;
|
|
639
|
+
object: "post_variant";
|
|
640
|
+
connection_id: string;
|
|
641
|
+
platform: "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
642
|
+
post_type: "text" | "single_image" | "multi_image" | "video" | "reel" | "carousel";
|
|
643
|
+
body: string | null;
|
|
644
|
+
status: "draft" | "scheduled" | "publishing" | "published" | "failed";
|
|
645
|
+
settings: {
|
|
646
|
+
[key: string]: unknown;
|
|
647
|
+
};
|
|
648
|
+
schedule_at: string | null;
|
|
649
|
+
result: {
|
|
650
|
+
platform_post_id: string;
|
|
651
|
+
permalink: string | null;
|
|
652
|
+
published_at: string;
|
|
653
|
+
} | null;
|
|
654
|
+
error: {
|
|
655
|
+
code: string;
|
|
656
|
+
message: string;
|
|
657
|
+
} | null;
|
|
658
|
+
media: Array<{
|
|
659
|
+
media_id: string;
|
|
660
|
+
position: number;
|
|
661
|
+
crop_box: {
|
|
662
|
+
[key: string]: unknown;
|
|
663
|
+
} | null;
|
|
664
|
+
alt_text_override: string | null;
|
|
665
|
+
}>;
|
|
666
|
+
}>;
|
|
667
|
+
created_at: string;
|
|
668
|
+
updated_at: string;
|
|
669
|
+
}>;
|
|
670
|
+
total: number;
|
|
671
|
+
limit: number;
|
|
672
|
+
offset: number;
|
|
673
|
+
has_more: boolean;
|
|
674
|
+
}>, Error>;
|
|
675
|
+
/**
|
|
676
|
+
* Retrieve a single post by id (its variants, schedule, and derived status).
|
|
677
|
+
* Auto-polls (2s) while the post is in-flight (`scheduled` / `publishing`) and
|
|
678
|
+
* stops once it reaches a terminal status — so a scheduled post visibly
|
|
679
|
+
* transitions with no manual refetch. `live` is on by default; pass
|
|
680
|
+
* `{ live: false }` to force a one-shot.
|
|
681
|
+
*/
|
|
682
|
+
declare function usePost(id: string, options?: LiveOptions): _tanstack_react_query.UseQueryResult<NoInfer<{
|
|
683
|
+
id: string;
|
|
684
|
+
object: "post";
|
|
685
|
+
profile_id: string;
|
|
686
|
+
external_id: string | null;
|
|
687
|
+
status: "draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed";
|
|
688
|
+
schedule_at: string | null;
|
|
689
|
+
tags: Array<string>;
|
|
690
|
+
notes: string | null;
|
|
691
|
+
metadata: {
|
|
692
|
+
[key: string]: string | number | boolean;
|
|
693
|
+
};
|
|
694
|
+
variants: Array<{
|
|
695
|
+
id: string;
|
|
696
|
+
object: "post_variant";
|
|
697
|
+
connection_id: string;
|
|
698
|
+
platform: "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
699
|
+
post_type: "text" | "single_image" | "multi_image" | "video" | "reel" | "carousel";
|
|
700
|
+
body: string | null;
|
|
701
|
+
status: "draft" | "scheduled" | "publishing" | "published" | "failed";
|
|
702
|
+
settings: {
|
|
703
|
+
[key: string]: unknown;
|
|
704
|
+
};
|
|
705
|
+
schedule_at: string | null;
|
|
706
|
+
result: {
|
|
707
|
+
platform_post_id: string;
|
|
708
|
+
permalink: string | null;
|
|
709
|
+
published_at: string;
|
|
710
|
+
} | null;
|
|
711
|
+
error: {
|
|
712
|
+
code: string;
|
|
713
|
+
message: string;
|
|
714
|
+
} | null;
|
|
715
|
+
media: Array<{
|
|
716
|
+
media_id: string;
|
|
717
|
+
position: number;
|
|
718
|
+
crop_box: {
|
|
719
|
+
[key: string]: unknown;
|
|
720
|
+
} | null;
|
|
721
|
+
alt_text_override: string | null;
|
|
722
|
+
}>;
|
|
723
|
+
}>;
|
|
724
|
+
created_at: string;
|
|
725
|
+
updated_at: string;
|
|
726
|
+
}>, Error>;
|
|
727
|
+
/**
|
|
728
|
+
* Compose and create a post. Resolves the profile's connections, builds the full
|
|
729
|
+
* variant set from `{ content, channels }` (per the `buildCreatePost` rules), and
|
|
730
|
+
* sends it — the customer never assembles variants or passes a `connection_id`.
|
|
731
|
+
* `connectedChannels` is the set of posting platforms this profile can reach.
|
|
732
|
+
*/
|
|
733
|
+
declare function useCreatePost(profileId: string): {
|
|
734
|
+
create: _tanstack_react_query.UseMutateAsyncFunction<{
|
|
735
|
+
id: string;
|
|
736
|
+
object: "post";
|
|
737
|
+
profile_id: string;
|
|
738
|
+
external_id: string | null;
|
|
739
|
+
status: "draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed";
|
|
740
|
+
schedule_at: string | null;
|
|
741
|
+
tags: Array<string>;
|
|
742
|
+
notes: string | null;
|
|
743
|
+
metadata: {
|
|
744
|
+
[key: string]: string | number | boolean;
|
|
745
|
+
};
|
|
746
|
+
variants: Array<{
|
|
747
|
+
id: string;
|
|
748
|
+
object: "post_variant";
|
|
749
|
+
connection_id: string;
|
|
750
|
+
platform: "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
751
|
+
post_type: "text" | "single_image" | "multi_image" | "video" | "reel" | "carousel";
|
|
752
|
+
body: string | null;
|
|
753
|
+
status: "draft" | "scheduled" | "publishing" | "published" | "failed";
|
|
754
|
+
settings: {
|
|
755
|
+
[key: string]: unknown;
|
|
756
|
+
};
|
|
757
|
+
schedule_at: string | null;
|
|
758
|
+
result: {
|
|
759
|
+
platform_post_id: string;
|
|
760
|
+
permalink: string | null;
|
|
761
|
+
published_at: string;
|
|
762
|
+
} | null;
|
|
763
|
+
error: {
|
|
764
|
+
code: string;
|
|
765
|
+
message: string;
|
|
766
|
+
} | null;
|
|
767
|
+
media: Array<{
|
|
768
|
+
media_id: string;
|
|
769
|
+
position: number;
|
|
770
|
+
crop_box: {
|
|
771
|
+
[key: string]: unknown;
|
|
772
|
+
} | null;
|
|
773
|
+
alt_text_override: string | null;
|
|
774
|
+
}>;
|
|
775
|
+
}>;
|
|
776
|
+
created_at: string;
|
|
777
|
+
updated_at: string;
|
|
778
|
+
dry_run: boolean;
|
|
779
|
+
executed: boolean;
|
|
780
|
+
}, Error, Omit<ComposePostInput, "profileId">, unknown>;
|
|
781
|
+
isPending: boolean;
|
|
782
|
+
error: Error | null;
|
|
783
|
+
data: {
|
|
784
|
+
id: string;
|
|
785
|
+
object: "post";
|
|
786
|
+
profile_id: string;
|
|
787
|
+
external_id: string | null;
|
|
788
|
+
status: "draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed";
|
|
789
|
+
schedule_at: string | null;
|
|
790
|
+
tags: Array<string>;
|
|
791
|
+
notes: string | null;
|
|
792
|
+
metadata: {
|
|
793
|
+
[key: string]: string | number | boolean;
|
|
794
|
+
};
|
|
795
|
+
variants: Array<{
|
|
796
|
+
id: string;
|
|
797
|
+
object: "post_variant";
|
|
798
|
+
connection_id: string;
|
|
799
|
+
platform: "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
800
|
+
post_type: "text" | "single_image" | "multi_image" | "video" | "reel" | "carousel";
|
|
801
|
+
body: string | null;
|
|
802
|
+
status: "draft" | "scheduled" | "publishing" | "published" | "failed";
|
|
803
|
+
settings: {
|
|
804
|
+
[key: string]: unknown;
|
|
805
|
+
};
|
|
806
|
+
schedule_at: string | null;
|
|
807
|
+
result: {
|
|
808
|
+
platform_post_id: string;
|
|
809
|
+
permalink: string | null;
|
|
810
|
+
published_at: string;
|
|
811
|
+
} | null;
|
|
812
|
+
error: {
|
|
813
|
+
code: string;
|
|
814
|
+
message: string;
|
|
815
|
+
} | null;
|
|
816
|
+
media: Array<{
|
|
817
|
+
media_id: string;
|
|
818
|
+
position: number;
|
|
819
|
+
crop_box: {
|
|
820
|
+
[key: string]: unknown;
|
|
821
|
+
} | null;
|
|
822
|
+
alt_text_override: string | null;
|
|
823
|
+
}>;
|
|
824
|
+
}>;
|
|
825
|
+
created_at: string;
|
|
826
|
+
updated_at: string;
|
|
827
|
+
dry_run: boolean;
|
|
828
|
+
executed: boolean;
|
|
829
|
+
} | undefined;
|
|
830
|
+
reset: () => void;
|
|
831
|
+
isReady: boolean;
|
|
832
|
+
connectedChannels: ("x" | "linkedin" | "facebook_page" | "instagram")[];
|
|
833
|
+
};
|
|
834
|
+
/**
|
|
835
|
+
* Update a post by id. Pass a light edit directly (`{ schedule_at }`,
|
|
836
|
+
* `{ tags }`, …) or a rebuilt body from `buildUpdatePost(input, connections)`
|
|
837
|
+
* for content edits (the API's PATCH replaces the variant set).
|
|
838
|
+
*/
|
|
839
|
+
declare function useUpdatePost(postId: string): _tanstack_react_query.UseMutationResult<{
|
|
840
|
+
id: string;
|
|
841
|
+
object: "post";
|
|
842
|
+
profile_id: string;
|
|
843
|
+
external_id: string | null;
|
|
844
|
+
status: "draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed";
|
|
845
|
+
schedule_at: string | null;
|
|
846
|
+
tags: Array<string>;
|
|
847
|
+
notes: string | null;
|
|
848
|
+
metadata: {
|
|
849
|
+
[key: string]: string | number | boolean;
|
|
850
|
+
};
|
|
851
|
+
variants: Array<{
|
|
852
|
+
id: string;
|
|
853
|
+
object: "post_variant";
|
|
854
|
+
connection_id: string;
|
|
855
|
+
platform: "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
856
|
+
post_type: "text" | "single_image" | "multi_image" | "video" | "reel" | "carousel";
|
|
857
|
+
body: string | null;
|
|
858
|
+
status: "draft" | "scheduled" | "publishing" | "published" | "failed";
|
|
859
|
+
settings: {
|
|
860
|
+
[key: string]: unknown;
|
|
861
|
+
};
|
|
862
|
+
schedule_at: string | null;
|
|
863
|
+
result: {
|
|
864
|
+
platform_post_id: string;
|
|
865
|
+
permalink: string | null;
|
|
866
|
+
published_at: string;
|
|
867
|
+
} | null;
|
|
868
|
+
error: {
|
|
869
|
+
code: string;
|
|
870
|
+
message: string;
|
|
871
|
+
} | null;
|
|
872
|
+
media: Array<{
|
|
873
|
+
media_id: string;
|
|
874
|
+
position: number;
|
|
875
|
+
crop_box: {
|
|
876
|
+
[key: string]: unknown;
|
|
877
|
+
} | null;
|
|
878
|
+
alt_text_override: string | null;
|
|
879
|
+
}>;
|
|
880
|
+
}>;
|
|
881
|
+
created_at: string;
|
|
882
|
+
updated_at: string;
|
|
883
|
+
dry_run: boolean;
|
|
884
|
+
executed: boolean;
|
|
885
|
+
}, Error, {
|
|
886
|
+
publish?: "now" | "schedule" | "draft";
|
|
887
|
+
schedule_at?: string | null;
|
|
888
|
+
external_id?: string | null;
|
|
889
|
+
metadata?: {
|
|
890
|
+
[key: string]: string | number | boolean;
|
|
891
|
+
};
|
|
892
|
+
tags?: Array<string>;
|
|
893
|
+
notes?: string | null;
|
|
894
|
+
dry_run?: boolean;
|
|
895
|
+
variants?: Array<{
|
|
896
|
+
platform: "x";
|
|
897
|
+
post_type: "text" | "single_image" | "multi_image" | "video";
|
|
898
|
+
connection_id: string;
|
|
899
|
+
body?: string;
|
|
900
|
+
media?: Array<{
|
|
901
|
+
media_id: string;
|
|
902
|
+
crop_box?: {
|
|
903
|
+
[key: string]: unknown;
|
|
904
|
+
} | null;
|
|
905
|
+
alt_text_override?: string | null;
|
|
906
|
+
}>;
|
|
907
|
+
settings?: {
|
|
908
|
+
reply_settings?: "everyone" | "following" | "mentionedUsers" | "subscribers" | "verified";
|
|
909
|
+
quote_tweet_id?: string;
|
|
910
|
+
poll?: {
|
|
911
|
+
options: Array<string>;
|
|
912
|
+
duration_minutes: number;
|
|
913
|
+
reply_settings?: "following" | "mentionedUsers" | "subscribers" | "verified";
|
|
914
|
+
};
|
|
915
|
+
reply?: {
|
|
916
|
+
in_reply_to_tweet_id: string;
|
|
917
|
+
exclude_reply_user_ids?: Array<string>;
|
|
918
|
+
auto_populate_reply_metadata?: boolean;
|
|
919
|
+
};
|
|
920
|
+
community_id?: string;
|
|
921
|
+
for_super_followers_only?: boolean;
|
|
922
|
+
geo?: {
|
|
923
|
+
place_id: string;
|
|
924
|
+
};
|
|
925
|
+
card_uri?: string;
|
|
926
|
+
media_tagged_user_ids?: Array<string>;
|
|
927
|
+
};
|
|
928
|
+
} | {
|
|
929
|
+
platform: "linkedin";
|
|
930
|
+
post_type: "text" | "single_image" | "multi_image" | "video";
|
|
931
|
+
connection_id: string;
|
|
932
|
+
body?: string;
|
|
933
|
+
media?: Array<{
|
|
934
|
+
media_id: string;
|
|
935
|
+
crop_box?: {
|
|
936
|
+
[key: string]: unknown;
|
|
937
|
+
} | null;
|
|
938
|
+
alt_text_override?: string | null;
|
|
939
|
+
}>;
|
|
940
|
+
settings: {
|
|
941
|
+
visibility: "PUBLIC" | "CONNECTIONS";
|
|
942
|
+
content_kind: "text" | "single_image" | "video" | "multi_image" | "document" | "article" | "poll";
|
|
943
|
+
article?: {
|
|
944
|
+
source: string;
|
|
945
|
+
title?: string;
|
|
946
|
+
description?: string;
|
|
947
|
+
thumbnail_media_id?: string;
|
|
948
|
+
};
|
|
949
|
+
poll?: {
|
|
950
|
+
question: string;
|
|
951
|
+
options: Array<string>;
|
|
952
|
+
duration: "ONE_DAY" | "THREE_DAYS" | "SEVEN_DAYS" | "FOURTEEN_DAYS";
|
|
953
|
+
};
|
|
954
|
+
document?: {
|
|
955
|
+
title: string;
|
|
956
|
+
};
|
|
957
|
+
disable_reshare?: boolean;
|
|
958
|
+
mentions?: Array<{
|
|
959
|
+
type: "person" | "organization";
|
|
960
|
+
name: string;
|
|
961
|
+
urn: string;
|
|
962
|
+
}>;
|
|
963
|
+
};
|
|
964
|
+
} | {
|
|
965
|
+
platform: "instagram";
|
|
966
|
+
post_type: "single_image" | "carousel" | "reel";
|
|
967
|
+
connection_id: string;
|
|
968
|
+
body?: string;
|
|
969
|
+
media?: Array<{
|
|
970
|
+
media_id: string;
|
|
971
|
+
crop_box?: {
|
|
972
|
+
[key: string]: unknown;
|
|
973
|
+
} | null;
|
|
974
|
+
alt_text_override?: string | null;
|
|
975
|
+
}>;
|
|
976
|
+
settings: {
|
|
977
|
+
media_type?: "IMAGE" | "CAROUSEL" | "REELS";
|
|
978
|
+
location_id?: string;
|
|
979
|
+
user_tags?: Array<{
|
|
980
|
+
username: string;
|
|
981
|
+
x: number;
|
|
982
|
+
y: number;
|
|
983
|
+
}>;
|
|
984
|
+
collaborators?: Array<string>;
|
|
985
|
+
share_to_feed?: boolean;
|
|
986
|
+
thumb_offset?: number;
|
|
987
|
+
cover_url?: string;
|
|
988
|
+
audio_name?: string;
|
|
989
|
+
};
|
|
990
|
+
} | {
|
|
991
|
+
platform: "facebook_page";
|
|
992
|
+
post_type: "text" | "single_image" | "multi_image" | "reel";
|
|
993
|
+
connection_id: string;
|
|
994
|
+
body?: string;
|
|
995
|
+
media?: Array<{
|
|
996
|
+
media_id: string;
|
|
997
|
+
crop_box?: {
|
|
998
|
+
[key: string]: unknown;
|
|
999
|
+
} | null;
|
|
1000
|
+
alt_text_override?: string | null;
|
|
1001
|
+
}>;
|
|
1002
|
+
settings?: {
|
|
1003
|
+
link?: string;
|
|
1004
|
+
};
|
|
1005
|
+
}>;
|
|
1006
|
+
}, unknown>;
|
|
1007
|
+
/** Delete a post by id; on success the lists refresh and its detail is dropped. */
|
|
1008
|
+
declare function useDeletePost(): _tanstack_react_query.UseMutationResult<{
|
|
1009
|
+
id: string;
|
|
1010
|
+
object: "post";
|
|
1011
|
+
deleted: true;
|
|
1012
|
+
}, Error, string, unknown>;
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Query-key factory for profiles. Hierarchical so a mutation can invalidate at
|
|
1016
|
+
* the right granularity: `lists()` after a create, `detail(id)` after an update.
|
|
1017
|
+
*/
|
|
1018
|
+
declare const profileKeys: {
|
|
1019
|
+
all: readonly ["postrun", "profiles"];
|
|
1020
|
+
lists: () => readonly ["postrun", "profiles", "list"];
|
|
1021
|
+
list: (query?: ListProfilesQuery) => readonly ["postrun", "profiles", "list", {
|
|
1022
|
+
limit?: number;
|
|
1023
|
+
offset?: number;
|
|
1024
|
+
external_id?: string;
|
|
1025
|
+
metadata?: {
|
|
1026
|
+
[key: string]: string | number | boolean;
|
|
1027
|
+
};
|
|
1028
|
+
}];
|
|
1029
|
+
infinite: (query?: ListProfilesQuery) => readonly ["postrun", "profiles", "list", "infinite", {
|
|
1030
|
+
limit?: number;
|
|
1031
|
+
offset?: number;
|
|
1032
|
+
external_id?: string;
|
|
1033
|
+
metadata?: {
|
|
1034
|
+
[key: string]: string | number | boolean;
|
|
1035
|
+
};
|
|
1036
|
+
}];
|
|
1037
|
+
details: () => readonly ["postrun", "profiles", "detail"];
|
|
1038
|
+
detail: (id: string) => readonly ["postrun", "profiles", "detail", string];
|
|
1039
|
+
};
|
|
1040
|
+
/** Query-key factory for posts (list filtered by query; detail by id). */
|
|
1041
|
+
declare const postKeys: {
|
|
1042
|
+
all: readonly ["postrun", "posts"];
|
|
1043
|
+
lists: () => readonly ["postrun", "posts", "list"];
|
|
1044
|
+
list: (query?: ListPostsQuery) => readonly ["postrun", "posts", "list", {
|
|
1045
|
+
limit?: number;
|
|
1046
|
+
offset?: number;
|
|
1047
|
+
profile_id?: string;
|
|
1048
|
+
external_id?: string;
|
|
1049
|
+
metadata?: {
|
|
1050
|
+
[key: string]: string | number | boolean;
|
|
1051
|
+
};
|
|
1052
|
+
scheduled_after?: string;
|
|
1053
|
+
scheduled_before?: string;
|
|
1054
|
+
updated_after?: string;
|
|
1055
|
+
status?: Array<"draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed">;
|
|
1056
|
+
}];
|
|
1057
|
+
infinite: (query?: ListPostsQuery) => readonly ["postrun", "posts", "list", "infinite", {
|
|
1058
|
+
limit?: number;
|
|
1059
|
+
offset?: number;
|
|
1060
|
+
profile_id?: string;
|
|
1061
|
+
external_id?: string;
|
|
1062
|
+
metadata?: {
|
|
1063
|
+
[key: string]: string | number | boolean;
|
|
1064
|
+
};
|
|
1065
|
+
scheduled_after?: string;
|
|
1066
|
+
scheduled_before?: string;
|
|
1067
|
+
updated_after?: string;
|
|
1068
|
+
status?: Array<"draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed">;
|
|
1069
|
+
}];
|
|
1070
|
+
details: () => readonly ["postrun", "posts", "detail"];
|
|
1071
|
+
detail: (id: string) => readonly ["postrun", "posts", "detail", string];
|
|
1072
|
+
};
|
|
1073
|
+
/** Query-key factory for media assets (single-asset only; no list endpoint yet). */
|
|
1074
|
+
declare const mediaKeys: {
|
|
1075
|
+
all: readonly ["postrun", "media"];
|
|
1076
|
+
details: () => readonly ["postrun", "media", "detail"];
|
|
1077
|
+
detail: (id: string) => readonly ["postrun", "media", "detail", string];
|
|
1078
|
+
};
|
|
1079
|
+
/** Query-key factory for connections (lists keyed by owning profile). */
|
|
1080
|
+
declare const connectionKeys: {
|
|
1081
|
+
all: readonly ["postrun", "connections"];
|
|
1082
|
+
lists: () => readonly ["postrun", "connections", "list"];
|
|
1083
|
+
list: (profileId: string) => readonly ["postrun", "connections", "list", string];
|
|
1084
|
+
details: () => readonly ["postrun", "connections", "detail"];
|
|
1085
|
+
detail: (id: string) => readonly ["postrun", "connections", "detail", string];
|
|
1086
|
+
accounts: (id: string) => readonly ["postrun", "connections", "accounts", string];
|
|
1087
|
+
};
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* Public input types for the post-preview components. These describe data the
|
|
1091
|
+
* CUSTOMER supplies for presentation — NOT shapes from our OpenAPI contract — so
|
|
1092
|
+
* they are authored here rather than derived. The one value with a contract
|
|
1093
|
+
* counterpart, a media asset's `kind`, IS derived from the SDK's `MediaKind`.
|
|
1094
|
+
*
|
|
1095
|
+
* Why author/media live outside the post schema: a connection stores only a
|
|
1096
|
+
* cached account name (no avatar, no `@handle`, no verified flag), and a variant
|
|
1097
|
+
* references media by id, not by pixels — at compose time the only pixels that
|
|
1098
|
+
* exist are a local `File`.
|
|
1099
|
+
*/
|
|
1100
|
+
/** The author identity rendered in an X preview header. */
|
|
1101
|
+
interface XPreviewAuthor {
|
|
1102
|
+
/** Display name, e.g. "Acme Studio". */
|
|
1103
|
+
name: string;
|
|
1104
|
+
/** Handle WITHOUT the leading `@`, e.g. "acmestudio". */
|
|
1105
|
+
handle: string;
|
|
1106
|
+
/** Avatar image URL. Omit for a neutral placeholder. */
|
|
1107
|
+
avatarUrl?: string;
|
|
1108
|
+
/** Show the verified badge. Default false. */
|
|
1109
|
+
verified?: boolean;
|
|
1110
|
+
}
|
|
1111
|
+
/** The author identity rendered in a LinkedIn preview header. LinkedIn shows a
|
|
1112
|
+
* name + a one-line headline (role/tagline), not an `@handle`. */
|
|
1113
|
+
interface LinkedInPreviewAuthor {
|
|
1114
|
+
/** Display name, e.g. "Acme Studio". */
|
|
1115
|
+
name: string;
|
|
1116
|
+
/** One-line headline under the name, e.g. "Founder & CEO at Acme". */
|
|
1117
|
+
headline?: string;
|
|
1118
|
+
/** Avatar image URL. Omit for a neutral placeholder. */
|
|
1119
|
+
avatarUrl?: string;
|
|
1120
|
+
/** Show the verified badge. Default false. */
|
|
1121
|
+
verified?: boolean;
|
|
1122
|
+
}
|
|
1123
|
+
/** The media kinds a social preview can render (documents are not previewable
|
|
1124
|
+
* here) — derived from the SDK's `MediaKind`, never re-listed. */
|
|
1125
|
+
type PreviewMediaKind = Extract<MediaKind, 'image' | 'video' | 'gif'>;
|
|
1126
|
+
/**
|
|
1127
|
+
* One media item to preview. Provide a `url` (e.g. the processed
|
|
1128
|
+
* `MediaResource.per_platform.<platform>.url`) OR a `file` (a compose-time blob,
|
|
1129
|
+
* before upload) — the component turns a `file` into an object URL and revokes it
|
|
1130
|
+
* on unmount. An item with neither is skipped.
|
|
1131
|
+
*/
|
|
1132
|
+
interface PreviewMedia {
|
|
1133
|
+
kind: PreviewMediaKind;
|
|
1134
|
+
url?: string;
|
|
1135
|
+
file?: File;
|
|
1136
|
+
/** Natural pixel width — improves layout fidelity when known. */
|
|
1137
|
+
width?: number;
|
|
1138
|
+
/** Natural pixel height — improves layout fidelity when known. */
|
|
1139
|
+
height?: number;
|
|
1140
|
+
/** Alt text; falls back to the variant media's `alt_text_override`. */
|
|
1141
|
+
alt?: string;
|
|
1142
|
+
/** Poster frame for a video; falls back to `url`/`file`. */
|
|
1143
|
+
posterUrl?: string;
|
|
1144
|
+
}
|
|
1145
|
+
/** @deprecated Use {@link PreviewMedia}. Kept as an alias for back-compat. */
|
|
1146
|
+
type XPreviewMedia = PreviewMedia;
|
|
1147
|
+
/**
|
|
1148
|
+
* Content for the nested quoted card. Supplied separately because our schema
|
|
1149
|
+
* carries only an opaque `quote_tweet_id` (no quoted text/author).
|
|
1150
|
+
*/
|
|
1151
|
+
interface XPreviewQuotedTweet {
|
|
1152
|
+
author: XPreviewAuthor;
|
|
1153
|
+
body?: string;
|
|
1154
|
+
media?: PreviewMedia[];
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
interface XPostPreviewProps {
|
|
1158
|
+
/** The X variant from our schema — the content source, untouched. */
|
|
1159
|
+
variant: XPostVariant;
|
|
1160
|
+
/** Author identity (not stored on our connection — supplied by you). */
|
|
1161
|
+
author: XPreviewAuthor;
|
|
1162
|
+
/** Resolved media pixels (URLs or compose-time File blobs). */
|
|
1163
|
+
media?: PreviewMedia[];
|
|
1164
|
+
/** Content for the quoted card when `settings.quote_tweet_id` is set. */
|
|
1165
|
+
quotedTweet?: XPreviewQuotedTweet;
|
|
1166
|
+
/** The replied-to account's handle (our schema only stores the parent id). */
|
|
1167
|
+
replyToHandle?: string;
|
|
1168
|
+
/** Color scheme. `auto` (default) inherits the host's theme. */
|
|
1169
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
1170
|
+
/** Show the static action row (icons, no counts). Default true. */
|
|
1171
|
+
showActions?: boolean;
|
|
1172
|
+
/** Class applied to the wrapper — your hook for sizing, shadows, etc. */
|
|
1173
|
+
className?: string;
|
|
1174
|
+
/** Inline styles on the wrapper — e.g. react-tweet CSS variables
|
|
1175
|
+
* (`{ ['--tweet-container-margin']: '0' }`). */
|
|
1176
|
+
style?: CSSProperties;
|
|
1177
|
+
/** Override react-tweet's internal pieces (e.g. `next/image` avatars). */
|
|
1178
|
+
components?: TwitterComponents;
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* A faithful, pixel-accurate preview of how an X post will look once published,
|
|
1182
|
+
* rendered straight from a Postrun X variant. Built on `react-tweet` (the same
|
|
1183
|
+
* card X itself ships), so you write zero card UI — pass the schema, render the
|
|
1184
|
+
* preview. Fully customizable: restyle via `className`/`style` (CSS variables)
|
|
1185
|
+
* or swap internals via `components`; theme light/dark/auto.
|
|
1186
|
+
*/
|
|
1187
|
+
declare function XPostPreviewImpl({ variant, author, media, quotedTweet, replyToHandle, theme, showActions, className, style, components, }: XPostPreviewProps): react.JSX.Element;
|
|
1188
|
+
/** Memoized: re-renders only when its props change (the resolved-media hook
|
|
1189
|
+
* already absorbs unstable media arrays). */
|
|
1190
|
+
declare const XPostPreview: react.MemoExoticComponent<typeof XPostPreviewImpl>;
|
|
1191
|
+
|
|
1192
|
+
/**
|
|
1193
|
+
* LinkedIn preview theming. Unlike the X preview (which inherits react-tweet's
|
|
1194
|
+
* CSS), we own the LinkedIn card, so we expose a small set of CSS custom
|
|
1195
|
+
* properties on the wrapper. The resolved palette sets their default values;
|
|
1196
|
+
* a customer can override any of them via `style`/`className`. Components read
|
|
1197
|
+
* `var(--pr-li-*)`, so restyling needs no fork.
|
|
1198
|
+
*/
|
|
1199
|
+
type LinkedInTheme = 'light' | 'dark' | 'auto';
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
* A faithful, schema-driven preview of how a LinkedIn post will look in-feed,
|
|
1203
|
+
* rendered straight from a Postrun LinkedIn variant. Clean-room components (no
|
|
1204
|
+
* dependency to "buy" exists for LinkedIn), mirroring the real feed card: header
|
|
1205
|
+
* with headline + audience icon, an entity-highlighted body with the "…more"
|
|
1206
|
+
* fold, the 1/2/3/4/+N image mosaic (or a video), and a static action bar.
|
|
1207
|
+
*
|
|
1208
|
+
* v1 renders text + images + video. The richer `content_kind`s (article, poll,
|
|
1209
|
+
* document) degrade gracefully to the text/media card and arrive next.
|
|
1210
|
+
*
|
|
1211
|
+
* Customize via `theme` (light/dark/auto), `className`/`style`, or by overriding
|
|
1212
|
+
* the `--pr-li-*` CSS variables the card reads.
|
|
1213
|
+
*/
|
|
1214
|
+
interface LinkedInPostPreviewProps {
|
|
1215
|
+
/** The LinkedIn variant from our schema — the content source, untouched. */
|
|
1216
|
+
variant: LinkedInPostVariant;
|
|
1217
|
+
/** Author identity (LinkedIn stores no avatar/headline on our connection). */
|
|
1218
|
+
author: LinkedInPreviewAuthor;
|
|
1219
|
+
/** Resolved media pixels (URLs or compose-time File blobs). */
|
|
1220
|
+
media?: PreviewMedia[];
|
|
1221
|
+
/** Color scheme. `auto` (default) follows the OS preference. */
|
|
1222
|
+
theme?: LinkedInTheme;
|
|
1223
|
+
/** Relative time label shown in the header. Default "Now". */
|
|
1224
|
+
time?: string;
|
|
1225
|
+
/** Show the static action bar (Like/Comment/Repost/Send). Default true. */
|
|
1226
|
+
showActions?: boolean;
|
|
1227
|
+
/** Class applied to the card — your hook for sizing, shadows, etc. */
|
|
1228
|
+
className?: string;
|
|
1229
|
+
/** Inline styles on the card — including `--pr-li-*` variable overrides. */
|
|
1230
|
+
style?: CSSProperties;
|
|
1231
|
+
}
|
|
1232
|
+
declare function LinkedInPostPreviewImpl({ variant, author, media, theme, time, showActions, className, style, }: LinkedInPostPreviewProps): react.JSX.Element;
|
|
1233
|
+
/** Memoized: re-renders only when its props change (the resolved-media hook
|
|
1234
|
+
* absorbs unstable media arrays). */
|
|
1235
|
+
declare const LinkedInPostPreview: react.MemoExoticComponent<typeof LinkedInPostPreviewImpl>;
|
|
1236
|
+
|
|
1237
|
+
export { type CalendarFilters, type ConnectParams, type InfiniteList, LinkedInPostPreview, type LinkedInPostPreviewProps, type LinkedInPreviewAuthor, type LiveOptions, type MediaUploadOptions, type MediaUploadStatus, type PostrunContextValue, PostrunProvider, type PostrunProviderProps, type PreviewMedia, type PreviewMediaKind, UploadError, XPostPreview, type XPostPreviewProps, type XPreviewAuthor, type XPreviewMedia, type XPreviewQuotedTweet, connectionKeys, mediaKeys, postKeys, profileKeys, useCalendar, useConnect, useConnection, useConnections, useCreatePost, useCreateProfile, useDeleteMedia, useDeletePost, useDeleteProfile, useDisconnect, useDiscoverableAccounts, useInfiniteList, useMedia, useMediaUpload, usePost, usePostrun, usePosts, usePostsInfinite, useProfile, useProfiles, useProfilesInfinite, useSelectAccount, useUpdateMedia, useUpdatePost, useUpdateProfile };
|